Files
gramps b5e3dbe614 Seed an AI-legible project memory map that stays small
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.
2026-10-30 06:51:19 -07:00

8.0 KiB
Raw Permalink Blame History

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:

  1. This file is the only mandatory read at session start. Everything else is read on demand.
  2. 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 one docs/ai/<topic>.md that matches the task → <dir>/index.md for the code you will touch.
  • TASKS.md is 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.md is 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 to environment.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 to HANDOFF.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:

  1. Doc budgets: wc -l every capped file, fail with "move the detail out, do not pad".
  2. Clean build: clean first, then build; any warning fails. (Incremental "0 warnings" lies.)
  3. Tests: full suite; a whitelist of known-flaky names, everything else is a regression.
  4. 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

  1. 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.
  2. 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.
  3. Write ai.md router, HANDOFF.md, TASKS.md (empty queue), docs/ai/index.md, docs/ai/environment.md, decisions.md skeleton, MyMistakes.md with an empty Recipes section, schema.md, and <dir>/index.md for each directory.
  4. Write the two scripts and prove the gate fires (create an over-cap file, watch it fail).
  5. 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.