open-standards/wai/CHANGELOG.md
Transaction Science 46c5688b86 wai: the WAI open standard — full cargo-class surface + provenance
Commit the WAI standard source: a content + capability-dispatch standard
whose thesis is "carries whatever it can reconstruct, verifies whatever
it carries." Source only — large vendored/model assets and build output
are gitignored.

Reconstruct classes (each: spec + conformance corpus + in-tab browser
sink that re-derives the corpus hash, one wai.det.fixed64 fixed-point
floor, one *-equivalence apiece):
  - interactive worlds  (replay-equivalence)   + 3 sim registrants,
    multiplayer over a relay, session receipts, glTF + real SPZ assets
  - spatial audio        (mixdown-equivalence)
  - haptics              (sample-equivalence)
  - state-feeds          (replay-equivalence, non-physics sim)
  - avatars / digital humans (pose-equivalence) + telepresence over the relay
  - volumetric / 4D splats   (frame-state-equivalence) + WebGPU EWA render,
    real-SPZ-derived clip

Verify half (lever 4):
  - asset provenance: a signed, energy-accounted lineage for opaque
    captured content WAI does not reconstruct; tamper-evident, in-tab.

Cross-cutting: JWP receipt profiles per class; a native energy meter
(IOReport via macmon, no sudo) emitting receipts with REAL measured
joules; the learned-image/neural codec family and JPEG AI entropy port
from earlier work.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-13 22:28:51 -04:00

42 KiB
Raw Permalink Blame History

WAI — changelog

Notable changes to the WAI standard and the reference implementation. Newest at the top. WAI is a draft standard; until v1.0 freezes, the wire format may change and such changes are recorded here.

v0.4.0 — current

Asset provenance — wai.asset.provenance, LIVE at /provenance (2026-06-13)

  • Lever 4 — the "verifies whatever it carries" half. For content that cannot be reduced to instructions (a photo, a recording), WAI does not reconstruct — it carries the opaque bytes content-addressed and attaches a signed, energy-accounted lineage. AssetReceipt (provenance.rs, provenance feature): a JWP group whose objects are processing steps (op + input/output content hash + work + measured joules), Merkle-bound, Ed25519-signed, with chain-linkage verification (each step's input = the previous output, final output = the asset hash) and parent_receipt_hash chaining. from_json so a verifying sink can re-parse it.
  • wai_prov tool: synthesizes a real image, builds a 3-step lineage (origin → PNG master → published JPEG) with the real measured CPU energy of each encode (IOReport via macmon, no sudo), wraps the JPEG as a content-addressed wai.image.jpeg envelope, and emits the signed receipt (origin 0 + PNG 0.43 J + JPEG 0.14 J = 0.57 J measured).
  • Browser sink — AssetProvenance (wai-web) + /provenance demo, LIVE: recomputes the asset's content hash in-tab and compares to the receipt (tamper-evidence — a "corrupt one byte" button flips it red), verifies the Ed25519 signature + Merkle chain, shows the energy- accounted lineage, and hands the carried JPEG to a native <img> (the browser decodes it; WAI does not). wasm pkg uniquely named wai_prov.
  • Spec PROMOTED to extensions/provenance.md (site mirror). It is a receipt profile about a carried asset (like jwp-receipts), not a §5 payload codec — the asset keeps its own capability (wai.image.jpeg). Completes the thesis: carries whatever it can reconstruct, verifies whatever it carries.

Cargo-class polish wave — real cloud, EWA render, receipts, telepresence (2026-06-13)

Four follow-on builds across the new cargo classes:

  • Real-SPZ-derived 4D clip (wai-spz-gen 4d): the bloom clip animates 1200 genuine Niantic-SPZ Gaussians (the same cloud the static wai.splat.spz asset ships, round-tripped through the SPZ library) — real cloud, authored motion. LIVE on /volumetric. Honest framing: the win is a verifiable per-frame state, not capture fidelity.
  • WebGPU EWA render on /volumetric: the page now renders the reconstructed cloud with a real anisotropic EWA splat pipeline (the same one the worlds demo uses) — per-Gaussian covariance projection, conic, 3σ bounding quad, premultiplied blend, back-to-front sort — with a 2D alpha-disc fallback where WebGPU is unavailable. The hash-verify badge is render-independent. Confirmed on WebGPU (Chrome) + 2D fallback.
  • Per-class receipts with measured joules: HapticReceipt (haptic/receipt.rs) + Splat4dReceipt (splat4d/receipt.rs) — the worlds/audio JWP receipt profile transposed to touch (per-channel blocks) and volumetric (per-frame blocks), reusing world::receipt:: merkle_root. New wai_meter bin measures real CPU energy (IOReport via macmon, no sudo) for haptic/splat4d reconstruction and emits a signed, self-verified receipt carrying the measured joules_micro; wai_world_meter now also dispatches feed0/skeletal0, so feed and avatar worlds get the same measured SessionReceipt. Every cargo class now has a measured-energy receipt path (haptic 57 µJ, splat4d 0.21 J for 1200 Gaussians × 17 frames, feed/avatar mJ-scale).
  • Avatar telepresence — LIVE at /telepresence: a live skeletal world of N avatars over the existing worlds relay. New SkeletalActor (wasm) signs CREATE + SET_ROTATION CausalOps; the worlds transport (relay-first + BroadcastChannel fallback, hello/sync/op/hash, boundary-hash convergence) is reused verbatim. Each tab creates and animates its own arm rig; sinks converge on the pose hash ("poses agree @ tick N"). Verified on prod through the real relay with two isolated contexts — identical pose hashes, zero errors.

Volumetric / 4D splats — wai.splat.4d, LIVE at /volumetric (2026-06-13)

  • Phase 5 complete — the roadmap frontier. A wai.splat.4d is a temporal Gaussian splat: the static splat extended to time. Each Gaussian carries a keyframed track (position / scale / rotation / color / opacity); the sink interpolates the cloud at frame N in the wai.det.fixed64 floor. Conformance is frame-state-equivalence: the reconstructed Gaussian set at frame N hashes identically on every sink, no tolerance — the temporal counterpart of the static splat.
  • wai-rs splat4d feature (reuses the world Fx floor + blake3, no codec/ML deps): the W4DS container (contract + per-Gaussian keyframe tracks, 14 Fx per key) + a deterministic reconstruct (Fx linear interpolation, hold outside the track). Trig-free (quaternions interpolate component-wise; the sink normalizes for rendering). frame_hash = the frame-state-equivalence quantity; clip_hash = frame-independent identity. Registered + tiered Lossy (consistent with wai.splat.spz — the splat representation approximates the captured scene, even though the reconstruction is frame-state-exact).
  • volumetric-conformance/ corpus + wai_splat4d_vectors gen|verify: orbit (two Gaussians swap places), pulse (scale + fade), morph (color shift) — every frame's hash checked, all pass.
  • Browser sink — Splat4dSink (wai-web) + /volumetric demo page, LIVE: reconstructs the cloud in-tab and verifies every frame's hash against the corpus; a frame scrubber re-derives the cloud, drawn as painter-sorted alpha Gaussians (a sink with WebGPU renders the same set with the full EWA pipeline — presentation). wasm pkg uniquely named wai_splat4d.
  • Spec PROMOTED to extensions/volumetric.md (site mirror), registered in SPEC.md §5 (wai.splat.4d). Honest about size: the win is content-addressing + dedup + a verifiable per-frame state, NOT payload reduction (a real cloud is MB-scale) — stated plainly.
  • The cargo set is complete across the medium: sight (worlds/replay), hearing (audio/mixdown), touch (haptics/sample), live state (feed/replay), a moving body (avatar/pose), and now a moving volume (splat.4d/frame-state) — one wai.det.fixed64 floor, one verification.

Avatars / digital humans — wai.avatar.pose, LIVE at /avatar (2026-06-13)

  • Phase 4 complete — digital humans: motion as instructions. An avatar is a skeletal world — the worlds container/op-log/ordering/ sealing/state-hash/receipt-chain, with the step reduced to the identity. Conformance is pose-equivalence (the per-bone local transforms hash identically), a special case of replay-equivalence.
  • wai.world.sim.skeletal0 (in wai-rs world feature): a bone is a parent[16] + translation[3] + rotation-quaternion[4] + scale[3] (all wai.det.fixed64). Mutations: CREATE / DELETE / SET_ROTATION (the animation driver) / SET_TRANSLATION / SET_SCALE, all LWW. Trig-free floor: rotations are quaternions and the FK composition is + − × only; axis-angle authoring happens off-line. The forward-kinematics → world space and the skinning of a wai.mesh.glb are presentation (a pure function of the hashed pose), never in the hash. Registered + tiered Lossless; dispatched in run_sealed_dispatch.
  • avatar-conformance/ corpus + wai_avatar_vectors gen|verify: a sealed 3-bone arm wave, a sealed 5-bone humanoid pose, and three seeded adversarial-arrival shuffles of the arm wave — all converge, all pass.
  • Browser sink — SkeletalSink (wai-web) + /avatar demo page, LIVE: replays a sealed animation in-tab, re-derives the sealed pose hash (checked against the native corpus and the file's own seal), and exposes FK world-space joints + bone segments to draw the skeleton on a rotating orthographic canvas with a tick scrubber. wasm pkg uniquely named wai_avatar.
  • Spec PROMOTED to extensions/avatars.md (site mirror), registered in SPEC.md §5 (wai.avatar.pose). A moving body joins sight (worlds), sound (audio), touch (haptics), and live state (feeds) under one floor.

State-feeds — wai.feed.state, LIVE at /feed (2026-06-13)

  • Phase 3 complete — live state-feeds: state as instructions. A feed is a non-physics world — the same WWLD container, op log, canonical ordering, sealing, state hash, and receipt chain as interactive-worlds, with the simulation step reduced to the identity. Conformance is therefore replay-equivalence, reused wholesale: no new criterion.
  • wai.world.sim.feed0 (in wai-rs world feature): nodes are records of self-describing typed cells (Int i64, Fixed Q32.32, Text UTF-8 — hashed without a schema). Mutations: CREATE / DELETE / SET_CELL (LWW) and ADD_INT / ADD_FIXED (SUM — commutative accumulation). Wrong-typed / out-of-range / absent-node updates are deterministic no-ops. Registered + tiered Lossless in the central codecs registry; dispatched in run_sealed_dispatch.
  • feed-conformance/ corpus + wai_feed_vectors gen|verify: sealed scoreboard (SUM scoring + an LWW correction), telemetry (LWW gauge + SUM packet count, incl. a negative ADD_FIXED), market tape (LWW last + SUM volume), and three seeded adversarial-arrival shuffles of the scoreboard — all converge, all pass (hash equality).
  • Browser sink — FeedSink (wai-web) + /feed demo page, LIVE: loads a sealed feed, replays it in-tab with the same engine that made the corpus, and re-derives the publisher's sealed BLAKE3 state hash (the file's seal also equals the native corpus hash — both checked). A tick scrubber re-derives the feed at any tick; the record table renders the typed cells generically. wasm pkg uniquely named wai_feed (avoids the deploy fingerprinter's basename collision).
  • Spec PROMOTED to extensions/state-feeds.md (site mirror), registered in SPEC.md §5 (wai.feed.state). The broadcast profile (one authoritative publisher, many read-only sinks) is documented as a deployment shape of wai.world.live, not a new format. State joins sight (worlds/replay), hearing (audio/mixdown), and touch (haptics/sample) under one floor — verified the same way.

Interactive worlds — world feature + conformance corpus (2026-06-11)

  • New cargo class implemented: the interactive-worlds extension (spec draft staged in wai-transaction-science-web/research/, destined for extensions/interactive-worlds.md). Media that consumes input: a world is a content-addressed artifact, every event is a signed CausalOp, and conformance is replay-equivalence — identical BLAKE3 state hash at every checkpoint, no tolerance parameter. One container (WWLD) serves wai.world.scene / wai.world.replay / wai.world.live, differing only in op-log seal state; an input log and a multiplayer op log are the same object.
  • wai-rs world feature (pure Rust, no ML dep chain; deps: blake3 + ed25519-dalek): Fx Q32.32 fixed-point (wai.det.fixed64, the floor profile — bit-exact unconditionally), xoshiro256++ contract rng, signed/dep-gated ops with canonical (effect_tick, lamport, actor) ordering, coordination-free BLAKE3 node minting, WWLD section container with content-binding seal, Sim trait (the extension standardizes the contract, not a physics engine) + kinematic0 reference registrant, sealed Replayer + LiveWorld engines (buffering, past-tick re-derivation, equivocation rejection, receipted-checkpoint history sealing).
  • world-conformance/ corpus + wai_world_vectors gen|verify: sealed replays, LWW/SUM conflict batteries, dep-gap / past-tick / shuffled-arrival live streams, expected hashes. All vectors pass; clippy clean on the new code.
  • Spec PROMOTED to extensions/interactive-worlds.md (site mirror src/pages/extensions/), registered in SPEC.md §5: wai.world.scene / wai.world.replay / wai.world.live + asset media wai.mesh.glb (canonical glTF 2.0 Binary, Khronos — decoder sink/library-supplied); media: "world" noted in §3. Capability strings live in the central codecs registry (known_capabilities()), tiered Lossless — replay-equivalence is exact state reproduction, the simulation analog of lossless.
  • Second sim registrant wai.world.sim.ballistic0 (gravity + ground-plane bounce, per-node radius/restitution, G = −10, all Q32.32 — bit-exact through every bounce) proving the registration story: entered registry, dispatch, and corpus (ballistic_bounce vector) without one line of the extension changing. New run_sealed_dispatch routes on contract.sim; a missing sim reports the world inert (UnknownSimCapability), mirroring SPEC.md §4 step-6 semantics so callers can fall back per the envelope.
  • Native energy meter — measured joules, no sudo (2026-06-13): corrected a wrong assumption that real energy needed RAPL/sudo (unavailable on the arm64 prod box). On Apple Silicon the SoC energy counters are readable through IOReport with no privileges (the source macmon/asitop use; verified euid≠0 reads CPU/GPU/ANE power on the M3 Ultra), and proc_pid_rusage gives exact per-process retired cycles/instructions. New wai_world_meter bin (world feature): brackets a tight replay burst of a sealed .wwld against an idle baseline, samples CPU power via macmon, and reports the marginal measured CPU energy — e.g. the truss replay metered at ~512 µJ / replay (~4.3 µJ/tick) at 3.2 W marginal, a real number that fills a receipt's joules_micro where a native sink runs. The burst runs on N threads so the marginal draw clears a shared box's idle fluctuation (single-thread 512 µJ vs 10-thread 524 µJ/replay cross-validates the method — per-replay energy is invariant to parallelism). With a second arg the meter emits a full §8 SessionReceipt carrying the MEASURED joules + exact work_steps, signed and self-verified — real measured energy end to end. Spec §8 + the /worlds page corrected: the sink-metering path needs no sudo (IOReport on Apple Silicon, RAPL on x86); the browser estimate is the fallback, not the ceiling. clippy clean, 94 tests green.
  • Phase 2 begun — haptics (wai.haptic.signal) (2026-06-13): touch as instructions. Spec drafted (research/haptics-draft.md), capability registered + tiered. wai-rs haptic feature (reuses the world Fx floor, no codec/ML deps): the WHAP container + a deterministic reconstruct — per channel, a keyframed intensity/sharpness envelope (the Core-Haptics pair every actuator API maps to) linear-interpolated in Fx and quantized to u8. Trig-free by construction (amplitude + sharpness, not a modulated carrier), so the floor reconstructs it exactly with +,−,×,÷ alone. signal_hash is the sample-equivalence quantity. wai_haptic_vectors gen|verify + haptic-conformance/ (ramp, thud, dual-rumble pulse) — all pass, hash equality. 104 tests, clippy clean. Next: Gamepad/Vibration browser sink + /haptics demo, then promote. This completes the sight → hearing → touch trio's engines.
  • Spatial-audio: receipt profile + spec PROMOTED (2026-06-13) — Phase 1 complete. audio_scene::SceneReceipt (the worlds receipt transposed to audio): identity scene_hash, the JWP group's objects are the mix's PCM blocks (BLAKE3("wai:audio-block")), Merkle-bound with JWP's exact domains, one Ed25519 sig over scene_hash + root + blocks + work_mac (samples × objects, exact signed) + carried joules_micro; parent_receipt_hash chains renders. Reuses world::receipt::merkle_root — minimal new code. 2 receipt tests (101 total). Draft promoted to extensions/spatial-audio.md (+ site mirror, SPEC §5 row + extension pointer) — and the canonical spec corrected to the as-built sqrt_constpower pan (sqrt-only, no transcendental tables) and the real receipt shape, since registration froze the format. clippy clean; spec page live. Phase 1 (spatial audio) DONE: spec · register · mixer · corpus · live /audio sink · receipt · promoted. Next: Phase 2 — haptics.
  • Spatial-audio browser sink — LIVE at /audio (2026-06-13): wai-web AudioSink (wasm-bindgen): parse WSCN, load the corpus sources, run the exact deterministic mixdown, expose mixdown_hash_hex + scene_hash_hex + mix (i16 PCM) + object_xz(t). The /audio page (site-styled, in nav) loads a scene, verifies the mixdown hash in-browser against the corpus (mixdown-equivalence, the same proof worlds does for state), plays the bit-exact stereo mix via an AudioBuffer, and shows a top-down radar of the objects panning. Proven on prod: all three scenes verify, zero errors — wasm-in-Chrome mixes byte-identically to native. Honest split kept: plays the exact stereo floor; binaural/HRTF noted as the richer optional presentation.
  • Spatial-audio conformance corpus (2026-06-13): wai_audio_vectors gen|verify + audio-conformance/ — the mixdown-equivalence analog of the worlds corpus. Three vectors (static stereo pair, distance near/far, keyframed left→right sweep) ship a .wscn scene + a .sources.bin (decoded mono tones) + expected scene_hash and mixdown_hash; verify mixes each and checks hash equality, no tolerance. All pass; clippy clean.
  • Spatial-audio reference mixer — mixdown-equivalence (2026-06-13): wai-rs audio_scene feature (reuses the world Fx floor + blake3, no codec/ML deps): the WSCN container (scene contract + object table
    • asset table + optional seal, mirrors WWLD) and a fully deterministic mixdown — Fx position interpolation, inverse_clamped distance attenuation, sqrt_constpower pan (sqrt only, no transcendental tables), Fx accumulate, round-half-away i16 quantization in integer space. mixdown_hash (BLAKE3 over canonical i16LE PCM for a declared layout) is the mixdown-equivalence quantity; scene_hash is the identity. 5 tests prove it: centered = equal L/R, hard-left = silent right, deterministic + layout-bound hash, distance attenuates, a moving source sweeps L→R + container round-trips. Sources arrive as decoded mono PCM keyed by content hash — decoding the wai.audio.* assets is the sink's job. clippy clean. Next: conformance corpus bin + Web Audio browser sink + demo.
  • Content taxonomy + cargo roadmap; spatial-audio Phase 1 begun (2026-06-13): mapped the full space of web-transported content WAI's approach covers (research/content-taxonomy.md) — a capture→synthesizable→executable→ symbolic spectrum × four levers (codec dispatch, neural prior, instructions-at-sink, determinism+receipts), with a per-row mechanism/extension/status table and the white space called out. A phased build plan (research/cargo-roadmap.md) takes each white-space class through the proven interactive-worlds recipe. Phase 1 kicked off — object-based spatial audio (wai.audio.scene): the audio analog of interactive-worlds (ship sound objects + a scene, render to the sink's layout; mixdown-equivalence = replay-equivalence with the tick replaced by the audio sample). Spec drafted (research/spatial-audio-draft.md, WSCN container, Fx mixdown, content-addressed wai.audio.* sources, stereo bit-exact floor + binaural perceptual tier, WAI2 recorded-mix fallback, JWP receipt profile); wai.audio.scene registered + tiered Lossless. 94 tests green. Remaining phases: haptics, live state-feeds, digital humans, volumetric/4D splats.
  • Real SPZ decode — wai.splat.spz end to end (2026-06-13): the splat gallery now renders a genuine Niantic-SPZ file, not a mesh-derived stand-in. New wai-spz-gen crate depends on the field's spz reference library (the sink-supplied codec WAI dispatches to), encodes a 2,400-Gaussian cube cloud to a real .spz (validated by re-loading through the library), and wraps it as a content-addressed wai.splat.spz WAI object (nebula.spz.wai). gen-gallery adds it to the scene's asset table (role 1) beside the glb. Browser: WorldSink.asset_payload(name, env, cap) generalizes the §4.1 verify to any capability; the page gunzips (DecompressionStream) and decodes the SPZ bitstream in-tab — 16-byte header, non-interleaved arrays, 24-bit fixed-point positions, log scales, smallest-three quaternions, byte/255 opacity+color — into per-Gaussian world covariance for the EWA pipeline. Decoded count matches the encoded 2,400 (validates the layout); the cube silhouette + surface-aligned discs validate the quaternion math. Page copy corrected: the splat view decodes a real SPZ asset (no longer "derived from mesh"). Verified locally (2,400 Gaussians, zero errors); prod serves the identical artifacts.
  • Anisotropic EWA splatting (2026-06-13): upgraded the splat renderer from isotropic billboards to real 3D Gaussian splatting. Each splat carries an anisotropic 3×3 covariance (surface-aligned flat discs: wide in the triangle tangent plane, thin along the normal); the vertex shader projects it to a screen-space conic (Σ' = J·W·Σ·Wᵀ·Jᵀ with the perspective Jacobian), emits a tight 3σ bounding quad, and the fragment evaluates the conic — the textbook 3DGS pipeline, still CPU-sorted back-to-front and alpha-blended. Cam uniform carries view + proj separately (+ viewport/focal) for the Jacobian. Visibly sharper, surface-coherent splats; proven on prod, zero errors.
  • 3D render layer — PBR mesh + Gaussian splats (2026-06-13): the /worlds gallery now renders the content-addressed, hash-verified wai.mesh.glb two ways in a real 3D path (perspective camera + depth buffer, all in wai-web/demo/world.js, no wasm change): a solid PBR-shaded cube (flat normals from screen-space derivatives, Lambert
    • spec + sky-ambient, gamma) and a Gaussian-splat cloud — instanced camera-facing quads with a Gaussian falloff, back-to-front depth-sorted each frame (painter's order) and alpha-blended. The splat cloud is derived from the same verified mesh, making the thesis visible: one content-addressed asset, two sink-side renderings, presentation never touches the state hash. SPZ binary decode stays sink-supplied (stated honestly on the page); the renderer is the real deliverable. Two gallery vectors (gallery / gallery_splat); the 2D sim path is untouched. Proven on prod: both render, 768 splats from the cube, zero errors.
  • Receipt chaining + work-meter + wai.splat.spz (2026-06-12): three follow-ons. (1) SessionReceipt gains parent_receipt_hash (BLAKE3 of the prior receipt's canonical bytes — the JWP linkage) + receipt_hash() + verify_chain: successive sealed sessions of one world (shared world_hash, group_id+1) form an append-only signed timeline. (2) An honest energy meter: receipts carry exact, signed, deterministic work_steps (Σ node-steps, from collect_checkpoints_and_work) AND a separately carried joules_micro — never derived in the receipt; the browser supplies a wall-clock estimate at a declared coefficient (labeled "est@4W"), native sinks supply real RAPL, an unmetered sink signs 0. (3) Registered wai.splat.spz — Gaussian-splat scenes as an asset capability parallel to wai.mesh.glb (presentation only, never in the state hash; the win is content-addressing + dedup, not payload size; renderer sink-supplied). Browser seal_session(seed, id, joules, group, parent) chains via localStorage; the /worlds HUD shows chain #N ↳linked · N steps · ≈X mJ est@4W · ✓ re-verified. Proven on prod: two seals chain (g0 parent null → g1 parent = g0.receipt_hash), exact work 248 steps, est joules carried, zero errors. Spec §8 updated (chaining + the two-quantity energy model). 94 native tests, 10/10 vectors, clippy clean.
  • Asset path SHIPPED — wai.mesh.glb, content-addressed (2026-06-12, extension §4.1): worlds are made of WAI objects. New world::asset_content_hash (BLAKE3 wai:asset\x01 over a complete WAI envelope) + DOMAIN_ASSET; native tests PROVE the load-bearing claim — a scene with an asset table has the byte-identical state hash AND world hash as the same scene without it (assets are presentation-only, never in the state hash), and the asset hash binds the exact envelope. Generator gen-gallery writes a gallery.wwld scene + assets/cube.glb.wai: a real glTF 2.0 Binary cube (hand-written GLB writer) wrapped as a wai.mesh.glb WAI envelope and content-addressed in the table. Browser: WorldSink.assets() + asset_glb(name, envelope) (verifies content hash in WASM, rejects a mismatch, unwraps the WAI envelope to the .glb payload); the page decodes the GLB (minimal JS decoder) and renders the verified mesh as a spinning wireframe. Proven on prod: 1/1 verified ✓ · cube.glb, and the state hash stays fixed while the mesh spins — §4.1 made visible. 92 native tests, 10/10 vectors, clippy clean.
  • Session receipts + seal-to-replay SHIPPED (2026-06-12, extension §8 implemented): world/receipt.rs builds a SessionReceipt — a JWP profile, not a fork: op batches (one per checkpoint interval, content-hashed wai:world-ops\x01) are Merkle-bound with JWP's exact leaf/node domain separators, and one Ed25519 signature covers the world-profile payload (world hash + checkpoint state_hash list + carried microjoules). Joules are carried, never fabricated — the builder takes the figure; an unmetered session signs 0 and says so. New world_hash (BLAKE3 over scene = contract + tick-0 graph, the §7.4 shareable identity), collect_checkpoints (unsealed replay → checkpoint list). Browser: WorldSink.seal_session(seed, signer_id, joules) → SealedSession{replay_bytes, receipt_json, root_hash, …}; the /worlds page's "⏷ seal & download replay" turns a live, shared, edited world into a portable .wwld + .receipt.json, re-opens the fresh replay in a throwaway sink to prove it re-verifies, and shows the Merkle root + batch count in the HUD. Proven on prod: fracture a tower across the relay → seal → 3-batch receipt, valid sig, replay re-verified. 90 native tests, 10/10 vectors, clippy clean.
  • Cross-device multiplayer SHIPPED (2026-06-12, wai-relay/ + wai-web Actor binding): every tab/device is a signed actor. New Actor wasm-bindgen class (browser-held Ed25519 key; clicks author real CausalOps; Lamport discipline via observe_lamport); wai-world-relay reference transport (axum WS, per-room fan-out, retains the signed op log for late joiners, verifies every op's Ed25519 signature at the door with the same wai crate — it adjudicates nothing; sinks converge because the math does). Page transport is relay-first (room in the URL hash) with BroadcastChannel fallback. Deployed at wai.transaction.science/worlds-ws/* (launchd com.wai.world-relay, localhost:9670). Proven on prod with two ISOLATED browser contexts: point-blank axial shoves snap two members (23→21 nodes) and both contexts converge — "✓ hashes agree". Also fixed build.rs emitting libFLAC link flags regardless of features (pkg-config probe side effect): now gated on codecs.
  • Browser sink SHIPPED (2026-06-12, wai-web/src/world.rs + wai-web/demo/world.{html,js}): a wai.world.replay sink in a tab. NOT a port — the wai crate itself now compiles to wasm32 via the new default-on codecs feature (C codec chain gated; envelope + world engine build with --no-default-features --features world), and wai-web binds it (WorldSink: advance/particles/members/ state-hash/verify-seal; sim state stays exact Q32.32, f32 only for display). WebGPU renderer (instanced SDF circles + member lines). Proven in real Chrome via Playwright: the 1,282-byte truss_fracture payload replays 120 ticks, the member snaps, and the browser's BLAKE3 state hash equals the native corpus hash byte-for-byte — replay-equivalence across arm64-native and wasm32-in-Chrome, demonstrated, with the Ed25519 seal verified in-page.
  • Solver-backed registrant wai.world.sim.truss0 (2026-06-12, world/truss.rs): structural simulation — particles + distance members solved per tick by position-based dynamics (fixed 8-pass Gauss–Seidel projection in canonical member order), entirely in wai.det.fixed64 including a new floor-rounded Fx::sqrt (128-bit integer Newton). Members carry a yield strain measured on predicted positions before the solve; an overloaded member fractures as an emergent solver consequence — two actors pulling the same member in opposite directions (the SUM rule feeding the solver) snap it bit-identically on every machine (truss_fracture corpus vector). Registration constants: G = −10, ITERATIONS = 8, ground at y = 0, velocity damping 63/64/tick (static equilibrium). LiveWorld gained state()/current_tick() accessors (what a renderer reads). Where the float-based CAD solvers can't transplant (floats aren't cross-platform bit-exact), solver form does: iterative constraint projection in the deterministic profile.

Inter-frame video, categorical/VQ images, and real-model validation

  • wai.neural.dcvc_rt / wai.neural.dcvc_fm — inter-frame video decoder implemented (neural/video_dcvc.rs). "Requires CUDA" was a speed claim: inter-frame decode is a frame loop that propagates a reference feature, and ONNX Runtime runs it on CPU. The per-frame entropy decode reuses the CompressAI-validated hyperprior path; the temporal net is sink-supplied. Validated end-to-end (3 inter-frames, feature propagation confirmed).
  • wai.neural.glc — categorical / VQ decoder implemented (neural/glc.rs). Not the Gaussian-conditional family: codebook indices decoded via a per-position softmax → pmf_to_quantized_cdf (bit-exact with CompressAI's C++, unit-tested) → a bypass-free categorical rANS over a checkerboard → VQ synthesis. Surfaced that categorical entropy is the most determinism-sensitive path — a per-position CDF flips on ~1e-5 logit drift where Gaussian scale buckets don't.
  • Real-model validation beyond synthetic stand-ins. SNAC's genuine snac_24khz now exports (tools/wai_snac_export.py: zero-noise so the decode is deterministic at all + a reshape-free snake) and wai-rs decodes it to ~9e-7 of the torch reference. A real PTQ-trained, activation-calibrated int_synth model decodes bit-identically (max|Δ|=0) to its integer-forward reference (tools/wai_int_synth_train.py; also fixed a zero-gradient torch.floor bug in the QAT trainer).

Learned-image codec family — decoders implemented and validated

  • The reference crate now decodes the full conditional-entropy family natively, not just the factorized baseline: wai.neural.mbt2018_mean (mean-scale hyperprior, Gaussian-conditional), wai.neural.elic (checkerboard spatial context), wai.neural.mlicpp (channel-autoregressive multi-reference), and the integer-exact wai.neural.int_synth (all-integer transposed-conv synthesis — a decode that is bit-identical on every machine by construction, the first capability that can soundly back intent=replicate cross-hardware). The rANS + entropy decode live in wai-rs; the analysis/synthesis nets are sink-supplied ONNX.
  • Current-SOTA entries added as live routes: wai.neural.mlicv2 (MLICv2/v2+, the current SOTA learned image) and wai.neural.cmic (Content-Aware Mamba) both decode through the multi-reference core — their entropy model is the same channel-slice + checkerboard structure; the gains live in their sink-supplied transforms.
  • Validation against the reference codec. bmshj2018 and mbt2018_mean are checked byte-for-byte against pretrained CompressAI models (reconstruction matches to within final-layer float rounding); elic/mlicpp are checked end-to-end against minimal CompressAI- compatible models; int_synth against a constructed integer model. Surfacing this also caught (and the spec now documents) a real determinism hazard: a learned codec's entropy decode desyncs unless the encoder and decoder compute the scale buckets with the same model — float drift between two implementations of h_s flips bucket assignments and corrupts the stream.

Audio: SNAC hierarchical codec

  • wai.neural.snac — SNAC's multi-resolution RVQ, distinct from the flat single-grid RVQ runtime: N variable-length code streams at hierarchical rates, decoded via dynamic-arity ONNX inputs. Ubiquitous in low-bitrate TTS.

Removed: off-charter Python runtime (wai-neural/)

  • Moved wai-neural/ OUT of this repo to ../../wai-neural-prototype/. It was a parallel Python runtime (WAI4 generative-semantic container + CLIP-embedding payloads + SD-XL-Turbo regeneration + CLIP-similarity conformance) — a disconnected second implementation in the wrong language. The reference implementation is Rust (wai-rs); nothing referenced the Python package. The idea it proved — a behavioral/perceptual neural path that conforms by semantic similarity rather than a weights hash — is sound and belongs in wai-rs as a future Rust path alongside the bit-exact, prior-pinned path. The Python is kept only as a prototype reference (and it hardcodes a machine-local model path, so it never ran portably). This does NOT touch the Python model-export tools in tools/, which are legitimate dev tooling.

Neural condition: working end-to-end

  • tools/wai_encodec_encode.py / wai_encodec_decode.py — first working neural capability (wai.neural.encodec32): source encodes audio via locally-installed EnCodec, ships only the quantized tokens in a standard WAI envelope (236 MB of model weights stay on the source's disk, never enter the envelope); sink with EnCodec installed decodes. Measured: 5 s of audio → 2.3 KB envelope (141× compressed), model on the wire = 0 B.
  • Rust SDK gains wai inspect CLI: parses an envelope, resolves the capability + fallback against sink_capabilities(), and prints verdict (DECODABLE via primary / via fallback / INERT here).

Browser runtime (wai-web/)

  • New crate: wasm-bindgen wrapper exposing parse(bytes) → WaiEnvelope, pack(manifest_json, payload), and known_capabilities(). 107 KB wasm + 16 KB JS glue.
  • wai-web/demo/wai.js — thin JS shim with WaiRuntime.register(cap, handler) dispatch. Backends are pluggable (browser-native APIs, transformers.js, WebGPU compute, WebNN, ONNX runtime web) — WAI doesn't bundle any. The sink-side compute fabric is heterogeneous; the deployer picks per capability.
  • wai-web/demo/index.html — drop-and-decode demo with handlers wired to: createImageBitmap for wai.image.{png,jpeg,avif,jxl}, AudioContext for wai.audio.{opus,flac}, placeholders for wai.neural.* showing where transformers.js / WebNN / WebGPU plug in. Run with python3 wai-web/demo/serve.py.
  • 4 sample .wai files in wai-web/demo/samples/ covering PNG, JXL, Opus, and EnCodec for testing.

Spec: v1.1 multi-rendition envelope (SPEC.md §6.1)

  • New magic WAI2 for envelopes that carry multiple renditions of the same content (e.g. EnCodec + Opus, or AVIF + JPEG-XL). Reframed from "graceful fallback for missing capability" to policy selection — in a self-contained ecosystem every sink has every required capability; renditions exist so the sink picks by compute budget, bandwidth, or runtime preference (browser-native vs WebGPU vs WebNN vs native ML). v1.0 (WAI1) remains valid and unchanged.

v0.3.0

Pivot: WAI is the envelope + capability-dispatch + neural-shared- prior standard. The zeroth condition is a menu of registered SOTA codec capabilities (AVIF, JPEG-XL, PNG, JPEG, Opus, FLAC, AV1, zstd, XZ), not a custom codec. The Python prototype and all hand-rolled codec implementations from v0.2.x were removed; Rust is the single reference implementation and the SDK.

Standard

  • SPEC.md rewritten as a capability-menu spec. Mandatory floor: wai.image.png, wai.audio.flac, wai.text.zstd (every conforming sink MUST decode these). Recommended modern set: wai.image.jxl, wai.image.avif, wai.image.jpeg, wai.audio.opus, wai.video.av1, wai.video.av1.lossless, wai.text.xz. Neural capabilities (wai.neural.*) remain OPTIONAL and sink-advertised.
  • Container envelope (WAI1 magic + length-prefixed manifest + length- prefixed payload) and manifest schema are unchanged from v0.2.x.
  • Conformance: bit-exact decode-equivalence with each capability's reference library (libjxl / libavif / libopus / libFLAC / rav1e / etc.).

Rust reference (wai-rs/, crate wai 0.3.0)

  • cargo build --release produces libwai.dylib/.so/.dll (cdylib), libwai.a (staticlib), and libwai.rlib (Rust-native). The crate type list is ["lib", "cdylib", "staticlib"] — drop-in for any language's C-FFI binding.
  • Codec wrappers: image (PNG, JPEG via jpeg-encoder, AVIF via ravif + libavif-image for decode, JPEG-XL via jpegxl-rs), opus (RFC 7845 Ogg-Opus container so output drops into ffmpeg/VLC/browsers), claxon+flac-bound for FLAC, rav1e+dav1d for AV1 (lossy + lossless), zstd+xz2 for text.
  • Generated C header: include/wai.h is regenerated by build.rs via cbindgen on every build. SDK consumers get a typed header rather than hand-writing extern "C" decls.
  • Cross-platform linkage: build.rs probes pkg-config for libflac; the macOS-hardcoded .cargo/config.toml from v0.2.x is gone. Builds clean on macOS (Homebrew) and Linux (apt) without RUSTFLAGS.

C FFI / SDK surface

All wai_* functions return a wai_status_t:

code meaning
WAI_OK (0) success
WAI_ERR_INVALID_ARG (1) null pointer / mismatched length / out-of-range dimension
WAI_ERR_CODEC (2) codec-level failure (details in wai_last_error())
WAI_ERR_CONTAINER (3) bad magic / truncated envelope / unparseable manifest JSON
WAI_ERR_PANIC (4) internal Rust panic caught at the boundary (a wrapper bug — never UB into the C caller)

Every FFI function is wrapped in std::panic::catch_unwind so Rust panics never unwind into C (UB). av1_decode validates header bounds to prevent libdav1d's C-level abort(). wai_last_error() is per- thread, populated on any non-OK return.

Testing

  • 13 lib tests: per-codec round-trip + envelope round-trip
  • 21 FFI robustness tests: null pointers, length mismatches, dimension overflow, malformed magic, truncated payloads, bad JSON, invalid Opus sample rates, zero fps, garbage decoder input
  • 10 fuzz smoke targets: 1024 adversarial random byte sequences per decoder asserting no panic. Stable Rust, no cargo-fuzz toolchain needed. Found and fixed a real envelope-truncation panic.
  • wai_bench corpus walker: quick mode (4 images + 4 audio + 3 text + 2 video) for spot-checks; --full walks the entire corpus (169 images + 5 audio + 13 text + 12 video sequences = 588 codec runs in ~9.4 min). Per-codec aggregate stats: runs, ok / fail counts, WAI vs reference byte sizes, PSNR delta vs ffmpeg, encode time.
  • --report file.json writes a structured bench report; wai_bench_diff baseline.json head.json flags regressions on bytes (±5% default tolerance), encode time (±25%), or new failures. Non-zero exit on regression — ready for CI gating.
  • GitHub Actions CI (.github/workflows/ci.yml): ubuntu + macOS matrix, apt/brew codec deps, cargo test --release, cdylib/staticlib artifact verification, quick bench, JSON report uploaded as artifact.

Honest codec measurements (vs ffmpeg reference, full Kodak/Tecnick/

CLIC/synthetic corpus = 169 images, plus SQAM audio + Silesia text + Derf CIF video)

codec runs size vs ref PSNR Δ vs ref notes
PNG 169 — lossless ffmpeg-interop ok
JPEG q=50 169 +12.7% +0.27 dB q-knob calibrated to libjpeg
JPEG q=80 169 +19.7% −0.31 dB residual gap is pure-Rust vs libjpeg-turbo asm
AVIF q=70 169 — — ffmpeg-interop ok
JPEG-XL lossless 169 — lossless bit-exact via libjxl
FLAC 5 −10.1% lossless WAI compression_level 8 vs ffmpeg default 5
Opus 64k 5 — — standard Ogg-Opus container, ffmpeg-interop ok
zstd-19 13 ±0.0% — byte-identical to system zstd
xz-6 13 ±0.0% — byte-identical to system xz
AV1 lossy 12 +28.3% — rav1e vs ffmpeg libsvtav1 (different encoders)

All 588 corpus runs and all 44 tests pass.

Removed

  • The Python prototype (wai/) and Python BD-rate harness (bench/). v0.2.x's hand-rolled wire format is dead; Rust is the single source of truth.
  • The webm_lottie_new/wai-rs/ pre-pivot Rust crate (Wasm-decoder-in- bundle model). Replaced by the clean wai-rs/ SOTA-wrapper crate.

v0.2.0 — superseded (historical record)

The v0.2.x direction was hand-rolling custom codec wire formats (DCT + quantization + rANS for image, MDCT for audio, I/P inter-frame for video). Two byte-interoperable reference implementations (Python + Rust) were built and cross-validated.

Why superseded: re-implementing JPEG/MPEG/Opus poorly is strictly worse than wrapping the field's SOTA libraries. WAI's actual value is the envelope + capability dispatch + the neural-shared-prior model, which v0.3 keeps. Custom codecs are gone; standard libraries are in.

What v0.2 had

  • SPEC.md defined byte-precise wire formats for image (8×8 DCT-II + YCbCr + JPEG-Q + zigzag + DC-Δ + rANS), audio (orthonormal MDCT + sine window + TDAC), video (I/P inter-frame with integer-pel motion).
  • Python (wai/) + Rust (wai-rs/) implementations, byte-equivalent on the lossless paths (rANS, container) and reconstruction-equivalent on the lossy paths.
  • Honest measured standing: image at JPEG-1992 parity (~5% behind libjpeg), audio uniform-MDCT (not perceptually competitive with MP3), video I/P at ~41% smaller than MJPEG floor but far behind H.264.

Licensing (unchanged)

  • Apache-2.0 for the standard and the reference implementation. Royalty-free implementation is a precondition for adoption (VP9/AV1 open-codec precedent; the H.264/H.265 royalty trap is avoided).