# Writing a set of documents

Load when writing or reworking more than one sibling document at once (a doctrine folder, a family of feature documents), or one doctrine document whose rules meet its siblings'. A single feature or package document needs only the steps in `SKILL.md`. One document joining an existing set runs every step below, with the existing documents as the rest of the set (§ One document into an existing set).

A set written one document at a time restates itself. Each document is made self-contained, so the same rule lands in four documents in four wordings, two of them contradict, and the defects surface only on rereading, which costs more than the writing did. So the set is designed once, as data, before any prose: every rule gets one home, every concept one name, and the review reads a table, where a fix is one edit, instead of twenty documents, where a fix is a reread of every one that states the rule.

## 1. Usefulness test

For each proposed document, list the decisions only it would own: rules a reader would get wrong without it, each checked against the documents that exist, by a search for its distinctive phrase. A decision another document already states belongs to that document.

- **Fewer than about six owned decisions:** the document is a section of a neighbour, or its rules belong in several neighbours. Fold them and drop the document.
- **Two documents owning overlapping lists:** the boundary between them is not drawn. Redraw it or merge them.
- **The output:** the document list, each with its owned decisions and its boundary sentence (the questions next to it, and which document answers each).

## 2. Term table

One row per concept: its name, a one-line definition, the one document that governs it (which lists it in `objects:`), and the synonyms it bans. The table comes before the ledger, because a rule written with two names for one concept becomes two rules.

The table starts from what the existing documents already name: every sibling's `objects:` and the definitions in its Terms table (an owning document's "For the agent" objects line). A new term is checked against them before it is used, because the collision a writer cannot see is with a name a sibling already gave another concept ("consent" for a client's scope, beside a sibling's consent of a data subject).

| Term | Means | Governed by | Not |
| --- | --- | --- | --- |
| operator | a person on the platform's own staff | authorization service | admin, staff account |

## 3. Rule ledger

One row per rule, from the user's rulings, the documents that exist, and the code where it states a design:

| Id | Rule | Reason | Source | Home | As | Stated in | Cited by |
| --- | --- | --- | --- | --- | --- | --- | --- |
| R12 | A change that narrows access ends the sessions it affects | a narrowed role must not outlive its token | owner ruling 6 | auth service | principle 5 | auth service | authorization service, security |

- **A source for every row:** an owner's ruling, a sibling's statement, or the code where it states a design. A rule with no source (a case the rulings leave open, a consequence the writer finds plausible) is not a row: it is a question for the user, with a recommendation, and the documents say nothing on the case until it is answered. Rules a writer supplies itself are where a written set's own defects concentrate, because no one has decided them.

- **Stated in, searched, not remembered:** each row's distinctive phrase is searched across the existing documents, and every document already stating the rule is listed. The ledger's defects are mostly here: a rule the writer homes in a new document while a sibling still states it is a double home on the first read.
- **One home per rule:** the document whose question the rule answers. A rule that seems to need two homes is resolved here, by picking one and adding the other to "Cited by". A rule a sibling already states keeps that home unless the same change edits the sibling to cite the new one; a home moves only with both edits.
- **Contradictions resolved here:** two rows that cannot both hold are settled before any prose exists. Where one source plainly outranks the other (the owner's latest ruling over an older sibling sentence), the ledger follows it and the losing statement is a sibling edit owed; the rest go to the user in one batch with the open cases, a recommendation first for each.
- **As:** a principle where the rule holds across the document's parts, a part's decision where it holds for one part only.
- **Scratch, never committed:** the documents are the record, and a committed ledger would be a second copy to drift from them.

## 4. Ledger review

One reviewer reads the ledger and the term table, not prose: the `doc-reviewer` agent in ledger mode, with § Rubric. Without the agent, a context-free sub-agent briefed with § Rubric and the paths, never the writer itself: a writer reviewing its own ledger passes its own blind spots, and in this skill's eval a self-reviewed ledger reached the cold read carrying seven blocking findings. Fixes land in the ledger, so every document rendered after them inherits them.

## 5. Render

Each document is written from its ledger rows and nothing else:

- **Principles and part decisions:** each rule one sentence, and its reason the next wherever the rule meets a trigger of the style guide's § Sentences.
- **Part sections:** the rows homed as part decisions. A part with no such row gets no section.
- **Reason check:** each rendered doctrine document then runs `templates/doctrine.md` § Reason check before the lint; the cold read sees only reasons a judge kept.
- **Rules homed elsewhere:** a citation with the one clause of context the sentence needs (style guide principle 7), never the rule in new words.
- **A sentence with no row:** filler, which is cut. A rule the writer finds missing is a question for the user (§ 3), never a row the writer adds for itself.

Writers may run in parallel, one sub-agent per document or per few documents. Each brief carries the ledger, the term table, the template, the style guide's § Labels, § Voice (with § Sentences and § Vocabulary) and § Net-net, the rows homed in its documents, and the instruction to write only its own files. Each writer returns paths, not prose.

## 6. Lint

`doc-lint` over the folder. Block findings are fixed. Each `sibling-duplicate` warning is a restatement the ledger did not ask for, or a row the ledger missed; fix it in the document.

## 7. Review

One cold read of the set by the `doc-reviewer` agent in docs mode, with § Rubric. Its brief carries the paths and nothing of the session, because a reader who saw the session already knows every undefined term. Without the agent, a context-free sub-agent briefed with § Rubric does the read.

- **BLOCKING findings:** fixed.
- **NITs:** reported to the user as one list, never looped on.
- **After the fixes:** the changed lines only are verified: re-lint, and re-read each citation a fix touched. A fix never adds an unsourced rule: a finding that needs a decision the sources do not make (a Two readings the rulings left open) narrows the sentence to what the sources say and goes to the user as a question. There is no second full cold read: a review that keeps finding new BLOCKING items is reading prose the ledger never governed, so the fix is to the ledger and a re-render of the documents it touches.

## One document into an existing set

- **The siblings are the set:** the term table and the ledger are built against them (§ 2, § 3), and the cold read reads the new document against them.
- **A fix that belongs in a sibling is made in the sibling,** in the same change: a rule whose home moved, a term renamed, a principle that now has an exception. Where the sibling is outside the change's scope, the fix is reported to the user as a sibling edit owed, never absorbed by restating the rule in the new document.
- **A contradiction with a sibling's principle** is never settled by the new document alone: it is an exception the sibling's principle must cite, or a question for the user.

## Rubric

A finding names the file and line, quotes the text, names its class, and proposes the fix. "Could be clearer" with no fix is not a finding.

**BLOCKING:** the set is wrong, or unreadable as a set, until fixed.

| Class | The defect |
| --- | --- |
| Contradiction | Two statements that cannot both hold, in one document or across two |
| Double home | A rule stated, not cited, in two documents, or twice in one |
| Wrong citation | A citation whose target does not say what the citing sentence claims (the lint checks that it exists; the reader checks what it says) |
| Split term | Two names for one concept, or one name for two |
| No decision of its own | A document under about six owned decisions; a section, table or bullet that states nothing the principles do not |
| Missing reason | A rule that meets a trigger of the style guide's § Sentences (a tempting alternative, a cost, an arbitrary value, an invisible failure) and carries no reason; in doctrine, a reason the reason check judged non-obvious and the document lacks |
| Filler | A sentence carrying no fact, rule, boundary or reason: a scene-setting opener, a generic truth used as framing, a metaphor or slogan standing in for a rule, a question |
| Wrong layer | Mechanism, a product's specifics or build state in doctrine, or a project link: the repository's own domain example, vendor, stack or document by path; history in a truth document |
| Fused reason | A rule and its reason joined into one sentence, so a reader cannot tell which half binds |
| Two readings | A rule a reader could act on in two incompatible ways |

**NIT:** wording, order, a label, a sentence that could be shorter, a reason a competent engineer would supply unprompted, a plainer synonym for a standard term, a cross-reference that would help. NITs never block.

In ledger mode the same classes apply to rows: two rows that contradict, a rule homed twice, a term used in two senses, a document left with fewer than about six rows, a row without its reason or without its source, a rule homed in a document whose question it does not answer.
