Repository navigation
test(enums): ratchet the two severity-literal shapes the #13597 guard cannot see (#14988, #13597) - #15508
Merged
Conversation
This was referenced Sep 2, 2026
Auto-regenerated (py3.14) to match the backend and/or SLM backend schema so the required verify-generated-types gate(s) pass. Triggered by auto-fix-generated-types.yml.
Contributor
✅ SSOT Configuration Compliance: Passing🎉 No new hardcoded values of either class — Known backlog in |
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.
Thinking Path
The three issues in this cluster describe a severity enum fork set. Measured against
Dev_new_guifirst, before touching anything, because the counts in this repo drift in bothdirections — and here they had drifted in both, plus one whole claim had gone stale.
Measured vs claimed
AlertSeverity/ErrorSeverityare forksSeverity, guardedCausalSeverityis a fourth fork declaring(str, Enum)import Severity as CausalSeverity, but unguardedEnumvs(str, Enum)rule is unstated and blocks the collapse(str, Enum)none10,moderate7,missing2,forbidden1Severitycode_intelligence/share one member setWhat the ratchet's matcher actually matches, quoted from
repo_tests/enum_union_guard_test.py:It requires a quoted key followed by a colon. So it sees a dict entry and nothing else —
every literal written as a keyword argument, an attribute assignment or an equality
comparison is structurally invisible to it. That is why 194 literals sit outside a guard that
reports 25.
The union, enumerated before proposing anything. Canonical
Severityalready carries theunion of every collapsed fork:
UNKNOWNunknownINFOinfoMINIMALminimalLOWlowAlertSeverity,ErrorSeverityWARNINGwarningCausalSeverity, Prometheus label (#14956)MEDIUMmediumAlertSeverity,ErrorSeverityDEGRADEDdegradedCausalSeverity, causal API response (#14956)HIGHhighAlertSeverity,ErrorSeverityERRORerrorCRITICALcriticalAlertSeverity,ErrorSeverity,CausalSeverityNothing was dropped to reach it: all ten rungs are present, and the three names the forks used
(
AlertSeverity,ErrorSeverity,CausalSeverity) still resolve, so no call site broke.The per-value decision #14988 asked for, answered with evidence. All four out-of-vocabulary
words are a different enum's vocabulary in a field named severity — a mis-typed field, not a
missing rung. None of them gets folded in:
forbidden— a dangerous-command grade; that ladder isCommandRisk, which already hasFORBIDDEN. The field is annotatedstrwith the three words in a trailing comment.none/moderate— the delta engine's metric-change classification.nonemeans nofinding at all, which no severity ladder can express.
missing— the env drift detector records a drift kind alongsidetype_mismatchandunknown, not how bad the drift is.That answer is the load-bearing part: the cheapest way to make an out-of-vocabulary count go
to zero is to widen
Severity, which would make the guard read clean while making thecanonical enum mean less. The guard fails if anyone takes that shortcut.
What Changed
repo_tests/severity_literal_shape_guard_test.py(new, 428 lines) — the #14988 guard.and the file spread 48-53. Down only; a conversion run lowers both bounds in one commit.
new bad word fails even while the total stays under the ceiling.
Severityabsorbs any of the four, with the reason for each in thefailure message.
CausalSeverityis still an alias binding (read by AST, so a re-declaration of the namefails), and that the collapse stayed safe — the report serialises
severity.valueand thediagnostics endpoint returns
to_dict(), which is the entire argument for dropping the(str, Enum)base.tracked file as well as against synthetic strings, so a matcher that has drifted away from
what the producers write fails instead of reading clean.
env=scrubbed_git_env()and drops.worktrees/by repo-relativepath.
autobot_shared/status_enums.py— theSeveritydocstring now names the three vocabulariesthat are not severity and points at the guard. This is the discoverability half: the reason
each copy got written was that nothing at the canonical source said what belongs there.
Deliberately not in this PR, with reasons rather than a bundle:
compared to a value that may arrive from outside. A sweep that size cannot get an honest
review pass alongside a guard, and canonical(enums): 169 bare severity literals remain, 43 of them outside the canonical vocabulary #14956's own sweep is the precedent — its regex rewrite
landed inside a documentation JSON body. Ratchet now, drain under canonical(enums): CausalSeverity is a fourth severity fork, and 219 severity literals sit outside the ratchet's matcher #14988.
code_intelligence/severity enums sharing one member set. This is a genuinefork set by the register's rule, but the two issues contradict each other on it — canonical(enums): AlertSeverity and ErrorSeverity duplicate the shared Severity enum, and 119 severity literals bypass enums entirely #13597
says "last and by judgement", the same enum vocabulary is declared twice — API schemas hand-copy domain enums, and six tests copy the production enum they check #14881 says the generic ladders are "not consolidation
candidates". That is an owner decision, not a refactor; posting it on the issue with a
recommendation rather than deciding it inside a PR.
API-schema layer hand-copying domain enums (the schema copies are
(str, Enum), the domaincopies plain
Enum, so importing one into the other changes a response contract); itsGroup 2 is tests copying the production enum they check. Neither is the severity fork set,
its guard is a different mechanism, and the issue itself rules the severity ladders out of
its own scope.
Verification
New guard, clean tree:
24 passed.Existing enum guard unaffected:
repo_tests/enum_union_guard_test.py+ the new file together91 passed. File-size ratchet31 passed(new file 428 lines, no entry added to either halfof the checked pair).
Mutation proof — every assertion made to fail, then reverted.
sweep does not read as clean:
fire:
Severitygiven amoderaterung — the shortcut fix:CausalSeverityre-declared as its own(str, Enum):.value:trap:
Every probe was removed from disk and from the index;
git statusis clean andgit diffonthe two product files touched during mutation is empty.
Pre-existing failure found while verifying, not caused here. The full
repo_tests/run is1 failed, 1230 passed, 17 skipped, 2 xfailed. The failure issdk_response_model_contract_test.py::test_every_sdk_response_model_is_paired_or_explicitly_unpaired,which passes in isolation and fails only after
sdk_request_signature_params_test.pyhas runand left five parameterised generic response aliases in the model registry. Reproduced with
this PR's file excluded from the run, so it is not this change. Filed separately.
Not verified here: nothing in this PR imports backend application code, so CI is the first
place the declared dependency set is exercised. The local run reports 91 of 206 declared
versions unsatisfied.
Refs #13597, Refs #14988
Model Used
Claude Opus 5 (1M context)