fix(mosaic): stop yolo runtime from leaking runtime name as first user message #455

Merged
jason.woltje merged 1 commits from fix/yolo-runtime-initial-arg into main 2026-04-11 16:57:44 +00:00
Owner

Summary

Fixes mosaicstack/stack#454. mosaic yolo <runtime> was forwarding the runtime name (e.g. claude) as the first positional argument to the underlying CLI, which Claude Code interpreted as the initial user message. As a secondary consequence, the mission-auto-prompt path (hasMissionNoArgs) was bypassed.

Root cause

Commander.js includes declared positional arguments in cmd.args. The yolo <runtime> action handler forwarded cmd.args verbatim to launchRuntime, so for mosaic yolo claude the forwarded args were ["claude"]. The non-yolo <runtime> subcommands were unaffected because they don't declare any positionals.

Fix

  • Extracts a registerRuntimeLaunchers(program, handler) factory exposing a RuntimeLaunchHandler type so the commander wiring is unit-testable without spawning subprocesses.
  • Slices the declared positional off cmd.args in the yolo action: handler(runtime, cmd.args.slice(1), true).
  • registerLaunchCommands delegates to the factory with the real launchRuntime as the handler.

Tests

Adds packages/mosaic/src/commands/launch.spec.ts (11 tests):

  • All 4 runtimes (claude, codex, opencode, pi) for non-yolo — handler receives (runtime, [], false).
  • All 4 runtimes for yolo — handler receives (runtime, [], true). Critical regression assertion.
  • Excess-args forwarding for both paths.
  • Invalid runtime rejected under yolo (process.exit(1)).

All 11 pass. Full mosaic suite is 270/271 — the 1 unrelated failure (uninstall.spec.ts:138) is pre-existing on branch main and was confirmed before this PR landed.

Test plan

  • Unit tests added and green
  • pnpm --filter @mosaicstack/mosaic run typecheck green
  • pnpm --filter @mosaicstack/mosaic run lint green
  • Repo pnpm typecheck / pnpm lint / pnpm format:check green
  • Independent code review (no blockers)
  • CI green on PR
  • Merged and verified on main

Affected version

Ships in mosaicstack/mosaic 0.0.30.

## Summary Fixes mosaicstack/stack#454. `mosaic yolo <runtime>` was forwarding the runtime name (e.g. `claude`) as the first positional argument to the underlying CLI, which Claude Code interpreted as the initial user message. As a secondary consequence, the mission-auto-prompt path (`hasMissionNoArgs`) was bypassed. ## Root cause Commander.js includes declared positional arguments in `cmd.args`. The `yolo <runtime>` action handler forwarded `cmd.args` verbatim to `launchRuntime`, so for `mosaic yolo claude` the forwarded args were `["claude"]`. The non-yolo `<runtime>` subcommands were unaffected because they don't declare any positionals. ## Fix - Extracts a `registerRuntimeLaunchers(program, handler)` factory exposing a `RuntimeLaunchHandler` type so the commander wiring is unit-testable without spawning subprocesses. - Slices the declared positional off `cmd.args` in the yolo action: `handler(runtime, cmd.args.slice(1), true)`. - `registerLaunchCommands` delegates to the factory with the real `launchRuntime` as the handler. ## Tests Adds `packages/mosaic/src/commands/launch.spec.ts` (11 tests): - All 4 runtimes (claude, codex, opencode, pi) for non-yolo — handler receives `(runtime, [], false)`. - All 4 runtimes for yolo — handler receives `(runtime, [], true)`. Critical regression assertion. - Excess-args forwarding for both paths. - Invalid runtime rejected under yolo (process.exit(1)). All 11 pass. Full mosaic suite is 270/271 — the 1 unrelated failure (`uninstall.spec.ts:138`) is pre-existing on branch main and was confirmed before this PR landed. ## Test plan - [x] Unit tests added and green - [x] `pnpm --filter @mosaicstack/mosaic run typecheck` green - [x] `pnpm --filter @mosaicstack/mosaic run lint` green - [x] Repo `pnpm typecheck` / `pnpm lint` / `pnpm format:check` green - [x] Independent code review (no blockers) - [ ] CI green on PR - [ ] Merged and verified on main ## Affected version Ships in `mosaicstack/mosaic` 0.0.30.
jason.woltje added 1 commit 2026-04-11 16:54:21 +00:00
fix(mosaic): stop yolo runtime from leaking runtime name as first user message
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
1dd4f5996f
`mosaic yolo <runtime>` forwarded `cmd.args` (which Commander populates with
the declared `<runtime>` positional) to the underlying CLI. For the claude
runtime that meant argv included the literal string "claude" as an initial
positional argument, which Claude Code interpreted as the first user message.
As a secondary consequence, the mission-auto-prompt path was also bypassed
because `hasMissionNoArgs` saw a non-empty args list.

Refactor the runtime subcommand wiring into an exported
`registerRuntimeLaunchers(program, handler)` factory with a
`RuntimeLaunchHandler` type so the commander integration is unit-testable
without spawning subprocesses. Slice the declared positional off `cmd.args`
in the yolo action before forwarding.

Adds `packages/mosaic/src/commands/launch.spec.ts` with 11 regression tests
covering all four runtimes (claude, codex, opencode, pi) for both `<runtime>`
and `yolo <runtime>` paths, excess-args forwarding, and invalid-runtime
rejection. The critical assertion blocks the regression: yolo parses must
forward `extraArgs = []`, not `[runtime]`.

Fixes mosaicstack/stack#454

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jason.woltje merged commit b2cec8c6ba into main 2026-04-11 16:57:44 +00:00
jason.woltje deleted branch fix/yolo-runtime-initial-arg 2026-04-11 16:57:45 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#455