AGENTS.md · diff
git:20260812.2349e87 to git:20260812.4ef30ce
108 added, 12 removed. Audit A to A.
# AGENTS.md — plumb-line
- Instructions for coding agents working in this repository. Humans want
- [`CONTRIBUTING.md`](CONTRIBUTING.md) (how to contribute),
- [`DEVELOPMENT.md`](DEVELOPMENT.md) (how to build and test), and
- [`ROADMAP.md`](ROADMAP.md) (what is planned) — this file does not repeat them.
+ Instructions for coding agents working in this repository, and the map a
+ new contributor needs to find everything else.
- Two things are load-bearing here and easy to get wrong:
+ This file deliberately **points rather than copies**. Every durable fact
+ about this repo already lives in a committed document; restating values
+ here would create a second source of truth that drifts — the failure this
+ repo exists to prevent. What is written here is what you cannot get by
+ reading one file: *which* file, and *that* it matters.
- **This repo is held to its own principles.** The
- [portable principles](reference/portable-principles.md) that the audit skill
- applies to other people's code apply to this code. Don't launder uncertainty,
- hardcode a prior, or overstate maturity — use the maturity vocabulary
- (`current` / `planned`), not aspirational claims.
+ ## Where things are written down
- **There is no root test command.** Each component is tested from its own
- directory; see [`DEVELOPMENT.md`](DEVELOPMENT.md).
+ | You need | It is in |
+ | --- | --- |
+ | How to build and test each component | [`DEVELOPMENT.md`](DEVELOPMENT.md) |
+ | How to contribute, and what a PR must satisfy | [`CONTRIBUTING.md`](CONTRIBUTING.md) |
+ | How releases are cut and published | [`RELEASING.md`](RELEASING.md) |
+ | The nine principles this project enforces — and is held to | [`reference/portable-principles.md`](reference/portable-principles.md) |
+ | The envelope schema (the formal spec) | [`primitives/SPEC.md`](primitives/SPEC.md) |
+ | The two API shapes, JS vs Python | [`docs/api.md`](docs/api.md) |
+ | Cross-language parity, and the case table that enforces it | [`primitives/PARITY.md`](primitives/PARITY.md), [`primitives/conformance/cases.json`](primitives/conformance/cases.json) |
+ | What is guaranteed, and what is only tamper-*evident* | [`docs/threat-model.md`](docs/threat-model.md), [`SECURITY.md`](SECURITY.md) |
+ | Exact-valued global constraints (versions, floors, contracts) | [`docs/constraints.md`](docs/constraints.md) |
+ | Why a past decision was made | [`docs/adr/`](docs/adr/) — append-only |
+ | What is planned, and how the backlog is organised | [`ROADMAP.md`](ROADMAP.md) |
+ | This repo's tracking vocabulary and modules | [`docs/tracking-dialect.md`](docs/tracking-dialect.md) |
+ ## Four things that are load-bearing
+
+ Each is documented above. They are repeated here as *warnings* because
+ each is something an agent gets wrong by acting on a reasonable default.
+
+ 1. **There is no root test command.** No root `package.json`. Each
+ component is tested from its own directory. Running "the tests" from
+ the repo root tests nothing. See [`DEVELOPMENT.md`](DEVELOPMENT.md).
+ 2. **Parity is the central invariant.** JS and Python must behave
+ *identically*. When you change combination or audit behaviour, change
+ **both** implementations and add a row to `cases.json`. A divergence
+ failing one suite is the system working. Never "fix" parity by editing
+ prose — fix the code or the case table.
+ 3. **This repo is held to its own principles.** The rules the audit skill
+ applies to other people's code apply here. Don't launder uncertainty,
+ hardcode a prior, or overstate maturity; use the maturity vocabulary
+ (`current` / `planned`), not aspirational claims.
+ 4. **New behaviour needs a failing test first.** Enforcement is proven by
+ tests, not asserted.
+
## Tracking (recursive-spine convention)
Work state lives in GitHub issues and milestones, not in prose files.
- What's in flight: `gh issue list --assignee @me`
- Deferred work: `gh issue list --label audit-deferral`
- Branches: `<prefix>/<issue>-<slug>`; PRs say `Closes #N`.
- Deferral requires a filed issue. Handover files its debts before closing.
Dialect and modules for this repo: [docs/tracking-dialect.md](docs/tracking-dialect.md)
Two local rules go beyond the convention's baseline, both from
[`ROADMAP.md`](ROADMAP.md):
- **Every open issue carries exactly one** of a release milestone
(= scheduled) or a `track:*` label (= deliberately unscheduled). Neither
is a tracking bug, not a backlog item.
- **Deferrals have an outbox.** At each release-scoping moment, every open
`audit-deferral` older than 30 days is either scheduled into the next
release or closed with a written waiver. No third option.
+
+ ## Moments map
+
+ When one of these happens, this is what handles it:
+
+ - postponing something → file an issue with `audit-deferral`; it must have a
+ revisit condition, not a wish
+ - an audit or dogfood pass produces a finding → file it with `gap`; work
+ issues cite the gaps they close
+ - closing a unit of work → `recursive-spine-handover` (files debts as
+ `inherited-debt`, asks the pollen question, posts the closing record)
+ - something here just proved itself → `recursive-spine-pollinate` captures it
+ to the hive (see the dialect note for hive routing)
+ - a durable decision gets made → add or amend an ADR in `docs/adr/`; a
+ superseded decision is *marked*, never deleted
+ - scoping a release → drain the deferral outbox (see above) before the
+ milestone is fixed
+ - a release diff touches `skills/`, `reference/portable-principles.md`,
+ `primitives/`, or `adapters/` → run [`docs/release-harness.md`](docs/release-harness.md)
+ before tagging
+ - "where does work stand?" → `recursive-spine-digest`
+
+ ## Review: run an independent layer
+
+ Run a **separate** reviewer over each unit of work before it lands — a
+ subagent with its own context, not the one that wrote the code. Not
+ because the author was careless: tests written by the author encode the
+ author's assumptions, and the defects that survive are precisely the ones
+ those assumptions hide.
+
+ The author's own harnesses are good at **behaviour** — differential runs,
+ fuzzing, mutation. What they structurally cannot see are **claims**: a
+ README teaching a path that crashes, "proven end-to-end" about two tests
+ that never touch the shipped path, a docstring describing a guarantee the
+ test does not provide. Those are defects *in the expectations*, so no
+ harness catches them; the only reader who can is one who does not already
+ believe them.
+
+ - Review **each unit as it completes**, not in a batch at the end.
+ Batching loses the correspondence between finding and reasoning, and by
+ then the next change is built on the defect.
+ - Give the reviewer an **explicit scope** — a commit range, not "the
+ current work".
+
+ Proven here across seven PRs (#213); three of four reviewed PRs that were
+ believed finished had defects that would have reached users.
+
+ ## Decisions needed
+
+ Every response ends with a `## Decisions needed` block: numbered, one line
+ each, **a recommendation per item**, and nothing requiring an answer
+ anywhere else in the message.
+
+ - It is a **running backlog** — anything still unanswered from earlier
+ turns is carried forward, not dropped.
+ - When no decision is genuinely needed, **say so** rather than omitting
+ the block; a silently absent block is ambiguous on exactly the turns
+ where it matters.
+ - Only decisions the human genuinely owns. Anything resolvable from the
+ code, the request, or a sensible default is the agent's to make —
+ otherwise the block becomes noise and gets skimmed like the prose it
+ replaced.
+
+ The point is separating **reporting** (read at whatever depth you choose)
+ from **blocking asks** (must not be missed). Prose is good at the first
+ and structurally bad at the second.