Conversation
A Treehouse pool is keyed by a project's resolved origin and shared by every local clone of that origin, so an agy spawn can be handed a pool worktree linked to a different home's clone than the project this spawn's own home registered. fm-spawn.sh passed the registered project to fm-agy-trust.sh regardless, whose structural scope test correctly refused the false assertion, so every cross-clone agy spawn fell back to answering the folder-trust dialog after launch: readiness depended on the dialog rendering, a single non-retried Enter landing, and a busy verdict all inside one bounded window, plus a warning per spawn for a structurally normal fleet shape. The fallback is bounded and cannot wedge - every gate failure path fails the spawn with endpoint cleanup - but it is the weaker, dialog-dependent route for a normal shape. Derive the agy-trust <project> argument from the acquired worktree's own git common dir instead, falling back to the registered project only when that cannot be resolved, the same derivation the claude pooled-worktree fix applies. The trust script's scope test is unchanged.
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
Follow-up raised during the review of fm-pooled-worktree-claude-trust, which fixed the same class of problem for claude.
bin/fm-spawn.sh:3967 still passes the spawning home's registered project to bin/fm-agy-trust.sh. So an agy spawn into a worktree that belongs to a different clone - the shared-pool case that fix addressed - hits the same structural scope mismatch. It is not fatal for agy today: it warns and falls back to the post-launch dialog gate, so the worker still reaches its brief.
docs/verification/agy.md:61 describes that path as asserting "the spawning project". That stays accurate for agy as written, but it now diverges from how claude derives the same value.
Firstmate's decision on that review finding was to leave both the code and the doc line untouched and carry this as its own item, because extending the derivation to agy is a decision about agy behaviour rather than a correction the claude fix required.
This task is also the first real piece of work dispatched on the Z.AI GLM-5.3 runtime, which the captain added to the fleet today. Work normally; that is a fleet matter, not a change to this task.
What Changed
bin/fm-spawn.shnow derives the<project>argument it passes tobin/fm-agy-trust.shfrom the acquired worktree's own git common dir instead of the spawning home's registered project, so a pooled worktree linked to another clone of the same origin passes the helper's structural scope test and gets pre-registered. The registered project stays the fallback when the common dir cannot be resolved, and the scope test itself is unchanged.tests/fm-agy-harness.test.shgains two cases: a worktree linked to a sibling clone of the project's own origin is pre-trusted through its real primary checkout with only the launch Enter, and a sibling clone's primary checkout that the same derivation names is still refused, leaves the store untouched, and takes the warn-and-answer dialog fallback.docs/verification/agy.mdand the agy harness adapter reference now describe the derivation, its fallback, and the new test coverage, replacing the earlier "spawning project" wording.Risk Assessment
✅ Low: The change is a bounded, single-arm derivation that mirrors an already-accepted fix, cannot loosen the trust helper's structural scope test, degrades only to the pre-existing warn-and-dialog-gate path on any resolution failure, and is covered by a behavioral regression test that reproduces the reported shape.
Testing
I derived the scenarios from the intent (an agy spawn into a pool worktree owned by another clone of the same origin must pre-register trust instead of falling back to the post-launch dialog) and drove them through the real bin/fm-spawn.sh CLI with the suite's fake tmux and fake agy pane. The pooled spawn now writes the worktree into agy's own settings.json, prints no pre-registration warning, and sends only the launch Enter. Restoring bin/fm-spawn.sh to the base commit makes the same scenario fail with the old scope refusal, so the regression is real and the fix closes it. I added an adversarial scenario: a sibling clone's primary checkout passes the spawn's isolation guard, so I checked the derivation cannot turn it into a trusted folder - the helper still refuses, the store is untouched, and the spawn takes the bounded dialog fallback. A mutation that removes that refusal makes the new case fail, so it is not vacuous. The live vendor path (a real agy 1.2.0 launch in an fm-herdr-lab session) could not be driven: agy is not installed on this host. There is no UI surface in this change, so evidence is CLI output and the persisted trust store rather than screenshots.
bin/fm-test-run.sh tests/fm-agy-harness.test.shdrives the real fm-spawn.sh; evidence file agy-pooled-spawn.txt shows the worktree added to agy's settings.json, no pre-registration warning, and 1 En…not ok - a worktree pooled against a sibling clone failed trust pre-registration, with the scope refusal and warning in agy-pooled-regression-before-after…test_agy_fresh_worktree_is_pre_trusted_and_launches_without_a_dialogpasses: store holds the worktree, unrelated keys preserved, 1 Enter sendtest_agy_spawn_refuses_to_pre_trust_a_sibling_primary_checkout; agy-sibling-primary-refused.txt shows the helper's primary-checkout refusal, the store left unchanged, and the bounded dialog fall…test_agy_unregistered_path_ignores_busy_until_the_dialog_is_answeredandtest_agy_unregistered_path_without_a_dialog_fails_the_spawnpass: the warning path, the unparseable store left untouched, a…Evidence: Pooled spawn: derived project, spawn output, agy trust store after the spawn
Source: Pooled spawn: derived project, spawn output, agy trust store after the spawn
Evidence: Adversarial: a sibling clone's primary checkout is refused and never trusted
Source: Adversarial: a sibling clone's primary checkout is refused and never trusted
Evidence: Before/after regression transcript plus the mutation check
Source: Before/after regression transcript plus the mutation check
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:3965- The derivation block added to the agy arm is a near-verbatim copy of the one the claude pooled-worktree fix (036f30e, branch fm/fm-pooled-worktree-claude-trust) adds to the claude arm of the same case statement. That branch is not in this base, so no duplication exists in this tree today; once both land, the same rule lives twice, ten lines apart, and must be kept in sync. No action needed now - noting it so a later cleanup can lift the derivation into one helper (for example next to spawn_worktree_isolated) rather than editing two copies.✅ **Test** - passed
✅ No issues found.
bin/fm-test-run.sh tests/fm-agy-harness.test.shdrives the real fm-spawn.sh; evidence file agy-pooled-spawn.txt shows the worktree added to agy's settings.json, no pre-registration warning, and 1 En…not ok - a worktree pooled against a sibling clone failed trust pre-registration, with the scope refusal and warning in agy-pooled-regression-before-after…test_agy_fresh_worktree_is_pre_trusted_and_launches_without_a_dialogpasses: store holds the worktree, unrelated keys preserved, 1 Enter sendtest_agy_spawn_refuses_to_pre_trust_a_sibling_primary_checkout; agy-sibling-primary-refused.txt shows the helper's primary-checkout refusal, the store left unchanged, and the bounded dialog fall…test_agy_unregistered_path_ignores_busy_until_the_dialog_is_answeredandtest_agy_unregistered_path_without_a_dialog_fails_the_spawnpass: the warning path, the unparseable store left untouched, a…bin/fm-test-run.sh tests/fm-agy-harness.test.sh(31 cases, all pass on the target commit)Base-commit regression: restoredbin/fm-spawn.shfrom a09090d and re-ran the same suite; the pooled case fails witherror: refusing to pre-register agy trust: ... is not a worktree of project ...New adversarial casetest_agy_spawn_refuses_to_pre_trust_a_sibling_primary_checkoutdriving fm-spawn.sh with a sibling clone's primary checkout as the acquired pathMutation check: removed the primary-checkout refusal inbin/fm-agy-trust.shand confirmed the adversarial case then fails (helper restored afterwards)Captured the real agysettings.jsonstate and the spawn CLI output for both the pooled and the refused shapesdocs/verification/agy.md:75- Judgment call, applied: the new evidence block in docs/verification/agy.md quoted a one-off PID-derived window name (firstmate:fm-agy-pooled-z15-70118). docs/documentation-audiences.md says one-off process identifiers stay in private task reports by default, while maintainer-verification pages may carry exact output. The surrounding block was already normalized with <tmp> placeholders, so I redacted the identifier to <id> for consistency rather than leaving a literal PID in a tracked page. If the reviewer prefers byte-exact captured output on verification pages, revert that one token.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.