Point 2 of the vacuity sweep is now MEASURED, not paired-by-reading. Every
one of the 8 got a mutation that detaches the seam it claims to guard, run
through a harness that asserts the anchor is unique before mutating, restores
in `finally`, and sha256-verifies the restore.
Six were value-proven — the negative itself went RED under its detach:
hitl :260 load_routing invents a default -> RED
hitl :298 route_pending hardcodes a fallback -> RED
step7 :145 the is_dir() guard deleted -> RED
step7 :171 the §4.2 vocabulary filter deleted -> RED
step7 :253 the id grammar off the model -> RED
prov :111 sdk_version becomes required -> RED
Two did not, and both are fixed here.
hitl :197 — the guard it appeared to prove is DEAD. Deleting the `is_dir()`
early-out from load_outbox_proposals leaves all 711 tests green: the tolerance
comes from `Path.glob`, which yields nothing on a missing directory and never
raises. The contrast is the finding: load_inbox carries an identically-shaped
guard that IS load-bearing, because it walks with `Path.iterdir`, which DOES
raise (measured both ways). Same guard, opposite verdict, and the difference
is the stdlib call behind it — the point-3 lesson one level out, where the
default being pinned belongs to the standard library rather than the SDK.
The stdlib baseline is now anchored explicitly, so a Python that makes glob
raise turns this red instead of quietly promoting a dead line to a seam.
What the test always did prove is kept and stated: replacing the early-out
with a raise turns it red, so it does hold tolerance.
portfolio :175 — the negative asserted over an unheld population. Measured, it
is real today (6 prompts), so the test is not vacuous now; nothing in it says
so, and a run_portfolio that stopped prompting would leave it green while
proving nothing. A positive control now runs first. Value-proven: green before,
red after the same mutation (iterate no projects), and it is that assertion
which fails, not an import.
The sibling repo sent the same rule from the other stack this week, arrived at
independently via its B4 empty-negative: on a negative assert, prove FIRST that
the event happened.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qr6TwWrHDHeukHy3bL4hgb
The operator's view of the long feedback loop (S5.1-analog, parity row 22;
buildable after K5): which proposals still AWAIT an expert verdict, and who
should judge each — a pure file-based id-join across the three layers hitl
READS and NEVER writes (role split §3 Step 7: the expert writes the inbox, the
system reads it; notification is K10's job, never this).
- hitl.py:
* pending_proposals — the id-join. An outbox proposal (K5) is pending unless
its persisted verdict_id (read verbatim from {run_id}-outcome.json, minted
the SAME way the inbox mints a verdict id — the K5 assumption) is in the
settled set. settled = §4.2-valid inbox verdicts (THROUGH load_inbox, so a
skipped/unknown decision never settles anything) ∪ promoted verdicts (§6,
optional bundle_dirs, so the core join is exactly outbox↔inbox).
* RoutingContract — nøkkel→ekspert, schema-validated fail-fast (§10): non-empty
table, non-empty keys/expert ids, optional default_expert. route_pending maps
a proposal's measure (a config-string key NOW; K13 formalizes the dimension
catalog) to an expert; an unmatched measure → default, else UNROUTED.
* CLI python -m …hitl pending|route — pending is a pure report (exit 0); route
loads the routing config fail-fast (a malformed/missing config exits non-zero
WITHOUT touching any layer). Neither subcommand writes anything.
- test_hitl_loadbearing.py: 23 tests. TWO seams detach-proven RED — the id-join
seam (drop the `not in settled` filter → a judged proposal is STILL listed →
red) and the read-only seam (any read path that writes a byte → the before/
after outbox+inbox snapshot diverges → red). Covers: undecided → pending,
inbox/promoted verdict settles, exact-id join (no coincidental match), skipped
decision does not settle, deterministic order, malformed routing fail-fast,
measure→expert / default / UNROUTED, and the CLI subcommands.
- 521→544 green, golden byte-exact, full gate clean (ruff+format+mypy strict,
25 src files). README: test-count sync ×2 + hitl module note + load-bearing
mention. IKKE-scope (held): notification (K10), web-UI, writing the inbox.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RiTwaKLesgcwXx2mDviqpt