# Darkbloom docs — how this documentation is organised and maintained
> Last updated: 2026-09-03 · commit `5d400cf75`
Rules for anyone — human or agent — who reads, writes, or checks a file under
`docs/`. The code is the source of truth; a doc that disagrees with the code is
a bug in the doc. Read this page before editing docs; read
[`README.md`](README.md) to find a doc.
## 1. The system in one table
Every page has exactly one job, chosen from a closed set. The set is the
[Diátaxis](https://diataxis.fr/compass/) compass (does the page inform *action*
or *cognition*; does it serve *acquiring* a skill or *applying* one) plus two
record types that engineering repos need and Diátaxis does not name.
| Directory | Type | Reader's question | Form |
|---|---|---|---|
| `consumer/`, `provider/`, `developer/` | how-to (action · application) | "How do I do X?" | Prerequisites → numbered steps → verify → troubleshoot |
| `operations/` | runbook (action · application, prod-touching) | "How do I operate X safely?" | Scope → prerequisites → steps → verification → rollback |
| `reference/` | reference (cognition · application) | "What exactly is X?" | Tables and schemas; one lede sentence per section; every row cites code |
| `architecture/` | explanation (cognition · acquisition) | "How and why does X work?" | Context → mechanism → invariants → failure modes → code map |
| `design/` | design record | "What was decided about X, and is it built?" | Status line + frozen body |
| `reports/` | dated record (incident, measurement, review) | "What happened / what did we measure on date D?" | Frozen; never edited after landing |
| `releases/` | release notes | "What changed in version V?" | Frozen |
| `legal/` | policy text | — | As published |
| `assets/` | diagrams, CSVs, images referenced by docs | — | — |
Apply the compass at the sentence level too: a how-to that starts explaining
*why* has drifted; move the why to `architecture/` and link.
The audience directories hold how-tos first, but a reference or explanation
page that only that audience reads lives beside them rather than in
`reference/` or `architecture/`: `provider/cli-reference.md`,
`provider/hardware-requirements.md` and `consumer/models.md` are reference
pages; `consumer/privacy-expectations.md` is an explanation. Such a page names
its type in the lede and follows the skeleton of that type (§3), not the how-to
skeleton.
## 2. Principles (and where they come from)
1. **One mode per page.** Mixed pages fail every reader: the operator wants
steps, the reviewer wants invariants, the SDK user wants a table. Split
rather than blend. — Diátaxis; *Software Engineering at Google* ch. 10
("a document should have a singular purpose").
2. **Every page is page one.** Readers arrive by search, grep, or a link, not
by reading in order. Each page: states its context in the first three lines,
assumes a qualified reader, stays on one level of abstraction, has no
"previous/next" dependency, and links richly to neighbours. — Mark Baker,
*Every Page is Page One* (seven principles).
3. **Conclusion first.** The lede answers *what is this, who is it for, what
will I be able to do*. Details descend from there. Reference tables put the
most-used columns left. — Minto, *The Pyramid Principle*; BLUF.
4. **Strong information scent.** File names, headings, and link text must
predict the content precisely enough that a reader (or an agent running
`grep`) picks the right page on the first try. Index pages are traffic
cops: links plus one-line descriptions, no content of their own. — Pirolli &
Card, *Information Foraging*; SWE at Google ("landing pages").
5. **Chunk, label, and be consistent.** Groups of at most nine items; every
block labelled; the same thing called the same name everywhere (see
[`glossary.md`](glossary.md)). Tables beat prose for anything with more
than two attributes. — Horn, *Information Mapping*.
6. **Two levels of disclosure, no split attention.** `README.md` → page. A
fact a reader needs for one task lives in one place; do not make them
assemble it from three pages. — Nielsen, *Progressive Disclosure*; Sweller,
cognitive-load theory (split-attention effect).
7. **Compress: one canonical home per fact.** State a fact once, in the page
whose type owns it, and link from everywhere else. Restating drifts;
linking does not. The owner is the `reference/` page that covers the fact,
or, when none does, the `architecture/` page that owns the mechanism. A
how-to or runbook may repeat a value in a prerequisite or step the reader
must act on ("requires macOS 26") and then links the owner in the same
sentence; other pages name the identifier and link, never the value. The
privacy model lives in
[`architecture/security/encryption.md`](architecture/security/encryption.md)
and nowhere else. Delete superseded text instead of caveating it. Where code
says it better, cite the code instead of paraphrasing it.
8. **Docs are code.** Under version control, reviewed with the code they
describe, linted in CI (`make docs-check`), stamped with a freshness date and
the commit they were verified against, and deprecated on purpose — never
abandoned. The owner of a doc is whoever changes the code it describes. —
SWE at Google ch. 10 (freshness dates, canonical docs, deprecation).
9. **Write for agents as well as people.** Agents forage with `grep`/`glob`
and read a page in isolation. Use stable, grep-able identifiers (exact env
var names, message `type` strings, function names, file paths); keep closed
vocabularies closed; put every fact in text, never only in an image; keep
pages short enough to fit in one read. — Anthropic, *Effective context
engineering for AI agents* (progressive disclosure, "right altitude");
[llms.txt](https://llmstxt.org/) (small map, links to detail).
## 3. Page skeletons
All pages start with `# Title`, the freshness stamp, and a one-to-three
sentence lede (principle 3). Then, by type:
| Type | Sections, in order |
|---|---|
| how-to | Prerequisites · Steps (numbered; one user action per step; commands in fenced blocks; system side-effects described in prose under the step) · Verify · Troubleshooting (optional) · Related |
| runbook | When to use · Prerequisites (access, approvals — production mutations need explicit human approval) · Steps · Verification · Rollback · Related |
| reference | Tables. Columns cite code (`path`, `Symbol`). Closed enums list every value. Defaults are the code's defaults, quoted |
| explanation | Context (why it exists, what problem) · Mechanism (how; a Mermaid diagram when there is flow or state) · Invariants (numbered; each cites the code that enforces it) · Failure modes · Code map (concern → file/symbol) · Related |
| design | Status line: `Status: Proposed | In progress | Implemented (vX.Y.Z) | Superseded by | Abandoned` and date. Body frozen except the status line |
| report | Frozen. Stamp reflects the report's own date (`scripts/docs-stamp.sh --from-git`) |
## 4. Citing code
- Cite `path/to/file.ext` plus the symbol: `coordinator/registry/scheduler.go`
(`selectCandidate`). Both are grep-able and the path is verified by
`docs-check`.
- **No line numbers** outside `reports/` and `releases/`. Lines rot within
days; symbols survive refactors and are searchable.
- Quote constants and defaults exactly as the code spells them
(`challengeFreshnessMaxAge = 16 * time.Minute`), not rounded.
- Environment variables, message `type` strings, HTTP paths, and CLI flags are
always in backticks and spelled exactly.
- A claim you cannot tie to code is either a design intention (put it in
`design/` with a status) or an inference (mark it `[INFERENCE]`); it is not
architecture.
## 5. Freshness stamp
Line 3 of every doc:
```
> Last updated: YYYY-MM-DD · commit ``
```
- *Last updated* is the day the content was last written or re-verified
against the code, not the day the file was touched by a rename.
- *commit* is the repository commit the claims were checked against.
- Update it whenever you change a doc's content: `make docs-stamp
FILES="docs/path.md"` (today + HEAD). For frozen records use
`scripts/docs-stamp.sh --from-git `.
- A doc whose stamp is older than the code it cites is suspect; re-verify and
restamp rather than trusting it.
## 6. Checks (`make docs-check`, CI job "Docs Lint")
`scripts/docs-check.sh` fails on: a missing stamp; a relative link to a
missing file; an inline-code citation of a repo path that does not exist
(exempt: `reports/`, `releases/`, `design/`); and an orphan page that no other
doc links to. Run it before opening a PR that touches `docs/`. It checks only
git-tracked files by default; `--all` includes untracked drafts.
## 7. When you change code, change these docs
| Code change | Doc(s) that must move in the same PR |
|---|---|
| HTTP route, header, status code, JSON shape (`coordinator/api/`) | `reference/api-contracts.md`; the relevant `consumer/` how-to |
| WebSocket message or field (`coordinator/protocol/messages.go` ↔ `provider-swift/Sources/ProviderCore/Protocol/`) | `reference/protocol-messages.md` |
| Telemetry wire type or allowlist (Go / Swift / TS mirrors) | `reference/telemetry-schema.md`, `architecture/telemetry.md` |
| Coordinator env var or config default | `reference/configuration.md`; `operations/coordinator-deploy.md` if prod sets it |
| Provider CLI command, flag, env var | `provider/cli-reference.md`; `reference/configuration.md` |
| Routing / admission / scheduling constant or gate | `architecture/routing.md` or `architecture/scheduling.md` |
| Trust level, attestation, enrollment, encryption | `architecture/security/*.md`; `provider/attestation.md`; `consumer/verification.md`; `threat-model.yaml` |
| Pricing, ledger, payouts, referral | `architecture/billing.md`, `reference/pricing-model.md`, `consumer/billing.md` |
| Store schema / migration | `architecture/storage.md` |
| Provider version bump (`ProviderCore.version` ↔ `LatestProviderVersion`) | `operations/provider-release.md`; `CHANGELOG.md` |
| Build, test, CI, or script | `developer/build.md`, `developer/test.md`; `operations/` runbook that invokes it |
| New model family or engine capability | `architecture/inference.md`, `consumer/models.md`, `provider/hardware-requirements.md` |
| Anything user-visible | `CHANGELOG.md` |
## 8. Adding, moving, retiring pages
- New page: pick the directory by type (§1), add it to that directory's
`README.md` index with a one-line description, stamp it, run the check.
- Move: `git mv`, fix every inbound link (`grep -rn "old-name.md" docs
README.md CONTRIBUTING.md`), keep the stamp.
- Retire: delete it. Do not leave a stub. If the information moved, fix the
inbound links to the new home. Frozen records (`reports/`, `releases/`,
`design/` with a final status) are the only pages that outlive the code they
describe.
- Plans that ship become explanation: fold the as-built facts into
`architecture/`, set the design doc's status to `Implemented` (or
`Superseded by`), and stop editing it.
## 9. Pull requests
Every PR description includes a **before-and-after Mermaid diagram** covering
both the observable behaviour (request/response flow, states, outcomes) and
the code path (which functions/components changed and how control flows).
Scope it to the PR's delta. A PR without it is not ready for review. Docs-only
PRs diagram the navigation delta (which pages moved, split, or were removed).
```mermaid
flowchart LR
subgraph Before
A1[request] --> B1[old behaviour / code path]
end
subgraph After
A2[request] --> B2[new behaviour / code path]
end
```
## 10. Voice
Plain, declarative, present tense. Say what the code does, not what it "aims
to" do. No marketing phrases: "the coordinator never sees plaintext" is false
under the hop-by-hop model and must not appear; link to
[`architecture/security/encryption.md`](architecture/security/encryption.md)
instead. Prefer a table to a paragraph, a number to an adjective, and a
citation to a description.