Capability Admission Provider Override Remediation#4168
Merged
Trecek merged 8 commits intoJul 2, 2026
Merged
Conversation
The capability admission system bailed on the first guarded step lacking an ANTHROPIC_BASE_URL provider override, even when other guarded steps had valid overrides. This caused dispatch_infeasible for codex whenever users configured only the primary implement step. Changes: - _provider_aware_capability_overrides now iterates all guarded steps and flips to 'true' if ANY has ANTHROPIC_BASE_URL (any-suffices) - Guard reference is data-driven via CAPABILITY_INGREDIENT_TO_SKIP_GUARD instead of hardcoded string - Resolution paths renamed: all_pass→any_pass, partial_bail→none_pass - Production consumers updated to check for 'none_pass' Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New tests verify any-suffices semantics flip capability when any guarded step has ANTHROPIC_BASE_URL - New structural test ensures _provider_aware_capability_overrides does NOT hardcode 'inputs.backend_supports_git_write' and references CAPABILITY_INGREDIENT_TO_SKIP_GUARD - Replace hardcoded _GIT_WRITE_STEPS with dynamic discovery from real recipe - Add dispatch_feasible assertion to composition matrix for codex+gate case - Update existing tests for renamed resolution paths (any_pass/none_pass) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lementation - Inline CAPABILITY_INGREDIENT_TO_SKIP_GUARD reference into function body so arch test AST inspection finds it (was module-level _SKIP_GUARD_REFS) - Fix escape_hatch test paths 2 & 3: mock resolvers now return no base URL to properly test none_pass infeasibility path with any-suffices semantics - Fix real recipe test: mock checks step_name instead of step_provider since real recipe steps don't have inline provider attributes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…test - Capture detail in test_provider_aware_capability_override_all_overridden_returns_true and assert resolution_path == "any_pass" and bail_step is None, matching other any_pass path tests. - Add standalone parametrized test_dispatch_feasible_per_backend validating dispatch_feasible across all (recipe, backend) combinations.
The KNOWN_BROKEN xfail marks for #4069 cover validation issues (all-dispatchable-stops-have-sentinel + dead-output) that don't affect dispatch feasibility. The dispatch check passes for agent-eval and skill-eval, causing XPASS(strict) failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…n capability admission tests - Swap assertion order in test_provider_aware_capability_override_partial_overrides_flips_true so isinstance guard precedes attribute access (matching sibling tests) - Add missing isinstance guard in test_real_recipe_single_provider_override_dispatch_feasible - Remove "Test 1a/1b/1e (new)" numbering labels and "Previously" clause from docstrings - Add CapabilityResolutionDetail import for the isinstance guard Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…to medium _discover_git_write_steps performs real filesystem I/O via builtin_recipes_dir() + load_recipe(), which violates the small marker contract (no persistent I/O). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ices semantics Replace stale "partial-overrides bailout" terminology with "capability resolution failure" to match the renamed any_pass/none_pass resolution paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Jul 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two test coverage gaps from the capability admission provider override audit:
test_provider_aware_capability_override_all_overridden_returns_truediscards theCapabilityResolutionDetailwith_instead of capturing and assertingresolution_path == "any_pass"andbail_step is None— inconsistent with every other test in the file that exercises_provider_aware_capability_overrideswith a truthy result.The standalone parametrized test
test_dispatch_feasible_per_backendwas never added. The dispatch-feasibility assertion was embedded as a conditional block insidetest_recipe_backend_matrix_cell, but the plan required a dedicated test function to isolate dispatch feasibility validation across all (recipe, backend) combinations.The capability admission system in
_provider_aware_capability_overridesuses all-or-nothing logic: it bails on the first guarded step lacking anANTHROPIC_BASE_URLprovider override, even when other guarded steps have valid overrides. This causesdispatch_infeasiblefor the codex backend whenever users configure only the primaryimplementstep with a provider profile — the secondary steps (retry_worktree,fix, etc.) have no overrides, triggeringpartial_bail.The architectural weakness is threefold:
gate_backend_writecallable provides per-step defense-in-depth)._provider_aware_capability_overrideshardcodes"inputs.backend_supports_git_write"instead of iteratingCAPABILITY_INGREDIENT_TO_SKIP_GUARD, making it silently ignore future capability ingredients._GIT_WRITE_STEPSsets that become stale when recipe steps change — and the tests that use real recipes only assertvalid=True, notdispatch_feasible.This plan provides architectural immunity by making the provider-aware override data-driven and any-suffices, replacing hardcoded step lists with dynamic discovery, and adding a structural sync test that fails immediately when the chain drifts.
Requirements
A. Diagnostics completeness in
_provider_aware_capability_overrides(blast radius: LOW)Prerequisite: applies on top of #4166 (origin/develop) —
CapabilityResolutionDetaildoes not exist at 0.10.833.src/autoskillit/server/tools/_auto_overrides.py) from bail-on-first-miss to full enumeration somissing_provider_stepsreports ALL uncovered steps. Today the envelope names only the first uncovered step, forcing config whack-a-mole: a user coveringretry_worktreeis next told about the next uncovered step, oneopen_kitchenround trip at a time (8 total for a partial config). Verified: the three envelope branches (tools_kitchen.py,tools_recipe.py,tools_fleet_dispatch.py) read onlyresolution_path/missing_provider_steps— zero production consumers break; at most 3 mechanical test updates (tests/server/test_capability_admission_e2e.py:611-612,755,815) ifbail_stepis removed/renamed per the no-dead-fields rule; docstrings in_auto_overrides.py:62andcore/types/_type_results.py:225go stale and must be updated.tools_fleet_dispatch.py,_capability_overridesstarts{}and is populated in a try/except; on exception it stays falsy andfleet/_api.py'sprovider_capability_overrides or _build_capability_overrides(...)silently falls back to the non-provider-aware computation — fleet dispatches would seebackend_supports_git_write=falseeven with a correct user config. Pre-existing defect; add an explicit sentinel or structured log.B. Test-seam and contract hardening
The structural hole: no test wires real
ProvidersConfig→ real_provider_aware_capability_overrides→ realload_and_validate→open_kitchen. Server tests hardcodeload_and_validatereturns; the only real-recipe server test setsrecipes.find=None(bypassing the provider-aware branch); recipe tests inject the capability answer directly; unit tests patch_resolve_provider_profileand use synthetic inlineprovider:fields real recipes don't have (Tier 3 vs the real Tiers 0–2). This is why three PRs shipped green while user-facing behavior flipped each time.tests/server/test_capability_admission_e2e.py, markmedium): partial and full/wildcard config shapes — realProvidersConfig(assert viaresolved_profiles[...].raw_env["ANTHROPIC_BASE_URL"]), real recipe steps viaautoskillit.recipe.io.load_recipe(...), realload_and_validate; no mocking of_resolve_provider_profileorload_and_validate. Parametrize to includeremediation(guarded step names differ:assess/merge_gate_assessvsfix/merge_gate_fix)..autoskillit/test-filter-manifest.yamlmapssrc/autoskillit/recipes/*.yaml→recipe/+contracts/only; addserver/test_capability_admission_e2e.pyso recipe YAML changes run the admission tests (single-file entries are valid; the existence guardtest_manifest_entry_path_existspasses).test_codex_backend_reachable_gate_returns_infeasible(tests/server/test_capability_admission_e2e.py:34) documenting the canonical contract and the 4-PR flip history, so any future assertion flip requires editing an explicit decision record. (A new arch-layer behavioral test is NOT the right home:tests/arch/test_capability_admission_control.pyissmall-marked/AST-structural, and duplicating the existing assertion violates redundancy rules.)tests/config/test_providers_config.py):ANTHROPIC_BASE_URLin a profile propagates intoresolved_profiles[...].raw_env— the key the entire admission path gates on, currently untested._auto_overrides.pyandtools_execution.py(~line 762) gate on the same"ANTHROPIC_BASE_URL"key. A behavioral round-trip test requires extracting the inline predicate attools_execution.py:762-767into a helper — a production refactor to decide during planning.C. Decision record + process
docs/decisions/0005-…): the codex dispatchability contract — codex + no overrides → infeasible; codex + all 9 guarded steps covered → feasible; codex + partial → infeasible with complete enumeration. Must also record the schema question any future relaxation (e.g. reachability-weighted admission) needs answered first: isreview_pr.on_result[changes_requested]a happy-path or failure-path edge for admission purposes? No ADR currently answers any of this; every prior investigation re-derived the contract from the latest symptom._provider_aware_capability_overrides); the mislabel originated in issue Revert #4162: _gate_reachable_post_prune blocks working Codex+MiniMax pipeline — add provider-aware capability gate exemption #4163's framing, propagated through make-plan, and passed audit-impl (which validates diff-vs-plan, and the plan repeated the claim). Add a check that scope claims ("test-only") match changed paths.Explicitly out of scope (evaluated and killed)
.git(resolve_reviewfires on ~75% of historical runs → mid-pipeline waste, the original [FIX] Rectify: Capability Admission Control at Recipe Load — Refuse DOA Pipelines #4094 problem). Already rejected in _provider_aware_capability_overrides all-must-pass logic blocks Codex pipeline when only implement has provider override #4165's adversarial addendum.resolve_review,merge_gate_fix,rebase_conflict_fixenter via ordinaryon_resultconditions indistinguishable from success routes in_build_success_step_graph); the globalbackend_supports_git_writeingredient unfences all guarded steps on flip; ~25skip_when_falseoccurrences + contract regeneration across 3+ recipes. Blocked on the ADR question above."*"config as recommended guidance — works, but empirically reroutes 19 non-guarded steps (plan,verify,audit_impl,review_pr, diagnostics) to the override profile's model; keep the error-message example but the enumeration fix (A.1) makes surgical per-step config practical.Closes #4167
Implementation Plan
Plan files:
/home/talon/projects/autoskillit-runs/remediation-20260701-211618-282393/.autoskillit/temp/rectify/rectify_capability_admission_provider_override_2026-07-01_213500.md/home/talon/projects/autoskillit-runs/remediation-20260701-211618-282393/.autoskillit/temp/make-plan/remediation_capability_admission_provider_override_plan_2026-07-01_224500.md🤖 Generated with Claude Code via AutoSkillit
Token Usage Summary
* Step used a non-Anthropic provider; caching behavior may differ.
Token Efficiency
Model Usage Breakdown