Files
ersatztv/scripts/tests/test_build_catalog.py
T
timothy 0ad02db651 feat(603): adopt OKF's optional stale-after and Sources decision-record metadata
Evaluated the Open Knowledge Format (GoogleCloudPlatform/knowledge-catalog okf
v0.2, scaccogatto/okf-skills) as a replacement for our decision-record system and
rejected it: its conformance rules are deliberately permissive exactly where ours
are strict (broken links, unknown types and missing fields must all be tolerated;
`deprecated` points at no successor), and its stable identity is the file path,
which the breadcrumb rule tells agents not to trust.

Adopted two of its optional families instead, additively:

- `stale-after: YYYY-MM-DD` on the metadata line — marks a record asserting an
  outside-world fact as due for re-confirmation. Absolute date, no TTL.
- `**Sources:**` in the metadata block — the evidence a record rests on, as
  distinct from `Signals:` (recall keywords).

Neither is required; absence is never an error. A malformed `stale-after` is
blocking (it would silently never fire), but a past-due record is only a
non-blocking `::notice::` — going stale is the passage of time, not a defect in
whatever commit is under test. The catalog's new "Review due" section renders the
date only and never a clock-derived verdict, so it cannot drift `--check` red on a
calendar boundary with no commit touching the corpus.

No backfill: no existing record adopts either field here.

fixes #603
2026-07-25 15:22:50 +02:00

93 lines
3.0 KiB
Python

from pathlib import Path
from typing import Any
import scripts.build_decisions_catalog as bc
import scripts.decisions_lib as dl
def test_catalog_lists_only_active_sorted_by_key():
recs = [
dl.Record(
heading="H2",
source=Path("x"),
lineno=1,
key="z.a",
status="active",
rule="Zeta rule",
),
dl.Record(
heading="H1",
source=Path("x"),
lineno=1,
key="a.b",
status="active",
rule="Alpha rule",
),
dl.Record(
heading="Old",
source=Path("x"),
lineno=1,
key="a.b",
status="superseded",
rule="old",
),
]
out = bc.render_catalog(recs)
assert "a.b" in out and "z.a" in out
assert out.index("a.b") < out.index("z.a") # sorted
assert "Alpha rule" in out and "Zeta rule" in out
assert "old" not in out # superseded excluded
assert "GENERATED" in out # do-not-edit banner
def test_anchor_matches_gitea_double_hyphen_slug():
# Ground truth: Gitea does NOT collapse hyphen runs. " — " (space, em dash, space) becomes
# "--" in the anchor (one hyphen per space/dash char), never collapsed to a single "-".
a = bc._anchor(
"2026-07-19 — CI `test` job reports a sampled true peak-anon, not cache-inflated `memory.peak` (#412)"
)
assert a == ("2026-07-19--ci-test-job-reports-a-sampled-true-peak-anon-not-cache-inflated-memorypeak-412")
b = bc._anchor("2026-07-16 — Optional advertised IPTV base URL (`iptv.base_url`)…")
assert "iptvbase_url" in b
def _r(key: str, **kw: Any) -> dl.Record:
base: dict[str, Any] = dict(
heading=f"H {key}",
source=Path("decisions.md"),
lineno=1,
key=key,
status="active",
rule="r",
)
base.update(kw)
return dl.Record(**base)
def test_review_due_section_lists_dated_records_soonest_first():
out = bc.render_catalog(
[
_r("b.later", stale_after="2027-03-01"),
_r("a.sooner", stale_after="2026-09-01"),
_r("c.undated"),
]
)
assert "## Review due" in out
assert out.index("2026-09-01") < out.index("2027-03-01")
assert "c.undated" not in out.split("## Review due")[1]
def test_review_due_section_omitted_when_no_record_is_dated():
assert "## Review due" not in bc.render_catalog([_r("a.b")])
def test_catalog_is_date_independent():
"""The generated file must never bake in 'today' — CI checks it with --check, so a
time-dependent render would drift red on a calendar boundary with no commit touching it."""
past = bc.render_catalog([_r("a.b", stale_after="2020-01-01")])
future = bc.render_catalog([_r("a.b", stale_after="2099-01-01")])
# A long-past and a far-future date must produce byte-identical output apart from the date
# itself: no stale/fresh verdict, no marker, nothing derived from the clock.
assert past.replace("2020-01-01", "D") == future.replace("2099-01-01", "D")