docs: split the root README into owned documents under docs/ and guard it with drift tests #263

Closed
opened 2026-10-13 16:40:22 +02:00 by dominik.polakovics · 0 comments

Summary

Split the 3,182-line root README.md into owned documents under docs/, cut the README back to orientation, and add the guards (drift tests, a CLAUDE.md rule, a docs map) that stop it from inflating again. This issue is the pure move: content changes location, not wording. Correcting and condensing the moved prose is #264.

Current behavior

README.md is 3,182 lines / 185 KB. It began as a 114-line baseline in July, was rewritten to ~360 lines for v1 (ff7ea68), and has since been appended to by nearly every feature commit — 70 commits touch it, with single commits adding 200–490 lines (multilingual 4e74536, host navigation c90b868, feature lifecycle 0b5423a, bundle dependencies 78e181e, categories 629834b, editor modules 640d8df). Only two commits ever removed more than they added.

What it holds is not a README:

  • ## How it works (707 lines) is the HTTP API's wire-shape reference — every JSON key of every endpoint — mixed with design rationale ("Rich text, never raw HTML", "Publish is a background job", "Branch mode", "Media gate").
  • ### Host navigation (~480 lines) is a versioned contract with the hosting layer, including a JSON schema "The shape, version 1".
  • ## Scaffolding / ### Feature bundles (~800 lines) is the bundle author's manual: manifest, dependencies, receipt, harness add/remove, machine-readable output, the shipped bundles.
  • ## Configuration reference repeats sidecar territory that scaffold/site/AGENTS.md owns (element sidecar, body policy, page-type, backend layout, editor module, sidecar language files).
  • The README is also an incomplete API reference: of the 67 /api/... routes registered in internal/server/server.go and internal/server/mutation.go, 24 are never named (all of /api/media/*, /api/element/body, /api/element/duplicate, /api/element/refs, /api/page/create-root, /api/page/discard, /api/page/move, /api/page/refs, /api/page/reorder, /api/publish/status).

Why it happened (the instructions, not the agents): CLAUDE.md has three "MUST update the docs in the same change" rules, all naming scaffold/site/AGENTS.md, the theme README and the skills; the root README is never mentioned and nothing says what it is for or what belongs elsewhere. docs/ holds only mockups; there is no API reference, no CONTEXT.md, no docs/adr/ — the triage and grill-with-docs skills route decisions to ADRs that do not exist, so rationale lands in the README. Issue briefs then point at "the README API section" (e.g. #257) because it already is one. The review rule is asymmetric: a change that leaves docs untouched is incomplete, but nothing penalises a doc that is too long or in the wrong file. The update-docs skill has never run (no docs/.docs-sync, no docs: commit since July) and its "match surrounding depth, don't restructure" rule would preserve the inflation anyway.

Nothing outside the repo links into README anchors (checked the deckle-hosted import), and the only in-repo anchor links are the README's own, so sections can move freely.

Desired behavior

Every documented fact has exactly one owning document, and the README only points at them. Target layout:

File Audience / content Receives (from today's README)
README.md (≈300 lines) Orientation: what deckle is, quick start, releases/install, a one-line-per-command table that links to the CLI reference, development, repository layout, v1 limitations, a "Documentation" section linking every doc below Keep # deckle intro, ## Quick start, ### Releases, ## Development, ## v1 limitations, ## Repository layout
docs/api.md HTTP API reference: one ###-level heading per route (GET /api/page, POST /api/page/save, …) with request and response shape; a short preamble on coded error bodies and Accept-Language The wire-shape bullets of ## How it works (server-described forms, coded messages, sidecar labels on the wire, translations on the wire, publish job/status/pending), the #### What the editor accepts route material, ## Multilingual sites API parts, #### Machine-readable output where it describes HTTP rather than CLI
docs/harness.md CLI reference: every command and flag, exit codes, --json output shapes, the receipt format, harness.yaml ### The ten commands, ### Serving the preview behind a reverse proxy, ### harness lang, #### Machine-readable output (CLI parts), #### The receipt, ### harness.yaml
docs/host-navigation.md The versioned host contract, moved verbatim including "The shape, version 1", "Safety", "Versioning", "The editor's language" ### Host navigation and all its #### children
docs/features.md Bundle authoring and lifecycle: manifest, dependencies, installing, bundles from a directory, filling gaps, page-type allowances, removing, the shipped categories and news bundles, "Not covered yet" ## Scaffolding and ### Feature bundles with children
docs/architecture.md The "How it works" narrative with the wire shapes removed (they live in docs/api.md, linked): canonical content engine, sidecars as constraint language, module shell, media, git backbone, branch mode, publish, link check Prose of ## How it works, ## Multilingual sites (model, not API)
docs/adr/ Directory created with a README.md stating the format (one dated file per decision: context, decision, consequences). May be otherwise empty after this issue; #264 extracts the decisions —
docs/agents/docs-map.md The area → document map the update-docs skill already looks for: which file owns which kind of fact, and the rule that the README gains no sections new
docs/.docs-sync Sync marker in the format update-docs reads (line 1 full HEAD SHA, line 2 YYYY-MM-DD), written at the end of this change new

The ## Configuration reference sidecar sections (### Element sidecar, ### The categories field type, ### Body policy, ### Page-type sidecar, ### Content-root authority, ### Backend layout sidecar, ### Slots, layout resolution, and inheritance, ### Editor module sidecar, ### Sidecar language files) are AGENTS.md's territory. Diff each against scaffold/site/AGENTS.md: a fact AGENTS.md already states is dropped from the README in favour of a link; a fact AGENTS.md lacks is added to AGENTS.md (the CLAUDE.md "skills are procedures, AGENTS.md is the facts" rule) and then dropped. Do not create a third copy in docs/.

Guards

Mechanical guards follow the pattern of internal/element/agentsdoc_test.go and scaffold/skills_test.go:

  1. Route drift test. Every route string registered by the server (internal/server/server.go, internal/server/mutation.go — find the registration function rather than grepping string literals in tests) must appear as a heading in docs/api.md, and every /api/... heading in docs/api.md must be a registered route. Because 24 routes are undocumented today, this test fails until docs/api.md has a heading for each; in this issue each missing route gets a heading with a one-line stub ("Documented in #264") so the test is green and the gap is visible. Writing the real sections is #264.
  2. Command drift test. Every command the harness dispatcher (cmd/harness/main.go run() switch, and the lang subcommand switch) accepts must be named in docs/harness.md, and vice versa. version is a command today and the README's "ten commands" block omits it while listing eleven lines — the test should catch exactly this class of drift. Preferred: the command table in docs/harness.md is checked against the usage() text so the CLI has one owner; acceptable: a name-set comparison.
  3. README shape test. README.md stays under a line budget (300; pick the number and state it in the test's failure message), contains no /api/ path and no fenced json/yaml block other than harness.yaml's minimal example if kept. The failure message must say where the content belongs (the docs map), because the point of this test is to tell the next agent where to put things.
  4. Cross-link test. Every [text](docs/...md#anchor) and [text](#anchor) in README.md and in docs/*.md resolves to an existing file and heading. Extend or mirror TestSkillSectionReferencesExist in scaffold/skills_test.go rather than writing a second heading-slug implementation (CLAUDE.md "exactly one owner": if the slug rule is needed in two tests, move it to a package both import).

CLAUDE.md rule

Add a fourth section to CLAUDE.md, in the voice and structure of the existing three (## Every fact has one document or similar), containing:

  • The owner table above (file → audience → what belongs there), including scaffold/site/AGENTS.md, the theme README and the skills so it is the complete map.
  • "The README never gains a section. A change that adds a wire shape, a flag, a sidecar key or a rationale puts it in the owning document and at most adjusts one pointer line in the README."
  • "When planning or grilling a change: name the owning document for each new fact, exactly as the rules above ask for affected skills and rule owners. A brief that says 'document it in the README' is incomplete."
  • A pointer to the drift tests that enforce the mechanical half.

Skills and process alignment

  • .claude/skills/update-docs/SKILL.md: it already reads docs/agents/docs-map.md and docs/.docs-sync; both now exist. Add one standing rule: a sync may remove or condense prose that the owning document now carries, and a doc that has grown past its scope is drift to report, not surrounding depth to match.
  • .claude/skills/triage/SKILL.md / AGENT-BRIEF.md: the brief's docs line names the owning document from the docs map. One sentence; do not restructure the skill.
  • .claude/skills/grill-with-docs/SKILL.md and triage already route ADRs to docs/adr/; verify the path they name matches the directory this issue creates and fix the skill if not.
  • The scaffolded site skills (scaffold/site/.claude/skills/*) do not reference the root README (checked: only the theme README and AGENTS.md). Confirm with the drift test and leave them alone.

Decisions

  • Pure move, no rewording — so the PR reviews with git diff --color-moved and the reviewer can confirm nothing was lost or silently changed. Fixing wrong or stale prose, condensing, and extracting ADRs is #264. The only text written fresh in this issue is: the README's new "Documentation" section, each doc's one-paragraph preamble, the route stubs, the docs map, the CLAUDE.md section, the skill sentences.
  • docs/ plain Markdown, no docs-site generator — the repo has none and the audience is agents and the maintainer; files and headings are enough and are what the drift tests can check.
  • One file per audience, not per feature — the README inflated because features appended; a per-feature file layout would reproduce that in docs/. The owner is the kind of fact (wire, CLI, host contract, bundle authoring, design), so a new feature touches existing files.
  • Guards are tests, not prose — the repo already trusts agentsdoc_test.go and skills_test.go for this; a CLAUDE.md sentence alone did not keep the README small and will not.
  • README budget is a hard test — blunt on purpose. The failing message routes the agent to the owning file, which is the instruction that was missing.
  • Sidecar reference lives in AGENTS.md only — CLAUDE.md already makes AGENTS.md the facts for the site developer; a second reference in docs/ would be the exact "sibling rule" CLAUDE.md forbids.
  • Host navigation moves verbatim as a versioned spec — it is a contract with deckle-hosted; rewording it is a contract change and out of scope here.

Key interfaces

  • internal/server route registration — the drift test needs the registered set as data; if it is only available as mux.HandleFunc calls inside a constructor, expose the route list (a function returning the patterns) so the test and the server share one owner.
  • cmd/harness/main.go run() and usage(); cmd/harness/lang.go subcommand switch.
  • scaffold/skills_test.go heading-slug / section-reference helpers — reuse for the cross-link test.
  • internal/element/agentsdoc_test.go — the model for "every X the engine accepts is named in doc Y".
  • .claude/skills/update-docs/SKILL.md steps 1 and 3 (baseline file, docs map path).
  • CLAUDE.md — new section after "Every rule has exactly one owner".

Acceptance criteria

  • README.md is under the budget the shape test states, contains no /api/ path, and has a "Documentation" section linking docs/api.md, docs/harness.md, docs/host-navigation.md, docs/features.md, docs/architecture.md, docs/adr/, scaffold/site/AGENTS.md and scaffold/themes/deckle/README.md.
  • Every paragraph, list item, table and fenced block of today's README exists verbatim in exactly one of: the new README, a docs/*.md file, or scaffold/site/AGENTS.md — or is listed in the PR description as dropped because AGENTS.md already stated it (with the AGENTS.md section named).
  • docs/api.md has a heading for all 67 registered routes; the 24 previously undocumented ones carry a stub pointing at #264.
  • docs/harness.md names every dispatcher command including version.
  • The four drift tests exist, pass, and each fails with a message naming the owning document when its invariant is broken (demonstrate in the PR description by quoting one failure).
  • CLAUDE.md has the new section with the owner table and the planning/grilling sentence.
  • docs/agents/docs-map.md exists and docs/.docs-sync holds the merge-ready HEAD and today's date.
  • .claude/skills/update-docs/SKILL.md carries the condense/remove rule; the triage brief guide names the docs map.
  • go test ./... and scaffold/skills_test.go and internal/element/agentsdoc_test.go are green; harness check on a freshly scaffolded site is unchanged.

How to verify

  • git diff --color-moved=dimmed-zebra main..HEAD -- README.md docs/ shows moves, not rewrites.
  • wc -l README.md under budget; grep -c '/api/' README.md is 0.
  • go test ./... green; then break each invariant (add a fake route heading to docs/api.md, add a /api/x line to README, remove a command from docs/harness.md, break a link) and confirm the matching test fails with a message naming the owning document.
  • go test ./scaffold/ ./internal/element/ green.
  • harness init into a scratch dir, harness check green.

Assumptions to check

  • That the server's routes are registered in one place that a test can read; if they are spread across packages, find all of them before writing the drift test — the 67 count came from grepping server.go and mutation.go only.
  • That no external repo links into README.md anchors — checked against the deckle-hosted snapshot at spawn; re-check the live repo's default branch if reachable.
  • That scaffold/site/AGENTS.md's drift test does not depend on anything in the root README.
  • That the ## Configuration reference sidecar sections contain nothing AGENTS.md lacks; where they do, the fact moves into AGENTS.md (and its drift test may need the new vocabulary).

Out of scope

  • Rewording, condensing or correcting moved prose (#264).
  • Writing the 24 missing route sections (#264).
  • Extracting ADRs from the "why" paragraphs (#264); only the docs/adr/ directory and its format README are created here.
  • Changing the host-navigation contract or its version.
  • Touching the scaffolded site skills or the theme README beyond what the drift tests require.
  • A docs-site generator or publishing pipeline.

Blocked by

None - can start immediately

## Summary Split the 3,182-line root `README.md` into owned documents under `docs/`, cut the README back to orientation, and add the guards (drift tests, a CLAUDE.md rule, a docs map) that stop it from inflating again. This issue is the *pure move*: content changes location, not wording. Correcting and condensing the moved prose is #264. ## Current behavior `README.md` is 3,182 lines / 185 KB. It began as a 114-line baseline in July, was rewritten to ~360 lines for v1 (`ff7ea68`), and has since been appended to by nearly every feature commit — 70 commits touch it, with single commits adding 200–490 lines (multilingual `4e74536`, host navigation `c90b868`, feature lifecycle `0b5423a`, bundle dependencies `78e181e`, categories `629834b`, editor modules `640d8df`). Only two commits ever removed more than they added. What it holds is not a README: - `## How it works` (707 lines) is the HTTP API's wire-shape reference — every JSON key of every endpoint — mixed with design rationale ("Rich text, never raw HTML", "Publish is a background job", "Branch mode", "Media gate"). - `### Host navigation` (~480 lines) is a versioned contract with the hosting layer, including a JSON schema "The shape, version 1". - `## Scaffolding` / `### Feature bundles` (~800 lines) is the bundle author's manual: manifest, dependencies, receipt, `harness add`/`remove`, machine-readable output, the shipped bundles. - `## Configuration reference` repeats sidecar territory that `scaffold/site/AGENTS.md` owns (element sidecar, body policy, page-type, backend layout, editor module, sidecar language files). - The README is also an *incomplete* API reference: of the 67 `/api/...` routes registered in `internal/server/server.go` and `internal/server/mutation.go`, 24 are never named (all of `/api/media/*`, `/api/element/body`, `/api/element/duplicate`, `/api/element/refs`, `/api/page/create-root`, `/api/page/discard`, `/api/page/move`, `/api/page/refs`, `/api/page/reorder`, `/api/publish/status`). Why it happened (the instructions, not the agents): CLAUDE.md has three "MUST update the docs in the same change" rules, all naming `scaffold/site/AGENTS.md`, the theme README and the skills; the root README is never mentioned and nothing says what it is for or what belongs elsewhere. `docs/` holds only mockups; there is no API reference, no `CONTEXT.md`, no `docs/adr/` — the `triage` and `grill-with-docs` skills route decisions to ADRs that do not exist, so rationale lands in the README. Issue briefs then point at "the README API section" (e.g. #257) because it already is one. The review rule is asymmetric: a change that leaves docs untouched is incomplete, but nothing penalises a doc that is too long or in the wrong file. The `update-docs` skill has never run (no `docs/.docs-sync`, no `docs:` commit since July) and its "match surrounding depth, don't restructure" rule would preserve the inflation anyway. Nothing outside the repo links into README anchors (checked the `deckle-hosted` import), and the only in-repo anchor links are the README's own, so sections can move freely. ## Desired behavior Every documented fact has exactly one owning document, and the README only points at them. Target layout: | File | Audience / content | Receives (from today's README) | |---|---|---| | `README.md` (≈300 lines) | Orientation: what deckle is, quick start, releases/install, a one-line-per-command table that links to the CLI reference, development, repository layout, v1 limitations, a "Documentation" section linking every doc below | Keep `# deckle` intro, `## Quick start`, `### Releases`, `## Development`, `## v1 limitations`, `## Repository layout` | | `docs/api.md` | HTTP API reference: one `###`-level heading per route (`GET /api/page`, `POST /api/page/save`, …) with request and response shape; a short preamble on coded error bodies and `Accept-Language` | The wire-shape bullets of `## How it works` (server-described forms, coded messages, sidecar labels on the wire, translations on the wire, publish job/status/pending), the `#### What the editor accepts` route material, `## Multilingual sites` API parts, `#### Machine-readable output` where it describes HTTP rather than CLI | | `docs/harness.md` | CLI reference: every command and flag, exit codes, `--json` output shapes, the receipt format, `harness.yaml` | `### The ten commands`, `### Serving the preview behind a reverse proxy`, `### harness lang`, `#### Machine-readable output` (CLI parts), `#### The receipt`, `### harness.yaml` | | `docs/host-navigation.md` | The versioned host contract, moved verbatim including "The shape, version 1", "Safety", "Versioning", "The editor's language" | `### Host navigation` and all its `####` children | | `docs/features.md` | Bundle authoring and lifecycle: manifest, dependencies, installing, bundles from a directory, filling gaps, page-type allowances, removing, the shipped `categories` and `news` bundles, "Not covered yet" | `## Scaffolding` and `### Feature bundles` with children | | `docs/architecture.md` | The "How it works" narrative with the wire shapes *removed* (they live in `docs/api.md`, linked): canonical content engine, sidecars as constraint language, module shell, media, git backbone, branch mode, publish, link check | Prose of `## How it works`, `## Multilingual sites` (model, not API) | | `docs/adr/` | Directory created with a `README.md` stating the format (one dated file per decision: context, decision, consequences). May be otherwise empty after this issue; #264 extracts the decisions | — | | `docs/agents/docs-map.md` | The area → document map the `update-docs` skill already looks for: which file owns which kind of fact, and the rule that the README gains no sections | new | | `docs/.docs-sync` | Sync marker in the format `update-docs` reads (line 1 full HEAD SHA, line 2 `YYYY-MM-DD`), written at the end of this change | new | The `## Configuration reference` sidecar sections (`### Element sidecar`, `### The categories field type`, `### Body policy`, `### Page-type sidecar`, `### Content-root authority`, `### Backend layout sidecar`, `### Slots, layout resolution, and inheritance`, `### Editor module sidecar`, `### Sidecar language files`) are AGENTS.md's territory. Diff each against `scaffold/site/AGENTS.md`: a fact AGENTS.md already states is dropped from the README in favour of a link; a fact AGENTS.md lacks is *added to AGENTS.md* (the CLAUDE.md "skills are procedures, AGENTS.md is the facts" rule) and then dropped. Do not create a third copy in `docs/`. ### Guards Mechanical guards follow the pattern of `internal/element/agentsdoc_test.go` and `scaffold/skills_test.go`: 1. **Route drift test.** Every route string registered by the server (`internal/server/server.go`, `internal/server/mutation.go` — find the registration function rather than grepping string literals in tests) must appear as a heading in `docs/api.md`, and every `/api/...` heading in `docs/api.md` must be a registered route. Because 24 routes are undocumented today, this test fails until `docs/api.md` has a heading for each; in *this* issue each missing route gets a heading with a one-line stub ("Documented in #264") so the test is green and the gap is visible. Writing the real sections is #264. 2. **Command drift test.** Every command the `harness` dispatcher (`cmd/harness/main.go` `run()` switch, and the `lang` subcommand switch) accepts must be named in `docs/harness.md`, and vice versa. `version` is a command today and the README's "ten commands" block omits it while listing eleven lines — the test should catch exactly this class of drift. Preferred: the command table in `docs/harness.md` is checked against the `usage()` text so the CLI has one owner; acceptable: a name-set comparison. 3. **README shape test.** `README.md` stays under a line budget (300; pick the number and state it in the test's failure message), contains no `/api/` path and no fenced `json`/`yaml` block other than `harness.yaml`'s minimal example if kept. The failure message must say where the content belongs (the docs map), because the point of this test is to tell the next agent where to put things. 4. **Cross-link test.** Every `[text](docs/...md#anchor)` and `[text](#anchor)` in `README.md` and in `docs/*.md` resolves to an existing file and heading. Extend or mirror `TestSkillSectionReferencesExist` in `scaffold/skills_test.go` rather than writing a second heading-slug implementation (CLAUDE.md "exactly one owner": if the slug rule is needed in two tests, move it to a package both import). ### CLAUDE.md rule Add a fourth section to `CLAUDE.md`, in the voice and structure of the existing three (`## Every fact has one document` or similar), containing: - The owner table above (file → audience → what belongs there), including `scaffold/site/AGENTS.md`, the theme README and the skills so it is the complete map. - "The README never gains a section. A change that adds a wire shape, a flag, a sidecar key or a rationale puts it in the owning document and at most adjusts one pointer line in the README." - "**When planning or grilling a change**: name the owning document for each new fact, exactly as the rules above ask for affected skills and rule owners. A brief that says 'document it in the README' is incomplete." - A pointer to the drift tests that enforce the mechanical half. ### Skills and process alignment - `.claude/skills/update-docs/SKILL.md`: it already reads `docs/agents/docs-map.md` and `docs/.docs-sync`; both now exist. Add one standing rule: a sync may *remove or condense* prose that the owning document now carries, and a doc that has grown past its scope is drift to report, not surrounding depth to match. - `.claude/skills/triage/SKILL.md` / `AGENT-BRIEF.md`: the brief's docs line names the owning document from the docs map. One sentence; do not restructure the skill. - `.claude/skills/grill-with-docs/SKILL.md` and `triage` already route ADRs to `docs/adr/`; verify the path they name matches the directory this issue creates and fix the skill if not. - The scaffolded site skills (`scaffold/site/.claude/skills/*`) do not reference the root README (checked: only the theme README and AGENTS.md). Confirm with the drift test and leave them alone. ## Decisions - **Pure move, no rewording** — so the PR reviews with `git diff --color-moved` and the reviewer can confirm nothing was lost or silently changed. Fixing wrong or stale prose, condensing, and extracting ADRs is #264. The only text written fresh in this issue is: the README's new "Documentation" section, each doc's one-paragraph preamble, the route stubs, the docs map, the CLAUDE.md section, the skill sentences. - **`docs/` plain Markdown, no docs-site generator** — the repo has none and the audience is agents and the maintainer; files and headings are enough and are what the drift tests can check. - **One file per audience, not per feature** — the README inflated because features appended; a per-feature file layout would reproduce that in `docs/`. The owner is the *kind* of fact (wire, CLI, host contract, bundle authoring, design), so a new feature touches existing files. - **Guards are tests, not prose** — the repo already trusts `agentsdoc_test.go` and `skills_test.go` for this; a CLAUDE.md sentence alone did not keep the README small and will not. - **README budget is a hard test** — blunt on purpose. The failing message routes the agent to the owning file, which is the instruction that was missing. - **Sidecar reference lives in AGENTS.md only** — CLAUDE.md already makes AGENTS.md the facts for the site developer; a second reference in `docs/` would be the exact "sibling rule" CLAUDE.md forbids. - **Host navigation moves verbatim as a versioned spec** — it is a contract with `deckle-hosted`; rewording it is a contract change and out of scope here. ## Key interfaces - `internal/server` route registration — the drift test needs the registered set as data; if it is only available as `mux.HandleFunc` calls inside a constructor, expose the route list (a function returning the patterns) so the test and the server share one owner. - `cmd/harness/main.go` `run()` and `usage()`; `cmd/harness/lang.go` subcommand switch. - `scaffold/skills_test.go` heading-slug / section-reference helpers — reuse for the cross-link test. - `internal/element/agentsdoc_test.go` — the model for "every X the engine accepts is named in doc Y". - `.claude/skills/update-docs/SKILL.md` steps 1 and 3 (baseline file, docs map path). - `CLAUDE.md` — new section after "Every rule has exactly one owner". ## Acceptance criteria - [ ] `README.md` is under the budget the shape test states, contains no `/api/` path, and has a "Documentation" section linking `docs/api.md`, `docs/harness.md`, `docs/host-navigation.md`, `docs/features.md`, `docs/architecture.md`, `docs/adr/`, `scaffold/site/AGENTS.md` and `scaffold/themes/deckle/README.md`. - [ ] Every paragraph, list item, table and fenced block of today's README exists verbatim in exactly one of: the new README, a `docs/*.md` file, or `scaffold/site/AGENTS.md` — or is listed in the PR description as dropped because AGENTS.md already stated it (with the AGENTS.md section named). - [ ] `docs/api.md` has a heading for all 67 registered routes; the 24 previously undocumented ones carry a stub pointing at #264. - [ ] `docs/harness.md` names every dispatcher command including `version`. - [ ] The four drift tests exist, pass, and each fails with a message naming the owning document when its invariant is broken (demonstrate in the PR description by quoting one failure). - [ ] `CLAUDE.md` has the new section with the owner table and the planning/grilling sentence. - [ ] `docs/agents/docs-map.md` exists and `docs/.docs-sync` holds the merge-ready HEAD and today's date. - [ ] `.claude/skills/update-docs/SKILL.md` carries the condense/remove rule; the triage brief guide names the docs map. - [ ] `go test ./...` and `scaffold/skills_test.go` and `internal/element/agentsdoc_test.go` are green; `harness check` on a freshly scaffolded site is unchanged. ## How to verify - `git diff --color-moved=dimmed-zebra main..HEAD -- README.md docs/` shows moves, not rewrites. - `wc -l README.md` under budget; `grep -c '/api/' README.md` is 0. - `go test ./...` green; then break each invariant (add a fake route heading to `docs/api.md`, add a `/api/x` line to README, remove a command from `docs/harness.md`, break a link) and confirm the matching test fails with a message naming the owning document. - `go test ./scaffold/ ./internal/element/` green. - `harness init` into a scratch dir, `harness check` green. ## Assumptions to check - That the server's routes are registered in one place that a test can read; if they are spread across packages, find all of them before writing the drift test — the 67 count came from grepping `server.go` and `mutation.go` only. - That no external repo links into `README.md` anchors — checked against the `deckle-hosted` snapshot at spawn; re-check the live repo's default branch if reachable. - That `scaffold/site/AGENTS.md`'s drift test does not depend on anything in the root README. - That the `## Configuration reference` sidecar sections contain nothing AGENTS.md lacks; where they do, the fact moves into AGENTS.md (and its drift test may need the new vocabulary). ## Out of scope - Rewording, condensing or correcting moved prose (#264). - Writing the 24 missing route sections (#264). - Extracting ADRs from the "why" paragraphs (#264); only the `docs/adr/` directory and its format README are created here. - Changing the host-navigation contract or its version. - Touching the scaffolded site skills or the theme README beyond what the drift tests require. - A docs-site generator or publishing pipeline. ## Blocked by None - can start immediately
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle#263
No description provided.