On by default, and it works offline. The catalog ships inside the binary, so
unlike the CVE overlay this needs no network and survives
--offline. Disable it with --no-eol.airom fs .
States
retired is derived at scan time from the shutdown date rather than stored, so a
curated record stays truthful as time passes: a deprecated entry becomes
retired on its own date with nobody re-editing it.
The honesty contract
- Every record is transcribed from the provider’s own deprecation page, carrying that URL and the date a maintainer verified it. A catalog file missing either is rejected at load. Nothing is inferred from naming patterns.
- Matching is exact, case-folded, explicit aliases only. A wrong retirement date is worse than no date.
- Platforms are scoped. Amazon Bedrock, Google Vertex, and Azure OpenAI publish their own schedules for the same weights, so their provider keys deliberately do not match these records.
- Migration advice carries the target’s state — providers point a deprecation
at whatever was current when they wrote it, then deprecate that too, so the
output says
gpt-5.1-chat-latest (retired)rather than sending you onto a model that is already gone. - Staleness is visible. If the least-recently-verified provider is more than 90 days old, the scan says so rather than quietly serving data that may have moved — naming the lever that actually refreshes this catalog (see below).
How it appears in output
- Table
- CycloneDX
- SARIF
- Native JSON / YAML
An
EOL column (retired / 87d), a Model lifecycle block in the summary
panel, and the detail table above with per-provider source footnotes.The CI gate
eol:<state> is a threshold, matching the cve:<severity> convention:
eol:deprecated fires on deprecated and retired.
eol:before:<YYYY-MM-DD> is the planning gate, and the one worth putting in a
release checklist: “fail if anything we ship depends on a model that dies before
our next train leaves.” before:D means “not still serving on D”, so a model shutting down exactly on D
matches — the tool already calls that day retired, and the gate must agree. A
retired model matches any date (already gone, dated or not); only an undated
deprecation matches nothing, because it cannot answer without inventing a
deadline the provider never announced.
Gating on a state that is not a finding (eol:supported, eol:unknown) is a
usage error, as is gating on eol while --no-eol is set, or &-combining an
eol selector with a cve one — lifecycle applies to hosted models and CVEs to
versioned packages, so no single component is both. All are rejected at parse
time: a gate that can only ever pass is worse than no gate.
Coverage
The catalog seeds OpenAI and Anthropic, the two providers whose deprecation pages publish structured, dated schedules. It is deliberately not a list of every model in existence: each record is hand-verified, and the cost of that discipline is coverage. A model outside it reportsunknown, which is the
honest answer.
Adding a provider is a data change, not a code change.
Where the catalog comes from
Retirement dates move on a provider’s calendar, not on AIROM’s release schedule, so the catalog is delivered two ways:
The two are merged per provider: a bundle shipping
eol/openai.yaml alone
says “here is newer OpenAI data”, not “Anthropic no longer has retirement
dates”, so untouched providers keep their embedded records. Within a provider
the bundle wins entirely. --no-cached-rules pins the scan to the embedded
catalog.
It is ed25519-verified like the rule packs, so a fresher catalog is not a less
trusted one. A malformed bundle catalog is ignored with a warning in the scan
output (Stats.Warnings, not just stderr) and the embedded catalog is used —
a bad publish must not be worse than an old binary, or quieter.
The staleness warning names whichever lever applies, so it never sends you in a
circle. A catalog can also be validated before publishing: