Commit graph

9 commits

Author SHA1 Message Date
62b61927a4 fix(adjudicate): a judgement that keeps nothing gets an artifact
Measured on the K3 corpus: 4 of 12 judgements produced no artifact, because
the verdict was "none of these segments should be persisted" and the plan
grammar refuses zero entries. That refusal is correct for the run path -- an
empty plan replayed would silently persist nothing for a document that was
dropped -- so the grammar is untouched and the recording tool is taught to
record a rejection instead.

Refusing to materialize and refusing to record are different acts. The
rejection artifact is deliberately NOT replayable: parse_segmentation_plan
still refuses it, and the suite asserts that rather than assuming it. The dwell
time rides at the top level because there is no entry to carry it, and a
ratified rejection with no time on it is as unfalsifiable as a ratified
acceptance with none.

Only the empty LIST takes the branch. A missing entries key, or one that is not
a list, stays the grammar's to refuse: "the adjudicator kept nothing" and
"this file is not a plan" must not collapse.

K4a re-run after the change: propose, adjudicate, run the path twice into two
bundles under SEGMENTED_OKF_V0_2, diff -r exit 0 with no output. 1034 -> 1041
tests.
2026-09-02 16:15:28 +02:00
bc0b4130f1 feat(tools): okf_contract_check reads the contract's checkable half
Fourteen rules, each with its own code: one "invalid" verdict over fourteen
different defects is a diagnostic no caller can act on. The report quotes its
own denominators -- rules run, excerpts and withheld entries examined -- because
a checker that exempted itself from section 5 would be stating the rule it
breaks.

Three exit codes, not two. "The check did not run" and "the check failed" are
different outcomes, and an unread file reported as a failed check is the fourth
face of the verification law.

The shipped template plus its example payload is the known-positive arm, so a
checker that refuses everything cannot be green on the thirteen negative ones.
A last test asserts every literal the checker enforces appears in the contract
document: two copies of a closed set drift, and the copy nobody reads is the
one that goes wrong.

996 -> 1023 tests.
2026-09-02 16:09:27 +02:00
70cf4af268 feat(tools): corpus harness reporting K1 and K2 with denominators 2026-09-02 15:40:06 +02:00
7c6910cb55 feat(tools): re-measurable K2 fidelity instrument with a negative control 2026-09-02 15:08:08 +02:00
a4ffa363fe feat(tools): adjudication command with a switchable model leg 2026-09-02 14:54:20 +02:00
c54e8383df feat(segmentation): quote anchors so a re-extraction costs a re-anchor 2026-09-02 14:42:16 +02:00
9e9bb8645d fix(segmentation): hash the extracted text and let the plan key fire 2026-09-02 14:38:20 +02:00
2cfb358b76 feat(tools): segmentation proposer emitting adjudicable PROPOSED entries 2026-09-01 00:28:41 +02:00
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