rename docs/ to harness/, and reserve docs/ for the reader
docs/content-model.md opens with "Engine specification". It is also where the rule lives that a leading underscore makes a file unaddressable — and the human who owns this site did not know that rule, because nothing in this repository is addressed to an author. Twelve documents named docs/ while being exclusively about building the parser is a signpost pointing at the wrong room. Naming the directory for its audience makes the gap visible instead of hiding it. docs/ is now reserved and deliberately absent: an empty docs/ is an honest statement that end-user documentation does not exist, where docs/ full of parser specs was a claim that it did. HARNESS.md stays at the root. Root holds the three entry points — README.md for a human, CLAUDE.md for an agent, HARNESS.md for whoever maintains the machine — and harness/README.md is the map of the directory, so moving the guide inside would have collided with it for nothing. Mechanical and wide: 100 path references across 24 files. Every verify.sh gate that names a doc by path, the directory lists the dangling-path and ADR-number gates scan, surface.sh's output target, the Makefile, CLAUDE.md's read order, the skill, four commands, and two Go package comments. A first pass with a shell loop silently edited only four files and the rest still said docs/; the fix was to write the file list out and check the remaining count was zero rather than trust the loop's exit status. No rule, threshold, gate or obligation moved — this is a rename, and the gates demonstrated it twice: they stayed green on the new paths, and the ADR-number gate caught ADR-0082 before the entry existed. Deferred, both on the human's call: the end-user documentation site itself, which wants its own decision about where it lives and whether its claims are gated; and moving examples/ under docs/, since demo-site is a live site root that verify.sh, the coverage test and make demo all point at, and moving it would couple a rename to a design nobody has made. 31 files, +146/-106. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# Context economy
|
||||
|
||||
How the agent spends context. The limit on this project is not typing speed, it is how much work fits
|
||||
in a session before the window fills — so bytes that buy nothing are features not built.
|
||||
|
||||
**This doc has a floor and the floor wins.** Every technique below is forbidden from buying:
|
||||
skipping the doc that owns a rule (`CLAUDE.md` §1), guessing an API instead of reading it, reporting
|
||||
success from a diff instead of a run (`SKILL.md` §4), keeping a test that was never seen to fail, or
|
||||
thinning generated code, content, tests, comments or commit messages. Those are all cheaper in tokens
|
||||
and every one of them has cost this project a defect. Frugality applies to **presentation and
|
||||
discovery**, never to the artifact or the evidence. When a saving and the floor disagree, pay.
|
||||
|
||||
## 1. Fewer turns beats fewer bytes
|
||||
|
||||
The whole context is re-sent on every tool call, so a six-call sequence costs roughly six times the
|
||||
window. Batch independent calls into one message. Where a sequence is known in advance or will be run
|
||||
again, write the script instead: one artifact that sets up, runs, probes and prints its conclusion —
|
||||
the live-reload check that measured the watcher is the shape to copy, and `verify.sh` is the same
|
||||
technique applied to the gates.
|
||||
|
||||
## 2. Read the compressed form first
|
||||
|
||||
In order of cost, stop at the first that answers the question:
|
||||
|
||||
| Question | Cheapest answer |
|
||||
|---|---|
|
||||
| where does X live, what is in this package | `harness/surface.md` (generated; `make surface`) |
|
||||
| what does this package offer callers | `go doc ./internal/<pkg>` |
|
||||
| what does this behave like | its `_test.go` — a table states in 20 lines what 200 implement |
|
||||
| why is it like this | `decisions.md`, `state.md` — never the code |
|
||||
| what changed and when | `git log --oneline -- <path>` |
|
||||
| how big is this before I open it | `wc -l`, or the manifest line in `surface.md` |
|
||||
|
||||
Then read the range, not the file: `grep -n` to locate, `Read` with `offset`/`limit`. A whole-file read
|
||||
is for the doc that owns a rule you are about to assert, and for a file you are about to rewrite.
|
||||
|
||||
## 3. Let the machine find it
|
||||
|
||||
Discovery by mechanism beats discovery by reading.
|
||||
|
||||
- **Break it and read the errors.** Changing a signature: `go build ./...` returns the exact caller
|
||||
list, complete, in a form a grep can miss.
|
||||
- `scripts/verify.sh --list` answers "does this gate exist" without running or reading anything.
|
||||
- `grep -c` for "does this exist", `-l` for "which files", `-n` for "where". Context flags only when
|
||||
the surrounding lines *are* the answer.
|
||||
- `go test -run TestName` over a full suite while iterating; the full suite once, at the end.
|
||||
|
||||
## 4. Shrink output at the source
|
||||
|
||||
Filtering inside the call is free. Filtering after it lands is impossible.
|
||||
|
||||
- `./scripts/verify.sh --quiet` — two lines on green instead of one per gate. The pre-commit hook uses
|
||||
it. Use the loud form when a gate fails or you are auditing the gates themselves.
|
||||
- Quiet and fail-fast flags by default: `-q`, `--porcelain`, `--short`, `--oneline`, `-failfast`,
|
||||
`--stat` before `-p`, and `2>/dev/null` for known noise.
|
||||
- Pipe through `tail`/`grep -v`/`awk` in the same call. Ten relevant lines, not four hundred.
|
||||
- Long or noisy runs write to the scratchpad and get queried; never `cat` a lock file, a binary, or
|
||||
generated output.
|
||||
- Sample rather than enumerate: two bundles out of thirty answer whether the shape holds.
|
||||
|
||||
## 5. Never pay for the same bytes twice
|
||||
|
||||
- No re-reading after `Edit` or `Write` — they fail loudly if they did not apply.
|
||||
- A background command's output is read once, after it completes. Not while polling, and not quoted
|
||||
back afterwards.
|
||||
- No restating the plan, then doing it, then summarising it. State once, report deltas.
|
||||
- Write a fact down where it belongs the first time it is established (`state.md`, an ADR, a resume
|
||||
note in the queue file) so the next session reads a line instead of re-deriving it. A handoff note
|
||||
is cheaper than a compaction summary and loses less.
|
||||
- Report `file:line`, never the code — the human has the file, and the reference is clickable.
|
||||
|
||||
## 6. Prose is the cheapest thing to cut and the easiest to overcut
|
||||
|
||||
Target density, not brevity: the same findings, numbers and caveats in fewer words. Cut preamble,
|
||||
recap, restatement, option surveys, and hedging. Do not cut a finding, a measurement, a stated
|
||||
assumption, or a caveat — a report that omits the caveat is not shorter, it is wrong.
|
||||
|
||||
## What is enforced, and what is not
|
||||
|
||||
Three of these are mechanical. `scripts/hooks/pre-commit` regenerates `harness/surface.md` and stages it,
|
||||
so no commit can carry a stale one, and `verify.sh` compares independently for the clone that never set
|
||||
`core.hooksPath`. `CLAUDE_LOC_MAX` bounds the one file billed on every turn. `--quiet` exists to be
|
||||
used, and the hook uses it.
|
||||
|
||||
Everything else here is discipline — no script can see a redundant read, an unnecessary whole-file
|
||||
Read, or a report that padded instead of informing. That asymmetry is the reason this doc is short
|
||||
enough to be re-read, and the reason its floor is stated first.
|
||||
Reference in New Issue
Block a user