feat(bin): add a single owner for verified harness launch commands - #1080
feat(bin): add a single owner for verified harness launch commands#1080sbracewell64 wants to merge 10 commits into
Conversation
A fleet launcher will soon open PRIMARY firstmate sessions alongside the crewmate sessions fm-spawn.sh opens, so both need the same verified launch commands. Today that knowledge lives only inside bin/fm-spawn.sh, and the drift a second copy causes is not hypothetical: a downstream registry hand-copied claude's command as `claude --dangerously-skip-permissions`, dropping CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false - the ghost-text suppression that keeps firstmate from reading predicted-prompt text as real typed input when it captures a pane. Extract launch_template, model_flag_for_harness, and effort_flag_for_harness (plus the shell_quote both flag resolvers depend on) into a new sourced bin/fm-launch-lib.sh, and have fm-spawn.sh source it. Every crewmate, scout, and secondmate template is byte-identical to before, so spawn behavior is unchanged on all six verified adapters. launch_template also gains a `primary` kind for the launcher. A primary session has no task, no worktree, no brief, and no status file, so it launches bare and is greeted by the session-start adapters already installed in the home; each primary template keeps its adapter's verified autonomy flag and claude's ghost-text prefix. An unrecognized kind still resolves to the crewmate shape, and an unverified adapter still returns non-zero for every kind. tests/fm-launch-lib.test.sh pins both arms directly, including a proof that fm-spawn.sh redefines none of the functions and that no other script under bin/ hand-writes a launch command. Existing suites that read the template bytes now read them from their new owner.
…ighten launch-lib ownership
|
CI verification available. Cross-fork PRs here do not run workflows without maintainer approval, so this PR shows no checks. The repository's own |
|
Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#1080 at |
|
Automated reminder: this PR still looks blocked on a rebase or merge conflict fix. If you are still interested, please rebase onto the current base branch, resolve the conflict, and push. If I do not hear back, I may close this as inactive. |
Intent
Give firstmate's harness launch knowledge exactly one owner, as a pure refactor with zero behavior change.
Background: firstmate is gaining a second caller of its launch knowledge - a fleet launcher that opens a PRIMARY firstmate session, alongside bin/fm-spawn.sh which opens crewmate sessions. Today that knowledge lives only inside bin/fm-spawn.sh. The drift this prevents already happened once: an external platform hand-copied Claude's launch command and dropped the CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false ghost-text suppression variable, which firstmate would otherwise read as real typed input when it captures a pane. One owner, or it happens again.
What was done: extracted launch_template, model_flag_for_harness, and effort_flag_for_harness out of bin/fm-spawn.sh into a new sourced bin/fm-launch-lib.sh, and had fm-spawn.sh source it. No copy of those three functions remains in fm-spawn.sh; the library is their single definition.
Deliberate decision the captain specified up front, not a free choice made during implementation: launch_template additionally gains a 'kind' axis distinguishing 'primary' from the existing crewmate shape, because a primary session has no task, no worktree, no brief, and no status file. The primary branch was added while keeping every existing crewmate call path byte-identical in behavior - a crewmate spawn on every verified harness must compose exactly the command it composes today, ghost-text variable included. The second consumer (sibling task fm-launch-menu, blocked on this one) is already designed against this exact shape, so the axis shape is intentional and any alternative shaping would have required escalation rather than a local judgment call.
Also deliberate: the launcher itself is explicitly out of scope and is not built here. bin/fm-brief.sh, bin/backends/herdr.sh, bin/fm-backend.sh, bin/fm-merge-local.sh, and bin/fm-ff-lib.sh were left untouched because other workers were concurrently live in those files.
Testing: a colocated regression test covers the extracted library directly, including the new primary kind, and proves the crewmate templates are unchanged. The existing spawn test suite passes untouched.
Repo conventions applied per firstmate's coding guidelines: shellcheck-clean bin scripts, one sentence per line in prose, plain dashes, colocated tests, no agent co-author on commits.
This is a relaunch for publication only. The implementation already passed review, tests, documentation, and lint in a prior pipeline run; that run failed solely at the push step because the GitHub account had pull-only access to the upstream repository. That is now cleared: pushes are routed to the sbracewell64/firstmate fork while fetches still track upstream, so the resulting pull request into kunchenguid/firstmate is expected to be a cross-fork PR.
Two review findings from the prior run were escalated and decided by the project owner; both decisions are already committed on this branch, so they are deliberate and should not be re-flagged:
The opencode primary template uses the full verified briefless shape - the OPENCODE_CONFIG_CONTENT allow-permission JSON plus
opencode --auto, not--prompt. The crewmate template keeps--promptbecause it has a brief to pass; a primary has none. The empirical evidence CONTRIBUTING.md:50 requires is tests/fm-opencode-primary-live-e2e.test.sh:256 and :310, which both launch a primary opencode TUI exactly that way, and it is cited in the code comment.Kimi binary resolution (resolve_kimi_binary) deliberately stays private to bin/fm-spawn.sh and was NOT extracted. The planned second consumer, fm-launch-menu, reaches Kimi through the pi harness rather than a native kimi binary, so it will never call it and there is no hand-copy drift to prevent; extracting it would have expanded a pure refactor to serve a consumer that will not exist. That rationale is recorded as a comment at the KIMIBIN placeholder so it is not re-raised, to be revisited only if a native kimi launch ever becomes a launcher entry.
Also already applied: the placeholder contract now lives in bin/fm-launch-lib.sh's own header (fm-spawn.sh points at it), AGENTS.md section 4 attributes the launch flags and unverified-adapter guard to bin/fm-launch-lib.sh, and the one-owner test guard in tests/fm-launch-lib.test.sh covers every per-harness autonomy marker with its fail-open
|| trueremoved.Publication routing note: the gate is configured with fork = sbracewell64/firstmate, so branches push to that fork while the pull request opens against kunchenguid/firstmate. A cross-fork PR is the expected and correct outcome here.
What Changed
launch_template,model_flag_for_harness, andeffort_flag_for_harness(plus theshell_quotehelper they depend on) out ofbin/fm-spawn.shinto a new sourcedbin/fm-launch-lib.sh, which is now their single definition;fm-spawn.shsources it and keepsresolve_kimi_binaryprivate, and the placeholder contract moved into the library's own header. Crewmate, scout, and secondmate launch commands are byte-identical to before.launch_templategained akindaxis with a newprimaryarm for briefless primary sessions on claude, codex, opencode, pi, and grok, while kimi returns non-zero forprimaryso the guard refuses instead of emitting an unsubstitutable command. Each arm cites its in-repo evidence, the header records a consumer obligation to disclose the permission-bypass posture of every primary template that carries one, and the library distinguishes "unverified adapter" from "verified adapter, unsupported kind" as separate refusal causes.tests/fm-launch-lib.test.shpinning every crewmate and primary template plus a one-owner guard that fails if a launch command is hand-written elsewhere inbin/, mapped the new file intobin/fm-test-run.shchange-based selection, and repointed launch-command ownership inAGENTS.md,CONTRIBUTING.md,docs/configuration.md,docs/scripts.md, and theharness-adaptersskill atbin/fm-launch-lib.sh.Risk Assessment
✅ Low: This round changes only comments, it correctly resolves the prior finding by grounding pi's posture in SKILL.md:272 and widening the consumer obligation to all five primaries rather than exempting one, every citation verifies, and the crewmate call paths remain byte-identical to the base commit.
Testing
I exercised the extraction end to end rather than only through unit assertions: the new tests/fm-launch-lib.test.sh, the touched kimi/pi/captain-translation contract tests, and the three spawn suites all pass, and on top of that I built a differential harness that compares base commit a5fe1bc against HEAD across 438 fully substituted launch commands (zero differences) and a real-script end-to-end run where bin/fm-spawn.sh at each commit types its launch line into a recording tmux (byte-identical for all five task harnesses). The new primary kind was demonstrated as the fleet launcher will consume it, including kimi's refusal and the fail-closed unverified-adapter guard still firing from the real script, and five planted mutations confirmed the one-owner guard and the template pins actually catch drift including the exact historical ghost-text omission. No visual artifact applies - this change is shell library code whose entire end-user surface is the composed launch command string, which the CLI transcripts capture directly. The only failure seen was one node-driven pi watch-extension assertion that reproduces unchanged at the base commit.
Evidence: base vs HEAD launch command differential (438 combinations, 0 differences) + the new primary kind
combinations compared (harness x kind x model x effort, fully substituted): 438 RESULT: 0 differences. Every composed launch command is byte-identical. --- ghost-text suppression survived the extraction (the drift this refactor exists to prevent) --- claude ship carries CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false claude scout carries CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false claude secondmate carries CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false claude primary carries CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false NEW 'primary' KIND: what the fleet launcher will get from the one owner claude CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false claude --dangerously-skip-permissions --model 'opus' --effort 'high' codex codex --model 'opus' -c 'model_reasoning_effort="high"' --dangerously-bypass-approvals-and-sandbox opencode OPENCODE_CONFIG_CONTENT='{"permission":{"*":"allow"}}' opencode --model 'opus' --auto pi pi --model 'opus' --thinking 'high' grok grok --trust --always-approve --model 'opus' --reasoning-effort 'high' kimi REFUSED (exit 1, no output) - not a verified primary harness --- unverified adapter still refused for every kind (the fail-closed guard) --- kind=ship refused (exit 1) kind=scout refused (exit 1) kind=secondmate refused (exit 1) kind=primary refused (exit 1)Evidence: end-to-end: the literal command the real fm-spawn.sh types into the crewmate pane, base vs HEAD
--- claude ------------------------------------------------------------- HEAD b08b230 (bin/fm-launch-lib.sh): CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false claude --dangerously-skip-permissions --model 'opus' --effort 'high' "$('<FM_ROOT>/bin/fm-operational-input.sh' encode launch-brief < '<RUN>/home/data/<TASK>/brief.md')" base a5fe1bc (pre-extraction fm-spawn.sh): IDENTICAL --- codex ------------------------------------------------------------- HEAD b08b230 (bin/fm-launch-lib.sh): codex --model 'opus' -c 'model_reasoning_effort="high"' --dangerously-bypass-approvals-and-sandbox -c "notify=["bash","-c","touch '<RUN>/home/state/<TASK>.turn-ended'"]" "$('<FM_ROOT>/bin/fm-operational-input.sh' encode launch-brief < '<RUN>/home/data/<TASK>/brief.md')" base a5fe1bc (pre-extraction fm-spawn.sh): IDENTICAL --- opencode ---------------------------------------------------------- base a5fe1bc: IDENTICAL --- pi ---------------------------------------------------------------- base a5fe1bc: IDENTICAL --- grok -------------------------------------------------------------- base a5fe1bc: IDENTICAL RESULT: real spawned launch lines are byte-identical at base and HEAD --- fail-closed unverified-adapter guard, still enforced through the sourced library --- $ fm-spawn.sh <task> <project> not-a-harness error: unknown harness 'not-a-harness'; pass a raw launch command to use an unverified adapterEvidence: mutation check: the one-owner guard and template pins catch all five planted drifts
--- mutation 1: a second bin/ consumer hand-copies claude's command --- not ok - a launch command is hand-written outside bin/fm-launch-lib.sh ('--dangerously-skip-permissions'): bin/fm-launch-menu.sh --- mutation 2: fm-spawn.sh keeps its own copy of launch_template --- not ok - bin/fm-spawn.sh defines launch_template again; bin/fm-launch-lib.sh is the single owner --- mutation 3: the grok primary template loses --trust --- not ok - launch_template grok primary drifted: expected: grok --trust --always-approve MODELFLAG____EFFORTFLAG got: grok --always-approve MODELFLAG____EFFORTFLAG --- mutation 4: the opencode primary reverts to the crewmate --prompt shape --- not ok - launch_template opencode primary drifted: expected: ... opencode MODELFLAG--auto got: ... opencode MODELFLAG--prompt --- mutation 5: a shipped crewmate template drifts (claude loses the prefix) --- not ok - launch_template claude ship drifted not ok - existing launch template changed: (tests/fm-kimi-harness.test.sh byte pin) RESULT: all five mutations are caught; the guard and the pins are load-bearing.Evidence: reproducible differential harness (base vs HEAD launch commands)
Evidence: reproducible end-to-end spawn harness
Evidence: changed-file test selection now includes tests/fm-launch-lib.test.sh
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 4 issues found → auto-fixed (4) ✅
bin/fm-launch-lib.sh:83- The new grokprimarytemplate isgrok --always-approve __MODELFLAG____EFFORTFLAG__, dropping--trust. Every other owner of grok primary knowledge says that flag is load-bearing: README.md:96 documents the primary launch asgrok --trust, README.md:105 says "--trustis needed once per clone so project hooks and the turn-end guard load", docs/turnend-guard.md:63 repeats it, and .agents/skills/harness-adapters/SKILL.md:345 states that without folder trust "this primary guard fails open". The empirical evidence for a grok PRIMARY launch is tests/fm-grok-continuity-live-e2e.test.sh:76, which launches it asgrok --trust --always-approve --reasoning-effort low- the same class of citation the author correctly used to justify opencode's--autoshape. A launcher inheriting this template on a not-yet-trusted clone silently loses the "no turn ends blind" backstop, which is precisely the hand-copied-command-drops-a-flag failure this whole change exists to prevent. Counter-argument worth the author's call: trust is granted once per clone, so an already-trusted captain home would not notice, and--trustmay be considered setup rather than launch knowledge - hence asking rather than fixing. tests/fm-launch-lib.test.sh:90 currently pins the trustless shape, so it would need updating too.bin/fm-launch-lib.sh:86-launch_template kimi primaryreturns 0 with__KIMIBIN__ __MODELFLAG__--auto, but README.md:61 lists only Claude Code, Grok, Pi, Codex, and OpenCode as verified primary harnesses (docs/configuration.md:177 explicitly defers the narrower primary set to README), and__KIMIBIN__is resolvable only inside bin/fm-spawn.sh by design. The result is the one primary arm that cannot produce a runnable command for any consumer other than fm-spawn.sh - and fm-spawn.sh never passes kind=primary (KIND is only ship|scout|secondmate at bin/fm-spawn.sh:145,172,173). A fleet launcher enumerating verified adapters and callinglaunch_template "$h" primarywould get a literal__KIMIBIN__ --autostring instead of the clean non-zero refusal the unverified-adapter guard gives everywhere else, and tests/fm-launch-lib.test.sh:91 pins that shape. This is a separate question from the already-decided "resolve_kimi_binary stays private" call: given that decision, the consistent shape is for the primary kind toreturn 1for kimi (matching kimi's absence from the supported primary set), so the guard refuses rather than emitting an unsubstitutable command. Flagging for the author because making launch_template total across all six verified adapters may itself be the intended contract.tests/fm-launch-lib.test.sh:243- The one-owner guard's--auto([^-a-z]|$)marker greps all ofbin/and fails if any file other than fm-launch-lib.sh matches.--autois a common flag outside launch commands (gh pr merge --autois the obvious candidate for the existing bin/fm-pr-*.sh scripts), so an unrelated future change would trip "a launch command is hand-written outside bin/fm-launch-lib.sh" with a misleading message. The guard's own self-check only proves the pattern still matches the library, not that it is specific to a launch command. Anchoring it to its adapter context (e.g.opencode [^']*--autoand__KIMIBIN__ [^']*--auto, or--auto'$) keeps the hand-copy detection while removing the false positive. The other five markers are already adapter-specific enough not to have this problem.bin/fm-launch-lib.sh:26-shell_quoteis a general-purpose helper, not launch knowledge, but it now lives in the launch library. bin/fm-spawn.sh calls it from several non-launch sites (lines 1253, 1273, 1355-1360, 1372), so sourcing fm-launch-lib.sh is silently load-bearing for code paths unrelated to launching; bin/fm-brief.sh:102 and bin/fm-supervision-instructions.sh:94 still carry their own copies, so this is now the third definition in bin/. The header comment already acknowledges the placement, and the intent explicitly excludes fm-brief.sh from this change, so noting only - a shared quoting lib would be the natural follow-up once those files are free.🔧 Fix: add grok --trust, refuse kimi primary, pin every primary shape
3 issues (1 warning, 2 infos) still open:
bin/fm-launch-lib.sh:90- Raising this for escalation exactly as the owner's instruction fix(bin): coalesce watcher signals into one wake #4 directed ("where a change would alter the AUTONOMY or PERMISSION posture of a primary session ... do NOT silently change it. Raise it as a finding"). The claude primary (line 90) carries --dangerously-skip-permissions and the codex primary (line 95) carries --dangerously-bypass-approvals-and-sandbox, both inherited from the crewmate command, and the author's own arm comments now state the repo has no interactive-primary evidence for either. I swept every in-repo use and confirm that: README.md:90 documents the primary launch as bareclaude; the only claude launch carrying the flag is tests/fm-claude-stop-autoarm-live-e2e.test.sh:115 (claude -p ..., headless print mode), matching docs/arm-pretool-check.md:201, docs/cd-guard.md:158, and docs/subagent-guard.md:248 which are all-ptoo; every codex use (tests/fm-codex-continuity-live-e2e.test.sh:40-42, docs/arm-pretool-check.md:202, docs/cd-guard.md:159, docs/subagent-guard.md:185, docs/verification/supervision.md:17) iscodex exec, headless. No doc anywhere states the primary session's permission posture. A COUNTER-ARGUMENT the arm comments miss and that likely settles it: this library's own header (line 38) defines thesecondmatekind as "a firstmate PRIMARY launched in a provisioned secondmate home", and the shipped, byte-pinned secondmate templates (lines 142 and 146) launch that interactive primary firstmate session with exactly these two flags. That is real in-repo evidence for an interactive primary shape. The distinction left for the owner is that a secondmate is an unattended firstmate while the fleet launcher's primary is the captain's own attended session, so the flags may or may not belong. Decide and record it; the pins at tests/fm-launch-lib.test.sh:94 and :105 currently freeze the inherited shape either way.bin/fm-launch-lib.sh:32- The function contract still reads "Returns 1 for a harness with no verified adapter - that non-zero return is the unverified-adapter guard every caller relies on". After this round that is incomplete: kimi IS a verified adapter (its crewmate template is live at line 170 and fm-spawn.sh depends on it) yet line 125 now returns 1 for kind=primary. A caller cannot distinguish "unverified adapter" from "verified adapter, unsupported kind", and bin/fm-spawn.sh:437/441 hardcode the first reading in their error text ("unknown harness '$HARNESS'; pass a raw launch command to use an unverified adapter"). fm-spawn never passes kind=primary so nothing misreports today, but the fleet launcher this library exists to serve would tell a user kimi is an unverified adapter and point them at the raw-launch escape hatch, when the real reason is that kimi is deliberately outside the verified primary set. Extend the header sentence to cover both refusal reasons so the next consumer writes the right message.bin/fm-launch-lib.sh:73- The new header sentence asserts unconditionally that "Every primary template below is the shape this repo empirically verified for a briefless PRIMARY launch, not the crewmate command with its brief argument subtracted". Two of the five arms directly beneath it say the opposite: line 84-89 records that for claude "the repo pins the prefix but not this flag's place in an interactive primary", and line 91-94 records that for codex "No in-repo primary codex TUI launch exists to pin" with the flag carried over from the crewmate command. In the file that is now the single owner of launch knowledge, a header making an unqualified verification claim that its own arms disclaim is the same knowledge-drift risk this change exists to close - a future reader trusting the header would treat the claude and codex primary shapes as empirically settled. Qualify it (e.g. "each arm cites its evidence, and where the repo has none the arm says so explicitly"), which the arms already support.🔧 Fix: record primary autonomy evidence and consumer obligation
1 warning still open:
bin/fm-launch-lib.sh:91- The new CONSUMER OBLIGATION enumerates the primary templates whose posture a consumer must disclose: "the claude and codex primary templates launch a session that runs with NO permission prompts, and the opencode primary template allows every permission outright". Four of the five primary templates carry a permission-bypass flag, not three - the grok primary at line 158 isgrok --trust --always-approve ..., and .agents/skills/harness-adapters/SKILL.md:304 defines --always-approve as "auto-approves every tool execution, verified to run fully unattended", explicitly equating it with--permission-mode bypassPermissions. That is the same no-permission-prompt posture the obligation exists to disclose. (pi at line 152 is correctly absent - it carries no autonomy flag.) Because the obligation is worded as binding and enumerative, a consumer implementing it literally would surface the posture for claude, codex, and opencode and silently ship grok's, which defeats the point of putting the obligation in the one owner. The same omission shows in the arm comments: the claude arm (lines 121-123) and codex arm both point back at the CONSUMER OBLIGATION, the grok arm does not. This is mechanical to close and matches the author's evident intent - the owner's instruction named only claude and codex, and the author already generalized it to opencode unprompted, so grok is the same generalization.🔧 Fix: bind consumer obligation to any bypass flag, add grok
1 warning still open:
bin/fm-launch-lib.sh:167- The new justification for excluding pi from the CONSUMER OBLIGATION is contradicted by the repo's own verified adapter knowledge. Lines 165-167 assert "--approve is part of that scaffolding, and leaving it out is why pi is the one primary template the header's CONSUMER OBLIGATION does not catch: a pi primary still prompts", and line 176 in the header repeats "a pi primary still prompts". But .agents/skills/harness-adapters/SKILL.md:272 states flatly: "Pi has no permission system, so crewmates are always autonomous." If pi has no permission system, a pi primary does not prompt - the correct reason pi is excluded is that there is no permission gate to bypass and therefore nothing for a consumer to disclose, not that the template withholds a bypass flag. The conclusion (exclude pi) is right; only the recorded reason is wrong. Two concrete harms, both the exact drift class this library exists to close. First, this file is now the designated single owner of launch knowledge, and it records a per-harness permission fact that its own skill contradicts. Second, the wording actively invites the next maintainer to "fix" it: read against the header's rule, "a pi primary still prompts" reads as pi missing an autonomy flag its siblings have, and the obvious next edit is to add --approve to the template - a silent permission-posture change of exactly the kind the owner has twice required be escalated rather than made locally. Separately, the claim that --approve is test-isolation scaffolding is unsupported: it appears in all nine pi invocations repo-wide (tests/fm-pi-primary-live-e2e.test.sh:124, 220, 233, 266 and tests/fm-calm-pi-extension.test.sh:1064, 1192, 1349, 1673, 1948) alongside completely different --no-* isolation sets, it is the only one of those flags without a --no- prefix, and no in-repo source documents its role - SKILL.md has Autonomy rows for grok (:304) and one at :361 but none for pi. Fix by grounding the exclusion in SKILL.md:272 and dropping the unsupported --approve characterization; do not add --approve to the template.🔧 Fix: bind consumer obligation to every primary, fix pi rationale
✅ Re-checked - no issues remain.
tests/fm-pi-watch-extension.test.sh:119- tests/fm-pi-watch-extension.test.sh:test_pi_extension_reports_external_healthy_watcher fails in this environment ("expected exit 0, got 1"). I verified it fails identically at base commit a5fe1bc with the branch's changes absent, so it is pre-existing and unrelated to the launch-library extraction. The two assertions in that file that this change actually touches (the Pi secondmate launch wiring now read from bin/fm-launch-lib.sh) both pass.bin/fm-test-run.sh tests/fm-launch-lib.test.sh tests/fm-kimi-harness.test.sh tests/fm-pi-watch-extension.test.sh tests/fm-captain-translation-contract.test.shbin/fm-test-run.sh tests/fm-spawn-batch.test.sh tests/fm-spawn-dispatch-profile.test.sh tests/fm-spawn-worktree-settle.test.sh(drives real spawns and pins the typed per-harness model/effort flags)Differential sweep: sourced the pre-extraction launch_template/model_flag_for_harness/effort_flag_for_harness out of base a5fe1bc's bin/fm-spawn.sh and HEAD's bin/fm-launch-lib.sh, replayed fm-spawn.sh's own placeholder substitution, and diffed 438 fully composed commands (/tmp/no-mistakes-evidence/01KYFJ46F1VNA026V80MW8WQVD/launch-command-differential.sh)End-to-end spawn: ran the realbin/fm-spawn.sh --model opus --effort high <task> <project>at base and at HEAD with a fake tmux recordingsend-keys -l, and compared the literal launch line typed into the pane for claude, codex, opencode, pi, grok (/tmp/no-mistakes-evidence/01KYFJ46F1VNA026V80MW8WQVD/spawn-e2e-launchline.sh)Manual guard check:bin/fm-spawn.sh <task> <project> not-a-harnessstill refuses witherror: unknown harness ...through the sourced libraryMutation check in a throwaway copy of HEAD: planted a hand-copiedclaude --dangerously-skip-permissionsin a new bin/ script, redefined launch_template inside fm-spawn.sh, dropped grok primary--trust, reverted opencode primary to--prompt, and dropped claude'sCLAUDE_CODE_ENABLE_PROMPT_SUGGESTIONprefix - each reverted afterbash tests/fm-launch-lib.test.sh/bash tests/fm-kimi-harness.test.shbin/fm-test-run.sh --list --changed --base a5fe1bcto confirm the new bin/fm-launch-lib.sh maps into test selectionbash tests/fm-pi-watch-extension.test.shrun against a base-commit (a5fe1bc) checkout to confirm the one failing assertion is pre-existingbin/fm-launch-lib.sh:82- bin/fm-launch-lib.sh's header and per-arm comments cite evidence by exact line number (README.md:61/90/96/102/105/106, .agents/skills/harness-adapters/SKILL.md:272/276-278/304/345, CONTRIBUTING.md:50, docs/configuration.md:177, docs/turnend-guard.md:63, several tests). Those citations are correct today and I preserved them by keeping every edit to a single-line, in-place rewrite, but nothing enforces them: any future insertion in those files silently slides the citations onto unrelated lines, and the argument each arm rests on becomes unverifiable. Out of scope here; worth a follow-up that either anchors the citations to quoted text/section headings or adds a check that resolves each cited line.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.