Skip to content

fix(bin): point seeded remote secondmate charter at its host-local steering inbox - #2

Merged
Freudator86 merged 13 commits into
mainfrom
fm/remote-secondmate-routing-vanilla-freudator-v2
Sep 21, 2026
Merged

Freudator86 merged 13 commits into
mainfrom
fm/remote-secondmate-routing-vanilla-freudator-v2

Conversation

@Freudator86

Copy link
Copy Markdown
Owner

Intent

Fix vanilla remote secondmate steering so the throwaway remote secondmate can actually receive and act on routed requests.
Coditan reported that the remote secondmate launched but refused its first message because its seeded charter kept the parent's steering inbox path while the doorbell named the guest inbox.
This is critical path before real secondmate conversions.
Do not hand-patch the remote home to make a false pass; install/test the vanilla behavior and fix the upstream-suitable path.

What Changed

  • bin/fm-remote-home-seed.sh now rewrites the parent's $STATE/<id>.inbox path in the remote charter copy to $REMOTE_HOME/state/parent-route/<id>.inbox, in addition to the existing status-path rewrite. That is the same inbox that fm-remote-secondmate-control.sh writes routed records into and rings the doorbell for, so the remote mate now reads the inbox that actually receives its requests.
  • tests/fm-remote-secondmate-lifecycle-e2e.test.sh now asserts that the seeded charter names the host-local steering inbox and not the parent's. It also restores an old-style charter that still names the parent inbox, re-runs fm-remote-home-seed.sh on the same route, and asserts that this republishes the corrected inbox path.
  • docs/remote-secondmates.md names the state/parent-route/<id>.inbox steering inbox and says the seeded charter points at that same inbox. It also notes that re-running fm-remote-home-seed.sh republishes the charter into an existing home.

🤖 Generated with Claude Code

Risk Assessment

✅ Low: Small, well-bounded fix that makes the seeded remote charter name the exact steering inbox that the control script writes to and rings the doorbell for; an end-to-end test runs the real seed script and checks the charter it writes.

Testing

An earlier attempt of this phase, driven against the authorized probe install on ak-secondmate, covered all five scenarios through the real seed, spawn, send and teardown scripts. Base commit dee119b published an inbox under the parent's /tmp home, which does not exist on the host. Reseeding at ad500bf fixed that same home without hand edits. A fresh seed named the inbox under state/parent-route/. The routed fm-send record landed in exactly that inbox, and the real Claude mate moved it to handled/ and appended a reply with the matching corr token (LIVEPROOF-01M31), which reached the parent status stream. This run re-checked over SSH that the entrypoint symlink is restored to firstmate-routing-vanilla, the probe dirs are gone, the vanilla root is unchanged and has no uncommitted changes, and the worker and ordinary pane are unaffected. The earlier attempt's readiness doctor returned ok. The focused lifecycle e2e test passes at HEAD and fails at the base seed on the new inbox assertion. No UI surface is involved, so the evidence is CLI transcripts, not screenshots.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Seeding a vanilla remote secondmate publishes a charter whose instruction inbox is the remote home's state/parent-route/<id>.inbox (not the parent's state/<id>.inbox) ✅ pass live live/07-fresh-seed-ad500bf.txt, live/08-fresh-charter-on-host.txt (0 parent-home paths in the published charter)
A routed fm-send request lands as a durable record in the exact inbox the charter tells the mate to read ✅ pass live live/13-fm-send.txt (exit 0), live/14-record-handled-reply.txt (corr=609fd3ad172c8aeb under the charter-named inbox)
Adversarial: the base-commit seed script reproduces the reported mismatch (charter keeps the parent inbox) ✅ pass live live/03-seed-base-dee119b.txt, live/04-base-charter-on-host.txt (charter names /tmp/.../parent/state/probe-oldseed.inbox, which does not exist on the host); lifecycle-e2e-base-seed.log fails on the ne…
Reseeding an existing home seeded with the old charter corrects the inbox without hand-patching the home ✅ pass live live/05-reseed-head-ad500bf.txt, live/06-reseed-charter-corrected.txt (same home, charter hash changed, 0 parent paths left). The first attempt failed because a worker from the ordinary route's root r…
A real remote secondmate (Claude pane on an SSH host) receives the doorbell and acts on the first routed message instead of refusing it ✅ pass live live/15-remote-pane-capture.txt, live/14-record-handled-reply.txt (001.msg moved to handled/, reply 'done [corr=609fd3ad172c8aeb] ... LIVEPROOF-01M31'), live/16-parent-reply-mirror.txt (pending-reply…
After the probe, the ordinary route is preserved: the entrypoint symlink is restored to firstmate-routing-vanilla and readiness is ok ✅ pass live live/18-entrypoint-restored.txt, live/19-host-cleanup.txt, live/20-ordinary-readiness.txt, plus this run's SSH re-check (symlink restored, probe dirs gone, vanilla root 4612388 clean, only pane w1:p2…
Evidence: Live probe evidence index

Source: Live probe evidence index

# Live proof at ad500bf on ak-secondmate (option B, fresh probe root)

Host `ak-secondmate` (account `fmremote`), driven over real SSH through the supported
`fm-remote-home-seed.sh` / `fm-spawn.sh` / `fm-send.sh` / `fm-teardown.sh` entrypoints.
Parent home: throwaway `FM_HOME=/tmp/fm-live-probe-01M31/parent`, removed afterwards; the
real parent home was not written to. Only the probe route ids `probe-oldseed` and
`probe-ak-fresh` were used. The ordinary `throwaway-ak-vanilla` route, home, charter and
pane `w1:p2` were not touched.

| # | File | Shows |
|---|------|-------|
| 00 | 00-entrypoint-original.txt | original symlink target recorded; vanilla root at 4612388, clean |
| 01 | 01-probe-root-created.txt | probe root ~/firstmate-probe-ad500bf at ad500bf (from a git bundle) |
| 02 | 02-entrypoint-repointed.txt | symlink repointed to the probe root for the bounded test |
| 03-04 | base seed + charter | **Scenario 3 (adversarial), LIVE:** base dee119b seed publishes the parent's `/tmp/.../state/probe-oldseed.inbox`, which does not exist on the host |
| 05-06 | reseed + charter | **Scenario 4, LIVE:** reseeding the same home with ad500bf republishes `~/fm-home-probe-old/state/parent-route/probe-oldseed.inbox`, with 0 parent paths left and no hand edits. Attempt 1 failed because a worker from the ordinary route's root replaced the probe worker; attempt 2 succeeded. |
| 07-08 | fresh seed + charter | **Scenario 1, LIVE:** a brand-new home's charter names `state/parent-route/probe-ak-fresh.inbox` |
| 09-11 | spawn, arm | real Claude pane w3:p2 launched. Arming failed first because the sandbox state dir was 0775 (setup mistake); `arm` succeeded after chmod 700 |
| 12-14 | send + record | **Scenario 2, LIVE:** fm-send exit 0; the record corr=609fd3ad172c8aeb landed in exactly the charter's inbox |
| 14-15 | handled + pane | **Scenario 5, LIVE:** the mate moved 001.msg to handled/ and appended `done [corr=609fd3ad172c8aeb] ...: LIVEPROOF-01M31` |
| 16 | parent mirror | reply ingested into the parent status stream; pending-reply phase=resolved |
| 17 | teardown | probe-ak-fresh retired via fm-teardown (probe-oldseed was never launched and had no task record, so its home was removed after checking its marker) |
| 18-19 | restore + cleanup | symlink restored to ~/firstmate-routing-vanilla/bin/fm-remote-entrypoint.sh; probe root and homes removed; vanilla root at 4612388, clean; ordinary home intact |
| 20 | ordinary readiness | read-only doctor through the ordinary route: `ok: remote second-mate readiness confirmed`; worker running from firstmate-routing-vanilla |
Evidence: Base-commit seed publishes the parent inbox (adversarial)

Source: Base-commit seed publishes the parent inbox (adversarial)

\### Charter PUBLISHED ON THE HOST by the base-commit (dee119b) seed, instruction-inbox section:
# Firstmate instruction inbox
Firstmate steers you through durable message files in '/tmp/fm-live-probe-01M31/parent/state/probe-oldseed.inbox'.
When a terminal message says an instruction is waiting there - and at any natural checkpoint when you are unsure - list '/tmp/fm-live-probe-01M31/parent/state/probe-oldseed.inbox'/*.msg, read and act on each message in numeric order, then acknowledge each handled message by moving it: `mv '/tmp/fm-live-probe-01M31/parent/state/probe-oldseed.inbox'/NNN.msg '/tmp/fm-live-probe-01M31/parent/state/probe-oldseed.inbox'/handled/`.
The move IS the acknowledgement: without it firstmate rings again and eventually treats you as stuck. An empty or absent inbox needs no action.

# Escalation to main firstmate
--- parent-home paths in charter:
2
--- does that path exist on the host?
ls: cannot access '/tmp/fm-live-probe-01M31/parent/state/probe-oldseed.inbox': No such file or directory
--- the inbox fm-send delivers to (remote route):
ls: cannot access '~/fm-home-probe-old/state/parent-route/probe-oldseed.inbox': No such file or directory
9830194054e2f21a1890179d644ebd120adf9ed26948fb95b41e44f193129924  ~/fm-home-probe-old/data/charter.md
Evidence: Reseed corrects the old charter

Source: Reseed corrects the old charter

\### Same home, charter after reseeding with ad500bf (no file on the host was edited by hand):
# Firstmate instruction inbox
Firstmate steers you through durable message files in '~/fm-home-probe-old/state/parent-route/probe-oldseed.inbox'.
When a terminal message says an instruction is waiting there - and at any natural checkpoint when you are unsure - list '~/fm-home-probe-old/state/parent-route/probe-oldseed.inbox'/*.msg, read and act on each message in numeric order, then acknowledge each handled message by moving it: `mv '~/fm-home-probe-old/state/parent-route/probe-oldseed.inbox'/NNN.msg '~/fm-home-probe-old/state/parent-route/probe-oldseed.inbox'/handled/`.
The move IS the acknowledgement: without it firstmate rings again and eventually treats you as stuck. An empty or absent inbox needs no action.

# Escalation to main firstmate
--- parent-home paths left in charter:
0
c1baa74a28a658bb468ac28a1d3347ecae33f2e8eef4a7598fceba8599f974a0  ~/fm-home-probe-old/data/charter.md
Evidence: Fresh seed charter on host

Source: Fresh seed charter on host

\### Parent brief (source of truth) names the PARENT inbox:
42:Firstmate steers you through durable message files in '/tmp/fm-live-probe-01M31/parent/state/probe-ak-fresh.inbox'.

\### Charter published into the brand-new remote home ~/fm-home-probe:
# Firstmate instruction inbox
Firstmate steers you through durable message files in '~/fm-home-probe/state/parent-route/probe-ak-fresh.inbox'.
When a terminal message says an instruction is waiting there - and at any natural checkpoint when you are unsure - list '~/fm-home-probe/state/parent-route/probe-ak-fresh.inbox'/*.msg, read and act on each message in numeric order, then acknowledge each handled message by moving it: `mv '~/fm-home-probe/state/parent-route/probe-ak-fresh.inbox'/NNN.msg '~/fm-home-probe/state/parent-route/probe-ak-fresh.inbox'/handled/`.
The move IS the acknowledgement: without it firstmate rings again and eventually treats you as stuck. An empty or absent inbox needs no action.

# Escalation to main firstmate
--- parent-home paths left in charter:
0
--- parent-replies channel:
22:Nobody reads this chat: the captain and the main firstmate see only what is appended to '~/fm-home-probe/state/parent-replies.status', and a captain-facing sentence that is not appended there has not been sent.
49:   `echo "{state} [at=<epoch>]: {one short line}" >> '~/fm-home-probe/state/parent-replies.status'`
Evidence: fm-send record landed, handled, and replied to

Source: fm-send record landed, handled, and replied to

\### Charter (published on host) names this steering inbox:
durable message files in '~/fm-home-probe/state/parent-route/probe-ak-fresh.inbox'

\### Remote inbox tree after fm-send (records + handled/):
~/fm-home-probe/state/parent-route/probe-ak-fresh.inbox
./handled/001.msg
--- ./handled/001.msg
schema=fm-task-inbox.v1
at=2026-09-21T08:09:07Z
--
[fm-from-firstmate]⁣corr=609fd3ad172c8aeb Routing proof LIVEPROOF-01M31: reply with exactly one short line that contains the token LIVEPROOF-01M31 and nothing else.

\### Remote parent channel (the mate's reply log):
done [corr=609fd3ad172c8aeb] [at=1789978162]: LIVEPROOF-01M31 (via-helper)

\### Parent pending-reply record:
corr_id=609fd3ad172c8aeb
task_id=probe-ak-fresh
phase=awaiting_report
resolved_epoch=
resolved_via=
delivered_epoch=1789978149

\### Parent status stream:
cat: /tmp/fm-live-probe-01M31/parent/state/probe-ak-fresh.status: No such file or directory
Evidence: Remote Claude pane capture acting on the request

Source: Remote Claude pane capture acting on the request

  '~/fm-home-probe/state/parent-route/pr
  obe-ak-fresh.inbox'/*.msg and, in numeric order,
  read and act on each, then mv each handled file to
  '~/fm-home-probe/state/parent-route/pr
  obe-ak-fresh.inbox'/handled/.

  Read 1 file, ran 3 shell commands

● Reply appended with the correlation token intact.
  Now acknowledging the handled instruction message.

  Ran 1 shell command

● Done — inbox is empty (only handled/ remains). Per
  charter, going idle now and waiting silently for the
  next routed request.

✻ Crunched for 20s · done 8:09 AM

──────────────────────────────────────────────────────
❯
──────────────────────────────────────────────────────
  ⏵⏵ bypass permissions on (shift+tab to cycle) · ←…
Evidence: Reply mirrored to parent; pending-reply resolved

Source: Reply mirrored to parent; pending-reply resolved

$ FM_HOME=/tmp/fm-live-probe-01M31/parent bin/fm-procevent.sh start remote-reply-probe-ak-fresh   # one-shot run of the reply source the sandbox has no watcher for
autohandled: remote-reply-probe-ak-fresh
cannot retire terminal source; it remains registered: remote-reply-probe-ak-fresh
captured: /tmp/fm-live-probe-01M31/parent/state/procevent-inbox/remote-reply-probe-ak-fresh.1.result
start exit: 0

\### Parent status stream:
done [corr=609fd3ad172c8aeb] [at=1789978162]: LIVEPROOF-01M31 (via-helper)
\### Parent pending-reply record:
corr_id=609fd3ad172c8aeb
phase=resolved
resolved_epoch=1789978189
resolved_via=helper
Evidence: Entrypoint restored and ordinary readiness ok

Source: Entrypoint restored and ordinary readiness ok

$ bin/fm-on.sh throwaway-ak-vanilla fm-remote-doctor.sh   # ordinary route record (root ~/firstmate-routing-vanilla), read-only check
mode=check
path=~/firstmate-routing-vanilla/bin:~/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
entrypoint=yes
platform=linux
required git=/usr/bin/git
required jq=/usr/bin/jq
required herdr=/usr/local/bin/herdr
required tasks-axi=/usr/local/bin/tasks-axi
required treehouse=/usr/local/bin/treehouse
required harness=claude:/usr/local/bin/claude
optional tmux=absent
optional no-mistakes=/usr/local/bin/no-mistakes
optional gh=/usr/local/bin/gh
check herdr=ok: /usr/local/bin/herdr
check gui-session=skip: no Aqua login session applies on linux
check remote-job-worker=ok: the Linux remote job worker is running
check remote-job-worker-loaded=skip: Aqua launch agents do not apply on linux
check remote-job-probe=ok: the remote job worker completed the required-tool probe
check launchagent=skip: launch agents apply only on darwin
check launchagent-scope=skip: launch agents apply only on darwin
check launchagent-loaded=skip: launch agents apply only on darwin
check herdr-server=ok: session fm-remote is running
check entrypoint-link=ok: ~/.local/bin/fm-remote-entrypoint.sh
ok: remote second-mate readiness confirmed on this host
doctor exit: 0
2862549 Mon Sep 21 08:10:29 2026 /bin/bash ~/firstmate-routing-vanilla/bin/fm-remote-job-worker.sh --serve
~/firstmate-routing-vanilla/bin/fm-remote-entrypoint.sh
Evidence: Lifecycle e2e at HEAD (rerun)

Source: Lifecycle e2e at HEAD (rerun)

ok - overlapping remote home provisioning serializes through publication and rollback
ok - remote seed rollback preserves serialized competing routes
ok - unknown readiness preserves its route and brief for reconciliation
ok - remote seeding checks, repairs, and re-checks readiness, then stops on a remaining gap
ok - remote seeding proceeds once the repair closes every gap
ok - remote seeding provisions a supplied origin without touching the primary project tree
ok - remote provisioning re-validates a supplied origin at the receiving host
ok - seeding carries bitbucket, self-hosted, and scp-like origins through to the remote clone
ok - remote seed registers the route and provisions the whole home and project clone on that host
ok - remote inheritance rejects incomplete and superseded payload generations
ok - mixed local and remote routes validate without migration
ok - remote spawn launches on the remote-local backend and records a host-qualified route
ok - legacy and mismatched remote endpoints fail closed before backend access
ok - non-herdr remote endpoints are refused without changing either route
ok - remote spawn serializes inheritance through launch publication
cannot retire terminal source; it remains registered: remote-reply-ios
ok - marked send and routed reply complete through the existing parent correlation owner
cannot retire terminal source; it remains registered: remote-reply-ios
ok - partial remote inheritance retains reread intent through bootstrap convergence
ok - config push and bootstrap serialize remote inheritance convergence
cannot retire terminal source; it remains registered: remote-reply-ios
ok - remote inherited config retains and retries a failed live reread nudge
cannot retire terminal source; it remains registered: remote-reply-ios
cannot retire terminal source; it remains registered: remote-reply-ios
cannot retire terminal source; it remains registered: remote-reply-ios
ok - fleet snapshot projects mixed local and remote structured state
ok - remote update imports and fast-forwards the persistent home on its configured host
ok - the remote restart verb delegates to the host-local control plane and refuses before stopping anything
ok - startup repairs remote readiness before probing without relaunching
ok - the host-local state read steps around a stale shadowing herdr client
ok - startup reports alive legacy backends without changing their routes
ok - unreachable no-ledger remote state remains explicit with no local respawn or failover
cannot retire terminal source; it remains registered: remote-reply-ios
ok - remote retirement refuses child work, then removes only its own endpoint while a shared-session sibling survives
ALL TESTS PASSED
Evidence: Lifecycle e2e with base seed (fails on inbox assertion)

Source: Lifecycle e2e with base seed (fails on inbox assertion)

ok - overlapping remote home provisioning serializes through publication and rollback
ok - remote seed rollback preserves serialized competing routes
ok - unknown readiness preserves its route and brief for reconciliation
ok - remote seeding checks, repairs, and re-checks readiness, then stops on a remaining gap
ok - remote seeding proceeds once the repair closes every gap
ok - remote seeding provisions a supplied origin without touching the primary project tree
ok - remote provisioning re-validates a supplied origin at the receiving host
ok - seeding carries bitbucket, self-hosted, and scp-like origins through to the remote clone
not ok - remote charter did not use its host-local steering inbox
- Outcome: 🔧 1 issue found → no changes applied ✅ across 2 runs (18m43s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

🔧 **Test** - 1 issue found → no changes applied ✅
  • ⚠️ live validation verdict: inconclusive (0 of 5 scenarios were driven live against the product); untested: Seeding a vanilla remote secondmate publishes a charter whose instruction inbox is the remote home's state/parent-route/<id>.inbox (not the parent's state/<id>.inbox), A routed fm-send request lands as a durable record in the exact inbox the charter tells the mate to read, Adversarial: the base-commit seed script reproduces the reported mismatch (charter keeps the parent inbox), Reseeding an existing home seeded with the old charter corrects the inbox without hand-patching the home, A real remote secondmate (Claude pane on an SSH host) receives the doorbell and acts on the first routed message instead of refusing it
  • Live validation: ⚠️ inconclusive - 0 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Seeding a vanilla remote secondmate publishes a charter whose instruction inbox is the remote home's state/parent-route/<id>.inbox (not the parent's state/<id>.inbox) ⏸️ untested no The earlier payload did not establish a live result. The real fm-remote-home-seed.sh ran only over the test's fake-SSH fixture, not against a real SSH host. A live run needs a disposable SSH alias wit…
A routed fm-send request lands as a durable record in the exact inbox the charter tells the mate to read ⏸️ untested no The earlier payload did not establish a live result. fm-send and remote control ran with SSH transport replaced by the deterministic fixture. A live run needs a disposable SSH-reachable host.
Adversarial: the base-commit seed script reproduces the reported mismatch (charter keeps the parent inbox) ⏸️ untested no The earlier payload did not establish a live result. The regression was reproduced only over the fake-SSH test fixture, not against a real remote host.
Reseeding an existing home seeded with the old charter corrects the inbox without hand-patching the home ⏸️ untested no The earlier payload did not establish a live result. The reseed ran only over the fake-SSH fixture. A live run needs a disposable SSH alias with an existing remote home.
A real remote secondmate (Claude pane on an SSH host) receives the doorbell and acts on the first routed message instead of refusing it ⏸️ untested no No SSH-reachable throwaway host is available to this agent: ssh localhost was refused (no sshd), and the configured SSH aliases are production fleet hosts. To drive it, provide a disposable SSH alia…
  • bash tests/fm-remote-secondmate-lifecycle-e2e.test.sh at head (full remote lifecycle over the deterministic SSH boundary: seed, reseed of an existing home, launch, fm-send into the remote inbox, retire)
  • Same lifecycle test in a /tmp copy with bin/fm-remote-home-seed.sh reverted to base dee119b, to reproduce the reported bug
  • Instrumented /tmp copy of the lifecycle test that dumped the seeded remote charter's inbox/status lines and the remote state/parent-route/ios.inbox/*.msg records right after fm-send delivered
  • ssh -o BatchMode=yes localhost true to check for a safe real SSH target (connection refused)

🔧 No changes applied.
✅ Re-checked - no issues remain.

  • Live validation: ✅ go - 6 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Seeding a vanilla remote secondmate publishes a charter whose instruction inbox is the remote home's state/parent-route/<id>.inbox (not the parent's state/<id>.inbox) ✅ pass live live/07-fresh-seed-ad500bf.txt, live/08-fresh-charter-on-host.txt (0 parent-home paths in the published charter)
A routed fm-send request lands as a durable record in the exact inbox the charter tells the mate to read ✅ pass live live/13-fm-send.txt (exit 0), live/14-record-handled-reply.txt (corr=609fd3ad172c8aeb under the charter-named inbox)
Adversarial: the base-commit seed script reproduces the reported mismatch (charter keeps the parent inbox) ✅ pass live live/03-seed-base-dee119b.txt, live/04-base-charter-on-host.txt (charter names /tmp/.../parent/state/probe-oldseed.inbox, which does not exist on the host); lifecycle-e2e-base-seed.log fails on the ne…
Reseeding an existing home seeded with the old charter corrects the inbox without hand-patching the home ✅ pass live live/05-reseed-head-ad500bf.txt, live/06-reseed-charter-corrected.txt (same home, charter hash changed, 0 parent paths left). The first attempt failed because a worker from the ordinary route's root r…
A real remote secondmate (Claude pane on an SSH host) receives the doorbell and acts on the first routed message instead of refusing it ✅ pass live live/15-remote-pane-capture.txt, live/14-record-handled-reply.txt (001.msg moved to handled/, reply 'done [corr=609fd3ad172c8aeb] ... LIVEPROOF-01M31'), live/16-parent-reply-mirror.txt (pending-reply…
After the probe, the ordinary route is preserved: the entrypoint symlink is restored to firstmate-routing-vanilla and readiness is ok ✅ pass live live/18-entrypoint-restored.txt, live/19-host-cleanup.txt, live/20-ordinary-readiness.txt, plus this run's SSH re-check (symlink restored, probe dirs gone, vanilla root 4612388 clean, only pane w1:p2…
  • Live probe on ak-secondmate (option B, fresh probe root ~/firstmate-probe-ad500bf, throwaway FM_HOME=/tmp/fm-live-probe-01M31/parent): bin/fm-remote-home-seed.sh from base dee119b, then reseed of the same home at ad500bf, then fresh seed at ad500bf
  • FM_HOME=... bin/fm-spawn.sh probe-ak-fresh --secondmate (real Claude pane w3:p2), bin/fm-procevent-remote-reply.sh arm, bin/fm-send.sh fm-probe-ak-fresh &#39;Routing proof LIVEPROOF-01M31 ...&#39;, bin/fm-procevent.sh start remote-reply-probe-ak-fresh, bin/fm-teardown.sh probe-ak-fresh
  • Restored ~/.local/bin/fm-remote-entrypoint.sh to point at firstmate-routing-vanilla and ran the read-only bin/fm-on.sh throwaway-ak-vanilla fm-remote-doctor.sh
  • Re-checked over SSH: the symlink target, that the probe dirs are gone, that the vanilla root is at 4612388 with no changes, the job worker process, and the herdr pane list
  • bash tests/fm-remote-secondmate-lifecycle-e2e.test.sh at HEAD (pass), plus the earlier run against the base-commit seed (fails on the new inbox assertion)
✅ **Document** - passed

✅ No issues found.

⚠️ **Lint** - 1 warning
  • ⚠️ linter found issues (exit code 1)
✅ **Push** - passed

✅ No issues found.

…failing test was tests/fm-remote-transport-lanes.test.sh (family=secondmate, the 1 failure of 2 in that family); it died with ".../remote-root/bin/fm-git-code-root-lib.sh: No such file or directory" at the control-state case. Root cause: the fixture builds a synthetic remote code root by copying an explicit list of bin/ scripts (tests/fm-remote-transport-lanes.test.sh:50). This branch added `. "$SCRIPT_DIR/fm-git-code-root-lib.sh"` to bin/fm-remote-secondmate-control.sh:72, but the new library was not added to that list, so the control script aborted at source time inside the fixture root. Fix (one line): stage bin/fm-git-code-root-lib.sh with the other libraries the fixture copies (tests/fm-remote-transport-lanes.test.sh:59). No production code changed. Verification run locally: fm-remote-transport-lanes reproduced the exact CI failure before the edit and reports ALL TESTS PASSED after; fm-remote-job (the other secondmate test in that shard), fm-remote-home-provision, fm-secondmate-sync, fm-remote-secondmate-parent-binding and fm-remote-code-root-ownership all pass; bin/fm-lint.sh on the changed file is clean. bin/fm-remote-home-provision.sh is the only other consumer of the new library and no test stages it into a synthetic bin tree, so no other fixture needed the same entry
@Freudator86
Freudator86 merged commit f2a9301 into main Sep 21, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants