model-is-not

Model not passed to claude CLI; display fabricates dated opus-4-6 instead of showing actual executor invocation

Metadata

Statusdone
Assignedagent-49
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Created2026-04-26T16:48:52.047768809+00:00
Started2026-04-26T16:49:49.049145164+00:00
Completed2026-04-26T17:22:34.727270302+00:00
Tagseval-scheduled
Eval score0.82
└ blocking impact0.90
└ completeness0.82
└ coordination overhead0.82
└ correctness0.85
└ downstream usability0.76
└ efficiency0.85
└ intent fidelity0.41
└ style adherence0.90

Description

Description

User's frustration trail: agents 'launch with opus-4-6' — but they don't. Two stacked bugs.

User's clarification on the right behavior

  • Pass-through what the user wrote. claude:opus stays opus (alias, latest version on claude CLI side); claude:claude-opus-4-6 stays claude-opus-4-6 (pinned, user's choice). NO auto-canonicalization either way.
  • Default: bare alias (opus/sonnet/haiku) — let claude CLI resolve to current.
  • Display = the actual string that was passed to the executor. The truth, not a fabricated canonical form.

Bug 1: Display fabricates a dated id

wg show <task> displays Model: claude-opus-4-6 for tasks created with --model claude:opus. The dated string was never typed by the user. Same fabrication shows up in the spawn log:

Spawned by coordinator --executor claude --model claude-opus-4-6 [agent-43]

Fix: in display paths, show what the user wrote (claude:opus), or what actually got passed to the executor after the prefix-strip (opus). NEVER a dated id the user didn't type.

Bug 2: Model is dropped between spawn-task and claude-handler (THE REAL BUG)

claude-handler stderr shows:

claude-handler: spawning claude (model=default, cwd=...)

Claude CLI is invoked with NO --model flag → uses claude CLI's own default (likely sonnet, NOT opus). The configured claude:opus is being dropped between spawn-task argv-construction and claude-handler exec.

Trace:

  • wg spawn-task .coordinator-1 --dry-run returns: wg claude-handler --chat coordinator-1 — no --model in argv
  • claude_handler.rs:376-379 DOES forward --model when given one, but spawn-task isn't giving it one
  • Effective model resolution returns claude:opus, but the spawn-task argv-builder for the claude branch isn't including --model

Fix: in src/commands/spawn_task.rs (around line 354 where the executor branch builds argv), the claude branch must pass --model <effective_model> to the claude-handler exec when the task or daemon config has a non-default model. Strip-provider-prefix already happens inside claude_handler; just pass the spec through.

Verification of fix

After fix, daemon log should show:

[INFO] [coordinator-0 stderr] claude-handler: spawning claude (model=opus, ...)

NOT model=default. And claude CLI then runs actual opus.

wg show shows the user's input string (claude:opus), not claude-opus-4-6.

The 'Spawned by coordinator' log line shows the same string the executor was actually invoked with.

Files likely to touch

  • src/commands/spawn_task.rs — add --model to claude-handler argv branch
  • src/commands/show.rs — display model string as-written / as-passed, no canonicalization
  • src/commands/service/coordinator.rs — 'Spawned by ...' log line uses the actual invocation string
  • Whatever resolver fabricates claude-opus-4-6 from claude:opus for display — neuter it for the claude executor path

What stays allowed

  • User explicitly specifying a dated id (e.g., --model claude:claude-opus-4-6 or --model claude:opus-4-6) is fine — that's pinning. Pass it through unchanged.

Validation

  • Failing tests first:
    • test_spawn_task_passes_model_to_claude_handler — spawn-task --dry-run for task with model='claude:opus' includes --model opus (after prefix strip) or --model claude:opus
    • test_show_displays_user_input_not_dated_id — wg show for task created with --model claude:opus displays the user's spec, NEVER a dated id
    • test_spawn_log_displays_actual_invocation — 'Spawned by ...' log line matches what was passed to the executor
    • test_user_pinned_dated_id_passes_through_unchanged — wg add 'x' --model claude:opus-4-6 displays and runs as opus-4-6
  • Implementation makes tests pass
  • cargo build + cargo test pass with no regressions
  • Manual smoke (live, after restart):
    • Daemon log: claude-handler: spawning claude (model=opus, ...) (NOT model=default)
    • wg show .coordinator-1 displays Model as user-written (e.g., 'claude:opus', or 'opus' after strip)
    • 'Spawned by ...' log lines use the same string the executor got

Depends on

Required by

Log