wai-mark:tent64s: the mark found again after crops, rotations and captures of a screen, exact and open #425

Closed
dcharlot wants to merge 0 commits from wai/mark-sync into main
Owner

What this is

SYN-3 of the synthesis-provenance slice: the second marking layer survives crops, small rotations and a simulated capture of a screen, and stays exact and open. Stacked on #407 (wai/synthesis-mark, SYN-2); the diff against main includes #407 until it merges, after which origin/main is merged in here (one ordinary merge).

  • wai-mark:tent64s (synthesis §7.9), a second registered scheme term: tent64's tent pattern, BCH code, amplitudes and margin, on a tiled layout. The 64 × 64 grid is cut into 2 × 2 tiles of 32 × 32 cells; every tile holds the same layout, four positions a bit, so a bit keeps 16 cells and the mark repeats with half the frame's width and height. The embedding is §7.5.4's under that layout: integer, recomputed by a verifier, no hidden channel, and nothing spent on synchronisation.
  • A two-stage, key-free detector, integer throughout, so Python and Rust agree on every vector by construction:
    • stage 1 reads the grid in place in the 8 quarter turns and mirrors (as tent64);
    • stage 2, where stage 1 reads nothing: the exact autocorrelation of a sign plane matched to the cell pattern (an NTT mod 998244353 in Rust; one big-integer product per frame in Python); 8 lattice candidates, each a pair of perpendicular vectors scored over 4 lattice points, chosen with suppression, refined to 1/64 sample by a parabola; each folded onto one tile by tile parity, the cells' phase taken where the tiles agree most (Σ S² − Σ S_c²); the orientation and the tile's offset where the four cells of every bit agree most; at most 4 words decoded.
  • False-positive bound over all 12 decodes: 2^−60.80, checked against the words both stages read from unmarked pictures (384 words, mean ones 124.14, sd 7.78; pair distances mean 123.90, sd 7.93, least 74 — the least is lower than the model makes likely over 71,424 pairs, and §7.9.5 says so and why). No unmarked picture of any set under any attack gives a payload.
  • Battery additions (§7.9.6): crop-25%; crop-{left,right,top,bottom}-{2,5,10,25}%; rotate-5; screen-a (×5/4, 1°, a display curve, noise) and screen-b (×4/5, −2°, curve, noise). Corpus derivations: a side crop of any percent, and periodic (a forged lattice).
  • Verification (§7.6 to §7.8): recompute and rerun dispatch over either registered scheme; the C2PA statement, signpost and resolver cover both.
  • scripts/check-public-names.sh (SYN-2's finding): it cd'd to the repository's root before reading its file arguments, so paths given from a subdirectory (a builder in wai/ or wai/wai-rs) did not exist and grep exited 2 for the whole list; a list from git diff --name-only after main moved fails the same way. Arguments are now resolved against the caller's directory, and every argument that is not a readable regular file is named before the scan (still exit 2). The self-test gains five cases.

Decisions and why

  • New term, not a revision. The same unmarked frames and payload give other marked frames; a tent64 marking commits to tent64's marked frames by digest and §7.6 recomputes under the term's own definition. Revising tent64 would make every signed tent64 marking unverifiable. tent64's files regenerate byte for byte, unchanged.
  • Self-synchronising tiling (approach b) with the mark's own period as the template (approach a's "periodic tiling of the mark itself"), no added pilot. Measured by prototype first: a separate known pilot pattern (a sync template at a 4-cell period) restored lattice estimates on hard photographs but cost about 1.6 dB of PSNR at amplitude 2 and still missed some; the tiled mark with a joint 4-point lattice score and fold-based verification reached the same or better with no cost. Four cells per bit per tile give the detector a self-reference: the four cells of a bit must agree at the true alignment, which ranks orientation × offset hypotheses with no key and no known signal.
  • Detection exact: floats would have been allowed, but an integer detector makes agreement a property rather than a test. The search grid and every tie-break are in §7.9.4.
  • Frame-relative grid kept, so pure rescales and aspect changes are still read by stage 1 exactly as tent64 reads them.
  • Corpus small: the scheme's files sit beside tent64's in live-conformance/synthesis-mark/ and share its frames. Only 2 new frame files (the still and the clip marked by the tiled scheme, ~290 KB); every crop, rotation, capture and forged lattice is derived at verify time from stored frames by the attack a vector names. Each detect vector also states stage 2's trace (every candidate's vectors, refined lattice, bins and phase, and the hypotheses decoded), so the whole pipeline is compared, not only the payload.

Measurement (§7.9.7)

Generated sets (spectral 16 × 512², leaves 16 × 512², clips 4 × 8 × 256²) and the informative photographs (24 × 768 × 512, fetched again from the same source under the terms SYN-2 recorded; all 24 SHA-256 match the README; not committed).

  • Both generated sets survive every attack of the table, every crop, rotation and capture, and resampling to 1/3 (which tent64 survives on spectral alone).
  • Claimed (every picture of every column, the photographs' among them, and no unmarked reading): every attack tent64 claims, plus scale-1/4, crop-1%, crop-2%, crop-5%, crop-left-2%, crop-left-5%, crop-left-10%, crop-bottom-2%, crop-bottom-5%, rotate-0.5, rotate-1, rotate-5, screen-a; all clip attacks.
  • Not claimed: scale-1/3, crop-10%, crop-25%, rotate-2, the right and top crops, crop-bottom-10% and -25%, crop-left-25%, screen-b. Every one of these is a single photograph: one dense natural texture (bc34a3ce… in the README) misses 14 crops and rotations, another (10349e96…) misses screen-b; on the rest all 24 pass. The cause (from the prototype's oracle runs): with the true lattice those pictures decode; the picture's own texture outweighs the mark in the autocorrelation and the lattice is not among the 8 candidates. In development runs, raising the candidates to 32 did not fix it (more wrong hypotheses compete for the 4 decodes), nor did a narrower search span.
  • Imperceptibility: no cost. PSNR least…mean / SSIM least…mean, tent64s vs tent64: spectral 44.71…44.99 / 0.9682…0.9730 vs 44.86…45.02 / 0.9688…0.9732; leaves 43.31…43.67 / 0.9677…0.9697 vs 43.05…43.69 / 0.9661…0.9696; clips 41.84…42.05 / 0.9439…0.9482 vs 41.90…42.08 / 0.9439…0.9495; photographs 41.78…43.63 / 0.9772…0.9844 vs 41.39…43.58 / 0.9761…0.9842. Floors unchanged (36.66, 38.73, 35.76 dB). No trade-off curve is needed: resynchronisation spends nothing.

Checks

check command (wai/wai-rs unless noted; on the build host via rb) result
scheme unit tests cargo test --release --locked --no-default-features --features synthesis_mark --lib -- synthesis::mark synthesis_mark:: 17 passed (the tiled layout, the exact autocorrelation against brute force, rounding and the vertex, a crop and a rotation found again, and SYN-2's)
synthesis lib without synthesis_mark cargo test --locked --no-default-features --features synthesis --lib synthesis:: 20 passed
synthesis corpus cargo test --locked --no-default-features --features synthesis --test synthesis 4 passed
scheme corpus and text cargo test --release --locked --no-default-features --features synthesis_mark --test synthesis_mark 7 passed in 220 s: every file regenerates byte for byte (both measurements), no other file; every vector, trace and case; §7.9.1 definition and digest, §7.9.2 shuffle, §7.9.5 bound and figures, §7.9.7 table (generated columns) and claims (every column)
corpus gen/verify wai_synthesis_mark_vectors gen then verify ../live-conformance/synthesis-mark PASS, PASS; tent64's files unchanged by the refactor
registry cargo test --lib codecs::registry, --test cli_registry, wai registry export then --check 14 + 6 passed; export up to date
clippy cargo clippy --locked --no-default-features --features synthesis_mark --all-targets and --features synthesis no note in any touched file
lockfiles cargo metadata --locked --offline --format-version 1 ok; no dependency added, no Cargo.lock change
second implementation python3 -I live-conformance/synthesis_mark_verify.py live-conformance/synthesis-mark (wai/) PASS in 5.6 min: both schemes; 106 battery samples, 9 detections with traces, 9 cases of the tiled scheme agree; 12 tiled mutations and 3 weakened verifiers caught
synthesis corpus, second implementation python3 -I live-conformance/synthesis_verify.py live-conformance/synthesis PASS, 41 vectors
repo checks (local) check-tests-in-ci.py, check-workflow-concurrency.sh, check-spec-refs.py, check-wai-section-refs.py, check-no-vanity-metrics.sh, test-public-text-checks.sh, check-comparative-prose.sh, check-orphan-sources.py all clean
public names check-public-names.sh with the private list, on every touched file; the commit messages and this body scanned per pattern clean; 0 hits

Falsifications

Each on a committed tree, the rule broken, the guarding check run, the file restored.

rule broken check result
stage 2's agreement counts one pair of a bit's cells, not six (Rust) --test synthesis_mark every_vector_and_case FAILED: the cropped and the turned clip read otherwise
§7.9.5's least distance changed 74 → 75 --test synthesis_mark the_extension_claims_only_what_the_tiled FAILED: §7.9.5's figures
screen-b added to §7.9.7's claims the same Rust test, and synthesis_mark_verify.py Rust test passed at first (it read only the generated sets) → fixed to read every column, then FAILED; Python FAIL: "claims screen-b, which a column of its table does not show survived"
the Python agreement's column roll off by one synthesis_mark_verify.py exit 1: detects and battery samples read null
the Python phase chosen by the tile's energy instead of the tiles' agreement synthesis_mark_verify.py exit 0 at first (payloads alone did not tell the rules apart) → each detect vector now states stage 2's trace; then exit 1: "stage 2 runs otherwise"
check-public-names.sh restored to its old form bash scripts/test-public-text-checks.sh 5 cases gave the wrong status (relative paths, many files, a missing file and a directory among many)

Not done

  • The one dense-texture photograph (and screen-b on a second): the next step is a known sync template with a matched detector, which the prototype showed costs imperceptibility; not done here, measured only as a prototype.
  • tent64's own Rust claims test checks §7.5.8's claims against the generated sets only (the second implementation checks the photographs' column); the tiled scheme's test now checks every column. tent64's was left as SYN-2 wrote it.
  • Nothing registered with IANA or C2PA, no EU body contacted (owner decisions).
  • Not merged; #407 must land first, then origin/main is merged in.

🤖 Generated with Claude Code


Closed: landed on main through merge train C (#461, e0ac15f5); this PR's head is an ancestor of main.

## What this is SYN-3 of the synthesis-provenance slice: the second marking layer survives crops, small rotations and a simulated capture of a screen, and stays exact and open. **Stacked on #407** (`wai/synthesis-mark`, SYN-2); the diff against `main` includes #407 until it merges, after which `origin/main` is merged in here (one ordinary merge). - **`wai-mark:tent64s`** ([synthesis](wai/extensions/synthesis.md) §7.9), a second registered scheme term: `tent64`'s tent pattern, BCH code, amplitudes and margin, on a **tiled layout**. The 64 × 64 grid is cut into 2 × 2 tiles of 32 × 32 cells; every tile holds the same layout, four positions a bit, so a bit keeps 16 cells and the mark repeats with half the frame's width and height. The embedding is §7.5.4's under that layout: integer, recomputed by a verifier, no hidden channel, and **nothing spent on synchronisation**. - **A two-stage, key-free detector, integer throughout**, so Python and Rust agree on every vector by construction: - stage 1 reads the grid in place in the 8 quarter turns and mirrors (as `tent64`); - stage 2, where stage 1 reads nothing: the exact autocorrelation of a sign plane matched to the cell pattern (an NTT mod 998244353 in Rust; one big-integer product per frame in Python); 8 lattice candidates, each a pair of perpendicular vectors scored over 4 lattice points, chosen with suppression, refined to 1/64 sample by a parabola; each folded onto one tile by tile parity, the cells' phase taken where the tiles agree most (Σ S² − Σ S_c²); the orientation and the tile's offset where the four cells of every bit agree most; at most 4 words decoded. - **False-positive bound** over all 12 decodes: 2^−60.80, checked against the words both stages read from unmarked pictures (384 words, mean ones 124.14, sd 7.78; pair distances mean 123.90, sd 7.93, least 74 — the least is lower than the model makes likely over 71,424 pairs, and §7.9.5 says so and why). No unmarked picture of any set under any attack gives a payload. - **Battery additions** (§7.9.6): `crop-25%`; `crop-{left,right,top,bottom}-{2,5,10,25}%`; `rotate-5`; `screen-a` (×5/4, 1°, a display curve, noise) and `screen-b` (×4/5, −2°, curve, noise). Corpus derivations: a side crop of any percent, and `periodic` (a forged lattice). - **Verification** (§7.6 to §7.8): recompute and rerun dispatch over either registered scheme; the C2PA statement, signpost and resolver cover both. - **`scripts/check-public-names.sh`** (SYN-2's finding): it `cd`'d to the repository's root before reading its file arguments, so paths given from a subdirectory (a builder in `wai/` or `wai/wai-rs`) did not exist and grep exited 2 for the whole list; a list from `git diff --name-only` after main moved fails the same way. Arguments are now resolved against the caller's directory, and every argument that is not a readable regular file is named before the scan (still exit 2). The self-test gains five cases. ## Decisions and why - **New term, not a revision.** The same unmarked frames and payload give other marked frames; a `tent64` marking commits to `tent64`'s marked frames by digest and §7.6 recomputes under the term's own definition. Revising `tent64` would make every signed `tent64` marking unverifiable. `tent64`'s files regenerate byte for byte, unchanged. - **Self-synchronising tiling (approach b) with the mark's own period as the template (approach a's "periodic tiling of the mark itself")**, no added pilot. Measured by prototype first: a separate known pilot pattern (a sync template at a 4-cell period) restored lattice estimates on hard photographs but cost about 1.6 dB of PSNR at amplitude 2 and still missed some; the tiled mark with a joint 4-point lattice score and fold-based verification reached the same or better with **no** cost. Four cells per bit per tile give the detector a self-reference: the four cells of a bit must agree at the true alignment, which ranks orientation × offset hypotheses with no key and no known signal. - **Detection exact**: floats would have been allowed, but an integer detector makes agreement a property rather than a test. The search grid and every tie-break are in §7.9.4. - **Frame-relative grid kept**, so pure rescales and aspect changes are still read by stage 1 exactly as `tent64` reads them. - **Corpus small**: the scheme's files sit beside `tent64`'s in `live-conformance/synthesis-mark/` and share its frames. Only 2 new frame files (the still and the clip marked by the tiled scheme, ~290 KB); every crop, rotation, capture and forged lattice is derived at verify time from stored frames by the attack a vector names. Each detect vector also states stage 2's trace (every candidate's vectors, refined lattice, bins and phase, and the hypotheses decoded), so the whole pipeline is compared, not only the payload. ## Measurement (§7.9.7) Generated sets (`spectral` 16 × 512², `leaves` 16 × 512², `clips` 4 × 8 × 256²) and the informative photographs (24 × 768 × 512, fetched again from the same source under the terms SYN-2 recorded; all 24 SHA-256 match the README; not committed). - **Both generated sets survive every attack of the table**, every crop, rotation and capture, and resampling to 1/3 (which `tent64` survives on `spectral` alone). - **Claimed** (every picture of every column, the photographs' among them, and no unmarked reading): every attack `tent64` claims, plus `scale-1/4`, `crop-1%`, `crop-2%`, `crop-5%`, `crop-left-2%`, `crop-left-5%`, `crop-left-10%`, `crop-bottom-2%`, `crop-bottom-5%`, `rotate-0.5`, `rotate-1`, `rotate-5`, `screen-a`; all clip attacks. - **Not claimed**: `scale-1/3`, `crop-10%`, `crop-25%`, `rotate-2`, the right and top crops, `crop-bottom-10%` and `-25%`, `crop-left-25%`, `screen-b`. Every one of these is a single photograph: one dense natural texture (`bc34a3ce…` in the README) misses 14 crops and rotations, another (`10349e96…`) misses `screen-b`; on the rest all 24 pass. The cause (from the prototype's oracle runs): with the true lattice those pictures decode; the picture's own texture outweighs the mark in the autocorrelation and the lattice is not among the 8 candidates. In development runs, raising the candidates to 32 did not fix it (more wrong hypotheses compete for the 4 decodes), nor did a narrower search span. - **Imperceptibility**: no cost. PSNR least…mean / SSIM least…mean, `tent64s` vs `tent64`: spectral 44.71…44.99 / 0.9682…0.9730 vs 44.86…45.02 / 0.9688…0.9732; leaves 43.31…43.67 / 0.9677…0.9697 vs 43.05…43.69 / 0.9661…0.9696; clips 41.84…42.05 / 0.9439…0.9482 vs 41.90…42.08 / 0.9439…0.9495; photographs 41.78…43.63 / 0.9772…0.9844 vs 41.39…43.58 / 0.9761…0.9842. Floors unchanged (36.66, 38.73, 35.76 dB). No trade-off curve is needed: resynchronisation spends nothing. ## Checks | check | command (wai/wai-rs unless noted; on the build host via rb) | result | |---|---|---| | scheme unit tests | `cargo test --release --locked --no-default-features --features synthesis_mark --lib -- synthesis::mark synthesis_mark::` | 17 passed (the tiled layout, the exact autocorrelation against brute force, rounding and the vertex, a crop and a rotation found again, and SYN-2's) | | synthesis lib without synthesis_mark | `cargo test --locked --no-default-features --features synthesis --lib synthesis::` | 20 passed | | synthesis corpus | `cargo test --locked --no-default-features --features synthesis --test synthesis` | 4 passed | | scheme corpus and text | `cargo test --release --locked --no-default-features --features synthesis_mark --test synthesis_mark` | 7 passed in 220 s: every file regenerates byte for byte (both measurements), no other file; every vector, trace and case; §7.9.1 definition and digest, §7.9.2 shuffle, §7.9.5 bound and figures, §7.9.7 table (generated columns) and claims (every column) | | corpus gen/verify | `wai_synthesis_mark_vectors gen` then `verify ../live-conformance/synthesis-mark` | PASS, PASS; `tent64`'s files unchanged by the refactor | | registry | `cargo test --lib codecs::registry`, `--test cli_registry`, `wai registry export` then `--check` | 14 + 6 passed; export up to date | | clippy | `cargo clippy --locked --no-default-features --features synthesis_mark --all-targets` and `--features synthesis` | no note in any touched file | | lockfiles | `cargo metadata --locked --offline --format-version 1` | ok; no dependency added, no Cargo.lock change | | second implementation | `python3 -I live-conformance/synthesis_mark_verify.py live-conformance/synthesis-mark` (wai/) | PASS in 5.6 min: both schemes; 106 battery samples, 9 detections with traces, 9 cases of the tiled scheme agree; 12 tiled mutations and 3 weakened verifiers caught | | synthesis corpus, second implementation | `python3 -I live-conformance/synthesis_verify.py live-conformance/synthesis` | PASS, 41 vectors | | repo checks (local) | `check-tests-in-ci.py`, `check-workflow-concurrency.sh`, `check-spec-refs.py`, `check-wai-section-refs.py`, `check-no-vanity-metrics.sh`, `test-public-text-checks.sh`, `check-comparative-prose.sh`, `check-orphan-sources.py` | all clean | | public names | `check-public-names.sh` with the private list, on every touched file; the commit messages and this body scanned per pattern | clean; 0 hits | ## Falsifications Each on a committed tree, the rule broken, the guarding check run, the file restored. | rule broken | check | result | |---|---|---| | stage 2's agreement counts one pair of a bit's cells, not six (Rust) | `--test synthesis_mark every_vector_and_case` | FAILED: the cropped and the turned clip read otherwise | | §7.9.5's least distance changed 74 → 75 | `--test synthesis_mark the_extension_claims_only_what_the_tiled` | FAILED: §7.9.5's figures | | `screen-b` added to §7.9.7's claims | the same Rust test, and `synthesis_mark_verify.py` | Rust test **passed** at first (it read only the generated sets) → fixed to read every column, then FAILED; Python FAIL: "claims screen-b, which a column of its table does not show survived" | | the Python agreement's column roll off by one | `synthesis_mark_verify.py` | exit 1: detects and battery samples read null | | the Python phase chosen by the tile's energy instead of the tiles' agreement | `synthesis_mark_verify.py` | **exit 0** at first (payloads alone did not tell the rules apart) → each detect vector now states stage 2's trace; then exit 1: "stage 2 runs otherwise" | | `check-public-names.sh` restored to its old form | `bash scripts/test-public-text-checks.sh` | 5 cases gave the wrong status (relative paths, many files, a missing file and a directory among many) | ## Not done - **The one dense-texture photograph** (and `screen-b` on a second): the next step is a known sync template with a matched detector, which the prototype showed costs imperceptibility; not done here, measured only as a prototype. - **`tent64`'s own Rust claims test** checks §7.5.8's claims against the generated sets only (the second implementation checks the photographs' column); the tiled scheme's test now checks every column. `tent64`'s was left as SYN-2 wrote it. - Nothing registered with IANA or C2PA, no EU body contacted (owner decisions). - Not merged; #407 must land first, then `origin/main` is merged in. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- **Closed:** landed on main through merge train C (#461, e0ac15f5); this PR's head is an ancestor of main.
A tent checkerboard in each cell of a 64 x 64 grid that follows the picture
through a rescale; a public stream shuffles the cells, signs them and masks the
code; the 8-byte payload is a BCH(255, 71) codeword shortened to 248 bits, each
bit carried by 16 cells; each bit is given the least amplitude up to 8 that
gives its statistic the sign the codeword asks with a margin of 3/2 of its
weight mass. The detector reads the signs in each of the 8 orientations and
decodes up to 29 errors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A marking states the frames it embedded into (their size and the digests of the
unmarked and the marked frames) and a detection the frames it read. Holding the
unmarked frames, a verifier recomputes the marking's derivation; holding the
decoded frames, it runs the detector again. New codes: scheme_mismatch,
mark_evidence_invalid, mark_input_mismatch, mark_recompute_mismatch,
detection_irreproducible, layer_not_proved; a policy member second_layer; each
marking states its C2PA signpost. The synthesis corpus regenerates with the new
members and gives the codes that need no frames.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The battery applies the crate's own integer codecs (wai.video.int_motion's
encoder, a staged base through wai-synthesis:upscale2), the pinned derivations
of §4, area resampling, crops, quarter turns and mirrors, small rotations,
noise from a fixed stream, brightness, contrast and a local blur, each an
integer function of the frames. The measurement sets are generated from fixed
seeds: wai.generate.spectral's generator with its committed model, and a
dead-leaves generator. The corpus holds the scheme's definition, the code's
words, embeddings and detections over stored frames, a battery sample, cases
whose markings are recomputed and detections run again, and the measurement.
The amplitude cap is 12: at 8 the most textured photographs left bits short.
A conversion's detection agrees with the claim it inherits the mark from.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
§7.4 registers wai-mark:tent64 by its definition and digest and keeps
wai-mark:conformance as the scheme with no algorithm. §7.5 is the scheme: frames
and luma, the grid and the tent pattern, the stream, the shuffle, the signs and
the mask, the shortened BCH code, the informed embedding, the detector in eight
orientations, what it guarantees (no other channel, a PSNR floor, a
false-positive bound derived and checked), the battery and the table of what it
survives, with the claims it makes. §7.6 proves a marking by recomputation and
reproduces a detection; §7.7 gives the signpost in the content and in the C2PA
statement, and a well-known resolver; §7.8 has a sink that generates mark as part
of the reconstruction it is held to. _wai_mark.py is the scheme and the battery
in Python from the text; synthesis_verify.py runs §7.6's checks with it;
synthesis_mark_verify.py verifies the scheme's corpus, mutates it and weakens
itself in turn.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The wire identifiers wai-mark:tent64 and wai-mark:conformance (schemes, §7.4) and
/.well-known/wai-mark/ (proposed, §7.7); the registry export regenerated. A CI
step runs the scheme's unit tests, tests/synthesis_mark.rs in release and
synthesis_mark_verify.py. The corpus README states its provenance and names the
photographs of §7.5.8's informative column by SHA-256.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge remote-tracking branch 'origin/main' into wai/synthesis-mark
All checks were successful
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m12s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m11s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 26s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 10m0s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 1m51s
wai-pack / wai-pack · linux (pull_request) Successful in 1m24s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 19m34s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 2m29s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m11s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 8m7s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 5m53s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 24s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 15s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 2m44s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 3m15s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 22m47s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m13s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 8m23s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 4m38s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 17s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 2m5s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 38m56s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 9m44s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 15m49s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 20s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 47s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m58s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 2m48s
wai-pack / wai-pack · macos (pull_request) Successful in 1m11s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m15s
5d33f01b4d
The script moved to the repository's root before reading its arguments, so paths
given from a subdirectory (a builder in wai/ or wai/wai-rs) did not exist and grep
exited 2 for the whole list; a list built from git diff after main moved, naming a
file absent from the work tree, failed the same way with nothing to say which. Each
relative argument is now resolved against the caller's directory, and every argument
that is not a readable regular file is named before the scan (still exit 2, fail
closed). The self-test gains cases for relative paths, many files, a missing file and
a directory among many.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The 64 x 64 grid is cut into 2 x 2 tiles of 32 x 32 cells, each tile holding the same
layout, four positions a bit, so a bit keeps 16 cells and the embedding is tent64's,
spending nothing on synchronisation. Stage 1 reads the grid in place in the 8
orientations, as tent64 does. Stage 2, where stage 1 reads nothing: the tile lattice from
the exact autocorrelation (a number-theoretic transform) of a sign plane matched to the
cell pattern, eight candidates scored over their four lattice points; each folded onto one
tile by the parity of its tiles, the cells' phase by how well the tiles agree; the
orientation and the tile's offset by how many pairs of a bit's four cells agree; at most
four words decoded. Integer throughout.

The verifier dispatches over the registered schemes (§7.6's recomputation and rerun).
The battery adds crops from each side, a crop of 25%, a rotation of 5 degrees and two
simulated captures of a screen; tent64's corpus files regenerate unchanged. The scheme's
corpus files sit beside tent64's and share its frames; frames a crop, a rotation or a
capture makes are derived at verify time, not stored.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
§7.9 specifies the tiled layout, the two stages of the detector step by step in integers,
the bound over all 12 decodes and its check, the battery's additions (crops from each
side, a crop of 25%, a rotation of 5 degrees, two simulated captures of a screen) and the
measurement: both generated sets survive every attack; the claims are what the
photographs survived too. §7.4, §7.6 to §7.8 and §13, §14 cover both registered schemes;
§1 drops the crop-and-rotation exclusion. Registry, export, SPEC §5, CHANGELOG, READMEs
and the CI step's description follow.

_wai_mark.py gains the tiled scheme from the text (the autocorrelation by one integer
product a frame, the fold, the phase and a bit-sliced agreement count); synthesis_verify.py
recomputes and reruns either scheme; synthesis_mark_verify.py checks the tiled files,
derives the frames they name, mutates them and weakens itself against them. Tests pin
§7.9.1's definition and digest, §7.9.2's shuffle, §7.9.5's figures and §7.9.7's table and
claims to the reference.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The crop-and-rotation unit test takes its pictures and attacks from synthesis_mark, so it
runs under that feature; the lib's synthesis:: tests build without it. Three clippy notes
in the detector (an indexed loop, a sort by key, a cloned slice) rewritten without
changing what it computes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The test checked §7.9.7's claims against the generated sets' tallies alone, so a claim
the photographs' column refutes passed it (screen-b, falsified); it now reads the row's
three columns, as the second implementation does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
tent64s corpus: each detect vector states stage 2's trace
All checks were successful
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m13s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m14s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 34s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 9m9s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 2m21s
wai-pack / wai-pack · linux (pull_request) Successful in 1m24s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 6m11s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 16s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 11s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 29s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 8m25s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 2m55s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 19m10s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m55s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m10s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 12m16s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m35s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 23m44s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 1m17s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m46s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 6m5s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 44m56s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m6s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 13m36s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 18s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 44s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 4m58s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 2m39s
wai-pack / wai-pack · macos (pull_request) Successful in 1m15s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m15s
2016ec1805
Every candidate stage 2 keeps (its vectors, refined lattice, bins and phase) and the
hypotheses it decodes, for every detect vector, stored or derived. The vectors' payloads
alone did not tell the phase rule apart: choosing the phase by the tile's energy rather
than the tiles' agreement passed the second implementation (falsified); with the traces
the two implementations compare the whole pipeline, and a mutated phase is caught.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
dcharlot closed this pull request 2026-10-25 23:51:01 -04:00
All checks were successful
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 5s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 4s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 5s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m46s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m30s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
WAI conformance / does this change touch it (pull_request) Successful in 6s
WAI energy receipts / does this change touch it (pull_request) Successful in 7s
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Successful in 6s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 6s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 9s
wai-web wasm32 / does this change touch it (pull_request) Successful in 9s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m10s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m13s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m14s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 34s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 9m9s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 2m21s
wai-pack / wai-pack · linux (pull_request) Successful in 1m24s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 6m11s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 16s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 11s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 29s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 8m25s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 2m55s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 19m10s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m55s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m10s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 12m16s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m35s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 23m44s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 1m17s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m46s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 6m5s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 44m56s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m6s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 13m36s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 18s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 44s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 4m58s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 2m39s
wai-pack / wai-pack · macos (pull_request) Successful in 1m15s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m15s

Pull request closed

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!425
No description provided.