ADR 0014: Filter rules v2, a migration_away label, and a fresh sample to measure them¶
- Status: Accepted
- Date: 2026-10-12
Context¶
The 300-commit validation sample (ADR 0013) was labelled by hand, re-checked, and scored (adjudicated labels):
| Stratum (rules v1) | In full set | Labelled yes |
|---|---|---|
| strict | 10,940 | 86 of 100 (78% to 92%) |
| broad_only | 28,241 | 25 of 100 (18% to 34%) |
| with_ai | 35,318 | 17 of 50 (22% to 48%) |
| rejected | 180,266 | 4 of 50 (3% to 19%) |
Reading the rows by what the rules decided showed three things:
- The "away" direction is the strong signal. Of the 107 sampled rows the v1 rules called "away", 96 were labelled
yes. That includes all 7 "away" rows with an AI-tool trailer, and all 3 "away" rows that were rejected only for being more than 30 days before the notice. - v1 misses common ways of saying a model is gone. Most
yesrows in the broad stratum say so without "from X" or "X to Y": "X was retired", "X is no longer served", "X returns 404", "remove A and X", "Y replaces X". - The migration word adds little once the direction is clear. Every sampled "away" row also had a migration word.
Decision¶
- Rules v2 add four "away" shapes to
research/filtering/rules.py: a statement that the model is gone within 40 characters on the same line (deprecated,retired,discontinued,sunset,removed,shut down,no longer,not available,unavailable,404); a removal verb within 60 characters on the same line (remove,drop,purge,deactivate); "X model to Y"; and "replaces/supersedes X". More adjectives are allowed before an ID ("unavailable model id X"). - A new label,
migration_away: the direction is "away" and the message is not from a dependency bot, whatever the date, the wording or an AI-tool trailer. Kim's labels (migration,migration_strict,migration_with_ai) keep their definitions and now use the v2 direction. labeled.stats.jsonrecordsrules_version: 2.research.validation.dev_checkreruns the rules on the labelled sample. Its numbers are in-sample and used only to develop the rules.- The quality of rules v2 will be measured on a fresh random sample drawn from the v2 labels and labelled blind (next step), not on the 300 rows the rules were tuned on.
Alternatives considered¶
- Re-score v2 on the same 300 rows: cheap, but the rules were written from these rows, so the numbers would be too good. They are reported only as development numbers.
- Keep only Kim's rules: keeps the comparison simple, but the sample shows that the AI-trailer and 30-day exclusions remove real migrations.
migration_awaykeeps them, and the exclusions stay available as flags. - A machine-learning classifier: 300 labels are too few to train and test one honestly. This may be revisited once more labelled data exists.
Consequences¶
- On the labelled sample (in-sample), "away" goes from 96 of 107 rows labelled
yesto 113 of 131, and from catching 96 to 113 of the 132yesrows. The new "gone" shapes also flag some notes and news ("X was retired" in a changelog), which is the main known source of false positives. - The funnel numbers in the paper change, so Step 11's numbers must be reported as rules v1 and the new ones as rules v2.
- The first-pass labels, the AI second rater's reading and the adjudicated labels are all kept, so the re-check can be reported in full (see validation).