Skip to content

fix(spawn): append launch brief to raw launch commands - #7829

Open
trillium wants to merge 2 commits into
kunchenguid:mainfrom
trillium:fix/spawn-raw-launch-brief
Open

trillium wants to merge 2 commits into
kunchenguid:mainfrom
trillium:fix/spawn-raw-launch-brief

Conversation

@trillium

Copy link
Copy Markdown
Contributor

Intent

Contribute this fix upstream to kunchenguid/firstmate as its own PR. Problem: a raw launch command (the unverified-adapter escape hatch, --harness '') skipped the launch-brief arg that every named adapter template embeds, so the agent started at an empty prompt. Change: bin/fm-spawn.sh appends the encoded launch-brief argument after the caller's own argv for raw commands. Deliberate decisions: Kimi is excluded (it rejects a positional prompt and gets its brief pointer after its readiness gate); a command that already names BRIEF is left alone. Tests: tests/fm-spawn-dispatch-profile.test.sh expectations updated for the appended argument; the chained raw launch case ends with '&& true' and the git-config probe with '; :' so the appended brief argument is harmless to the probed command. Scope is only this raw-launch brief append; no internal ticket references or AI attribution.

What Changed

  • bin/fm-spawn.sh: raw launch commands (the --harness '<cmd>' escape hatch) now get the encoded launch-brief argument appended after the caller's own argv, so the agent no longer starts at an empty prompt. Kimi is excluded (it rejects a positional prompt and gets its brief pointer after its readiness gate), and a command that already names __BRIEF__ is left unchanged.
  • tests/fm-spawn-dispatch-profile.test.sh: updated expectations for the appended brief argument. The chained raw launch case now ends with && true and the git-config probe with ; :, so the appended argument is harmless to the probed command.

Risk Assessment

✅ Low: Small, bounded change: the raw-launch brief append excludes kimi* and rovo*, skips commands that already name BRIEF, and the added rovo test runs the real spawn and asserts on the emitted command.

Testing

I ran the four tests this change touches against the real fm-spawn.sh and the emitted launch command, and all passed. They cover the appended brief on a generic raw launch, the rovo exclusion, the chained '&& true' case and the '; :' git-config probe. The full test file timed out, so the rest of it did not run. I did not drive a Herdr lab or a real harness CLI.

  • Live validation: ✅ go - 3 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Generic raw launch command gets the encoded launch-brief arg appended after the caller's argv ✅ pass live test_active_dispatch_profile_allows_raw_launch_command passed (real fm-spawn.sh, fake pane, asserts the exact emitted launch command)
Raw rovo launch gets no positional brief and takes the rovo readiness path ✅ pass live test_raw_rovo_launch_gets_no_positional_brief passed
Chained raw launch ('&& true') and git-config probe ('; :') still run correctly with the appended arg ✅ pass live test_chained_raw_launch_strips_ai_trailer_in_every_step and test_launch_preserves_inherited_git_config passed
Kimi raw launch is excluded from the brief append, and a command that already names BRIEF is left alone ⏸️ untested no Not driven: no existing or new test exercises these two branches, and I did not run the real spawn for them.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed ✅
  • ⚠️ bin/fm-spawn.sh:2906 - The brief-append exclusion covers only kimi*. rovo has the same constraint, and a raw launch whose first word is rovo (for example rovo run --yolo) now gets the positional brief appended. The comments above the rovo template (about line 2850) record that a positional brief is dead-on-arrival for rovo: it loads, never enters a working state, and drops back to an idle shell within seconds. The later [ &#34;$HARNESS&#34; = rovo ] readiness-and-pointer path (about line 7354) is not gated on RAW_LAUNCH, so a raw rovo launch runs both the appended argument and the post-ready pointer. A command that worked before this change can now exit before the readiness gate. The change's "Deliberate decisions" name only Kimi, so adding rovo to the exclusion goes beyond the stated intent. That is why this is ask-user: the smallest remedy is kimi* | rovo) in the case at bin/fm-spawn.sh:2906.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 3 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Generic raw launch command gets the encoded launch-brief arg appended after the caller's argv ✅ pass live test_active_dispatch_profile_allows_raw_launch_command passed (real fm-spawn.sh, fake pane, asserts the exact emitted launch command)
Raw rovo launch gets no positional brief and takes the rovo readiness path ✅ pass live test_raw_rovo_launch_gets_no_positional_brief passed
Chained raw launch ('&& true') and git-config probe ('; :') still run correctly with the appended arg ✅ pass live test_chained_raw_launch_strips_ai_trailer_in_every_step and test_launch_preserves_inherited_git_config passed
Kimi raw launch is excluded from the brief append, and a command that already names BRIEF is left alone ⏸️ untested no Not driven: no existing or new test exercises these two branches, and I did not run the real spawn for them.
  • Ran the four affected functions from tests/fm-spawn-dispatch-profile.test.sh through a temporary harness, since the full file exceeds the time budget: test_launch_preserves_inherited_git_config, test_active_dispatch_profile_allows_raw_launch_command, test_raw_rovo_launch_gets_no_positional_brief, test_chained_raw_launch_strips_ai_trailer_in_every_step
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

trillium and others added 2 commits October 26, 2026 17:31
A raw launch command skipped the launch-brief arg that every named adapter template embeds, so the agent started at an empty prompt. Append it after the caller's own argv. Kimi rejects a positional prompt and keeps its post-readiness brief pointer, and a command that already names __BRIEF__ is left alone.
@trillium

Copy link
Copy Markdown
Contributor Author

CI note: the only failing check, Behavior portable serial 1, fails in the unrelated timing-sensitive tests/fm-supervision-host.test.sh (host wake hand-off wait_until timeout); this PR does not touch that area.

@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate: thank you @trillium, this is a clear, small change and the rovo catch from review is a good one.

What I checked at head f6c486d1 against main 7da4c362: for a raw --harness '<cmd>' launch, bin/fm-spawn.sh now appends "$(… encode launch-brief < __BRIEF__)" after the caller's argv. kimi*/rovo* and commands that already name __BRIEF__ are skipped. Named adapters are untouched.

Contract-class: new-default (my own read). Main specifies the raw escape hatch as passing the captain's command through as written. The existing test says "nothing else may rewrite the captain's own command" and asserts that the raw command is unchanged. This PR changes that default for every raw launch, which is why the tests needed && true / ; : to absorb the extra argument. Starting with the brief is clearly useful. Still, changing what happens to a command the captain typed is the captain's call, so this won't auto-merge. Once it's otherwise ready, I'll put it to the captain as a merge-or-leave decision.

VISION:

  • One captain aligns: the worker no longer starts at an empty prompt.
  • Authority is a captain call: fm-spawn now edits the captain's own raw command with no opt-in.
  • Scripts aligns: a deterministic append.
  • Restart aligns.
  • Spine aligns.
  • Vendor: cannot tell. The skip list knows two harnesses that reject a positional prompt, but other unverified CLIs may reject one too. Raw launch exists precisely for unknown adapters.
  • Scope aligns.

CI: the only red is Behavior portable serial 1 in tests/fm-supervision-host.test.sh ("return-fail: the host did not hand the wake to main"). That's a known timing flake we're working on separately. It isn't your change, and I've re-run that job.

One ask, whenever you have time: the "live" rows in the description are the spawn tests with a fake pane. Could you do one real raw launch with an actual harness CLI (a generic one, plus kimi or rovo if you can) and post what the agent received? You could also re-raise through git push no-mistakes with that evidence. That's the only thing waiting on you. The rest is CI and then the captain.

@trillium

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I don't have kimi or rovo installed, so I can't test the raw launch against either of those.

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