✏ Write and accept the chapters¶
Status: tutorial, steps 3, 3b and 4 of Write a book.
Written for whoever writes the chapters: you, a co-author, or a genre skill working from a contract. Assumed: a signed outline (step 2). Not covered here: how each genre drafts a chapter; the table in step 3 points at each genre's own tutorial.
▶ Step 3: hand each chapter to its author¶
The spec owns the book's structure; the genre skills own its content. This is the handover:
1 | |
1 2 3 4 5 6 | |
ch-cost and ch-sync declare no sections, so there is nothing to
seed for them; each is still a unit, written as one file named for the
chapter's id. For each chapter the outline describes at section
level, it writes that chapter's section names into its dossier's
outline.md as bare ## headings and stops. Every brief:, claim:
and queries: line beneath them is left for whoever drafts the
chapter; a brief the spec invented would be the book track writing
content.
It refuses an unsigned outline, because seeding from a structure
nobody approved puts unsettled section names in front of an author as
though they were decided. It never rewrites a heading, so it is safe
to re-run once the spec grows a section; --dry-run says what it would
add. The write itself is done by dossier init, so the package that owns
content/dossiers/ stays the one creating files in it.
A freshly seeded outline has headings and no briefs, so
dossier outline <draft> --check will report each as "neither a brief:
nor a claim: block". That is expected, since nobody has filled it in yet.
Filling it in is the chapter author's job, and it is the same
outline.md every other genre uses. Per section: brief: (steering,
never printed), claim: (your prose, grounded or reported back),
queries: (run verbatim). Each chapter also gets its own scope.md:
the reader, what the chapter covers, what it defers to another chapter,
and the glossary.
Fill in the glossary most carefully. Chapter authors working in parallel will
define the same term three ways unless each chapter's scope.md pins
it, and step 5's terminology registry catches them when they do.
Whichever genre a chapter is, its tutorial has the field-by-field walkthrough and a complete filled-in example:
| Chapter is | Follow |
|---|---|
| teaching material, worked examples, exercises | WRITE-A-TEXTBOOK-CHAPTER.md |
| a hands-on lab the reader follows at a keyboard | WRITE-A-TUTORIAL.md |
| a literature map or state-of-the-art chapter | WRITE-A-SURVEY.md |
| an RQ-driven argument | WRITE-A-THESIS-CHAPTER.md |
| a multi-perspective, contradiction-mapped report | WRITE-A-DEEP-RESEARCH-REPORT.md |
A book may mix them: a textbook whose third chapter is a survey and whose fifth is a lab is a normal shape, and the unit record does not care which genre wrote a chapter.
▶ Step 3b: generate one unit¶
Ask for the contract, which is what the unit is generated from:
1 2 | |
1 2 3 4 5 6 7 8 9 10 11 | |
The contract is explicit in both directions:
| In | Out |
|---|---|
| the spec slice (title, brief, the part and chapter above it) | the unit's prose at content/drafts/<book>/<unit-id>.md |
the sources it is grounded in, given as --source <citekey> |
the citekeys it cites, recorded |
| registry excerpts, injected at generation time | the claims the register picks up |
--source is repeatable and is part of the input digest, so grounding a
unit in a different set of papers is a different unit to generate
(what else the digest covers).
Registry excerpts are handed to the generator but deliberately left out
of that digest
(why).
Then write the unit. This is the one step this track does not own: a
genre skill drafts it (thesis-chapter-writer for a .tex fragment,
another genre for Markdown, handing any figure to figure-drawer),
grounded in the sources, and saves it as
content/drafts/twins/ch-what.md. From step 5 on you can hand that skill
what the rest of the book already settled:
1 | |
A part has no contract, and neither does a section inside a chapter that declares sections, because that chapter is the unit. Asking for either is refused rather than answered with an empty contract, and the refusal names the units that do exist.
Which entries are units, so you know which files to write:
| The outline says | The unit is | Its file |
|---|---|---|
| a chapter with two or more sections, or one section titled differently from the chapter | the chapter | <chapter-id>.md |
| a chapter with exactly one section carrying the chapter's own title (a retrofitted book) | that section | <section-id>.md |
a chapter with no sections (ch-cost, a preface, an appendix) |
the chapter | <chapter-id>.md |
{#glossary}, {#symbols}, {#figures}, {#tables} |
none: generated at assembly | none |
a part ({#front} and {#back} included) |
none | none |
Not every unit goes through a genre skill. A preface, an
acknowledgements page or an "about the author" page is in your own
voice, so you write it by hand, and it is accepted exactly like a
chapter: unit accept needs only the citation gate to pass, which a page
citing nothing does. Front matter has the workflow.
▶ Step 4: accept the unit¶
Before accepting, check that what was written still matches what you approved:
1 | |
1 2 3 4 5 6 7 8 9 10 | |
It compares the sections your outline declares for a chapter against the
## headings that chapter's author wrote, and reports four
things: a declared section not authored, an authored section not
declared, a renamed heading, and sections all present but out of
order. A reworded heading is one finding rather than two, because "you
renamed this" is what happened. Numbering is ignored, so 3.1 The model half and
The model half are the same section: a genre skill numbers what it
writes and the outline does not.
align reads and refuses nothing, and exits non-zero on a finding the
way spec status does. It is silent on a chapter the outline describes
only at chapter level; see
why a chapter is the authored document
for the scoping rule and what it is protecting against.
1 | |
1 2 3 | |
accept writes the record only after the project's one gate passes on
the draft. It refuses five ways, each for a stated reason:
- This unit's chapter is not signed off. There is nothing to accept a unit against until a human has approved the structure. Asked of the unit's own chapter, not of the whole book, so revising chapter 7 does not stop you accepting a unit in chapter 3 (why).
- The unit's chapter does not match the outline. Acceptance
records that a human approved this prose against that outline, and a
chapter whose headings have drifted makes the record say something
untrue.
spec alignlists what moved. A chapter nobody has written yet is deliberately not a refusal: a book is drafted unit by unit, and holding the first unit until the whole chapter exists would make it impossible to accept. - There is no draft. Generate the unit from its contract first.
- A
--sourceis not in the ledger.--sourcenames the papers this unit claims to be grounded in, and the acceptance record keeps that claim permanently, so it is checked against the ledger before anything is written. A record asserting grounding in a citekey no real parse ever produced is exactly the fabricated reference CLAUDE.md's one rule exists to prevent. It is reported with the argument-shaped faults above, not beside the gate's findings, where it would read as a defect in the prose. - The citation gate refuses the draft.
acceptruns the project's one gate rather than re-implementing or replacing it: it reads the draft once and hands that string tocitation_gate.check_text, reporting throughcitation_gate.report, which is the same printerchitragupta draft gateitself uses, so the two read identically. It reads the file once on purpose, so the prose it hashes and records is exactly the prose the gate checked, even if a write lands while it runs. A unit that fails the gate cannot be assembled into a book, andacceptadds no second gate.
The record holds the input digest the prose was generated against, the
sources, what it cites, and a digest of the prose itself. It carries
no timestamp, so accepting an unchanged unit twice produces
byte-identical files and a diff of content/specs/ is a diff of what was
accepted.
Repeat steps 3b and 4 per unit. unit status is the board, and it names
what the dossier says about the same prose beside what this layer
recorded:
1 2 3 4 5 6 | |
The two records of the same text answer different questions:
accept's output_digest is "has this changed since a human accepted
it", the dossier's fingerprint is "has it changed since the sidecars were
reconciled". Different commands refresh them (unit accept and
dossier stamp), so they can disagree, and unit status prints both.
no dossier, not stamped, agrees, disagrees and
stamped, no draft are the five answers. The comparison is reported and
never enforced, because this layer does not judge a dossier.
1 | |
| State | Means |
|---|---|
unwritten |
no draft on disk |
drafted |
prose exists, nobody accepted it (also what an unreadable record reads as) |
accepted |
the record matches both the current contract and the prose |
stale: inputs changed |
the outline moved under an accepted unit |
stale: draft changed since accepted |
the prose moved after acceptance |
It re-derives all three digests rather than trusting them, and exits 0
only when every unit is accepted and current, the same standing as
spec status.
An acceptance record whose unit has left the outline is listed, not
deleted. Remove ### What a twin costs {#ch-cost} from spec.md
after accepting it, and unit status adds a line after its summary:
1 | |
--json carries the same ids under "orphaned". They do not count
towards the exit code, and nothing deletes units/ch-cost.json or
ch-cost.md: the prose is yours, and whether to keep it is your call.
Changing the outline after sign-off has the
rest of that workflow.
Next: build the registries.