fix(xai): scan the primary model.default slot in the retirement migration/doctor check - #55737
fix(xai): scan the primary model.default slot in the retirement migration/doctor check#55737briandevans wants to merge 2 commits into
Conversation
…tion/doctor check
find_retired_xai_refs scanned principal, auxiliary, delegation, tts.xai and
plugins.image_gen.xai — but never the top-level model block, which is the
PRIMARY active-model slot. runtime_provider._get_model_config resolves the
active model from model.default (with model.model as the accepted alias), so
a user with the canonical model: {provider: xai, default: grok-3} got a false
'nothing to migrate' from both hermes migrate xai and hermes doctor after the
May 15, 2026 grok retirement.
Add a model-block scan (placed first, since it is the primary slot) mirroring
_get_model_config's precedence: model.default is canonical, model.model is
consulted only when default is absent. apply_migration's _walk_to_parent
already resolves the 2-segment model.default / model.model paths, so the
apply side rewrites them (and adds the reasoning_effort sibling) unchanged.
There was a problem hiding this comment.
Pull request overview
Fixes a gap in the xAI retirement scanner (find_retired_xai_refs) used by both hermes migrate xai and the hermes doctor xAI-retirement check, ensuring it also detects retired models configured in the primary active-model slot (model.default, with model.model as fallback alias).
Changes:
- Extend
find_retired_xai_refsto scan the top-levelmodelblock, mirroringruntime_provider._get_model_configprecedence (model.default>model.model). - Update the scanner docstring slot list to include the primary
model.defaultslot. - Add/extend unit tests to cover
model.default,model.modelalias behavior, and default-precedence over alias.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
hermes_cli/xai_retirement.py |
Adds scanning of the primary model.default slot (and model.model alias) to prevent false “nothing to migrate” results. |
tests/hermes_cli/test_xai_retirement.py |
Adds targeted coverage for the model-block scan and updates the full-config trap test accordingly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| issues = find_retired_xai_refs(cfg) | ||
| assert len(issues) == 5 | ||
| assert len(issues) == 6 |
Per Copilot review: asserting only the issue count is brittle and breaks whenever slots are added/removed. Assert the exact set of trapped config paths instead — more robust and more informative.
|
@copilot Addressed in commit 9e166fb: |
Related: this overlaps with open #31614, which already adds the same |
|
Thanks @alt-glitch — agreed, #31614 is the broader change here: it also adds apply-side provider-prefix preservation ( Worth flagging the asymmetry for the maintainer pick: #31614 is the superset but has been idle since 2026-05-24 (~39d, unmerged); this PR is fresh and CI-clean. Happy either way — if maintainers prefer #31614 as the canonical fix I'll close this in its favor, or if the apply-side widening stalls, this green subset closes the most common gap (the active |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating the canonical model.default omission. Current main confirms the scanner skips the top-level model block (hermes_cli/xai_retirement.py:92-120) even though runtime resolution uses model.default (hermes_cli/runtime_provider.py:281-299).
Problems
- The new branch only handles mapping-shaped
modelvalues. Runtime still accepts a legacy scalar root model (model: xai/grok-3) athermes_cli/runtime_provider.py:298-299; it would remain undetected and therefore unapplied. Open #31614 already covers that sibling shape and root-path application.
Suggested changes
- Either add scalar-root detection, root-path application, and regression coverage, or keep this as the narrower canonical-dict fix for a maintainer choice alongside #31614.
Automated hermes-sweeper review.
| # Primary active-model slot. Mirror runtime_provider._get_model_config: | ||
| # model.default is canonical, model.model is the accepted alias (only | ||
| # consulted when default is absent). | ||
| model = config.get("model") |
There was a problem hiding this comment.
Completeness: runtime still treats scalar model: xai/grok-3 as the active model (hermes_cli/runtime_provider.py:298-299), but this dict-only branch leaves it undetected. Please either scan/apply that root path too or explicitly leave it to the broader #31614 implementation.
|
Closing to keep my open queue focused and reviewable. This has sat ~2 weeks without any human review interest, and I would rather maintain a small set of actively-reviewed PRs than a large standing backlog. The analysis and branch remain available if anyone wants to pick this up — happy to reopen if it is useful. |
What does this PR do?
find_retired_xai_refs(hermes_cli/xai_retirement.py) powers bothhermes migrate xaiand thehermes doctorxAI-retirement check. It scannedprincipal,auxiliary.<slot>,delegation,tts.xai, andplugins.image_gen.xai— but never the top-levelmodelblock, which is the single most important slot: the primary active model.runtime_provider._get_model_configis the schema source-of-truth here — it resolves the active model frommodel.default, acceptingmodel.modelas an alias only whendefaultis absent. So a user with the canonical config:got a false "No retired xAI models in config — nothing to migrate" from both commands after the May 15, 2026 grok retirement, even though their primary model was retired.
This PR adds a
model-block scan (placed first, since it is the primary slot) that mirrors_get_model_config's precedence:model.defaultis canonical,model.modelis consulted only whendefaultis absent.Mirrors
runtime_provider._get_model_configprecedence:model.default>model.model.Related Issue
Code-originated; found by cross-checking the scanner against
_get_model_config. No filed issue.Type of Change
Changes Made
hermes_cli/xai_retirement.py: scan the top-levelmodelblock infind_retired_xai_refs, emittingmodel.default/model.modelissues per the resolver precedence. Docstring slot list updated.tests/hermes_cli/test_xai_retirement.py: addTestFindRetiredModelBlock(default slot, alias slot, default-precedence-over-alias, valid-not-flagged) and extendtest_full_trap_configto include themodel.defaultslot.The apply side needs no change:
_walk_to_parentalready resolves the 2-segmentmodel.default/model.modelpaths, sohermes migrate xai --applyrewrites them (and adds thereasoning_effortsibling) correctly — verified end-to-end against a sampleconfig.yaml.How to Test
Before the fix,
find_retired_xai_refs({"model": {"provider": "xai", "default": "grok-3"}})returned[]; after, it returns one issue atmodel.default→grok-4.3. The four newTestFindRetiredModelBlocktests fail before the production change and pass after.Checklist
Code
fix(scope):,feat(scope):, etc.)test_xai_retirement.py,test_migrate_xai.py,test_doctor.py) and they passDocumentation & Housekeeping
docs/, docstrings) — updated thefind_retired_xai_refsdocstring slot listcli-config.yaml.exampleif I added/changed config keys — or N/A (no new keys)CONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A