Repository navigation
fix(bin): resolve backend adapter sibling libs when sourced under zsh - #6279
Closed
tuprogramadorfav wants to merge 3 commits into
Closed
tuprogramadorfav wants to merge 3 commits into
tuprogramadorfav wants to merge 3 commits into
Conversation
|
tuprogramadorfav
force-pushed
the
fm/fm-backend-zsh-split
branch
from
October 2, 2026 04:46
a1d859d to
4d49ced
Compare
Author
|
@kunchenguid this PR comes from a fork, so its workflow runs are waiting on maintainer approval and no CI job has run yet. Could you approve the runs when you have a moment, and merge if they come back green? The branch has no conflicts with |
Author
|
Closing, I will not be following up on this one. |
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
"When doing bug fixes ... Apply that same high standard to engineering excellence: lint, test failures, and test flakiness. If you see one, even if it is not caused by what you are working on right now, still get it fixed." (standing instruction)
Context: the fm-captain-hold-cross-home worker found that tests/fm-backend.test.sh fails its zsh case on main. In bin/fm-backend.sh, fm_backend_source loops over an unquoted $siblings list, which zsh does not word-split, so sourcing the backend adapters (herdr) fails under zsh.
What Changed
bin/backends/{cmux,herdr,orca,zellij}.sh) and the shared libs (bin/fm-tmux-lib.sh,bin/fm-agent-process-lib.sh,bin/fm-session-lock-lib.sh) now find their own directory with${BASH_SOURCE[0]:-$0}. zsh does not setBASH_SOURCE, so before this change, sourcingbin/fm-backend.shfrom zsh printed errors and could not load the sibling libraries. The adapters compute their root without acaseinside command substitution, and the libs pick the directory with acaseon whether the path contains/.test_backend_source_shell_portableintests/fm-backend.test.shnow runs under both zsh and bash (FM_TEST_BASHcan override the bash binary). For each backend (tmux, herdr, zellij, orca, cmux), it checks thatfm_backend_sourceloads the adapter and its sibling-lib functions without printing anything, and that an unknown backend is rejected. The existing zsh check that PATH stays intact is kept./bin/bash(3.2) and/bin/zsh, and fails unless all threeok -lines appear (zsh, bash 3.2, zsh PATH).🤖 Generated with Claude Code
Risk Assessment
✅ Low: The change is limited to seven own-directory lookups plus one test and one CI step. Probes showed all five adapters load with their sibling libraries under zsh and stock /bin/bash 3.2, and the expected count of 3 matches the three pass sites when /bin/zsh is present.
Testing
I compared sourcing results across shells at HEAD and at base, driven from a different working directory, for all 5 backends under zsh, /bin/bash 3.2 and bash 5. I ran 48 edge cases per shell: sourcing inside a function, relative paths, cd before loading, a repo path containing spaces, and sourcing herdr.sh, orca.sh, fm-tmux-lib.sh and fm-agent-process-lib.sh directly. All were clean. In a guarded fm-lab-* Herdr session I drove the herdr adapter's send and capture against a real pane from all three shells, and showed base under zsh half-loading. I ran the real fm-peek.sh entrypoint against a disposable lab FM_HOME under /bin/bash, bash 5 and zsh, and tore the lab down. I ran the new regression test against the base tree (exit 1) and at HEAD (pass), and replayed the macos-stock-bash CI step exactly (count 3, exit 0). tests/fm-backend.test.sh passed 31/31 under both bashes. Under /bin/bash 3.2, the cmux (61/61) and herdr (227/227) adapter tests pass. Orca and zellij each have one failure, both the already-ignored host issue where tasks-axi is missing. A real tmux pane could not be driven because tmux is not installed. This is a shell-library change with no UI, so the evidence is CLI transcripts, not screenshots.
Evidence: Sourcing matrix at HEAD (zsh / bash 3.2 / bash 5 x 5 backends)
Source: Sourcing matrix at HEAD (zsh / bash 3.2 / bash 5 x 5 backends)
Evidence: Sourcing matrix at pre-fix base f593060 (zsh half-load reproduced)
Source: Sourcing matrix at pre-fix base f5930603 (zsh half-load reproduced)
Evidence: Adversarial sourcing edge cases at HEAD (48 cases, all clean)
Source: Adversarial sourcing edge cases at HEAD (48 cases, all clean)
Evidence: Live Herdr lab: adapter send/capture from zsh/bash3.2/bash5, base zsh failure, fm-peek.sh via three shells
Source: Live Herdr lab: adapter send/capture from zsh/bash3.2/bash5, base zsh failure, fm-peek.sh via three shells
Evidence: Regression test fails on base, CI macos-stock-bash step replay passes (count 3)
Source: Regression test fails on base, CI macos-stock-bash step replay passes (count 3)
Evidence: tests/fm-backend.test.sh under /bin/bash 3.2
Source: tests/fm-backend.test.sh under /bin/bash 3.2
Evidence: tests/fm-backend.test.sh under bash 5
Source: tests/fm-backend.test.sh under bash 5
Evidence: tests/fm-backend-cmux.test.sh under /bin/bash 3.2 (61/61)
Source: tests/fm-backend-cmux.test.sh under /bin/bash 3.2 (61/61)
Evidence: tests/fm-backend-orca.test.sh under /bin/bash 3.2 (38 ok, 1 known tasks-axi host failure)
Source: tests/fm-backend-orca.test.sh under /bin/bash 3.2 (38 ok, 1 known tasks-axi host failure)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ No issues found.
.github/workflows/ci.yml:511- The step that round 2's fix added to the macos-stock-bash job will always fail. It requires exactly 2ok -lines fromFM_TEST_ONLY=test_backend_source_shell_portable FM_TEST_BASH=/bin/bash /bin/bash tests/fm-backend.test.sh, but on macos-latest that test prints 3. The job's PATH (/bin:/usr/bin:...) contains/bin/zsh, which macOS always ships, so all three pass sites run: the zsh leg of the shell loop (tests/fm-backend.test.sh:531), the /bin/bash leg of the same loop (tests/fm-backend.test.sh:531), and the zsh PATH-intact block (tests/fm-backend.test.sh:546).grep -c '^ok - 'returns 3,[ 3 -eq 2 ]is false, and the step exits 1. If any assertion failed,failexits 1 and the step'sset -eaborts it anyway, so no outcome passes. Round 2's fix introduced this; it is not a sibling left behind. Remedy: expect 3 in ci.yml:511 and fix the message at ci.yml:512 to match. Add a short comment that macOS ships /bin/zsh, so this step also runs the zsh legs. That is useful, because it is the only CI leg where zsh is known to exist.🔧 Fix applied.
✅ Re-checked - no issues remain.
🔧 **Test** - 2 issues found ✅
tests/fm-backend-orca.test.sh- Local setup issue, not caused by this change. 'Orca scout teardown should succeed once report exists' (tests/fm-backend-orca.test.sh) and 'fm-teardown should succeed for a zellij scout whose worktree is already gone' (tests/fm-backend-zellij.test.sh) fail identically under /bin/bash 3.2 and Bash 5. The refusal is 'fm-captain-hold: compatible tasks-axi is required ... REFUSED: scout task ... has not passed the captain-call completion gate', andtasks-axiisn't on PATH on this host. Neither the failing code path (fm-captain-hold) nor the tests are part of this change, and installing the tool system-wide is outside this phase's boundary. Put a compatible tasks-axi on PATH to run these two tests locally; CI should cover them.bin/fm-composer-lib.sh:214- Outside this change's scope, for awareness. The zsh contract (from fix: make backend matching shell-portable #230 and this fix) covers recognizing and loading backends. Under zsh, loading and the send/capture functions now work against a real Herdr pane. But some runtime functions still use bash-only code that predates this change, so they fail when called from zsh.fm_backend_herdr_composer_statefails with 'bad substitution' infm_composer_normalize_spaces_var(${!1}andprintf -vat bin/fm-composer-lib.sh:214).fm_backend_herdr_version_checkfails with 'read-only variable: status' at bin/backends/herdr.sh:528. Every product entrypoint is a#!/usr/bin/env bashscript and works from zsh, as the fm-peek scenario shows, so only direct interactive zsh calls are affected.patharray is not clobbered and the caller's positional args surviveset --inside fm_backend_source; loading works from another cwd, inside a function, via relative p…fm-captain-hold: compatible tasks-axi is required.tasks-axiisn't on PATH on this host, it isn't reposit…/bin/zsh,/bin/bash(3.2.57) and Bash 5.3:cd $ROOT && source bin/fm-backend.sh && fm_backend_source <tmux|herdr|zellij|orca|cmux|bogus>, capturing rc, stderr, sibling-lib functions defined and whethercommand -v dirnamestill worksSamefm_backend_source herdrcheck on base aedb7bbf (zsh) and round-1 4ebc5b4b (/bin/bash), extracted withgit archiveinto a temp dirFM_TEST_ONLY=test_backend_source_shell_portable bash tests/fm-backend.test.shat HEADFM_TEST_ONLY=test_backend_source_shell_portable FM_TEST_BASH=/bin/bash /bin/bash tests/fm-backend.test.sh(the new CI macos-stock-bash step; ok-count must be 2) at HEADHEAD's strengthened test file run against aedb7bbf bin/ and 4ebc5b4b bin/ (must fail)Edge cases in all three shells: absolute path from cwd=/, sourcing inside a function,./fm-backend.shfrom bin/, cd away beforefm_backend_source, sourcingbin/backends/herdr.shdirectly, comparing PATH before and after, keeping caller$@, and checkingFM_BACKEND_HERDR_ROOTequals the repo rootbin/fm-herdr-lab.sh name zshsrc+provision+run <s> workspace create(isolated Herdr session fm-lab-zshsrc-58392-31225)zsh -f:fm_backend_source herdr,fm_backend_herdr_send_text_line,fm_backend_herdr_capture,fm_backend_herdr_composer_stateagainst the real lab pane; same under /bin/bash and on the base/round-1 trees for contrastbin/fm-lab-home.sh create $LAB+state/zshprobe.meta(backend=herdr), thenFM_HOME=$LAB bin/fm-peek.sh zshprobe 4via /bin/bash, Bash 5, and launched fromzsh -fbin/fm-herdr-lab.sh teardown(tripwire check passed; default session still running),rm -rfof the lab home and temp treesFM_TEST_BASH=<sh> <sh> tests/fm-backend{,-orca,-cmux,-zellij,-herdr}.test.shfor /bin/bash 3.2 and Bash 5 (cmux passed in both, fm-backend passed under Bash 5, orca and zellij failed one tasks-axi-gated teardown test each in both, herdr unfinished)Confirmation reruns, unfinished at handoff:FM_TEST_BASH=/bin/bash /bin/bash tests/fm-backend.test.shalone, andtests/fm-backend-orca.test.shon the base commit✅ No issues found.
matrix.sh <worktree> HEAD: fm_backend_source {tmux,herdr,zellij,orca,cmux} under /bin/zsh, /bin/bash 3.2, bash 5.3 from cwd=/, checking rc, stderr, sibling-lib functions and PATHmatrix.sh <git-archive f5930603> BASE: same matrix on the pre-fix tree, reproducing the zsh half-loadEdge cases under each shell: source+load inside a function, relative ./fm-backend.sh then cd /, herdr.sh sourced directly and from its own dir, fm-tmux-lib.sh, fm-agent-process-lib.sh and orca.sh sourced directly, worktree and path-with-spaces copies (48 cases)bin/fm-herdr-lab.sh name/provision/run workspace create/teardownfm-lab-zshlive-* session: fm_backend_herdr_send_text_line plus fm_backend_herdr_capture against a real pane from/bin/zsh -f,/bin/bash3.2, bash 5, plus base under zshbin/fm-lab-home.sh create $LAB+ state/zshprobe.meta (backend=herdr):bin/fm-peek.sh zshprobe 4via /bin/bash, bash 5, and a zsh shell running the shebangFM_TEST_ONLY=test_backend_source_shell_portable FM_TEST_BASH=/bin/bash /bin/bash tests/fm-backend.test.shagainst the base tree (expect fail, exit 1)Replay of the ci.yml macos-stock-bash step underenv -i PATH=/bin:/usr/bin:/usr/sbin:/sbin /bin/bash -e(portable_count=3)/bin/bash tests/fm-backend.test.shandbash tests/fm-backend.test.sh(31/31 each)/bin/bash tests/fm-backend-{orca,cmux,zellij,herdr}.test.sh✅ **Document** - passed
✅ No issues found.
✅ No issues found.
✅ **Push** - passed
✅ No issues found.
✅ No issues found.