From 0c6b0e5a87153797279a917e08721185649b446f Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Sun, 11 Oct 2026 21:46:30 +0000 Subject: [PATCH 1/2] fix(spawn): append the launch brief to raw launch commands 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. --- bin/fm-spawn.sh | 15 +++++++++++++++ tests/fm-spawn-dispatch-profile.test.sh | 7 ++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index 43176544f18..96abda4e2cb 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -2897,6 +2897,21 @@ case "$ARG3" in ;; esac done + # A named adapter template embeds the launch-brief arg itself; a raw command + # has no such placeholder and would start the agent at an empty prompt. + # Append it after the caller's own argv. Kimi rejects a positional prompt and + # gets its brief pointer after its readiness gate, and a command that already + # names __BRIEF__ is left alone. + case "$HARNESS" in + kimi*) : ;; + *) + # shellcheck disable=SC2016 # literal text, expanded by the launched shell + case "$LAUNCH" in + *__BRIEF__*) : ;; + *) LAUNCH=$LAUNCH' "$(__OPINPUT__ encode launch-brief < __BRIEF__)"' ;; + esac + ;; + esac ;; '') # No explicit harness: resolve from config. A secondmate AGENT launches on the diff --git a/tests/fm-spawn-dispatch-profile.test.sh b/tests/fm-spawn-dispatch-profile.test.sh index 4ef24298dd0..6f335a356af 100755 --- a/tests/fm-spawn-dispatch-profile.test.sh +++ b/tests/fm-spawn-dispatch-profile.test.sh @@ -508,7 +508,7 @@ test_launch_preserves_inherited_git_config() { rec=$(make_spawn_case "$id" codex "$id") read_case_record "$rec" out=$(run_ship_spawn "$HOME_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$LAUNCH_LOG" \ - "$id" "$PROJ_DIR" --harness 'echo WORKER-RAN >&2; git config --get-all credential.helper; git config --get core.hooksPath') + "$id" "$PROJ_DIR" --harness 'echo WORKER-RAN >&2; git config --get-all credential.helper; git config --get core.hooksPath; :') status=$? expect_code 0 "$status" "Git configuration probe should spawn: $out" launch=$(cat "$LAUNCH_LOG") @@ -597,7 +597,8 @@ test_active_dispatch_profile_allows_raw_launch_command() { # The unverified-adapter escape hatch is still an agent this fleet launched, # so it carries the compact-adviser floor and the AI-trailer strip; nothing # else may rewrite the captain's own command. - [ "$launch" = "export COMPACT_ADVISER_DISABLE=1; $(task_inbox_export "$HOME_DIR" "$id")$(fm_test_launch_git_prefix "$launch")custom-agent --flag" ] || fail "raw launch command changed"$'\n'"actual: $launch" + expected="export COMPACT_ADVISER_DISABLE=1; $(task_inbox_export "$HOME_DIR" "$id")$(fm_test_launch_git_prefix "$launch")custom-agent --flag \"\$('$ROOT/bin/fm-operational-input.sh' encode launch-brief < '$HOME_DIR/data/$id/launch-brief.md')\"" + [ "$launch" = "$expected" ] || fail "raw launch command changed"$'\n'"actual: $launch" pass "active crew-dispatch profile allows the raw launch-command escape hatch" } @@ -608,7 +609,7 @@ test_chained_raw_launch_strips_ai_trailer_in_every_step() { read_case_record "$rec" out=$(run_ship_spawn "$HOME_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$LAUNCH_LOG" \ - "$id" "$PROJ_DIR" "cd . && git commit -q --allow-empty --trailer 'Co-authored-by: Cursor ' -m 'fix: chained raw launch'") + "$id" "$PROJ_DIR" "cd . && git commit -q --allow-empty --trailer 'Co-authored-by: Cursor ' -m 'fix: chained raw launch' && true") status=$? expect_code 0 "$status" "chained raw launch should spawn: $out" launch=$(cat "$LAUNCH_LOG") From f6c486d1a17c688481d097e6bffae68051264865 Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Mon, 26 Oct 2026 17:49:04 -0700 Subject: [PATCH 2/2] no-mistakes(review): Exclude rovo from raw-launch brief append --- bin/fm-spawn.sh | 8 ++++---- tests/fm-spawn-dispatch-profile.test.sh | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index 96abda4e2cb..2e0e675b409 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -2899,11 +2899,11 @@ case "$ARG3" in done # A named adapter template embeds the launch-brief arg itself; a raw command # has no such placeholder and would start the agent at an empty prompt. - # Append it after the caller's own argv. Kimi rejects a positional prompt and - # gets its brief pointer after its readiness gate, and a command that already - # names __BRIEF__ is left alone. + # Append it after the caller's own argv. Kimi and rovo reject a positional + # prompt and get their brief pointer after their readiness gate, and a command + # that already names __BRIEF__ is left alone. case "$HARNESS" in - kimi*) : ;; + kimi* | rovo*) : ;; *) # shellcheck disable=SC2016 # literal text, expanded by the launched shell case "$LAUNCH" in diff --git a/tests/fm-spawn-dispatch-profile.test.sh b/tests/fm-spawn-dispatch-profile.test.sh index 6f335a356af..6ea0d2b4c21 100755 --- a/tests/fm-spawn-dispatch-profile.test.sh +++ b/tests/fm-spawn-dispatch-profile.test.sh @@ -602,6 +602,23 @@ test_active_dispatch_profile_allows_raw_launch_command() { pass "active crew-dispatch profile allows the raw launch-command escape hatch" } +test_raw_rovo_launch_gets_no_positional_brief() { + local rec id out status launch + id=raw-rovo-nobrief-z15 + rec=$(make_spawn_case raw-rovo-nobrief claude "$id") + read_case_record "$rec" + + out=$(run_ship_spawn "$HOME_DIR" "$WT_DIR" "$FAKEBIN_DIR" "$LAUNCH_LOG" \ + "$id" "$PROJ_DIR" "rovo run --yolo") + status=$? + expect_code 1 "$status" "raw rovo launch should reach rovo's readiness gate, which the fake pane never satisfies" + assert_contains "$out" "rovo did not show a verified ready signal" "raw rovo launch did not take the rovo readiness path" + launch=$(cat "$LAUNCH_LOG") + assert_contains "$launch" "rovo run --yolo" "raw rovo launch command was not emitted" + assert_not_contains "$launch" "launch-brief" "raw rovo launch got a positional brief argument" + pass "a raw rovo launch is not given the positional launch-brief argument" +} + test_chained_raw_launch_strips_ai_trailer_in_every_step() { local rec id out status launch body id=chained-raw-z15 @@ -2728,6 +2745,7 @@ test_active_dispatch_profile_requires_explicit_harness_for_scout test_active_dispatch_profile_allows_explicit_harness test_active_dispatch_profile_allows_positional_harness 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 test_claude_threads_model_and_effort test_codex_threads_model_and_effort