fix(harness): stop BSD basename spraying stderr on the ancestry walk - #846
Open
tkt028 wants to merge 1 commit into
Open
fix(harness): stop BSD basename spraying stderr on the ancestry walk#846tkt028 wants to merge 1 commit into
tkt028 wants to merge 1 commit into
Conversation
ps -o comm= reports a login shell with a leading dash ("-zsh"), and BSD
basename parses that "-z" as an option and fails with "illegal option -- z".
Every harness detection that walks past a login shell therefore writes that to
stderr on macOS/BSD. GNU basename accepts it, so the noise is BSD-only.
This is a DIAGNOSTICS fix, not a behaviour fix — it changes no verdict.
fm-harness.sh runs `set -u` without `set -e`, and fm-spawn.sh invokes it as a
subprocess, so a failed $(basename ...) yields an empty string, matches no case
arm, and the walk continues to the next ancestor. Verified against a faked ps:
a `claude` ancestor above a `-zsh` is still detected.
It is worth fixing anyway because the noise is emitted immediately before
spawn's genuine "no launch template for harness 'unknown'" refusal, and the two
adjacent lines read as cause and effect. Downstream we misdiagnosed exactly
that way; the real cause was mundane and correct — a dispatch from a plain
login shell has no harness anywhere in its ancestry.
Take the command name with parameter expansion instead: ${comm##*/} strips any
directory prefix (what basename gave us) and ${name#-} strips the login-shell
dash. Besides being immune to option parsing, this removes up to 8 subprocess
forks per detection from a path that runs on every spawn and session start.
Adds tests/fm-harness-detect-login-shell.test.sh (6 assertions, registered in
the pure-contract-unit family), which drives a faked ps so an ancestry can be
described independently of the real process tree. It pins both halves — no
stderr noise, AND verdicts unchanged — and is verified to fail without the fix.
tkt028
force-pushed
the
fix/harness-detect-bsd-login-shell-dash
branch
from
July 22, 2026 10:01
4b572c1 to
8ca4404
Compare
4 tasks
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
Make a failed spawn on macOS diagnosable. Today the harness detector emits a spurious
basename: illegal option -- zimmediately above spawn's genuine refusal, and the two adjacentlines read as cause and effect. They aren't related at all — but a reader can't tell that from
the output, so the first thing they investigate is the wrong thing.
This is a diagnostics change. It fixes no behaviour and changes no verdict.
When this bites
Detection short-circuits on Layer 1 env markers, so this never fires when
CLAUDECODE=1(or
PI_CODING_AGENT/GROK_AGENT) is set. It bites when detection falls through to theLayer 2 ancestry walk on a BSD userland:
fm-harness.shorfm-spawn.shfrom a terminalps -o comm=reports a login shell with a leading dash (-zsh), and BSDbasenameparses that-zas an option:GNU
basenameaccepts it, so Linux users never see this and it doesn't show up in CI.Outcome
What a macOS user sees on a refused spawn today:
What they see after this change:
The remaining line is true, actionable, and points at the real fix (set
config/crew-harness,or pass a launch command). The removed line pointed at nothing.
Evidence this is noise-only, not behaviour
Worth stating explicitly, because I originally got this wrong myself and don't want to hand
anyone a rationale I can't back.
fm-harness.shrunsset -uwithoutset -e, andfm-spawn.shinvokes it as asubprocess (
HARNESS=$("$FM_ROOT/bin/fm-harness.sh" crew)), sofm-spawn.sh'sset -eunever propagates in. A failed
$(basename …)yields an empty string, matches nocasearm, andthe walk simply continues to the next ancestor.
Verified against a faked
psso the ancestry could be controlled:-zshonlyunknown— correct, no harness presentbasename: illegal option -- z-zsh→claudeclaude— detected through the dashbasename: illegal option -- zzsh→claudeclaudeRow 2 is decisive: the dash never blocked detection. And row 1 shows
unknownwas the correctanswer — a dispatch from a plain login shell genuinely has no harness in its ancestry.
Why I know the confusion is real, not hypothetical. Downstream we hit exactly this output,
read the two lines as cause→effect, and pursued "BSD
basenamebreaks harness detection" as theroot cause. It isn't. The actual cause was mundane — a crew harness that was never configured,
so detection was consulted at all. The misleading line is what sent the investigation sideways,
and it will do the same to the next person.
Change
Take the command name with parameter expansion instead of
basename(1):Immune to option parsing by construction — there is no argv to misparse. Behaviour is otherwise
deliberately identical: an absolute
commstill reduces to its basename, and the exact-match arm(
pi) still matches exactly.(It also drops one fork per ancestor. Minor — each iteration still forks
pstwice plustr, sothis is roughly a quarter of an already-cheap loop, not a meaningful speedup. Noted for accuracy,
not offered as a reason to merge.)
Tests
New
tests/fm-harness-detect-login-shell.test.sh(6 assertions), registered in thepure-contract-unitfamily. It drives a fakedpsvia the existingfm_fakebinshim so anancestry can be described without depending on the real process tree, and pins both halves —
no stderr noise, and verdicts unchanged:
unknown(no harness in the ancestry)commpath still resolves to its basenamepiarm still matches after stripping-bashis not mistaken for a harnessVerified to fail without the fix — the test is not decorative:
Checks
shellcheck --norcclean on all three touched files (0.11.0, the pinned/CI version)bin/fm-test-run.shon the affected suites —fm-harness-detect-login-shell(6),fm-secondmate-harness(27),fm-secondmate-liveness(10),fm-session-start(20),fm-turnend-guard(40),fm-test-run(10) — 113 ok, 0 failuresfm-backendshows 1 failure (old fm-teardown.sh (scout, report present)—fm-decision-hold: compatible tasks-axi is required, localtasks-axi 0.1.2). It ispre-existing and environmental: reproduced identically with this change reverted.
Tested on macOS (BSD userland), which is where the defect is observable.