Harness Engineering / Anatomy of a Charter / reference

Every line in a charter is a scar.

Most teams write their charter on day one, from best practices, in one sitting. That document is a list of guesses, and it will be argued away the first time it is inconvenient, because nobody can say what it cost to learn. Good charters are not authored. They accrete, one incident at a time, and every rule carries the date and the damage that put it there. Here is one, in full, annotated line by line.

who it's for · anyone maintaining a CLAUDE.md, a rules directory, or a system prompt
the charter below · a billing team's. The same rules that fire in the audit trail and get measured in the eval loop
the shape it argues for · forty lines, every rule dated, adding requires removing
license · CC BY 4.0. Fork it, change every rule, keep the annotation format
The incident
What went wrong, when, and what it cost. A rule without one is a preference wearing a uniform.
The altitude
Sentence, check, or gate. Stated explicitly, and always the cheapest one that actually holds.
The expiry
When this gets reviewed for deletion. A rule that cannot expire is a rule nobody will ever remove.
0 The premise

A charter written in advance is a list of guesses

The best practices you would put in it on day one are the ones the model already follows. The rules that matter are the ones your codebase taught you, and you cannot know those yet.

Watch what happens to a day-one charter. It says "write clean, maintainable code" and "follow existing patterns" and "add tests". Every line is true, none of it changes any behaviour, because the model was already doing roughly that. Then a real problem arrives, somebody adds a paragraph about it, and now the document is nine tenths ornament and one tenth load-bearing, with no way to tell which is which from the inside.

The alternative is uncomfortable and works: start with nothing, and add a rule only after something has gone wrong. The resulting document is shorter, every line has a story, and when someone proposes dropping one under deadline pressure there is an answer that is not an opinion.

two documents of the same lengthonly one survives a crunch
AUTHORED
  "Prefer clear names."           ← already true. costs nothing, does nothing
  "Handle errors appropriately."  ← unfalsifiable
  "Write maintainable code."      ← nobody has ever done otherwise on purpose

ACCRETED
  "Money is integer cents."       ← #412, silent rounding loss on refunds
  "Payment calls fail fast."      ← INC-88, 1,140 double charges
  "Only paths named in the ticket."← #388, unreviewed rename broke two teams
The test for any line you are about to add

Can you name the specific thing that went wrong without it? If not, you are writing a wish. Wishes are free to add and impossible to remove, which is the exact combination that produces a charter nobody reads.

1 In full

The whole charter, forty lines

A billing team, three years in, after roughly a dozen incidents. This is what is left after the deletions.

CHARTER.mdthe artifact
# Billing · agent charter
#
# Every rule names the incident that caused it. No incident, no rule.
# Adding one requires removing or merging one. Reviewed each January.

## Money
Money is integer cents. Percentages resolve through Decimal, then
round half-up to cents. Never float on a money path.
  gate money.integer-cents
  2026-03-04 · #412 · float refund rounding, ~$40/day lost silently

## Failure
Payment calls fail fast. No retries on any non-idempotent path.
  gate payments.no-retry
  2025-11-22 · INC-88 · retry storm double-charged 1,140 customers

## Scope
A change touches only paths named in the ticket. Renames, reformats
and refactors are separate changes with their own review.
  check scope.allowed-paths
  2025-08-09 · #388 · a rename rode along and broke two other teams

## Tests
Every behaviour change ships a test that goes red when the change is
reverted. A test that cannot fail is not a test.
  check test.must-fail-when-reverted
  2026-01-15 · #401 · 300 lines of coverage asserting against its own mock

## Secrets
Never read .env, credentials, or key material. Never write a literal
token, even in a fixture.
  gate secrets.no-read · secrets.no-literals
  2025-06-30 · INC-71 · test fixture key leaked to a public fork

## Comprehension
Don't merge a change you can't explain. Four claims, in the PR.
  human see the Comprehension Standard
  2025-04-02 · standing · adopted team-wide, not incident-driven

## Refusal
When the ticket and the code disagree about what the rule is, stop
and ask. Do not pick the one that is easier to implement.
  none unenforceable, and the most valuable line here
  2026-02-11 · INC-94 · agent implemented the ticket; the ticket was wrong

Seven sections, six of them traceable to a specific bad day. Notice how much is absent: nothing about style, nothing about naming, nothing about architecture, no instructions to be careful or thorough. §5 is about why.

2 The unit

Four parts, and none of them optional

The rule text is the part everyone writes and the least important of the four.

the annotation formatsteal this, not the rules
Money is integer cents. Percentages resolve through Decimal,
then round half-up to cents. Never float on a money path.
└─ 1. THE RULE — behavioural, testable, and about this codebase

  gate money.integer-cents
   └─ 2. THE ALTITUDE — where it is enforced, and its identifier

  2026-03-04 · #412
   └─ 3. THE DATE AND THE LINK — so it can be looked up

  float refund rounding, ~$40/day lost silently
   └─ 4. THE DAMAGE — in the units the business uses
  1. The rule Behavioural and specific to this system. "Money is integer cents" is a rule. "Be careful with money" is a mood.
  2. The altitude One of gate, check, human, or none. Writing it down forces the question "is this actually enforced anywhere", which is uncomfortable roughly a third of the time.
  3. The date and link Makes the rule auditable and makes §7 possible. Also tells a reader instantly whether this rule is from a world that still exists.
  4. The damage In money, customers, or hours. This is the part that wins the argument in a crunch, and it is the part that always gets dropped when people are in a hurry to write the rule.
Why "~$40/day" and not "a bug"

Six months from now somebody will propose relaxing this rule because it is inconvenient in one place. "It caused a bug" loses that argument. "It quietly cost forty dollars a day for three weeks before anyone noticed" wins it, and more importantly it lets you lose the argument correctly on the occasions when forty dollars a day is genuinely the right price.

3 Three scars

Why these three are at three different altitudes

Same document, three enforcement strengths, and the choice is not about how much the team cares. It is about what the failure is shaped like.

picking the cheapest altitude that actually holds
RuleAltitudeWhy not lowerWhy not higher
Money is integer cents gate Reached production once and cost money. Prose already failed here. Nothing higher exists.
Only paths in the ticket check Happens constantly; prose alone was ignored under deadline. Legitimate exceptions exist, so a hard refusal would be routinely overridden, and a gate everyone overrides is worse than a check.
Stop and ask when the ticket is wrong none Nothing lower than prose. Not mechanically detectable. A gate here would be a lie. §4.

The rule for choosing

  • Start at prose. Most rules never need to leave. Promotion costs engineering time and adds friction to every future change.
  • Promote on evidence, not on fear. A rule earns a check when prose demonstrably failed, and a gate when the failure reached production. Both of those are facts you can point at, not predictions.
  • Do not gate what has legitimate exceptions. A refusal that gets overridden weekly teaches everyone that refusals are negotiable, and it damages the gates that are not.
Demotion is a move too

A gate whose rule has become second nature can go back down to a check, or out entirely. Almost nobody does this, which is why charters only grow. See the demotion section for the version of this argument that applies to harness code.

4 The best line

The most valuable rule is the one you cannot enforce

"When the ticket and the code disagree about the rule, stop and ask." No gate can detect this. It stays anyway, and it is the line that has prevented the most expensive failures.

INC-94 is worth telling in full because it is the failure mode that survives every mechanical control on this page. A ticket asked for discount codes to apply to shipping. The code had a rule, three years old and undocumented, that shipping is never discounted because of how the carrier contract settles. The agent implemented the ticket. Every test passed, every gate passed, review approved it, and the company spent five weeks under-billing carriers before anyone connected the two.

No gate catches this. The change was correct with respect to the ticket, correct with respect to the tests, and consistent with the codebase style. The only thing that catches it is somebody noticing that two sources of truth disagree and stopping to ask which one is wrong. That is the whole skill, and it is why the exercises in this catalog exist.

Do not delete the rules you cannot enforce

There is a tidy-minded instinct to strip a charter down to only the mechanically enforced rules, on the grounds that the rest is decoration. Resist it. The unenforceable lines are where the expensive failures live, precisely because they are the ones no gate is watching. Marking them none is honest. Removing them is not.

What to do instead of enforcing it

Train for it. A rule marked none is a standing instruction to the humans, and the way it gets installed is reverse-review and the workshop, not a hook. Charter rules at the none altitude should each point at how the team practises them.

5 Absent

Six things deliberately not in there

A charter is defined by its omissions. Every line you add dilutes the ones that matter, so the omissions have to be argued for as carefully as the inclusions.

  1. Style Line length, quote style, import order. The formatter already does this deterministically and for free. A charter rule here spends attention to duplicate a solved problem.
  2. Type-enforced facts "Always return a Result type." If the compiler enforces it, saying it again buys nothing and dates badly when the types change.
  3. Generic virtue "Write clean, maintainable, well-documented code." Unfalsifiable, universally agreed, and changes no output. The most common filler in the genre.
  4. Things done well already Instructions the model follows at a high rate unprompted. Measure before adding: if it is already at 95%, the rule is buying the last five points at the cost of diluting everything else.
  5. Architecture essays Three paragraphs on the service topology. This is documentation, it belongs in the repo, and the agent can read it when the task calls for it. A charter is rules, not context.
  6. Anything about tone How the agent should phrase things. Occasionally worth having, almost never worth the space it takes at the top of a document whose lower half is already weakly followed.
Ordering is a real effect, and a reason to stay short

Instructions near the top of a long document are followed more reliably than instructions near the bottom. You can respond to that by carefully ordering a long charter, or by keeping it short enough that ordering does not matter much. The second is more robust, because the first is a property of today's models that you would have to re-verify every time one changes.

6 40 lines

A fixed budget, because growth is the default

Nothing in the ordinary operation of a team ever removes a charter rule. Without a hard constraint the document grows monotonically until it stops working, and nobody can point at the day it did.

rule adding requires removing cap 40 lines of rules

The mechanism is one line at the top of the file: adding a rule requires removing or merging one. It is crude, it is occasionally annoying, and it is the only thing that reliably works, because it converts every addition into a comparison. Not "is this rule good" but "is this rule better than the weakest rule currently in here", which is a question with an answer.

Three ways to make room

  • Merge. Two rules about money handling become one rule about money handling. Usually possible and usually an improvement in clarity.
  • Promote. Move the rule out of the prose and into a gate, then delete the prose. The constraint gets stronger and the document gets shorter, which is the best available trade.
  • Delete. The rule has not fired in a year, see §7.
Promotion is the move to reach for first

A rule that becomes a check or a gate stops needing to be prose at all. The agent does not have to remember it, the document gets a line shorter, and the constraint gets stronger. Promotion to the harness is the same idea worked through five different mount points.

7 Annually

Deletion day

One afternoon a year, with the audit trail open. The question for each rule is not "is this still a good idea" but "when did this last do anything".

This is why the trail records passes as well as blocks. A rule that has never blocked anything is either perfectly internalised or completely dead, and those look identical from the outside until you have the numbers.

the annual review, one row per rule
RuleFiredBlockedLast blockVerdict
money.integer-cents1,204316 days agokeep · load-bearing
payments.no-retry89043 months agokeep · rare and catastrophic
scope.allowed-paths1,204147todaykeep · but 147 is a smell, investigate
test.must-fail-when-reverted1,2040neverdemote to check-only, revisit next year
logging.structured-only1,2040neverdelete · superseded by the linter in March

Two judgement calls in that table are worth naming. A rule with four blocks in a year stays, because the metric is not frequency but expected damage, and a double-charge event dwarfs a hundred scope warnings. And a rule with a hundred and forty-seven blocks is not a success story: something is systematically producing changes that violate it, and the rule is absorbing a problem rather than solving it.

The deletion has to be someone's job

Additions happen naturally, because adding a rule is how a team demonstrates it took an incident seriously. Deletion has no such motivation behind it and will not happen spontaneously. Put a name and a date on it, or accept that the charter grows forever.

8 Day one

Writing your first one: start empty

Genuinely empty, apart from the header that says how the file works.

CHARTER.md, day onethe whole file
# Charter
#
# Every rule names the incident that caused it. No incident, no rule.
# Adding one requires removing or merging one. Reviewed each January.
#
# Format:
#   the rule, in behavioural terms
#     altitude: gate | check | human | none
#     date · link · what it cost

(no rules yet)

It will not stay empty for long, and every line that arrives will have earned its place. Two exceptions are reasonable on day one: a comprehension bar, because that one is a policy decision rather than a lesson, and anything you are carrying over from a previous team with the original incident still attached.

Where to start with an existing charter

Do not rewrite it. Go through it once and put a date and a cause on every line you can. The lines where you cannot are your answer: some of them are load-bearing and merely undocumented, and the rest are the ones to delete first. That exercise takes an hour and is usually the most informative hour anyone has spent on the document.