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
93 lines
3.0 KiB
Python
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")
|