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

132 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/`](../../product/index.md) | **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`](../../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](index.md).
Inside `docs/`, each section owns one question:
| Section | Owns |
| --- | --- |
| [`rules/`](index.md) | What must never be broken |
| [`integration/`](../integration/index.md) | The client↔server seam: contract, config, topology, OpenAPI |
| [`flows/`](../flows/index.md) | What is implemented and how to test it, one file per user journey |
| [`status/`](../status/index.md) | Where the project actually is: implemented, backlog, decisions |
| [`roadmap/`](../roadmap/index.md) | 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/`](../integration/index.md) + 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](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](../../CLAUDE.md) |
| Frontend | **"Project structure"** in [client/CLAUDE.md](../../client/CLAUDE.md), expanded in [client/structure.md](client/structure.md) |
| Backend | **"Project map"** in [server/CLAUDE.md](../../server/CLAUDE.md), expanded in [server/structure.md](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.