wai.media.contribution: who contributed what, computed from the process (CO1) #403

Merged
dcharlot merged 6 commits from wai/contribution into main 2026-10-21 19:02:22 -04:00
Owner

What this adds

wai.media.contribution (CO1): who contributed what to media made by people and models together, computed from the process that made it.

  • Extension text: wai/extensions/contribution.md (§1 scope, §2 records, §3 session and membership, §4 steps, acts, parameters, check and pinned operations, §5 chain and Merkle tree, §6 the contribution record, §7 the authorship map, §8 disclosure, §9 origin-claim agreement and the C2PA, identity and live-track mappings, §10 verification, §11 reasons, §12 conformance, §13 security and privacy).
  • Reference module: wai-rs/src/contribution.rs behind feature contribution = ["synthesis", "generate"] (no new dependency), its corpus generator src/contribution/corpus.rs, the bin wai_contribution_vectors, and tests/contribution.rs.
  • Corpus: wai/live-conformance/contribution/vectors.json (written from fixed seeds) and its README with the Provenance. line.
  • Second implementation: wai/live-conformance/contribution_verify.py, standard library only, run as python3 -I.
  • CI: a step in .github/workflows/wai-conformance.yml beside synthesis's, and wai/extensions/contribution.md in the workflow's paths:.
  • Registry: the record wai.media.contribution and five document kinds (wai-session §3.1, wai-membership §3.2, wai-step §4.1, wai-contribution §6, wai-authorship-map §7.3) in codecs/registry.rs; registry export regenerated (registry/capabilities.json, vocab/v2.ttl, REGISTRY.md). SPEC §5 paragraph and record list, CHANGELOG entry, live-conformance/README.md, and the live-conformance exclusion reason in tests/int_kernels_vectors.rs (the generated pictures are made against a model file and each is named by the SHA-256 of its RGB8 samples).

Design decisions, and why

  • Reuse, by name. Records use synthesis §2's encodings, signature and link-hash pattern with the domains wai:contribution\x01 / wai:contribution-link\x01. Transforms evaluate deriving-edge §4.2's wai.derive.crop, rotation, mirror, overlay_composition and grid_composition, and synthesis §4.1/§4.2's wai-synthesis:upscale2 and denoise3, by name and arithmetic. wai.derive.scaling stays unpinned (attested), as deriving-edge has it.
  • One new operation, wai-contribution:lut. The brief expected a colour operation in deriving-edge §4.2; there is none, and no WAI text pins a per-sample colour mapping. A value transform is needed for the "keeps made_by, adds the chooser" rule, so the extension pins one 768-byte per-channel table and says why.
  • Exact generator: wai.generate.spectral (SPEC §5, generate.rs) with the model file of its conformance vector, which the corpus embeds byte for byte. An exact inpainting makes the generator's picture at the input's size and copies it inside the region. The Python port of the generator checks itself against wai-rs/tests/vectors/generate/sha256.json before it is trusted.
  • check instead of a boolean exact. Records admit no boolean; the step's check takes deriving-edge §4.5's replicate / attest. Samples a person introduces (author, an edit's region) are the source of the chain, as a capture is in synthesis §3.2, so those acts are replicate.
  • Countersigned membership is a separate record over the session's link hash, so a person signs the whole list of parties; the tool's key may not be a person's.
  • Inputs name a state by (step, samples), not by digest alone, so two states with equal samples but different histories cannot be confused.
  • Two markers, never credited. unknown: no pinned rule fixes the sample even with every step disclosed (an attested transform or composition). undisclosed: a verifier's computed map only, for samples from steps it does not hold. A stated map may hold unknown, never undisclosed. Comparison: where the computed set holds undisclosed, its other members must be in the stated set; otherwise the sets are equal. A stated party where the computed set is unknown is unknown_attributed; other differences are map_mismatch.
  • A model's samples from an attested generator are made_by that model, with the step attested, rather than unknown. Reading the brief's "a step that isn't exact leaves its region unknown" literally would make the generated region of every float-model session unknown, which defeats separating model-made from person-made parts; here unknown is reserved for an unpinned sample mapping, and the tier reports what was regenerated. The lead may want to confirm this reading.
  • Edit and inpaint regions take nothing from the samples they replace (directed_by is reset inside the region). Conditioning from outside the region is left to the conditioning-attribution slot.
  • Merkle tree: jwp-receipts §2.2's construction with domains of this extension's own; leaf index = seq; proofs walked as jwp-receipts §3 step 5. The duplicated last leaf also walks from the position past the end; the record's steps count and §5.1's seq < steps rule close that, and the unit test states it.
  • Tiers: recomputed (every step behind the output held and checked), checked (otherwise, with at least one step), stated (no step held). A policy member tier refuses an outcome below it (tier_not_met).
  • Origin agreement reads the origin claim with synthesis's own reader and requires class synthesized wherever the stated map has a model-made sample.
  • C2PA: one actions statement, computed where every step is disclosed: c2pa.created from http://c2pa.org/digitalsourcetype/empty (C2PA 2.4 §18.15.2), then one action per step behind the output with softwareAgent, IPTC digital source type and changes region maps. A selection gets no action (C2PA 2.4's Table 8 has none, and it changes no sample). Identity assertions (Identity Assertion 1.2) and live tracks (live-provenance) are informative.
  • Scope: RGB8 images fully. Audio maps by sample interval and video maps by frame are not in this revision; the session's media is image and §1 says so.
  • WAI decides no legal question. §1 says so and cites the copyrightability report only by title, for what it takes up and concludes.

Checks

All cargo work ran on the build host through ~/kani-logs/remote/rb, on the merged tree (head 2d67596d9).

check command result
unit tests cargo test --no-default-features --features contribution --lib contribution:: ok, 3 passed
corpus test cargo test --no-default-features --features contribution --test contribution ok, 4 passed
corpus verify cargo run -q --no-default-features --features contribution --bin wai_contribution_vectors -- verify ../live-conformance/contribution PASS
second implementation python3 -I live-conformance/contribution_verify.py live-conformance/contribution exit 0: every vector agrees with wai-rs, every reason of §11 refused, all three tiers reached, every mutated copy fails, every dropped check caught
synthesis (imported by the verifier) cargo test --no-default-features --features synthesis --test synthesis; python3 -I live-conformance/synthesis_verify.py live-conformance/synthesis ok; exit 0
every other live verifier python3 -I <x>_verify.py <dir> for events, rooms, takes, compose, recordings, captions, metering, steering, moderation, ads, e2ee, watermark, c2pa-live, synthesis, usage all exit 0
registry export cargo run -q --no-default-features --bin wai -- registry export then -- registry export --check regenerated; "up to date"
registry tests cargo test --no-default-features --lib codecs::registry; cargo test --no-default-features --test cli_registry --test corpus_provenance ok (14; 6 + 2)
corpus rule cargo test --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int --test int_kernels_vectors every_decoded_output_states_a_sha256 ok
clippy cargo clippy --no-default-features --features contribution --all-targets 0 notes in the new files (the two chunks_exact notes the new 1.98 lint raised were fixed with as_chunks)
lockfile cargo metadata --locked --offline --format-version 1 (wai-rs) ok; no dependency added
repo checks (local) python3 -I scripts/check-tests-in-ci.py, ./scripts/check-workflow-concurrency.sh, python3 scripts/check-spec-refs.py, python3 scripts/check-wai-section-refs.py, bash scripts/check-no-vanity-metrics.sh, bash scripts/test-public-text-checks.sh, bash scripts/check-comparative-prose.sh, python3 scripts/check-orphan-sources.py all exit 0

scripts/check-public-names.sh needs the private denylist and was not run locally; CI runs it.

Falsifications

Committed first; each break applied to the build host's snapshot, tested, then restored.

break cargo test --features contribution --test contribution
baseline exit 0, 4 passed
the outside-region comparison dropped exit 101
unknown_attributed folded into map_mismatch exit 101
the inpainted region's regeneration check dropped exit 0 at first: no vector covered it. Added regeneration_mismatch_inpaint; now exit 101
the tree's leaf domain changed exit 101
a code removed from §11 exit 101 (the_extension_lists_the_reasons)
a transform's chooser not added to directed_by exit 101
the performer-role check dropped exit 101
the record's output-length check dropped exit 101
a selection's output-is-its-input check dropped exit 101
the record's session check dropped exit 101
the record's signer check dropped exit 101
the prev link check dropped exit 101
the size-only recompute check dropped exit 101
the held-input size check of an edit dropped exit 101

The inpaint gap led to a second control for every check with a second place in §10.2 (record-level samples_mismatch, session_mismatch, signer_mismatch, party_unknown; region_invalid from a held buffer; selection_not_in_set for an output that is not its member; size-only recompute_mismatch; shape-only params_invalid; a prev that skips). The Python verifier drops each of its own checks in turn and the corpus catches every one; it exits 1 on a copy of the corpus with one byte of the inpainted state changed.

Not done

  • Audio maps by sample interval, video maps by frame.
  • Aggregating an audience's choices into one act, direction tracks (direct is reserved and refused), conditioning attribution, tooling and presentation: slots named in §1.
  • Live-track carriage of a record is informative (§9.4); no assertion is registered.
  • Owner decisions, not taken here: whether to approach any registration authority, collective-management organisation or standards group about the record, or to propose an assertion for C2PA/the identity assertion; none was contacted.

🤖 Generated with Claude Code

## What this adds `wai.media.contribution` (CO1): who contributed what to media made by people and models together, computed from the process that made it. - **Extension text**: `wai/extensions/contribution.md` (§1 scope, §2 records, §3 session and membership, §4 steps, acts, parameters, check and pinned operations, §5 chain and Merkle tree, §6 the contribution record, §7 the authorship map, §8 disclosure, §9 origin-claim agreement and the C2PA, identity and live-track mappings, §10 verification, §11 reasons, §12 conformance, §13 security and privacy). - **Reference module**: `wai-rs/src/contribution.rs` behind feature `contribution = ["synthesis", "generate"]` (no new dependency), its corpus generator `src/contribution/corpus.rs`, the bin `wai_contribution_vectors`, and `tests/contribution.rs`. - **Corpus**: `wai/live-conformance/contribution/vectors.json` (written from fixed seeds) and its README with the **Provenance.** line. - **Second implementation**: `wai/live-conformance/contribution_verify.py`, standard library only, run as `python3 -I`. - **CI**: a step in `.github/workflows/wai-conformance.yml` beside synthesis's, and `wai/extensions/contribution.md` in the workflow's `paths:`. - **Registry**: the record `wai.media.contribution` and five document kinds (`wai-session` §3.1, `wai-membership` §3.2, `wai-step` §4.1, `wai-contribution` §6, `wai-authorship-map` §7.3) in `codecs/registry.rs`; `registry export` regenerated (`registry/capabilities.json`, `vocab/v2.ttl`, `REGISTRY.md`). SPEC §5 paragraph and record list, CHANGELOG entry, `live-conformance/README.md`, and the `live-conformance` exclusion reason in `tests/int_kernels_vectors.rs` (the generated pictures are made against a model file and each is named by the SHA-256 of its RGB8 samples). ## Design decisions, and why - **Reuse, by name.** Records use synthesis §2's encodings, signature and link-hash pattern with the domains `wai:contribution\x01` / `wai:contribution-link\x01`. Transforms evaluate deriving-edge §4.2's `wai.derive.crop`, `rotation`, `mirror`, `overlay_composition` and `grid_composition`, and synthesis §4.1/§4.2's `wai-synthesis:upscale2` and `denoise3`, by name and arithmetic. `wai.derive.scaling` stays unpinned (attested), as deriving-edge has it. - **One new operation, `wai-contribution:lut`.** The brief expected a colour operation in deriving-edge §4.2; there is none, and no WAI text pins a per-sample colour mapping. A value transform is needed for the "keeps `made_by`, adds the chooser" rule, so the extension pins one 768-byte per-channel table and says why. - **Exact generator: `wai.generate.spectral`** (SPEC §5, `generate.rs`) with the model file of its conformance vector, which the corpus embeds byte for byte. An exact inpainting makes the generator's picture at the input's size and copies it inside the region. The Python port of the generator checks itself against `wai-rs/tests/vectors/generate/sha256.json` before it is trusted. - **`check` instead of a boolean `exact`.** Records admit no boolean; the step's `check` takes deriving-edge §4.5's `replicate` / `attest`. Samples a person introduces (`author`, an edit's region) are the source of the chain, as a capture is in synthesis §3.2, so those acts are `replicate`. - **Countersigned membership** is a separate record over the session's link hash, so a person signs the whole list of parties; the tool's key may not be a person's. - **Inputs name a state by `(step, samples)`**, not by digest alone, so two states with equal samples but different histories cannot be confused. - **Two markers, never credited.** `unknown`: no pinned rule fixes the sample even with every step disclosed (an attested transform or composition). `undisclosed`: a verifier's computed map only, for samples from steps it does not hold. A stated map may hold `unknown`, never `undisclosed`. Comparison: where the computed set holds `undisclosed`, its other members must be in the stated set; otherwise the sets are equal. A stated party where the computed set is `unknown` is `unknown_attributed`; other differences are `map_mismatch`. - **A model's samples from an attested generator are `made_by` that model**, with the step `attested`, rather than `unknown`. Reading the brief's "a step that isn't exact leaves its region unknown" literally would make the generated region of every float-model session unknown, which defeats separating model-made from person-made parts; here `unknown` is reserved for an unpinned *sample mapping*, and the tier reports what was regenerated. The lead may want to confirm this reading. - **Edit and inpaint regions** take nothing from the samples they replace (`directed_by` is reset inside the region). Conditioning from outside the region is left to the conditioning-attribution slot. - **Merkle tree**: jwp-receipts §2.2's construction with domains of this extension's own; leaf index = `seq`; proofs walked as jwp-receipts §3 step 5. The duplicated last leaf also walks from the position past the end; the record's `steps` count and §5.1's `seq < steps` rule close that, and the unit test states it. - **Tiers**: `recomputed` (every step behind the output held and `checked`), `checked` (otherwise, with at least one step), `stated` (no step held). A policy member `tier` refuses an outcome below it (`tier_not_met`). - **Origin agreement** reads the origin claim with synthesis's own reader and requires class `synthesized` wherever the stated map has a model-made sample. - **C2PA**: one actions statement, computed where every step is disclosed: `c2pa.created` from `http://c2pa.org/digitalsourcetype/empty` (C2PA 2.4 §18.15.2), then one action per step behind the output with `softwareAgent`, IPTC digital source type and `changes` region maps. A selection gets no action (C2PA 2.4's Table 8 has none, and it changes no sample). Identity assertions (Identity Assertion 1.2) and live tracks (live-provenance) are informative. - **Scope**: RGB8 images fully. Audio maps by sample interval and video maps by frame are **not** in this revision; the session's `media` is `image` and §1 says so. - **WAI decides no legal question.** §1 says so and cites the copyrightability report only by title, for what it takes up and concludes. ## Checks All cargo work ran on the build host through `~/kani-logs/remote/rb`, on the merged tree (head `2d67596d9`). | check | command | result | |---|---|---| | unit tests | `cargo test --no-default-features --features contribution --lib contribution::` | ok, 3 passed | | corpus test | `cargo test --no-default-features --features contribution --test contribution` | ok, 4 passed | | corpus verify | `cargo run -q --no-default-features --features contribution --bin wai_contribution_vectors -- verify ../live-conformance/contribution` | PASS | | second implementation | `python3 -I live-conformance/contribution_verify.py live-conformance/contribution` | exit 0: every vector agrees with wai-rs, every reason of §11 refused, all three tiers reached, every mutated copy fails, every dropped check caught | | synthesis (imported by the verifier) | `cargo test --no-default-features --features synthesis --test synthesis`; `python3 -I live-conformance/synthesis_verify.py live-conformance/synthesis` | ok; exit 0 | | every other live verifier | `python3 -I <x>_verify.py <dir>` for events, rooms, takes, compose, recordings, captions, metering, steering, moderation, ads, e2ee, watermark, c2pa-live, synthesis, usage | all exit 0 | | registry export | `cargo run -q --no-default-features --bin wai -- registry export` then `-- registry export --check` | regenerated; "up to date" | | registry tests | `cargo test --no-default-features --lib codecs::registry`; `cargo test --no-default-features --test cli_registry --test corpus_provenance` | ok (14; 6 + 2) | | corpus rule | `cargo test --no-default-features --features neural_int,video_int,audio_int,world_int,splat_int --test int_kernels_vectors every_decoded_output_states_a_sha256` | ok | | clippy | `cargo clippy --no-default-features --features contribution --all-targets` | 0 notes in the new files (the two `chunks_exact` notes the new 1.98 lint raised were fixed with `as_chunks`) | | lockfile | `cargo metadata --locked --offline --format-version 1` (wai-rs) | ok; no dependency added | | repo checks (local) | `python3 -I scripts/check-tests-in-ci.py`, `./scripts/check-workflow-concurrency.sh`, `python3 scripts/check-spec-refs.py`, `python3 scripts/check-wai-section-refs.py`, `bash scripts/check-no-vanity-metrics.sh`, `bash scripts/test-public-text-checks.sh`, `bash scripts/check-comparative-prose.sh`, `python3 scripts/check-orphan-sources.py` | all exit 0 | `scripts/check-public-names.sh` needs the private denylist and was not run locally; CI runs it. ## Falsifications Committed first; each break applied to the build host's snapshot, tested, then restored. | break | `cargo test --features contribution --test contribution` | |---|---| | baseline | exit 0, 4 passed | | the outside-region comparison dropped | exit 101 | | `unknown_attributed` folded into `map_mismatch` | exit 101 | | the inpainted region's regeneration check dropped | **exit 0 at first**: no vector covered it. Added `regeneration_mismatch_inpaint`; now exit 101 | | the tree's leaf domain changed | exit 101 | | a code removed from §11 | exit 101 (`the_extension_lists_the_reasons`) | | a transform's chooser not added to `directed_by` | exit 101 | | the performer-role check dropped | exit 101 | | the record's output-length check dropped | exit 101 | | a selection's output-is-its-input check dropped | exit 101 | | the record's session check dropped | exit 101 | | the record's signer check dropped | exit 101 | | the `prev` link check dropped | exit 101 | | the size-only recompute check dropped | exit 101 | | the held-input size check of an edit dropped | exit 101 | The inpaint gap led to a second control for every check with a second place in §10.2 (record-level `samples_mismatch`, `session_mismatch`, `signer_mismatch`, `party_unknown`; `region_invalid` from a held buffer; `selection_not_in_set` for an output that is not its member; size-only `recompute_mismatch`; shape-only `params_invalid`; a `prev` that skips). The Python verifier drops each of its own checks in turn and the corpus catches every one; it exits 1 on a copy of the corpus with one byte of the inpainted state changed. ## Not done - Audio maps by sample interval, video maps by frame. - Aggregating an audience's choices into one act, direction tracks (`direct` is reserved and refused), conditioning attribution, tooling and presentation: slots named in §1. - Live-track carriage of a record is informative (§9.4); no assertion is registered. - Owner decisions, not taken here: whether to approach any registration authority, collective-management organisation or standards group about the record, or to propose an assertion for C2PA/the identity assertion; none was contacted. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The extension text (extensions/contribution.md), the reference module behind the
contribution feature, its corpus generator and test, and the generated corpus.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Written from the extension's text; ports the pinned generator and checks it against
the generator's own conformance vector first; mutates copies of the corpus and drops
each of its own checks in turn.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Registers the record and its five document kinds (registry export regenerated), adds
the SPEC §5 paragraph and the CHANGELOG entry, the CI step beside synthesis's, the
corpus README with its provenance line, and the live-conformance exclusion reason for
the generated pictures. The tree test now states the duplicated last leaf's second
position, which the record's count refuses (§5.1).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
An inpainting whose region does not regenerate, a record whose output samples are not
its size, an edit over a held input of another size, a selection whose output is not
its member, a crop of the wrong size without its input, a rotation by five quarter
turns, and the record's own party, session and signer; a prev that skips its
predecessor. state_map gives an operation it cannot read no mapping (unknown) rather
than panicking.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge origin/main into wai/contribution
All checks were successful
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 5m22s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m23s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 31s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 10m48s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 1m51s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 19m55s
wai-pack / wai-pack · linux (pull_request) Successful in 1m17s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 3m9s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m8s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 27m4s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 30s
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 47s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m34s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 42m17s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m44s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 10m40s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 51s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 4m8s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m19s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 6m28s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 39m7s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m49s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 13m36s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 21s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 52s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 5m37s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 2m34s
wai-pack / wai-pack · macos (pull_request) Successful in 1m8s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m21s
2d67596d9d
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!403
No description provided.