fix(bin): reset FM_*_OVERRIDE for every spawned pane - #3700
Open
Valentino-Sole wants to merge 10 commits into
Open
Valentino-Sole wants to merge 10 commits into
Valentino-Sole wants to merge 10 commits into
Conversation
…mate An ordinary ship/scout worker's launch line never cleared FM_ROOT_OVERRIDE/FM_STATE_OVERRIDE/FM_DATA_OVERRIDE/FM_PROJECTS_OVERRIDE/ FM_CONFIG_OVERRIDE - that reset lived only inside the KIND=secondmate branch. A pane that inherits environment from elsewhere in the launching process tree could then carry a foreign home's overrides into the worker's own watcher and fm-*.sh helpers, which then looked at the wrong home (the recurring false WATCHER-DOWN alarms). Hoist the five-variable reset out of the KIND-specific branch so it applies to every spawn regardless of kind, while keeping the FM_HOME redirect (and the secondmate-only extras riding with it) secondmate-exclusive. fm-control.sh relaunch and the bootstrap secondmate-liveness respawn both funnel through this same single LAUNCH-assembly chokepoint in fm-spawn.sh, so both were already covered by the pre-existing KIND=secondmate reset and are now covered unconditionally too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AkAKUTzwUaMkU3gcQZMJsf
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Reviews (2): Last reviewed commit: "no-mistakes(document): document fish out..." | Re-trigger Greptile |
Valentino-Sole
force-pushed
the
fm/fm-spawn-override-reset
branch
from
September 4, 2026 07:31
8689223 to
0284d11
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
Reset FM_ROOT_OVERRIDE, FM_HOME, and FM_STATE_OVERRIDE for every spawned worker pane so child sessions inherit their own home scope instead of the parent home, fixing false WATCHER-DOWN alarms.
What Changed
bin/fm-spawn.shnow prefixes every pane launch line — not justKIND = secondmate— with a reset that leavesFM_ROOT_OVERRIDE,FM_STATE_OVERRIDE,FM_DATA_OVERRIDE,FM_PROJECTS_OVERRIDE, andFM_CONFIG_OVERRIDEgenuinely unset (unset, not an empty assignment prefix, since consumers distinguish the two), so a worker pane can no longer inherit a foreign home's overrides from the launching process tree. The reset is spelled twice — the POSIXunsetplus astatus fish-path-guardedset --erase --global— becauseunsetis not a fish builtin; both spellings discard only stderr and stay statement prefixes so a compound raw launch command runs entirely under the reset. The secondmate-onlyFM_HOMEredirect stays behind it and remains secondmate-exclusive.tests/fm-spawn-override-reset.test.sh, which drives real ship and secondmate spawns against a fake tmux pane, captures the literalsend-keys -lpayload, and replays it through a fake agent that reports its own environment under both the POSIX and fish pane shell families.tests/lib.shgains sharedFM_TEST_SPAWN_RESET_*launch-line literals, and the existing spawn, Kimi, Pi-extension, and secondmate-lifecycle suites were updated for the new prefix (the Pi follow-up e2e now waits for a rendered pane)..gitignoreignores.squish/, withtests/fm-gitignore-config.test.shasserting that.no-mistakes/,.lavish/, and.squish/are ignored as directories and leavegit status --porcelainclean.docs/configuration.mddocuments the reset's scope, its unset-vs-empty semantics, that an operator's universal fish variable (set -Ux) deliberately survives it, and that fish panes print one cosmetic interpreter-path line from the shell probe.Risk Assessment
✅ Low: The change is a well-bounded, unconditional launch-line prefix backed by a genuinely behavioral test (it replays the real captured launch line through an env-reporting fake agent rather than grepping the string), every exact-match assertion site was updated consistently through a single shared constant, and the POSIX pane behavior is directly verified silent and complete; the one residual - whether fish's unknown-command diagnostic is actually suppressed by the
2>/dev/null, which would make the fish assertion at tests/fm-spawn-override-reset.test.sh:258 fail on a developer machine that has fish - was raised in round 5 and explicitly accepted by the author as documented uncertainty.Testing
Completed 1 recorded test check.
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:3105- Intent requires "Reset FM_ROOT_OVERRIDE, FM_HOME, and FM_STATE_OVERRIDE for every spawned worker pane so child sessions inherit their own home scope instead of the parent home", but SPAWN_OVERRIDE_RESET_VARS covers only the five FM__OVERRIDE names; FM_HOME is neither reset nor pinned for ship/scout panes (the FM_HOME redirect at :3070 stays secondmate-only), and tests/fm-spawn-override-reset.test.sh:221 asserts the opposite ("ship spawn must still hand the launching firstmate's FM_HOME to the worker"). This is not just wording: the same failure class stays reachable. bin/fm-wake-lib.sh:7 resolves FM_HOME="${FM_HOME:-${FM_ROOT_OVERRIDE:-$FM_ROOT}}", so an inherited FM_HOME takes precedence and the now-unset FM_ROOT_OVERRIDE changes nothing. Concrete path: bin/backends/tmux.sh:69 starts the shared tmux server from whichever process spawns first, and that server passes its startup environment to every later pane; if a secondmate (FM_HOME=<subhome>) starts it, a ship pane the PRIMARY later spawns inherits FM_HOME=<subhome> and its watcher/fm-.sh helpers read the secondmate's state dir - the WATCHER-DOWN false alarm this change targets. The reverse case is equally reachable: a secondmate spawning a ship worker writes the brief and meta under <subhome>/state (fm-spawn.sh:275), but the pane with FM_HOME unset resolves FM_HOME=FM_ROOT, the main checkout. bin/backends/herdr.sh:1458 already unsets FM_HOME together with the same five overrides when starting its server, for exactly this stated reason, so FM_HOME belongs in this boundary too. A bare unset is not sufficient (it breaks the secondmate-launched ship case); pin FM_HOME=<launching firstmate's resolved home> in the launch line for every kind, the way CLAUDE_CONFIG_DIR is pinned at :3051, with the secondmate redirect overriding it. Please confirm whether omitting FM_HOME was intended before this merges..gitignore:7- Commit 0df6e84 in this branch added .squish/squish.db, a 724 KB SQLite blob, and 22a1719 removed it again, so the working tree is clean but the blob still lives in the branch's commit objects. Recent main history (75b2de2 "fix: copy PR URLs from durable records (fix: copy PR URLs from durable records #3648)") looks squash-merged, which would keep it out of main - but if this branch is ever merged with history preserved, the blob is permanent and only removable by a history rewrite, exactly the hazard tests/fm-gitignore-config.test.sh now documents. Confirm the merge is a squash, or rewrite the branch to drop the blob.bin/fm-spawn.sh:3105- The fish guard is a PATH command lookup, so any executable namedstatuson the pane's PATH that exits 0 makesset --erase ...run in a POSIX pane. Verified locally:dash -c 'unset FOO; set --erase FOO; echo LAUNCHED'prints "set: Illegal option --" and never reaches the echo - dash and /bin/sh abort the whole command line, so the pane would be created with no agent started and read as a wedged worker (bash is benign, rc=2 with a usage message). The failure mode is silent and costs the launch, not just a stray line. A guard that cannot be shadowed by PATH would be safer; note that the obvious alternativetest -n "$FISH_VERSION"is what the csh reasoning in the comment rules out, since csh aborts on an undefined variable.docs/configuration.md:288- The doc claims the reset "takes effect whatever login shell the pane runs", and the comment at bin/fm-spawn.sh:3097 reasons explicitly about keeping a csh pane's launch intact, but in csh/tcshunsetremoves shell variables only - environment variables needunsetenv- so on a csh pane the reset is a silent no-op and the inherited overrides survive exactly as before. bin/backends/tmux.sh:174 does list tcsh|csh as recognized pane shells. Practically the impact is near zero because the pre-existingspawn_send_text_line "$T" "export GOTMPDIR=..."at bin/fm-spawn.sh:3139 is already invalid csh, so a csh pane is not a working pane today. Either drop the csh reasoning and soften the doc claim to the POSIX family plus fish, or add theunsetenvspelling; as written the comment and doc overstate the guarantee.🔧 Fix: no change: FM_HOME redirect intentionally stays secondmate-only
3 issues (1 warning, 2 infos) still open:
bin/fm-spawn.sh:3105- The fish half of the reset usesset --erasewith no scope flag. In fish an unscoped erase removes the variable from the smallest scope in which it is defined, and universal is one of those scopes — universal variables are persisted to ~/.config/fish/fish_variables and shared by every fish session on the machine.FM_ROOT_OVERRIDEis a documented operator-facing override (docs/configuration.md:283, and the env template at docs/configuration.md:796), so a fish operator settingset -Ux FM_ROOT_OVERRIDE /path/to/firstmateis a realistic configuration. Concrete path: that operator spawns any worker; the pane's fish reads the launch line,status fish-pathsucceeds, andset --erase FM_ROOT_OVERRIDE …runs. One of two things then happens, and both are wrong: either the universal variable is the smallest scope holding the name and it is deleted from disk — a silent, cross-session mutation of the operator's own shell config that outlives the pane and breaks every future fish session's root resolution — or a global env-imported copy shadows it, the erase hits only that copy, the exported universal is still in the pane's environment, and the reset silently does not do its job on exactly the shell it was added for. Both outcomes are invisible because stderr is discarded. Spelling itset --erase --global …confines the erase to the scope an inherited environment variable actually lands in; note the tradeoff that a universal-exported override would then survive the reset, which is why this is a scope decision for the author rather than a mechanical fix. The POSIX half is unaffected —unsetin a POSIX shell has no persistent-scope equivalent.tests/fm-spawn-override-reset.test.sh:235-test_fish_pane_launch_line_clears_overridesskips outright when fish is absent, and neither CI lane installs it (.github/workflows/ci.yml runs bare ubuntu-latest / macos-latest; nofishappears anywhere in the workflows). The skip is also invisible to the runner's gate accounting: bin/fm-test-run.sh:1421 only treats askip:line as a gate skip when it is the FIRST non-empty output line, andtest_ship_spawn_clears_overrides_set_in_parent_envprintsok - …before it. So the fish spelling — the half of the fix that carries theset --erasescope risk above and the whole reason the reset is written twice — will report green in CI without ever having run. Either add fish to the portable serial lane, or make the skip a declared gate-skip token so its absence is at least visible.bin/fm-spawn.sh:3104- Recorded for the audit trail, no action expected: the stated intent names "FM_ROOT_OVERRIDE, FM_HOME, and FM_STATE_OVERRIDE", but SPAWN_OVERRIDE_RESET_VARS covers only the five FM_*_OVERRIDE names and FM_HOME is deliberately left inherited for ship/scout panes. The author adjudicated this in the previous round ("Keine Codeaenderung, bewusst so"), and the code, the comment at bin/fm-spawn.sh:3072-3075, docs/configuration.md:288 and tests/fm-spawn-override-reset.test.sh:221 all agree with that decision — it is the intent sentence that is broader than the shipped scope, not the implementation that is inconsistent with itself.🔧 Fix: scope fish override erase to global scope
3 infos still open:
docs/configuration.md:288- The fix round scoped the fish erase toset --erase --global(bin/fm-spawn.sh:3105), which is right for the inherited-environment case but makes the doc's absolute wording no longer true for the one shell it names. In fish, an exported universal variable (set -Ux FM_STATE_OVERRIDE /some/home/state, a documented operator-facing override per docs/configuration.md:283 and the env template at :796) lives in universal scope, is exported to children, and is untouched by a global-scoped erase. Concrete path: a fish operator with that universal set spawns a ship worker; the pane's fish imports the parent's copy as global,set --erase --globalremoves only that global copy, and the still-exported universal value is handed to the agent, so the worker's fm-*.sh helpers resolve /some/home/state. Line 287 ("unsets all five ... in the launch line of every spawned pane") and line 288 ("takes effect whatever login shell the pane runs, including fish") both promise more than the code delivers. The behavior itself is defensible - a universal variable is the operator's own machine-wide config, not a foreign home leaking through the launching process tree, which is the failure class the intent names - so the fix is to the sentence, not the flag. Since it is a deliberate scope tradeoff the author chose in the previous round, confirm the wording before narrowing it.bin/fm-spawn.sh:3105- The 18-line comment above this line explains the double spelling, thestatusguard, why only stderr is discarded, and why both stay statement prefixes - but says nothing about--global, which the fix round added and which is load-bearing in a non-obvious way. Unscoped, fish'sset --erasetargets the smallest scope holding the name, so dropping the flag would let the erase delete a persisted universal variable out of the operator's ~/.config/fish/fish_variables, a cross-session mutation that outlives the pane. In a comment block this dense, an unexplained flag reads as removable noise to the next editor. One clause - global is where fish puts an inherited environment variable, and confining the erase there keeps it from reaching the operator's persisted universal config - would pin the decision.tests/fm-spawn-dispatch-profile.test.sh:134- The exact ~230-character reset prefix is now hardcoded in four test files: tests/fm-spawn-override-reset.test.sh:39 (RESET_PREFIX), tests/fm-kimi-harness.test.sh:208 and :465, tests/fm-spawn-dispatch-profile.test.sh:134 and :387, and a partial copy in tests/fm-secondmate-lifecycle-e2e.test.sh:127. This fix round already had to touch five of those six sites just to add one word (--global), which is the drift cost showing up in practice: a site missed in a future edit fails with a full-string diff that says nothing about which token moved. Hoisting the literal into one shared constant in tests/lib.sh (a plain string constant, not something derived by reading bin/fm-spawn.sh) and referencing it from all six keeps the exact-launch-line assertions intact while making the next spelling change a one-line edit.🔧 Fix: document fish --global scope and share test reset literal
4 infos still open:
bin/fm-spawn.sh:3113- The POSIX half of the reset carries no stderr redirection:unset $SPAWN_OVERRIDE_RESET_VARS;runs first on every pane, andunsetis not a fish builtin, so a fish pane prints fish's unknown-command diagnostic (command name plus the caret-underlined source line) into the pane on every single spawn, before thestatus fish-pathguard is even reached. The comment block directly above claims the cost on a fish pane is "one printed path" (fromstatus fish-path's stdout) and "costs no pane its launch" - the launch part is right, the noise accounting is not: it is that path plus a multi-line error, on exactly the shell the second spelling was added to support.tests/fm-spawn-override-reset.test.sh:test_posix_pane_reset_is_quiet_and_completeasserts quietness only for sh/dash/bash, andtest_fish_pane_launch_line_clears_overridesasserts nothing about pane output, so nothing in the suite contradicts the comment. Spelling itunset $SPAWN_OVERRIDE_RESET_VARS 2>/dev/null;silences it and stays csh-parseable (one redirection, not the "second redirection" the comment rules out) - though it does not help csh, whereunset ... 2would then complain about a numeric variable name on stdout. Since the comment reasons explicitly about what gets discarded and why, confirm the noise tradeoff was intended rather than changing it silently.bin/fm-spawn.sh:3147- Bounding what the new fish spelling actually buys, in case the doc wording is read more broadly than intended. Two sibling text lines are sent into the same pane just before the launch line and are still POSIX-only:spawn_send_text_line "$T" "export GOTMPDIR=$TASK_TMP/gotmp"(:3147) andspawn_send_text_line "$T" "export TRACEPARENT=$SPAWN_TRACEPARENT"(:3152). fish has noexportbuiltin - it answersexport FOO=barwith an "Unsupported use of '='" error and sets nothing - so on a fish pane the worker's agent and itsgo build/go testchildren never receive GOTMPDIR, and TRACEPARENT is never set (which incidentally makes the pre-existing POSIX-onlyunset TRACEPARENTat :3115/:3154/:3162 harmless on fish rather than a second leak). Net effect: this change makes the FM_*_OVERRIDE reset fish-correct, which is a real improvement, but a fish pane is still not a fully working pane. docs/configuration.md:288 only claims the reset works on fish, so it is accurate as written; flagging so the fish half is not mistaken for general fish pane support. No change requested inside this change's scope.bin/fm-spawn.sh:3112- Audit trail only, no action expected - re-verified against the current code, unchanged since the author adjudicated it in round 1 ("Keine Codeaenderung, bewusst so"). The stated intent names "FM_ROOT_OVERRIDE, FM_HOME, and FM_STATE_OVERRIDE", but SPAWN_OVERRIDE_RESET_VARS covers only the five FM_*_OVERRIDE names; FM_HOME is neither unset nor pinned for ship/scout panes, and the FM_HOME redirect at bin/fm-spawn.sh:3070 remains secondmate-only. The implementation, the comment at :3075-3076, docs/configuration.md:290 and tests/fm-spawn-override-reset.test.sh ("ship spawn must still hand the launching firstmate's FM_HOME to the worker") are all mutually consistent with the author's decision - it is the intent sentence that is broader than the shipped scope, not the code that is inconsistent with itself..gitignore:7- Recorded so the author sees the branch's real blast radius: the pipeline's fix round (commit 22a1719) added.squish/to the repository-wide .gitignore and 39 lines of new coverage in tests/fm-gitignore-config.test.sh, neither of which relates to the FM_*_OVERRIDE reset this branch is about. It was self-remediation for the fixer's own accidental commit of a 724 KB SQLite memory database in 0df6e84. The hygiene itself is sound and the tests are behavioral (they invokegit check-ignoreandgit status --porcelainagainst a real seeded repo rather than grepping the .gitignore text), so nothing here is wrong - but a branch named fm/fm-spawn-override-reset now also changes repo-wide ignore policy for a tool not every contributor runs. Related history finding was already reviewed and dismissed by the author in round 1.🔧 Fix: silence POSIX override unset on fish panes
1 warning still open:
bin/fm-spawn.sh:3116- The newest fix-round commit (674896c, "silence POSIX override unset on fish panes") adds2>/dev/nullto the POSIX half of the reset and rewrites the comment (:3105-3109) to claim that "Every command in the reset discards its own stderr ... without those redirections a fish pane would take fish's unknown-command diagnostic on every spawn". That claim is very likely false for fish, and I could not verify it here: no fish is installed in this worktree environment (command -v fishfinds nothing), and CI installs none either (the round-2 finding on that was reviewed and dismissed), so nothing has ever executed this path. Source-level reasoning: a POSIX shell reports a missing command as part of executing that command, so its "command not found" IS covered by the command's own2>/dev/null- that is exactly why thestatus fish-path 2>/dev/nullguard is silent on sh/dash/bash, and tests/fm-spawn-override-reset.test.sh:test_posix_pane_reset_is_quiet_and_complete confirms it there. fish is different: it resolves the command name during job planning, before the job's redirections are established, and when resolution fails it firesfish_command_not_foundand then emits a parser backtrace (fish: Unknown command: unsetplus the caret-underlined source line) on the shell's own stderr, not on the job's redirected fd. If that holds, the added redirection changes nothing on a fish pane and the diagnostic still lands there on every spawn - and the unredirectedunset TRACEPARENT;prepended at :3118/:3157/:3165 (pre-existing) would print a second one on every relaunch regardless. Concrete failure this creates: tests/fm-spawn-override-reset.test.sh:256-259 now assertswith = withoutfor the fish replay, so on any developer machine that HAS fish the suite fails with "the reset wrote its own diagnostic into a fish pane", while CI stays green because the test skips at :233. Before merging, run that one test on a real fish (fish 3.4+) - it is precisely the right check. If it fails, either revert the2>/dev/nullon the POSIX unset and restore the previous comment wording (accepting the noise, as the pre-existingunset TRACEPARENTlines already do), or gate the POSIX unset behind a guard fish fails silently on; do not leave the comment, docs, and test asserting a silence the shell does not actually provide.🔧 Fix: no change: fish unset redirect accepted as-is
2 issues (1 warning, 1 info) still open:
tests/fm-secondmate-lifecycle-e2e.test.sh:128- The fix round replaced the old positive assertion (assert_grep 'FM_CONFIG_OVERRIDE=') withassert_no_grep "FM_CONFIG_OVERRIDE=$HOME_DIR/parent-config", but that pattern can never match the form fm-spawn.sh actually emits, so the guard can never fire. Concrete trace:assert_no_grepisgrep -F -- "$1"(tests/lib.sh:323), i.e. an exact fixed string, and every path-valued env prefix in fm-spawn.sh goes throughshell_quote(bin/fm-spawn.sh:1216-1220), which unconditionally wraps the value in single quotes -- see bin/fm-spawn.sh:3051 (CLAUDE_CONFIG_DIR=$(shell_quote ...)) and :3070 (FM_HOME=$sq_home). So a regression that carried the parent's config override into the pane would logFM_CONFIG_OVERRIDE='/tmp/.../main home/parent-config', never the unquotedFM_CONFIG_OVERRIDE=/tmp/.../main home/parent-configthe pattern demands. The sibling line 127 in the same block proves the convention: it assertsFM_HOME='$SUB_ABS'WITH the quotes, and passes. Net effect: line 128 passes unconditionally today and would keep passing if the leak it names were reintroduced. Real coverage for the reset comes only from line 128's neighbour,assert_grep "$FM_TEST_SPAWN_RESET_POSIX". Fix is mechanical: quote the path in the pattern (FM_CONFIG_OVERRIDE='$HOME_DIR/parent-config') so it matches the emitted spelling.bin/fm-spawn.sh:3116- Audit-trail record only, no action expected -- re-verified against the current code and unchanged since you adjudicated it in round 1 ("Keine Codeaenderung, bewusst so") and again in round 4. The stated intent names "FM_ROOT_OVERRIDE, FM_HOME, and FM_STATE_OVERRIDE", but SPAWN_OVERRIDE_RESET_VARS (bin/fm-spawn.sh:3115) covers only the five FM_*_OVERRIDE names; FM_HOME is neither unset nor pinned for ship/scout panes, and the FM_HOME redirect at :3070 remains secondmate-only. The implementation, the comment at :3078-3080, docs/configuration.md:290 and tests/fm-spawn-override-reset.test.sh:219 ("ship spawn must still hand the launching firstmate's FM_HOME to the worker") are all mutually consistent with that decision -- it is the intent sentence that is broader than the shipped scope, not the code that is inconsistent with itself. Recorded because intent conformance is a standing check, not because anything changed.🔧 Fix: make parent config-override leak assertion non-vacuous
2 infos still open:
bin/fm-spawn.sh:3115- Standing intent-conformance record, no action expected - re-verified against the current code and unchanged since you adjudicated it in round 1 ("Keine Codeaenderung, bewusst so") and again in rounds 4 and 6. The stated intent names "FM_ROOT_OVERRIDE, FM_HOME, and FM_STATE_OVERRIDE", but SPAWN_OVERRIDE_RESET_VARS covers only the five FM_*_OVERRIDE names; FM_HOME is neither unset nor pinned for ship/scout panes, and the FM_HOME redirect at bin/fm-spawn.sh:3070 remains secondmate-only. I re-checked the sibling paths this round for a reachable inversion of the failure and found none: the one in-repo caller that spawns with non-default overrides set is bin/fm-remote-secondmate-control.sh:195-199, and that is a --secondmate spawn whose launch line pins FM_HOME to the same TARGET_HOME the FM_CONFIG_OVERRIDE pointed at, so the pane resolves the identical config/state dirs before and after this change. The implementation, the comment at :3068-3076, docs/configuration.md:290 and tests/fm-spawn-override-reset.test.sh:219 all agree with your decision - it is the intent sentence that is broader than the shipped scope, not the code that is inconsistent with itself.tests/fm-spawn-override-reset.test.sh:4- The new file's header attributes the FM_*_OVERRIDE vocabulary toAGENTS.md "Layout and state", but AGENTS.md section 2 does not mention FM_ROOT_OVERRIDE, FM_STATE_OVERRIDE, FM_DATA_OVERRIDE, FM_PROJECTS_OVERRIDE or FM_CONFIG_OVERRIDE at all (grep over AGENTS.md returns nothing for_OVERRIDE). That section explicitly delegates: "docs/configuration.md is the single owner of the top-level operational-home layout and configuration schemas" (AGENTS.md:50), and docs/configuration.md:286-290 is in fact where all five are defined and where this change documents the reset. A reader following the citation lands on a section that owns FM_HOME only and will not find the contract the test claims to anchor to. Point the header at docs/configuration.md instead; purely a comment fix, no behavior involved.⏭️ **Test** - skipped
bin/fm-test-run.sh --changed --exclude-family real-herdr-gated🔧 Fix: wait for rendered pane in Pi follow-up e2e
1 error still open:
bin/fm-test-run.sh --changed --exclude-family real-herdr-gateddocs/configuration.md:288- docs/configuration.md states the FM_*_OVERRIDE reset "takes effect both in POSIX pane shells and in fish" without qualification, but the fish half is gated onstatus fish-path, which fish only grew in 3.0. On a fish 2.x pane the probe fails, the erase never runs, and the reset is a silent no-op. I left the sentence unqualified deliberately: fish 2.x predates 2018 and a version caveat would be noise for every operator, and the underlying question (whether the probe should tolerate older fish) is a behavior decision, not a documentation one. Flagging it so the choice is visible rather than assumed.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.