Skip to content

Documentation policy

Last updated: 2026-08-22 (created in the doc reset, D:doc-reset). This file is normative: it defines which docs are maintained, how they get updated, and how docs die. The failure mode it exists to prevent is the one the reset fixed — a STATUS.md whose top banner stayed fresh while the body froze six weeks behind the code.

  1. Living trackers — describe NOW; updating them is part of shipping. STATUS.md, decisions-logs/entries/** (one new decision = one new file, never an edit to an existing one), plans/OWNER-OPS.md, plans/BONDLAYER-FOLLOWUPS-WORKSTREAM.md, plans/LOOSE-ENDS-EXECUTION-SPECS.md, db/MIGRATIONS.md, CLAUDE.md, this file.
  2. Durable reference — architecture and contracts that change rarely: ARCHITECTURE.md, docs/architecture/**, docs/reference/**, docs/specs/**, docs/design/**, active plans/* specs. Must carry a dated status header.
  3. Dated research — docs/Research/**: captures with a Captured: date and a “re-verify before relying on it” banner. Never “updated” — superseded by a new capture.
  4. Frozen archive — everything under archive/, plans/archive/ and decisions-logs/archive/ (the pre-2026-09-27 DECISIONS.md history, split and byte-frozen — D:decisions-logs). Never edited, for any reason. DECISIONS.md at the repo root is a short stub kept only so old links resolve; decisions-logs/INDEX.md is generated from the archive, not hand-edited.
  • STATUS.md describes the present. Edit the section that changed, bump the single Last updated: date at the top. No banner stacking — do not prepend dated announcements; history belongs to decisions-logs/ and git. If a section no longer matches the code, fixing it is in scope for whatever PR broke it.
  • decisions-logs/entries/ is append-only, but each decision is its own file — never edit another entry’s file, and never touch decisions-logs/archive/. Copy entries/_TEMPLATE.md, name it <YYYY-MM-DD>-<slug>.md, cite it as D:<slug>. No number is ever claimed (see decisions-logs/README.md and CLAUDE.md).
  • Plans open with a status header (Status: active|proposal|spec — YYYY-MM-DD). When the work ships, either annotate as-built (and say so in the header) or move the plan to the current archive set. A plan that self-declares “EXECUTED/CLOSED” should be archived in the same PR that closes it, not left to rot.
  • Migrations: every new file in db/migrations/ or workers/drizzle/ gets its row in db/MIGRATIONS.md in the same PR — the prod-apply ledger only works if it’s complete.
  • Docs describing future work must say so explicitly (proposal/spec/deferred). When the future arrives, the doc gets repaired or archived — a doc claiming something is “not yet executed” after it shipped is a bug.
  1. Create (or reuse) a dated set: archive/YYYY-MM-DD-<reason>/.
  2. git mv files preserving their repo-relative paths under it.
  3. Repoint inbound links in kept files (grep for the filename). Historical citations inside decisions-logs/archive/** and plans/archive/** are left as-is.
  4. Add/extend the set’s README.md: what moved, why, what replaced it.
  5. Never edit anything already under archive/.
  • docs.matriz.design — apps/docs-product (Astro Starlight). User-facing product docs, authored by hand in src/content/docs/. Written for customers: no internal codenames, no repo paths. Update when user-visible behavior changes.
  • dev.matriz.design — apps/docs-dev (Astro Starlight). Engineering docs generated from repo markdown at build time by scripts/sync-content.mjs (manifest inside the script). Never edit src/content/docs/repo/** — edit the repo source file; add new pages by extending the manifest.
  • Both deploy from master via .github/workflows/deploy-docs-*.yml to Cloudflare Pages (projects matriz-docs / matriz-docs-dev). The docs apps are deliberately outside the pnpm workspace (own lockfiles) so Astro stays out of the main install; build them with pnpm --dir apps/docs-<x> build.

Before each launch milestone (and roughly monthly), run a docs audit: every class-2 doc’s status header is checked against code; anything failing moves through the archiving procedure.

⚠️ archive/2026-08-22-doc-reset/ does not exist in this repo’s history on any branch (confirmed 2026-09-13 — git log --all --diff-filter=A returns nothing for that path), despite being cited as “the template” here and from 30+ other files (STATUS.md, CLAUDE.md, several plans/*.md, docs/Research/**). The 2026-08-22 reset rewrote docs in place rather than preserving the pre-reset versions under archive/, so that citation is a dead link everywhere it appears — the actual template for the archiving procedure this file already describes above is archive/2026-06-24-doc-snapshot/ (which does exist) or archive/2026-09-13-doc-rework/ (created in this pass). Don’t recreate 2026-08-22-doc-reset/ retroactively — the content it would contain is gone; just stop citing it as if it exists, and use one of the two real sets above as the example when this procedure is next explained.