| name | remove-mlinter-rule |
| description | Retire a TRF rule from the mlinter. Marks the rule deprecated in rules.toml, deletes its module and tests, and records the removal in the CHANGELOG. Use when asked to remove, retire, drop, or delete a rule. |
Remove Mlinter Rule
Input
<rule id>: the rule to retire, e.g. TRF054. Accept a bare number (54) and normalise it to
TRFXXX, zero-padded to three digits.
- Optional: the reason for the removal. Ask for one if none is given — it becomes the CHANGELOG entry
and the tombstone description, and it is the only record contributors will have of why the rule went
away.
Why a tombstone and not a deletion
Rule ids are referenced from outside this repo: # trf-ignore: TRFXXX comments in the transformers
tree, CI configs, and copies of rules.toml passed via --rules-toml. So a removal keeps a tombstone
entry in rules.toml instead of deleting the table:
- The engine drops a deprecated id from
TRF_RULES, TRF_RULE_SPECS, TRF_RULE_CHECKS,
DEFAULT_ENABLED_TRF_RULES, the mlinter.TRFXXX public constants, and --list-rules. Projects that
still suppress or configure the id are silently unaffected.
- The docs site is the exception: it keeps publishing a page for the id, built from the tombstone and
listed under
Removed rules on the rule index. A number that used to fire has to stay findable by
whoever meets it in an old CI log.
- Asking for it explicitly (
--enable-rules TRFXXX, --rule TRFXXX) fails with exit code 2.
- A rules TOML that still lists the id as an active rule fails the whole run with exit code 2. The
bundled
rules.toml is the authority here, so this holds for custom files too.
- Leaving
trfXXX.py on disk while the id is deprecated is also an error, which is what makes a
half-finished removal impossible to ship.
Never reuse a retired number for a new rule: the tombstone stays forever, and add-mlinter-rule picks
the next number after the highest trf*.py.
Workflow
-
Confirm the rule exists and read it.
grep -n "\[rules.TRFXXX\]" mlinter/rules.toml and read the whole table plus mlinter/trfXXX.py.
- If the id is already marked
deprecated = true, stop and report that it is already retired.
- Summarise for the user what the rule checks and any
allowlist_models / cutoff_date it carries,
so they can confirm this is the rule they mean before anything is deleted.
-
Replace the TOML table with a tombstone in mlinter/rules.toml.
-
Delete the rule module.
git rm mlinter/trfXXX.py
-
Delete the tests.
- Delete the rule's own test file,
tests/test_trfXXX.py.
- Remove the id from the public-API tests: the
assertEqual(public_api.TRFXXX, "TRFXXX") line and the
assertIn("TRFXXX", public_api.__all__) line.
grep -rn "TRFXXX" tests/ mlinter/ must come back empty except for the tombstone in rules.toml.
Watch for helper fixtures or shared source strings that only that rule used, and for any other rule's
test that happened to reference it.
- No new test is needed for the removal itself:
test_bundled_deprecated_rules_are_fully_retired loops
over every tombstone in the bundled rules.toml and asserts the module and the public constant are
gone, so it starts covering the new id automatically.
Reference
- Rule metadata and tombstones:
mlinter/rules.toml
- Deprecation handling:
_load_rule_specs, _build_rule_checks, _validate_rule_ids, and
BUNDLED_DEPRECATED_TRF_RULES in mlinter/mlinter.py
- Public API surface:
mlinter/__init__.py
- Rule tests:
tests/test_trfXXX.py
- General linter tests:
tests/test_mlinter.py (engine behaviour under "Deprecated rules")
- The inverse skill:
.ai/skills/add-mlinter-rule/SKILL.md