Skip to content

fix(bin): validate default branch refs before worktree spawn - #1245

Closed
wuzihuang wants to merge 2 commits into
kunchenguid:mainfrom
wuzihuang:fm/o1-server-build-base-r4
Closed

fix(bin): validate default branch refs before worktree spawn#1245
wuzihuang wants to merge 2 commits into
kunchenguid:mainfrom
wuzihuang:fm/o1-server-build-base-r4

Conversation

@wuzihuang

Copy link
Copy Markdown

Intent

Let a project whose remote publishes only build/production get an isolated worktree instead of failing: firstmate must resolve a default branch that actually exists rather than a stale origin/HEAD target, and refuse up front with the real cause when the base ref treehouse would allocate from is missing, so the O1-Server implementation can resume from a safe isolated copy.

What Changed

  • Centralized default-branch resolution in bin/fm-tangle-lib.sh so callers only trust origin/HEAD when its target ref exists, then fall back to local main/master.
  • Added a fm-spawn.sh treehouse base-ref preflight that refuses before launch when the resolved allocation base is missing and reports the available remote branches.
  • Documented the base-ref behavior and added shell coverage for dangling origin/HEAD, build/production-only remotes, valid repointed defaults, and unfetched clones.

Risk Assessment

🚨 High: High because the new spawn preflight still misses a source-verifiable stale origin/HEAD case and can fall back to the generic treehouse failure instead of satisfying the required upfront refusal.

Testing

Ran the focused tangle/worktree guard regression and a manual CLI transcript; an initial transcript attempt hit the validator's NO_MISTAKES_GATE environment guard, then the same scenario was rerun with the repository test bypass so the target spawn path was exercised successfully.

Evidence: Manual fm-spawn build-only base-ref transcript
Manual verification: fm-spawn base-ref preflight for build/production-only project
workspace: /home/dev/.no-mistakes/worktrees/4d31509af733/01KYQ1JTXDGBY6QW93K094PHWT

$ git -C "$PROJ" for-each-ref --format="%(refname:short)" refs/remotes/origin
  origin/build
  origin/production

$ git -C "$PROJ" symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
$ git -C "$PROJ" symbolic-ref refs/remotes/origin/HEAD
  refs/remotes/origin/main
$ bin/fm-spawn.sh stale-main "$PROJ" codex
  error: treehouse would build the isolated worktree for stale-main from 'main', but neither refs/heads/main nor refs/remotes/origin/main exists in /tmp/no-mistakes-evidence/01KYQ1JTXDGBY6QW93K094PHWT/manual-spawn.h8Fiyv/project; refusing to launch rather than allocating from a base ref that is not there. Remote branches present: build,production. Repointing that clone's origin/HEAD at a branch that exists is a project-side repair firstmate does not make.
  exit=1
$ test ! -e "$HOME_DIR/state/stale-main.meta" && echo no metadata written
  no metadata written

$ git -C "$PROJ" symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/build
$ bin/fm-spawn.sh build-ok "$PROJ" codex
  warn: no registry at /tmp/no-mistakes-evidence/01KYQ1JTXDGBY6QW93K094PHWT/manual-spawn.h8Fiyv/home/data/projects.md; defaulting project to no-mistakes off
  spawned build-ok harness=codex kind=ship mode=no-mistakes yolo=off window=firstmate:fm-build-ok worktree=/tmp/no-mistakes-evidence/01KYQ1JTXDGBY6QW93K094PHWT/manual-spawn.h8Fiyv/worktree
  exit=0
$ test -e "$HOME_DIR/state/build-ok.meta" && echo metadata written
  metadata written

Transcript saved to /tmp/no-mistakes-evidence/01KYQ1JTXDGBY6QW93K094PHWT/build-only-spawn-base-ref-transcript.txt

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 error
  • 🚨 bin/fm-spawn.sh:882 - Criterion contradiction: intent requires firstmate to "refuse up front with the real cause when the base ref treehouse would allocate from is missing", but this guard accepts a leftover local refs/heads/$branch even when treehouse_base_branch chose $branch from refs/remotes/origin/HEAD. For origin/HEAD -> origin/main, deleted refs/remotes/origin/main, and an old local main, this returns success even though treehouse will allocate from the missing remote ref and fail later. The contradicting hunk is the local-or-remote check: refs/heads/$branch || refs/remotes/origin/$branch.
✅ **Test** - passed

✅ No issues found.

  • tests/fm-tangle-guard.test.sh
  • Manual bin/fm-spawn.sh verification with a temporary build/production-only project, fake tmux/treehouse backend, stale refs/remotes/origin/HEAD -> refs/remotes/origin/main, then valid refs/remotes/origin/HEAD -> refs/remotes/origin/build; transcript saved at /tmp/no-mistakes-evidence/01KYQ1JTXDGBY6QW93K094PHWT/build-only-spawn-base-ref-transcript.txt
  • git status --short to confirm no working-tree artifacts were left behind
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

A project clone keeps refs/remotes/origin/HEAD from whatever its remote
advertised at clone time, and that symbolic ref keeps resolving after the
branch it names is renamed or deleted. git symbolic-ref reports the dangling
target happily, so every unvalidated read handed callers a branch name that
cannot be checked out, diffed, or merged into. Seen live on a clone that
publishes only build and production while origin/HEAD still names main.

fm_default_branch now trusts origin/HEAD only when its target exists, and
falls through to the local candidates otherwise. The five byte-identical
copies of that resolution in fm-ff-lib, fm-review-diff, fm-teardown,
fm-merge-local, and fm-fleet-sync now delegate to it instead of carrying the
same defect five more times.

fm-spawn additionally refuses up front when the base treehouse would build the
isolated worktree from is missing. treehouse get takes no base-ref argument
and treehouse does not verify the base it resolves, so git worktree add fails
inside the pane and firstmate saw only the generic 60s did not enter a
worktree timeout. The refusal names the missing ref and the branches that do
exist, and stays read-only: repointing a project's origin/HEAD is a
project-side repair firstmate does not make. A clone with nothing fetched yet
is deliberately not refused, since treehouse fetches before it allocates.
@wuzihuang wuzihuang closed this Jul 29, 2026
@wuzihuang
wuzihuang deleted the fm/o1-server-build-base-r4 branch July 29, 2026 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants