# Building the manuscript and its evidence
The manuscript has four distinct build layers. Keeping them separate prevents a
render command from silently becoming a database experiment and makes every
published figure traceable to its input.
1. **Capture evidence** — run literal `EXPLAIN` statements against PostgreSQL and
update the tracked JSON audit manifests.
2. **Render assets** — turn tracked plan evidence and normalized teaching fixtures
into SVG files under `assets/`.
3. **Compile Markdown** — concatenate the chapter sources into
`ManuscriptCompiled/` for Obsidian.
4. **Export PDF** — ask Better Export PDF to render the compiled manuscript, then
create and structurally verify the compressed editions.
Run `make help` for the complete target list.
## Make one operation card at a time
The common editorial loop should not require remembering which plan and trace
scripts must run, nor should changing one card rewrite all 36 operation assets.
Use the operation key printed by `make list-operations`:
```sh
make list-operations
make operation-assets OP=IndexOnlyScan
```
That one command rebuilds both target images for the card:
- its graphical plan tree, from the literal plan already stored in
`scratch/actual_operation_plans.json`; and
- its plan performance signature, from the exact OTLP capture already attached
in `artifacts/chapter4_runtime_evidence.json`. Non-wait execution time is
labeled `CPU`; observed waits retain their exact
`wait_event_type:wait_event` names. Runtime classes use distinct vector
hatching as their primary encoding so the figures remain legible when
printed in grayscale; color is supplementary.
For narrower or broader iterations:
```sh
make operation-plan OP=IndexOnlyScan
make operation-trace OP=IndexOnlyScan
make section-assets SECTION=Index
make operation-assets-all
```
`SECTION` is the Operations folder name (`Index`, `ResultSet`, `Tuple`, and so
on). Operation and section matching is case-insensitive. These targets render
images only: they do not connect to PostgreSQL, recapture evidence, edit the
Markdown cards, concatenate the manuscript, or invoke Obsidian. An explicitly
requested card or section fails when a trace is still `capture-required`; the
whole-ledger target reports known pending traces and renders everything that has
evidence. This makes a missing Citus trace visible without blocking unrelated
stock-PostgreSQL asset work.
## The ordinary Chapter 4 loop
After editing Chapter 4 prose or a deterministic diagram fixture:
```sh
make chapter-4
make review-plans
```
`make chapter-4` performs only reproducible local rendering, compilation, and
validation. It does not start PostgreSQL, change planner settings, or refresh
captured evidence. Open `scratch/preview_pgadmin_plans.html` when plan-tree
appearance or audit consistency changed.
When the compiled chapter looks correct, export separately:
```sh
make pdf
```
Keeping PDF export separate avoids paying for Obsidian rendering while iterating
on SVGs or prose.
## When literal plan evidence must change
The files `scratch/actual_illustrated_plans.json` and
`scratch/actual_operation_plans.json` are captured evidence. Do not edit their
plan text to make a diagram agree with an expectation.
For stock PostgreSQL plan cases, start the repository's normal populated audit
database and pass its connection URI explicitly:
```sh
make capture-plans AUDIT_DATABASE=postgresql://
[email protected]/plan_audit
```
That target captures the literal plans first, then renders the plan assets and
rebuilds the HTML review. It fails before capture when `AUDIT_DATABASE` is absent;
there is no implicit production or developer-database default. The stock target
merges only cases without extension requirements, so it preserves previously
captured pgvector and Citus evidence.
For pgvector and Citus cases, use the pinned disposable environments:
```sh
make capture-extension-plans
```
The extension workflow records PostgreSQL and extension versions, fixture names,
capture timestamps, and complete literal plan text. See
`scripts/extension_audit/README.md` for ports and the `--keep-running` inspection
option.
## What the wait-event timelines mean
`make trace-assets` regenerates the teaching timeline SVGs from deterministic
fixtures in:
- `scripts/generate_plan_traces_svg.py`
- `scripts/generate_pathological_traces.py`
These fixtures normalize observed execution phases into legible teaching
timelines. They demonstrate sequencing and attribution—such as a `Sort` moving
from CPU to `BufFileWrite` and `BufFileRead`—but they are not raw exports from
`pg_stat_activity` or `pg_wait_tracer`. They remain available for the dedicated
wait-event teaching chapters, but they are not valid runtime evidence for a
Chapter 4 operation card.
Chapter 4 uses a strict capture contract:
- literal `EXPLAIN (ANALYZE, BUFFERS)` excerpts for nodes, rows, buffers, spill
methods, worker counts, and batch counts; and
- an exact `pg_wait_tracer` capture exported through `pgwt-server
execution_detail` and `tools/export_otel.py` before a wait-event diagram can
be attached to an operation card.
The manifest marks every card without that source as `capture-required`; it
does not render a substitute diagram. After attaching a capture, rebuild only
that graph with `make operation-trace OP=<key>`. The exact attachment procedure
is in `scripts/wait_capture/README.md`.
## Target dependency map
```text
live PostgreSQL ──capture-*──> tracked audit JSON ──plan-assets──> plan_tree_*.svg
normalized teaching fixtures ──trace-assets──> trace_*.svg
exact pg_wait_tracer OTLP ──trace-assets──> operation-card wait SVG
chapter Markdown + assets ──manuscript──> ManuscriptCompiled/*.md
ManuscriptCompiled/*.md ──pdf──> master PDF ──verify──> compressed PDFs
```
The validation target follows Chapter 4's actual operation-card transclusions,
checks that those sources refer to real assets, parses every referenced SVG as
XML, rejects the removed generic `Factors`, `Operates on`, `Workloads`,
`Description`, and `Runtime signature` rows, and audits the literal-plan and
exact-capture boundaries recorded in
`artifacts/chapter4_runtime_evidence.json`. A wait SVG can appear on an
operation card only when its raw capture is recorded in that manifest. It then
runs the trace renderer unit tests. It deliberately does not sweep unrelated
Operations library index pages:
```sh
make check-assets
```