operationalize_design.py: golden before/after tests from the 005b/006a/007 backfill, fix to green nf-b21e ← Beads

closed priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/961 by tools/beads/import_github.py's reconcile pass.

Goal

Turn the 005b/006a/007 backfill (design 008 T4, #939) into an executable spec for design_docs/tools/operationalize_design.py: commit each doc's before and after states plus the GitHub side-effects as testdata, and add golden tests asserting the script transforms each before-state into exactly the after-state — then fix the script until those tests are green. The after-states are the *hand-corrected* live outcomes, so green means resolving #941, #951, #956 and asserting #960's repo-link, not just snapshotting today's behaviour.

Why: the script's unit tests were green throughout the backfill, yet every bug filed against it (#951 header-wrap corruption, #956 doubled Project title, #941/#938 hardcoded-OPEN status) surfaced only when --apply hit the real docs. Synthetic fixtures encode the author's assumptions; the three real docs encode the actual variety — wrapped Refs: bullets, <id> — title H1s, pre-convention issues hand-filled in Issue cells. Golden before→after tests make "what should --apply do" a test, not prose in 008 §6, and defend every future fix against the next regression.

Testdata (design_docs/tools/tests/testdata/<docid>/)

One directory per doc — 005b/, 006a/, 007/ — each holding:

Curation rule (important): projects cfsh/4,5,6 are live state and have drifted since the backfill — statuses move and issues close *because the design works*. Fetch the current specs (gh project view/item-list, or GraphQL for the repo link) as the generation aid and reference, but curate the committed golden down to expected initial provisioning: Status is Done iff the seeded issue's state was CLOSED at apply time, else Backlog — the script's actual contract. Do not commit the raw fetch as the oracle; it asserts things --apply never did. Record the fetch commands + curation rule in a testdata/README.md so the goldens are regenerable.

Issue-number fidelity: each doc's minted range is contiguous (005b minted only #940; 006a minted #943–950; 007 minted #953–955), and FakeGh mints sequentially from max(seeded)+1. Run each doc against its own FakeGh seeded so the first minted number matches reality (a seed entry at first−1 suffices) — then after.md comparison can be byte-exact, no normalization layer.

Harness (design_docs/tools/tests/test_golden.py or similar)

Per doc: build FakeGh from github_before.json → copy before.md to a tmp path → apply(gh, path, owner="cfsh") (prefer driving via main() without --owner where practical — that also closes #959's missing default-owner regression test) → assert:

  1. the rewritten file == after.md byte-for-byte;
  2. the fake's end-state (project title/owner/URL, linked repo, items + statuses, minted issue titles/bodies for spot-check) matches github_after.json;
  3. a second apply() run against the result is a no-op (the idempotency contract, now against real-shaped data).

Plus one synthetic --close golden (no doc has been closed yet, so no real data exists): start from 007's operationalized after-state with a mix of Done and non-Done items, run close(gh, "007"), assert every non-Done item → Deprioritized and the project closed. That puts all three modes under one harness.

Fake fidelity fixes are in scope where the goldens demand them: FakeGh.project_create currently builds users/{owner} URLs, but the real after-docs carry orgs/cfsh/... — the fake needs to produce org-shaped URLs for an org owner (and carry project_link state, which #960's FakeGh.project_link recorder already adds).

Script fixes in scope — the red→green work

The goldens will be red against today's script by construction; fixing these makes them green (close each with Closes #n in the PR that fixes it):

Explicit non-goal: 008 §6's "Ready for whatever §0 flagged as land-first" initial-status clause is not implemented and not golden-encoded — the contract under test is Backlog/Done. If that clause is ever wanted, it's its own issue with its own design (parsing §0 prose is not mechanical).

Done when
Refs

Design 008 §6/T3/T4 · backfill PRs #942 #952 #957 · tracking #939 · script PR #937 · follow-ups #938 #941 #951 #956 #959 · PR #960 · live Projects cfsh/projects/4,5,6 (005b/006a/007 respectively).

Unclaimed — sized and specified for a fresh session to pick up self-contained (this issue + what's on main).

Dependencies

None.

Comments

No comments.

Add a comment