runward

RW™ · V0.22.0

Docs · Décisions · ADR-0023

ADR-0023.

manifest --sync — runward scaffolds the form, never the content

Date: 2026-07-16 Status: accepted Deciders: Thibault Souris (maintainer) Method: decision-loop — factual audit (the hand-maintained manifest as the adoption brake and rubber-stamp feeder), challenge against the operator-owns-the-decision invariant, durable position

Context

The conformance manifest is maintained entirely by hand: the operator (or their agent) writes every row of every gated deliverable's table. The audit named the two costs. Tedium feeds theater: the more painful the table plumbing, the more a tired operator stamps it — the exact failure mode ADR-0001's trigger (b) watches. Rule-set evolution lands on the operator: a renamed rule (ADR-0006) must be hand-edited in every manifest, and a rule newly mapped to a phase surfaces only as a red row at check time, one run at a time.

The plumbing is deterministic; the decisions are not. Today runward makes the operator do both.

Decision

A runward manifest command. Read-only by default: for each gated deliverable, the overview — rows accounted for, expected rules missing, renamed slugs with their migration, duplicates, unknown slugs. --sync writes the form, never the content:

  • creates a missing ## Rule conformance section (with its documentation blockquote) in a gated deliverable that lacks one;
  • appends one row per missing expected rule with empty status and empty evidence — and the gate refuses an empty status with a message that names the choice (applied | deviated | n/a), so a scaffolded row can never pass as accounted for;
  • rewrites a renamed slug in place per the migration record (ADR-0006), preserving the row's status and evidence;
  • reports and never deletes: duplicates, removed rules, unknown slugs stay the operator's edit.

The invariant, stated once: --sync never sets a status, never writes evidence, never deletes a row. The decision content stays the operator's and their agent's; runward moves the deterministic plumbing out of their way so the human effort lands on the pointer, not the table syntax. Respects --dry-run.

Alternatives discarded

  • Pre-filling scaffolded rows with a default status (n/a, or applied with a TODO). Builds the rubber stamp into the tool — a table full of plausible defaults is exactly what gets waved through. An empty status that the gate loudly refuses is the honest scaffold.
  • A virtual manifest (derive the table at check time, no file). The manifest is an operator-owned document with provenance and history (ADR-0001); hiding it in the tool makes the trace invisible and the diff unreviewable.
  • Report-only linting (no scaffold). Keeps the exact tedium that feeds the stamping; the audit's point was to kill the plumbing, not to describe it.

Consequences

  • Positive. A new mission or an updated rule set is one manifest --sync away from a complete, honest table skeleton; migrations stop being a hand-edit per manifest; the adoption brake and the theater feeder shrink together.
  • Negative, accepted. A write path into operator-owned documents — bounded by the form-only invariant and --dry-run; the section-insertion logic must stay conservative (append, never reorder).
  • On other boundaries. src/lib/manifest-sync.ts + src/commands/manifest.ts + a CLI entry; the gate's empty-status message names the expected gesture; smoke and unit tests cover scaffold, migration, idempotence, and that a scaffolded row still fails --strict.

Reevaluation trigger (mandatory, dated)

Reopen if operators start treating a freshly synced (empty-status) table as progress in itself — the plumbing became the theater — or if --sync ever needs to touch a row's content to stay useful: that would cross the invariant and must be refused or re-decided here.

Trigger set on: 2026-07-16 · Watched via: how synced manifests look when missions cross the gate (empty rows filled, or lingering).

References

  • ADR-0001 — the manifest this scaffolds; the operator-owns-the-decision invariant.
  • ADR-0006 — the migration record --sync applies mechanically.
  • ADR-0019 — the pointer grammar the freed effort should go into.
← Tous les ADR