Repository navigation
fix(bin): trust Claude worktrees cut from a sibling clone of the same repo - #5
Merged
Merged
Conversation
…ository When multiple firstmate homes share one treehouse worktree pool, a pool slot may belong to a sibling clone of the project rather than the spawning home's own clone. The scope test now accepts these through two checks: 1. Origin URL comparison: normalize and compare git remote origins 2. Path-based heuristic: check if the worktree's primary checkout lives at <firstmate-home>/projects/<basename> and verify same repo via origin When a sibling clone is detected, trust and external-imports consent are registered against the sibling checkout (Claude Code's canonicalization target), not the spawning home's clone. New tests: sibling clone with same origin accepted, sibling clone with declined imports refused, different repo at same basename path refused.
MrGTV-love
force-pushed
the
fm/fm-claude-trust-sibling-clones
branch
from
September 29, 2026 01:18
3a0efd5 to
99a6ed4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
The captain chose on 2026-09-28 to land firstmate fixes on his own fork, https://github.com/MrGTV-love/firstmate, instead of upstream and to avoid bothering Kun. He said to merge the fork PRs when green.
Land the Claude trust-guard fix in the existing fork PR #5 from branch fm/fm-claude-trust-sibling-clones. The fix makes the Claude trust check accept a treehouse pool worktree cut from a sibling clone of the same repository while continuing to refuse unrelated repositories. The PR branch conflicted with fork main, and its graft-cache untracking portion had already landed on fork main through fork PR 1.
What Changed
bin/fm-claude-trust.shnow accepts a linked worktree whose git common dir belongs to a different clone than<project>. It accepts it only when that owning checkout is the primary checkout for the common dir and both repos have the exact sameoriginURL. Trust and the consent-gated external-imports flags are then written against that sibling checkout. It prints aninfo:line on stderr. If the sibling already declined external imports, the whole registration refuses. Worktrees of unrelated repos are still refused.tests/fm-claude-trust.test.shadds three cases. A sibling-clone worktree with the same origin is trusted, and both the worktree and the sibling checkout are recorded. A sibling clone with declined imports is refused and the refusal names the sibling path. A different repo at a same-basenameprojects/path is refused.bin/fm-spawn.shandbin/fm-agy-trust.share updated, plus the docs in.agents/skills/harness-adapters/references/harness/claude.md,docs/orca-backend.mdanddocs/verification/runtime-backends.md. They now describe the sibling-clone scope. They also note thatfm-agy-trust.shstill refuses sibling-clone slots.Risk Assessment
✅ Low: The sibling-clone acceptance is narrowly gated (verified primary checkout owning the worktree's common dir plus exact non-empty origin URL match), fails closed otherwise, is covered by behavioral tests, and the prior out-of-scope graft ignore rules were correctly removed so the branch carries only the intended trust-guard change.
Testing
I ran the targeted tests/fm-claude-trust.test.sh file, and every case passed. Then I drove the real trust script by hand against real git sibling clones in 9 scenarios, with the base-commit script as a before control. The last step was an A/B launch of the real Claude Code CLI on a private lab tmux socket. With no trust recorded, the trust dialog blocked the pane. After fm-claude-trust.sh ran with home B as the project, Claude reached its composer in the same sibling pool slot. Every scenario passed. I removed the lab directory and the tmux server, and the worktree is clean. This is a CLI and TUI change, so text pane captures are the visual evidence.
Evidence: fm-claude-trust.sh CLI transcript (before/after + adversarial scenarios, store contents)
Source: fm-claude-trust.sh CLI transcript (before/after + adversarial scenarios, store contents)
Evidence: Real Claude Code A/B pane capture: trust dialog without registration vs composer after registration in sibling pool slot
Source: Real Claude Code A/B pane capture: trust dialog without registration vs composer after registration in sibling pool slot
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
🔧 **Rebase** - 1 issue found → auto-fixed ✅
.agents/skills/harness-adapters/references/harness/claude.md- merge conflict rebasing onto origin/fm/fm-claude-trust-sibling-clones🔧 Fix applied.
✅ Re-checked - no issues remain.
🔧 **Review** - 1 issue found → auto-fixed ✅
.ignore:1- Unrequired component: commit 192abdf (a 'docs' commit) adds a new/graft/rule to .gitignore and a new top-level.ignorefile that re-admits graft/ to ripgrep search. The user intent covers only the Claude trust-guard sibling-clone fix. It says the graft-cache untracking 'had already landed on fork main through fork PR 1' (6ff611a, which added onlygraft/.cache/). No intent requirement needs a whole-directory/graft/ignore or a new ripgrep.ignorepolicy, and neither is part of what PR 1 landed. With/graft/in place, the existinggraft/.cache/line from PR 1 also becomes redundant. Recommended remedy: drop the.gitignorehunk and the new.ignorefile from this branch, so the PR carries only the trust-guard change and main's existing graft ignore stays as it is.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bash tests/fm-claude-trust.test.sh(targeted file: all cases ok, including the 3 new sibling-clone cases and the fake-claude fm-spawn cases)Manual run ofbin/fm-claude-trust.shagainst real git fixtures (a bare origin, home A and home B clones, a shared pool slot from A, an own-clone worktree, an unrelated repo, repos with no origin) with isolated CLAUDE_CONFIG_DIR stores, 9 scenariosBefore/after control:git show 6c174d8:bin/fm-claude-trust.shrun on the same sibling pool slot. The base version refuses it.Realclaude2.1.284 launched on a privatetmux -L fm-labsocket (TMUX_TMPDIR inside the lab) in the sibling pool slot: a control store with no trust vs a store written by fm-claude-trust.sh. Captured withtmux capture-pane, thenkill-serverandrm -rfof the lab.git diff --stat 6c174d8..5013e5fconfirms no .gitignore/.ignore hunks (review-1 decision) and that the worker-account-pin wording is kept in claude.md (rebase-1 decision)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.