Repository navigation
fix(cli): bind a model's top-level extra like args.extra - #228
Merged
Merged
Conversation
The configuration guide documents `extra` on a model "top level or
`args`", and the schema check validated both, but model binding read
only `args.extra`. A top-level `extra` was dropped: `Model.extra` was
`{}`, tasks rendered plain prompts, and the inference identity left it
out.
`model_config_extra` (cli/resolution.py) reads either placement and
refuses both at once. `extra` enters the inference identity, so a
silent pick between two values would record a capability set nobody
chose. For other dual-placement keys named models let the top level
win and inline roles let `args` win, but none of those keys is
identity. The refusal fires at schema validation and at
named/inline normalization, before any engine starts.
Every binding path reads it: canonical named models, the sglang_legacy
root and derived paths, and inline roles. A derived model inherits its
base's `extra` unless it sets its own; a task's `infer_args.extra`
replaces the model's.
A config that sets `args.extra` keeps its inference identity.
Closes #227
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Inline grader/extractor configs used to accept both `extra` placements and silently use `args.extra` (`args` is laid over the top level there; named models let the top level win). The CHANGELOG now lists the both-placements refusal as breaking for them too. Pin `model_config_extra`'s null fall-through with unit tests, note why the prelaunch call exists, and tighten the docstring, guide paragraph and CHANGELOG entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ethan-scitix
force-pushed
the
fix/model-top-level-extra
branch
from
October 24, 2026 06:36
d0819e1 to
9e15b03
Compare
Merged
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.
Type
Summary
extraas "top level orargs", and the schema check validated both placements, but model binding read onlyargs.extra. A top-levelextrawas dropped:Model.extra == {}, tasks rendered plain prompts, and the inference identity left it out. This affected the canonical path and bothsglang_legacypaths (root and derived). Inlinegrader/extractorconfigs flattenargs, so they already accepted both placements.model_config_extra(sieval/cli/resolution.py) reads either placement. Every binding path uses it, socheck_extra,Model.extra, the inference identity and--dry-run(which plans through the same session setup) all see the top-level value.argswin, but none of those keys is identity; inlineextraused to silently resolve toargs.extra, so refusing both there is a behaviour change too (in the CHANGELOG).extrais part of the inference identity, so silently picking one of two values would record a capability set nobody chose. The refusal fires at schema validation and at named/inline normalization, before any engine starts. A derived model (base:) inherits its base'sextraunless it sets its own. A task'sinfer_args.extrareplaces the model's. Neither merges keys, as before.args.extra. Themodel_request_argsdigests for a root and a derived model matchmain. A 0.12.0 result directory written from a top-levelextraran without it, so a resume now sees an inference change and is refused (noted in the CHANGELOG).Related Issues
Closes #227
Test Plan
Automated
ruff check && ruff format --check)ty check)pytest tests/unit tests/integration tests/acceptance -m "not stress and not benchmark" -n auto: 9488 passed, 1 failed. The failure istest_exec_quotebench_anchor, a known macOS-only failure. Coverage on unit + integration: 97.11% (gate 95%).pre-commit run -a,scripts/check_preflight.py,scripts/sync_package_stubs.py --checkNew tests (
tests/unit/cli/test_session.py::TestModelExtraPlacement, full session setup through binding):argsbind the sameModel.extraandmodel_request_args()["extra"], on a canonical and ansglang_legacymodel;base:inherits a top-levelextra, and its own top-levelextrareplaces the base's (both paths);infer_args.extrareplaces a top-level modelextraon the task's model and leaves the named model unchanged;tests/unit/cli/test_resolution.py::TestModelConfigExtra: either placement, null on one side defers to the other, both refused.tests/unit/cli/test_validation.py: the schema rejects both placements, and the--dry-runschema check catches a malformed top-level orargsextra, rejects both, and passes a valid top-level one.Ten of the new session tests fail on
main. The four that pass are the inline-placement cases and theargsbaseline.Manual
model_request_argsdigests for anargs.extraroot and derived model are byte-identical before and after.Checklist
Required (all PRs)
type(scope): description)AI-Generated Code - <model> (<provider>)in module docstring (no new modules)core/If: Breaking Change
extraat both placements is now refused; keep one.🤖 Generated with Claude Code