Skip to content

dispatch_food_truck per-dispatch backend override (heterogeneous routing R1)#4182

Merged
Trecek merged 7 commits into
developfrom
dispatch-food-truck-per-dispatch-backend-override-heterogene/4179
Jul 5, 2026
Merged

dispatch_food_truck per-dispatch backend override (heterogeneous routing R1)#4182
Trecek merged 7 commits into
developfrom
dispatch-food-truck-per-dispatch-backend-override-heterogene/4179

Conversation

@Trecek

@Trecek Trecek commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add an optional backend parameter to the dispatch_food_truck MCP tool that selects which coding-agent backend executes the dispatched child session. When omitted, behavior is byte-for-byte identical to today (uses ctx.backend). When supplied, the per-dispatch backend is used for: capability gating (food_truck_capable), command building (build_food_truck_cmd), pre-launch validation (ensure_pre_launch), recipe admission control (capability overrides, backend-incompatible-skill rule, effective_backend_map), session-log resolution, and record persistence. The DispatchRecord gains a backend_name field so downstream consumers (reset, diagnostics, session-log lookup) resolve against the correct backend. The field is added to _RETRY_IDENTITY_FIELDS so retried dispatches preserve the backend override.

The implementation follows the existing run_headless_core call-local override pattern: ctx.backend is never mutated; a resolved CodingAgentBackend instance is threaded through the dispatch path as a function argument.

Requirements

REQ-HBR-001: The dispatch_food_truck MCP tool (server/tools/tools_fleet_dispatch.py) must accept an optional backend parameter whose accepted values are the names registered in BACKEND_REGISTRY ("claude-code", "codex").

REQ-HBR-002: When the backend parameter is omitted, dispatch behavior must be byte-for-byte identical to the current ctx.backend path — zero behavior change for existing single-backend flows.

REQ-HBR-003: The child session command must be built via the per-dispatch backend's build_food_truck_cmd, with backend-correct env injection (AUTOSKILLIT_AGENT_BACKEND__BACKEND, AUTOSKILLIT_AGENT_BACKEND, AUTOSKILLIT_MCP_CLIENT_BACKEND) so the child process resolves the per-dispatch backend at boot.

REQ-HBR-004: ensure_pre_launch() must be invoked on the per-dispatch backend before spawn (e.g., Codex MCP registration in config.toml).

REQ-HBR-005: The food_truck_capable capability gate must be evaluated against the per-dispatch backend, not the kitchen backend.

REQ-HBR-006: Recipe admission control and capability overrides must be computed against the per-dispatch backend: _provider_aware_capability_overrides, the backend_supports_git_write ingredient, _compute_effective_backend_map, and the backend-incompatible-skill validation rule (server/tools/_auto_overrides.py, recipe/rules/rules_backend_compat.py).

REQ-HBR-007: Per-dispatch backend selection must compose with existing provider profiles (e.g., a MiniMax implement-step provider override via ANTHROPIC_BASE_URL) and with the R0 capability-driven auto-route (#4176) inside the child session — existing provider recipe overrides must behave identically.

REQ-HBR-008: The DispatchRecord must persist which backend the dispatch ran on, so that reset_dispatch, diagnostics, and session-log lookup (Channel B for Claude Code vs CodexSessionLocator for Codex) resolve against the correct backend.

REQ-HBR-009: Any BackendCapabilities field addition required by this work must be forward-declared with a tracking entry in _FORWARD_DECLARED in test_capability_consumption.py (frozen-dataclass constraint noted in the forward-obligations doc).

Closes #4179

Implementation Plan

Plan file: .autoskillit/temp/make-plan/dispatch_food_truck_per_dispatch_backend_override_plan_2026-07-04_152400.md

🤖 Generated with Claude Code via AutoSkillit

Token Usage Summary

Step Model count uncached output cache_read peak_ctx turns cache_write time
plan* opus[1m] 1 2.2k 44.9k 4.1M 168.5k 87 149.6k 22m 37s
review_approach* opus 1 9.2k 5.3k 199.4k 49.0k 12 61.8k 6m 1s
verify* fable 1 31.1k 41.3k 2.0M 169.7k 44 170.1k 14m 49s
implement* MiniMax-M3 1 96.2k 18.9k 7.0M 0 156 0 18m 6s
fix* opus 1 77 14.4k 4.4M 112.5k 97 93.3k 12m 11s
Total 138.7k 124.8k 17.6M 169.7k 474.7k 1h 13m

* Step used a non-Anthropic provider; caching behavior may differ.

Token Efficiency

Step LoC Changed cache_read/LoC cache_write/LoC output/LoC
plan 0
review_approach 0
verify 0
implement 577 12052.9 0.0 32.8
fix 37 119182.5 2520.4 388.2
Total 614 28647.1 773.2 203.2

Model Usage Breakdown

Model steps uncached output cache_read cache_write time
opus[1m] 1 2.2k 44.9k 4.1M 149.6k 22m 37s
opus 2 9.3k 19.7k 4.6M 155.0k 18m 13s
fable 1 31.1k 41.3k 2.0M 170.1k 14m 49s
MiniMax-M3 1 96.2k 18.9k 7.0M 0 18m 6s

Trecek and others added 7 commits July 4, 2026 17:45
Adds an optional `backend` parameter to the `dispatch_food_truck` MCP tool
that selects which coding-agent backend executes the dispatched child session.
When omitted, behavior is identical to today (uses ctx.backend). When supplied,
the per-dispatch backend is used for capability gating, command building,
pre-launch validation, recipe admission control, session-log resolution, and
record persistence.

Key changes:
- FleetErrorCode.FLEET_INVALID_BACKEND for unknown backend names
- DispatchRecord.backend_name field (in _RETRY_IDENTITY_FIELDS)
- dispatch_food_truck executor resolves + threads dispatch_backend
- execute_dispatch / _run_dispatch accept dispatch_backend parameter
- MCP tool validates backend against BACKEND_REGISTRY before dispatch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ckend override

- Move resolve_backend_override to server/_misc.py (allowed import layer for tools)
- Hoist BACKEND_REGISTRY import to module level to satisfy IL-3 deferred import rules
- Fix mock backend .name attribute causing JSON serialization failures
- Fix mock project_log_dir returning string instead of Path
- Update test assertions to match actual dispatch behavior
- Bump headless/__init__.py line budget to 510
- Add fleet cascade map entries for new test file

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…escing

Aligns with fleet/_api.py pattern that uses `is not None` guard instead
of falsy `or` coalescing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The `as BACKEND_REGISTRY` form is only needed for public re-exports;
this import is consumed locally within _misc.py.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ackend guard

The assert at L432 could be stripped under python -O, leaving a silent
None dereference. An explicit if-raise provides deterministic behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… guard

The previous commit changed the assert to an explicit RuntimeError raise;
the test must match the new exception type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…kend enum

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant