# 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 ```