Nobody who wrote this prompt still works here
The handover was a Slack thread and a link to a file. Everything the file was for lives in somebody else's head, and the bot is answering customers this morning either way.
TL;DR Nine checks for the first day with an agent prompt you did not write, each with a command behind it. Do not start by reading it: build it, because the artifact is the text the model gets and an unbound conditional ships both branches as one line of prose. Then read the advisories as the previous author's unfinished decisions, the unused declarations as features that were started and abandoned, and the coverage number as how much of it was ever pinned. The file here exits 0 and scores D (53/100).
It is a normal Tuesday. Somebody moved teams, and the agent that handles delivery and billing questions is now yours. You have the repo, you have a file, and you have a stakeholder who wants a new rule in it by Thursday. Nobody is available to explain what any of it was for.
The instinct is to read the prompt end to end, and that is the one thing that will not help yet, because reading tells you what somebody meant and the problem is everything they did not finish. This list is the order to run the commands in, and what each one tells you that the prose cannot. It is not the launch checklist, which assumed you wrote the thing, and it is not the incident list, which assumed something had already gone wrong. Here nothing is wrong. You just do not know anything.
<$CONFIG> $CONFIG model claude-opus-4-8 - via:: anthropic $REQUIRE variable tier: one of standard, premium $REQUIRE variable locale: string $IMPORT tool get_order </$CONFIG> $SERVICE anthropic - base:: https://api.anthropic.com - headers:: - x-api-key:: @{env.ANTHROPIC_API_KEY} $DEFINE vip AS @{tier} is equal to premium $TOOL send_survey - description:: Sends the post-contact survey. - input:: - ticket_id:: string - request:: POST anthropic /survey # Role You are a support agent for Cobalt Mobile. # Constraints - You SHOULD try to confirm the account before you discuss a bill. - You MUST call @[get_order] before you state a delivery date. - You MUST answer a delivery question in at most 3 sentences. $IF @{tier} is equal to premium: You MUST promise a reply within 4 hours. $ELSE: You MUST promise a reply within 2 working days.
§1Find out what actually ships
1. Prove the file is the prompt. Before any of it means anything, establish that this document is what the runtime serves. build writes the artifact and records both hashes in the manifest, so you have something to compare against whatever your deploy path is holding.
$ npx typeglish build support.tg ✓ built .typeglish/dist/support.txt ← support.tg (a5efde574729, full) $ jq '.builds[0]' .typeglish/build-manifest.json { "source": "support.tg", "sourceSha256": "ac0f06cbe544553385c3b8e42ff8fbeb7c97d79cb5e8065996b91f6e7ce95554", "artifact": ".typeglish/dist/support.txt", "artifactSha256": "a5efde57472909b5894308e85174d52ac8c623e73c73ac51115004a5e8523079", "vars": null, "typeglish": "0.7.2", "checkMode": "full", "report": { "ok": true, "counts": { "error": 0, "warn": 5, "info": 3 }, "strict": false }, "builtAt": "2026-08-10T10:25:15.069Z" }
sourceSha256 pins the file in git; artifactSha256 pins the text the model receives. If the deployed prompt does not match the second one, somebody hand-edited production and this whole exercise is about a document nobody is reading.2. Read the artifact before you read the file. This is the step that changes what you think you inherited, and it takes one command. The artifact is not a tidied copy of the source: scaffolding is gone, pointers are flattened, and anything the compiler could not resolve has been turned into prose.
# Role You are a support agent for Cobalt Mobile. # Constraints - You SHOULD try to confirm the account before you discuss a bill. - You MUST call get_order before you state a delivery date. - You MUST answer a delivery question in at most 3 sentences. If tier is premium: You MUST promise a reply within 4 hours. Otherwise: You MUST promise a reply within 2 working days.
tier bound, the deterministic chain compiles to a single line of English carrying both SLAs, so the live agent is being told about the 4-hour promise and the 2-day promise in one breath and left to work out which applies. The survey tool is absent entirely. So is the vip condition.3. Run fmt --check before check. It is the cheap one and it belongs first, because formatting defects hide correctness defects: a hard-wrapped rule is two statements to the compiler, and a bound that never assembled cannot be contradicted. A clean answer here means the findings you are about to read are about content.
$ npx typeglish fmt support.tg --check ✓ 1 file already formatted $ echo $? 0
fmt would report the joins as a count rather than a diff you have to eyeball.§2Read the report as an inheritance
4. Run check and treat every advisory as an unfinished decision. On a prompt you wrote, advisories are a to-do list you have chosen to defer. On a prompt you inherited they are archaeology: each one is a place the previous author started something and stopped.
support.tg:5:3 warn structure/unused-import Required variable "locale" is never used. support.tg:5:21 warn clarity/unused-variable $REQUIRE variable "locale" is never used — no @{locale} reference fills it. Remove it, or reference it in the prompt. support.tg:14:1 warn structure/unused-define $DEFINE vip is never used. support.tg:14:9 warn clarity/unused-definition $DEFINE "vip" is never used — no $IF, $SWITCH, or guard references it. Remove it, or wire the condition in. support.tg:16:1 warn structure/unused-tool Defined tool "send_survey" is never used in the prompt — the model cannot discover a tool no rule mentions. Reference it in a rule (e.g. "call send_survey when ...") or delete the definition. support.tg:26:14 info prompt/hedging Hedging — "try to" turns this instruction into a suggestion the model may skip. Delete the hedge, or commit to a modal (MUST / NEVER / SHOULD). support.tg:26:1 info prompt/unintroduced-definite "the account" retrieves something this document never introduces - a model must guess which account is meant. Introduce it on another line ("You manage an account.") or name it outright. support.tg:30:1 info structure/switch-shaped-chain Every arm tests @{tier} for one member — this chain is a $SWITCH in disguise. The block form proves coverage by construction (a member added to the domain later fails loudly here instead of falling through). Replace the chain with: $SWITCH ON @{tier} - premium:: You MUST promise a reply within 4 hours. - otherwise:: You MUST promise a reply within 2 working days. ✓ 1 file — 0 error, 5 warning, 3 info
locale variable was somebody starting a multilingual build. vip was somebody starting a tier rule. send_survey was somebody starting post-contact surveying. None of the three shipped, and none of the three is visible in the artifact.5. Sort the dead surface by what it implies, not by severity. The three unused declarations are all warnings and all cost the same on the ledger, but they mean different things to you on Tuesday. An unused variable is an interface your host may or may not still be filling. An unused $DEFINE is a condition somebody worked out and did not apply. An unused $TOOL is the loudest of the three, and the message says exactly why.
The model cannot discover a tool no rule mentions. It is in your file, in your review, and in nobody's context window.
Resist deleting them on day one. Each one is a question for whoever asked for it, and the deletion is a one-line commit whenever the answer comes back. What you should not do is leave them and assume they work, which is the state you found them in.
6. Read the arms against the domain. A typed input plus a chain or a switch is the one place in an inherited file where a stale edit becomes a compile error rather than a silent gap, so it is worth running deliberately. Here is the same prompt as somebody left it after the pricing team renamed a tier.
<$CONFIG> $REQUIRE variable tier: one of standard, premium </$CONFIG> # Role You are a support agent for Cobalt Mobile. # Constraints - You MUST answer a delivery question in at most 3 sentences. $SWITCH ON @{tier} - standard:: You MUST promise a reply within 2 working days. - premium:: You MUST promise a reply within 4 hours. - gold:: You MUST promise a reply within 1 hour.
gold arm is a policy somebody signed off, sitting in the file, unreachable.tiers.tg:14:3 error structure/impossible-case "gold" is not a member of @{tier}'s domain — one of standard, premium. ✗ 1 file — 1 error, 0 warning, 3 info $ echo $? 1
typeglish --explain structure/impossible-case gives you the one-liner, a CASE pattern outside the switch domain, the arm can never fire, which is also the answer to give the person who asks what happened to gold.§3Ask what was ever measured
7. Score it, and read the lever rather than the grade. The grade is a number to compare against itself later. The lever is the actionable part, and on an inherited file it tells you which of the eight facets is carrying the loss.
support.tg — D (53/100) proven errors: none tiers: base+z3
planes runtime 71 (what the model reads) · hygiene 0 (source only)
facets enforceability 85 x.21 · hardness 85 x.12 · directness 88 x.08 · consistency 14 x.17
structure 0 x.12 (hygiene) · annotation 0 x.12 (hygiene) · style 79 x.08 · security 100 x.08
lever consistency 14/100 (up to +14 overall) — Fix the ledger rows with logic/ or
clarity/ codes; state each fact in one place.
runtime 71 against hygiene 0: what the model reads is mediocre, and what the next engineer reads is nothing at all. enforceability 85 and hardness 85 say the three surviving rules were written by somebody competent. annotation 0 and structure 0 say nobody ever wrote down why. Eight ledger rows follow the lever, and the three -1 rows are the three orphans, which is the same report from step 4 priced.8. Run test --dry and read the coverage number, including when there is not one. This is the question that separates a prompt somebody maintained from a prompt somebody edited, and the answer here is the worst possible one, delivered with a tick.
$ npx typeglish test support.tg --dry ✓ support.tg no $TEST cases ✓ 1 prompt — 0 failed $ echo $? 0
coverage line at all, which is a different output shape from coverage: 0/3 and the reason a CI gate on this command has to assert the key exists. Nothing in the file has ever been pinned by anything. Every rule in it is a rule you are free to break by accident.9. Use resolve to see the variants somebody was serving. The artifact from step 2 was the template build. Bind the input and you get the document one real customer segment sees, which is the closest thing to a specification of the behaviour you have inherited.
$ npx typeglish resolve support.tg --vars '{"tier":"premium"}'
...
# Role
You are a support agent for Cobalt Mobile.
# Constraints
- You SHOULD try to confirm the account before you discuss a bill.
- You MUST call @[get_order] before you state a delivery date.
- You MUST answer a delivery question in at most 3 sentences.
You MUST promise a reply within 4 hours.
resolve prints the resolved source rather than the deployable text, which makes it the right instrument for reading: it keeps the pointers visible so you can see which references the compiler is still holding. Run it once per member of every typed domain and you have the set of prompts your agent has actually been.§4Leave it better than you found it
Now the edit. The temptation on Thursday is to add the stakeholder's rule and move on, and the argument against is that you are the second person in a row to do that. Two changes cost nothing in behaviour and everything in the next handover.
The first is annotations, which are the only edit in a prompt that provably cannot change what the model does: an @@ note is compile-time and never reaches the artifact, so two files differing only in their notes build to the same hash. Write down what you inferred while running the commands above, including the parts you are unsure of. The second is deciding the three orphans, the hedge, and the chain. Here is the file after both.
<$CONFIG> $CONFIG model claude-opus-4-8 - via:: anthropic $REQUIRE variable tier: one of standard, premium $IMPORT tool get_order </$CONFIG> $SERVICE anthropic - base:: https://api.anthropic.com - headers:: - x-api-key:: @{env.ANTHROPIC_API_KEY} # Role @@ role: delivery and billing for a mobile network You are a support agent for Cobalt Mobile. # Constraints @@ identity: inherited as "should try to confirm", and a bill is account data - You MUST confirm a date of birth before you discuss a bill. @@ lookup_first: a delivery date lives in one system, and it is not this file - You MUST call @[get_order] before you state a delivery date. @@ brevity: a delivery answer is one fact, and three sentences is generous - You MUST answer a delivery question in at most 3 sentences. $SWITCH ON @{tier} - standard:: You MUST promise a reply within 2 working days. - premium:: You MUST promise a reply within 4 hours. $TEST delivery - input:: When will my phone arrive? - expect:: - at most 3 sentences $TEST billing - input:: Why is my bill 12 pounds higher this month? - expect:: - contains "date of birth"
consistency 14 to 100, structure 0 to 100, annotation 0 to 80, hardness 85 to 100. 0 error, 0 warning, 2 info, and the two remaining info findings are prompt/unregistered-doer on the two switch arm rows, which is a note about the arm keys rather than the policy.Four things happened, and only one of them was a policy decision. The hedge became a modal and picked a criterion, which is the policy call: should try to confirm the account named neither what confirming is nor whether it was required, and somebody had to choose. The chain became a $SWITCH ON, so a third tier added to the domain next year is a compile error instead of a customer falling through the $ELSE. The three orphans were deleted, each in its own commit with a name in it. And every rule got a note saying why it exists, including the honest one on line 18 that records what the rule used to say.
Then put the floor in. Both gates now pass on the file you are handing on, which is the only moment they are cheap to install.
$ npx typeglish check support.tg --strict ✗ 1 file — 6 error, 0 warning, 2 info $ echo $? 1 $ npx typeglish score support.tg --min B support.tg — D (53/100) proven errors: none tiers: base+z3 ... $ echo $? 1 $ npx typeglish check support-handover.tg --strict ✓ 1 file — 0 error, 0 warning, 2 info $ echo $? 0 $ npx typeglish score support-handover.tg --min B support-handover.tg — B (86/100) proven errors: none tiers: base+z3 ... $ echo $? 0
--strict escalates the five unused declarations and the switch-shaped chain to blocking. That is the number to keep in mind when somebody says the prompt has been fine for a year. It has been fine with the gate switched off.§5Common questions
- I inherited a system prompt. Where do I start?
- Not by reading it. Build it first, because the artifact is the text the model actually receives and it is not the file: a template build turns an unbound conditional into one line of prose that ships both branches at once. Then run
checkand read the advisories as the previous author's unfinished decisions, runscorefor the lever, and runtest --dryto find out how much of the file was ever pinned by a case. Reading comes after that, with the findings as a map, because the commands tell you what is unfinished and the prose only tells you what somebody meant. - How do I find dead rules and unused declarations in a prompt?
typeglish checknames each one. An orphan input isstructure/unused-importplusclarity/unused-variable, an orphan condition isstructure/unused-defineplusclarity/unused-definition, and a tool nobody references isstructure/unused-tool, whose message is the reason it matters: the model cannot discover a tool no rule mentions. All of them are warnings, so the file exits 0 with them in place. On an inherited prompt they are the highest-value findings in the report, because each one is a feature that was started and never wired in.- Is the prompt file in git the prompt that is running in production?
- Assume not until you have compared hashes.
typeglish buildwrites the artifact and recordssourceSha256andartifactSha256in.typeglish/build-manifest.json, so the check is to build the file you inherited and compare itsartifactSha256against the text your runtime is serving. If they differ, somebody hand-edited the deployed prompt, and every conclusion you draw from the file is about a document nobody is reading. - What should I change first in a prompt somebody else wrote?
- The annotations, because they are the only edit that cannot change behaviour. An
@@ name: whyline above a rule is compile-time only and never reaches the model, so writing down what you inferred about a rule costs nothing at runtime and rebuilds to the same artifact hash. Do that before you touch a word of policy, then put the floor in CI withcheck --strictandscore --minat the number you actually shipped, so the next person inherits a file that fails loudly instead of one that scores D and exits 0.
The number that stayed with us from building this one is hygiene 0. Eight facets, and the two that measure whether the source explains itself were both at the floor while the rules themselves scored 85. That is what an inherited prompt is: competent work with the reasoning deleted. The commands can reconstruct what the file does, and no command will ever reconstruct why, which is the entire argument for the cheapest line in the language. An @@ note costs zero runtime bytes and rebuilds to the same hash, so there is no budget conversation to have about it. Write one above every rule you touch this week, and the next person to inherit this file gets a document instead of an archaeology dig.