Skip to content

Activate Claude worker routing for agent_subagent, agent_model, cross_skill_ref #4235

Description

@Trecek

Problem

run_skill() admits skills that declare Claude-only agent capabilities to the Codex backend. This is the validated, implementation-ready refinement of #4227, based on the 2026-07-12 deep investigation (5-agent exploration, adversarial challenge round, breakage analysis, 2 post-report validators; all load-bearing claims independently fact-checked against code, git history, and sessions.jsonl).

Validated four-step root cause (each step SUPPORTED by direct code evidence):

  1. SKILL_CAPABILITY_REGISTRY (src/autoskillit/core/types/_type_constants_registries.py:335-381) marks agent_subagent, agent_model, and cross_skill_ref as codex_status="fix-required" with worker_routable=False (default).
  2. SkillCapabilityDef.required_backends (:318-324) is a derived property returning frozenset() for fix-required — advisory-only by design ([FIX] Skill Capability Registry Derived-Field Immunity #3680, commit 98e685574); the comment block at :327-334 (added in [FIX] Fix-Required Dispatch Gate Cross-Registry Immunity #4086) documents this explicitly and names the three capabilities as still Codex-dispatchable.
  3. _has_routing_capability() (src/autoskillit/server/tools/tools_execution.py:519-525) keys solely on worker_routable, so _skill_requires_claude stays False (:807-811) and backend_override stays None (:827-831).
  4. The admission-time gate (src/autoskillit/recipe/rules/rules_backend_compat.py:55) keys on the same always-empty backend_requirements — admission and dispatch share one blind spot, which is why the admission/dispatch-agreement test suite passes while both gates are wrong.

The reroute mechanism delivered by PR #4176 is already fully generic over worker_routable=True capabilities (_has_routing_capability/_get_routing_caps loop over the registry; an AST-guard test bans hardcoding git_metadata_write in tools_execution.py). Activating routing for these three capabilities is therefore a registry-data-only change.

Design Context

Occurrence Adjudication (corrections to #4227's evidence)

Occurrence Session Verdict
make-plan on Codex, order 4150-round6-audit-remediation-make-plan-1 019f4d21-8ed6-7520-903e-7f1d10095e5c Genuine instance. Codex read make-plan/SKILL.md (declares all three caps: uses_capabilities: [agent_model, agent_subagent, cross_skill_ref]), then failed on the transient "Selected model is at capacity" error. The retry-classification gap for that error is owned by #4226, not this issue.
investigate with literal model fable, order 4226-recovery-investigate-fable-1 019f4fa0-0bc6-70c2-9572-cb1312248310 Genuine instance. "fable" exists in no AutoSkillit alias table; CodexBackend.translate_model() passes it through literally and Codex's ChatGPT-account model allowlist rejects it with HTTP 400. Four such failures 2026-07-08 → 07-12 (vs. 18 successful fable-on-claude-code runs of 23 total). Had routing fired, the worker would have been Claude Code and the model valid.
prepare-issue, adjudicated_failure 019f4efb-0397-7431-92a8-bb34688caf1e Misattributed in #4227. prepare-issue/SKILL.md declares only github_api_write — none of the three capabilities — so this fix provably cannot change its routing. Actual failure chain: guard-blocked improvised open_kitchen/run_skill calls, then an invalid gh OAuth token (~/.config/gh/hosts.yml; GH_TOKEN/GITHUB_TOKEN unset). The "successful" sibling session 019f4edf-0f99-7321-827c-9b297ae774a3 hit the identical auth failure and created no issue either, despite success: true in sessions.jsonl — exposing a separate session-success classifier bug (workflow result "created": false scored as success). Both to be filed separately.
implement step of the #4233 work order with opus[1m] ran on claude-code (note: issue #4233 itself concerns async-subagent lifecycle, not routing — the connection is only that order 4233-section7i-remaining-delta-implement-codex-1 was implementing #4233's fix) 3958e362-07f4-46d2-b163-d5f68ed5c845 Not a defect occurrence. /autoskillit:implement-worktree-no-merge declares git_metadata_write (worker_routable=True), so the existing reroute fired as designed — deterministically across the kitchen (every implement step → claude-code; every make_plan/investigate/audit_impl step → codex). Model strings never participate in backend selection. The real gap it exposes is observability: the reroute is silent to operators, and no backend_override_activated line was recoverable in that session's artifacts.

Empirical Nuance

26 of 27 Codex make-plan sessions completed with subtype=success and real write activity (7.75–32.6 min, write_call_count 1–16). Sampled rollout logs show Codex improvising subagents via its native spawn_agent/wait_agent tools (tool namespace multi_agent_v1) and handling cross_skill_ref by raw sed reads of the referenced SKILL.md into its own context (no isolation, no separate model, no true activation). The defect's practical harm is (a) loss of the authored Claude Code execution contract (Agent/Skill/model-selection semantics) with non-deterministic improvisation quality, and (b) deterministic hard failures in specific combinations (unsupported model strings, guard-blocked improvisation) — not a universal hard block. "Structurally unavailable" is accurate for the authored skill contract, not for Codex's raw feature set.

Remediation

Reclassify agent_subagent, agent_model, and cross_skill_ref in SKILL_CAPABILITY_REGISTRY to codex_status="not-applicable" + worker_routable=True — the exact REROUTE configuration git_metadata_write already uses. Registry-data-only; no routing-logic code change.

Mandatory companions:

  1. cross_skill_ref declaration audit: ~88 skills declare it; 4 of 6 sampled non-arch-lens declarations are over-applied (self-referential invocation syntax, advisory "consider running" text, See-Also links — no actual Skill-tool invocation). Union blast radius of the three capabilities as-declared is 105/142 skills (~74%). Declaration accuracy is the lever that reconciles activating the route with keeping Codex-capable skills on Codex.
  2. Real-registry routing tests (synthetic-only coverage insufficient): make-plan and investigate reroute on a non-Anthropic backend; a Codex-compatible control skill stays; prepare-issue does not reroute (correct behavior under its actual declarations — replaces Skill capability routing omits Claude-only agent capabilities and dispatches make-plan to Codex #4227's literal ask for prepare-issue regression coverage, which was premised on the misattribution above).
  3. Observability — capability set must be ADDED to the log: the backend_override_activated log call (tools_execution.py:845-853) currently emits only reason, skill, original_backend, target_backend; the triggering capability set is computed only in the fail-closed crash branch (_get_routing_caps, line 815) and is not logged. Acceptance criterion 4 therefore requires adding the routing-capability set to this log call, and verifying the line lands in per-session audit artifacts (it was not recoverable for session 3958e362).
  4. Scope _provider_aware_capability_overrides before the flip: its trigger (_auto_overrides.py:93-119) loops over ALL run_skill steps and fires on ANY worker_routable=True capability, then sets the git-specific ingredient backend_supports_git_write="true" — the sole member of BACKEND_CAPABILITY_INGREDIENTS. Post-flip, a non-git skill alone (e.g. make-plan in research-implement.yaml:185) would satisfy the trigger and can authorize skip_when_false: inputs.backend_supports_git_write steps on non-git grounds. Scope the trigger to git_metadata_write-declaring steps (or generalize the ingredient model) so a git-specific ingredient cannot be set by unrelated capabilities.
  5. Deployment guard: doctor check and/or open_kitchen warning when backend=codex and the claude binary is absent. Post-flip, the fail-closed check (tools_execution.py:813-825, SkillResult.crashed) would otherwise crash nearly every step of the implementation, implementation-groups, remediation, and merge-prs recipes on claude-less Codex hosts — the flip converts the claude CLI from an optional to a de facto mandatory dependency on Codex kitchens.
  6. Follow-up issues to file: (a) fleet quota guard cannot see rerouted Claude workers (tools_fleet_dispatch.py:445-468 keys provider="anthropic" on the orchestrator's backend capability — rerouted workers bypass all quota I/O); (b) model-string normalization on reroute — a Codex-native default_model (e.g. gpt-5.6-sol post-[FIX] Route Codex aliases to GPT-5.6 Sol #4220) passes unchanged into claude --model gpt-5.6-sol; recipe-declared canonical aliases (sonnet/opus/opus[1m]) are safe.

Breakage Analysis (summary)

Acceptance Criteria

  1. Skills declaring agent_subagent, agent_model, or cross_skill_ref activate the existing Claude Code worker route when the active backend cannot provide those capabilities; the Codex parent remains the orchestrator.
  2. make-plan and investigate no longer launch as Codex workers solely because the parent kitchen is Codex.
  3. Capabilities Codex can execute natively remain on Codex — enforced through declaration accuracy (companion 1), not by weakening the mechanism.
  4. Backend-override logging identifies skill_requirement and the triggering capability set, and the line is present in per-session audit artifacts.
  5. Real-registry tests cover make-plan (reroutes), investigate (reroutes), one Codex-compatible control skill (stays), and prepare-issue (stays — does not reroute).
  6. Admission and runtime routing remain consistent, with no hard block where a valid Claude worker route exists.
  7. A missing claude CLI on a Codex kitchen is surfaced at doctor/open_kitchen time, not as mid-pipeline SkillResult.crashed failures.
  8. task test-check passes.

Relationship to Existing Issues

Investigation

Deep investigation completed 2026-07-12 (deep mode: 5-agent parallel exploration, historical-recurrence check, adversarial challenge round, solution convergence with breakage analysis, 2 post-report validators; factual-accuracy validation applied 3 corrections, recommendation-soundness verdict SOUND-WITH-CORRECTIONS).

Report: .autoskillit/temp/investigate/investigation_capability_routing_claude_only_agents_2026-07-12_093924.md (repo-local).
Prior investigation (2026-07-10): /home/talon/projects/autoskillit-runs/remediation-4150-20260710-093024-046178/.autoskillit/temp/investigate/investigation_codex_make_plan_immediate_failure_2026-07-10_181743.md (205 lines — note its Part-B recommendation is invariant-violating as written; see Design Context).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugExisting behavior is brokenrecipe:remediationRoute: investigate/decompose before implementationstagedImplementation staged and waiting for promotion to main

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions