Problem
A source file can declare @adr 0007 while ADR-0007 is superseded by ADR-0019. Since #39 the governance surfaces are status-aware, and #95/#106/#109 gave us inbound markers with a format-aware scan — so a stale marker's record is at least no longer rendered as governing. But the marker line itself keeps asserting the dead id in source, and no diagnostic ever tells the author to fix it. That is the worst failure mode for a decision system — the code actively asserts stale governance, which is more misleading than no marker at all. Anyone reading the file directly (humans, or agents that read source rather than calling the tools) inherits the stale assertion.
Proposal (part A — stale-marker lint, deterministic, no new schema)
New diagnostic in adr lint / adr check:
src/auth/session.ts:3 stale-marker @adr 0007 is superseded by 0019 — update the marker or re-affirm 0007
Resolution is a pure join: marker id → record status → follow the supersession link to the live successor. Severity: warning by default, --strict promotes to error for CI. deprecated and rejected markers get the same treatment with their own message. Zero model/network calls, consistent with ADR-0009.
Prior art: Hunch (git-native engineering memory, TypeScript) ships exactly this as its anchor-stale / doc-anchor-stale drift kinds — deterministic marker→graph joins, CI-gated, healed by a guided command rather than silent rewrite. Happy to port the approach; the marker resolver from #106 and the format-aware scan from #109 give us the marker side for free, and supersededBy is already in the schema for the join.
Proposal (part B — optional follow-up: as-of resolution)
Because every record already carries date and a supersession link, a valid-time window is derivable with no schema change: a record's window opens at its date and closes at its successor's date. That makes this answerable:
adr explain src/auth/session.ts --as-of 2026-03-01
adr explain src/auth/session.ts --as-of a1b2c3d # resolve ref → commit date via git
"Which decisions governed this file when this code was written?" is the question every archaeology session asks, and no ADR tool currently answers it. The bi-temporal model is well established (Zep/Graphiti's temporal knowledge graph, arXiv:2501.13956); Hunch has this in production over the same shape of data (windows closed at successor's effective date, never deleted; legacy records with unknown close dates stay null = open so they remain visible to time-travel rather than silently vanishing — that last edge case matters and is easy to get wrong).
Part A stands alone; part B builds on it. I can implement either or both — part A first as a small PR if that ordering suits.
Problem
A source file can declare
@adr 0007while ADR-0007 issupersededby ADR-0019. Since #39 the governance surfaces are status-aware, and #95/#106/#109 gave us inbound markers with a format-aware scan — so a stale marker's record is at least no longer rendered as governing. But the marker line itself keeps asserting the dead id in source, and no diagnostic ever tells the author to fix it. That is the worst failure mode for a decision system — the code actively asserts stale governance, which is more misleading than no marker at all. Anyone reading the file directly (humans, or agents that read source rather than calling the tools) inherits the stale assertion.Proposal (part A — stale-marker lint, deterministic, no new schema)
New diagnostic in
adr lint/adr check:Resolution is a pure join: marker id → record status → follow the supersession link to the live successor. Severity: warning by default,
--strictpromotes to error for CI.deprecatedandrejectedmarkers get the same treatment with their own message. Zero model/network calls, consistent with ADR-0009.Prior art: Hunch (git-native engineering memory, TypeScript) ships exactly this as its
anchor-stale/doc-anchor-staledrift kinds — deterministic marker→graph joins, CI-gated, healed by a guided command rather than silent rewrite. Happy to port the approach; the marker resolver from #106 and the format-aware scan from #109 give us the marker side for free, andsupersededByis already in the schema for the join.Proposal (part B — optional follow-up: as-of resolution)
Because every record already carries
dateand a supersession link, a valid-time window is derivable with no schema change: a record's window opens at itsdateand closes at its successor'sdate. That makes this answerable:"Which decisions governed this file when this code was written?" is the question every archaeology session asks, and no ADR tool currently answers it. The bi-temporal model is well established (Zep/Graphiti's temporal knowledge graph, arXiv:2501.13956); Hunch has this in production over the same shape of data (windows closed at successor's effective date, never deleted; legacy records with unknown close dates stay
null= open so they remain visible to time-travel rather than silently vanishing — that last edge case matters and is easy to get wrong).Part A stands alone; part B builds on it. I can implement either or both — part A first as a small PR if that ordering suits.