rebuild_f5 should run in a dedicated worktree, not the session's checkout nf-vwfi ← Beads

closed priority 2 task unassigned

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

rebuild_f5.py drives the session's own checkout — it moves HEAD to f5/integration, merges every open PR there, builds, imports, and hands HEAD back. Almost every sharp edge that keeps getting filed against this script is a consequence of that one fact, and each has been fixed separately at the symptom.

Aedan asked for this shape on #503 after approving the sweep-and-warn fix:

> I think worktree option is better long-term. Since dev-a/b/c live in long-lived clones of the repo, they could make a worktree just for rebuilding f5 and it wouldn't need a full clone each time right, so it would be expensive on setting up a new dev-x, but cheap on incremental IIUC?

Filing it as its own issue because it currently lives only in a comment on a closed issue, which is the reliable way to lose it.

Answering the cost question — measured, in ninefold-c

Yes, and cheaper than expected. git worktree add shares the object store, so nothing is re-cloned:

| | size | duplicated by a worktree? | |---|---|---| | .git | 235 MB | no — shared | | tracked tree | 1238 files, ~1 MB | yes (trivial) | | .godot/ import cache | 235 MB | yes — generated once, then incremental | | .godot/mono build output | 9 MB | yes |

So: ~1 MB of real checkout, plus a second Godot import cache that is generated on first run and incremental thereafter. Exactly the "expensive to set up a new dev-x, cheap incrementally" shape guessed on #503 — and the expensive part is a one-time import, not a clone.

What it closes structurally

| | today | with a worktree | |---|---|---| | #503 — generated .uid/.import sidecars leak into the session's branch | fixed by a before/after sweep (#505) | impossible — different tree | | #512 item 1 — rerere's git add -A commits, then destroys, the session's untracked scratch files | open | impossible — the session's tree is never touched | | #512 item 3 — a failed baseline git status inverts the sweep into "delete everything untracked" | open | the sweep stops existing | | HEAD parked on the throwaway branch (below) | partially guarded | impossible — HEAD never moves |

The sweep, the before/after baseline, bail_to_start, hand_back, and the start_ref(git) == F5 guard inside sweep_artifacts all exist *only* to manage the blast radius of borrowing the session's checkout. A worktree deletes that whole category rather than hardening it.

A live gap in the hand-back, found today

hand_back is a no-op when the ref you started on is f5/integration itself:

```python def hand_back(git: Git, ref: str) -> int: if ref and ref != F5: # <-- silently skipped when ref IS f5 ... ```

That state is not exotic, it is the *documented workflow*: an unrecorded conflict deliberately parks you on f5/integration so you can resolve it in place. You resolve, commit, re-run — and now start_ref is f5/integration, so the successful run "hands HEAD back" to the throwaway branch and says nothing. The ⚠ STILL ON f5/integration warning only fires when a hand-back to a *different* ref fails, which is the one path this isn't.

It bit me twice today on #511: two commits of feature work landed on f5/integration, and the only symptom was git push failing with *"upstream branch does not match"* — because f5/integration tracks origin/main. Build and tests both passed on the wrong branch. Recovered by cherry-picking, but the next rebuild would have destroyed them silently.

The script's own docstring says this class already cost a full review round (#348/#375). That was a *failed* hand-back; this is a *skipped* one — a different entry into the same hole.

Cheap standalone mitigation if the worktree is not taken soon: warn (don't checkout) when ref == F5, reusing the existing message. Currently the quietest outcome is the most dangerous one.

What it does not fix
Implementation notes

Filed unclaimed.

Dependencies

None.

Comments

No comments.

Add a comment