test(mutants,assets): a mutant is judged by the suite that owns it, 45 of 45
The runner could only run one test file, which is why PM's three
survivors from `43331fc` could not be added: two are held by the gate's
row 3 and one by the soft-hyphen door's suite. A mutant now names its
suite; the catalogue goes 39 to 45.
X3 and X4 rewritten against the code as it now stands -- a mutant table
is a copy of the code it mutates, and this round moved the lines both of
them quoted. X6 is the defeated state exactly, X7 cuts the ledger off at
its source, X8 removes the cursor rule, P6/P11/P12 are PM's three.
Two survivors on the first run, both findings, both closed:
- X4 survived because every forgery arm now fails on the ledger check
before the binding is reached. An arm was added where the run DID book
the pair and the block stating it points at another picture.
- X5 survived the WHOLE suite -- 2134 passed with the disarming removed
-- because a document-supplied field can no longer reach the gate. The
property is about the BUNDLE and not about one judge, so it is kept and
measured in `tests/test_assets.py`, with a known-positive counting the
run's own two fields on the same expression.
killed 45 of 45, exit 0. Report, CHANGELOG and CLAUDE.md written.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
6d7dc7a660
commit
44ad845e29
6 changed files with 431 additions and 17 deletions
71
CHANGELOG.md
71
CHANGELOG.md
|
|
@ -282,6 +282,77 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Fixed
|
||||
|
||||
- **The conversion claim the content-accounting gate believes now comes from
|
||||
the RUN, not from the bundle's prose (0.10.1).** The previous round bound
|
||||
the claim to a pointer block, which closed the two forgeries PM had
|
||||
measured and did not close the class: a pointer block is two lines of
|
||||
markdown, and one ordinary HTML file with two `<p>` elements writes them.
|
||||
Reproduced through the real `okf build` — a BMP refused `asset_too_large`
|
||||
and absent from `assets/` read as CARRIED, from a document naming one
|
||||
digest that is public in the bundle and one that is computable in advance.
|
||||
- `okf build --accounting` now books every conversion the run performed:
|
||||
`assets.conversion` names the `(source digest, asset digest)` pair,
|
||||
`DocumentAssets.conversions` carries it out of the run and the accounting
|
||||
JSON states it per document as `conversions: [{from, to}]`.
|
||||
- The gate reads the pair from there and uses the bundle text only to
|
||||
CONFIRM it. The confirmation can be forged and the ledger cannot, which is
|
||||
why the ledger decides.
|
||||
- **Chosen over neutralising pointer-shaped text at extraction**, because
|
||||
that fix changes what every document SAYS in order to defend a tool
|
||||
outside the build: a source quoting a bundle listing would come out
|
||||
altered and existing bundles would move bytes.
|
||||
- A build run with no accounting door has no ledger, so a converted image
|
||||
is reported claimed-and-not-found rather than believed. That is the same
|
||||
reading the gate had before the conversion route existed.
|
||||
- Measured: the three arms PM reproduced go forged → refused, 3 of 3, with
|
||||
the known-positive (a BMP the run really does convert) True in all three.
|
||||
The text-level regression guard goes 3 arms to 13. R761 rebuilt is
|
||||
`diff -r`-identical, 50 assets (29 JPEG + 21 PNG), 19 of 19 conversions
|
||||
confirmed against 19 declared, SHY 71, u = 0, d = 0.
|
||||
- **An RLE8 stream that stops before the frame is refused (0.10.1).** The
|
||||
terminator rule added earlier in this version asks only that a stream SAY it
|
||||
is finished, and a stream can say so anywhere: measured 2026-09-19, one
|
||||
whose FIRST two bytes are the end-of-bitmap escape was carried with 32 of 32
|
||||
pixels never decoded, while an independent decoder refuses the same file.
|
||||
`_bmp_rle8_rows` now also requires the cursor to stand at or past the end of
|
||||
the last row (`asset_samples_invalid`).
|
||||
- **The line is the cursor and not the pixels.** A delta escape and an
|
||||
end-of-line escape state their skip, so the pixels they pass over keep
|
||||
index 0 and every decoder produces the same picture; a pixel-coverage
|
||||
count would refuse both constructions the format defines. The corpus
|
||||
cannot choose between the two rules — over the 25 RLE8 BMPs the R761
|
||||
delivery ships, 25 of 25 paint every pixel, 25 of 25 reach the end of the
|
||||
frame and 0 of 25 use a delta — and an independent decoder can: Pillow
|
||||
reads 5 of the 8 streams in the table and refuses the same 3 the new rule
|
||||
does, one of them short by a single pixel.
|
||||
- Two docstrings this round was sent to correct are rewritten: the test no
|
||||
longer claims every pixel is decoded, and `_bmp_rle8_rows` no longer
|
||||
frames the delta argument as read off the corpus, which it never was.
|
||||
- **The published `tbx:` count is one number, guarded without the delivery
|
||||
(0.10.1).** `assert sum(tbx.values()) == 568` sat behind a `skipif` on a file
|
||||
only one machine has, so on a fresh clone the sentence five files publish was
|
||||
unguarded — the state in which 574 survived in four docstrings. `N101_TBX_TAGS`
|
||||
is now the one place it lives and a second test holds all five published
|
||||
sentences to it, with no corpus and no clock. What it does not prove is
|
||||
stated: five files agreeing is agreement, not a count.
|
||||
- **The mutant runner judges a mutant by the suite that owns it, and the
|
||||
catalogue goes 39 to 45 (0.10.1).** It could only run one test file, which is
|
||||
why PM's three survivors from `43331fc` could not be added. `X3`/`X4` were
|
||||
rewritten against the code as it now stands; `X6` is the defeated state
|
||||
exactly (a pointer block believed without the run having booked it); `X7`
|
||||
cuts the ledger off at its source; `X8` removes the cursor rule; `P6`, `P11`
|
||||
and `P12` are PM's three. Two survivors appeared on the first run and both
|
||||
were findings — the asset binding had stopped being exercised, and the
|
||||
`_inline` disarming survived the WHOLE suite (2134 passed) because the gate
|
||||
no longer reads its claim from the bundle. The disarming is KEPT and now
|
||||
measured in `tests/test_assets.py`: the property is about the bundle, not
|
||||
about one judge. `killed 45 of 45`, exit 0.
|
||||
- **`test_the_four_existing_goldens_are_untouched` skips, with its reason, in
|
||||
a `git archive` extract (0.10.1).** It called `git status` with `check=True`
|
||||
outside a repository and raised. It was the single failure of the whole
|
||||
suite run from a clean extract, twice reported as a round's one failure by a
|
||||
round that had not touched the file.
|
||||
|
||||
- **A truncated RLE8 BMP is refused instead of carried as a partly blank PNG
|
||||
(0.10.1).** `_bmp_rle8_rows` painted what the stream held and left the rest
|
||||
of the frame at palette index 0 — which is what the format says about a
|
||||
|
|
|
|||
29
CLAUDE.md
29
CLAUDE.md
|
|
@ -1081,6 +1081,35 @@ and fixtures, never code.
|
|||
and not FIDELITY, which its docstring now states: a converter writing a
|
||||
blank PNG is accepted, the suite fells that mutant and the judge cannot.
|
||||
Report: `docs/2026-09-19-bmp-resten-terminator-og-pekerblokk.md`.
|
||||
**AND THAT ROUND NARROWED BOTH DEFECTS WITHOUT CLOSING EITHER.** A POINTER
|
||||
BLOCK IS A FORM AND A FORM IS NOT A SIGNATURE: measured through the real
|
||||
`okf build`, one ordinary HTML file with **two `<p>` elements** writes the
|
||||
two lines `_POINTER` matches, and the same refused BMP read as held again --
|
||||
also with `<p>`+`<br>`, and with a markdown note beside the HTML carrier,
|
||||
**3 of 3**. So the pair is read from the RUN's own ledger (`--accounting`
|
||||
now books `conversions: [{from, to}]` per document, off `assets.conversion`)
|
||||
and the bundle text only CONFIRMS it: the confirmation can be forged and the
|
||||
ledger cannot. **Chosen over neutralising pointer-shaped text at
|
||||
extraction**, which would change what every document SAYS to defend a tool
|
||||
outside the build. A build with no accounting door reports a converted image
|
||||
claimed-and-not-found rather than believing it. Measured: 3 of 3 forged ->
|
||||
refused with the known-positive True in all three, the text-level regression
|
||||
guard 3 arms -> 13, R761 rebuilt `diff -r`-identical, 50 assets, **19 of 19**
|
||||
conversions confirmed against 19 declared, SHY 71, u = 0, d = 0. And the
|
||||
TERMINATOR asks only that a stream say it is finished, which it may do
|
||||
anywhere: a stream whose FIRST two bytes are the EOB escape was carried with
|
||||
**32 of 32** pixels never decoded while Pillow refuses the same file. The
|
||||
cursor must now also stand at or past the end of the last row. **The line is
|
||||
the CURSOR and not the pixels** -- a delta and an end-of-line escape state
|
||||
their skip, so every decoder agrees on the index-0 pixels they pass over,
|
||||
and a pixel-coverage count would refuse both constructions the format
|
||||
defines. The corpus cannot choose (over the **25** RLE8 BMPs the delivery
|
||||
ships, 25 of 25 paint every pixel, 25 of 25 reach the end, **0 of 25** use a
|
||||
delta) and an independent decoder can: Pillow reads **5 of 8** streams and
|
||||
refuses the same **3**, one short by a single pixel. The earlier `19 of 19`
|
||||
figures above are the BUNDLE's carried assets; 25 is what the delivery
|
||||
ships. Report:
|
||||
`docs/2026-09-19-pekerblokken-bindes-til-kjoringen.md`.
|
||||
- **Account for content: `okf build --accounting PATH` and its judge
|
||||
`python3 tools/okf_accounting_gate.py` (2026-09-17).**
|
||||
- The gate was written RED at `0b00de4` and turned GREEN on all six rows by
|
||||
|
|
|
|||
174
docs/2026-09-19-pekerblokken-bindes-til-kjoringen.md
Normal file
174
docs/2026-09-19-pekerblokken-bindes-til-kjoringen.md
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
# The pointer block, bound to the run
|
||||
|
||||
2026-09-19. PM's checkpoint on `ae441ab` judged the previous round PARTIAL
|
||||
with one load-bearing rest and two small ones. The rest is the same class the
|
||||
round before it: the judge's fasit came from the reader it judges. It had been
|
||||
narrowed, not closed. This closes it, closes the two small ones, and clears
|
||||
three further residuals PM had listed. No new format, no new dependency, no
|
||||
version bump and no tag.
|
||||
|
||||
## 1. A form is not a signature
|
||||
|
||||
`tools/okf_accounting_gate.py` read the conversion claim out of the bundle
|
||||
text. The round before bound it to a POINTER BLOCK, which is the two lines
|
||||
`assets.render_block` writes:
|
||||
|
||||
```
|
||||

|
||||
Image: <name> (<w>x<h> px) -- converted from <type> sha256:<A> to <type> sha256:<B>
|
||||
```
|
||||
|
||||
That closed the two routes PM had measured (an `alt` attribute and plain body
|
||||
text) and left the class open, because a document can write the whole block.
|
||||
Reproduced here through the real `okf build`, three ways, each a whole build:
|
||||
|
||||
| way | before | known-positive in the same build |
|
||||
|---|---|---|
|
||||
| two `<p>` elements in one HTML file | **forged** | held |
|
||||
| one `<p>` with a `<br>` | **forged** | held |
|
||||
| a markdown note beside the HTML carrier | **forged** | held |
|
||||
|
||||
"Forged" means `asset_holds` returned True for a BMP declaring 50 000 x
|
||||
50 000, refused `asset_too_large`, absent from `assets/`. The forger needs two
|
||||
digests: the one it wants vouched for, and one of a picture the bundle really
|
||||
carries — public in the bundle, and computable in advance for a PNG carried
|
||||
verbatim.
|
||||
|
||||
### What was chosen, and why
|
||||
|
||||
Two fixes were on the table. The claim is now read from the RUN's own ledger:
|
||||
|
||||
- `assets.conversion(image)` names the `(source digest, asset digest)` pair.
|
||||
- `DocumentAssets.conversions` carries it out of the run.
|
||||
- `DocumentAccount.conversions` books it, and `okf build --accounting` writes
|
||||
`conversions: [{from, to}]` per document.
|
||||
- `_declared_conversions` reads that file; `_conversions` believes a pair only
|
||||
when the ledger holds it AND a pointer block confirms it for the asset it
|
||||
points at.
|
||||
|
||||
The confirmation can be forged and the ledger cannot, which is why the ledger
|
||||
decides. The alternative — neutralising pointer-shaped text at extraction, the
|
||||
way the soft-hyphen door neutralises U+00AD — was felled: it changes what every
|
||||
document SAYS in order to defend a tool outside the build, a source quoting a
|
||||
bundle listing would come out altered, and the bytes of existing bundles would
|
||||
move. This reads a file the run already writes.
|
||||
|
||||
A build with no accounting door has no ledger. A converted image is then
|
||||
reported claimed-and-not-found rather than believed, which is the reading the
|
||||
gate had before the conversion route existed, and it is visible in the row.
|
||||
|
||||
### After
|
||||
|
||||
3 of 3 forged → refused, with the known-positive True in all three. The
|
||||
text-level regression guard goes from 3 arms to 13: PM's eleven ways that the
|
||||
shape anchoring already refused, kept so a later narrowing cannot widen one of
|
||||
them, plus the two forms that defeated it — a perfectly written pointer block
|
||||
the run never booked.
|
||||
|
||||
R761 rebuilt from the frozen delivery: bundle `diff -r`-identical to the build
|
||||
before the change, 50 assets (29 JPEG + 21 PNG, 0 BMP), 19 of 19 conversions
|
||||
confirmed against 19 declared, soft hyphens 71 → 0, u = 0, d = 0, exit 0.
|
||||
|
||||
## 2. A terminator is not a coverage proof
|
||||
|
||||
The previous round's terminator rule asks only that a stream SAY it is
|
||||
finished, and a stream may say so anywhere. Measured: a stream whose FIRST two
|
||||
bytes are the end-of-bitmap escape was carried, with 32 of 32 pixels never
|
||||
decoded and all of them palette index 0. Pillow refuses the same file.
|
||||
|
||||
`_bmp_rle8_rows` now also requires the cursor to stand at or past the end of
|
||||
the last row, refusing with the same `asset_samples_invalid` otherwise.
|
||||
|
||||
**The line is the cursor, not the pixels.** A delta escape and an end-of-line
|
||||
escape STATE their skip, so the pixels they pass over keep index 0 and every
|
||||
decoder produces the same picture; a pixel-coverage count would refuse both
|
||||
constructions the format defines. The corpus cannot choose between the two
|
||||
rules — over the 25 RLE8 BMPs the R761 delivery ships (24 distinct; the bundle
|
||||
carries 19), 25 of 25 paint every pixel, 25 of 25 reach the end of the frame
|
||||
and 0 of 25 use a delta. An independent decoder can:
|
||||
|
||||
| stream over one 8x4 frame | cursor reaches the frame | Pillow |
|
||||
|---|---|---|
|
||||
| end-of-bitmap before one pixel is decoded | no | refuses |
|
||||
| one 4-pixel run, then end-of-bitmap | no | refuses |
|
||||
| last row one pixel short, no end-of-line | no | refuses |
|
||||
| every row painted and closed | yes | reads |
|
||||
| last row one pixel short, then end-of-line | yes | reads |
|
||||
| a delta skipping a whole row | yes | reads |
|
||||
| last row painted to its end, no end-of-line | yes | reads |
|
||||
| the shipped fixture, which uses a delta | yes | reads |
|
||||
|
||||
Eight of eight agree with the new rule, and a second test holds Pillow to the
|
||||
table so it is not our own rule restated.
|
||||
|
||||
Both docstrings PM named are rewritten. The test no longer says "NO PIXEL MAY
|
||||
BE GUESSED: either every one of them is decoded from the stream, or the picture
|
||||
is refused" — that was false as measured. `_bmp_rle8_rows` no longer frames the
|
||||
delta argument as read off the corpus, which it never was: 0 of the 25 files
|
||||
use a delta, so the corpus had nothing to say about it.
|
||||
|
||||
## 3. One number, read from one place
|
||||
|
||||
`assert sum(tbx.values()) == 568` sat behind a `skipif` on a delivery only this
|
||||
machine has, so on a fresh clone the sentence five files publish was unguarded
|
||||
again — the state in which 574 survived in four docstrings until PM counted it.
|
||||
`N101_TBX_TAGS` is now the one place the number lives, and a second test reads
|
||||
the published sentence out of `CHANGELOG.md`, `CLAUDE.md`, `tools/okf_witness.py`,
|
||||
`tests/test_accounting_gate.py` and this round's predecessor report, holding all
|
||||
five to it. It needs no corpus and no clock.
|
||||
|
||||
It was red at birth, and for a reason worth keeping: the scan read the test
|
||||
file's own known-positive string (`574`) as a sixth publisher. That string is
|
||||
now assembled from pieces, and the failure is the demonstration that the scan
|
||||
reads what it is pointed at. What the guard does NOT prove is stated in its
|
||||
docstring: five files agreeing is agreement, not a count. The measurement stays
|
||||
where it was.
|
||||
|
||||
## 4. A clean extract is not a checkout
|
||||
|
||||
`test_the_four_existing_goldens_are_untouched` ran `git status` with
|
||||
`check=True` in a `git archive` extract and raised `CalledProcessError`. It was
|
||||
the single failure of the whole suite run from a clean extract, twice reported
|
||||
as a round's one failure by a round that had not touched the file. Both arms
|
||||
measure the checkout with `git`, so an extract has nothing to ask: it now skips
|
||||
with the reason stated, and a checkout still has to answer.
|
||||
|
||||
## 5. The mutant runner
|
||||
|
||||
`tools/okf_gate_mutants.py` could only run one test file, which is why PM's
|
||||
three survivors from `43331fc` could not be added: two are held by the gate's
|
||||
row 3 and one by the soft-hyphen door's own suite. A mutant now names the suite
|
||||
it is judged by, and the catalogue goes 39 to 45:
|
||||
|
||||
- **X3** and **X4** were rewritten against the code as it now stands. A mutant
|
||||
table is a copy of the code it mutates, and this round moved the lines both
|
||||
of them quoted.
|
||||
- **X6** is the defeated state exactly: a pointer block believed without the
|
||||
run having booked it.
|
||||
- **X7** cuts the ledger off at its source.
|
||||
- **X8** removes the cursor rule.
|
||||
- **P6**, **P11**, **P12** are PM's three, now held by what runs AS the gate.
|
||||
|
||||
Two survivors appeared on the first run and both were findings.
|
||||
|
||||
**X4** — "the claim need not be about the asset its block points at" — survived
|
||||
because every forgery arm now fails on the ledger check before the binding is
|
||||
reached. An arm was added where the run DID book the pair and the block stating
|
||||
it points at another picture; under the mutant that reads as a carry.
|
||||
|
||||
**X5** — "a document-supplied label may emit a checksum field" — survived the
|
||||
WHOLE suite, measured: 2134 passed with the disarming removed. The gate no
|
||||
longer reads its claim out of the bundle, so a document-supplied field cannot
|
||||
reach it. The property did not stop mattering — the line stands in every
|
||||
concept body, and a bundle must not state a conversion in a sentence the run
|
||||
did not write — so it is measured where it lives, in `tests/test_assets.py`,
|
||||
and the mutant is judged there. Deleting an unfellable guard was the other
|
||||
option and was felled: this guard is about the bundle, not about one judge.
|
||||
|
||||
## 6. What this round does not do
|
||||
|
||||
- It does not teach the gate FIDELITY. A converter writing a blank PNG is still
|
||||
accepted, for the reason `asset_holds` states: both routes ask whether a file
|
||||
holds the bytes the run names, and neither decodes a pixel.
|
||||
- It does not touch the guard, the goldens, the proposer, any profile, any
|
||||
version or any dependency.
|
||||
|
|
@ -755,13 +755,30 @@ def test_a_document_cannot_forge_a_conversion_claim(tmp_path: Path) -> None:
|
|||
# KNOWN-POSITIVE on the same bytes: the last arm's text, believed once the
|
||||
# RUN books the pair. Without it every arm above would pass on a route
|
||||
# that had simply stopped working.
|
||||
booked = _ledger((before, after))
|
||||
honest = _build(
|
||||
assets=assets,
|
||||
bundle_text=arms["that block alone in the bundle"],
|
||||
accounting=_ledger((before, after)),
|
||||
accounting=booked,
|
||||
)
|
||||
assert gate.asset_holds(honest, never_carried) is True
|
||||
|
||||
# THE ASSET BINDING, ON ITS OWN. The run booked this pair and the block
|
||||
# stating it points at a different picture -- a sentence nothing here
|
||||
# writes. Measured 2026-09-19: with the ledger in front of it, every arm
|
||||
# above passes whether or not the binding is checked, so without this the
|
||||
# mutant that removes it survives the whole suite.
|
||||
misplaced = _build(
|
||||
assets=assets,
|
||||
bundle_text=(
|
||||
f"\nImage: figur.bmp (8x4 px) -- {clause}\n"
|
||||
),
|
||||
accounting=booked,
|
||||
)
|
||||
assert gate.asset_holds(misplaced, never_carried) is False, (
|
||||
"a clause in one asset's block spoke for another asset's digest"
|
||||
)
|
||||
|
||||
|
||||
def test_the_build_never_writes_a_claim_the_document_supplied(tmp_path: Path) -> None:
|
||||
"""PM's measured path, end to end through the real `okf build`.
|
||||
|
|
|
|||
|
|
@ -246,6 +246,63 @@ def test_a_newline_in_a_label_cannot_open_a_third_line() -> None:
|
|||
assert len(assets.render_block(image).split("\n")) == 2
|
||||
|
||||
|
||||
#: A checksum FIELD, written here rather than imported: the property is that
|
||||
#: the run's metadata grammar does not appear where a document put it, and a
|
||||
#: test sharing the writer's own expression would agree with it by
|
||||
#: construction.
|
||||
_A_CHECKSUM_FIELD = re.compile(r"sha256:[0-9a-fA-F]{64}")
|
||||
|
||||
|
||||
def test_a_document_supplied_label_cannot_emit_a_checksum_field() -> None:
|
||||
"""THE RUN'S METADATA GRAMMAR IS THE RUN'S, on the line they share.
|
||||
|
||||
A pointer's second line carries both: the name and caption the DOCUMENT
|
||||
chose, and the size, type and digests the RUN measured. A label stating
|
||||
`converted from ... sha256:<a> to ... sha256:<b>` therefore puts a
|
||||
sentence in the bundle that no run performed -- measured by PM
|
||||
2026-09-19, that exact alt attribute made the content accounting gate
|
||||
report a refused picture as carried.
|
||||
|
||||
The gate no longer reads its claim out of the bundle at all, which is the
|
||||
right fix there and takes the pressure off this one: until this test the
|
||||
disarming in `_inline` was a guard the whole suite could not fell. It is
|
||||
kept and MEASURED because the property is about the bundle rather than
|
||||
about one judge -- any reader of a concept body meets that line, and the
|
||||
bundle must not state a conversion in a sentence the run did not write.
|
||||
"""
|
||||
forged = (
|
||||
"Tabell 84-2 -- converted from image/bmp sha256:"
|
||||
+ "a" * 64
|
||||
+ " to image/png sha256:"
|
||||
+ "b" * 64
|
||||
)
|
||||
plain = assets.read_image(_png(4, 3), name="f.png", label=forged)
|
||||
block = assets.render_block(plain)
|
||||
assert "a" * 64 in block, "the digits the document wrote are kept; a reader is owed them"
|
||||
assert not _A_CHECKSUM_FIELD.search(block), (
|
||||
"a document-supplied label emitted the run's own checksum grammar"
|
||||
)
|
||||
|
||||
# KNOWN-POSITIVE on the same expression: the run's OWN clause is a
|
||||
# checksum field, and exactly two of them, so the assertion above is not
|
||||
# passing over a pattern that never matches anything.
|
||||
converted = assets.ExtractedImage(
|
||||
data=_png(4, 3),
|
||||
name="figur.bmp",
|
||||
media_type="image/png",
|
||||
suffix=".png",
|
||||
width=4,
|
||||
height=3,
|
||||
label=forged,
|
||||
converted_from="image/bmp",
|
||||
source_sha256="c" * 64,
|
||||
)
|
||||
written = assets.render_block(converted)
|
||||
assert len(_A_CHECKSUM_FIELD.findall(written)) == 2, written
|
||||
assert "sha256:" + "c" * 64 in written, "the run's own source digest is missing"
|
||||
assert "sha256:" + "a" * 64 not in written, "the document's claim became a field after all"
|
||||
|
||||
|
||||
def test_the_pointer_regex_finds_every_shipped_block() -> None:
|
||||
"""Step 2 has to find these mechanically; the finder ships with the writer."""
|
||||
images = [
|
||||
|
|
|
|||
|
|
@ -63,6 +63,12 @@ class Mutant:
|
|||
#: a chance to see the disagreement.
|
||||
occurrences: int = 1
|
||||
first_only: bool = False
|
||||
#: The test file this mutant is judged by. Defaults to the gate's own
|
||||
#: suite, which every mutant used until 2026-09-19 -- which is why the
|
||||
#: three PM found in `43331fc` could not be added here: they are held by
|
||||
#: the SHY door's suite and by the gate's row 3, and a runner that can
|
||||
#: only run one file cannot ask about them.
|
||||
suite: str = SUITE
|
||||
|
||||
|
||||
MUTANTS: tuple[Mutant, ...] = (
|
||||
|
|
@ -304,31 +310,82 @@ MUTANTS: tuple[Mutant, ...] = (
|
|||
Mutant(
|
||||
"X3 the conversion claim is read from anywhere in the bundle text",
|
||||
GATE,
|
||||
""" found: dict[str, str] = {}
|
||||
for pointer in _POINTER.finditer(bundle_text):
|
||||
clause = _CONVERSION.search(pointer.group("detail"))
|
||||
if clause is None:
|
||||
continue
|
||||
after = clause.group("after")
|
||||
# The claim has to be about the picture the block points at. A clause
|
||||
# standing in one asset's block while naming another's digest is a
|
||||
# sentence nothing in this build writes.
|
||||
if pointer.group("asset").startswith(after[:12]):
|
||||
found[clause.group("before")] = after
|
||||
return found""",
|
||||
""" return {m.group("before"): m.group("after") for m in _CONVERSION.finditer(bundle_text)}""",
|
||||
""" declared = _declared_conversions(build)
|
||||
if not declared:
|
||||
return {}
|
||||
found: dict[str, str] = {}""",
|
||||
""" declared = _declared_conversions(build)
|
||||
del declared
|
||||
return {
|
||||
m.group("before"): m.group("after") for m in _CONVERSION.finditer(build.bundle_text)
|
||||
}
|
||||
found: dict[str, str] = {}""",
|
||||
),
|
||||
Mutant(
|
||||
"X4 the claim need not be about the asset its block points at",
|
||||
GATE,
|
||||
'if pointer.group("asset").startswith(after[:12]):',
|
||||
"if True:",
|
||||
'if (before, after) in declared and pointer.group("asset").startswith(after[:12]):',
|
||||
"if (before, after) in declared:",
|
||||
),
|
||||
# X5 moved suites 2026-09-19. It was felled by the gate's own suite while
|
||||
# the gate read its claim out of the bundle; once the claim came from the
|
||||
# run's ledger, a document-supplied field could not reach the gate at all
|
||||
# and the mutant survived the WHOLE suite -- measured, 2134 passed. The
|
||||
# property did not stop mattering: the line is in every concept body, and
|
||||
# a bundle must not state a conversion the run never performed. It is
|
||||
# measured where it lives now.
|
||||
Mutant(
|
||||
"X5 a document-supplied label may emit a checksum field",
|
||||
"src/llm_ingestion_okf/assets.py",
|
||||
'return _CHECKSUM_FIELD.sub("sha256 ", collapsed.replace("[", "(").replace("]", ")"))',
|
||||
'return collapsed.replace("[", "(").replace("]", ")")',
|
||||
suite="tests/test_assets.py",
|
||||
),
|
||||
# PM's sjekkpunkt 2026-09-19 on `ae441ab`: the round above bound the claim
|
||||
# to a pointer BLOCK, and one HTML file with two `<p>` elements writes one.
|
||||
# X6 is that state exactly -- the shape believed without the run's ledger.
|
||||
Mutant(
|
||||
"X6 a pointer block is believed without the run having booked it",
|
||||
GATE,
|
||||
'if (before, after) in declared and pointer.group("asset").startswith(after[:12]):',
|
||||
'if pointer.group("asset").startswith(after[:12]):',
|
||||
),
|
||||
Mutant(
|
||||
"X7 the run's ledger is read from the bundle instead of the accounting",
|
||||
GATE,
|
||||
" accounting = build.accounting\n if not isinstance(accounting, dict):",
|
||||
" accounting = None\n if not isinstance(accounting, dict):",
|
||||
),
|
||||
# The RLE8 cursor rule, judged by the file that measures it against an
|
||||
# independent decoder. Without a per-mutant suite this could not be asked
|
||||
# from here at all.
|
||||
Mutant(
|
||||
"X8 a stream may end before the cursor reaches the frame",
|
||||
"src/llm_ingestion_okf/assets.py",
|
||||
" if y < height - 1 or (y == height - 1 and x < width):",
|
||||
" if False:",
|
||||
suite="tests/test_asset_viewable.py",
|
||||
),
|
||||
# PM's three survivors from `43331fc`, held until now by ordinary tests
|
||||
# and not by what runs AS the gate.
|
||||
Mutant(
|
||||
"P6 the normalisation door removes U+00A0 as well",
|
||||
"src/llm_ingestion_okf/extract.py",
|
||||
' return text.replace(SOFT_HYPHEN, ""), removed',
|
||||
' return text.replace(SOFT_HYPHEN, "").replace("\\u00a0", ""), removed',
|
||||
suite="tests/test_soft_hyphen_door.py",
|
||||
),
|
||||
Mutant(
|
||||
"P11 row 3's detail line drops the refused count",
|
||||
GATE,
|
||||
'f"unverified={u.unverified} invalid={u.invalid} refused={u.refused}"',
|
||||
'f"unverified={u.unverified} invalid={u.invalid}"',
|
||||
),
|
||||
Mutant(
|
||||
"P12 row 3's reason drops the refused-whole clause",
|
||||
GATE,
|
||||
'f"{refused} element(s) lost with {refused_docs} of {documents} document(s) refused whole"',
|
||||
'f"{refused} element(s) lost"',
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -378,7 +435,16 @@ def main(argv: list[str] | None = None) -> int:
|
|||
environment["PYTHONPATH"] = str(root / "src")
|
||||
try:
|
||||
run = subprocess.run(
|
||||
[sys.executable, "-m", "pytest", SUITE, "-q", "-x", "-p", "no:cacheprovider"],
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pytest",
|
||||
mutant.suite,
|
||||
"-q",
|
||||
"-x",
|
||||
"-p",
|
||||
"no:cacheprovider",
|
||||
],
|
||||
cwd=root,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue