receipt-ledger: version 5 holds a decode to the frames it delivered, its codestream what it read #559

Merged
dcharlot merged 3 commits from wai/decode-output into main 2026-11-01 04:38:01 -05:00
Owner

The flaw. The receipt ledger gives every int_motion job output as its decode receipt and its codestream, and since #556 holds the codestream to what the served hop delivered. That is true of an encode. A decode delivers its reconstruction, and the codestream is what it read. A conforming router therefore had to state the decode's input as what it delivered, and commit the hop's OER/2 receipt to an object the hop never produced: the binding #552 exists to forbid.

The rule (extensions/receipt-ledger.md §4.8, tariff and invoice version 5). Version 5 is version 4's layout, rules and prices with one rule more:

  1. A decode's output gives receipt, codestream and frames. The receipt is still re-derived from the codestream, which is the decode's input.

  2. frames is one animated PNG (PNG's third edition: acTL, fcTL, fdAT) of 8-bit RGB. It is read whole first, by a still's chunk rules plus the animation's:

    • every frame is the whole picture with blend 0, so nothing is composited;
    • the default image is the first frame;
    • sequence numbers run in order;
    • acTL counts the frames it holds.

    It must have the receipt's size and frame count. Then each frame is read as a still's image data, and its samples must hash (integer-payloads §15.1) to the receipt's frame at its index.

  3. The served hop states exactly that animation, by content hash, and nothing else.

Why one object, not one PNG per frame. An earlier head of this PR held each frame as its own PNG, and that cannot work. A route record states a hop's outputs once each and at most 1024 (route-record §5.2). A decode of more than 34 s at 30 fps could not be recorded, and a still scene, which repeats a frame, could not be stated at all. An animated PNG is lossless, one file that every browser plays and any tool splits into stills, and a still reader reads its first frame. The frame hash binds the samples, not the PNG's bytes, so any writer's animation of the right samples holds.

Reason for a new version. A version-4 reader would refuse a decode's frames, and no version-4 verdict may change. Versions 1 to 4 read, verify and bill exactly as before. A decode bills its receipts' subpixels as before, and an encode and every other job are held as in version 4.

Animated PNG in wai-rs (png_still):

  • encode_animation: every byte is a function of the frames and the delay.
  • animation: reads the whole structure, then each frame's samples only when asked, so a long clip is never held decoded in memory.
  • The still reader and writer now share the inflate-and-unfilter and compress steps with it. Their output is unchanged, and every still corpus is untouched.

Corpus. 89 → 108 vectors. One is accepted: a decode held to its animation, beside an encode. Eighteen are controls:

  • the record states the codestream the decode read;
  • it states that codestream past the animation;
  • the decode is in version 4's form;
  • a frame has one sample changed;
  • two frames are swapped;
  • a still is given for the animation;
  • a frame is missing;
  • the frames have another shape but the same samples;
  • the codestream is not the receipt's;
  • the animation blends a frame over the one before;
  • it disposes of a frame by an undefined operation;
  • it has a frame of part of the picture;
  • it skips a sequence number;
  • its default image is apart from its frames;
  • it counts one frame more than it holds;
  • its last frame has no data;
  • version 5's form is given under version 4;
  • a version-4 invoice is given under a version-5 tariff.

Every other vector and source is unchanged byte for byte, except the acknowledged invoice_version control (now version 6).

Checked.

  • wai-rs on Linux, with receipt_ledger's features:

    • --lib png_still::: 6 passed, including a round trip with a repeated frame and every animation rule refused alone;
    • --lib receipt_ledger::: 13 passed;
    • wai_receipt_ledger_vectors gen regenerates the file byte for byte, and verify gives every vector its outcome.
  • receipt_ledger_verify.py, written from the text and sharing no code, with its own animation reader:

    • all 108 vectors pass;
    • all 124 mutated copies fail;
    • all 33 of its checks, decode-frames among them, are caught when dropped.
  • Dependent verifiers: those of the corpora that read the ledger's (revenue share, opportunity report, route record) all pass.

  • Rust falsification: each rule was mutated alone in the reference (16 mutations), each run against a passing baseline:

    • ledger: only version 5 holds a decode; version 5 bills as 4; a version-5 tariff reads; the operation key; the re-derivation from the codestream; the animation's size; its frame count; each frame's hash; the animation at its place; nothing past it;
    • animation reader: acTL's count; each frame the whole picture; a defined dispose; blend 0; an fdAT's sequence number; the last frame's data.

    The corpus caught every one, and the restored tree passes. Two reader rules have no corpus control that only they refuse: an fcTL's sequence number, and image data only as the first frame's (the default-image-apart control breaks other rules too). The unit tests refuse each of them alone.

🤖 Generated with Claude Code

**The flaw.** The receipt ledger gives every `int_motion` job output as its decode receipt and its codestream, and since #556 holds the codestream to what the served hop delivered. That is true of an encode. A decode delivers its reconstruction, and the codestream is what it read. A conforming router therefore had to state the decode's *input* as what it delivered, and commit the hop's OER/2 receipt to an object the hop never produced: the binding #552 exists to forbid. **The rule** (`extensions/receipt-ledger.md` §4.8, tariff and invoice version 5). Version 5 is version 4's layout, rules and prices with one rule more: 1. A decode's output gives `receipt`, `codestream` and `frames`. The receipt is still re-derived from the codestream, which is the decode's input. 2. `frames` is **one animated PNG** (PNG's third edition: `acTL`, `fcTL`, `fdAT`) of 8-bit RGB. It is read whole first, by a still's chunk rules plus the animation's: - every frame is the whole picture with blend 0, so nothing is composited; - the default image is the first frame; - sequence numbers run in order; - `acTL` counts the frames it holds. It must have the receipt's size and frame count. Then each frame is read as a still's image data, and its samples must hash (integer-payloads §15.1) to the receipt's frame at its index. 3. The served hop states exactly that animation, by content hash, and nothing else. **Why one object, not one PNG per frame.** An earlier head of this PR held each frame as its own PNG, and that cannot work. A route record states a hop's outputs once each and at most 1024 (route-record §5.2). A decode of more than 34 s at 30 fps could not be recorded, and a still scene, which repeats a frame, could not be stated at all. An animated PNG is lossless, one file that every browser plays and any tool splits into stills, and a still reader reads its first frame. The frame hash binds the samples, not the PNG's bytes, so any writer's animation of the right samples holds. **Reason for a new version.** A version-4 reader would refuse a decode's `frames`, and no version-4 verdict may change. Versions 1 to 4 read, verify and bill exactly as before. A decode bills its receipts' subpixels as before, and an encode and every other job are held as in version 4. **Animated PNG in wai-rs** (`png_still`): - `encode_animation`: every byte is a function of the frames and the delay. - `animation`: reads the whole structure, then each frame's samples only when asked, so a long clip is never held decoded in memory. - The still reader and writer now share the inflate-and-unfilter and compress steps with it. Their output is unchanged, and every still corpus is untouched. **Corpus.** 89 → 108 vectors. One is accepted: a decode held to its animation, beside an encode. Eighteen are controls: - the record states the codestream the decode read; - it states that codestream past the animation; - the decode is in version 4's form; - a frame has one sample changed; - two frames are swapped; - a still is given for the animation; - a frame is missing; - the frames have another shape but the same samples; - the codestream is not the receipt's; - the animation blends a frame over the one before; - it disposes of a frame by an undefined operation; - it has a frame of part of the picture; - it skips a sequence number; - its default image is apart from its frames; - it counts one frame more than it holds; - its last frame has no data; - version 5's form is given under version 4; - a version-4 invoice is given under a version-5 tariff. Every other vector and source is unchanged byte for byte, except the acknowledged `invoice_version` control (now version 6). **Checked.** - **wai-rs on Linux, with `receipt_ledger`'s features:** - `--lib png_still::`: 6 passed, including a round trip with a repeated frame and every animation rule refused alone; - `--lib receipt_ledger::`: 13 passed; - `wai_receipt_ledger_vectors gen` regenerates the file byte for byte, and `verify` gives every vector its outcome. - **`receipt_ledger_verify.py`**, written from the text and sharing no code, with its own animation reader: - all 108 vectors pass; - all 124 mutated copies fail; - all 33 of its checks, `decode-frames` among them, are caught when dropped. - **Dependent verifiers:** those of the corpora that read the ledger's (revenue share, opportunity report, route record) all pass. - **Rust falsification:** each rule was mutated alone in the reference (16 mutations), each run against a passing baseline: - **ledger:** only version 5 holds a decode; version 5 bills as 4; a version-5 tariff reads; the operation key; the re-derivation from the codestream; the animation's size; its frame count; each frame's hash; the animation at its place; nothing past it; - **animation reader:** acTL's count; each frame the whole picture; a defined dispose; blend 0; an fdAT's sequence number; the last frame's data. The corpus caught every one, and the restored tree passes. Two reader rules have no corpus control that only they refuse: an fcTL's sequence number, and image data only as the first frame's (the default-image-apart control breaks other rules too). The unit tests refuse each of them alone. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
receipt-ledger: version 5 holds a decode to the frames it delivered, its codestream what it read
All checks were successful
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 17m54s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (pull_request) Successful in 10s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 14m29s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 9m42s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 7m18s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 8m22s
wai-quantum docs, course and locales / the course and the command line's languages · linux (pull_request) Successful in 2m25s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 3m36s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 3m47s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 10m4s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 6m20s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 7m15s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 28m47s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 13s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 15m51s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 45s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m34s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 19m27s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 1m3s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 20m53s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 8m27s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 7m9s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m20s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 15m9s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 26s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 10m37s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m28s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m54s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 3m17s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h17m30s
b9ed0f2b5e
Version 4 gives every int_motion output as its receipt and its codestream and holds the
codestream to what the hop delivered (§5.1). That is true of an encode and false of a decode,
which delivers its reconstruction: a conforming router had to state the codestream the decode
read as what it delivered, and commit the hop's receipt to an object it never delivered.

Tariff and invoice version 5 (§4.8) are version 4's layout, rules and prices with one rule
more. A decode's output also gives `frames`, one PNG of 8-bit RGB per frame read as packaging
§5.7 reads a still, each one's samples hashing to the receipt's frame at its index; the receipt
is still re-derived from the codestream, the decode's input; and the served hop states exactly
those frames, in order, and nothing else. Versions 1 to 4 read, verify and bill as before.

The corpus adds thirteen vectors (one accepted, twelve controls) and keeps every other vector
but the `invoice_version` control byte for byte; receipt_ledger_verify.py reads version 5 with
the packaging verifier's PNG reader and drops one more check (`decode-frames`); the ledger
service bills version 5 as version 4.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
receipt-ledger: a frame is read as packaging §5 reads a still
Some checks failed
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-quantum docs, course and locales / does this change touch it (pull_request) Has been cancelled
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Has been cancelled
wai-quantum docs, course and locales / the course and the command line's languages · linux (pull_request) Has been cancelled
wai-quantum docs, course and locales / the Studio's words in every locale · linux (pull_request) Has been cancelled
wai-quantum for JavaScript / does this change touch it (pull_request) Has been cancelled
wai-quantum for JavaScript / javascript · linux (pull_request) Has been cancelled
wai-quantum studio and desktop / does this change touch it (pull_request) Has been cancelled
wai-quantum studio and desktop / studio · browser (pull_request) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (pull_request) Has been cancelled
wai-quantum studio and desktop / desktop app · linux (pull_request) Has been cancelled
wai-quantum studio and desktop / desktop app · windows (pull_request) Has been cancelled
wai-sink-android native sink library / does this change touch it (pull_request) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Has been cancelled
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Has been cancelled
wai-sink-swift native sink package / does this change touch it (pull_request) Has been cancelled
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Has been cancelled
WAI Studio / does this change touch it (pull_request) Has been cancelled
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Has been cancelled
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Has been cancelled
WAI Studio / Studio in WebKit · linux (pull_request) Has been cancelled
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
fff7c5b8a6
packaging numbers its subsections in bold, not as headings, so §5.7 is not a
section the cross-reference check can resolve; the other texts cite §5.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
receipt-ledger: a decode delivers its frames as one animated PNG
All checks were successful
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 11m39s
wai-pack / wai-pack · linux (pull_request) Successful in 3m47s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (pull_request) Successful in 21s
wai-quantum docs, course and locales / the course and the command line's languages · linux (pull_request) Successful in 2m7s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 9m55s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 3m48s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 16m28s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 4m0s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 51s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 15m56s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 13m43s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 5m29s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m24s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 15m39s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 11m10s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 7m34s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 21s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 20m17s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 12s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 34s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m35s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 15m30s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 7m20s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 15m4s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m59s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 22s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m22s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m48s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m16s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h10m24s
4eb5caa684
Version 5 held each frame of a decode to its own PNG object, matched in order
against the served hop's outputs. A route record states those outputs once each
and at most 1024 (route-record §5.2), so a decode longer than 1024 frames could
not be recorded and a still scene, whose frames repeat, could not be stated.

A decode's `frames` is now one animated PNG (PNG's third edition: acTL, fcTL,
fdAT) of 8-bit RGB, read whole first by a still's chunk rules and the
animation's (each frame the whole picture, blended over nothing; the default
image the first frame; the sequence numbers in order; acTL counting the frames
it holds), of the receipt's size and count, and then frame by frame as a
still's image data, each frame's samples hashing to the receipt's frame. The
served hop states that one object and nothing else.

png_still gains encode_animation, every byte a function of the frames and the
delay, and animation, which reads the structure and inflates a frame only when
asked; the still reader and writer share their steps with it, their output
unchanged. The corpus replaces the per-frame controls with the animation's:
89 to 108 vectors, every other vector and source unchanged.
receipt_ledger_verify.py reads the animation with a reader of its own.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!559
No description provided.