simplify-executor-taxonomy

Simplify executor taxonomy: model+endpoint as user-facing primitives; executor becomes implementation detail

Metadata

Statusdone
Assignedagent-687
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Created2026-04-27T14:15:39.175623226+00:00
Started2026-04-27T14:16:03.021433250+00:00
Completed2026-04-27T15:29:17.126893421+00:00
Tagseval-scheduled

Description

Description

The executor taxonomy has 6 overlapping user-facing concepts (executor, provider, endpoint, route, handler, model) that reduce to TWO real axes (delegate-vs-in-process, wire protocol). The proliferation causes constant confusion and config bugs (model-routes-to-wrong-executor, claude+local-model = 404, etc — see agency-picks-claude, agency-still-picks, local-providers-fix history this session).

User decision (verbatim): 'lets simplify executor taxonomy. deeply problematic.'

Target model

User picks ONE thing: a (model, endpoint) pair. wg derives everything else.

  • modelclaude:opus, openrouter:anthropic/claude-opus-4-6, local:qwen3-coder, oai-compat:gpt-5, etc. Carries provider prefix.
  • endpoint — defaults from provider (claude → claude CLI's own auth; openrouter → openrouter.ai; local → user-supplied URL). Optional.

From these two, wg internally decides:

  • Which handler subprocess to spawn (claude-handler / codex-handler / nex)
  • Which wire protocol to use (Anthropic vs OAI-compat)
  • Whether it's delegate-to-CLI (claude, codex, aider/llm if added) or in-process (nex/native)

The user never types --executor again. Never sees [agent].executor in config. Never has to pick -x claude vs -x native — the model spec implies it.

What changes (user-facing)

TodayNew
wg init -x claude -m claude:opuswg init -m claude:opus (executor implied)
wg init -x nex -m qwen3-coder -e https://lambda01...wg init -m local:qwen3-coder -e https://lambda01... (or just -m if endpoint isn't local-style)
wg add 'task' --executor claude --model opuswg add 'task' --model claude:opus
[agent] executor = 'claude' in configDEPRECATED. Just [agent] model = 'claude:opus'.
[dispatcher] executor = 'native'DEPRECATED. [dispatcher] model = 'local:qwen3-coder' is the only knob.
wg setup --route claude-cliUNCHANGED (routes were already the right idea — make them the canonical setup path)

What changes (internals — not user-facing)

The wg codebase still has all the executor implementations (claude-handler, codex-handler, nex/native). They become internal handler types keyed off model-prefix → handler-kind:

  • claude:* → claude-handler subprocess
  • codex:* or oai-compat:gpt-* → codex-handler
  • local:*, openrouter:*, oai-compat:* → nex (in-process)
  • Future: aider/llm/etc each get their own internal handler

This mapping lives in ONE place (e.g., src/dispatch/handler_for_model.rs) and is the single source of truth for 'given this model, what binary do I spawn'.

Deprecation surfaces

For one release:

  • -x <executor> flag accepted with deprecation warning, mapped to corresponding model spec
  • [agent].executor field accepted with deprecation warning, ignored if model has provider prefix
  • --executor on wg add accepted with deprecation warning
  • wg config --coordinator-executor accepted with deprecation warning

After one release: drop them entirely.

Documentation rewrite

CLAUDE.md, AGENT-GUIDE.md, README.md, docs/AGENT-SERVICE.md — all references to 'executor' as a user concept get rewritten:

  • 'pick an executor' → 'pick a model'
  • 'executor types: claude, native, codex, ...' → 'wg picks the right handler based on your model and endpoint'
  • Examples use only model + endpoint

Files likely to touch

  • src/cli.rs — drop / deprecate -x and --executor flags on init / add / spawn / setup
  • src/commands/init.rs — implied-executor logic from -m
  • src/commands/add.rs — same
  • src/commands/setup.rs — routes are the canonical entry; drop the duplicate executor-question paths
  • src/config.rs — mark executor field deprecated; warn on load if set
  • src/dispatch/plan.rsplan_spawn already does most of this work; just remove the agent_executor parameter and infer from model
  • New: src/dispatch/handler_for_model.rs (or similar) — single source of truth for model → handler-kind mapping
  • Docs: CLAUDE.md, AGENT-GUIDE.md, README.md, docs/AGENT-SERVICE.md, docs/COMMANDS.md
  • Migration tests: legacy configs with executor=X still load with deprecation warning, behavior matches

What stays

  • Routes (wg setup --route claude-cli) — they were always the right user-facing abstraction; keep them
  • Handlers themselves (claude-handler, codex-handler, nex) — internal implementation, unchanged
  • shell exec-mode (genuinely doesn't involve an LLM) — stays as an exec_mode flag, not an executor
  • Per-task model override (wg add 'X' --model Y) — stays

Migration plan

  1. Add deprecation warnings on every executor= surface (config, CLI, IPC) — don't break anyone.
  2. Update docs + examples to use model+endpoint only.
  3. Implement handler-for-model resolver as single source of truth.
  4. After one release: hard-remove the deprecated surfaces.

Out of scope

  • Rewriting the handler implementations themselves (claude-handler, nex) — those are fine, just become internal
  • The chat-as-first-class refactor (wg-chat-as already done, separate concern)
  • The route default-model splits (wg-setup-routes already filed, separate concern)

Validation

  • Failing tests first:
    • test_init_without_executor_flag_uses_model_prefix — wg init -m claude:opus produces config with handler=claude (no --executor needed)
    • test_init_with_local_model_routes_to_nex — wg init -m local:qwen3-coder -e https://... produces config that uses nex handler (no --executor needed)
    • test_legacy_executor_flag_warns_and_works — wg init -x claude -m claude:opus still produces same config + emits one deprecation warning
    • test_legacy_executor_field_warns_on_load — config with [agent] executor = 'claude' loads, emits warning, model spec wins
    • test_handler_for_model_is_single_source_of_truth — grep src/ for executor-decision logic outside the handler-for-model resolver returns zero hits
    • test_no_executor_in_user_facing_help — wg --help, wg init --help, wg add --help mention model + endpoint, NOT executor
  • Implementation makes tests pass
  • cargo build + cargo test pass with no regressions
  • Manual smoke (HARD GATE):
    • Fresh dir: wg init -m claude:opus works, config has no executor field, dispatch produces claude-handler spawn
    • Fresh dir: wg init -m local:qwen3-coder -e https://lambda01... works, dispatch produces nex spawn against the endpoint
    • Legacy config with executor=claude loads, emits one warning, behaves identically
    • wg setup --route claude-cli --yes produces a no-executor-field config that works
    • All docs read coherently with no mention of 'executor' as a user concept (only routes + models)

Depends on

Required by

Log