test(accounting): the judge cannot prove a CONVERTED image was carried (red)

Found by running the gate against the working tree: R761 goes from 0 to
**19 claimed and not found** the moment the conversion lands, and 19 is
exactly its RLE8 BMP count.

The cause is a rule that was right until this round. `asset_holds` proves a
carry by hashing the SOURCE file and looking for those bytes under their own
content address in `assets/`. A converted image's source bytes are not in the
bundle and never will be -- the run carried the picture under a new digest,
which the bundle states on the pointer line beside the old one.

Red on the claim: `asset_holds` returns False for a build whose bundle
declares the conversion and whose `assets/` holds the named file. Two
known-negatives are in the same test so the second route cannot become a way
of believing the report: a bundle that claims a conversion and ships no file,
and a bundle shipping a file under a digest it never tied to this source.
Both must stay False, because the judge has to hash the asset itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-19 07:57:43 +02:00
commit 955ec4b2ca
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q

View file

@ -461,6 +461,48 @@ def _build(
)
def test_the_judge_proves_a_CONVERTED_image_was_carried(tmp_path: Path) -> None:
"""A BMP reaches the bundle as a PNG, so the SOURCE's bytes are not in
`assets/` and never will be.
`asset_holds` proved a carry by hashing the source file and looking for
those bytes. That is right for an image carried verbatim and wrong for one
the build converts: the run did carry the picture, under a new digest the
bundle STATES, and a judge that only knew the first rule reported 19 of
R761's 50 images as claimed-and-not-found the day the conversion landed.
The second route is not the build's naming rule restated. The gate reads
the two digests the bundle writes, and then HASHES the asset itself: the
claim is only accepted when a file in `assets/` actually holds the bytes
the bundle says it wrote. A bundle claiming a conversion it did not
perform still fails.
"""
source = tmp_path / "figur.bmp"
source.write_bytes(b"BM" + b"\x00" * 200)
carried = tmp_path / "carried.png"
carried.write_bytes(b"\x89PNG\r\n\x1a\n" + b"\x01" * 64)
before = gate._sha256(source)
after = gate._sha256(carried)
text = (
f"![Figur](/assets/{after[:12]}-figur.png)\n"
f"Image: graphics/figur.bmp (8x4 px) -- converted from image/bmp "
f"sha256:{before} to image/png sha256:{after}\n"
)
build = _build(assets={f"{after[:12]}-figur.png": after}, bundle_text=text)
assert gate.asset_holds(build, source) is True
# Known-negative on the same shape: the bundle says it converted, and the
# file it names is not there. A route that read the claim alone would pass.
empty = _build(assets={}, bundle_text=text)
assert gate.asset_holds(empty, source) is False
# Known-negative two: an asset IS there, under a digest the bundle never
# tied to this source.
other = "0" * 64
stranger = _build(assets={f"{other[:12]}-x.png": other}, bundle_text=text)
assert gate.asset_holds(stranger, source) is False
def _declared(heading: int = 2, image: int = 1, fate: str = "rejected") -> dict[str, Any]:
return {
"accounting_version": 1,