You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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):
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).
_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).
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.
Invariant warning for implementers:tests/arch/test_skill_capability_registry.py::test_worker_routable_implies_not_applicable_and_empty_required_backends (line 95) enforces worker_routable=True ⟹ codex_status="not-applicable". The prior investigation report's Part-B recommendation (flip worker_routable alone while keeping fix-required) violates this invariant and will fail the arch suite if implemented verbatim; its stated reason for killing the not-applicable alternative ("hard-blocks rather than reroutes") is wrong under current semantics — not-applicable + worker_routable=True IS the REROUTE configuration (exactly git_metadata_write's).
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 nativespawn_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:
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.
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).
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).
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.
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.
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)
Test-suite-neutral: required_backends returns frozenset() both for fix-required (today) and for not-applicable+worker_routable=True (REROUTE), so every consumer and test keyed on backend_requirements is invariant to the flip; registry invariant tests are satisfied by construction. Notably, no negative-guard test pins the current no-reroute behavior for these three capabilities (unlike the deliberate open_kitchen/github_api_write must-not-route tests) — nothing pins against the change, and nothing would catch a mistake in it either.
Risk: MEDIUM for the flip alone (mechanically safe, reversible data change); MEDIUM–HIGH without companions 1 and 4. Named rollout risk: Claude session-limit/quota exhaustion — the ~74% figure is a skill-declaration count, not a measured traffic share, but the exposure is not hypothetical (session ef64b03b-e68c-4729-b73a-56413b6a92b6 hit the explicit Claude session limit during this issue's own investigation, api_retry_exhausted=true after 917.51s), and the quota guard cannot see rerouted workers. Capacity impact modeling is a rollout prerequisite for Codex-primary fleets.
One additional volume-multiplied-but-currently-inert surface: the HOOK_REGISTRY fix-required matcher gate inside _check_backend_compat (tools_execution.py:141-154) evaluates the effective (post-override) backend's guards; inert today only because HOOK_REGISTRY has zero fix-required entries.
Acceptance Criteria
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.
make-plan and investigate no longer launch as Codex workers solely because the parent kitchen is Codex.
Capabilities Codex can execute natively remain on Codex — enforced through declaration accuracy (companion 1), not by weakening the mechanism.
Backend-override logging identifies skill_requirement and the triggering capability set, and the line is present in per-session audit artifacts.
Real-registry tests cover make-plan (reroutes), investigate (reroutes), one Codex-compatible control skill (stays), and prepare-issue (stays — does not reroute).
Admission and runtime routing remain consistent, with no hard block where a valid Claude worker route exists.
A missing claude CLI on a Codex kitchen is surfaced at doctor/open_kitchen time, not as mid-pipeline SkillResult.crashed failures.
To be filed separately per this investigation: (a) session-success classifier scores workflow-failed prepare-issue runs as success; (b) stale gh OAuth token operational issue.
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, andsessions.jsonl).Validated four-step root cause (each step SUPPORTED by direct code evidence):
SKILL_CAPABILITY_REGISTRY(src/autoskillit/core/types/_type_constants_registries.py:335-381) marksagent_subagent,agent_model, andcross_skill_refascodex_status="fix-required"withworker_routable=False(default).SkillCapabilityDef.required_backends(:318-324) is a derived property returningfrozenset()forfix-required— advisory-only by design ([FIX] Skill Capability Registry Derived-Field Immunity #3680, commit98e685574); 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._has_routing_capability()(src/autoskillit/server/tools/tools_execution.py:519-525) keys solely onworker_routable, so_skill_requires_claudestaysFalse(:807-811) andbackend_overridestaysNone(:827-831).src/autoskillit/recipe/rules/rules_backend_compat.py:55) keys on the same always-emptybackend_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=Truecapabilities (_has_routing_capability/_get_routing_capsloop over the registry; an AST-guard test bans hardcodinggit_metadata_writeintools_execution.py). Activating routing for these three capabilities is therefore a registry-data-only change.Design Context
8e9c1a037, 2026-07-03, closes Restore capability-driven backend auto-route (R0): codex orchestrators dispatch git_metadata_write skills to claude-code workers #4174) delivered the Claude-worker reroute scoped togit_metadata_write("R0"); the scope fell mechanically out of which capabilities werenot-applicableat the time (Admission truth-telling: any-pass capability override + pruning-filter erasure of ERROR rules let statically-doomed codex dispatches through #4171). No commit message, code comment, TODO, docs/ file, or ADR defers the three agent capabilities — the gap is an oversight, not a staged rollout. (R0's scoping was capability-aware in design — REQ-ROUTE-003 deliberately excludedopen_kitchen-capability skills — but its coverage reasoning never addressed the three fix-required capabilities.)worker_routablefield itself was formalized four days later in Rectify: check_review_posted Step Wiring #4205 (cbd216336, 2026-07-07), folded into an unrelated-titled commit.tests/arch/test_skill_capability_registry.py::test_worker_routable_implies_not_applicable_and_empty_required_backends(line 95) enforcesworker_routable=True ⟹ codex_status="not-applicable". The prior investigation report's Part-B recommendation (flipworker_routablealone while keepingfix-required) violates this invariant and will fail the arch suite if implemented verbatim; its stated reason for killing thenot-applicablealternative ("hard-blocks rather than reroutes") is wrong under current semantics —not-applicable+worker_routable=TrueIS the REROUTE configuration (exactlygit_metadata_write's).Occurrence Adjudication (corrections to #4227's evidence)
4150-round6-audit-remediation-make-plan-1019f4d21-8ed6-7520-903e-7f1d10095e5cmake-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.fable, order4226-recovery-investigate-fable-1019f4fa0-0bc6-70c2-9572-cb1312248310CodexBackend.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.adjudicated_failure019f4efb-0397-7431-92a8-bb34688caf1eprepare-issue/SKILL.mddeclares onlygithub_api_write— none of the three capabilities — so this fix provably cannot change its routing. Actual failure chain: guard-blocked improvisedopen_kitchen/run_skillcalls, then an invalidghOAuth token (~/.config/gh/hosts.yml;GH_TOKEN/GITHUB_TOKENunset). The "successful" sibling session019f4edf-0f99-7321-827c-9b297ae774a3hit the identical auth failure and created no issue either, despitesuccess: truein sessions.jsonl — exposing a separate session-success classifier bug (workflow result"created": falsescored as success). Both to be filed separately.implementstep of the #4233 work order withopus[1m]ran on claude-code (note: issue #4233 itself concerns async-subagent lifecycle, not routing — the connection is only that order4233-section7i-remaining-delta-implement-codex-1was implementing #4233's fix)3958e362-07f4-46d2-b163-d5f68ed5c845/autoskillit:implement-worktree-no-mergedeclaresgit_metadata_write(worker_routable=True), so the existing reroute fired as designed — deterministically across the kitchen (everyimplementstep → claude-code; everymake_plan/investigate/audit_implstep → codex). Model strings never participate in backend selection. The real gap it exposes is observability: the reroute is silent to operators, and nobackend_override_activatedline was recoverable in that session's artifacts.Empirical Nuance
26 of 27 Codex make-plan sessions completed with
subtype=successand real write activity (7.75–32.6 min,write_call_count1–16). Sampled rollout logs show Codex improvising subagents via its nativespawn_agent/wait_agenttools (tool namespacemulti_agent_v1) and handlingcross_skill_refby rawsedreads 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, andcross_skill_refinSKILL_CAPABILITY_REGISTRYtocodex_status="not-applicable"+worker_routable=True— the exact REROUTE configurationgit_metadata_writealready uses. Registry-data-only; no routing-logic code change.Mandatory companions:
cross_skill_refdeclaration 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.make-planandinvestigatereroute on a non-Anthropic backend; a Codex-compatible control skill stays;prepare-issuedoes 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).backend_override_activatedlog call (tools_execution.py:845-853) currently emits onlyreason,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 session3958e362)._provider_aware_capability_overridesbefore the flip: its trigger (_auto_overrides.py:93-119) loops over ALLrun_skillsteps and fires on ANYworker_routable=Truecapability, then sets the git-specific ingredientbackend_supports_git_write="true"— the sole member ofBACKEND_CAPABILITY_INGREDIENTS. Post-flip, a non-git skill alone (e.g.make-planinresearch-implement.yaml:185) would satisfy the trigger and can authorizeskip_when_false: inputs.backend_supports_git_writesteps on non-git grounds. Scope the trigger togit_metadata_write-declaring steps (or generalize the ingredient model) so a git-specific ingredient cannot be set by unrelated capabilities.open_kitchenwarning whenbackend=codexand theclaudebinary is absent. Post-flip, the fail-closed check (tools_execution.py:813-825,SkillResult.crashed) would otherwise crash nearly every step of theimplementation,implementation-groups,remediation, andmerge-prsrecipes on claude-less Codex hosts — the flip converts theclaudeCLI from an optional to a de facto mandatory dependency on Codex kitchens.tools_fleet_dispatch.py:445-468keysprovider="anthropic"on the orchestrator's backend capability — rerouted workers bypass all quota I/O); (b) model-string normalization on reroute — a Codex-nativedefault_model(e.g.gpt-5.6-solpost-[FIX] Route Codex aliases to GPT-5.6 Sol #4220) passes unchanged intoclaude --model gpt-5.6-sol; recipe-declared canonical aliases (sonnet/opus/opus[1m]) are safe.Breakage Analysis (summary)
required_backendsreturnsfrozenset()both forfix-required(today) and fornot-applicable+worker_routable=True(REROUTE), so every consumer and test keyed onbackend_requirementsis invariant to the flip; registry invariant tests are satisfied by construction. Notably, no negative-guard test pins the current no-reroute behavior for these three capabilities (unlike the deliberateopen_kitchen/github_api_writemust-not-route tests) — nothing pins against the change, and nothing would catch a mistake in it either.ef64b03b-e68c-4729-b73a-56413b6a92b6hit the explicit Claude session limit during this issue's own investigation,api_retry_exhausted=trueafter 917.51s), and the quota guard cannot see rerouted workers. Capacity impact modeling is a rollout prerequisite for Codex-primary fleets.HOOK_REGISTRYfix-required matcher gate inside_check_backend_compat(tools_execution.py:141-154) evaluates the effective (post-override) backend's guards; inert today only becauseHOOK_REGISTRYhas zero fix-required entries.Acceptance Criteria
agent_subagent,agent_model, orcross_skill_refactivate the existing Claude Code worker route when the active backend cannot provide those capabilities; the Codex parent remains the orchestrator.make-planandinvestigateno longer launch as Codex workers solely because the parent kitchen is Codex.skill_requirementand the triggering capability set, and the line is present in per-session audit artifacts.make-plan(reroutes),investigate(reroutes), one Codex-compatible control skill (stays), andprepare-issue(stays — does not reroute).claudeCLI on a Codex kitchen is surfaced at doctor/open_kitchentime, not as mid-pipelineSkillResult.crashedfailures.task test-checkpasses.Relationship to Existing Issues
_CODEX_API_ERROR_PATTERNS).worker_routable.success; (b) staleghOAuth token operational issue.Investigation