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.
Doc classes
Section titled “Doc classes”- 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. - Durable reference — architecture and contracts that change rarely:
ARCHITECTURE.md,docs/architecture/**,docs/reference/**,docs/specs/**,docs/design/**, activeplans/*specs. Must carry a dated status header. - Dated research —
docs/Research/**: captures with aCaptured:date and a “re-verify before relying on it” banner. Never “updated” — superseded by a new capture. - Frozen archive — everything under
archive/,plans/archive/anddecisions-logs/archive/(the pre-2026-09-27DECISIONS.mdhistory, split and byte-frozen —D:decisions-logs). Never edited, for any reason.DECISIONS.mdat the repo root is a short stub kept only so old links resolve;decisions-logs/INDEX.mdis generated from the archive, not hand-edited.
Update rules
Section titled “Update rules”- 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 todecisions-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/. Copyentries/_TEMPLATE.md, name it<YYYY-MM-DD>-<slug>.md, cite it asD:<slug>. No number is ever claimed (seedecisions-logs/README.mdandCLAUDE.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/orworkers/drizzle/gets its row indb/MIGRATIONS.mdin 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.
Archiving procedure
Section titled “Archiving procedure”- Create (or reuse) a dated set:
archive/YYYY-MM-DD-<reason>/. git mvfiles preserving their repo-relative paths under it.- Repoint inbound links in kept files (grep for the filename). Historical
citations inside
decisions-logs/archive/**andplans/archive/**are left as-is. - Add/extend the set’s
README.md: what moved, why, what replaced it. - Never edit anything already under
archive/.
The docs sites
Section titled “The docs sites”- docs.matriz.design —
apps/docs-product(Astro Starlight). User-facing product docs, authored by hand insrc/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 byscripts/sync-content.mjs(manifest inside the script). Never editsrc/content/docs/repo/**— edit the repo source file; add new pages by extending the manifest. - Both deploy from
mastervia.github/workflows/deploy-docs-*.ymlto Cloudflare Pages (projectsmatriz-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 withpnpm --dir apps/docs-<x> build.
Freshness audit
Section titled “Freshness audit”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.