Writing the documentation¶
This page is the standard every page in this site is written to. It exists because an audit found the old pages explained the library in its own vocabulary ("family 229", "supercritical", "channels B and C") before telling the reader what problem they were solving. Follow it when you add or change a page, and point reviewers here.
Start from the reader¶
Before writing, answer three questions at the top of your draft (then delete them):
- Who is reading? Pick from the readers below. Most pages serve one or two.
- What do they already know when they arrive? Assume only what the pages before this one in the nav have taught.
- What can they do when they leave? A concrete ability: "wire the
decide call into a FastAPI handler", "explain to a fraud lead why a
card was held", "choose
p_thresholdfrom last quarter's data".
| Reader | Arrives knowing | Wants |
|---|---|---|
| Evaluator | Python, their own product | "What is this? Is it for me?" |
| Integrator | Their service, HTTP, databases | "How do I wire it in and run it?" |
| Domain owner | Fraud, clinical, ops, moderation | "What will it decide, and why?" |
| Data scientist | Models, scores, graphs, statistics | "How do my data and scores map in?" |
| Theory reader | Probability, graphs, algorithms | "Which result, stated how, with what limits?" |
| Contributor | This repository | "How is it built and how do I change it?" |
Kinds of page¶
Every page is one of four kinds. Don't mix them; link between them.
| Kind | Section | Reader is… | Shape |
|---|---|---|---|
| Tutorial | Get started | learning by doing | numbered steps, each with a command and its real output |
| How-to | How-to guides | doing a specific task | goal → prerequisites → steps → result → what can go wrong |
| Explanation | Concepts, Theory | trying to understand | question → intuition → example → precise statement → limits |
| Reference | Reference | looking something up | complete, consistent tables and definitions; little prose |
Openings¶
The first three sentences of every page say, in plain words, what problem this page is about and why the reader should care. No term the reader hasn't met yet, no family number, no formula.
Bad: "Family 229 is the kernel's refusal to emit a seed label when the broadcast is too weak."
Good: "Sometimes the cases related to this one tell you a lot about it; sometimes they're too few or too mixed to tell you anything. This page explains how the library tells those apart, and why it holds a decision when the related cases are too weak to support it."
Then say what the page covers and what it assumes.
Concrete before abstract¶
Order every explanation as:
- The situation, in a domain the reader recognises (a card, a patient, a pager alert).
- The intuition, in plain words or a picture.
- A worked example with real numbers, copied from running the code
(
uv run grounded-decision examples <id>), not computed by hand. - The precise statement (formula, rule, type signature).
- What it does not do: limits, failure modes, honest caveats.
- What to do about it in practice: the setting to change, the page to read next.
A formula never appears before the reader knows what question it answers.
Words¶
- Define every term on first use on each page, or link it to the glossary. Readers arrive from search; don't assume they read the previous page.
- Use the reader's words first, then ours: "how strongly linked cases agree (we call this neighbour agreement, λ)".
- One name per thing. Use the canonical terms below. Never "channel B", "the cursor" and "state" for different things on the same page.
- No aphorisms in place of explanations. "Silence is not coverage" is a conclusion; show the reader the empty calibration set and what happens.
- No history. "The old regex tokenizer skipped characters" belongs in the changelog, not on a reader page.
- Plain sentences. Full sentences, active voice, one idea each. Cut rhetorical repetition and intensifiers.
Canonical terms¶
| Say | Not | Meaning |
|---|---|---|
| policy | grammar, run-book (alone) | The short text or chart listing which events lead to which proposed actions. |
| event | letter | Something that happened, named the way the policy names it (suspicious). |
| state | cursor, vertex | Where an entity currently is in its policy. Saved after each decision, restored before the next. |
| proposed action | proposal, marking (alone) | What the policy would do next if nothing else were checked. Always recorded. |
| check | channel (alone), channel A/B/C | One of six independent yes/no tests. Any "no" means the decision is held. "Channel" is the field name in records. |
| act / abstain / degrade | fire / hold (as verdicts) | The three verdicts. "Hold" is fine in prose for abstain-and-route-to-a-person. |
| evidence | snapshot (alone) | The numbers describing the related cases around this decision (EvidenceSnapshot). |
| related cases / corroboration graph | broadcast tree, seed graph | Your related cases as dots, with lines between cases that share something. |
| neighbour agreement (λ) | lambda_hat (in prose), channel correlation | How much more often linked cases share a label than chance. 0 = no better than chance. |
| evidence strength (dλ²) | KS score, supercriticality | Average links per case × agreement². Above about 1, the related cases genuinely inform. |
| decision line / knife-edge window | flicker band, p*, p_* | The range of link density near your cut-off where a little noise flips the answer. |
| unusualness score, calibration set | nonconformity bag | How unusual this case is compared with recent cases where the answer was right. |
| trust level: proven / published / practical | lean / paper / operational (alone) | How much of a mathematical result a check relies on. Field values stay lean, paper, operational. |
| math catalog, result number | family (alone), pin | The companion collection of math results; each has a number. Give the plain name first: "Kesten–Stigum reconstruction (catalog result 229)". |
Numbers and examples¶
- Every number on a page comes from running the code, and the page
says which command produces it. If the code changes, the golden-output
tests in
tests/snapshots/change too; update the page in the same commit. - Prefer one worked example carried through the page over several half-examples.
- Show units and meaning next to every number: "dλ² = 1.51 (above the 1.05 line, so the related cases are informative)".
Honesty¶
- Describe what the code does, not what we wish it did. If a check is weaker than its name suggests, say so on the page where readers rely on it.
- Separate "proven" (with the exact statement used), "published but not machine-checked", and "practical stand-in".
- Every page that recommends acting on a verdict says what the verdict does not establish.
Math¶
- Inline math is
\( ... \), display math is\[ ... \](MathJax). Don't escape underscores or asterisks inside formulas;tests/test_docs_math.pyfails if a formatter has. - Code identifiers inside a formula:
\texttt{label\_score}. - Never let Prettier or another Markdown formatter rewrite these files
(
.prettierignoreexcludes them). - Every symbol is defined in words on the page where it appears.
Mechanics¶
- New pages go in
mkdocs.ymlnavand are linked from at least one existing page.make docs(strict) fails on broken links. - Commands in fenced shell blocks must be real
maketargets or real example ids;tests/test_docs_commands.pychecks. - Diagrams use Mermaid fences (
```mermaid). - Admonitions (
!!! note,!!! warning) for caveats a reader must not miss; don't use them for decoration. - Run
make docs-serveand read your page in the browser before you finish.