wai-pack: staged packages — refinement layers, stills, a piece's ladder, live windows and simulated delivery (W4-4) #199
Merged
dcharlot
merged 27 commits from 2026-10-11 16:58:55 -04:00
wai/w4-4-staged-packages into main 2026-10-11
Merge wai/d1-record-true (the wasip2 link fix, with #215, #216, #217 and main) into wai/w4-4-staged-packages
All checks were successful
standards workspaces build + test / openpay (pull_request) Successful in 7m30s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 1m35s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 23m14s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m8s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 4m17s
wai-vector vector graphics / linux-aarch64 (pull_request) Successful in 1m51s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m6s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 7m38s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 9m45s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 50s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 20m3s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 43s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 4m27s
wai-vector vector graphics / macos-arm64 (pull_request) Successful in 1m48s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 56m44s
wai-pack / wai-pack · macos (pull_request) Successful in 3m34s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 55m49s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 8m46s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 11m58s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 5m39s
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Successful in 4s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m18s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m8s
wai-pack / wai-pack · linux (pull_request) Successful in 1m16s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 3m55s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 16s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m19s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m30s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 56m7s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m10s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge wai/d1-record-true (the record leg runs the record's own demo scripts) into wai/w4-4-staged-packages
Some checks failed
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 57s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 2m50s
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Successful in 5s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 1m19s
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Successful in 1m27s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m38s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 4s
WAI section references / cited sections exist (pull_request) Successful in 12s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 4m33s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 4s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 17m55s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 3m21s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 3m0s
wai-pack / wai-pack · macos (pull_request) Successful in 2m24s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 37m13s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 37m24s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 4m34s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 5m23s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 4m50s
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Successful in 3s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m17s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m9s
wai-pack / wai-pack · linux (pull_request) Successful in 1m14s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 4m9s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 16s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m13s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m31s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m14s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10
Merge wai/d1-record-true (with #205, #197 and main) into wai/w4-4-staged-packages
Some checks failed
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 4m30s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 4s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 17m2s
wai-ops integer operators / linux-aarch64 (pull_request) Successful in 24s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 3m5s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 5m15s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m56s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 31s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 12m35s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 31s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m10s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 3m26s
wai-ops integer operators / macos-arm64 (pull_request) Successful in 26s
wai-pack / wai-pack · macos (pull_request) Successful in 2m28s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Successful in 36m19s
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Successful in 36m22s
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Successful in 4m34s
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Successful in 5m17s
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Successful in 4m39s
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Successful in 4s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 2m26s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m13s
wai-pack / wai-pack · linux (pull_request) Successful in 1m15s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 3m56s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 21s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m19s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Failing after 1m58s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m15s
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Successful in 37m20s
Brings in #201, #205 and #197 and, through them, main as of #200 and #206. - .github/workflows/wai-conformance.yml: both sides added a step after sim_verify.py. Kept both: this branch's sim_diff.py differential, then main's quantum referee.py. wai-pack.yml merged without conflict: this branch's test-count floors (--lib 34, --test=staged 10) and differential steps, and main's cargo deny step for the wai binary's TLS client. - wai/CHANGELOG.md: both sides added entries at the top of v0.4.0. Kept every entry, newest first: this branch's "Packaging: refinement layers, stills, ...", then #201's, #205's and #197's, then main's unchanged. - wai/http-conformance/cases.json: regenerated with wai_http_vectors gen; the generator's output equals the merged text (1051 cases, with union_O10_repeated_layer_after_first and _after_second), and both wai_http_vectors verify and http_verify.py give every outcome. - falsify/union-no-layer.patch, regenerated on this branch, applies to the merged codecs.rs unchanged and names the two repeated-layer cases among its must-fail cases; it is patches 0/3 of the sharded runner. This branch adds no http_verify.py mutation, so mutations.txt is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
http falsification: union-no-layer against this branch's described()
All checks were successful
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m7s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 1m4s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m17s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 4s
WAI section references / cited sections exist (pull_request) Successful in 10s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 4m34s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 2m58s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
WAI HTTP delivery / HTTP corpus · falsification and differential (pull_request) Successful in 1h31m2s
wai-pack / wai-pack · linux (pull_request) Successful in 1m17s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 23s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m10s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 3m55s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 36m24s
standards workspaces build + test / aac-rs (pull_request) Successful in 8m34s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 5m25s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 3m16s
standards workspaces build + test / map-rs (pull_request) Successful in 4m35s
standards workspaces build + test / mesh-rs (pull_request) Successful in 4m26s
standards workspaces build + test / openpay (pull_request) Successful in 33m15s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 10m24s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 2m2s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 4m32s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 3m50s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m48s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m21s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 10m9s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 29s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 3m13s
wai-pack / wai-pack · macos (pull_request) Successful in 2m27s
The union-no-layer patch was written against the described() that this branch
rewrote in round 2 (a repeated object described once, a layer joining every
occurrence of its base), so CI could not apply it ("patch failed: codecs.rs:326").
It is regenerated from the branch's codecs.rs, still a plain patch file: the
layer joins no alt. Its must-fail list adds the two cases that pin the
repeated-object rule: union_O10_repeated_layer_after_first and
union_O10_repeated_layer_after_second. With the patch applied, verify fails all
three and two multivariant playlists.
The receipt-surrogates mutation is left to #200's sharded runner, which owns it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09
wai-pack: the inflater's bit reader aligns, by name (clippy's conversion rule)
Some checks failed
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m19s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m9s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 4m17s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 17s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 7m37s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 9s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 25s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 49s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 1m51s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 14m49s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m33s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 1m8s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m14s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 4s
WAI section references / cited sections exist (pull_request) Successful in 11s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 5m13s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 3m7s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
WAI HTTP delivery / HTTP corpus · falsification and differential (pull_request) Failing after 1h32m26s
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (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
Co-Authored-By: Claude Opus 5.5 <[email protected]>
changelog: W4-4 round 3 — zlib's code-set rules, the longest piece, manifests in both verifiers, live bookkeeping
Co-Authored-By: Claude Opus 5.5 <[email protected]>
ci: wai-pack's test-count floors at its counts (lib 34, staged 10)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-pack live keeps no record per file: listing lines on disk, open objects only
LiveOut held every object's path, hex SHA-256 and first piece for the whole session. It now holds: - no listing record per file. Each file's listing line is appended to a hidden .LISTING.lines beside the package as the file is written. At the end the lines are read back, sorted into LISTING, and the lines file is removed; that is the one moment it holds a line per file. - no set of written objects. An object already written is known by its file on disk. - for the abandon path, only the objects the unsealed pieces published, as a piece number and a 32-byte content hash. Those of a window are dropped when the window is sealed. packaging §9.2 and the CLI help now say exactly what remains: - what no window has sealed yet: those pieces' entry fields and their objects' hashes, which with --window 0 means every piece's until the end; - the frames of the piece being cut; - eight bytes per piece for the plan. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-pack: both verifiers compare manifests with §5.2/§5.4 (object-manifest); an unreadable still is prefix-digest
The Rust verifier never compared a base's manifest with §5.2, while pack_verify.py did, under a refusal that named no §11.3 reason. A still whose manifest had one extra target member was ok in Rust and refused in Python. Python's refusal of a base it cannot decode named no reason either. §11.3 now states one order, and both verifiers follow it. They take every base and refinement in entry order: - a base decodes by its capability, or it is prefix-digest; - its manifest is §5.2's for its piece's frames and frame size (object-manifest, a new §11.3 reason); - a refinement's manifest is §5.4's (object-manifest); - each layer applies to every frame of the stage below, or it is prefix-digest; - a base that does not decode, or a layer that does not apply, ends the pass; - then the decode-equivalent prefixes are compared with their digests. Rust's prefix_digests was restructured into this pass. The new staged mutation cases are: - still-manifest-target (object-manifest); - refinement-manifest-target (object-manifest); - still-incomplete-dist: the still re-coded with a lone two-bit distance code (prefix-digest). The reviewer's still-png-variant and still-manifest-variant packages now get those reasons from both verifiers. Co-Authored-By: Claude Opus 5.5 <[email protected]>
packaging §4.4: a piece is at most ten minutes and 2^24 units; floors counted before decoding
The new max_ms check bounded nothing, because a policy could set max_ms up to
2^53 − 1. A still's piece could then state 2^32 − 1 frames. Rust hashed once
per stated frame (about 29 minutes), and Python built a list of n references
(about 34 GB).
- **§3.4 item 5 and §4.4.** max_ms is at most 600000, and at most 2^24 units on
every component's timebase. Both are policy-piece-bounds, in both readers.
§4.4 gives the reason: a verifier takes a piece whole, so the longest piece
bounds its work. Ten minutes is far past any piece a delivery cuts, and 2^24
units bounds the work on any timebase, which may have up to 2^32 − 1 units a
second.
- **§11.3, before any frame is decoded.** Each piece's floor object, where its
framing reads, must hold one unit per frame of its piece
(floor-object-mismatch). Both verifiers make this check first.
- **Held stills.** Python holds a still's frame and its count (Held) and hashes
the digest a block at a time. Rust's held_digest also feeds a block at a time.
- **Corpus.**
- refusals: max_ms 600001; and the default max_ms on a timebase of 2^32 − 1
units a second.
- policy/max-piece.toml: accepted at both bounds.
- staged-mutations max-ms-past-cap (policy-piece-bounds).
- staged-mutations still-at-cap: the still given the longest piece the policy
allows, its manifest naming the frames, refused by the floor count in both
verifiers.
- **policy_diff.** Its random policies now reach both bounds.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-pack: a still's reader inflates as zlib does; png_diff runs both readers
The reader used miniz_oxide, which accepts a dynamic block whose lone distance code is longer than one bit. zlib's inflate, and so pack_verify.py, refuses that block. A golden resealed with such a still verified in wai-pack and was refused by pack_verify. Both readers now refuse incomplete code sets exactly as zlib does: the only incomplete literal/length or distance code allowed is one whose longest code is one bit. The reader now uses its own inflater (png::inflate_zlib), written from RFC 1950/1951 to zlib's inflate rules: - the header's check bits, method, window and preset-dictionary flag; - the stored-block complement; - the symbol counts; - a complete code-length code; - repeats with a length before them and within the code lengths; - a code for the end of the block; - over-subscribed and incomplete codes; - a code with no symbol, or a distance past the bytes written, refused where it is read; - the Adler-32, with nothing after it. miniz_oxide is kept only as a dev-dependency: the writer's round-trip test reads its stills back with an inflater independent of the reader's. packaging §5.7 now states these rules instead of "any PNG reader", and says that a still the verifier does not read is prefix-digest. stills/ gains the same dynamic block twice: a lone one-bit distance code (read) and a lone two-bit one (refused, still-incomplete-dist). png_diff.py drives wai-pack's reader (a new stage-json op, read-png) against pack_verify.py's. The inputs are: - zlib's own streams at every level, strategy and window; - the packager's own stills; - dynamic blocks built on each code-set rule (22 kinds, each checked against the verdict the rules give it); - mutations of all of these. wai-pack.yml runs it in debug and release. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge remote-tracking branch 'origin/main' into wai/w4-4-staged-packages
Some checks failed
WAI HTTP delivery / HTTP corpus · falsification and differential (pull_request) Failing after 1h19m24s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 1m4s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 1m4s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m10s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 6s
WAI section references / cited sections exist (pull_request) Successful in 11s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 4m19s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 2m40s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
standards workspaces build + test / aac-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (pull_request) Has been cancelled
standards workspaces build + test / joulecontract-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / map-rs (pull_request) Has been cancelled
standards workspaces build + test / mesh-rs (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (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
standards workspaces build + test / jouleclaw-rs (pull_request) Has been cancelled
2026-10-08
changelog: W4-4 round 2 — live writes as it goes, PNG rules, repeated objects over HTTP, one stall bound
Co-Authored-By: Claude Opus 5.5 <[email protected]>
staged-measure: the delivery simulator differentially, in CI
sim_verify.py reproduced the committed simulator cases, but nothing ran the two simulators side by side on inputs outside the corpus. Those inputs include a refinement with its own delivery timeout, which the corpus has few of. sim_diff.py generates seeded random models and plans. A model has groups of a base and up to three layers, each layer one object or one per unit; a refinement either has its own timeout (zero, small, large or null) or takes the plan's. A plan varies: - live or on demand; - fifo or strict priority; - subgroup or datagram; - base and refinement timeouts; - a layer cap; - one or two workers; - the decode order; - what happens to late refinements. Each case runs through `wai_stage_measure sim` and through sim_verify.py. The two must agree on the refusal, or on the whole result, the stall bound and the longest stall. Where the bound applies, every stall must be within it. It started as a review probe; the hard-coded paths are removed. wai-conformance now runs it with two fixed seeds next to sim_verify.py. Co-Authored-By: Claude Opus 5.5 <[email protected]>
stage_diff: wide stills, so every deflate distance code is exercised
stage_diff's stills were at most 48 columns wide, so the still writer's matches never reached past distance code 22. Every sixth still is now a picture 1024 to 10923 columns wide whose rows repeat, some with a few bytes changed. The match to the row above, one filtered row back, then uses distance codes 23 to 29. At 10923 columns that row is past the 32768-byte window, so the writer must fall back to nearer matches or literals. A run with nine or more wide stills fails if any of codes 23 to 29 goes unused. Co-Authored-By: Claude Opus 5.5 <[email protected]>
pack-conformance: a live-window corpus, checked by both implementations
The corpus had no live windows, so pack_verify.py never read a live-window receipt, a non-zero `prev_index_digest` or a `first_entry` past zero. live/ holds the staged golden's source packed live with its key, in windows of two pieces: each window's index and receipt, and expected.json with each window's place in the chain, index digest and receipt hash. pack_verify.py reads each window with its own index reader and §6.3 rules, and verifies the receipt (§9.1, strict Ed25519). It then checks the chain: - the parent receipt (`live-window`); - `prev_index_digest`; - `first_piece` and `first_entry`; - the timeline; - the signer is the golden's key. It also checks that each window's pieces, entries (but flags and window-relative `refines`), class plan and plan digest are the golden's. wai-pack's conformance check writes the windows again, compares their bytes, and verifies the same chain. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-pack live writes as it goes: each object when published, each window when sealed
`wai-pack live` used to gather every object and window in memory and write them all after the end of the stream. It now writes: - each object when it is published; - each window's index, then its receipt, when the window is sealed; - the plan file and LISTING at the end. Each file is written to a hidden temporary file beside it, then renamed into place. If the source fails mid-stream (a short frame or a frame of another size): - every sealed window and the objects it lists are kept; - the objects only unsealed pieces published are removed; - no plan file and no LISTING are written; - it exits 1, naming what it kept. Once an object is written, its bytes are no longer held. A coded piece's stages now carry their entry lengths (`pack::Lens`), so window_index builds an entry without the envelope. The live packer moves each envelope into its publication. The packer hands out sealed windows with `take_sealed()` and keeps none. With --window 0, the packer still holds every piece's entry fields until the end of the stream. The module doc, the CLI help and packaging §9.2 now say exactly what is held. wai::pin::listing_from_sha256 builds the listing from per-file digests (the same lines as listing_from), so LISTING needs no file's bytes. Tests: - A CLI test feeds the stream through a pipe and checks that windows 0 and 1 and their objects are on disk while the stream is still open. - A second CLI test checks that a stream cut inside a frame keeps window 0 and its objects and nothing else. - A unit test checks that no open piece holds an envelope. - A wai-rs test checks that the listing from digests equals the listing from bytes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-pack: one PNG reader's rules in both verifiers, with a corpus of stills
§5.7 says a still is any PNG of 8-bit RGB without interlace, and the two readers disagreed on what that admits. Rust refused a suggested palette, which an RGB picture may carry; Python accepted an interlace, bytes after IEND and a short row. Both now read by PNG's chunk rules: IHDR first; an optional PLTE before the image data; consecutive IDATs; ancillary chunks read past; unknown critical chunks refused; IEND last and empty; a whole zlib stream with a window of at most 32 KiB, its Adler-32 checked and nothing after it; exact rows. Rust now inflates with miniz_oxide's core decompressor, so it sees how much input the stream used. It refuses bytes after the stream, which it used to read past whenever their last four bytes were the checksum. It also refuses the window PNG forbids, which a non-wrapping buffer would otherwise let through. pack-conformance/stills/ holds the files both readers give one verdict on. wai-pack's conformance check and pack_verify.py check each file against its verdict and, when it is read, the SHA-256 of its samples. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-pack: a still held for its piece is hashed, never repeated; no piece past max_ms
The verifier built a still's prefix as the frame repeated for the piece's duration (`vec![rgb; n]`), so a package stating a long duration made it allocate in proportion to that number. - verify.rs: a still's prefix digest is its frame's digest fed n times (`pack::held_digest`); no frame is repeated in memory. - §4.4 bounds every piece by max_ms; the verifier holds an index to it first of every per-piece rule, so nothing is decoded for a piece past it (index-policy-mismatch). pack_verify.py does the same, and hashes a held still once. - staged-mutations: the last piece, and the still as the last piece of a cut package, each lasting 2^32 − 1 frames with their rules, moments and class plan what that span gives, are refused, not aborted. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai: a repeated object is one object of a sequence; pack_verify reads the playlists with http_verify
http_verify.py joined a layer only to the first occurrence of its base, so the staged golden's tv playlist, which lists the bumper's base twice, gave a floor without +video.int_refine while wai-rs, which reads each object once, gave it with: the two implementations of http-delivery §4.2 disagreed. - http-delivery §4.2: an object a sequence lists more than once is one object of it, described once with every layer it has, and a layer joins every object of the sequence that is its base. - wai-rs (`codecs::described`) and http_verify.py both: each object once, each layer joined to every object that is its base. - http-conformance: two vectors, a base listed twice with its layer beside the first and beside the second occurrence; the union and floor keep the layer. - pack_verify.py runs http_verify.py's adjacency, union and floor over every golden's class playlists and MPDs, so CI sees a disagreement; wai-pack.yml's push filter lists http_verify.py. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai: staged_resources counts each thread's allocations, not the process's
The counters were process-wide, so libtest's main thread, which allocates a 594-byte message when a test passes 60 seconds, landed in the parse window on a loaded host: 1,310,720 + 594 = 1,311,314 bytes against 1,310,721 declared. - The allocator keeps per-thread counts (`thread_local!` `const` `Cell`s, no destructor, reached with `try_with`) of bytes allocated, allocations, bytes live (signed: a thread may free what another allocated) and their peak, and every window reads the measuring thread's. - A new check: a megabyte another thread allocates inside a window does not count, and one this thread allocates does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai: one stall bound, of a model — wai-web prints the bound the native tool prints
wai-web's simulated() printed the plan-only bound while wai_stage_measure prints the model's, so a per-track case (refinements with timeouts of their own) gave 35000 against the corpus's 65000 and measure::tests failed. - wai-web: `stall_bound_for(model, &p)`. - stage_measure::sim: the plan-only bound is gone from the API; §10.4's bound is `stall_bound_for(model, plan)` alone, its documentation the full rule. The simulator's tests keep a plan-only helper over `bound_with`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ci, changelog: wai-pack's staged packages
- wai-pack.yml: the push filter lists the staged-delivery and staged-measurement verifiers pack_verify.py now imports; the test-count floor covers tests/staged.rs and the library's new tests; stage_diff.py runs against the debug and the release build; the media job reads both goldens' floors. - CHANGELOG: the staged packages, the MoQ stage set, live windows, simulated delivery and the simulator's per-object timeout. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-pack: staged packages — refinement layers, stills, a piece's ladder, live windows and simulated delivery (W4-4)
The packer writes refinement layers, chooses each piece's representation by its ladder, packs live, and simulates delivery over MoQ; the corpus gains a staged golden that the independent verifier re-derives byte for byte. - Refinements (packaging §5.4): for each refinement rung of a piece's ladder, a wai.video.int_refine object over the int_motion base, written by wai-rs's refinement encoder (staged::wir1::encode) with the manifest `wai stage refine` writes; every layer applied to the decoded base by the reference sink before it is kept. The index states each prefix's tier, digest, SSE and deadline. - A piece's ladder and stills (§5.7, plan::piece_ladder): a rule's then.ladder, or the component's first base rung, its refinement chain and its floors. §3.4 item 10 now requires a rule's ladder to name exactly one base, every refinement over a rung it names and every floor. A wai.image.png base is a still, the piece's first frame held for the piece, written as a PNG whose every byte is stated (png.rs; the verifier's reader inflates with miniz_oxide, the one new dependency). - One coder (pack::Coder) for the on-demand and the live packer; the verifier holds each piece to its ladder and its plan's deadline, and decodes every prefix (a still held, each layer through the sink). - Catalogs: the MoQ catalog is a stage set of moq-streaming-format §4.1, written by staged::moq (wai_staged, a receipts track and an alias per media track, depends on a track of every layer below); `priority` (MOQT's, §8.5) and `wai_layer` leave it, and the registry drops `wai_layer`. HTTP views carry the component's default base capability only: a still's piece plays from the floor there (http-delivery §4.2), and its stage view and MoQ tracks list it. - Live (§9.2, live.rs, `wai-pack live`): frames pushed one at a time, pieces coded as the segmenter closes them, windows sealed by version-2 receipts chained live-window; its plan, bases and refinements are the on-demand package's byte for byte (`wai-pack listing --primary`). - Delivery (§8.9, delivery.rs, `wai-pack sim`): a thin consumer of stage_measure::sim — per-track timeouts, §8.5's priorities, the subscriber's cap, group receipts on each track's chain; delivered objects accepted by Merkle proof, dropped ones held by inclusion only. - Corpus: the golden video-staged-01 (fixture, policy, supplied floor and supplied_floor.py, which states how it was written), staged-mutations/, delivery/; video-base-01 keeps its objects, index and receipt (its MoQ catalog and LISTING change). - pack_verify.py re-derives every layer and still from the source (its own rANS coder and deflate), decodes every prefix (staged_verify.py's WIR1 and PNG readers), checks the MoQ catalog with staged_verify.py's §4.1 check, renders every catalog, and re-derives each delivery case through sim_verify.py's simulator. stage_diff.py runs layers, stills, piece plans and deliveries differentially. - Tests 5, 7, 12 and 13 over the staged golden (tests/staged.rs). Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai: a refinement's own delivery timeout in the staged delivery simulator
A MoQ track sets one DELIVERY_TIMEOUT for every object on it, and a packager gives each refinement layer and deadline its own track (packaging §8.6), so one refinement timeout per plan cannot model a package's delivery. - stage_measure::sim: a model object may carry `timeout_us`, a refinement's own timeout in place of the plan's for its layer; a base carrying one is not a well-formed model. `timeout_us` is written only where an object has one, so every existing model reads and writes back unchanged. - §10.4's bound under fifo takes T as the longest timeout a refinement takes, its own or the plan's (`stall_bound_for`); `stall_bound` keeps its meaning for a model with none, and `check_stall` uses the model's. - staged-measurement §10.4 and Appendix B state both; the corpus adds the `per-track` model and three cases (a fifo plan with no plan timeout is bounded by the objects' own); sim_verify.py follows, independently. - Tests: a hand-computed case, and the bound over targeted draws whose refinements carry timeouts of their own. Co-Authored-By: Claude Opus 5.5 <[email protected]>