Implement `design_docs/004-one-owner-for-the-integration-build.md` nf-g3zu ← Beads

closed priority 2 task unassigned

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

Implementation issue for [design 004](https://github.com/cfsh/ninefold/blob/main/design_docs/004-one-owner-for-the-integration-build.md) (status proposed, written under #543). Unclaimed and unlabelled — for the next /triage round.

The recommendation, in two lines

Take S1 — serialize the rebuild's *publish* with a lock in the shared .git, make a losing run an announced no-op, and refuse a push whose inputs moved since the merge began. Sequence S2 (the full scheduled rebuilder service Aedan proposed) after the WSL move, and do not build S7 (the rr-cache sync #535 proposes — already true on this box).

⚠️ Why S1 and not straight to S2: two of the three costs #543 argues from have already been paid down. The rr-cache half was never true on this box (every session is a worktree of one clone), and the unconvergeable-conflict half is fixed by #465 in #654. What is left is the force-push race, which S1 closes for a fraction of S2's cost. §5 of the doc lists what would change that call.

Shape of the work

Roughly two to three PRs, in this order:

  1. The lock + the pre-push input re-read (S1, S3) — one PR, in tools/pr/rebuild_f5.py and tools/tests/test_rebuild_f5.py. The cases that matter are the ones a happy-path test misses: a stale lock must not freeze f5 (fail-open — #467 is the precedent, a 45-minute lock that silently suppressed work), a losing run must exit 0 not 1, and the pre-push re-read must refuse when main moved.
  2. Manifest provenance (S4) — its own PR, because it changes a contract /playtest reads. This is also where §2.4's gap gets closed: a branch dropped by the #465 skip is currently *absent* from the manifest rather than marked excluded, so the exclusion is loud in the session's terminal and invisible to the person actually test-driving.
  3. Liveness (S5) — extend poll.py --check's STALE-DISPATCH to cover the rebuilder. Depends on whether S2 is coming; a stale lock is the same failure wearing different clothes, so this has value under S1 alone.

Tier 2, and a hardeningrebuild_f5.py is on the merge path with over 140 unit tests and silent-and-expensive failure modes. ⚠️ S2 is new capability, not a hardening of this subsystem, and should not inherit S1's justification.

Open questions the doc could not settle

§7 has four, each with a recommended default and what ships if it is never answered. The one worth answering even if S1/S2 stalls is #3 — should the manifest carry dropped branches? It is cheap and it is the half of #465 that is still open.

⚠️ Per /design Step 6, the work breakdown is in the doc, not filed as separate issues. Whoever takes this holds the whole thing and may split it then.

Dependencies

None.

Comments

No comments.

Add a comment