wai: channel lineup and guide — a linear channel's feeds imported, signed (wai.video.lineup), and its guide checkable #540

Merged
dcharlot merged 15 commits from wai/fast-channel-guide into main 2026-10-30 02:17:33 -04:00
Owner

Updated after #539 (the revenue share), main at 7473e6d7e

  • Merged origin/main (3fb4e67dd). Both sides kept in CHANGELOG.md, SPEC.md §5, catalogue.rs, dx/mod.rs, tests/cli_ops.rs and the two workflows; WAI_FEATURES, the union test build and the features-alone list each hold revenue_share and channel_lineup. The generated files (wai/catalogue/ops.json, wai/registry/capabilities.json, wai/vocab/v2.ttl, REGISTRY.md's table, Studio's actions.generated.js) were taken from main and regenerated from the merged sources (wai registry export, wai ops export --out, node scripts/actions.mjs), not merged as text. The channel lineup's --dry-run sample in tests/cli_ops.rs now writes channel-operator.key: the revenue share's sample writes operator.key in the same directory, and quickstart,revenue_share runs both.
  • One JSON carriage for the channel receipt (3320d5b59). channel_lineup::receipt_to_json / receipt_from_json are gone: the import writes a receipt with ChannelReceipt::to_json and verification reads one with ChannelReceipt::from_json (main's, revenue-share §4.1, "the one JSON form of a channel receipt"); signing_payload stays private as on main and this branch calls main's payload(), so wai_video_channel.rs is main's file unchanged. channel-lineup §5 keeps its number and is now a normative reference: the carriage is revenue-share §4.1, the leaves, root, signing payload, signature and identity §4.2, the rules §4.3 rules 1 to 5 and the signature rule 6; §1, §8.2 and §11 point there. channel_lineup_verify.py reads receipts with revenue_share_verify.py's read_run, run_payload, run_identity, run_verifies, leaf and merkle, and no longer takes anything from live_ads_verify.py.
  • Proof, before the pair was deleted (the test was run, not committed): over every corpus receipt (sample.channel.json, media_rss_loop.channel.json, aired-misreported.channel.json; the two receipts that verification vectors edit, receipt_malformed and receipt_bad_signature; and the sample re-sealed with each energy class: ModelBased, Estimator, OnChipCounter, CalibratedInstrument), the old reader and serde_json + ChannelReceipt::from_json gave equal results, the old writer and to_json equal JSON values, and the indented files were byte-identical, each unedited one equal to its bytes on disk. Output: CARRIAGE-EQUIVALENCE: 9 receipts (8 read, 1 refused by both readers); readers, writers and files identical. After the change, wai_channel_lineup_vectors gen changes no file of the corpus (0 files differ; nothing to pull back).
  • Spans written in words (88deef467): with §5 now linking to revenue-share, check-wai-section-refs.py paired the bare [ of an interval written [a, b) with that link; each span is now written from its start to its end.
  • The checks below were all rerun at the merged head.

What this adds

A linear channel's feeds, as operators exchange them, become signed WAI records, and the channel's guide becomes checkable against them. One new record, wai.video.lineup (WLU1); the wai.video.channel receipt keeps its signed bytes.

  • The text, wai/extensions/channel-lineup.md ("Channel Lineup and Guide"): §3 the bounds, text values, the XML subset (stitched-presentation §3.5 plus one document type declaration that defines nothing) and the XMLTV and HLS time forms; §4 the import; §5 the receipt's JSON carriage (revenue-share §4, by reference); §6 the lineup; §7 the guide; §8 verification; §9 the operations and a worked example; §10 the reasons (30 added, plus live-events' bad_key and bad_signature); §11 conformance; §12 security and privacy.
  • The import (§4): an XMLTV schedule (programmes of one XMLTV channel, the asset named by an episode-num system, wai-asset-id by default), Media RSS catalogues (each with its owner; items alone play back to back from a start), or a JSON form of both (wai-channel-feed), and the SCTE-35 date ranges of the channel's HLS Media Playlist (an out/in pair across two tags of one ID merged; duration from DURATION, END-DATE or PLANNED-DURATION). Breaks split their programme into program and ad entries. It yields the receipt (unmetered, a grant reference with no ceilings), the lineup, and one live-events §4.3 cue payload per break, its cue_id a splice_insert()'s splice_event_id (SCTE 35-1 §9.6, §9.7.3) or a hash of the break id. Refused, each with its reason, in a stated order (§4.10): a gap, an overlap, a programme with no stop, a time zone named by letters, a malformed time, a break outside its programme or of no duration, a window outside the schedule, an unknown or duplicate asset, a missing owner or artwork file, an SCTE-35 section that does not read, an oversized document or count, and a document outside its form.
  • The lineup (§6): channel id and name, the schedule root and span, each programme's start, and per asset its title, description, categories, rating, artwork (SHA-256 and URI), where it may be shown (everywhere, only in, everywhere but; ISO 3166-1 alpha-2), rights holder, content URI and duration; signed by the operator, the same key that signs the receipt. §6.5 says when a lineup describes a schedule (five rules).
  • The guide (§7): an XMLTV document (DTD element order; its sources named in tv's source-data-url as urn:wai:guide:<root>:<lineup>:<from>:<to>) and a now/next document (RFC 8785, wai-now-next), both pure functions of the receipt and the lineup. Verification (§8) recomputes and compares: guide_entry_unscheduled for a guide that places a programme where the schedule does not, guide_mismatch for any other difference, and for each programme whether the receipt's program-as-run says it aired.
  • wai-rs: feature channel_lineup (video_channel, stitched_presentation; no new dependency), module src/channel_lineup.rs with import.rs and corpus.rs; it writes and reads receipts with ChannelReceipt::to_json / from_json and splits a bad signature from a broken rule with ChannelReceipt::payload(); wai_video_channel.rs is unchanged. quickstart, the shipped wai's build, now holds channel_lineup (it already held every feature it depends on).
  • Operations: channel.import, channel.guide, channel.verify (wai channel ...), placed local, with --json, --dry-run on the two that write, --yes before a file is replaced, and a refusal's reason as the error's code with exit 1. ops.json and Studio's generated actions follow; no Studio binding is needed (local placement).
  • Conformance: wai/live-conformance/channels/, written from fixed seeds by wai_channel_lineup_vectors gen: a sample channel (XMLTV beside another channel's programme, two owners' Media RSS, a Media Playlist with real splice_insert()/time_signal() sections and CRCs, the same channel as the JSON form, SVG artwork), 27 import vectors (3 that yield, 24 controls, each the sample with one stated edit) and 22 verification vectors (6 verified, 16 controls). wai/live-conformance/channel_lineup_verify.py is the second implementation, from the text alone.
  • Registry (wai.video.lineup; wire identifiers WLU1, wai-channel-feed, urn:wai:guide:, wai-asset-id, wai-now-next) and its export, SPEC §5 paragraph, CHANGELOG entry, the conformance workflow step, the feature in features-alone, and the catalogue workflow's path for the corpus tests/cli_ops.rs now reads.

Design decisions

  • Name: channel-lineup.md (the brief's): the lineup is the one record it registers; the import produces it and the guide is rendered from it.
  • The guide is not signed. It is a pure function of two signed records, so a signature would add nothing; anyone holding the receipt and the lineup recomputes it byte for byte. A guide names its sources (schedule root, lineup digest, range or instant).
  • Programme boundaries live in the lineup. A schedule's entries cannot say which programme an ad between two programmes belongs to (an end-of-episode break and a pre-roll look the same), so the lineup records where each guide programme begins, and §6.5 checks it against the entries. This makes import then guide give back the XMLTV programmes' own slots, breaks included.
  • Whole seconds and 2^53 − 1. XMLTV times have no unit below the second, so programme boundaries must be whole seconds (breaks need not be); every instant a guide writes fits JSON's exact integers (RFC 8785).
  • Rights holder is a name, not a key: a lineup states what the operator published; a revenue-share contract (FAST-B's) names its parties itself and does not depend on the lineup.
  • Not read: EXT-X-CUE-OUT/CUE-IN tags (no HLS text defines them), interstitial date ranges (stitched-presentation's), elements under media:group other than the content, and anything the text does not name. Named in §1.
  • The magic is WLU1: WCL1, first chosen, is live-recording's link record; the registry's test caught it.
  • Shared files: every addition to CHANGELOG.md, SPEC.md §5, catalogue.rs, ops.json, the conformance workflow and tests/cli_ops.rs is its own block, so a parallel branch's additions merge beside it; the shared single lines (WAI_FEATURES, the union test build, the features-alone list) hold both features after the merge.

Checks (all on the Framework box, [email protected] rb, unless marked local)

check command (in wai/wai-rs unless noted) result
module unit tests cargo test --locked --no-default-features --features channel_lineup --lib channel_lineup:: 6 passed
corpus, outcomes, §10, worked example, CLI refusal cargo test --locked --no-default-features --features channel_lineup --test channel_lineup 5 passed
channel receipt's own tests (format pinned) cargo test --locked --no-default-features --features video_channel --lib wai_video_channel:: 8 passed
the revenue share (main's), with the shared carriage cargo test --locked --no-default-features --features revenue_share --test revenue_share 7 passed
corpus tool cargo run --features channel_lineup --bin wai_channel_lineup_vectors -- verify ../live-conformance/channels 18 files regenerate, every vector holds
second implementation python3 -I live-conformance/channel_lineup_verify.py live-conformance/channels (in wai/) 27 imports and 22 verifications hold; 18 of 18 mutated copies fail; 32 of 32 checks, each dropped alone, caught
catalogue rules cargo test --locked --no-default-features --lib catalogue 6 passed
registry cargo test --locked --no-default-features --lib codecs::registry 14 passed
the CLI's agent rules (as wai-catalogue.yml runs them) cargo test --locked --no-default-features --features quickstart --bin wai --test cli_ops; also --features quickstart,app and --features quickstart,generate,score,staged,video_int,audio_int,splat_int and --features quickstart,revenue_share --test cli_ops 47 + 10 passed; 10; 10; 10
ops export cargo run --no-default-features --bin wai -- ops export --check ../catalogue/ops.json up to date
registry export cargo run --no-default-features --bin wai -- registry export --check up to date
compatibility gate cargo run --no-default-features --bin wai -- breaking --against 7473e6d7e (origin/main) no unacknowledged breaking change
feature alone cargo check --locked --no-default-features --features channel_lineup --tests ok
union feature build (the workflow's WAI_FEATURES, channel_lineup appended) cargo test --no-run --locked --no-default-features --features "$WAI_FEATURES" --lib --test channel_lineup --test revenue_share --test stitched_presentation ok
clippy, touched files cargo clippy --no-default-features --features channel_lineup --all-targets; cargo clippy --no-default-features --features quickstart --bin wai --tests; --features quickstart,revenue_share --bin wai --tests 0 notes in touched files (pre-existing notes elsewhere unchanged)
lockfile cargo metadata --locked --offline --format-version 1 ok; no dependency added, no lockfile changes
every other live-conformance verifier (shared text touched) each python3 -I live-conformance/<x>_verify.py <dir> line of wai-conformance.yml 52 lines: 51 pass on the build host, among them main's revenue_share_verify.py; bearer_verify.py needs cryptography, absent there, so run locally: pass; dred_verify.py takes a built artifact and was not run (reads nothing changed)
Studio (local) node wai/wai-studio/scripts/actions.mjs --check holds to the catalogue
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 exit 0
workflows (local) ruby -ryaml ... over .github/workflows/*.yml; wfsteps.py HEAD b929c31ae 7473e6d7e (the two merged refs) parse; 2 findings, both steps that both sides changed (the union build's step and the features-alone list), so neither source's body can match; checked three-way against the merge base 564a42df8: each is exactly the union of the two sides' line changes (this branch's four --bin lines and --test channel_lineup, main's --test revenue_share; both features in features-alone), nothing else
public names (local) check-public-names.sh over the 43 files this branch changes against main; grep -E of the patterns over every commit message and this body clean; no hit

Falsifications (each guard mutated on the build host, run, restored with git checkout --; all rerun at the merged head 88deef467: 18 of 18 caught, no anchor missed)

guard mutation result
lineup signature (§8.2 step 5) verify_signature accepts any signature tests/channel_lineup.rs fails (exit 101)
one operator signs both (step 6) signer check disabled fails (101)
§6.5 rule 3, a programme begins where an entry does rule disabled fails (101): lineup_programme_mid_entry
receipt rules (step 3) receipt_verdict skips verify() fails (101): receipt_invalid
guide bytes (step 11) byte comparison disabled fails (101)
guide entries (step 10) entry check disabled fails (101), incl. the CLI refusal test
import gap (§4.6) gap check disabled fails (101)
break inside its programme (§4.7) end check disabled fails (101)
XMLTV zone (§3.4) named zones accepted unit test fails (101)
one document type declaration (§3.3) every declaration skipped unit test fails (101)
cue_id from splice_insert() (§4.8) bytes 13..17 read fails (101), after the section-builder fix; before it, passed (see below)
corpus byte-stability a committed guide's title gains a space fails (101)
§10 lists the reasons import_gap's row removed fails (101)
§9's worked example runs as written --mrss-owner owner-b becomes owner-z fails (101)
ChannelReceipt bytes unchanged window_end_ms written little-endian legacy_hwshunt_receipt_keeps_its_signed_bytes fails (101)
Python: a corpus file a guide's title altered exit 1 (guide_mismatch)
Python: the text's §10 a row removed exit 1 (import_gap is not a reason of §10)
CLI --dry-run channel.import writes with std::fs::write cli_ops dry-run test fails (101)

One falsification found a real defect: breaking the splice_event_id path of §4.8 was not caught at first, because the corpus generator wrote splice_info_section() one byte short (4 bytes for the 40-bit encryption/pts_adjustment block), so splice_command_type landed on byte 12 and every cue took the hashed id; both implementations agreed on the wrong bytes. Fixed (b929c31ae) and pinned by a unit test that reads SCTE 35-1 §14.2's splice_insert() sample (splice_event_id 0x4800008F) and §14.1's time_signal() sample. A second, from the Python verifier's dropped-check loop, showed the count bound, whole-second boundaries and break/break overlap had no control; and planning the Rust falsifications showed the one §6.5 control was refused by two rules at once. Each now has its own control.

Not in this PR

Revenue share (FAST-B); ad decisioning; playout; SCTE 224 audience or blackout rules (a lineup states where an asset may be shown, not when); EXT-X-CUE-OUT/CUE-IN; fetching artwork over the network (the import hashes files it is given); signing the cues as room events (an import yields the payloads; a room's principal signs them); Studio panels (the operations are local); any deploy, tag or release.

🤖 Generated with Claude Code

## Updated after #539 (the revenue share), main at 7473e6d7e - **Merged `origin/main`** (3fb4e67dd). Both sides kept in `CHANGELOG.md`, `SPEC.md` §5, `catalogue.rs`, `dx/mod.rs`, `tests/cli_ops.rs` and the two workflows; `WAI_FEATURES`, the union test build and the features-alone list each hold `revenue_share` and `channel_lineup`. The generated files (`wai/catalogue/ops.json`, `wai/registry/capabilities.json`, `wai/vocab/v2.ttl`, `REGISTRY.md`'s table, Studio's `actions.generated.js`) were taken from main and **regenerated** from the merged sources (`wai registry export`, `wai ops export --out`, `node scripts/actions.mjs`), not merged as text. The channel lineup's `--dry-run` sample in `tests/cli_ops.rs` now writes `channel-operator.key`: the revenue share's sample writes `operator.key` in the same directory, and `quickstart,revenue_share` runs both. - **One JSON carriage for the channel receipt** (3320d5b59). `channel_lineup::receipt_to_json` / `receipt_from_json` are gone: the import writes a receipt with `ChannelReceipt::to_json` and verification reads one with `ChannelReceipt::from_json` (main's, revenue-share §4.1, "the one JSON form of a channel receipt"); `signing_payload` stays private as on main and this branch calls main's `payload()`, so `wai_video_channel.rs` is main's file unchanged. channel-lineup **§5 keeps its number** and is now a normative reference: the carriage is revenue-share §4.1, the leaves, root, signing payload, signature and identity §4.2, the rules §4.3 rules 1 to 5 and the signature rule 6; §1, §8.2 and §11 point there. `channel_lineup_verify.py` reads receipts with `revenue_share_verify.py`'s `read_run`, `run_payload`, `run_identity`, `run_verifies`, `leaf` and `merkle`, and no longer takes anything from `live_ads_verify.py`. - **Proof, before the pair was deleted** (the test was run, not committed): over every corpus receipt (`sample.channel.json`, `media_rss_loop.channel.json`, `aired-misreported.channel.json`; the two receipts that verification vectors edit, `receipt_malformed` and `receipt_bad_signature`; and the sample re-sealed with each energy class: `ModelBased`, `Estimator`, `OnChipCounter`, `CalibratedInstrument`), the old reader and `serde_json` + `ChannelReceipt::from_json` gave equal results, the old writer and `to_json` equal JSON values, and the indented files were byte-identical, each unedited one equal to its bytes on disk. Output: `CARRIAGE-EQUIVALENCE: 9 receipts (8 read, 1 refused by both readers); readers, writers and files identical`. **After the change, `wai_channel_lineup_vectors gen` changes no file of the corpus** (0 files differ; nothing to pull back). - **Spans written in words** (88deef467): with §5 now linking to revenue-share, `check-wai-section-refs.py` paired the bare `[` of an interval written `[a, b)` with that link; each span is now written from its start to its end. - The checks below were all rerun at the merged head. ## What this adds A linear channel's feeds, as operators exchange them, become signed WAI records, and the channel's guide becomes checkable against them. One new record, `wai.video.lineup` (`WLU1`); the `wai.video.channel` receipt keeps its signed bytes. - **The text**, `wai/extensions/channel-lineup.md` ("Channel Lineup and Guide"): §3 the bounds, text values, the XML subset (stitched-presentation §3.5 plus one document type declaration that defines nothing) and the XMLTV and HLS time forms; §4 the import; §5 the receipt's JSON carriage (revenue-share §4, by reference); §6 the lineup; §7 the guide; §8 verification; §9 the operations and a worked example; §10 the reasons (30 added, plus live-events' `bad_key` and `bad_signature`); §11 conformance; §12 security and privacy. - **The import (§4)**: an XMLTV schedule (programmes of one XMLTV channel, the asset named by an `episode-num` system, `wai-asset-id` by default), Media RSS catalogues (each with its owner; items alone play back to back from a start), or a JSON form of both (`wai-channel-feed`), and the SCTE-35 date ranges of the channel's HLS Media Playlist (an out/in pair across two tags of one `ID` merged; duration from `DURATION`, `END-DATE` or `PLANNED-DURATION`). Breaks split their programme into program and ad entries. It yields the receipt (unmetered, a grant reference with no ceilings), the lineup, and one live-events §4.3 `cue` payload per break, its `cue_id` a `splice_insert()`'s `splice_event_id` (SCTE 35-1 §9.6, §9.7.3) or a hash of the break id. Refused, each with its reason, in a stated order (§4.10): a gap, an overlap, a programme with no stop, a time zone named by letters, a malformed time, a break outside its programme or of no duration, a window outside the schedule, an unknown or duplicate asset, a missing owner or artwork file, an SCTE-35 section that does not read, an oversized document or count, and a document outside its form. - **The lineup (§6)**: channel id and name, the schedule root and span, each programme's start, and per asset its title, description, categories, rating, artwork (SHA-256 and URI), where it may be shown (everywhere, only in, everywhere but; ISO 3166-1 alpha-2), rights holder, content URI and duration; signed by the operator, the same key that signs the receipt. §6.5 says when a lineup describes a schedule (five rules). - **The guide (§7)**: an XMLTV document (DTD element order; its sources named in `tv`'s `source-data-url` as `urn:wai:guide:<root>:<lineup>:<from>:<to>`) and a now/next document (RFC 8785, `wai-now-next`), both pure functions of the receipt and the lineup. **Verification (§8)** recomputes and compares: `guide_entry_unscheduled` for a guide that places a programme where the schedule does not, `guide_mismatch` for any other difference, and for each programme whether the receipt's program-as-run says it aired. - **wai-rs**: feature `channel_lineup` (`video_channel`, `stitched_presentation`; no new dependency), module `src/channel_lineup.rs` with `import.rs` and `corpus.rs`; it writes and reads receipts with `ChannelReceipt::to_json` / `from_json` and splits a bad signature from a broken rule with `ChannelReceipt::payload()`; `wai_video_channel.rs` is unchanged. `quickstart`, the shipped `wai`'s build, now holds `channel_lineup` (it already held every feature it depends on). - **Operations**: `channel.import`, `channel.guide`, `channel.verify` (`wai channel ...`), placed local, with `--json`, `--dry-run` on the two that write, `--yes` before a file is replaced, and a refusal's reason as the error's code with exit 1. `ops.json` and Studio's generated actions follow; no Studio binding is needed (local placement). - **Conformance**: `wai/live-conformance/channels/`, written from fixed seeds by `wai_channel_lineup_vectors gen`: a sample channel (XMLTV beside another channel's programme, two owners' Media RSS, a Media Playlist with real `splice_insert()`/`time_signal()` sections and CRCs, the same channel as the JSON form, SVG artwork), 27 import vectors (3 that yield, 24 controls, each the sample with one stated edit) and 22 verification vectors (6 verified, 16 controls). `wai/live-conformance/channel_lineup_verify.py` is the second implementation, from the text alone. - Registry (`wai.video.lineup`; wire identifiers `WLU1`, `wai-channel-feed`, `urn:wai:guide:`, `wai-asset-id`, `wai-now-next`) and its export, SPEC §5 paragraph, CHANGELOG entry, the conformance workflow step, the feature in `features-alone`, and the catalogue workflow's path for the corpus `tests/cli_ops.rs` now reads. ## Design decisions - **Name**: `channel-lineup.md` (the brief's): the lineup is the one record it registers; the import produces it and the guide is rendered from it. - **The guide is not signed.** It is a pure function of two signed records, so a signature would add nothing; anyone holding the receipt and the lineup recomputes it byte for byte. A guide names its sources (schedule root, lineup digest, range or instant). - **Programme boundaries live in the lineup.** A schedule's entries cannot say which programme an ad between two programmes belongs to (an end-of-episode break and a pre-roll look the same), so the lineup records where each guide programme begins, and §6.5 checks it against the entries. This makes import then guide give back the XMLTV programmes' own slots, breaks included. - **Whole seconds and 2^53 − 1.** XMLTV times have no unit below the second, so programme boundaries must be whole seconds (breaks need not be); every instant a guide writes fits JSON's exact integers (RFC 8785). - **Rights holder is a name, not a key**: a lineup states what the operator published; a revenue-share contract (FAST-B's) names its parties itself and does not depend on the lineup. - **Not read**: `EXT-X-CUE-OUT`/`CUE-IN` tags (no HLS text defines them), interstitial date ranges (stitched-presentation's), elements under `media:group` other than the content, and anything the text does not name. Named in §1. - **The magic is `WLU1`**: `WCL1`, first chosen, is live-recording's link record; the registry's test caught it. - **Shared files**: every addition to `CHANGELOG.md`, `SPEC.md` §5, `catalogue.rs`, `ops.json`, the conformance workflow and `tests/cli_ops.rs` is its own block, so a parallel branch's additions merge beside it; the shared single lines (`WAI_FEATURES`, the union test build, the features-alone list) hold both features after the merge. ## Checks (all on the Framework box, `[email protected] rb`, unless marked local) | check | command (in `wai/wai-rs` unless noted) | result | |---|---|---| | module unit tests | `cargo test --locked --no-default-features --features channel_lineup --lib channel_lineup::` | 6 passed | | corpus, outcomes, §10, worked example, CLI refusal | `cargo test --locked --no-default-features --features channel_lineup --test channel_lineup` | 5 passed | | channel receipt's own tests (format pinned) | `cargo test --locked --no-default-features --features video_channel --lib wai_video_channel::` | 8 passed | | the revenue share (main's), with the shared carriage | `cargo test --locked --no-default-features --features revenue_share --test revenue_share` | 7 passed | | corpus tool | `cargo run --features channel_lineup --bin wai_channel_lineup_vectors -- verify ../live-conformance/channels` | 18 files regenerate, every vector holds | | second implementation | `python3 -I live-conformance/channel_lineup_verify.py live-conformance/channels` (in `wai/`) | 27 imports and 22 verifications hold; 18 of 18 mutated copies fail; 32 of 32 checks, each dropped alone, caught | | catalogue rules | `cargo test --locked --no-default-features --lib catalogue` | 6 passed | | registry | `cargo test --locked --no-default-features --lib codecs::registry` | 14 passed | | the CLI's agent rules (as wai-catalogue.yml runs them) | `cargo test --locked --no-default-features --features quickstart --bin wai --test cli_ops`; also `--features quickstart,app` and `--features quickstart,generate,score,staged,video_int,audio_int,splat_int` and `--features quickstart,revenue_share` `--test cli_ops` | 47 + 10 passed; 10; 10; 10 | | ops export | `cargo run --no-default-features --bin wai -- ops export --check ../catalogue/ops.json` | up to date | | registry export | `cargo run --no-default-features --bin wai -- registry export --check` | up to date | | compatibility gate | `cargo run --no-default-features --bin wai -- breaking --against 7473e6d7e` (origin/main) | no unacknowledged breaking change | | feature alone | `cargo check --locked --no-default-features --features channel_lineup --tests` | ok | | union feature build (the workflow's `WAI_FEATURES`, `channel_lineup` appended) | `cargo test --no-run --locked --no-default-features --features "$WAI_FEATURES" --lib --test channel_lineup --test revenue_share --test stitched_presentation` | ok | | clippy, touched files | `cargo clippy --no-default-features --features channel_lineup --all-targets`; `cargo clippy --no-default-features --features quickstart --bin wai --tests`; `--features quickstart,revenue_share --bin wai --tests` | 0 notes in touched files (pre-existing notes elsewhere unchanged) | | lockfile | `cargo metadata --locked --offline --format-version 1` | ok; no dependency added, no lockfile changes | | every other live-conformance verifier (shared text touched) | each `python3 -I live-conformance/<x>_verify.py <dir>` line of wai-conformance.yml | 52 lines: 51 pass on the build host, among them main's `revenue_share_verify.py`; `bearer_verify.py` needs `cryptography`, absent there, so run locally: pass; `dred_verify.py` takes a built artifact and was not run (reads nothing changed) | | Studio (local) | `node wai/wai-studio/scripts/actions.mjs --check` | holds to the catalogue | | 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 exit 0 | | workflows (local) | `ruby -ryaml ...` over `.github/workflows/*.yml`; `wfsteps.py HEAD b929c31ae 7473e6d7e` (the two merged refs) | parse; 2 findings, both steps that both sides changed (the union build's step and the features-alone list), so neither source's body can match; checked three-way against the merge base 564a42df8: each is exactly the union of the two sides' line changes (this branch's four `--bin` lines and `--test channel_lineup`, main's `--test revenue_share`; both features in features-alone), nothing else | | public names (local) | `check-public-names.sh` over the 43 files this branch changes against main; `grep -E` of the patterns over every commit message and this body | clean; no hit | ## Falsifications (each guard mutated on the build host, run, restored with `git checkout --`; all rerun at the merged head 88deef467: 18 of 18 caught, no anchor missed) | guard | mutation | result | |---|---|---| | lineup signature (§8.2 step 5) | `verify_signature` accepts any signature | `tests/channel_lineup.rs` fails (exit 101) | | one operator signs both (step 6) | signer check disabled | fails (101) | | §6.5 rule 3, a programme begins where an entry does | rule disabled | fails (101): `lineup_programme_mid_entry` | | receipt rules (step 3) | `receipt_verdict` skips `verify()` | fails (101): `receipt_invalid` | | guide bytes (step 11) | byte comparison disabled | fails (101) | | guide entries (step 10) | entry check disabled | fails (101), incl. the CLI refusal test | | import gap (§4.6) | gap check disabled | fails (101) | | break inside its programme (§4.7) | end check disabled | fails (101) | | XMLTV zone (§3.4) | named zones accepted | unit test fails (101) | | one document type declaration (§3.3) | every declaration skipped | unit test fails (101) | | `cue_id` from `splice_insert()` (§4.8) | bytes 13..17 read | fails (101), after the section-builder fix; before it, **passed** (see below) | | corpus byte-stability | a committed guide's title gains a space | fails (101) | | §10 lists the reasons | `import_gap`'s row removed | fails (101) | | §9's worked example runs as written | `--mrss-owner owner-b` becomes `owner-z` | fails (101) | | `ChannelReceipt` bytes unchanged | `window_end_ms` written little-endian | `legacy_hwshunt_receipt_keeps_its_signed_bytes` fails (101) | | Python: a corpus file | a guide's title altered | exit 1 (`guide_mismatch`) | | Python: the text's §10 | a row removed | exit 1 (`import_gap is not a reason of §10`) | | CLI `--dry-run` | `channel.import` writes with `std::fs::write` | `cli_ops` dry-run test fails (101) | One falsification found a real defect: breaking the `splice_event_id` path of §4.8 was **not** caught at first, because the corpus generator wrote `splice_info_section()` one byte short (4 bytes for the 40-bit encryption/`pts_adjustment` block), so `splice_command_type` landed on byte 12 and every cue took the hashed id; both implementations agreed on the wrong bytes. Fixed (b929c31ae) and pinned by a unit test that reads SCTE 35-1 §14.2's `splice_insert()` sample (`splice_event_id` 0x4800008F) and §14.1's `time_signal()` sample. A second, from the Python verifier's dropped-check loop, showed the count bound, whole-second boundaries and break/break overlap had no control; and planning the Rust falsifications showed the one §6.5 control was refused by two rules at once. Each now has its own control. ## Not in this PR Revenue share (FAST-B); ad decisioning; playout; SCTE 224 audience or blackout rules (a lineup states where an asset may be shown, not when); `EXT-X-CUE-OUT`/`CUE-IN`; fetching artwork over the network (the import hashes files it is given); signing the cues as room events (an import yields the payloads; a room's principal signs them); Studio panels (the operations are local); any deploy, tag or release. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The import of a linear channel's feeds (XMLTV, Media RSS, a JSON form, a Media
Playlist's SCTE-35 date ranges) into a wai.video.channel receipt and a signed
lineup (WCL1); the receipt's JSON carriage, its signed bytes unchanged; the
guide, XMLTV or now/next, rendered from both and verified by recomputation;
the operations channel.import, channel.guide and channel.verify; the reasons.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The feature channel_lineup (video_channel, stitched_presentation; no new
dependency): the import of §4, the lineup record WCL1, the receipt's JSON
carriage, the XMLTV and now/next guides and the verification of §8. The corpus
live-conformance/channels/ is written from fixed seeds by
wai_channel_lineup_vectors; tests/channel_lineup.rs requires it byte for byte,
every vector's outcome, §10's table, and the worked example of §9 run as the
text writes it. ChannelReceipt's signing payload becomes visible to the crate;
its bytes do not change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
In the catalogue (and its export), with the agent rules: --json, --dry-run on
the two that write, --yes before a file is replaced, and a refusal's reason as
the error's code with exit 1. quickstart, the shipped wai's build, holds
channel_lineup. tests/cli_ops.rs gains the two writes' dry-run samples.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Written from extensions/channel-lineup.md alone; shares no code with wai-rs.
It reimports every vector's feeds and requires its outcome (the refusal, or
the receipt, the lineup and the cues, signatures verified), recomputes every
verification's facts, mutates copies of the corpus and requires each to fail,
and drops each of its checks in turn and requires the corpus to catch it. The
corpus gains three controls that only such a weakened verifier showed were
missing: the count bound, a boundary off a whole second, and two breaks that
overlap; and an edit form that repeats its text.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The record in the registry's table, with its wire identifiers (WLU1,
wai-channel-feed, urn:wai:guide:, wai-asset-id, wai-now-next) and the export
regenerated; SPEC §5's paragraph and the CHANGELOG entry. The lineup's magic
is WLU1: WCL1 is live-recording's link record, which the registry's test of
wire identifiers caught. The conformance workflow runs the module's tests,
tests/channel_lineup.rs, the corpus tool's verify and channel_lineup_verify.py,
and builds the feature alone; the catalogue workflow fires on the corpus,
which tests/cli_ops.rs reads. Studio's generated actions follow the catalogue.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Type names for the import's intermediate forms, the date fields of an instant
as one array, and a plain to_string. No change of behaviour.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The one lineup control moved a programme's start, which rule 4 refuses as well
as rule 3, so it did not show that rule 3 holds on its own. Four signed lineups
now each break one rule alone: another schedule root, a programme that begins
inside an entry, a programme of two assets, an asset no programme airs. The
second implementation drops each rule as a check of its own, and the corpus
catches each.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai: the corpus's SCTE-35 sections, five bytes of pts_adjustment
Some checks failed
wai-pack / wai-pack · macos (pull_request) Successful in 4m18s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m7s
wai-quantum docs, course and locales / the course and the command line's languages · linux (pull_request) Successful in 5m2s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 4m26s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 12m22s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 12m53s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 8m14s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 10m35s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 13m37s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m25s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m57s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 12m12s
WAI conformance / cargo-class corpora · macos (pull_request) Failing after 15m22s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 15m0s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m2s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m7s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 13m26s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 17s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 19m6s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m43s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m33s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 7m49s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 11m10s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 16m14s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 11m0s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m52s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 11m38s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m31s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 25m3s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h7m0s
b929c31aec
The generator wrote four bytes where splice_info_section() has five (the
encryption bits and the 33-bit pts_adjustment), so splice_command_type fell on
byte 12 and every cue took the hashed cue_id: the splice_event_id path of §4.8
was never reached, and both implementations agreed on the wrong bytes. A
falsification that broke that path showed it. The sections now have the layout
of SCTE 35-1 §9.6, and a unit test reads §14.2's splice_insert() and §14.1's
time_signal() samples: 0x4800008F, and the break id's hash.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both sides kept in CHANGELOG, SPEC §5, catalogue.rs, dx/mod.rs, tests/cli_ops.rs and the
two workflows; WAI_FEATURES, the test build list and the features-alone list hold both
revenue_share and channel_lineup. The generated files (ops.json, the registry export,
vocab/v2.ttl, REGISTRY.md's table, Studio's actions) are regenerated from the merged
sources, not merged as text. wai_video_channel.rs is main's: signing_payload stays private
and this branch calls its public payload(). The channel lineup's --dry-run sample writes
its own key file, as the revenue share's writes operator.key in the same directory.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
channel_lineup's own receipt_to_json and receipt_from_json are gone: the import
writes a receipt with ChannelReceipt::to_json and a verification reads one with
ChannelReceipt::from_json, the one JSON form of a channel receipt. channel-lineup
§5 keeps its number and is now a normative reference to revenue-share §4.1 (the
carriage), §4.2 (leaves, root, signed bytes, identity) and §4.3 (rules 1 to 5, the
signature rule 6). channel_lineup_verify.py reads receipts with
revenue_share_verify.py's read_run, run_payload, run_identity and run_verifies,
and no longer takes anything from live_ads_verify.py.

Before the pair was removed, a test (not kept) ran both readers and both writers
over every corpus receipt: the three receipt files, the two receipts verification
vectors edit, and the sample sealed with each energy class: 9 receipts, 8 read and
1 refused by both, every reading, every JSON value and every file identical. After
it, the corpus regenerates byte for byte.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai: channel-lineup, spans written in words
Some checks failed
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m18s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m27s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 10m39s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m11s
wai-fleet service / service · macos (pull_request) Successful in 41s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m23s
wai-ledger service / service · macos (pull_request) Successful in 1m4s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 16m5s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 18m37s
WAI energy receipts / energy receipts · linux (pull_request) Failing after 18m35s
wai-pack / wai-pack · macos (pull_request) Successful in 3m36s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 11m3s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 16m15s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 11m51s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 4m35s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 13m42s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 8m10s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 10m36s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 19m32s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m35s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 9m21s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 6m5s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 24m8s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 27s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m25s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 11m22s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m28s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 10m56s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m22s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h2m25s
88deef4675
The section-reference check pairs a bare [ with the next link, and §5 now links to
revenue-share, so an interval written [a, b) before it read as a link's text. Each
span is written from its start to its end instead; the meaning is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
# Conflicts:
#	.github/workflows/wai-conformance.yml
#	wai/wai-rs/src/catalogue.rs
#	wai/wai-studio/src/actions.generated.js
wai channel: no dead code or unused import in a build without channel_lineup
Some checks failed
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 2m5s
WAI energy receipts / energy receipts · linux (pull_request) Failing after 9m24s
wai-pack / wai-pack · linux (pull_request) Successful in 3m18s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 9m35s
wai-fleet service / service · macos (pull_request) Successful in 48s
wai-ledger service / service · macos (pull_request) Successful in 1m4s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m0s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 13m3s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m5s
wai-pack / wai-pack · macos (pull_request) Successful in 2m24s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 17m54s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 4m24s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m59s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 10m48s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 14m45s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 2m11s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m6s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 23m55s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 21s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 5m12s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 14m42s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m24s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 16m53s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 11m36s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m26s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m42s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 6m45s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 7m41s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 11m31s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h1m23s
cc2c7ead70
done() is called only by the feature's operations, as io_fail and the other
helpers are, and EXIT_FAILED and json! only by them: the helper takes the
same allow as its neighbours, and the two imports come in with the feature,
as in the opportunity report's door.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Merge remote-tracking branch 'origin/main' into wai/fast-channel-guide
Some checks failed
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m19s
wai-pack / wai-pack · linux (pull_request) Successful in 4m22s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 2m11s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 3m0s
wai-pack / wai-pack · macos (pull_request) Successful in 3m14s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 9m46s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 8m1s
WAI energy receipts / energy receipts · linux (pull_request) Failing after 10m22s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 5m26s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 6m8s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 13m24s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m59s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 24s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 4m37s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 19m12s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 5m13s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m34s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m49s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 10m16s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 21m3s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m25s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 23m35s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 7m2s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 18m27s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 10m47s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 9m39s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 24m44s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 26m29s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 41m42s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 58m53s
31d4b23b8d
Merge remote-tracking branch 'origin/main' into wai/fast-channel-guide
All checks were successful
WAI examples / WAI examples · portable · linux (pull_request) Successful in 10m6s
wai-fleet service / service · macos (pull_request) Successful in 45s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 11m12s
wai-ledger service / service · macos (pull_request) Successful in 53s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 9m8s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m2s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 6m2s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m3s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 15m52s
wai-pack / wai-pack · macos (pull_request) Successful in 2m22s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 18m2s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 12m35s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 4m43s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 9m47s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 14m43s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 5m19s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 11m10s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m45s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 13m44s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m54s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 20m9s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 22m9s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 35s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m29s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m32s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 7m19s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 6m54s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 23m35s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 16m43s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h0m32s
db2147c2d8
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!540
No description provided.