packaging §5.8: a package leads with its video component and carries beside it up to seven more on one presentation timeline, each cut at the lead's piece starts and each piece one object of the capability that suits it: audio as FLAC from a WAV, a score with a FLAC floor of its mixdown, vector graphics (wai.graphics.vector), timed text (wai.text.timed, each piece the WebVTT segment of its span, its target naming its language) and a feed (wai.feed.state, each piece sealed by the package's key and starting from the state the one before seals). Every decode-equivalent base states its piece's decoded-output digest in the stage index the receipt signs: the SHA-256 of interleaved s16le samples for audio and a score's mixdown, the clip digest of the overlay's RGBA8P frames for graphics, the SHA-256 of the segment its cues write back to for text. wai-pack packs, lists, signs and verifies them, and refuses by name what it does not pack. The policy takes the media graphics and text and a text component's lang; the stage index the media classes 7 and 8. wai.graphics.vector is read as its pending registration states and wai.text.timed, a record, as a text component's base whose payload is a segment, each with no licence class. wai-rs adds codecs::audio::flac_encode_i16 and flac_decode_i16, FLAC of 16-bit mono or stereo samples in pure Rust (feature flac); the mono f32 encoder is unchanged. pack-conformance/multi/: three goldens and multi_verify.py, which recomputes every digest and payload from the sources. The composing sink's reference package (wai-web/compose/package/, browser-sink §14) is now wai-pack's, from compose/policy.toml, the fixture compose-01, committed sources and a supplied AV1 floor, held byte for byte by the corpus check, which also writes the forged receipt; wai-compose-package, its own policy schema and native.json are gone. The page plays each component piece by piece and holds every overlay piece and caption segment to its signed digest too; run.mjs exits non-zero on any failure, page error, missing engine or missing check. Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.9 KiB
WAI Extension: State-Feeds
Status: Draft. Phase 3 of the cargo roadmap. State as instructions: ship a signed op log of typed-field updates — a scoreboard, a telemetry stream, a market tape — not a recorded video of a dashboard. A state-feed is a non-physics world, so conformance is replay-equivalence, reused wholesale from interactive-worlds. Reference impl: the
worldfeature ofwai-rs(simwai.world.sim.feed0); corpus:feed-conformance/; live sink: wai.transaction.science/feed. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.
1. Scope and model
A wai.feed.state object is a non-physics world: the same WWLD
container, op log, canonical ordering, causality, sealing, state hash,
and receipt chain as interactive-worlds (see interactive-worlds.md),
with one difference — the simulation step is the identity. Nothing is
integrated; state changes only when a signed op applies a typed-field
update. It is lever 3 (instructions-at-the-sink) for live state: a
scoreboard update is a few signed bytes ("add 7 to field 1"), not a
frame of a broadcast.
In scope: the record/cell model, the registered feed sim
(wai.world.sim.feed0) and its mutation kinds, the broadcast profile,
and the statement that conformance is exactly worlds' replay-equivalence.
Out of scope: everything interactive-worlds already defines (it is normative here unchanged); a transport; a schema language (a declared schema is an edge-level validation/labelling layer — the floor parses self-describing cells without one).
Relationship to the core spec: a registration under interactive-worlds,
not a new container. media takes the value "feed"; the authoritative
capability is wai.feed.state, carried in a WWLD whose contract names
sim = wai.world.sim.feed0.
2. Records and cells
A node is a record: an ordered vector of self-describing typed cells. Canonical field order is index order (hence hash order). Three cell types cover scoreboards, telemetry, and market data:
| tag | type | encoding | use |
|---|---|---|---|
0x01 |
Int |
i64 LE |
scores, counts, volumes, enums, booleans |
0x02 |
Fixed |
i64 LE (Q32.32 Fx bits) |
gauges, prices, percentages |
0x03 |
Text |
u16 len + UTF-8 |
names, ticker symbols, labels |
A record body is n_cells u16 | cells…; each cell is tag u8 | payload.
Cells being self-describing is deliberate: the canonical state bytes —
and therefore the state hash — parse with no external schema, so the
determinism contract has no schema dependency.
3. The feed sim — wai.world.sim.feed0
Registers these mutation kinds (a field-update kind carries a
field_idx u16 prefix). The step is the identity.
| kind | payload | resolution | effect |
|---|---|---|---|
0x0001 CREATE |
record body | LWW | insert; target MUST equal mint_node_id(actor, lamport) |
0x0002 DELETE |
(empty) | LWW | remove the node |
0x0010 SET_CELL |
field_idx u16 | cell |
LWW | replace one cell |
0x0011 ADD_INT |
field_idx u16 | i64 |
SUM | add to an Int cell (saturating) |
0x0012 ADD_FIXED |
field_idx u16 | i64 Fx bits |
SUM | add to a Fixed cell (saturating) |
An op targeting an absent node, an out-of-range index, or a wrong-typed cell is a deterministic no-op (an op set MUST mean the same thing on every sink — interactive-worlds §6.4). LWW rides the canonical total order for free; SUM kinds accumulate, and because every op within a tick applies in canonical order, the result is deterministic regardless of arrival.
4. Conformance — replay-equivalence
Given the same feed container and the same signed op set, a conforming sink MUST compute the identical BLAKE3 state hash at every checkpoint — on every machine, no tolerance parameter.
This is interactive-worlds' criterion verbatim; the feed adds no new
conformance idea. state_hash = BLAKE3("wai:world-state\x01" || canonical_state_bytes), the canonical bytes being the records in
node-id order, each as id | len | record-body.
5. Broadcast profile
The commercial shape of a feed is one authoritative publisher and
many read-only sinks ("ship state, not pixels" for sports, events,
telemetry). This is a deployment profile of wai.world.live, not a new
format: the publisher signs ops and fans them out over the same relay;
a read-only sink simply never publishes. A sink that wants a literal
picture falls back to a spectator AV1 stream of a capable participant's
render (interactive-worlds §9) — presentation, never conformance. The
authoritative artifact a spectator can audit is the op log + the sealed
state hash.
6. Receipt (JWP profile)
The interactive-worlds session receipt (jwp-receipts.md) applies
unchanged: world identity over contract + tick-0 graph; the group's
objects are the op batches, Merkle-bound; one Ed25519 seal (verified as
SPEC §7 Signatures requires) over world
hash + root + checkpoints + exact signed work + carried joules_micro
(with its acquisition class as an optional signed label,
energy-measurement §2.8);
parent_receipt_hash chains a feed's seals into a timeline.
In a package (packaging §5, Components beside the lead), a feed is cut at the lead's piece starts:
each piece a sealed WWLD of the state at its start and the signed ops of its ticks, sealed
by the package's key, each piece's graph the state the piece before it seals.
Appendix
A state-feed is the minimal world: drop the physics and you are left with exactly the part of interactive-worlds that was always doing the load-bearing work — a signed, canonically-ordered, content-addressed, sealed-and-receipted log that every sink replays to the same state. That the same machinery covers a multiplayer game and a stock ticker is the point: the cargo class is "any live state worth auditing", and the verification is identical to sight (worlds), sound (mixdown), and touch (sample).