# How the User Manual Evolves

The manual is a product with a release cycle, not a document written once.
This file defines the practices that keep it true as the platform changes.
It is normative from M8 onward (the programme gate in [PLAN.md](PLAN.md) §13);
during the build-out programme, PLAN.md governs.

The design borrows the two conventions that already work in this repo: the
**living-spec build-status discipline** of the settlement docs (dated
verified-against stamps, honest ✅/⚠️/🔲 claims) and the **coverage-contract
discipline** of the consolidated setup (an enumerated matrix that makes
"complete" checkable).

---

## 1. Markdown is the source; HTML is a build artifact

The single most important rule, because its violation is how the current
manuals lost their sources: **never edit `docs/user-manual/*.html` directly.**
Edit `src/`, run `./build.sh`, commit source and artifact together. Every
built page carries a `<!-- GENERATED — edit docs/user-manual/src/ -->` banner;
a PR that changes an `.html` file without the corresponding `src/` change is
wrong by definition.

## 2. Docs ship with the change — the change map

A behaviour change and its manual update belong in the **same PR**. To make
"which chapter?" a lookup instead of a judgment call, maintain this change
map (extend it as the codebase grows):

| When you touch… | Update… |
| --- | --- |
| `lib/wb_wheeling_web/router.ex` (routes added/removed) | `COVERAGE.md` matrix 1 + the owning volume |
| `lib/wb_wheeling_web/live/**` (screen behaviour, fields, tabs) | the owning volume's screen chapter (see COVERAGE) |
| `lib/wb/wheeling/settlement/**` | V8; if the pipeline stages change, also V0 §4 spine |
| `lib/wb/wheeling/contracts/**`, proposal/wizard components | V7; party-assignment tables if S/B/J/D moves |
| `lib/wb/wheeling/forecast/**`, hierarchy resources | V4 |
| `lib/wb/strategy/**` | V3 (engine) · V4 IPP · V5 OffTaker · V6 Trader |
| `lib/wb/brp/**`, MO/SO consoles | V9 · V10 · V11 · V12 |
| `lib/wb/tariff/**`, `lib/wb/ts/**`, entity resources, wizards | V2 |
| `config/config.exs` Oban cron / AshOban triggers / supervision tree | V1 rhythms + V21 §3 catalog + V0 §6 clock preview |
| `lib/wb/setup/**`, `lib/wb/sim/**`, profiles/stages | V21 §§4–6 + [V14 Scenario Lab](v14-scenario-lab.html) + re-check example provenance (§4 below) |
| Enums that name states or line kinds | the owning volume's lifecycle-rail figure + glossary |
| `StrategyComponents` icon changes | STYLE.md + V0 §7 |
| New user-facing term of art | `GLOSSARY.md` (§5) |

The PR template should carry one checkbox: *"User manual: updated / not
user-visible (why)."*

## 3. The coverage contract is a regression gate

`COVERAGE.md` enumerates every route, stateful component, background process
and seat, each mapped to manual sections. Keep it current in the same PR that
adds or removes a row's subject. Drift check today is manual: reconcile the
header counts against `router.ex` and the cron table whenever they change.

*Optional automation (backlog, post-programme):* a `mix wb.docs.coverage`
task that diffs the router and Oban config against `COVERAGE.md` and fails CI
on unmapped additions. Do this only when manual reconciliation starts
missing things — the process matters more than the tooling.

## 4. Worked examples stay re-derivable

Every worked example carries a provenance stamp: profile, seed, stage, seat,
click path, last-re-derived date + dataset checksum. Consequences:

- A change to `WB.Setup` packs/stages or `Sim.MeterProfiles` that alters
  seeded numbers **owns** re-deriving the affected examples (grep the manual
  for the stage id in provenance stamps).
- Engine changes that legitimately change results (pricing, allocation,
  imbalance) update the example tables in the same PR — the diff of manual
  numbers is part of the review evidence, exactly like a golden-test update.
- At every release, re-derive at least the six flagship thread examples
  (M8 §Tasks 6 procedure) and refresh their stamps.

## 5. One glossary, growing monotonically

New terms enter `GLOSSARY.md` in the PR that introduces them, with at least
one "Explained in →" backlink. Never define a term inline in a volume without
a glossary entry; never fork a second definition. Renaming a term keeps the
old name as a one-line "formerly X, see Y" entry for one release.

## 6. Verified-against stamps and honest claims

Each chapter footer carries *last verified: date · commit*. Claims about
behaviour follow the settlement-docs rule: document what is **built and
wired**; if a screen is a placeholder or a feature is partial, say so plainly
(V7 does this for the Eskom/Munix placeholders). A quarterly audit (§9) flags
chapters whose stamp is older than two quarters for re-verification.

## 7. Anchor stability — append, don't renumber

Published chapter numbers and the frozen spine-locator anchors are permanent.
New content appends within a volume (new §N+1, or lettered subsections) rather
than renumbering existing chapters. If a restructure is unavoidable, ship an
anchor map in the old location exactly as the M5 redirect stubs do. This is
what keeps years of cross-links, bookmarks and support answers alive.

## 8. Figures before screenshots

Hand-crafted CSS/SVG figures from the STYLE.md catalog are the default — they
survive UI restyles and print cleanly. When a real screenshot is genuinely
better (rare), it must be taken from the seeded `full_demo` dataset with its
seat + path recorded in the caption, so it can be retaken identically. When
the UI restyles, screenshots are retaken; figures usually survive untouched —
that asymmetry is the point.

## 9. Cadences

| Rhythm | Work |
| --- | --- |
| **Every PR** | Change-map lookup; same-PR doc updates; `./build.sh` green |
| **Every release** | Version stamp on hub; `CHANGELOG.md` entry; flagship examples re-derived; new/changed screens sweep |
| **Quarterly** | Coverage reconciliation; staleness sweep (chapter stamps > 2 quarters); glossary orphan check; docs-backlog triage. **Next audit window:** 2026-10 (scheduled at M8 programme gate). |
| **Yearly** | Full stranger read-through of one seat path; print/PDF pass; figure-gallery visual regression check |

## 10. Superseding and archiving

When manual content (or a corpus design doc it cites) is superseded:

- Manual content: rewrite in place (the manual states the present, history
  lives in git); note the change in `CHANGELOG.md`.
- Corpus docs: move to an `archive/` sibling **and leave a stub at the old
  path** naming the successor — this repairs the current broken pattern of
  archive pointers that name files that don't exist. Add a
  banner ("superseded by …") rather than deleting.
- Redirect stubs (legacy manual URLs) are permanent.

## 11. Feedback loop and ownership

- **Ownership**: each volume has a named owner (recorded in the volume's
  source dir README/frontmatter at M8). The owner reviews doc PRs touching
  their volume and runs its quarterly checks.
- **Backlog**: reader findings, gaps and wish-list items go to
  **[V22 · TODOs](v22-todos.html)** — one chapter per owning volume (V0–V19),
  each item citing volume + chapter (what exists today, trigger,
  first-guess shape). The
  stub `docs/user-manual/BACKLOG.md` only points at V20. Triage quarterly.
- **Support answers are doc smells**: an answer given twice in support that
  isn't in the manual becomes a V20 item under the owning volume, with the
  FAQ ([V21 §7](v21-operations.html#7-troubleshooting--faq)) as the usual
  landing place when the smell is operational.

## 12. Growth path (explicit non-goals today)

Single-page Pandoc volumes are the right tool while the set is ~10 pages and
readers ⌘F within a volume. Revisit **only** when a concrete trigger fires:

- Volumes exceed ~500 KB rendered or authors collide on the same chapter
  files weekly → split source files further (build already concatenates).
- Readers demonstrably need cross-volume search → consider a static site
  generator (mdBook-style) *keeping the same Markdown sources* — the D1
  decision to own sources is what makes any future migration cheap.
- Non-English readers appear → per-volume translation dirs mirroring `src/`.

Until a trigger fires, resist tooling churn: every hour spent on doc
infrastructure is an hour not spent keeping chapters true.
