# Documentation Structure — Authority Map

This file is the authority on **what belongs where** in `docs/`: the folder map, naming, lifecycle, the doctrine every genre follows, and the decision table for adding a doc. Read it before adding or moving any documentation. Start reading from [`README.md`](README.md).

**This file is the harness's, not the project's.** The installer writes it on every install and refresh, so nothing in it describes one repository: a folder a repo does not use is simply absent on disk, and a repo's own notes — legacy folders kept as provenance, retired genres, local exceptions — live in [`README.md`](README.md) § Notes for this repository, never here. Hand edits are overwritten on the next refresh. The one field written in place is `harness-version` in the frontmatter, stamped by the `maintenance` agent after its baseline reconcile; its absence is what tells a session the repo has not been baselined against the installed harness.

One canonical source per topic — link, don't copy. Only `CLAUDE.md`, `AGENTS.md`, and `README.md` live at the repo root. Every per-genre fact this file does not need for placement — a genre's nature, its `type:` value, its required keys and sections — is the `documentation` skill's genre registry (`templates/Readme.md`), and `doc-lint` checks documents against it.

---

## Folder map

```
docs/
├── README.md              # Documentation root — the product in a paragraph, what each folder holds, and the repo's
│                          #   own notes. Describes directories, never files or a tree — `ls` is the roster
├── structure.md           # This file — harness-owned authority map; `harness-version` stamped after baseline
├── architecture/          # The design layer, in five folders; Readme.md is its summary and names folders only
│   ├── packages/          # One `{package}.md` per project package: what it is, how it behaves. Speaks
│   │                      #   RESIDUALLY for `packages/<pkg>/**` — every file no narrower document speaks for
│   ├── systems/           # One `{machine}.md` per machine spanning packages. Speaks for its subtrees,
│   │                      #   more specific than a package's claim
│   ├── doctrine/          # The enterprise plane — one `{concern}.md` per concern the platform handles
│   │                      #   the same way everywhere, in general form. Owns no code
│   ├── playbooks/         # One `{subject}.md` per interface or workflow shape every product builds (the shell,
│   │                      #   a settings area, a record's lifecycle), in general form. Owns no code
│   └── decisions/         # ADs — `AD-NNN-{slug}.md`, one per subject, updated in place; the journey lives in
│                          #   each file's Decision Changelog tail. Each AD's `description:` and `status:` say
│                          #   what it decides and whether it stands; Readme.md describes the folder, never a row per AD
├── features/              # Feature docs — `{feature}.md`, one per thing a person points at (an address, a command
│                          #   family, a named control), cut by its objects (flat, no subfolders). One of three owning genres, beside
│                          #   `architecture/packages/` and `architecture/systems/`; ownership is computed from `objects:` and source headers
├── acceptance/            # Acceptance criteria — `{capability}.md`, stable `AC-n` assert lines. Owns no code
├── operations/            # Procedures — `setup.md` (the one-time first run, incl. the stack), then development, deployment, signing, rotation, diagnostics;
│   │                      #   one topic-named `{procedure}.md` each. Also holds bookkeeping.md, the shared
│   │                      #   doc-sync work queue (hook-appended, bookkeeper-drained, a drained row deleted)
│   ├── release-notes/     # One operator-facing note per release (`YYYY-MM-DD-vX.Y.Z.md`); listing the folder is the index
│   ├── issues/            # Local-tracker issue records (`type: issue`, `YYYY-MM-DD-{slug}.md`) — the
│   │                      #   `triage` skill's local pack; `status:` is the lifecycle
│   └── triage/            # Triage dossiers (`type: triage`, `YYYY-MM-DD-{slug}.md`) — one per investigated
│                          #   issue, written by the `triage` skill; owns no code, never a feature doc
├── modeling/              # Formal models — one `{system}/` per modelled machine: `BRIEF.md`, `MODEL.md`, `DISCOVERY.md`,
│                          #   the Quint spec and its tests, `bindings/{layer}.md`, the case harvest, `evidence.json`,
│                          #   `conformance.json`, and `lean/` once a promise is proved. Owns no code; a plan
│                          #   touching a path a binding names owes a Model Obligations ledger
├── tests/                 # Behavioral test checklists (truth docs) — `{feature}.md`, step → **Assert**, named for
│                          #   the doc whose promises it proves. `ls docs/tests/` is the roster
├── research/              # Records — in-progress brainstorm sessions (`{topic}-brainstorm/`), standing-research
│                          #   folders (`{topic}/`) and loose standing-research notes (`{topic}.md`). The folder name is the topic
├── history/
│   ├── CHANGELOG.md       # The changelog guide: how entries are named, owed and read. Never appended to
│   ├── changelog/         # Individual changelog entries, `YYYY-MM-DD-{three-words}.md` (frozen at commit)
│   ├── plans/             # Dated implementation plans, `YYYY-MM-DD-{slug}.md` (Status: field; Complete/Abandoned = frozen)
│   ├── migrations/        # One-shot migration runbooks, `YYYY-MM-DD-{slug}.md` — authored ahead, outcome-stamped, frozen
│   ├── brainstorms/       # Harvested brainstorm sessions (`{topic}/`), kept as provenance; the folder name is the topic
│   ├── research/          # Deep-research records (`{topic}/` — README.md synthesis + findings.md + sources.md).
│   │                      #   Frozen, cited, owns no code. Distinct from research/ at the docs root
│   ├── health-log.md      # The maintenance agent's append-only pass record, one generated row per pass
│   ├── journal.md         # Queue — mid-execution facts, one line each; a line resolves by landing in its owning
│   │                      #   doc (delete the row, cite it in the changelog entry)
│   └── backlog.md         # Queue — open work by priority (P0–P3); a finished item is deleted
└── memory/                # Queues — project knowledge + per-agent strategy memory, compacted by their writers
    ├── main.md            # Main-agent project memory
    └── {agent}.md         # One strategy-memory file per sub-agent that keeps one
```

## Doctrine every genre follows

- **Every document has one of three natures.** A **truth** document states what is true now and is rewritten in place, present tense, with no history in its body. A **record** states what happened, is dated, and is frozen at its terminal status. A **queue** holds work not done yet: rows are appended and deleted when resolved, and nothing else is edited — the backlog, the journal, the bookkeeping queue and `memory/`. Which genre has which nature is the genre registry's; the folders below follow it, with `history/` holding records and two queues.
- **No index keeps a row per file.** A folder's `Readme.md` describes what the folder holds and how its files are named; each file's `description:` is its own account, and listing the folder is the roster. Nothing appends to an index when a sibling file is added — not the changelog guide, not a decisions, research, brainstorms or release-notes folder.
- **`docs/architecture/`** is the design layer in five folders: **`packages/`** (one per project package — what it is and how it behaves), **`systems/`** (one per machine spanning packages), **`doctrine/`** (the enterprise plane), **`playbooks/`** (the shapes every product builds) and **`decisions/`** (the ADs, one per subject, updated in place, each journey confined to that file's Decision Changelog tail).
  **`doctrine/`, `playbooks/` and `decisions/` own no code; `packages/` and `systems/` do.** Ownership is computed, not positional and not typed: a document names the objects it designs in `objects:`, each source file's path header names the document that speaks for it, and the object closure links the two; the more specific claim wins — a feature's beats a system's, a system's beats a package's. Until the ownership scan switches to those edges it reads a transitional `owns:` region glob on each of the three owning genres (the `documentation` skill's `references/frontmatter.md`). **A package document is the residual owner of its tree**, so a package's exhaustive behavior spec is that document, not a feature doc.
  **What earns which genre.** A project package earns a `packages/` document — one, always. A machine whose parts sit in several packages, which a reader asks about as one thing, earns a `systems/` document. A **feature** document exists for something a person points at — an address, a command family, a named control — and is cut by the objects it designs, never by the code's routers, tables, plans or packages; a machine nobody navigates to is a `systems/` document even when it owns tables, and a fragment whose central object is declared in a sibling merges into it. A concern handled the same way everywhere is `doctrine/` and owns nothing; a shape every product's interface or workflow repeats is `playbooks/` and owns nothing. Both are written in general form, and a new one is created only with the user's approval (the `documentation` skill § Doctrine and playbooks) — including the governing-decisions register (fixed product decisions `F-###`, baseline defaults `B-###`, external boundaries, out-of-scope), which is authored doctrine the `boundary` skill never persists to.
- **`history/research/` is not legacy — it is the installed deep-research genre**, one `{topic}/` folder per research pass in the three-file shape. A record is frozen and cited, owns no code, and is never edited to stay current; a new question gets a new topic folder. Entries that predate the three-file convention — a single file or a single-report folder — are kept as authored.
- **`docs/features/` is flat — every feature authority is a file, and no subfolder exists.** A subject too large for one file is two files, not a folder: `objects:` and the source headers already state authority, and a nested doc is one the ownership scan and the index rows reach last.
- **`docs/research/`** holds records, not authorities: its standing-research folders and loose notes ground plans and decisions. The `brainstorm` skill finds a session by its folder name.
- **`docs/tests/`** holds behavioral test checklists — one `{feature}.md` per surface, written as `- [ ] step` → `- [ ] **Assert**` (how to verify a feature's promised behavior). A checklist is written or updated **at the verification gate, before the driving** — it is the script the real surface is driven against and the menu the pinned suite tests are drawn from, so each behavior section closes with a `> Pinned:` line naming the test that guards it, `driven only` with the reason, or `none yet` with the test it owes. **No section carries a date** — the *event* of driving (its date, environment, evidence, a `FAIL` and the backlog item it raised) belongs to the changelog entry of the unit that drove it. A section a drive cannot reach says `not reachable — {what blocks it}` on its trace line until the blocker is gone. **The gate that drives a checklist maintains it** — retiring dead sections and repairing traces is part of the run, because a checklist owns no code and no ownership glob implicates it. The cross-system testing strategy is doctrine in `architecture/doctrine/`. A checklist carries `type: checklist` plus `verifies:`, the doc(s) whose promises it proves; a target is legitimately a feature, a package or a system document, and several values are correct where one checklist proves promises two docs decide.
  **`verifies:` is the load-bearing key, and the filename convention is not a substitute for it.** A same-named file is a coincidence no resolver can trust — it breaks the moment a checklist spans two docs or a feature is renamed. The inverse — which checklists cover a feature — is **generated, never listed in the feature doc**.
- **`docs/operations/bookkeeping.md`** is the shared doc-sync work queue — hooks append rows, the `bookkeeper` agent drains them, and the commit wall blocks while rows remain. It is **author-created, never scaffolded**, and its rows are **live work, never drift**: a drained row is deleted, so a fully drained file holds no rows at all. Read a waiver's referent before deleting it; deleting the record while the condition survives re-appends the finding as an `auto:` row that fails the wall the waiver passed.
- **`type:` is a required frontmatter key** on every doc that carries frontmatter — the genre stamp, its values the genre registry's `type:` column (`feature`, `architecture-decision`, `project-memory`, `ux`, `acceptance-criteria`, …). It is tooling metadata like `last-reviewed:` and `status:`: external tooling reads it, sessions **preserve it on edits** and never narrate it in the body. The `maintenance` agent stamps it on docs that lack it. The owning genres (`type: feature`, `type: package`, `type: system`) carry the transitional `owns:` region glob the ownership scan reads until it switches to source headers; `type: doctrine` carries `objects:` and owns no code; the bookkeeping queue carries no block. Docs written by a skill that ships a block (`triage`'s `type: issue` / `type: triage`) carry it.
- **The docs tree is a graph, and nothing in it that can be computed is typed.** A document names the objects it designs (`objects:`); a source file names the document that speaks for it in its path header; the object closure computes the rest — which files a document speaks for, and which surfaces a doctrine governs. One doc → doc edge is authored, because nothing computes it: **`verifies:`** (checklist → the doc whose promises it proves). Its inverse is **generated** — `buildEdgeIndex()` in `.claude/hooks/lib/ownership.mjs`, injected at SessionStart beside the ownership index — and authoring an inverse by hand is a defect. `applies:` is retired; `owns:` is a transitional region glob (the `documentation` skill's `references/frontmatter.md`).
- **`docs/acceptance/` holds the acceptance-criteria genre** — one `kebab-case.md` per capability, written at specification time, before implementation, holding stable `AC-n` assert lines that verification surfaces parse as claims to grade the built product against; each file is keyed to the checklist sections that grade it. The folder is created on first use and never scaffolded. The `AC-n:` line grammar is load-bearing: the key sits at line start, exactly `AC-<number>:`, followed by the assert sentence — tables, emphasis-wrapped keys, and nested bullets break the parse.
- **The `ux` genre decides observable behavior; `docs/tests/` only verifies it.** A feature doc states what a feature is and which contracts it honours — all of which stay plausibly true through a rewrite of the surface — so a UX-behavior doc states what a person *observes*, and is written **before** the code. A surface needing the genre gets `features/{surface}-ux.md`, named in the headers of the component files no other document speaks for; where a feature document already speaks for them, the UX document is named in its For the agent **See also** line.
- **`docs/history/journal.md` drains into documents, and `docs/memory/` does not.** Both are queues. The journal holds mid-execution facts one line each, each resolved by landing in its owning doc; memory holds only per-agent strategy and project knowledge no single doc owns, compacted by its writer. A fact an owning doc will eventually carry goes to the journal, never to memory — nothing drains memory into a document, so what lands there stays until its writer retires it.
- **There is no `docs/history/sessions/`.** Per-session gate logs are machine-local, written by `.claude/hooks/lib/session-log.mjs` into `.claude/state/sessions/` (self-ignored), so they never enter `docs/` or git. A `docs/history/sessions/` folder is residue, not shape.
- **The repo-root `README.md` opens outward and turns inward.** What the product does, for whom and where it runs, in a user's terms; then, for the team and agents, how it works, a Map of top-level units with their owning doc, the rules that bite, where to go by intent, and at most four everyday commands. It carries no install, stack or tree — install and stack are `operations/setup.md`, the tree is this file's. Template: the `documentation` skill's `templates/root-readme.md`.
- **`docs/README.md` describes directories, never files.** One entry per folder: what it holds, who reads it, how its files are named — no per-file rows, no tree. It closes with the repository's own notes, the one place project-specific placement facts live.
- **`operations/setup.md` is the one first-run document**, fixed name, one per repo: stack by layer naming the pinning file, prerequisites, install, env files, first run, verification, failures by exact error text. Every other procedure is topic-named and recurring.

---

## Lifecycle

- **Plans** (`history/plans/YYYY-MM-DD-{slug}.md`) carry a `Status:` field (`Draft` / `In Progress` / `Complete` / `Abandoned`). Once `Complete`/`Abandoned`, a plan is frozen — never edited; scope changes get a new dated plan that links back.
- **Migration runbooks** (`history/migrations/YYYY-MM-DD-{slug}.md`) are authored ahead of execution and record a one-shot infra/cutover procedure; once executed, the outcome is stamped into the file and it is frozen — a re-run gets a new dated runbook.
- **Changelog** entries land in `history/changelog/`, one per unit of work, each opening on its one-line summary. `history/CHANGELOG.md` is the folder's guide and takes no row per entry; listing the folder is the index.
- **Backlog** items live in `history/backlog.md` under P0–P3 priorities — a queue: appended, and deleted when the work lands.
- **Brainstorm sessions** are author-created by the `brainstorm` skill: an active session at `docs/research/{topic}-brainstorm/` (older folders carry the legacy `-brainstorming/` suffix; both are canonical), moved to `docs/history/brainstorms/{topic}/` on a passed harvest — the move is the completion marker, and the moved folder's fate (delete or commit) is the author's call. Never scaffolded empty; no index keeps a row per session.
- **Source-of-truth audits** write nothing to `docs/`. The `polygraph` agent runs only when the user asks, on a named target (a doc, a feature, a folder, a code path or a plan), and keeps its rows under `.claude/state/polygraph/{run}/`, machine-local, never tracked, deleted in the same turn as the report. What survives a run is the corrected document itself and the backlog rows it registered; a run against a plan also leaves a `Polygraph:` segment on its `Gates:` line, which nothing reads.
- **Boundaries** are a plan-time diagnostic — the `boundary` skill reads contracts fresh from source; there is no persisted `boundaries/` tree.
- **Modules** are _declared labels_ (a `module:` key on a feature doc), never inferred from physical layout and never a folder. A feature always lives flat in `features/`.

---

## Add-a-doc decision table

The `type:` column is the value the document carries; its required keys and sections are the genre registry's row for that type.

| You are adding… | It goes in… | `type:` |
| --- | --- | --- |
| A feature document — something a person points at (an address, a command family, a named control), cut by the objects it designs | `features/{feature}.md` (flat) | `type: feature` |
| What a person sees and can do on a surface (UX behavior) | `features/{surface}-ux.md`, named in the headers of the component files no other document speaks for; a shape every product repeats is a playbook | `type: ux` |
| A package's behavior document | `architecture/packages/{package}.md`, one per package | `type: package` |
| A system's behavior document | `architecture/systems/{system}.md`, one per machine | `type: system` |
| Cross-cutting design (doctrine) — with the user's approval, after extending an existing one is ruled out | `architecture/doctrine/{concern}.md` | `type: doctrine` |
| An interface or workflow shape every product builds (playbook) — with the user's approval, after extending an existing one is ruled out | `architecture/playbooks/{subject}.md` | `type: playbook` |
| The testing strategy | `architecture/doctrine/testing.md` | `type: testing-strategy` |
| An Architecture Decision (AD) | `architecture/decisions/AD-NNN-{subject}.md` — one file per subject, updated in place; the journey lives in its Decision Changelog | `type: architecture-decision` |
| The system at a glance | `architecture/system-design.md` | `type: system-overview` |
| The domain model | `architecture/domain-model.md` | `type: domain-model` |
| The glossary | `architecture/glossary.md` | `type: glossary` |
| The non-goals | `architecture/non-goals.md` | `type: non-goals` |
| The security overview | `architecture/security.md` | `type: security-overview` |
| The API surface | `architecture/api.md` | `type: api-reference` |
| The environment variables | `operations/environment.md` | `type: environment-registry` |
| One-time machine setup, first run, stack, prerequisites, env files | `operations/setup.md` — fixed name, one per repo, linked from the root README; a diverging package gets a `### {unit}` subsection, never a second first-run doc | `type: operations` |
| A recurring procedure (develop, deploy, rotate, diagnose, CI) | `operations/{procedure}.md` | `type: operations` |
| The build order of a project built from its design | `operations/implementation-map.md` | `type: implementation-map` |
| The protected-files list | `operations/protected-files.md` | `type: protected-files` |
| A tracker issue held in the repo | `operations/issues/YYYY-MM-DD-{slug}.md` (via the `triage` skill's local pack) | `type: issue` |
| A triage dossier for an investigated issue | `operations/triage/YYYY-MM-DD-{slug}.md` (via the `triage` skill) — a dated working artifact that never claims `owns:` | `type: triage` |
| A formal model of one machine | `modeling/{system}/` (via the `modeling` skill) — `MODEL.md` is the source, the spec and `bindings/` are derived; `explorer.html` is never committed | none |
| A behavioral test checklist | `tests/{feature}.md` — written at the verification gate before the driving, each section carrying a `Pinned:` trace; owns no code | `type: checklist` |
| Acceptance criteria for one capability | `acceptance/{capability}.md` — stable `AC-n` assert lines; keys are never renumbered or reused, a retired criterion is marked retired in place | `type: acceptance-criteria` |
| A folder's landing page | `{folder}/Readme.md` — describes the folder, never a row per file | `type: folder-index` |
| An in-progress brainstorm session | `research/{topic}-brainstorm/` (via the `brainstorm` skill) | none |
| A source-of-truth audit | Nowhere in `docs/` — the `polygraph` agent corrects the target doc in place | none |
| An implementation plan | `history/plans/YYYY-MM-DD-{slug}.md` (a `Status:` line is required) | none |
| A one-shot migration runbook | `history/migrations/YYYY-MM-DD-{slug}.md` (authored ahead; outcome-stamped and frozen once executed) | none |
| A hand-over at the end of an unattended or multi-session build | `history/handovers/YYYY-MM-DD-{slug}.md` | `type: handover` |
| A deep-research record | `history/research/{topic}/` — `README.md` synthesis + `findings.md` + `sources.md`; frozen and cited, a new question gets a new topic folder | none |
| A harvested brainstorm session | `history/brainstorms/{topic}/` (via the `brainstorm` skill's harvest) | none |
| A changelog entry | `history/changelog/YYYY-MM-DD-{three-words}.md`; `CHANGELOG.md` takes no row | none |
| A tracked work item | a row in `history/backlog.md` | none |
| A doc-sync debt row | a row in `operations/bookkeeping.md` (hook-appended; drained by the `bookkeeper` agent, deleted on drain) | none |
| A mid-execution fact worth keeping | a row in `history/journal.md` (resolves by landing in its owning doc) | none |
| Agent strategy / project memory | `memory/main.md`, `memory/{agent}.md` | `type: project-memory` on `main.md` |

---

## Harness version

`harness-version` in this file's frontmatter is the **single** baseline/version sentinel for a repo — the semver of the installed harness (`.claude/harness.json`) the `docs/` tree was last reconciled to. The installer ships this file without the field; the `maintenance` agent (baseline mode) stamps it after reconciling the tree, and a session whose installed version is ahead of the stamp — or that finds no stamp — dispatches that agent before anything else. There is no second marker.

---

## Health Log

The `maintenance` agent appends its pass record to [`history/health-log.md`](history/health-log.md) — an append-only record, kept out of this file, which it never otherwise edits.
