docs: the BMP rest, the terminator and the pointer block
CHANGELOG under the UNTAGGED `[0.10.1]` -- no version bump, no tag. Three entries: the forged carry under Security, the truncated RLE8 under Fixed, and the two small rests (the judge's fidelity limit, the lossless guard's core arm) under "Documented, not changed". The report carries the measurements with their denominators, including the two checks this round introduced and then REMOVED after measuring that no mutant can fell them -- with the numbers for each (the gate suite green without the line anchor; 95 passed with and 95 without the length check, so the mutant the order asked for survives). CLAUDE.md records both defects and both rules where the viewable-asset paragraph already stands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
beef436cbb
commit
ae441abec4
3 changed files with 267 additions and 0 deletions
65
CHANGELOG.md
65
CHANGELOG.md
|
|
@ -141,6 +141,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Security
|
||||
|
||||
- **A document can no longer forge a carry in the content-accounting gate
|
||||
(0.10.1).** New in the viewable-asset round: a converted image's own bytes
|
||||
are not in `assets/`, so `asset_holds` gained a second route that reads the
|
||||
two digests the bundle states on the pointer line. The expression ran over
|
||||
the WHOLE bundle text, so a document could simply write the sentence.
|
||||
Measured by PM 2026-09-19: a BMP declaring 50 000 x 50 000, refused
|
||||
`asset_too_large` and absent from `assets/`, was reported as held — through
|
||||
an image's `alt` text, and through ordinary body text. Before that route
|
||||
existed, `asset_holds` hashed the source file and nothing a document wrote
|
||||
could reach it; the gate's own first sentence is that the fasit never comes
|
||||
from the reader it judges, and `claimed and not found` could be silenced by
|
||||
a document that asked for it.
|
||||
- The claim now counts only inside a POINTER BLOCK this code wrote, and only
|
||||
where it names the asset that block points at. That closes body text and a
|
||||
table cell.
|
||||
- An image's LABEL is document text written inside a pointer block, so
|
||||
`assets._inline` disarms a checksum field in anything that came from the
|
||||
document: the digits are kept, the colon that makes them a field is not.
|
||||
That closes the `alt` route. Neither half is sufficient alone.
|
||||
- Three mutants in `tools/okf_gate_mutants.py`, one per check, each felled by
|
||||
its own arm; the harness now runs the copy with its own `src/` on
|
||||
`PYTHONPATH`, because an editable install made a `src/` mutant resolve to
|
||||
the working tree and survive without having been applied.
|
||||
|
||||
- **A remote image reference is no longer a live markdown image link
|
||||
(0.10.1).** New in 0.10.0: before it, no reader read an `<img>` attribute at
|
||||
all. A document could put ``
|
||||
|
|
@ -258,6 +282,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Fixed
|
||||
|
||||
- **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
|
||||
SKIPPED pixel, so no decoder disagreed and the picture was wrong with no
|
||||
code and no row. Measured by PM 2026-09-19 on a real R761 asset (352x548 =
|
||||
192 896 pixels): cut to 90 % it was carried with 13 923 pixels wrong, to
|
||||
50 % with 95 890, to 10 % with 166 525. The uncompressed path already
|
||||
refused the same shape.
|
||||
- The decode may now end at an explicit end-of-bitmap escape and nowhere
|
||||
else; running out of bytes raises `asset_samples_invalid`, the code the
|
||||
uncompressed path uses. NO PIXEL IS GUESSED: either every one is decoded
|
||||
from the stream, or the picture is refused with a line in the concept.
|
||||
- The rule is the terminator rather than `biSizeImage` (a claim by the same
|
||||
untrusted header) or a coverage count (which would refuse the delta escape
|
||||
the format defines), and it is read off the corpus: over the 19 real RLE8
|
||||
assets of the frozen R761 delivery, **19 of 19** end at an explicit
|
||||
end-of-bitmap, on **19 of 19** it is the stream's last two bytes, and on
|
||||
**19 of 19** `biSizeImage` equals the available bytes. A whole stream that
|
||||
omits the terminator is refused alongside a cut one.
|
||||
- **Nothing real changes hands:** the same 19 files still convert losslessly
|
||||
after the rule, **2 366 365 pixels** compared — this time with stdlib on
|
||||
BOTH sides, an independent BMP reader and an independent `zlib` +
|
||||
filter-reversal PNG decoder, with a one-byte control proving the
|
||||
comparison can fail.
|
||||
|
||||
- **The content-accounting gate: a document refused whole is never clean.**
|
||||
Its elements are all booked as coded rejections, so u = 0 and d = 0, and
|
||||
`refused_whole` asks its question only for a corpus that persisted NOTHING —
|
||||
|
|
@ -317,6 +366,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Documented, not changed
|
||||
|
||||
- **The accounting gate proves CARRIAGE, not FIDELITY.** Neither of
|
||||
`asset_holds`'s routes decodes a pixel: a converter writing a blank PNG is
|
||||
accepted, because the bundle is internally consistent. The suite fells that
|
||||
mutant by decoding both sides; the judge cannot, and its docstring now says
|
||||
so — "claiming a conversion it did not perform" means claiming one whose
|
||||
FILE is missing, never one whose pixels are wrong.
|
||||
|
||||
- **The lossless guard now has an arm that runs on a core install.** It decoded
|
||||
through Pillow, an OPTIONAL dependency here (transitive under `pdfplumber` in
|
||||
`[extract]`), so 4 of the 13 guards in `tests/test_asset_viewable.py` were
|
||||
SKIPPED on a plain `pip install llm-ingestion-okf` — the lossless one among
|
||||
them. The new arm decodes the carried PNG with `zlib` and the five PNG SS 9.2
|
||||
filters and compares against pixels written out in the test file, and it is
|
||||
re-run under a `sys.meta_path` finder that makes every `PIL` import fail.
|
||||
|
||||
|
||||
- `images: N` in a concept counts POINTER BLOCKS, not unique pictures (12
|
||||
pointers to 2 files is `images: 12`). Now stated in the README.
|
||||
- A concept that is only a pointer block is persisted as substantive, because
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue