FIELD NOTES//LOG 02 · PRACTICE

Your agent changed 14 files. Which docs went stale?

The failure mode of AI-assisted development is quiet. Nothing crashes, the tests pass, the diff merges. And somewhere in your docs, a paragraph that used to be true just stopped being true.

2026-07-117 MIN READPRACTICECHANGE CONTROL
← All field notes

Docs are load-bearing now

Coding agents read documentation before they write code. That changed what a stale doc costs. It used to mislead the next engineer, who would notice the smell and double-check the source. Now it steers the next agent session, which will confidently build on whatever the doc claims. A wrong sentence in a feature doc becomes wrong code within the hour.

In agent-speed development, documentation stopped being a courtesy. It is an input.

Staleness is a measurement problem

Most teams treat doc drift like weather: everyone complains, nobody measures. But drift has a precise definition once you write down one fact per file: which doc owns it. codument keeps that fact in a registry, docs/.registry.json, mapping every source file to the feature doc responsible for it.

With ownership recorded, staleness becomes checkable. A source file changed and its owning doc did not: that is not a vibe, it is a finding.

TERMINAL
$ npx codument review

  2 changed file(s): 1 source, 0 docs

  Stale docs (source changed, mapped doc did not)
    ⚠ auth: docs/features/auth.md (changed: src/auth/session.ts)

Only the owner wakes

File-level checks cause alarm fatigue: touch a big file and every doc that mentions it screams. codument resolves staleness per symbol instead. Each exported symbol's token stream is fingerprinted across two git refs, and names bound inside a declaration are rewritten to positions before hashing. A local rename that preserves meaning moves nothing.

When a documented symbol genuinely moves and its owning doc does not, exactly one feature wakes, and the finding names the symbol:

TERMINAL
  Symbol drift — resolve each: update the doc, or ack a contract-neutral move
    • rotateToken (changed) in auth
        contract changed → update docs/features/auth.md at intent altitude
        internal only   → codument ack src/auth/session.ts::rotateToken(). --reason "..."

The verdict is a pure function of two git refs: same repo state, same output, no model call anywhere on the path.

When no doc is owed: acknowledge, don't paper

Some moves change no contract. The worst response is editing prose to appease a checker, because junk mirror edits rot docs as surely as staleness does. codument's answer is an acknowledgment:

TERMINAL
$ codument ack src/auth/session.ts::rotateToken(). --reason "moved intact, contract unchanged"

✓ acknowledged src/auth/session.ts::rotateToken(). (3a992885→388fb915, self)

An ack is bound to the exact fingerprint transition it adjudicated. The next time that symbol moves, the ack expires on its own. There is no ride-forever exemption to accumulate.

The gate only trusts what it can re-run

A drift check keeps docs honest; it says nothing about whether the change itself holds up. For that, codument runs two adversaries across the workflow, and neither one gets to be creative.

The plan adversary contests the plan before code exists. Its objections must be grounded: each one cites a committed doc, a test, or the stated scope. It never blocks; the human adjudicates every objection in chat.

The review adversary attacks a fingerprint-bound bundle of the diff plus the documented invariants it crosses. Its findings only block when a named test is genuinely red on a live re-run. No red test, no block. And because the recorded review binds to both the reviewed sources and the tests its findings name, fixing the code or touching a test invalidates the review, and the gate reopens:

TERMINAL
  ✗ --require-review: 1 confirmed finding(s) unresolved.
    • src/auth/session.ts:rotateToken — the per-rotation cap still extends the
      session on every refresh; continuous rotation keeps a session alive forever
      (test: test/session-ttl.test.ts)

A reviewer's prose is never trusted. A verdict is computed, not generated.

The payoff is retrieval

Here is the part that makes the discipline pay rent every day, not just on the day something drifts. The same registry that catches staleness can be projected the other way: given a feature, hand back the smallest grounded working set for it. The owning doc, its invariants with their test pointers, the primary sources, the declared risk.

TERMINAL
$ codument context --feature auth

  auth — docs/features/auth.md  ~88 tok
    Invariants & boundaries
      - An expired session must never authorize
      - Sessions expire one hour after issue.
    primary sources: src/auth/authorize.ts, src/auth/session.ts
    risk: security

An agent that starts from this pack reads a fraction of what a whole-repo crawl costs, and everything it reads has been kept true by the gate above. In codument's packaged benchmark the context pack measured 1,746 estimated tokens against 3,068 for whole-file context, an eight-file working set instead of sixteen. It is a fixture benchmark, not your repo, but the direction is the point: docs in, trusted context out.

That loop is the whole argument. A doc you can trust is retrieval infrastructure. A doc you cannot trust gets routed around, and then it is just weight.

Try it on the history you already have

You do not need to adopt anything to see your own number. Two read-only commands replay your committed history against a proposed ownership map and report every feature whose code moved while its doc got no attention:

TERMINAL
$ npx codument scan
$ npx codument audit v1.0.0..HEAD

Read the damage report, then decide. Nothing is gated, nothing needs committing; delete the scaffolds and you have adopted nothing.

One honest limit, because honest limits are the house style: codument reports facts and gaps. It does not certify that a change is safe, and it does not try. The judgment stays with you; the instrument just makes sure you are judging the change that actually happened, against docs that are actually true.

SEE THE CATCH HAPPEN · 30 SECONDS