Commit graph

10 commits

Author SHA1 Message Date
23ef6bbef3
docs(privacy): no private path and no coordination id in what this span added
A public repository should not carry the layout of the machine it was written
on, and it should not carry the identifiers of a queue nobody outside can see.
Six places in material this span added or changed did.

Neutral text, same facts: a private queue path in the EOL report, a private
note path in two docstrings and one report header, and four order identifiers
opening four reports. Where a sentence lost its source it says `internal
measurement note` -- the measurement is still named, the path is not.

One of them was output, not prose: row 9 of the retrieval gate printed a
`~/corpora/...` path to stdout on every run. It says the bundles exist on the
machine the row was written against; the row already takes `--k2 SET SHA
BUNDLE` from anyone who holds them.

Measured with the patterns as given, and both validated against a
known-positive on `df5a118` first -- an unvalidated pattern reporting zero is
not a measurement:

* `~/\.claude|/Users/|coord/.*/orders` over the 74 files the span touches:
  **9 -> 6**. The six left are deliberate: two README lines telling a reader to
  install a skill into their OWN `~/.claude/skills`, one prose line arguing
  that `/Users/...` is not more portable than a relative path, and three lines
  of `tests/test_retrieval_gate.py`'s own known-positive for this exact check,
  which removing would disarm it.
* `[0-9]{8}T[0-9]{6}Z-[0-9]+` over the 38 files the span ADDED: **4 -> 0**.

A note on the method, because the first run of the first grep reported 0 and
was wrong: zsh does not word-split an unquoted parameter, so
`git grep -- $FILES` passed 74 names as one argument and matched no file at
all. Both numbers above come from `$(git diff --name-only ...)`, which zsh does
split, and the known-positive is what made the false zero visible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 15:40:38 +02:00
05cb19087a
feat(consume): the payload says what of the question it reached, and row 4 reads it
`coverage` carries three lists: the terms the pre-pass read the question as,
the terms no concept in the bundle answers, and the terms no delivered
excerpt answers. Without it a reader holding eight excerpts cannot tell a
bundle that ANSWERED its question from one that merely ranked something --
the two payloads have the same shape.

FACTS, AND NO VERDICT, which is a measurement and not caution. Two readings
were built and both falsified over 81 questions (16 synthetic, 65 across the
three real sets, 2026-09-20): the share of question terms a delivered
excerpt answers separates the synthetic controls at 0.33 against 0.50 and
REVERSES on real data (covered questions down to 0.27, one genuinely
uncovered question at 0.71); the share of a bundle tying the best lexical
match is ~0.00 for every real question either way. Question style dominates
the first, corpus size the second.

The one bar this repository declares is the gate's: `UNANSWERED_BAR = 2/3`
over `unanswered_in_bundle`, swept and collapsing at both ends -- at 0.50
eleven real covered questions are marked, at 0.70 the row falls to 5 of 6,
at 2/3 the row is 6 of 6 and 0 of 65 real questions are marked. The margin
is thin (0.6087 against 0.6667) and is published that way, together with
what it does not catch: r761-sk2's own known-negative sits at 0.2857.

Row 4: 3 of 6 RED -> 6 of 6 GREEN, with the 10 answered synthetic questions
held unmarked as the known-negative. The contract's SS 8 gains point 7, the
consumption skill is told to read the block, and the SS 7.4 known-positive
moves with the document (14 721/375 -> 16 389/417). Suite 2292 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 08:44:06 +02:00
735fb237e4
feat(retrieval-gate): row 5 reads the threshold as a number and compares it with the hold-out
Two checks replace `bool(threshold)`: `_as_share` parses it as a share in
[0, 1] -- so `report-only; any number is acceptable for v1` is a NO, and so
is `80` -- and `_hold_out_verdict` RUNS the registered set against the
registered bundle and prints `answered of asked = share against threshold`.

A registration naming an absent set, an unreadable bundle or an empty set
is a NO with its reason, never an exception and never a silent pass. The
row is 11 checks; it stays RED today because no registration exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 08:11:03 +02:00
34fe70a401
feat(retrieval-gate): row 8 names the bundle it measured, and the three real sets are pinned here
REAL_SET_PINS states what each set IS -- questions, fasit entries, controls
and sha256 -- so a one-question file in the right shape is refused
(`check_real_pin`, exit 2) instead of reading `1 of 1 | 3 of 3 | GREEN`.
Three counts rather than one: the digest says the bytes are the pinned
bytes, the counts are what a reader can check against the source.

Every set's line now carries `measured against <key> = <path> | bundle_id
<id> | ref <sha256-tree:...>`, for the bundles the run actually used and
SS 3.3's two halves both printed -- three builds on this machine share one
bundle_id at three refs.

Stated limit: the table lives in the file a capability session edits, as
SYNTHETIC_SETS and SPECS_SHA256 do. It raises the cost of the attack and
does not remove it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 08:06:23 +02:00
714aafbff2
fix(retrieval-gate): the seven small findings -- a corpus pin, a K2 input, an observed term
PM's checkpoint left seven small findings beside the four bearing ones. Six
are closed here (the seventh, running row 8 against the real sets, follows).

G9 -- THE CONFIRMATION TERM IS OBSERVED NOW. `hit = bool(hit_ids) and
bool(confirmed)` survived all 46 tests, because every mutation of the text
empties `hit_ids` one step earlier. The shape that reaches it is a delivery
that still CARRIES the citation and is no longer the concept file's bytes:
`M14` is that mutation and it is FELLED (row 7 goes 11 of 13 to 12 of 14, bar
12 of 13 to 13 of 14, still RED, the same two survivors), and a test drives it
with its known-positive in the same test. No production line changed: the term
was always observable, it was unobserved.

AND THAT MEASURES THE JUDGE'S INDEPENDENCE RATHER THAN ASSERTING IT. The judge
does read the bundle through `consume.read_concept` and `delivered_text` --
PM's finding -- but the index is warmed BEFORE the first mutation, so the two
sides do not move together. Measured both ways: index warmed first, every unit
is a miss with `confirmed False`; index built UNDER the same patch, every unit
is a hit. The gate never builds one under a mutation. Stated in `LIMITS` with
that measurement, rather than closed by re-implementing a normalisation rule
this repository already owns once.

SPECS -- the synthetic corpus is pinned like the sets (`SPECS_SHA256` over
`specs_digest`). PM's corpus tuning was caught by row 2's forced classes and
not by a pin, and a more careful tuning was left standing.

ROW 9 TAKES AN INPUT. `--k2 SET SHA256 BUNDLE` reads a gold set in this gate's
own set shape; `K2_QUESTIONS` stays the denominator whatever the file carries,
and a set of another size is refused (exit 2) as another set wearing this
one's name. Without a set the row stays RED and not NOT RUN -- ITS denominator
is known, six recorded questions, so the absence is measured; row 8's is not
known until the sets arrive. Both fail the gate identically. This is a
deliberate divergence from the order's parenthetical, stated here and in the
row.

MYPY. `mypy --strict` on this file goes 8 errors to 0, the four in
`read_real_set` among them (`questions = []` against a name inferred
`tuple[Question, ...]`) -- the adapters that meet the real sets.

63 passed. The verdict is unchanged: GATE RED: rows 3, 4, 5, 7, 8, 9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 21:24:40 +02:00
2f94bbcbd4
fix(retrieval-gate): the mutant roster is pinned apart from the list it names
PM's J3. `MUTANT_ROSTER` carries the thirteen labels and `MUTANT_COUNT` their
number, both written apart from `MUTANTS`, and `row_seven` refuses to run
unless the labels it was handed ARE that roster, in order, with no duplicate.
The bar is taken from the roster's length, not from `len(mutants)`.

Why a pin and not a share: the bar is a percentage, so a longer list is a
lower bar per survivor. Seven copies of `M03 k = 1` took the row to 18 of 20
GREEN with the same two survivors -- nothing new felled, the bar lowered.
Lengthening the list honestly now costs three edits in three places, each
readable as what it is; a duplicate label is refused outright, because two
copies of one mutation are one mutation whatever the roster says.

Row 7 is unchanged on the shipped list: 11 of 13, bar 12 of 13, RED, the same
two survivors with the same measured notes. 56 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 21:14:34 +02:00
30cbb69ac0
fix(retrieval-gate): row 5 reads git for the half a registration cannot assert
PM's J1. Three of row 5's ten checks now read the repository's history instead
of the registration's own fields:

- the registration is COMMITTED and unmodified against HEAD -- a file written
  in a working tree is not a pre-registration;
- the commit that ADDED it is not itself a change to the ranking -- a
  threshold and the change it is supposed to bind, in one commit, is neither;
- a change to the ranking landed AFTER it. This is the one that cannot be
  self-attested: it is satisfied only in the order a pre-registration actually
  happens, and it is red today because neither half has happened.

The three come from `git_provenance`, a `Provenance` the row receives the way
it already receives a path, so both directions are driven from the test and
the default is the real git. Outside a git tree, or with no git on PATH, the
fields come back in their REFUSING form with the reason printed -- unknown is
not unknown-and-therefore-fine.

WHAT GIT CANNOT PROVE IS STATED IN THE ROW, not implied: history shows ORDER,
never that nobody read the number before writing the threshold -- a number can
be read from an uncommitted tree. Order is what these three checks are.

Row 5 is unchanged where it matters today: `0 of 1 RED`, no registration. The
two existing direction tests move 7 -> 10 checks and a third arm is added that
drives each git check red on its own. 54 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 21:08:52 +02:00
be899106c4
fix(retrieval-gate): rows 2 and 3 count against the pinned set, not the run
PM's J10 and J8. Two mechanisms, one per attack, and neither is a pin a
capability session can edit in the same breath as the code.

J10 -- THE DENOMINATOR IS THE SET'S. `Unit` now carries the class its question
DECLARES. Row 2's denominator is the misses plus every forced fixture that
came back a hit, and row 3's is every unit whose set declares a withheld class
(b, c, e -- (a) is not in the bundle and (d) was delivered, so neither can
carry a printed reason) plus whatever the run withheld besides. A fixture that
stops producing its declared class is a BROKEN PREMISE, printed as one, and it
counts against its row: at `k = 32` row 2 stays RED with its denominator held
and row 3 keeps 5 units where it had shrunk to 2 and called that green.

J8 -- THE ROW CARRIES A KNOWN-POSITIVE. With `--source-quota` off, every
printed reason is true; that reading is not a lie, it is an empty measurement,
and row 3 must say so rather than print `6 of 6 GREEN` beside row 1 falling to
8 of 9. A set may now declare `source_quota_in_force`, and the row is NOT RUN
for such a set when the default cut and the quota-off cut deliver the same
concepts everywhere.

THE CONTROL'S OWN PREMISE WAS MEASURED FIRST, and it was false where it was
first put: over the five existing sets the two cuts deliver the SAME concepts
(the quota is topped back up), so 52 labels move `source_quota_exceeded` ->
`below_k` without one delivery changing. `set-quota.json` is the set where the
quota genuinely decides -- measured, `oversikt-08` is delivered without the
quota and withheld with it, and the fasit `svar/broennproeve` is delivered
only with it -- so the requirement is declared there and nowhere else. It
survives the honest fix, which changes labels and not the cut.

Rows 1 and 6 go 9 of 9 to 10 of 10: one added fixture, one added hit, both
green before and after. Rows 2 (7 of 7), 3 (2 of 5), 4, 5, 7, 8, 9 and the
verdict `GATE RED: rows 3, 4, 5, 7, 8, 9` are unchanged. 52 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 21:03:55 +02:00
b4f03e44cb
fix(retrieval-gate): row 8 is the three sets, and its headline is one granularity
Two of PM's eight attacks, closed where they were measured.

J2 -- a set left out. `REQUIRED_REAL_SETS` names the three (`wiki-20`,
`r761-sk2`, `vegnormal-32`) and the row is NOT RUN until all three are given,
whatever the ones that ran scored. The numbers the run DID measure are still
printed: a missing set must not cost the reader the set that was measured, and
"not run" is the row's status, never a reason to withhold a figure.

J2b -- the headline was `quoted_hits + concept_hits` over
`quoted_units + concept_units`, written one line above the detail that says
the two are not summed. The three sets do not share a unit: `wiki-20` names a
citation, `r761-sk2` a section title, `vegnormal-32` a requirement number, and
a citation hit plus a concept hit is a number that is neither. A QUESTION is
the one unit all three have, so the headline is questions answered of
questions asked -- answered meaning at least one of the question's fasit
entries arrived, the reading row 1 already prints beside its own units -- and
the two unit totals keep their own denominators below it, unsummed.

49 passed (was 46 passed, 3 failed). The gate is unchanged where it did not
run: still exit 1, still `0 of 3 NOT RUN` with PM's recorded figures carried.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 20:51:41 +02:00
2c8296b807
test(consume): the retrieval gate, written red over nine rows
One command, one exit code, and no capability: nothing here changes the
ranking, the fusion, the tokenisation or the cut. For a frozen question set
against a bundle it asks how many of N measurement units the payload carries
the fasit for, gives every miss exactly ONE class, and asks the thing the
payload does not do at all -- say so when it does not know.

Today, on the synthetic corpus this repository generates and the five sets it
ships pinned by sha256: rows 1 (9 of 9), 2 (7 of 7) and 6 (9 of 9) green;
3 (2 of 5), 4 (3 of 6), 5 (0 of 1), 7 (11 of 13), 8 (not run) and 9 (0 of 6)
red. GATE RED, exit 1.

- Row 3 is the finding to read first. In a bundle built from ONE source
  document, every concept past the first two carries that document's
  `source_file`, so a concept the RANK had already lost is withheld as
  `source_quota_exceeded`. The truth is decided by the SAME cut run without
  the quota -- PM measured the same lie on 13 of 25 real misses 2026-09-17.
- Row 4 is the second. No payload key says "this bundle does not answer
  that", so the only honest reading today is `delivered == 0`; three of six
  controls come out right and the three that do not get eight excerpts and no
  statement. A control the bundle DOES answer must come back unmarked, or the
  marking says nothing, so both directions sit in the same row.
- A miss has exactly one class -- (a) not in the bundle, (b) below k, (c) cut
  by quota or budget, (d) delivered without the citation, (e) other -- and
  each is FORCED by its own fixture. An unplaced miss takes the row to 0 of N.
- The judge opens the bundle. Every concept is read off disk before a payload
  is built, a delivered excerpt whose text is not the concept file's bytes is
  not a hit, and the two title forms come from `quality` rather than being
  written a second time.
- FELLED means a row got WORSE, never merely that something changed: removing
  the quota makes row 3 green, and counting that as a kill would credit this
  gate with a check it does not have. The two survivors are reported with what
  they measured -- the document prior dead and RRF_K flattened each moved 0
  ranks and 0 deliveries on these fixtures -- and with a mechanism for each.
- Rows 8 and 9 are never green by leaving something out. The three real sets
  are read from path + sha256 and never committed: a gold set names a
  consumer's documents and this repository is public. K2 is 0 of 6 because the
  gold set exists nowhere while its bundles do.

Denominators re-measured against the sources 2026-09-19, and all four hold:
wiki 20 questions / 29 fasit entries (sha 972d0f57...), R761 8 (S1-S6 + KP +
KN), vegnormal 32 questions / 43 must_cite, K2 6. PM's 45 of 70 is itself a
mixed sum -- wiki at question level, vegnormal at citation level -- so this
gate carries it labelled as recorded and never sums the two granularities.

46 tests, each failing row driven both ways through inputs rather than by
editing the row. No network (the socket guard is fired before its silence
counts), no private corpus, no clock.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 10:47:21 +02:00