Reconciliation: shipped rules against the new catalog¶
This document maps each of the 19 shipped rule codes in
src/humansays/catalog.py to its fate in the new 158-rule catalog published
under docs/site/planned/. The mapping follows a two-hop join: a shipped
HS0NN code matches a prototype PY0NN check by name and behavior, §8 of
NEW_RULES.md crosswalks that prototype to one or more HS-DOMAIN-NN
provenance slugs, and §9 of NEW_RULES.md resolves each slug to a final
DOMAIN### rule or an internal evidence ID.
Two disposition facts from docs/site/planned/index.md govern the last
column. A hint is "emitted by the review profile; intentionally unweighted"
and does not count toward a score. evidence is "hidden unless cited by a
finding or requested with --show-evidence" and also does not count toward a
score. Both are demotions from the shipped model, where every rule was scored:
each shipped warning carried weight 3.0 and each advisory carried weight
1.0.
Full mapping¶
| Shipped | Signal | Prototype | Source slug | New ID | Disposition | What changes for a user |
|---|---|---|---|---|---|---|
| HS001 | many-arguments | PY001 | HS-ARGS-01 | CONTRACT003 | on | No change. Stays a scored, selectable rule. |
| HS002 | boolean-modes | PY002 | HS-ARGS-03 | KISS003 | on | No change. Stays a scored, selectable rule. |
| HS003 | deep-nesting | PY003 | HS-SHAPE-03 | kiss.deep_nesting | evidence | No longer a standalone scored rule. Becomes hidden evidence that surfaces only when cited by a finding or with --show-evidence. |
| HS004 | shared-mutable-state | PY004 | HS-STATE-06 | STATE006 | on | No change. Stays a scored, selectable rule. |
| HS005 | broad-exception | PY005 | HS-FAIL-01/02/03 | FAIL004 (+ 2 evidence) | on (split) | The swallowed-exception case stays scored as FAIL004. The logged-only and re-raised variants become hidden evidence (fail.broad_exception_logged_only, fail.broad_exception_reraised). |
| HS006 | multiple-mutation-owners | PY006 | HS-STATE-04 | state.multiple_mutation_owners | evidence | No longer a standalone scored rule. Becomes hidden evidence. The concern re-surfaces through the "missing state owner" finding (STATE011). |
| HS007 | mixed-boundaries | PY007 | HS-EFFECT-06, HS-FIND-01/02 | SRP003, FAIL008 (+ 1 evidence) | on (split) | The raw mixed-boundary signal becomes hidden evidence (srp.mixed_effect_boundaries). Its two findings stay scored: mixed responsibilities (SRP003) and side-effect orchestration risk (FAIL008). |
| HS008 | low-class-cohesion | PY008 | HS-CLASS-01, HS-FIND-05 | SRP005, SRP008 | on (split) | No loss of scoring. Splits into two scored rules: low field cohesion (SRP005) and incohesive class (SRP008). |
| HS009 | long-function | PY009 | HS-SHAPE-01 | kiss.long_function | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
| HS012 | many-class-attributes | PY012 | HS-CLASS-03 | srp.many_class_attributes | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
| HS013 | attribute-prefix-cluster | PY013 | HS-CLASS-05 | srp.attribute_prefix_cluster | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
| HS014 | validated-argument-bundle | PY014 | HS-INIT-07 | contract.validated_argument_bundle | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
| HS015 | static-method | PY015 | (none in §9) | NIT022 | hint | No longer contributes to the score. Becomes an unweighted reviewer hint in the review profile. |
| HS016 | lambda-expression | PY016 | (none in §9) | NIT023 | hint | No longer contributes to the score. Becomes an unweighted reviewer hint in the review profile. |
| HS017 | long-file | PY017 | HS-SHAPE-10 | kiss.long_module | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
| HS018 | many-base-classes | PY018 | HS-CLASS-08 | srp.many_base_classes | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
| HS019 | many-branches | PY019 | HS-SHAPE-04 | kiss.many_branches | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
| HS021 | lazy-import | PY021 | (none in §9) | IDIOM016 | hint | No longer contributes to the score. Becomes an unweighted reviewer hint in the review profile. |
| HS022 | dense-function | PY022 | HS-SHAPE-02 | kiss.dense_function | evidence | No longer a standalone scored rule. Becomes hidden evidence. |
Note on the three hint rows: §8 crosswalks PY015, PY016, and PY021 to "NIT
rule" or "IDIOM rule; reviewer hint only" without a DOMAIN### ID, and those
three IDs do not appear in the §9 ledger. The specific IDs come from the domain
pages themselves. docs/site/planned/nit.md lists NIT022 ("Stateless
method declared on a class", "Prototype PY015") and NIT023 ("Named behavior
expressed as lambda", "Prototype PY016"). docs/site/planned/idiom.md
lists IDIOM016 ("Import inside function or method", "Prototype PY021"). All
three carry default = hint.
The three gaps in the shipped numbering¶
The shipped codes skip HS010, HS011, and HS020. These line up with the three
prototype checks §8 marks omitted:
- PY010 (comments): "raw comment count was noisy and duplicated narration evidence."
- PY011 (docstrings): "raw docstring count did not establish a structural problem."
- PY020 (future annotations): "version-dependent modernization belongs to Ruff and loses value on newer Python."
These were never shipped, so nothing is lost for a user of the shipped tool.
What to keep from the drop list¶
No shipped rule is removed from the catalog. Every one of the 19 survives as a scored rule, an unweighted hint, or hidden evidence. The judgment calls are about demotion from scored to unscored, not deletion.
The three hint demotions look right¶
The brief flagged HS015, HS016, and HS021 as the most user-visible change. Their demotion to unweighted hints is defensible:
- HS015 static-method and HS016 lambda-expression shipped with confidence 0.99 and weight 3.0. High detection confidence is not the same as high concern. A static method on a class and a lambda holding named behavior are both style positions, not correctness or hazard signals. NIT is explicitly "deliberately opinionated reviewer hints", which is the right home for them. Keeping them visible but unweighted preserves the prompt to a reviewer without letting a stylistic preference move a score.
- HS021 lazy-import shipped as advisory weight 1.0. Lazy imports are frequently correct: they break import cycles and defer optional dependencies. IDIOM016's message even carves out "configured optional-dependency or cycle-breaking boundaries." A rule that fires on a legitimate pattern belongs as a hint, not a scored finding. This demotion looks right.
If any of the three were to be reconsidered for scoring, IDIOM016 (lazy-import) is the weakest candidate to promote, because the false-positive rate on intentional lazy imports is high. NIT022 and NIT023 would stay in NIT.
The evidence demotions are the larger change and are individually defensible¶
Ten shipped rules dropped from scored to hidden evidence: HS003, HS006, HS009, HS012, HS013, HS014, HS017, HS018, HS019, HS022. This is a bigger shift in scored behavior than the three hint demotions, because it is more rules.
Most of these are raw size or shape thresholds: deep-nesting, long-function, dense-function, many-branches, long-file, many-class-attributes, many-base-classes, attribute-prefix-cluster. A raw threshold on its own is a weak basis for a score, and the new model routes these into KISS and SRP as inputs that findings can cite rather than as standalone penalties. That is a reasonable design and none of them belongs back in the scored set on its own.
Two are worth a second look:
- HS006 multiple-mutation-owners (shipped warning, confidence 0.70) is now
state.multiple_mutation_ownersevidence. The concern it raised is picked up by the "missing state owner" finding (HS-FIND-04 to STATE011, on), so the signal is not lost as long as that finding cites it. If it belonged anywhere as a scored rule again, it would be STATE. - HS014 validated-argument-bundle (shipped warning, confidence 0.88) is now
contract.validated_argument_bundleevidence. This shipped with high weight and confidence, so the demotion is the most aggressive of the ten. A validated argument bundle can be a legitimate pattern, so evidence is the safer default, but if it were promoted it would sit in CONTRACT.
Residual risk this reconciliation cannot close¶
evidence surfaces to a default user only when a finding cites it or when
--show-evidence is passed. For the ten evidence demotions, the concern reaches
a default user only through some retained finding. The §9 ledger records the
disposition of each signal but not which findings cite which evidence, so this
reconciliation cannot confirm, for every evidence row, that a retained finding
actually cites it. Where no finding cites a given piece of evidence, that signal
is effectively silent by default. Confirming the citation edges for the ten
evidence rows is an open item that needs the finding definitions, not the
ledger.
Behavior-change callouts¶
Every case below changes what a shipped user sees or how a score is computed.
Scored to unweighted hint (3 rules):
- HS015 static-method: warning weight 3.0 to NIT022 hint. No longer scored.
- HS016 lambda-expression: warning weight 3.0 to NIT023 hint. No longer scored.
- HS021 lazy-import: advisory weight 1.0 to IDIOM016 hint. No longer scored.
Scored to hidden evidence (10 rules):
- HS003 deep-nesting, HS009 long-function, HS022 dense-function, HS019
many-branches, HS017 long-file, HS012 many-class-attributes, HS013
attribute-prefix-cluster, HS018 many-base-classes: each was scored and is now
kiss.*orsrp.*evidence, hidden by default. - HS006 multiple-mutation-owners: scored to
state.multiple_mutation_ownersevidence. - HS014 validated-argument-bundle: scored to
contract.validated_argument_bundleevidence.
Split, with partial demotion (3 rules):
- HS005 broad-exception: the swallowed case stays scored (FAIL004); the logged-only and re-raised variants become evidence.
- HS007 mixed-boundaries: the raw signal becomes evidence
(
srp.mixed_effect_boundaries); two findings stay scored (SRP003, FAIL008). - HS008 low-class-cohesion: no demotion. Splits into two scored rules (SRP005, SRP008).
No change (4 rules):
- HS001 (CONTRACT003), HS002 (KISS003), HS004 (STATE006) stay scored and selectable. HS005's primary path (FAIL004) also stays scored.
Nothing dropped from the catalog. No shipped rule maps to omitted,
external, or off. The three omitted prototype checks (PY010, PY011, PY020)
correspond to the unused HS010, HS011, and HS020 numbering gaps and were never
shipped.