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>
This commit is contained in:
parent
2f94bbcbd4
commit
714aafbff2
2 changed files with 257 additions and 31 deletions
|
|
@ -979,7 +979,84 @@ def test_j3_row_seven_refuses_a_mutant_list_that_is_not_the_pinned_roster(
|
|||
assert "roster" in row.reason or "duplicate" in row.reason
|
||||
|
||||
|
||||
def test_g9_a_delivery_that_carries_the_citation_and_not_the_bundles_bytes_is_not_a_hit(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""PM's G9: `hit = bool(hit_ids) and bool(confirmed)` -- removing the
|
||||
second term left all 46 tests green, because every mutation that touched
|
||||
the text emptied `hit_ids` one step earlier. The shape that reaches the
|
||||
term is a delivery that still CARRIES the quote and is no longer the
|
||||
concept file's bytes, and the judge must have read the bundle first."""
|
||||
bundles = _bundles(tmp_path)
|
||||
gate.bundle_index(bundles["positive"]) # the judge reads the bundle BEFORE the payload
|
||||
question_set = gate.load_set(
|
||||
FIXTURES / "set-positive.json", gate.SYNTHETIC_SETS["set-positive.json"]
|
||||
)
|
||||
with gate._extend_delivered():
|
||||
units = gate.measure_case(question_set, bundles).units
|
||||
assert units, "the known-positive: this set delivers on the unmutated run"
|
||||
assert [unit.hit for unit in units] == [False] * len(units)
|
||||
assert all(unit.confirmed is False for unit in units)
|
||||
assert all(unit.detail == "the delivered text is not the bundle's bytes" for unit in units)
|
||||
|
||||
|
||||
def test_the_unmutated_run_of_that_same_set_is_every_hit(tmp_path: Path) -> None:
|
||||
units = _case(tmp_path, "set-positive.json").units
|
||||
assert [unit.hit for unit in units] == [True] * len(units)
|
||||
|
||||
|
||||
def test_the_mutant_roster_is_pinned_apart_from_the_list_it_names() -> None:
|
||||
assert tuple(mutant.label for mutant in gate.MUTANTS) == gate.MUTANT_ROSTER
|
||||
assert len(gate.MUTANT_ROSTER) == gate.MUTANT_COUNT
|
||||
assert len(set(gate.MUTANT_ROSTER)) == len(gate.MUTANT_ROSTER)
|
||||
|
||||
|
||||
def test_the_synthetic_corpus_is_pinned_like_the_sets(tmp_path: Path) -> None:
|
||||
assert gate.specs_digest() == gate.SPECS_SHA256
|
||||
tuned = dict(gate.SPECS)
|
||||
first = tuned["positive"]
|
||||
tuned["positive"] = gate.BundleSpec(first.bundle_id, first.documents[:1])
|
||||
assert gate.specs_digest(tuned) != gate.SPECS_SHA256
|
||||
|
||||
|
||||
def test_a_corpus_that_is_not_the_pinned_corpus_is_refused(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
monkeypatch.setattr(gate, "SPECS_SHA256", "0" * 64)
|
||||
with pytest.raises(gate.GateUsage) as refusal:
|
||||
gate.synthetic_bundles(tmp_path / "bundles")
|
||||
assert "not the corpus that was pinned" in str(refusal.value)
|
||||
|
||||
|
||||
def _k2_shaped(tmp_path: Path, questions: int) -> tuple[Path, str]:
|
||||
"""A K2 gold set in this gate's own shape. `set-positive.json` carries
|
||||
exactly six questions the bundle answers, which is K2's denominator."""
|
||||
spec = json.loads((FIXTURES / "set-positive.json").read_text(encoding="utf-8"))
|
||||
spec["set_id"] = "k2-gold"
|
||||
spec["questions"] = spec["questions"][:questions]
|
||||
path = tmp_path / "k2.json"
|
||||
path.write_text(json.dumps(spec, ensure_ascii=False), encoding="utf-8")
|
||||
return path, gate.sha256_of(path)
|
||||
|
||||
|
||||
def test_row_nine_is_green_when_a_k2_gold_set_arrives(tmp_path: Path) -> None:
|
||||
path, sha = _k2_shaped(tmp_path, gate.K2_QUESTIONS)
|
||||
question_set = gate.load_set(path, sha)
|
||||
row = gate.row_nine((question_set, _bundles(tmp_path)))
|
||||
assert (row.k, row.m, row.status) == (6, 6, gate.GREEN)
|
||||
|
||||
|
||||
def test_row_nine_is_red_when_the_gold_set_is_not_answered(tmp_path: Path) -> None:
|
||||
path, sha = _k2_shaped(tmp_path, gate.K2_QUESTIONS)
|
||||
question_set = gate.load_set(path, sha)
|
||||
bundles = dict(_bundles(tmp_path))
|
||||
bundles["positive"] = bundles["miss"] # the same six questions, the wrong bundle
|
||||
row = gate.row_nine((question_set, bundles))
|
||||
assert (row.k, row.m, row.status) == (0, 6, gate.RED)
|
||||
|
||||
|
||||
def test_a_k2_set_of_another_size_is_another_set_and_is_refused(tmp_path: Path) -> None:
|
||||
path, sha = _k2_shaped(tmp_path, gate.K2_QUESTIONS - 1)
|
||||
with pytest.raises(gate.GateUsage) as refusal:
|
||||
gate._k2_set([str(path), sha, str(tmp_path)])
|
||||
assert "K2's denominator" in str(refusal.value)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue