test(v1-gate): the attestation's date, form and writer, as red tests — a future date, a +14:00 offset and a duplicated key all read green

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-18 18:11:42 +02:00
commit cd6fb4302e
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q

View file

@ -18,6 +18,7 @@ import os
import shutil
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
@ -841,19 +842,223 @@ def test_m7_the_attestation_file_is_pinned() -> None:
def test_m7_the_gate_never_writes_an_attestation(tmp_path: Path) -> None:
"""The file is the operator's word. A product that can produce one has produced a witness to
its own run, which is the whole thing rows 1-2 cannot do: so no source file in the package
writes ``ATTEST_FILE``, and scoring a tree leaves none behind."""
root = _unattested(_green_rounds(tmp_path))
gate.score_rounds(root, 3, _AI)
gate.score_changes(root, 3, _AI)
assert list(root.rglob(_ATTEST_FILE)) == []
writes = [
f"{path.name}:{i}"
for path in sorted((_REPO / "src" / "portfolio_optimiser").rglob("*.py"))
for i, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1)
if _ATTEST_FILE in line and "write_text" in line
]
assert writes == []
its own run, which is the whole thing rows 1-2 cannot do. Measured as BEHAVIOUR for the whole
package (18.09, PM): every entry point runs against an unattested but otherwise consistent
round directory, and none may leave an attestation behind. A grep for the file name reads a
name, and a writer called from ``render`` or the command line slipped past it."""
root = _unattested(_green_rounds(tmp_path / "rounds"))
config = json.loads(json.dumps(_CONFIG))
config["maf_points"]["points"] = _one_point([6])["points"]
entries: dict[str, Any] = {
"score_rounds": lambda: gate.score_rounds(root, 3, _AI),
"score_changes": lambda: gate.score_changes(root, 3, _AI),
"score_kept": lambda: gate.score_kept(root, 0.8, _AI),
"read_attestation": lambda: [gate.read_attestation(root / str(n)) for n in range(4)],
"evaluate+render": lambda: gate.render(
gate.evaluate(
rounds_dir=root,
config=config,
repo_root=_REPO,
src=_synthetic_src(tmp_path / "src"),
probe_runner=_all_pass,
stress_measure=_CLEAN,
)
),
}
for name, entry in entries.items():
entry()
assert list(root.rglob(_ATTEST_FILE)) == [], name
for flags in ((), ("--json",)):
proc = _cli("--rounds-dir", str(root), *flags)
assert proc.returncode == 1, proc.stderr
assert list(root.rglob(_ATTEST_FILE)) == [], ("cli", flags)
# ---------------------------------------------------------------------------------------------
# M-8 — what the attestation's DATE and FORM may say (PM checkpoint 18.09 of 1b48124)
# ---------------------------------------------------------------------------------------------
_NOW = datetime(2026, 5, 29, 12, 0, tzinfo=timezone.utc)
def _both_rows(root: Path, now: datetime | None = None) -> list[gate.Row]:
return [gate.score_rounds(root, 3, _AI, now=now), gate.score_changes(root, 3, _AI, now=now)]
def test_m8_the_baseline_stays_green_on_the_injected_clock(tmp_path: Path) -> None:
"""Positive control for everything below: the same tree, the clock on the fixture day."""
rows = _both_rows(_green_rounds(tmp_path), _NOW)
assert [(r.k, r.status) for r in rows] == [(3, gate.GREEN)] * 2, rows
@pytest.mark.parametrize(
"given",
["2026-05-30", "3000-01-01", "2026-05-29T23:00:00-05:00"],
)
def test_m8_an_attestation_dated_in_the_future_is_red(tmp_path: Path, given: str) -> None:
"""Finding 1: ``dato: 3000-01-01`` on every round read GREEN — the check only asked whether
the date was before the run. The last case is a future INSTANT written in a west-of-UTC
offset, so its wall-clock date is still today."""
root = _green_rounds(tmp_path)
_attest(root / "1", on=given)
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (2, gate.RED), (given, row.exceptions)
assert any("i framtiden" in x for x in row.exceptions), row.exceptions
def test_m8_the_clock_is_a_parameter_and_the_default_is_the_real_one(tmp_path: Path) -> None:
root = _green_rounds(tmp_path)
_attest(root / "1", on="3000-01-01")
assert gate.score_rounds(root, 3, _AI).status == gate.RED # the real clock, no injection
@pytest.mark.parametrize(
"given",
["2026-05-29T00:00:00+14:00", "2026-05-28T10:00:00+00:00", "2026-05-28T20:26:00+00:00"],
)
def test_m8_a_timezone_cannot_date_an_attestation_before_the_run(
tmp_path: Path, given: str
) -> None:
"""Finding 2: ``2026-05-29T00:00:00+14:00`` is 2026-05-28T10:00Z, ten hours BEFORE the run
(20:26Z), and read GREEN because only the wall-clock date was compared. A date that carries a
time is compared as the instant it is."""
root = _green_rounds(tmp_path)
_attest(root / "1", on=given)
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (2, gate.RED), (given, row.exceptions)
assert any("før kjøringen" in x for x in row.exceptions), row.exceptions
def test_m8_a_time_without_an_offset_is_ambiguous_and_red(tmp_path: Path) -> None:
root = _green_rounds(tmp_path)
_attest(root / "1", on="2026-05-29T10:00:00")
row = gate.score_rounds(root, 3, _AI, now=_NOW)
assert (row.k, row.status) == (2, gate.RED), row.exceptions
assert any("tidssone" in x for x in row.exceptions), row.exceptions
@pytest.mark.parametrize("given", ["2026-05-29T08:00:00+02:00", "2026-05-29T00:00:00+00:00"])
def test_m8_an_instant_after_the_run_and_before_now_is_green(tmp_path: Path, given: str) -> None:
root = _green_rounds(tmp_path)
_attest(root / "1", on=given)
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (3, gate.GREEN), (given, row.exceptions)
def test_m8_a_plain_date_keeps_the_same_day_rule(tmp_path: Path) -> None:
"""Same day as the run, and same day as ``now``, cannot be told apart from a date alone — so
it passes, and the contract text says so."""
root = _green_rounds(tmp_path)
_attest(root / "1", on="2026-05-28") # the run's own day
assert gate.score_rounds(root, 3, _AI, now=_NOW).status == gate.GREEN
_attest(root / "1", on="2026-05-29") # today
assert gate.score_rounds(root, 3, _AI, now=_NOW).status == gate.GREEN
assert "samme dag" in gate.ATTEST_RULE
_BODY = {"runde": "runde: 1", "kjøring": "kjøring: r1", "dato": "dato: 2026-05-29"}
@pytest.mark.parametrize("key", ["runde", "kjøring", "dato"])
@pytest.mark.parametrize("first_is_right", [True, False])
def test_m8_a_key_written_twice_is_red_in_either_order(
tmp_path: Path, key: str, first_is_right: bool
) -> None:
"""Finding 3: ``runde: 1`` then ``runde: 2`` was GREEN and the reverse RED — first-wins by
accident, and a last-wins mutant survived the whole suite. Two answers to one question are
not an answer, whichever comes first."""
root = _green_rounds(tmp_path)
wrong = {"runde": "runde: 2", "kjøring": "kjøring: r9", "dato": "dato: 2020-01-01"}[key]
pair = [_BODY[key], wrong] if first_is_right else [wrong, _BODY[key]]
lines = [x for k, x in _BODY.items() if k != key] + pair
_write(root / "1" / _ATTEST_FILE, "\n".join(lines) + "\n")
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (2, gate.RED), row.exceptions
assert any("to ganger" in x for x in row.exceptions), row.exceptions
def test_m8_even_the_same_value_twice_is_red(tmp_path: Path) -> None:
root = _green_rounds(tmp_path)
_write(root / "1" / _ATTEST_FILE, "\n".join([*_BODY.values(), _BODY["runde"]]) + "\n")
assert gate.score_rounds(root, 3, _AI, now=_NOW).status == gate.RED
def test_m8_a_byte_order_mark_is_tolerated(tmp_path: Path) -> None:
"""Finding 5a: a real file from an ordinary editor may start with a BOM, which made the first
key read as a different word and the round RED. The person is not wrong; the gate tolerates
it."""
root = _green_rounds(tmp_path)
text = "\n".join(_BODY.values()) + "\n"
(root / "1" / _ATTEST_FILE).write_bytes(b"\xef\xbb\xbf" + text.encode("utf-8"))
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (3, gate.GREEN), row.exceptions
def test_m8_an_attestation_that_is_a_directory_is_red_not_missing(tmp_path: Path) -> None:
"""Finding 5b: a directory named like the file is something PUT there — not the same as
nobody having confirmed yet."""
root = _green_rounds(tmp_path)
(root / "1" / _ATTEST_FILE).unlink()
(root / "1" / _ATTEST_FILE).mkdir()
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (2, gate.RED), row.exceptions
assert any("vanlig fil" in x for x in row.exceptions), row.exceptions
@pytest.mark.parametrize("target", ["valid", "dangling"])
def test_m8_an_attestation_that_is_a_symlink_is_red(tmp_path: Path, target: str) -> None:
"""Finding 5c: F4 refuses a linked outbox, and ``is_file()`` followed the same link here. What
a forger gains is nothing (the content binds), but the asymmetry was unmeasured."""
root = _green_rounds(tmp_path / "rounds")
elsewhere = tmp_path / "elsewhere.txt"
if target == "valid":
elsewhere.write_text("\n".join(_BODY.values()) + "\n", encoding="utf-8")
(root / "1" / _ATTEST_FILE).unlink()
(root / "1" / _ATTEST_FILE).symlink_to(elsewhere)
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (2, gate.RED), (target, row.exceptions)
assert any("lenke" in x for x in row.exceptions), row.exceptions
def test_m8_a_hard_link_is_a_declared_limit_not_a_rule(tmp_path: Path) -> None:
"""Chosen 18.09: a hard link is NOT refused, and the output says so. Nothing in the tree marks
where it points, ``cp -l`` and some backup tools make them innocently, and refusing would gain
nothing the attestation's content binds round, run and date either way."""
root = _green_rounds(tmp_path / "rounds")
outside = tmp_path / "outside.txt"
outside.write_text("\n".join(_BODY.values()) + "\n", encoding="utf-8")
(root / "1" / _ATTEST_FILE).unlink()
os.link(outside, root / "1" / _ATTEST_FILE)
assert gate.score_rounds(root, 3, _AI, now=_NOW).status == gate.GREEN
assert "hardlenke" in gate.ATTEST_RULE
def test_m8_an_attestation_that_is_not_utf8_is_red_because_it_is_unreadable(
tmp_path: Path,
) -> None:
"""Finding 6: the ``except`` arm on the read was uncovered — a whole-file garbage input goes
RED anyway through the missing keys, so a lenient decode (``errors="ignore"``) survived. Here
the three keyed lines are perfect and ONE stray byte follows: only strictness can refuse it."""
root = _green_rounds(tmp_path)
good = ("\n".join(_BODY.values()) + "\n").encode("utf-8")
(root / "1" / _ATTEST_FILE).write_bytes(good + b"merknad \xff\xfe\n")
for row in _both_rows(root, _NOW):
assert (row.k, row.status) == (2, gate.RED), row.exceptions
assert any("uleselig" in x for x in row.exceptions), row.exceptions
def test_m8_the_output_says_the_stress_row_needs_the_untracked_scratchpad() -> None:
"""Finding 7: row 7's 1 of 20 stands on ``scratchpad/`` being present. Without it the row is
NOT MEASURED, and that dependency is a fact about the checkout, not about the product."""
assert "scratchpad" in gate.STRESS_DEPENDENCY and "IKKE MÅLT" in gate.STRESS_DEPENDENCY
rows = gate.evaluate(
rounds_dir=Path("/nonexistent"),
config=_CONFIG,
repo_root=_REPO,
probe_runner=_all_pass,
stress_measure=_CLEAN,
)
assert gate.STRESS_DEPENDENCY in gate.render(rows)
def _outcome_obj(rows: list[dict[str, Any]], removed: dict[str, set[str]] | None = None) -> Any: