Files
baya-monorepo/docs/rules/documentation.md
T
2026-07-30 02:26:52 +03:30

6.6 KiB
Raw Blame History

The documentation convention

How this repository keeps its own docs from lying. Read before writing or editing any .md.

Last verified: 2026-07-30 against commit d3ec723.


1. One home per fact

Three trees, and a fact belongs to exactly one of them.

Tree Answers Example
product/ What the business is escrow holds funds until check-out is confirmed
docs/ What we built, and how we work the escrow ledger is implemented; here is how to test it
archive/ How we got here the phase-10 prompt that built the ledger, and its report

If you are about to write a business rule into docs/, it belongs in product/. If you are about to obey something in archive/, stop — it is a record, not an instruction.

Two documents stay outside docs/ on purpose:

  • DEPLOY.md — the deploy procedure, at the repo root where an operator will look.
  • The three CLAUDE.md files — the hard-rule tier. See rules/index.md.

Inside docs/, each section owns one question:

Section Owns
rules/ What must never be broken
integration/ The client↔server seam: contract, config, topology, OpenAPI
flows/ What is implemented and how to test it, one file per user journey
status/ Where the project actually is: implemented, backlog, decisions
roadmap/ Where it goes next, and what gates a launch

product/ is a structured docs tree with a generated HTML view: the .md files are canonical, the matching .html files are built by cd product && node build-docs.mjs. Edit the Markdown and regenerate — never hand-edit the HTML. If you add or rename a .md, update the NAV manifest in product/build-docs.mjs in the same change.


2. What to update when X changes

This is the anti-drift contract. Each row is enforced by review, and (from phase 7) warned about by the pre-commit hook.

When you change… Update, in the same change
An endpoint's route, shape, or status codes docs/integration/ + the OpenAPI snapshot
A project, layer, route group, provider, or major folder The matching architecture section — see §3
A user-facing flow, so it now works end to end docs/flows/<flow>.md — what it does, and how to test it
A backlog item, so it is now done Tick it in docs/status/backlog.md. Never delete a row — a ticked row is the record that it shipped
A decision that isn't derivable from the code docs/status/decisions.md — the decision, the date, and why
A business rule you discovered or decided The relevant product/**.md, then regenerate the HTML. Record decisions; do not invent rules
A rule, so it now says something different The one file that owns it (see rules/index.md) — not a second copy elsewhere
A new reusable pattern, seam, base class, or hook family A short note in the reference file for that area, so the next change reuses it instead of reinventing it
A mock or deferred external service docs/status/ — the seam (interface + file), what is faked, why, the config keys it reads, and step-by-step how to make it real

A mock is only sanctioned behind a DI-registered interface. Mock and real implement the same interface; selection is by configuration, never by an if (mock) scattered through the code. An unrecorded mock is a defect.


3. Architecture sections are canonical, and there are exactly three

Level Canonical section
Repo "Repository layout" in root CLAUDE.md
Frontend "Project structure" in client/CLAUDE.md, expanded in client/structure.md
Backend "Project map" in server/CLAUDE.md, expanded in server/structure.md

A map is only canonical if it stays accurate. Stale instructions are worse than none — an agent that trusts a wrong map spends its budget in the wrong place and lands a change in the wrong layer.

An architecture section describes patterns and boundaries, not a file listing. If it wants to grow a line per file, that is the signal it has stopped being a map: describe the shape of a route group, not each page inside it. git ls-files already lists files, for free, and never goes stale.


4. Last verified

Every doc that makes a claim about the current state of the code carries, directly under its title:

> Last verified: <YYYY-MM-DD> against commit <short-sha>.

A doc without one is a claim, not a fact.

Must carry it May omit it
Everything in docs/rules/, docs/status/, docs/flows/, docs/integration/ Index/README files that only link onward
Any doc quoting a line count, a file count, a config key, or a default value product/ (business truth, not code state — it carries its own decision dates)

Two companion rules:

  • Verify, don't copy. A load-bearing claim is checked against the code or against a run before it is written down. Re-stamping the date without re-checking is the failure mode this is designed to catch.
  • If it cannot be checked, mark it. Prefix the sentence with UNVERIFIED: and say what would settle it. An honest gap is useful; a confident guess is not.

5. Length budgets

So this doesn't regrow into the thing it replaced.

Tier Budget If it overflows
A CLAUDE.md 250 lines Something in it is reference, not a hard rule. Move it.
A hard-rule list 1525 numbered items The weakest items aren't hard rules. Cut them.
A docs/rules/** reference file 400 lines Split by sub-topic, or you are listing where you should be describing.
A docs/flows/<flow>.md 200 lines It is covering two journeys.

The rule behind the numbers: loading a rule must not cost 40k tokens. That is what the old 1,098-line client/CLAUDE.md did to every frontend change, and it is why nobody read past the top.


6. Style

  • English throughout, including in files that describe Persian UI copy. Quote the Persian, explain in English.
  • Prose over bullet soup for reasoning; tables for anything with more than three parallel cases.
  • Link, don't restate. Two copies of a rule drift; one copy and a link cannot.
  • Write the why down when it isn't obvious from the rule. A rule whose reason is recorded survives contact with a case it didn't anticipate; a bare prohibition gets worked around.