llm-ingestion-okf/tests/test_okf_watch.py
Kjell Tore Guttormsen 3233b19b30 feat(watch): weekly OKF upstream watch that can prove it found nothing
The operator asked for a job that checks at least weekly whether Google OKF has
moved, and messages the right repo immediately when it has. It belongs here
rather than in `.claude` because knowing what a meaningful spec change IS
requires owning the pin, the runbook and the always-latest policy.

`tools/okf_watch.py`, stdlib only, driving git against the local read-only
mirror. It lives outside `src/` so it never enters a wheel; a new packaging test
holds that as a promise rather than an accident of the build config.

Three properties carry the design, and each closes a failure this repo has
actually met:

1. A failed call is never an empty result. Every git invocation raises on a
   non-zero exit and carries stderr, so a caller reading "" knows the query ran.
   The precedent is `grep ... | head; echo $?` reporting head's exit status - a
   broken query read as a quiet upstream.
2. It proves it can find, every run. Before believing any zero it re-runs the
   full detect-and-classify path over `ad30107^1..ad30107`, a range known to have
   changed SPEC.md. An empty known-positive aborts loudly rather than reporting a
   clean sweep. Network failure likewise raises; it never degrades to "no change".
3. It reports on change, not on state. A pin-keyed state file records what has
   been announced; moving the pin resets it, because a pin move means everything
   behind it was absorbed.

Quiet is the enumerated list, not signal. Enumerating what counts as normative
can only match what upstream has already invented, so anything new would fall
outside it and the watch would go silent - failing in the direction nobody
notices. A small measured quiet list, everything else reports. README.md is
deliberately not quiet: the repository move was announced in a README commit.

Sixteen tests build their own git repository in tmp_path rather than skipping
when the mirror is absent - a skipped test preserves nothing on the machine
where the dependency exists. All four load-bearing behaviours were mutation-
tested red before this landed.

Two more tests exist because building this fired a real false alarm: running
with `--pin` and without `--dry-run` delivered two live coord messages. The
override now implies dry-run, enforced in argument parsing rather than
remembered, and `.claude` has the correction.

The runbook gains a section stating what the watch CANNOT do, because that is
the part a future session will otherwise assume away: it sees commits, not
meaning. It would have fired on the 2026-08 tightening because SPEC.md changed,
but no commit list says a value that conformed last month no longer does, and
none says is_stale reversed. Its output is "run the runbook", never "here is
your exposure".
2026-08-23 20:38:37 +02:00

223 lines
8.3 KiB
Python

"""The upstream OKF watch: it must be able to prove it can find.
This watch reports a NEGATIVE result almost every time it runs. That is the
whole hazard: a run that never reached the network, or whose query silently
matched nothing, produces the same "no change" as a run that genuinely found
nothing. Trust in an absence that was never measured is worse than no watch,
so every test here is about keeping those two outcomes distinguishable.
The git-backed tests build their own repository in tmp_path. Skipping when
`~/repos/_okf-canonical` is missing would preserve nothing on the machine
where it exists, and pointing them at the real mirror would make the suite
depend on upstream's history.
"""
from __future__ import annotations
import json
import subprocess
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "tools"))
import okf_watch # noqa: E402
# --- the exit-status / empty-result seam -----------------------------------
def _git(repo: Path, *args: str) -> str:
return subprocess.run(
["git", *args], cwd=repo, capture_output=True, text=True, check=True
).stdout
@pytest.fixture
def repo(tmp_path: Path) -> Path:
"""A repository with one quiet commit and one normative commit."""
r = tmp_path / "upstream"
r.mkdir()
_git(r, "init", "-q", "-b", "main")
_git(r, "config", "user.email", "t@example.invalid")
_git(r, "config", "user.name", "t")
(r / "SPEC.md").write_text("Version 0.2\n", encoding="utf-8")
(r / "CONTRIBUTING.md").write_text("hello\n", encoding="utf-8")
_git(r, "add", "-A")
_git(r, "commit", "-q", "-m", "base")
(r / "CONTRIBUTING.md").write_text("hello again\n", encoding="utf-8")
_git(r, "add", "-A")
_git(r, "commit", "-q", "-m", "docs: contributing")
(r / "SPEC.md").write_text("Version 0.2 tightened\n", encoding="utf-8")
_git(r, "add", "-A")
_git(r, "commit", "-q", "-m", "spec: tighten timestamps")
return r
def test_a_failing_git_call_raises_instead_of_returning_empty(repo: Path) -> None:
"""The defect this watch exists to avoid, at its smallest.
`git log <nonexistent>` writes to stderr and exits non-zero. A helper that
returned its empty stdout would hand the caller "no commits" — a negative
manufactured by a broken query.
"""
with pytest.raises(okf_watch.WatchError) as exc:
okf_watch.git(repo, "log", "--format=%H", "no-such-ref..HEAD")
assert "exit" in str(exc.value)
def test_an_empty_result_from_a_successful_call_is_not_an_error(repo: Path) -> None:
"""The other half of the seam: a real zero must still be readable as zero."""
head = okf_watch.git(repo, "rev-parse", "HEAD")
assert okf_watch.git(repo, "log", "--format=%H", f"{head}..{head}") == ""
# --- classification --------------------------------------------------------
def test_a_spec_change_is_normative() -> None:
normative, quiet = okf_watch.classify(["SPEC.md", "CONTRIBUTING.md"])
assert normative == ["SPEC.md"]
assert quiet == ["CONTRIBUTING.md"]
def test_the_reference_reader_is_normative_because_is_stale_reversed_there() -> None:
normative, _ = okf_watch.classify(["src/reference_agent/bundle/document.py"])
assert normative == ["src/reference_agent/bundle/document.py"]
def test_the_viewer_is_quiet_but_the_readme_is_not() -> None:
"""README carries the relocation notice. That is how the move was announced."""
normative, quiet = okf_watch.classify(
["src/reference_agent/viewer/static/viz.css", "bundles/acme_retail/viz.html", "README.md"]
)
assert normative == ["README.md"]
assert quiet == ["src/reference_agent/viewer/static/viz.css", "bundles/acme_retail/viz.html"]
def test_an_unknown_path_defaults_to_normative() -> None:
"""Quiet is an enumerated list; signal is not.
A watch that enumerates what matters cannot see a change upstream has not
invented yet, and fails in the silent direction. Over-firing is visible;
under-firing is not.
"""
normative, quiet = okf_watch.classify(["some/new/thing-upstream-adds-later.md"])
assert normative == ["some/new/thing-upstream-adds-later.md"]
assert quiet == []
# --- proving it can find ---------------------------------------------------
def test_the_self_check_passes_on_a_range_that_really_changed_the_spec(repo: Path) -> None:
base = okf_watch.git(repo, "rev-parse", "HEAD~1")
head = okf_watch.git(repo, "rev-parse", "HEAD")
okf_watch.prove_can_find(repo, base, head) # must not raise
def test_the_self_check_fails_loudly_when_the_query_finds_nothing(repo: Path) -> None:
"""An empty known-positive means the query is broken, not that upstream is quiet."""
head = okf_watch.git(repo, "rev-parse", "HEAD")
with pytest.raises(okf_watch.WatchError) as exc:
okf_watch.prove_can_find(repo, head, head)
assert "known-positive" in str(exc.value)
def test_the_self_check_fails_loudly_when_the_range_is_unreachable(repo: Path) -> None:
with pytest.raises(okf_watch.WatchError):
okf_watch.prove_can_find(repo, "deadbeef", "HEAD")
# --- idempotence: report on change, not on state ---------------------------
def test_a_first_normative_change_is_reported(tmp_path: Path) -> None:
state = okf_watch.State.load(tmp_path / "s.json", pin="PIN")
assert okf_watch.decide(state, ["aaa", "bbb"]) == ["aaa", "bbb"]
def test_the_same_upstream_state_is_not_reported_twice(tmp_path: Path) -> None:
path = tmp_path / "s.json"
state = okf_watch.State.load(path, pin="PIN")
okf_watch.decide(state, ["aaa"])
state.record(["aaa"])
state.save(path)
again = okf_watch.State.load(path, pin="PIN")
assert okf_watch.decide(again, ["aaa"]) == []
def test_only_the_new_commits_are_reported(tmp_path: Path) -> None:
"""Upstream advancing must not re-announce what was already announced."""
path = tmp_path / "s.json"
state = okf_watch.State.load(path, pin="PIN")
state.record(["aaa"])
state.save(path)
later = okf_watch.State.load(path, pin="PIN")
assert okf_watch.decide(later, ["aaa", "bbb"]) == ["bbb"]
def test_moving_our_pin_resets_what_counts_as_already_reported(tmp_path: Path) -> None:
"""A pin move means we absorbed everything behind it. Nothing before it is news."""
path = tmp_path / "s.json"
state = okf_watch.State.load(path, pin="OLDPIN")
state.record(["aaa"])
state.save(path)
assert json.loads(path.read_text(encoding="utf-8"))["pin"] == "OLDPIN"
after = okf_watch.State.load(path, pin="NEWPIN")
assert after.reported == []
# --- what gets sent --------------------------------------------------------
def test_the_coord_body_is_ascii_because_coord_send_requires_it() -> None:
body = okf_watch.render_body(
pin="ad30107",
head="beef123",
commits=[("beef123", "spec: tighten timestamps")],
normative=["SPEC.md"],
quiet=["CONTRIBUTING.md"],
)
body.encode("ascii") # raises UnicodeEncodeError if not
def test_the_body_names_the_repository_it_watched() -> None:
""" "No change" is only meaningful with the object named. So is a hit."""
body = okf_watch.render_body(
pin="ad30107", head="beef123", commits=[("beef123", "x")], normative=["SPEC.md"], quiet=[]
)
assert okf_watch.CANONICAL_REPO in body
assert "ad30107" in body and "beef123" in body
def test_the_body_carries_the_denominator_not_just_the_hits() -> None:
body = okf_watch.render_body(
pin="p",
head="h",
commits=[("a", "one"), ("b", "two")],
normative=["SPEC.md"],
quiet=["CONTRIBUTING.md", "LICENSE.md"],
)
assert "1 of 3" in body
# --- the override that fired a false alarm ---------------------------------
def test_an_overridden_pin_cannot_send_a_real_message(tmp_path: Path, repo: Path) -> None:
"""Measured 2026-08-23: this exact combination delivered two false alarms.
`--pin` exists so the reporting branch can be exercised on demand against
real upstream history. Exercising it must never be indistinguishable from
upstream actually moving, so the override forces dry-run rather than
trusting the operator to pair two flags correctly.
"""
args = okf_watch.parse_args(["--pin", "deadbeef", "--state", str(tmp_path / "s.json")])
assert args.dry_run is True
def test_the_real_pin_leaves_dry_run_alone() -> None:
assert okf_watch.parse_args([]).dry_run is False