> Markdown rendition of https://typeglish.dev/blog/roll-back-agent-prompt ("Put it back the way it was on Tuesday - Tidelines"). Canonical page: https://typeglish.dev/blog/roll-back-agent-prompt · All pages: https://typeglish.dev/llms.txt

[← Tidelines](https://typeglish.dev/blog)/ Best practices Sep 16, 2026

# Put it back the way it was on Tuesday

Nine checks for the afternoon somebody asks you to undo the week. A rollback feels like the safe option because it only removes things, and that is the exact reason it goes wrong: a revert is an edit, and it has to survive every line that landed after the one you are putting back.

by **TypeGlish team** 12 min read #best-practices

A revert is an edit.

**TL;DR** Name the rollback target as an artifact hash, never as a day; revert the *directory* the prompt composes from, because a single-file revert leaves an imported house-rules file at today's version and lands you on a prompt that never existed; then rebuild and require the recorded hash, run `check` because last week's wording against this week's rules can be a blocking contradiction, and read the artifact diff line by line to see what you are giving back. Two things ride along invisibly: the `$CONFIG model` row, which no artifact diff can see, and the host's input bag, which the file never held.

It is half past three on a Friday. Containment on the billing queue has been sliding since Wednesday, a team lead has three transcripts that all look wrong in the same way, and the sentence everyone has landed on is that it was fine on Tuesday. The ask is reasonable and the ask is urgent, and both of those things push you toward the same wrong move, which is to open the file, find the line you think it is, and put the old wording back.

Nine checks, run against a small energy-billing prompt. It is not a broken prompt; it is a prompt three people edited in one week. That is the normal case and it is the whole difficulty.

billing.tg - the prompt as it runs now, Friday ✓ A (95/100)

```
<$CONFIG>
  $IMPORT file "house.tg" as house
  $CONFIG model claude-haiku-4-5
    - via:: anthropic
  $REQUIRE variable balance: number
</$CONFIG>

$SERVICE anthropic
  - base:: https://api.anthropic.com

# Role
@@ role: one sentence names the speaker, so every later "you" is the agent
You are Ora, the billing assistant for Fernhill Energy.

@<house.Constraints>

# Constraints
@@ plan_cap: ops doubled the ceiling after the winter bills landed
- You MUST offer a payment plan of at most 24 months.
@@ plan_floor: collections will not take a plan shorter than this
- You MUST offer a payment plan of at least 18 months.
@@ meter: never quote a figure the meter has not confirmed
- You MUST NOT quote a final bill amount.
@@ arrears_route: the arrears team owns a large balance
$IF @{balance} is at least 300:
  - You MUST transfer a customer to an arrears adviser.
$ELSE:
  - You MUST offer a monthly instalment.

$TEST behind
  - input:: I am two months behind on my bill.
  - expect::
    - offers a payment plan
```

Two files, not one: `house.tg` carries the brevity rule and the AI-disclosure rule every Fernhill prompt shares. Hold on to that, because it is check 4 and it is the one that catches people.

git log - one week, three hands

```
$ git log --format='%h  %ad  %s' --date=short
72189ff  2026-09-16  billing: add the 18-month floor, the house complaints rule, and move to haiku
0a4733e  2026-09-16  billing: raise the payment-plan ceiling to 24 months
ff83d07  2026-09-16  billing: the desk prompt as it ran on Tuesday
```

Three commits, and only the middle one is about the thing anybody suspects. The top one bundles a policy floor, a regulatory rule in the shared file, and a model swap, which is a perfectly normal Thursday and a genuinely awkward thing to roll back.

## §1 Before you touch the file

**Check 1: name the target as a hash, not as a day.** "Tuesday" is not an identifier. It is a shared memory, and in a week nobody will agree on it. What you want is the artifact hash your deploy recorded for the build you are going back to, and the build manifest is the shape that record comes in.

the build manifest - one row per build

```
{
 "source": "billing.tg",
 "sourceSha256": "2b3e35b010cd8ddcfbd5730279504ce4d33e044f726eb09a0e9a1b15504e5b77",
 "artifact": ".typeglish/dist/billing.txt",
 "artifactSha256": "cd9c4b99bc51753a0c9c015c5d985880d68d71efa82045d9fe43e10f8d3ce37b",
 "vars": null,
 "typeglish": "0.9.0",
 "checkMode": "full",
 "report": { "ok": true, "counts": { "error": 0, "warn": 0, "info": 0 }, "strict": false },
 "builtAt": "2026-09-16T09:29:02.017Z"
}
```

Three fields do work here that a commit sha cannot. `artifactSha256` identifies the bytes the model actually read, so it survives a rename, a comment, and a reformat. `vars` records the input bag the build was pinned to, or `null` for a template build. And `typeglish` records the compiler, which is what makes a rebuilt artifact comparable with the one it is replacing. Note what this row is and is not: the manifest holds the latest build per artifact path, so this is `cd9c4b99bc51`, what is live. Tuesday's hash has to come from wherever the deploy logged it, and in this repo that is `6d35707cb150`. If nobody logged it, the fallback is to rebuild Tuesday's commit and take what comes out, while saying out loud that you are trusting the `typeglish` field to still read `0.9.0`.

**Check 2: reproduce the complaint as a `$TEST` before you change anything.** This is the check most likely to be skipped and the only one that outlives the afternoon. You have three transcripts. Turn the clearest one into a case with a deterministic assert, and add it to the file you are about to roll back *and* the file you are rolling back to. If the rollback fixes the behaviour, the test is now a regression test that will fail the day somebody re-lands the change without thinking. If the rollback does not fix it, you have learned that in twenty seconds rather than after a deploy, which is the more valuable outcome and the one nobody plans for. [Your agent said the wrong thing, now what](https://typeglish.dev/blog/agent-said-the-wrong-thing) is the longer version of this hour; the short version is that the transcript is evidence and a transcript nobody wrote down is a rumour.

## §2 The revert is an edit

**Check 3: run `check` on the revert, because last week's wording has to live with this week's rules.** Here is the move everybody makes under time pressure. The plan ceiling looks like the culprit, so put it back to what it was on Tuesday and leave everything else alone. In isolation that line is unimpeachable: it is the line that was running when the numbers were fine.

the two rules, as they stand on Friday ✓ clean

```typeglish
# Role
@@ role: one sentence names the speaker, so every later "you" is the agent
You are Ora, the billing assistant for Fernhill Energy.

# Constraints
@@ plan_cap: ops doubled the ceiling after the winter bills landed
- You MUST offer a payment plan of at most 24 months.
@@ plan_floor: collections will not take a plan shorter than this
- You MUST offer a payment plan of at least 18 months.
```

A ceiling of 24 and a floor of 18 leave a six-month window, so the prover has nothing to say. Both rules are good policy and neither was written by the person who wrote the other.

the same two rules with the ceiling reverted ✗ logic/numeric

```typeglish
# Role
@@ role: one sentence names the speaker, so every later "you" is the agent
You are Ora, the billing assistant for Fernhill Energy.

# Constraints
@@ plan_cap: twelve months is the ceiling collections signed off
- You MUST offer a payment plan of at most 12 months.
@@ plan_floor: collections will not take a plan shorter than this
- You MUST offer a payment plan of at least 18 months.
```

Nothing was added. One number went back to what it was three days ago, and the window closed.

tg check + score + build - the partial revert ✗ F (79/100)

```
$ npx typeglish check .
billing.tg:19:1  error  logic/time  Conflicts with line 14. Time conflict — "at most 12 months" and "at least 18 months" cannot both bound "you offer a payment · plan": the windows never intersect.
billing.tg:19:1  error  logic/numeric  Conflicts with line 14. Numeric conflict — "at most 12 months" and "at least 18 months" can't both hold.
billing.tg:21:1  error  logic/time  Conflicts with line 13. Time conflict — "at most 12 months" and "at least 18 months" cannot both bound "you offer a payment · plan": the windows never intersect.
billing.tg:21:1  error  logic/numeric  Conflicts with line 13. Numeric conflict — "at most 12 months" and "at least 18 months" can't both hold.

✗ 2 files — 4 error, 0 warning, 0 info
program: 1 root — billing.tg (2 files)
# exit 1

$ npx typeglish score billing.tg
billing.tg — F (79/100)  proven errors — grade capped at F  tiers: base+z3

$ npx typeglish build billing.tg
typeglish build: billing.tg refused — nothing written
```

Four findings on two planes for a one-number edit: the numeric prover reads it as an empty interval and the time layer reads the same bound as a duration whose windows never intersect. The build writes nothing, which is the behaviour you want from a rollback at half past three on a Friday. Reverting to a wording that was correct in its own week is not a safe operation, and this is the whole reason to put the revert through the compiler instead of straight into the console.

**Check 4: revert the directory, not the file.** So do it properly: take the whole prompt file back to Tuesday's commit rather than hand-picking a line. This passes, which is the problem.

git checkout - the single-file revert ✗ not Tuesday

```
$ git checkout ff83d07 -- billing.tg

$ npx typeglish check .
✓ 2 files — 0 error, 0 warning, 0 info
program: 1 root — billing.tg (2 files)

$ npx typeglish build billing.tg
✓ built .typeglish/dist/billing.txt ← billing.tg (7744c9d03bb6, full)
```

`7744c9d03bb6`. The target was `6d35707cb150` and the thing you are replacing was `cd9c4b99bc51`, so this is a third prompt: not the one that shipped on Tuesday, not the one running now, and one that has never been in production or in front of a reviewer. `house.tg` is still at Thursday, because a revert of one file is a revert of one file, and the shared file is part of the deployed prompt.

**Check 5: rebuild and require the recorded hash.** This is the null test, and it is four seconds. Revert everything the prompt composes from, rebuild, and demand the twelve characters the manifest wrote down for the day you are going back to. Equality is the whole claim of a rollback, and until this command passes it is an assertion.

git checkout - the directory revert, and the null test ✓ 6d35707cb150

```
$ git checkout ff83d07 -- .

$ npx typeglish check .
✓ 2 files — 0 error, 0 warning, 0 info
program: 1 root — billing.tg (2 files)

$ npx typeglish build billing.tg --bundle
✓ built .typeglish/dist/billing.txt ← billing.tg (6d35707cb150, full)
```

Byte for byte the prompt that ran on Tuesday. That is a rollback. The two commands above it, which produced a clean check and a successful build on a prompt nobody has ever run, are what a rollback looks like when nobody asks for the hash. The same `$IMPORT` mechanics are the point of [the paragraph that lives in three prompts](https://typeglish.dev/blog/house-rules-import-rewrite), and this is their bill coming due.

## §3 Read what you are giving back

**Check 6: diff the live artifact against the one you are about to deploy, and read every line.** A rollback is a change with a direction, and the direction does not make it small. Three days of decisions come out in one command, and the useful discipline is to say out loud, for each line, who decided it and whether they know it is going.

diff - what the rollback gives back ✗ 3 rules

```
$ diff live/billing.txt .typeglish/dist/billing.txt
5d4
< - WHEN a customer raises a complaint THEN you MUST transfer them to a complaints handler.
9,10c8
< - You MUST offer a payment plan of at most 24 months.
< - You MUST offer a payment plan of at least 18 months.
---
> - You MUST offer a payment plan of at most 12 months.
```

Two of those three lines are the thing you meant to undo. The first is not. A complaints rule with an eight-week regulatory clock behind it went into the shared file on Thursday, and rolling the billing prompt back to Tuesday removes it from the deployed prompt, on a Friday afternoon, as a side effect of a containment decision. Nobody chose that. It is in the diff because the diff is the artifact rather than the file, and it is the reason this check is not optional.

**Check 7: read the bundle, because the model rides along and the artifact cannot see it.** Thursday's commit moved the prompt to a smaller model in the same breath as the rules. Rolling the file back rolls that decision back too, and there is no trace of it in the prompt the model reads.

the --bundle sidecar - the only place the model appears

```
$ cat .typeglish/dist/billing.agent.json
{
 "model": {
  "id": "claude-opus-4-8",
  "service": { "name": "anthropic", "base": "https://api.anthropic.com", "headers": [] }
 }
}
```

Build the identical prompt against `claude-haiku-4-5` and against `claude-opus-4-8` and both come out at `6d35707cb150`. A `$CONFIG` row is control plane, stripped before a byte is emitted, so the artifact hash you have been leaning on for the last four checks is blind to it by design. That is correct behaviour and it is a hole in your rollback: an artifact-only review cannot tell a prompt rollback from a prompt rollback plus a model change. If the swap is the thing you actually wanted to keep, [somebody wants the model bill smaller](https://typeglish.dev/blog/cheaper-model-checklist) is the list for unpicking the two.

**Check 8: the host's input bag does not roll back, because it was never in the file.** Half the deployed prompt arrives at request time, and a git history has no opinion about it. The same reverted source, built against two bags, is two different prompts.

tg build --vars - one source, two host bags

```
$ npx typeglish build billing.tg --vars '{"balance": 250}' --out-dir v250
✓ built v250/billing.txt ← billing.tg (fb15eae9d05e, full)

$ npx typeglish build billing.tg --vars '{"balance": 400}' --out-dir v400
✓ built v400/billing.txt ← billing.tg (dfe052b5cadd, full)

$ diff v250/billing.txt v400/billing.txt
10c10
< - You MUST offer a monthly instalment.
---
> - You MUST transfer a customer to an arrears adviser.
```

Two hashes from one reverted file. If the incident was a routing problem rather than a wording problem, rolling the prompt back changes nothing about it, because the threshold that chose the arm is in the prompt and the value that met it came from the host. Before you roll back, check whether whatever feeds `@{balance}` also changed this week. [Your prompt cannot tell a missing input from a real one](https://typeglish.dev/blog/missing-input-ablation) is the same seam, seen from the other side.

## §4 Landing it

**Check 9: land the rollback as a commit forward, with the tests from check 2 still in the file.** Not a force push, not a reset, not a deploy from a detached head. The prompt is source and its history is the audit trail: somebody will ask in October why the complaints rule disappeared for four days, and the answer needs to be a commit message rather than a recollection. Put the hash in it, both of them, the one you left and the one you landed on.

tg test --dry - the coverage denominator moves with the rules

```
$ npx typeglish test billing.tg --dry          # before the rollback
✓ billing.tg  coverage: 5/6 rules exercised

$ npx typeglish test billing.tg --dry          # after the rollback
✓ billing.tg  coverage: 4/5 rules exercised
```

The suite did not change; both halves of the fraction did. Coverage counts the rules the cases reach over the rules that exist, so a rollback moves the denominator under a fixed suite and the two readings are not comparable across the versions. Do not gate a rollback on it. What the suite *should* hold after this afternoon is one more case than it held before: the transcript from check 2, pinning the behaviour the rollback was for.

And the part a checklist cannot do for you. Every command above answers the question "did I land where I meant to", and none of them answers "should I have". A rollback trades a known-bad week for a known-good one and pays for it in whatever was genuinely better about the week you are deleting. In this file that is a ceiling ops raised for a reason, a floor collections asked for, and a regulatory rule with a clock on it, all of which will have to be re-landed on Monday by somebody reading a diff. The narrower fix, reverting one rule with its guard intact, is usually the right one, and check 3 exists because the narrow fix is the one the compiler has the most to say about.

## §5 Common questions

**How do I roll back an AI agent system prompt?**

Treat it as an edit, not an undo. Name the target as the artifact hash the build manifest recorded for the day you want back, rather than as a day. Revert the *directory* the prompt composes from rather than the one file, because an imported house-rules file is part of the deployed prompt and a single-file revert leaves it at today's version. Rebuild and require the hash to equal the recorded one, which is the null test that proves you landed where you meant to. Then run `check`, because a revert composes last week's wording against every rule added since and can be a blocking contradiction. Finally diff the live artifact against the one you are about to deploy and read every line you are giving back.

**Why does reverting one line of my prompt break the build?**

Because a revert is an edit, and the line you are putting back has to live with the lines added after it left. A billing prompt holding *a payment plan of at most 24 months* and *a payment plan of at least 18 months* is clean. Restore the ceiling to the 12 months it was on Tuesday and the same file is 4 blocking errors, two `logic/time` and two `logic/numeric`, graded `F (79/100)`, and the build refuses to write anything. This is the rollback working. A partial revert that reintroduces an old bound under a new floor is exactly the change no reviewer catches by eye, and it is the one the prover catches every time.

**Does a git revert of my prompt file roll back the deployed prompt?**

Not by itself, if the prompt composes from more than one file. Reverting only `billing.tg` while the imported `house.tg` stays at today's version checks clean, builds, and produces an artifact that is neither the prompt that shipped on Tuesday nor the one running now. The two differ by a regulatory complaints rule that was added to the shared file and that a single-file revert silently keeps. Revert the directory, rebuild, and compare the hash against the manifest. And one thing a git revert can never bring back at all is the host's input bag, because it arrives at request time and nothing in the file pins it.

**What does a prompt rollback silently change besides the rules?**

The model, and no artifact diff can see it. A `$CONFIG model` row is control plane: it is stripped before a byte is emitted, so the same prompt built against `claude-haiku-4-5` and `claude-opus-4-8` produces the identical artifact hash. If the model was swapped in the same week as the rules, a rollback of the file swaps it back, and the only place that shows is the `build --bundle` sidecar, which names the model id and the service it requests through. Read the sidecar as part of the rollback, and log the compiler version from the build manifest too, so a rebuilt artifact is an apples-to-apples comparison with the one it is replacing.

Field note

The reason a rollback is worth nine checks rather than one command is that it is the only prompt change routinely made by somebody who is not trying to change anything. Every other edit on this blog arrives with an intent you can hold the result against: a rule to add, a bound to move, an arm to scope. A rollback arrives with an intent of "less", and "less" is not a specification, so the thing that decides what actually ships is whatever the tooling happens to reach. A single-file `git checkout` reaches one file and produces a prompt that has never existed. A hand-edited line reaches the wording and not the week it has to live in, which is `4 error` and a refused build if you run the compiler and a silent policy contradiction if you do not. What holds it together is the same discipline as the rest of the pipeline and the same one nobody enjoys: the artifact is the deliverable, its hash is its name, and the diff against the live artifact is the only honest statement of what a rollback does. Get those three in the ticket and the October question answers itself. If you are building the gate, [the prompt is frozen, the artifact is not](https://typeglish.dev/blog/frozen-prompt-artifact) is what counts as a change, and [we moved eleven lines, six shipped a different prompt](https://typeglish.dev/blog/rule-order-ablation) is why the source diff is not the document to review.

∿ washed up Sep 16, 2026 ∿
