One file (AGENTS.md) that bootstraps the rest: rules, the file map to create, what belongs in each file, the first-session interview order, and the list of anti-patterns that killed the previous map (1,308-line guide, 63 task files, narrative history inline, sessions skimming 56k tokens of context). Separates four kinds of content by read frequency: rules/invariants -> AGENTS.md (every session) subsystem truth -> docs/ai/<topic>.md (only the matching one) lookups -> environment.md (grepped, never read) retired decisions -> decisions.md (only when re-opening one) Caps are enforced, not promised: scripts/verify.sh checks doc budgets before the build, so a commit that pads a capped file fails. Proven both ways — it passes clean and exits 1 on an over-cap file. scripts/scope-check.sh blocks edits outside the declared file list. templates/ holds fill-in skeletons for the seven files a project must create. CC0: copy it, rename it, sell it, no attribution needed.
8.0 KiB
AGENTS — bootstrap
You are starting this project's memory from nothing. This file is self-contained: it gives you the rules, the file map you must create, what belongs in each file, and the order to do it in.
Two standing orders:
- This file is the only mandatory read at session start. Everything else is read on demand.
- Finish work; do not manage it. A session that produces task lists, re-prioritisation or documentation of work instead of working has failed, even if the docs are good.
1. Rules — non-negotiable
Delivery
- One unit = one behaviour = one test = one commit. If a request needs several tests, pick the one the user cares about and finish it before the next.
- No feature branches pre-1.0. Work lands on
main, committed per unit. - Commit every unit without asking. Push only at checkpoints the user names.
- Declare the exact file list before editing. No "while I'm here" edits, no drive-by refactors.
Anything spotted outside the list becomes a one-line follow-up in
HANDOFF.md. - One pre-commit gate for code: clean build at 0 warnings, full tests, scope check, doc budgets
(
scripts/verify.sh "<files>"). Docs-only units run the scope check alone.
Reading
- Session start, in this order, and stop:
HANDOFF.md→ai.md→ the onedocs/ai/<topic>.mdthat matches the task →<dir>/index.mdfor the code you will touch. TASKS.mdis read when the question is "what's next" — never as a prerequisite to code.- Never read the whole map "for context". If the map is a required read, the map is wrong.
Memory
- The map is corrected by the change that falsifies it — in the same commit. It is not a unit of its own; no "docs backfill" commits unless asked.
- Three kinds of truth, three homes: rules/invariants → this file; subsystem detail →
docs/ai/<topic>.md; lookups (paths, ports, hosts, credential locations) → one cheat sheet. History and abandoned decisions → a decisions log, never inline in the docs. HANDOFF.mdis current state only, overwritten not appended, hard-capped.- A fact recorded once ends the re-derivation loop: paths, traps and recipes go in the map the first time they cost a hunt. Grep the recipes file before re-deriving anything.
Behaviour
- Do the work, then report what changed and what's next. No plans, pros/cons tables or "pitfalls" sections unless asked.
- Nothing here is novel: scan externally before building anything new, cite the reference in the commit. A second failed fix for the same symptom is a research trigger, not a persistence trigger — stop and find the established answer.
- Follow the codebase's existing conventions; don't add comments the code doesn't need; don't invent work items.
2. Files you must create
| File | Role | Cap | Written by |
|---|---|---|---|
AGENTS.md |
This file: rules + the project's invariants | 210 lines | you, rarely |
ai.md |
Router: what the product is, build commands, architecture table, where truth lives | 100 lines | you, rarely |
HANDOFF.md |
Current state: branch, in flight, next action, landmines | 40 lines | every session, overwritten |
TASKS.md |
The active queue, one line per live item | 120 lines | on status change |
TASKS/archive.md |
Everything done, as a dated snapshot | unbounded | at trim time |
docs/ai/<topic>.md |
Subsystem truth — one file per subsystem | unbounded | as that subsystem changes |
docs/ai/index.md |
Routing table: file ↔ what it covers ↔ when to read it | — | as files are added |
docs/ai/decisions.md |
Retired paths + cause of death, and the permanent out-of-scope list | — | when a decision dies |
docs/ai/environment.md |
Lookups: hosts, ports, paths, build/run/test commands, suite map | — | when a fact costs a hunt |
MyMistakes.md |
Failure log + recipes registry (grep-first) | — | when something is learned the hard way |
schema.md |
The conventions above, restated for this repo | — | once |
<dir>/index.md |
One per code directory: file list + one-line purpose + links out | — | when layout changes |
If a file is over cap: move detail out, never pad — the gate fails padding.
3. What goes in each file
HANDOFF.md (≤40)
# HANDOFF — <date> (<one-line state>)
## State branch, worktree, unpushed commits
## Next action the single next unit, and why it is next
## Landmines live traps only — paths, flaky tests, do-not-touch rules
## Pending what is blocked on the user (checks, decisions, takes)
ai.md (≤100) — # <Product> — AI guide & router, then:
## What it is— five lines max.## Build, run, test— the actual commands, plus the pointer toenvironment.md.## Architecture— one table row per top-level directory: path → role.## Where the truth lives— table: subsystem → doc → "read when".## Current state→ a one-line pointer toHANDOFF.md. Nothing else.
docs/ai/<topic>.md — open with one line of "read when". Then observed reality only:
how it works, the traps that cost time, the measurements that settled an argument, and the
guard test that protects each rule. Date contested facts. Never re-tell the product pitch.
TASKS.md — ## Next up (the one unit, 5 lines) · ## Queue (one table row per item:
id, status ☐🔶⏳⏸❌, one-line scope, detail link) · ## Pending the user · ## Release gates.
decisions.md — one dated line per decision that no longer governs, with the reason it died,
plus the permanent out-of-scope list. Read only when about to re-open one.
MyMistakes.md — ## Recipes first (how-to, verbatim commands, traps). Then dated failure
entries: symptom → wrong guess → actual cause → the rule that prevents it.
4. Create the gate
scripts/scope-check.sh — fails if any changed file is outside the declared list.
scripts/verify.sh "<files>" — in this order:
- Doc budgets:
wc -levery capped file, fail with "move the detail out, do not pad". - Clean build: clean first, then build; any warning fails. (Incremental "0 warnings" lies.)
- Tests: full suite; a whitelist of known-flaky names, everything else is a regression.
- Scope check with the passed file list.
A budget that is not a failing gate gets eaten by the next append. This is the load-bearing part.
5. First session — do this, in order
- Ask the user for: what the product is in one paragraph, the architecture's top-level directories, the build/run/test commands, the deployment target, and anything that must never be violated (legal, data-loss, output-corrupting). One question at a time.
- Write
AGENTS.md§1 rules as-is, then add the invariants: 10–20 lines, each stating a rule and pointing at the doc that explains it. An invariant earns its line only if violating it breaks output, destroys user data, or creates a legal/trust breach. - Write
ai.mdrouter,HANDOFF.md,TASKS.md(empty queue),docs/ai/index.md,docs/ai/environment.md,decisions.mdskeleton,MyMistakes.mdwith an empty Recipes section,schema.md, and<dir>/index.mdfor each directory. - Write the two scripts and prove the gate fires (create an over-cap file, watch it fail).
- Commit once: "docs: project memory map + gate". Then stop mapping and start working.
6. Anti-patterns that killed the last map
- Appending instead of replacing — the file only grows, and stale facts outlive the code.
- One task file per task, with paragraph-length status prose — a second, worse source of truth.
- Cross-references like "TASK 3 item 17" — numbers rot; cite a path or a feature name.
- Narrative history kept inline "for context" — it is 30% of the file and read by nobody.
- Splitting into more files without a router — discovery cost just moved.
- Docs commits as units of work — the cheapest thing to produce, so it replaces real progress.
- Reading the whole map every session — a tax that trains sessions to skim.