From bcef9a5671f9e514326ee8233c36a1ed3ffe5638 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 13:41:14 -0400 Subject: [PATCH 1/8] wai.media.exploration: descriptors, archives that replay, default-distance, collection statements, taste priors, rankings and picks (CO2, CO3) The extension, the wai-rs module behind the feature exploration, the corpus live-conformance/exploration/ written by wai_exploration_vectors gen, its second implementation exploration_verify.py, the CI step, and the registry, SPEC and CHANGELOG entries. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/wai-conformance.yml | 30 +- wai/CHANGELOG.md | 46 + wai/REGISTRY.md | 8 +- wai/SPEC.md | 23 +- wai/extensions/exploration.md | 817 ++++ wai/live-conformance/README.md | 16 +- wai/live-conformance/exploration/README.md | 37 + wai/live-conformance/exploration/vectors.json | 3697 +++++++++++++++++ wai/live-conformance/exploration_verify.py | 1230 ++++++ wai/wai-rs/Cargo.toml | 19 + wai/wai-rs/src/bin/wai_exploration_vectors.rs | 139 + wai/wai-rs/src/codecs/registry.rs | 14 +- wai/wai-rs/src/exploration.rs | 1714 ++++++++ wai/wai-rs/src/exploration/corpus.rs | 1136 +++++ wai/wai-rs/src/lib.rs | 8 + wai/wai-rs/tests/exploration.rs | 73 + wai/wai-rs/tests/int_kernels_vectors.rs | 2 +- 17 files changed, 8994 insertions(+), 15 deletions(-) create mode 100644 wai/extensions/exploration.md create mode 100644 wai/live-conformance/exploration/README.md create mode 100644 wai/live-conformance/exploration/vectors.json create mode 100644 wai/live-conformance/exploration_verify.py create mode 100644 wai/wai-rs/src/bin/wai_exploration_vectors.rs create mode 100644 wai/wai-rs/src/exploration.rs create mode 100644 wai/wai-rs/src/exploration/corpus.rs create mode 100644 wai/wai-rs/tests/exploration.rs diff --git a/.github/workflows/wai-conformance.yml b/.github/workflows/wai-conformance.yml index ce39465a6..46a54aa55 100644 --- a/.github/workflows/wai-conformance.yml +++ b/.github/workflows/wai-conformance.yml @@ -122,6 +122,10 @@ on: # ai_usage_verify.py reads that table, and the registry's wire identifiers test reads its # sections. - 'wai/extensions/ai-usage.md' + # tests/exploration.rs requires this extension's §13 to list the codes the reference + # reports and its §3.2 table to name the reference's descriptors, exploration_verify.py + # reads §13, and the registry's wire identifiers test reads its sections. + - 'wai/extensions/exploration.md' - 'wai/wai-web/**' # The audio provenance check below reads the corpora above with this tool. - 'wai/tools/wai_audio_provenance_check.py' @@ -794,7 +798,8 @@ jobs: # e2ee_verify.py (the end-to-end encrypted rooms corpus), live_watermark_verify.py (the # forensic-watermark corpus), live_ads_verify.py (the live-ads corpus), c2pa_live_verify.py # (the live-provenance corpus), edge_verify.py (the deriving-edge corpus), - # synthesis_verify.py (the synthesis corpus) and ai_usage_verify.py (the AI usage corpus). + # synthesis_verify.py (the synthesis corpus), ai_usage_verify.py (the AI usage corpus) and + # exploration_verify.py (the exploration corpus). # Each exits non-zero on any failure or any difference, and the step fails with it. # One platform: what they check is the reading of the text, not the architecture. independent-verifiers: @@ -1176,6 +1181,29 @@ jobs: (cd wai-rs && cargo test --no-default-features --features ai_usage --test ai_usage) python3 -I live-conformance/ai_usage_verify.py live-conformance/usage python3 -I claim-conformance/claim_verify.py consumption live-conformance/usage/vectors.json + # wai.media.exploration (extensions/exploration.md): the reference module's unit tests (the + # descriptors of flat, single-row and checkerboard pictures, grid bins at both ends, the + # sample distance's zero, the taste score, derived prompts, and a schedule that replays and + # keeps the first comer without an objective) and tests/exploration.rs (vectors.json + # regenerates byte for byte from its fixed seeds and no other file is there, wai-rs gives + # every generation, descriptor vector and case its stated outcome, §13 lists exactly the + # reference's codes, each of which the corpus gives, and §3.2 names the reference's + # descriptors); then the corpus's second implementation, exploration_verify.py, written from + # the extension's text and sharing no code with wai-rs, which makes every picture with the + # generator as the extension's Appendix A restates it, computes the descriptors, replays + # every archive's schedule, reads usage statements with ai_usage_verify.py, verifies every + # record with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, reads the + # extension's reason table, requires every mutated copy of the corpus to fail, and drops each + # of its own checks in turn and requires the corpus to catch the weakened verifier; standard + # library only, run isolated (-I). + - name: exploration · wai-rs and exploration_verify.py + working-directory: wai + shell: bash + run: | + set -euo pipefail + (cd wai-rs && cargo test --no-default-features --features exploration --lib exploration::) + (cd wai-rs && cargo test --no-default-features --features exploration --test exploration) + python3 -I live-conformance/exploration_verify.py live-conformance/exploration # wai.live.e2ee (extensions/confidentiality.md): the corpus's second implementation, # e2ee_verify.py, written from the extension's text and the documents it reads and # sharing no code with the reference (joule-moq's secure_objects and joule-moq-mls, diff --git a/wai/CHANGELOG.md b/wai/CHANGELOG.md index a961d721c..8aac23e7b 100644 --- a/wai/CHANGELOG.md +++ b/wai/CHANGELOG.md @@ -6,6 +6,52 @@ wire format may change and such changes are recorded here. ## v0.4.0 — current +### `wai.media.exploration`: archives that replay, default-distance, a homogenization meter, and taste as a declared, owned objective + +- **The extension** ([exploration](extensions/exploration.md)) registers the record + `wai.media.exploration`. It builds on the exactness of `wai.generate.spectral`: what elsewhere + can only be estimated about a generator's outputs is recomputed here. +- **Descriptors.** Six integer derivations over a picture's `RGB8` samples, each from 0 to 1024: + mean luma, chroma, detail (the mean luma step between neighbours), palette diversity (the + Gini–Simpson index of a 64-colour quantisation) and the two coordinates of the luma centroid. + No learned model: they place a picture and judge nothing. A grid of one to four axes bins them + into niches. +- **Archives.** A generation request may ask for an archive instead of one picture: + MAP-Elites over a declared grid, through the prompt and up to eight modifiers the person + declares, run by the pinned schedule `wai-exploration:map-elites/1` from a declared search + seed. Each elite names its genome (seed, steps, modifier mask) and regenerates; the archive + replays bit for bit, so an elite dropped or chosen after the fact is refused + (`archive_replay_mismatch`). The placement rule is `none` (the first trial to reach a niche + keeps it) or a taste prior. +- **Default-distance.** A prompt's default set is seeds 0 to 15 at four steps. A work's distance + from it, in descriptors and in samples (0 exactly when the work is a default), is a signed + `measured` figure for the exact generator, an `estimate` for any other, and `unknown` with + every figure `null`, never 0. +- **Collection statements.** The descriptor coverage of a grid and the distribution of pairwise + descriptor distances of a gallery, a room's outputs, a session's candidates or an archive, + recomputed from the samples. +- **Taste priors.** An integer ranking model over the descriptors (`rise`, `fall`, `near` and + `far` terms, unsigned throughout), a one-file parameter set pinned as SPEC §3.1 pins one, + signed by its owner (`taste_not_owner` otherwise) and carrying the owner's `wai.ai.usage` + statement; a ranking under it reproduces, and states the use it made of the prior, which the + owner's statement may disallow. Personal and community priors are the same kind of object, and + none is a default. +- **Disclosure.** Every archive, ranking and pick that an aesthetic or reward model steered names + it by digest or states `none`. A missing disclosure is reported undisclosed, never `none`; a + policy may require it (`objective_undisclosed`), and a pick from an archive a prior steered must + name that prior (`objective_mismatch`). A pick from an archive inherits the elite's genome: the + slot the contribution record fills to point a `candidates` step at an archive. +- **Reference and corpus.** `wai-rs` feature `exploration` (`src/exploration.rs`), and + `live-conformance/exploration/`, written from fixed seeds by `wai_exploration_vectors gen`: + generations that check the generator's restatement, descriptor vectors, archives, distances, + collections, rankings and picks, accepted and refused at each rule. Checked by + `tests/exploration.rs` and by `live-conformance/exploration_verify.py`, a second implementation + that shares no code with `wai-rs`, implements the generator from the extension's Appendix A, + requires every mutated copy of the corpus to fail and every weakened copy of itself to be + caught. `wai_exploration_vectors measure` runs an archive against plain seed sampling and + against uniform sampling of the same genome space at equal compute. The three priors of the + corpus are written in code with hand-set weights; nothing is trained on anyone's choices. + ### `wai.ai.usage`: AI usage preferences bound to the bytes, and the agent's consumption claim - **The extension** ([ai-usage](extensions/ai-usage.md)) registers the record `wai.ai.usage`. diff --git a/wai/REGISTRY.md b/wai/REGISTRY.md index 4bf39d63a..45caac416 100644 --- a/wai/REGISTRY.md +++ b/wai/REGISTRY.md @@ -44,8 +44,9 @@ Every registered string has one kind. `wai.live.metering`, `wai.live.steering`, `wai.live.moderation`, `wai.live.e2ee`, `wai.live.watermark`, `wai.live.ads` and `wai.live.provenance`; timed text, `wai.text.timed`; the deriving edge's record, `wai.edge.derivation`; the origin claims of - media, `wai.media.synthesis`; AI usage preferences and consumption claims, `wai.ai.usage`). - It names no payload format. + media, `wai.media.synthesis`; AI usage preferences and consumption claims, `wai.ai.usage`; + exploration archives, default-distances, collection statements, taste priors, rankings and + picks, `wai.media.exploration`). It names no payload format. A derivation or record string is not a payload capability, so it is not dispatchable (SPEC §4): dispatch never takes an envelope's capability that names @@ -68,7 +69,8 @@ they serve ([jwp-receipts](extensions/jwp-receipts.md) §7), [packaging](extensions/packaging.md), [live-events](extensions/live-events.md), [live-rooms](extensions/live-rooms.md), [capture-binding](extensions/capture-binding.md), [live-compose](extensions/live-compose.md), [live-recording](extensions/live-recording.md), -[timed-text](extensions/timed-text.md) and [ai-usage](extensions/ai-usage.md) put on the wire outside a +[timed-text](extensions/timed-text.md), [ai-usage](extensions/ai-usage.md) and +[exploration](extensions/exploration.md) put on the wire outside a manifest — magic numbers, a media type, `codecs` prefixes, paths, playlist tags and attributes, document kinds, catalog fields, MOQT Setup Options and HTTP fields — each with its kind, the section that defines it, and whether it is defined, provisional (test material only until diff --git a/wai/SPEC.md b/wai/SPEC.md index d3617b4c2..54a1f835e 100644 --- a/wai/SPEC.md +++ b/wai/SPEC.md @@ -596,8 +596,9 @@ kind: `wai.live.metering`, `wai.live.steering`, `wai.live.moderation`, `wai.live.e2ee`, `wai.live.watermark`, `wai.live.ads` and `wai.live.provenance`, and timed text, `wai.text.timed`; an edge's derivation record, `wai.edge.derivation`; the origin claims of - media, `wai.media.synthesis`; and AI usage preferences and consumption claims, `wai.ai.usage`), - which names no payload format. + media, `wai.media.synthesis`; AI usage preferences and consumption claims, `wai.ai.usage`; + and exploration archives, default-distances, collection statements, taste priors, rankings and + picks, `wai.media.exploration`), which names no payload format. Only payload, companion and refinement capabilities have a media class, a fidelity tier, a replicate class and a role. A derivation or record string is not a payload @@ -1161,6 +1162,24 @@ statements it saw and its grant; a verifier checks it against the objects, their the room, and refuses a use they disallow (`usage_disallowed`), and a relay or gateway MAY require claims before it serves an agent: [`extensions/ai-usage.md`](extensions/ai-usage.md). +And for **exploration** with the exact generator, and **taste** as a declared, owned objective — +`wai.media.exploration`: six integer descriptors over a picture's `RGB8` samples (mean luma, +chroma, detail, palette diversity and the luma centroid's two coordinates) place it without +judging it. An archive is MAP-Elites over a declared grid of descriptors, run over +`wai.generate.spectral` by a pinned schedule from a declared search seed, through the prompt and +the modifiers a person declares: every elite names its genome and regenerates, and the archive +replays bit for bit (`archive_replay_mismatch` otherwise). A prompt's default set is seeds 0 to +15 at four steps, and a work's default-distance from it, in descriptors and in samples (0 exactly +when the work is a default), is a signed measurement for the exact generator and an estimate, +never a measurement, for any other; an unknown figure is never written as 0. A collection +statement gives a gallery's, a room's or a session's descriptor coverage and pairwise distances. +A taste prior is an integer ranking model over the descriptors, a one-file parameter set pinned as +§3.1 pins one, signed by its owner (`taste_not_owner` otherwise) and carrying the owner's +`wai.ai.usage` statement; a ranking under it reproduces. Every archive, ranking and pick that an +aesthetic or reward model steered names it by digest or states `none`; a policy may require the +disclosure of every pick, a pick from an archive a prior steered names that prior, and no default +objective exists: [`extensions/exploration.md`](extensions/exploration.md). + ### Payloads of the WAI-native integer codecs This revision pins a payload format to each WAI-native integer codec whose row named diff --git a/wai/extensions/exploration.md b/wai/extensions/exploration.md new file mode 100644 index 000000000..1b539f20d --- /dev/null +++ b/wai/extensions/exploration.md @@ -0,0 +1,817 @@ +# WAI Extension: Exploration and Declared Taste + +> Status: Draft. Registers the record `wai.media.exploration`. `wai.generate.spectral` is exact: +> a model file, a prompt, a seed and a number of steps give the same bytes on every machine +> ([SPEC](../SPEC.md) §5, *Payload of `wai.generate.spectral`*). This extension builds on that. +> Six **descriptors**, each an integer derivation over a picture's `RGB8` samples, place a +> picture: how bright, how colourful, how busy, how many colours, and where its light sits. An +> **archive** asks the generator for many pictures that differ, not one: MAP-Elites over a +> declared grid of descriptors, run by a pinned schedule from a declared search seed, so every +> elite regenerates from the genome it names and the whole archive replays bit for bit. The +> **default set** of a prompt is what the model makes on its own, seeds 0 to 15 at four steps; a +> work's **default-distance** is how far it sits from the nearest default, a signed measurement +> for the exact generator and an estimate, never a measurement, for any other. A **collection +> statement** gives a gallery's, a room's or a session's descriptor coverage and pairwise +> distances: a homogenization meter that recomputes. **Taste** is a declared, owned objective: a +> **taste prior** is an integer ranking model over the descriptors, pinned by digest as a WAI +> prior, signed by its owner and carrying its owner's usage statement +> ([ai-usage](ai-usage.md)); a **ranking** under it reproduces; and every archive, ranking and +> **pick** an aesthetic or reward model steered names that model by digest, or states `none`. A +> policy may require the disclosure, and a selection from a steered archive cannot drop it. No +> default objective exists: a personal prior and a community prior are the same kind of thing. +> No new transport. The reference implementation is the `exploration` module of `wai-rs` +> (feature `exploration`); the corpus is +> [`live-conformance/exploration/`](../live-conformance/exploration/), and its second +> implementation is `live-conformance/exploration_verify.py`. +> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174. + +## 1. Scope + +In scope: the records and their encodings (§2); the descriptors, their distance and grids (§3); +the generator path, modifiers and genomes (§4); archives and their schedule (§5); the default set +and default-distance (§6); collection statements (§7); taste priors (§8) and rankings (§9); the +disclosure of what steered a record, and the pick record (§10); the slot this extension leaves +the contribution record (§11); verification (§12). + +Out of scope: a user interface; how a person chooses a prompt, a modifier or a pick; training a +taste prior from anyone's choices (the corpus's priors are written in code with hand-set +weights, §14); a learned embedding (the descriptors are arithmetic, §3.3); and any statement of +what a picture is worth. + +### 1.1 Why + +Help from a generator can make one person's work more inventive while making many people's work +more alike: different people asking for the same thing receive the same few answers, and +different generators converge on similar answers to open prompts. A person shown one example +tends to stay near it, and a generator asked again with an edited prompt tends to repeat itself. +A single aesthetic objective applied to everyone narrows what is made further: it ranks one +taste above others by construction and refuses requests outside it. Rewarding a result for +differing from what others produce, rather than for matching one objective, restores variety. + +Each of these is a statement about outputs, and for most generators it can only be estimated. +For an exact generator it can be checked. This extension makes four such statements checkable: +how widely an archive explored (§5), how far a work is from what the model does on its own (§6), +how alike a collection is (§7), and which objective, if any, chose what a person was shown +(§8–§10). + +### 1.2 Relationships + +Relationship to the core spec: `wai.media.exploration` is a **record** ([SPEC](../SPEC.md) §5): a +signed record a WAI tool emits and verifies. It names no payload format and is not +dispatchable. A taste prior is a parameter set in SPEC §3.1's sense, pinned by a pin of SPEC +§3.1's members (§8.3). + +Relationship to `wai.generate.spectral`: every picture this extension recomputes is made by that +capability's reference generator, with the model file the record names by SHA-256 (§4.1). +Appendix A restates the generator for a second implementation. + +Relationship to [ai-usage](ai-usage.md): a taste prior carries its owner's usage statement, read +by ai-usage §3.6, and a ranking states the use it made of the prior in ai-usage §6.1's form; the +preference is decided by ai-usage §5.2 rule 2 (§9.3). + +Relationship to [synthesis](synthesis.md): a picture an archive holds is generated; its origin +claim, where its publisher signs one, is synthesis §3's, step `generate`. Nothing here changes +a class. + +Relationship to the contribution record, `wai.media.contribution`: §11 names the slot a +contribution session's `candidates` and `select` steps fill to point at an archive, and the +disclosure member they carry. + +## 2. Records + +Every record of this extension is a JSON object (RFC 8259) under the encodings of +[jwp-receipts](jwp-receipts.md) §2.4.3: byte strings in lowercase hexadecimal; integers unsigned, +at most 2^53 − 1, in plain decimal; no other number; no boolean; a **term** and a **date-time** +as defined there. A record is read as jwp-receipts §3.1 step 1 reads a claim: RFC 8259's grammar, +no member named twice in one object, at most 32 levels of nesting. Each record has exactly the +members its section lists, no member missing and none added, at any level, except where a +section marks a member OPTIONAL, and a `kind` naming it; one that does not, or whose member is +of another type or outside its range, is `record_malformed`. + +Every record carries `issued_at` (a date-time: when its signer signed it), `signer_pubkey` (32 +bytes, the Ed25519 key of RFC 8032 that signs it) and `sig` (64 bytes): + +``` +sig = Ed25519(signer_key, "wai:exploration\x01" || JCS(record without "sig")) +link_hash = BLAKE3("wai:exploration-link\x01" || JCS(record)) +``` + +JCS is RFC 8785, which on these values reduces to what jwp-receipts §2.4.3 states. The signature +is verified strictly ([SPEC](../SPEC.md) §7 *Signatures*): a key that fails step 1 or 2 is +`bad_key`, and a signature that fails a later step `bad_signature`. A record is named by its +link hash wherever another names it. + +A **picture** is named by its samples: the SHA-256 (FIPS 180-4) of its `RGB8` buffer as +[reconstruction-binding](reconstruction-binding.md) §2 defines it (rows top to bottom, pixels +left to right, three bytes a pixel, no padding), its **samples digest**. A picture object is +`{"samples", "width", "height"}`, and `{"samples", "width", "height", "descriptors"}` where a +table says it carries descriptors: a samples digest, a width and a height each from 1 to 4096 +with their product at most 2^23 (the ranges of an instruction object, SPEC §5), and a descriptor +vector (§3.4). + +A record names the descriptor set it uses in `descriptors`: `wai-exploration:image6`, the one +this revision defines. Another value is `record_malformed`. + +## 3. Descriptors + +### 3.1 Luma + +The descriptors are computed from a picture's `RGB8` buffer of *w* × *h* pixels, *n* = *w* · *h*, +in integer arithmetic; ⌊ ⌋ is the floor of an exact rational, and no step rounds otherwise. The +**luma** of a pixel with bytes *R*, *G*, *B* is + +*Y* = (77 · *R* + 150 · *G* + 29 · *B* + 128) >> 8, + +an integer from 0 to 255 (the weights sum to 256, so a grey pixel's luma is its value). + +### 3.2 The six descriptors + +Each descriptor is an integer from 0 to 1024. The **descriptor vector** is the six, in this +order: + +| # | name | value | +|---|---|---| +| 1 | `luma` | ⌊1024 · Σ *Y* / (255 · *n*)⌋ | +| 2 | `chroma` | ⌊1024 · Σ (max(*R*, *G*, *B*) − min(*R*, *G*, *B*)) / (255 · *n*)⌋ | +| 3 | `detail` | with *P* = (*w* − 1) · *h* + *w* · (*h* − 1) and *D* the sum of \|*Y*(*x* + 1, *y*) − *Y*(*x*, *y*)\| over every horizontal pair and \|*Y*(*x*, *y* + 1) − *Y*(*x*, *y*)\| over every vertical pair: 0 when *P* is 0, otherwise min(1024, ⌊1024 · *D* / (16 · *P*)⌋) | +| 4 | `palette` | each pixel's colour is (*R* >> 6) · 16 + (*G* >> 6) · 4 + (*B* >> 6), one of 64; with *k*ᵢ the number of pixels of colour *i*: ⌊1024 · (*n*² − Σ *k*ᵢ²) / *n*²⌋ | +| 5 | `centroid_x` | with *V* = *Y* + 1 at each pixel: ⌊1024 · Σ (2*x* + 1) · *V* / (2 · *w* · Σ *V*)⌋ | +| 6 | `centroid_y` | ⌊1024 · Σ (2*y* + 1) · *V* / (2 · *h* · Σ *V*)⌋ | + +Sums run over every pixel unless the row says otherwise; *x* runs from 0 to *w* − 1 left to +right and *y* from 0 to *h* − 1 top to bottom. Every intermediate value fits in 64 unsigned bits +for every size §2 admits. + +### 3.3 Why these six + +Each answers a question a viewer asks of a picture, in one number: how bright it is (`luma`); how +colourful (`chroma`, the mean spread of a pixel's three channels); how busy (`detail`, the mean +luma step between neighbours, sixteen levels a step counting as full); how many colours it uses +and how evenly (`palette`, the probability that two pixels drawn at random differ in their +64-colour quantisation, the Gini–Simpson index); and where its light sits (`centroid_x` and +`centroid_y`, the luma-weighted centre, 512 being the frame's centre; *V* is *Y* + 1 so that a +black picture has a centre). They are arithmetic over the samples, with no learned model and so +no population's judgement inside them: they place a picture, they do not rank it. Each is scaled +to the same range so that a distance (§3.4) weighs no axis above another by its units; weighing +one above another is a taste, which §8 makes a declared, owned object instead. + +### 3.4 Distance + +The **descriptor distance** of two vectors is Σ \|*a*ᵢ − *b*ᵢ\| over the six, an integer from 0 to +6144. In JSON a vector is an array of six integers, each from 0 to 1024. + +### 3.5 Grids + +A **grid** is an array of 1 to 4 **axes**, each `{"descriptor", "lo", "hi", "bins"}`: a descriptor +name of §3.2, no name twice; 0 ≤ `lo` < `hi` ≤ 1024; `bins` from 1 to 64; and the product of +every axis's `bins`, the grid's **cells**, at most 4096. The **bin** of a value *d* on an axis is +0 when *d* < `lo`, `bins` − 1 when *d* ≥ `hi`, and ⌊(*d* − `lo`) · `bins` / (`hi` − `lo`)⌋ +otherwise. The **niche** of a vector is its bins read as a mixed-radix number, the first axis +most significant: *k* = 0, then *k* = *k* · `bins` + bin for each axis in order. + +## 4. The generator path + +### 4.1 Generation + +`gen(model, prompt, seed, steps, w, h)` is the picture SPEC §5 has a sink make for an +instruction object of `wai.generate.spectral`: the reference generator's +`generate(model, prompt, seed, steps, h, w)`, `w` · `h` · 3 bytes of `RGB8`, with the model file +whose SHA-256 the record names as `sha256:` and 64 lowercase hexadecimal digits. A prompt is what +an instruction object's `prompt` is: 0 to 256 bytes, each 0x20 to 0x7E other than `"` and `\`. +A seed is from 0 to 2^32 − 1 and `steps` from 1 to 64. Appendix A restates the generator. + +A verifier holds model files and finds one by its SHA-256. A record that asks it to generate with +a model file it does not hold is `model_unheld`. + +A generator other than `wai.generate.spectral` is named by a term and is not recomputed here +(§6.3, §10.2). + +### 4.2 Modifiers and derived prompts + +An archive declares 0 to 8 **modifiers**, each 1 to 32 bytes of `a`–`z` and `0`–`9`: words the +search may add to the prompt. A **modifier mask** is an integer below 2^*M*, *M* the number of +modifiers. The **derived prompt** of a mask is the prompt followed, for each *i* from 0 to *M* − 1 +whose bit *i* is set, by one space (0x20) and modifier *i*. The derived prompt of the full mask +MUST be a prompt (§4.1). The modifiers are the person's: the archive explores the space they +declare, and the prompt they wrote is always the first word. + +### 4.3 Genomes + +A **genome** is `(seed, steps, mods)`; its picture is `gen(model, derived(prompt, mods), seed, +steps, w, h)` for the archive's model, prompt, modifiers and size. + +## 5. Archives + +### 5.1 The request + +An archive record carries what was asked: + +| member | value | +|---|---| +| `generator` | `wai.generate.spectral` | +| `model` | `sha256:` and the model file's SHA-256 | +| `prompt` | a prompt (§4.1) | +| `modifiers` | 0 to 8 modifiers (§4.2) | +| `width`, `height` | the pictures' size (§2) | +| `steps` | from 1 to 64: the steps every initial trial uses | +| `descriptors` | `wai-exploration:image6` | +| `grid` | a grid (§3.5) | +| `search` | `{"schedule", "seed", "trials", "init"}`: `schedule` `wai-exploration:map-elites/1`; `seed` an integer, the search seed; `trials` from 1 to 4096; `init` from 1 to `trials` | +| `objective` | `"none"`, or a taste objective (§10.1): what decides between two pictures of one niche | + +An objective of type `model` is `record_malformed` here: a schedule steered by a model a +verifier cannot run cannot be replayed. + +### 5.2 The schedule `wai-exploration:map-elites/1` + +The schedule draws from **splitmix64**, a 64-bit state *s* that starts at the search seed; each +draw sets *s* to *s* + 0x9E3779B97F4A7C15 modulo 2^64, then *z* = *s*, *z* = (*z* ⊕ (*z* >> 30)) · +0xBF58476D1CE4E5B9, *z* = (*z* ⊕ (*z* >> 27)) · 0x94D049BB133111EB, each product modulo 2^64, +and returns *z* ⊕ (*z* >> 31). The archive *A* maps a niche to its **elite**; the visits *V* map +a niche to the number of trials that reached it. Both start empty. For each trial *t* from 0 to +`trials` − 1, in order: + +1. **Genome.** When *t* < `init`: seed = draw mod 2^32, `steps` the request's, mods 0. Otherwise: + - with *O* the occupied niches in ascending order, *a* = *O*[draw mod \|*O*\|], then + *b* = *O*[draw mod \|*O*\|]; the parent is *A*[*b*] when *V*[*b*] < *V*[*a*], and *A*[*a*] + otherwise; + - mods = the parent's; when *M* > 0, for each *i* from 0 to *M* − 1 in order, bit *i* is + flipped when draw mod *M* is 0; + - with *d* = draw mod 8, steps = the parent's steps plus *d* − 4 when *d* < 4 and *d* − 3 + otherwise, clamped to 1 to 64; + - seed = draw mod 2^32. +2. **Picture.** The genome's picture (§4.3), its descriptor vector and its niche *k* in the grid; + *V*[*k*] increases by 1. +3. **Score.** With a taste objective, the score of the vector under the prior (§8.2); with + `none`, no score. +4. **Placement.** When *k* is not occupied, the trial becomes its elite. When it is, the trial + replaces the elite only under a taste objective and only with a strictly greater score; a tie + keeps the earlier trial, and with `none` the first trial to reach a niche keeps it. + +The parent is the less-visited of two occupied niches drawn at random: the search spends its +trials where few have landed. A child keeps its parent's recipe close (each modifier flips with +probability 1/*M*, the steps move by one to four) and draws a new seed. The archive is therefore a +function of the request alone. + +### 5.3 The record + +An archive record, `kind` `"wai-archive"`, has the members of §5.1 and: + +| member | type | meaning | +|---|---|---| +| `elites` | array | every occupied niche's elite, in strictly ascending order of `niche`, at least one | +| `coverage` | object | `{"occupied", "cells"}`: the number of elites and the grid's cells | +| `issued_at`, `signer_pubkey`, `sig` | | §2 | + +An elite is `{"niche", "trial", "seed", "steps", "mods", "samples", "descriptors", "score"}`: its +niche, below the grid's cells; the trial that placed it, below `trials`, no trial twice; its +genome (`seed` below 2^32, `steps` from 1 to 64, `mods` below 2^*M*); its picture's samples +digest and descriptor vector; and its score, an integer under a taste objective and `null` +under `none`. + +### 5.4 Verifying an archive + +In this order: + +1. The record reads (§2, §5.1, §5.3) and its signature verifies. +2. `coverage` states the number of elites and the grid's cells: otherwise `coverage_mismatch`. +3. A taste objective's prior resolves and verifies (§8.3, §8.4). +4. The verifier holds the model (`model_unheld`). +5. For each elite in order: its genome's picture has its samples digest + (`generation_mismatch`), the picture's descriptor vector is its `descriptors` + (`descriptor_mismatch`), that vector's niche is its `niche` (`niche_mismatch`), and its score + is the prior's score of the vector, or `null` with `none` (`score_mismatch`). +6. Under a policy that requires replay (§12.1): the schedule of §5.2, run from the request, + leaves exactly these elites, member for member: otherwise `archive_replay_mismatch`. + +An archive that passes step 5 is **elite-checked**: every picture it lists is what its genome +makes, and sits where it says. One that passes step 6 is **replayed**: the archive is the +schedule's, every niche's elite is the one the schedule keeps, and no trial was left out or +chosen after the fact. Replay costs `trials` generations; step 5 costs one per elite. + +## 6. Default-distance + +### 6.1 The default set + +The **default set** of a model, a prompt and a size is the 16 pictures `gen(model, prompt, k, 4, +w, h)` for *k* from 0 to 15: what the model makes for the prompt on its own, at the steps of the +registered conformance object (SPEC §5) and the first sixteen seeds. They stand for what a person +who chooses nothing receives, and they are the same sixteen for every verifier. + +### 6.2 Two distances + +A work's **descriptor distance** to the default set is the least descriptor distance (§3.4) +between its vector and a default's; `nearest_descriptor` is the lowest *k* that attains it. Its +**sample distance** is the least ⌈1024 · Σ \|*a* − *b*\| / (765 · *n*)⌉ between its buffer and a +default's, the sum over every byte; `nearest_sample` is the lowest *k* that attains it. + +Both are given because they answer different questions. The descriptor distance says how +different a *kind* of picture the work is from what the model does on its own, and is blind to +which exact draw it is. The sample distance says whether the work *is* a default: it is 0 exactly +when the work's bytes are a default's (the ceiling keeps any difference above 0), and otherwise +how far in samples. A work that is seed 3 of the prompt as written has sample distance 0; a work +regenerated with other words, other steps or another seed, or edited afterwards, does not. + +### 6.3 The record and its class + +A distance record, `kind` `"wai-distance"`: + +| member | type | meaning | +|---|---|---| +| `work` | picture with descriptors | the work | +| `generator` | term | `wai.generate.spectral`, or a term naming another generator | +| `model` | term | for `wai.generate.spectral`, `sha256:` and the model file's SHA-256; otherwise a term naming the model | +| `prompt` | string | a prompt (§4.1) | +| `descriptors` | string | `wai-exploration:image6` | +| `defaults` | array | 0 to 16 entries `{"samples", "descriptors"}`: a default's samples digest or `null`, and its vector | +| `class` | string | `measured`, `estimate` or `unknown` | +| `descriptor_distance`, `nearest_descriptor`, `sample_distance`, `nearest_sample` | integer or `null` | §6.2 | +| `issued_at`, `signer_pubkey`, `sig` | | §2 | + +The class says what kind of figure it is: + +- **`measured`**: the generator is exact, the default set is recomputed, and the figure is a + measurement anyone holding the model and the work repeats. `defaults` has 16 entries, every + `samples` a digest, in seed order, and all four figures are integers. +- **`estimate`**: the generator is not exact. Its defaults are the signer's statement of what + the generator made (their vectors, and their samples where the signer has them), and the + figure is the descriptor distance from those: an estimate of how far the work is from the + generator's defaults, never a measurement of it. `defaults` has 1 to 16 entries, + `descriptor_distance` and `nearest_descriptor` are integers, and `sample_distance` and + `nearest_sample` are `null`. +- **`unknown`**: no default set is known. `defaults` is empty and all four figures are `null`. + Unknown is never zero: a record that writes 0 for a figure it does not have states that the + work is a default. + +A record whose members break its class's shape is `record_malformed`. A `measured` record over a +generator other than `wai.generate.spectral`, or a record over `wai.generate.spectral` of +another class, is `distance_class_invalid`: the exact generator's figure is always a +measurement, and no other generator's ever is. + +### 6.4 Verifying a distance + +In this order, after the record reads and its signature verifies: + +1. The class agrees with the generator (`distance_class_invalid`). +2. Held samples of the work are `width` · `height` · 3 bytes (`samples_mismatch`). +3. `measured`: the verifier holds the model (`model_unheld`); the default set at the work's size + is made, and each entry's samples digest and vector are the default's + (`default_mismatch`); the verifier holds the work's samples (`work_unheld`), and their vector + is the work's `descriptors` (`descriptor_mismatch`); all four figures are computed by §6.2. +4. `estimate`: where the work's samples are held, their vector is its `descriptors` + (`descriptor_mismatch`); the descriptor distance and the nearest default are computed from + the work's vector and the stated vectors. +5. `unknown`: where the work's samples are held, their vector is its `descriptors` + (`descriptor_mismatch`). +6. The figures computed are the figures stated (`distance_mismatch`). + +A verifier reports the class with the figures, and reports an `unknown` figure as unknown, +never as 0. + +## 7. Collection statements + +### 7.1 The record + +A collection statement, `kind` `"wai-collection"`, is the homogenization meter of a set of +pictures: + +| member | type | meaning | +|---|---|---| +| `scope` | string | `gallery`, `room` (a room's outputs), `session` (a session's candidates) or `archive` | +| `subject` | term | what the collection is: a gallery's URI, a room's id, an archive's link hash | +| `descriptors` | string | `wai-exploration:image6` | +| `grid` | array | a grid (§3.5) | +| `members` | array | 2 to 256 pictures with descriptors; a picture may appear more than once | +| `coverage` | object | `{"occupied", "cells"}` | +| `distances` | object | §7.2 | +| `issued_at`, `signer_pubkey`, `sig` | | §2 | + +### 7.2 The figures + +- `coverage`: `occupied`, the number of distinct niches the members' vectors fall in; `cells`, + the grid's. +- `distances`: over every unordered pair of members (*i* < *j*), the descriptor distance of + their vectors: `pairs`, their number; `sum`, their total, so the mean is `sum` / `pairs` + exactly; `min` and `max`; `median`, the element at position ⌊(`pairs` − 1) / 2⌋ of the + distances in ascending order; `width`, from 1 to 6144; and `histogram`, 16 counts, a distance + *d* counted in bin min(⌊*d* / `width`⌋, 15). + +A collection whose members are all alike has few occupied cells and small distances; one that +explores has many and large ones. The figures say nothing of quality. + +### 7.3 Verifying a collection + +After the record reads and its signature verifies: for each member in order, the verifier holds +its samples (`member_unheld`), of its size (`samples_mismatch`), whose vector is its +`descriptors` (`descriptor_mismatch`); then `coverage` is computed from the vectors +(`coverage_mismatch`), and then `distances` with the stated `width` (`distances_mismatch`). +Every figure is computed from samples the verifier holds; a statement over pictures it does not +hold is not checked, and is not accepted. + +## 8. Taste priors + +### 8.1 The prior + +A **taste prior** is a file: the canonical form (JCS) of a signed record, `kind` `"wai-taste"`: + +| member | type | meaning | +|---|---|---| +| `owner` | 32 B hex | the Ed25519 key of the person or community whose taste it is | +| `scope` | string | `personal` or `community` | +| `descriptors` | string | `wai-exploration:image6` | +| `terms` | array | 1 to 32 terms (§8.2) | +| `usage` | object or `null` | the owner's usage statement ([ai-usage](ai-usage.md) §3), or `null` | +| `issued_at`, `signer_pubkey`, `sig` | | §2 | + +A file whose bytes are not the canonical form of the record they hold is `record_malformed`, +and so is a `usage` that does not read by ai-usage §3.6. The prior's **digest** is the SHA-256 +of the file. + +### 8.2 The score + +A term is `{"descriptor", "shape", "at", "weight"}`: a descriptor name; a shape; `at` from 0 to +1024, which is 0 for `rise` and `fall`; and `weight` from 1 to 1024. Its value at a vector whose +descriptor is *d*: + +| shape | value | +|---|---| +| `rise` | `weight` · *d* | +| `fall` | `weight` · (1024 − *d*) | +| `near` | `weight` · (1024 − \|*d* − `at`\|) | +| `far` | `weight` · \|*d* − `at`\| | + +The **score** of a vector is the sum of its terms' values, an integer from 0 to 2^25. Every +value is non-negative, so the arithmetic is unsigned throughout and the same on every machine. A +prior that likes calm, dark pictures says `fall` on `detail` and `luma`; one that likes a +mid-grey says `near` at 512; one that wants pictures unlike the usual says `far` from where +the usual sits. The score is a few integer operations over six numbers, stated in full here, +so it is not expressed as an integer-operator graph ([integer-operators](integer-operators.md)). + +### 8.3 Carriage as a WAI prior + +A taste prior is a parameter set of one file in SPEC §3.1's sense: what a ranking's output +depends on, besides its input. A record names it by a **pin** of SPEC §3.1's members `id` (a +name for people, 1 to 256 bytes), `sha256` (the prior's digest) and `determinism` (in words, +1 to 256 bytes), and no other member: the form is undeclared, and the digest covers the one file. +A verifier holds priors and finds one by its digest, as a sink resolves a pin: nothing but the +digest selects it, not the `id`. A pin that names a prior the verifier does not hold is +`objective_unresolved`. + +### 8.4 Ownership and usage + +A prior is its owner's: it **MUST** be signed by `owner`. One signed by any other key is +`taste_not_owner`, whatever its signature: a tool can publish a person's taste only by holding +the person's signature over it. The checks run in this order: the file reads, the signature +verifies (`bad_key`, `bad_signature`), and the signer is the owner. + +The owner's usage statement governs the prior as it governs any content +([ai-usage](ai-usage.md) §5): it is the prior's signed statement, signed with it by the owner. A +ranking states the use it made of the prior (§9.3), and a use the statement disallows is refused. +A prior that travels in a WAI envelope carries the same statement in the envelope's manifest +(ai-usage §4.1), and an agent that consumes it claims its use there as for any object. + +### 8.5 No default objective + +This extension defines no taste prior of its own, ships none as a default, and ranks nothing +without one. A personal prior and a community prior are the same kind of object: a community's +taste is owned by the community's key, and sits beside each member's own, not above it. No prior +is privileged by the specification, by a verifier or by a registry: what ranks a set is always a +named prior someone owns, and anyone may compare what two priors do with the same pictures. A +taste is as legitimate when it prefers what most priors reject: `far` makes an anti-aesthetic as +expressible as an aesthetic. + +## 9. Rankings + +### 9.1 The record + +A ranking, `kind` `"wai-ranking"`, says what a taste prior made of a set of pictures: + +| member | type | meaning | +|---|---|---| +| `prior` | object | the prior's pin (§8.3) | +| `descriptors` | string | `wai-exploration:image6` | +| `candidates` | array | 1 to 256 pictures with descriptors | +| `scores` | array | one integer per candidate, in their order | +| `order` | array | the candidates' indices, best first: a permutation of 0 to *n* − 1 | +| `usage` | array | 0 to 3 entries `{"vocabulary", "term"}`: the use made of the prior, in ai-usage §6.1's form, in strictly ascending order of `vocabulary` | +| `issued_at`, `signer_pubkey`, `sig` | | §2 | + +A `usage` entry's `vocabulary` is `aipref`, `cawg` or `tdmrep`, and its `term` a term of that +vocabulary (ai-usage §6.2 rule 4) or `null`, a use outside it. Anything else is +`record_malformed`. A ranking is signed by whoever ran it; the prior's owner signed the prior. + +### 9.2 The order + +Each candidate's score is the prior's score of its vector. The order is by score, greatest +first; candidates of equal score keep their order in `candidates`, the lower index first. + +### 9.3 The prior's usage + +The prior's usage statement, where it has one, governs the use. For every vocabulary it carries, +`usage` has an entry (`prior_usage_unanswered`); for each entry whose `term` is not `null`, the +statement's preference for the term (ai-usage §3.2, §3.4, §3.5) is not disallow +(`prior_usage_disallowed`). A ranking states the use it made in each vocabulary as a +consumption claim does (ai-usage §6.1): running a prior to order pictures is the ranking signer's +use, which it names. A prior with no statement governs nothing; a ranking MAY still state its +use. + +### 9.4 Verifying a ranking + +After the record reads and its signature verifies: + +1. The prior resolves and verifies (§8.3, §8.4). +2. For each candidate whose samples the verifier holds: they are of its size + (`samples_mismatch`), and their vector is its `descriptors` (`descriptor_mismatch`). A + candidate whose samples are not held is scored from its stated vector. +3. The scores and the order are those of §9.2 (`ranking_mismatch`). +4. The usage is answered and allowed (§9.3). + +A ranking that passes reproduces: any party holding the prior gets the same scores and the same +order from the same vectors. The verifier reports whether every vector was recomputed from +samples or some were taken as stated. + +## 10. Disclosure of objectives + +### 10.1 The member `objective` + +Every record that an aesthetic or reward model steered — a generation, a selection, a ranking — +names that model, or states that none steered it. The disclosure is the member `objective`: + +| value | meaning | +|---|---| +| `"none"` | no aesthetic or reward model steered the record | +| `{"type": "taste", "prior"}` | a taste prior of §8, by its pin: a verifier resolves it and runs it | +| `{"type": "model", "sha256", "id"}` | another aesthetic or reward model, by the SHA-256 of its parameter set (SPEC §3.1) and a name for people: named, not run here | + +A **taste objective** is a value of type `taste`. An archive's `objective` (§5.1) is the +disclosure of its placement rule, and a ranking's `prior` is its objective. A record of another +extension that a model may steer carries the same member where that extension adds it (§11). + +### 10.2 The pick + +A pick, `kind` `"wai-pick"`, says that a party generated or selected a work, and what steered it: + +| member | type | meaning | +|---|---|---| +| `act` | string | `generate` or `select` | +| `work` | picture | the work | +| `from` | object | where it came from (below) | +| `objective` | | OPTIONAL: §10.1 | +| `issued_at`, `signer_pubkey`, `sig` | | §2 | + +`from` is one of: + +- `{"type": "archive", "archive", "niche"}`: a `select` of the elite of `niche` in the archive + whose link hash is `archive`; +- `{"type": "set", "set"}`: a `select` of one of 1 to 256 samples digests; +- `{"type": "generation", "generator", "model", "prompt", "seed", "steps"}`: a `generate`, by a + generator term, a model term (for `wai.generate.spectral`, `sha256:` and the model file's + SHA-256), a prompt (§4.1), and a seed (below 2^32) and steps (1 to 64), each `null` where the + generator has none. + +A `generate` whose `from` is not a generation, or a `select` whose `from` is one, is +`record_malformed`. + +A pick from an archive **inherits** the elite's genome: its seed, steps and modifier mask, and so +its derived prompt. A pick from an archive whose objective is a taste prior was steered by that +prior, since the prior chose every elite: its `objective` MUST name the same prior +(`objective_mismatch`), absent or not. + +### 10.3 Policy + +A missing `objective` is never read as `none`: the record is **undisclosed**, and a verifier +reports it so. A policy MAY require the member of every pick (§12.1); under it, a pick without +`objective` is `objective_undisclosed`. Every archive and ranking carries its objective by +construction. A universal aesthetic objective therefore cannot steer a record silently: it is +named by digest, or the record says that nothing steered it, or the record is undisclosed and a +policy that requires disclosure refuses it. + +### 10.4 Verifying a pick + +After the record reads and its signature verifies, in this order: + +1. Without `objective`, under a policy that requires it: `objective_undisclosed`. +2. A taste objective's prior resolves and verifies (§8.3, §8.4). +3. Held samples of the work are of its size (`samples_mismatch`). +4. From an archive: the verifier holds the archive, verified earlier in the same case + (`archive_unheld`); the archive has an elite at `niche`, whose samples digest is the work's + and whose archive's size is the work's (`pick_not_in_archive`); and where the archive's + objective is a taste prior, the pick's `objective` names that prior's digest + (`objective_mismatch`). +5. From a set: the work's samples digest is one of the set (`pick_not_in_set`). +6. From a generation by `wai.generate.spectral` with a seed and steps: the verifier holds the + model (`model_unheld`), and `gen` at the work's size has the work's samples digest + (`generation_mismatch`). Any other generation is taken as stated. + +The verifier reports the objective (`none`, the type and digest it names, or `undisclosed`), +how the work was checked (`in-archive`, `in-set`, `regenerated` or `stated`) and, for a pick +from an archive or a regenerated generation, the genome. + +## 11. The slot contribution fills + +The contribution record, `wai.media.contribution`, records a creative session step by step; its `candidates` step +commits a set of pictures by samples digest and seed, and its `select` step picks one. This +revision leaves it one slot and one member, which that extension fills: + +- **`archive`**: a `candidates` step MAY name an archive record by its link hash. The set it + commits is then the archive's elites in ascending niche order: each member's samples digest is + the elite's `samples`, and its generation is the elite's genome, the seed, the steps and the + derived prompt (§4.3), at the archive's model and size. A `select` of a member of such a set + inherits the elite's genome as a pick from the archive does (§10.2). How the member is written + in a step, and how a step that names an archive is checked against it, are contribution's. +- **`objective`**: a step that a model steered carries the member of §10.1 with its meaning + there; a `select` from a set an archive steered by a taste prior carries that prior. + +Nothing here depends on contribution: an archive, a pick and their checks stand alone. + +## 12. Verification + +### 12.1 Inputs + +A verifier is given a **case**: records in an order, as texts; what it holds, each found by its +SHA-256 (model files, taste prior files, and `RGB8` sample buffers); and its policy: + +- `replay`: `required`, every archive is replayed (§5.4 step 6); or `elites`, it is + elite-checked; +- `objective`: `required`, every pick carries `objective` (§10.3); or `optional`. + +### 12.2 Steps + +The records are verified in their order, each by its section: §5.4, §6.4, §7.3, §9.4 or §10.4, +by its `kind`. A record whose `kind` is none of `wai-archive`, `wai-distance`, +`wai-collection`, `wai-ranking` and `wai-pick`, or that does not read, is `record_malformed`. +Each section's checks follow reading and the signature (§2), in the order the section gives; +the first that fails is the case's refusal, with the record's position. An archive that a pick +names is held only once it has been verified, earlier in the case. + +### 12.3 What an accepted case states + +For each record, in order: + +- an archive: its link hash, `replayed` or `elites`, `occupied`, `cells`, and its objective + (`none`, or `{"type", "sha256"}`); +- a distance: its link hash, its class and the four figures, `null` where unknown; +- a collection: its link hash, the number of members, `occupied`, `cells` and `distances`; +- a ranking: its link hash, the prior's digest, owner and scope, the order, `recomputed` or + `stated`, and for each `usage` entry its vocabulary, term and preference (`allow`, `unknown`, + `outside` for a `null` term, or `absent` when the prior's statement does not carry the + vocabulary); +- a pick: its link hash, its act, its objective, its check and its genome (or `null`). + +## 13. Reasons + +The codes this extension adds, each with where it is raised: + +| reason | raised at | +|---|---| +| `record_malformed` | §2, §5.1, §6.3, §8.1, §9.1, §10.2, §12.2 | +| `bad_key` | §2 | +| `bad_signature` | §2 | +| `model_unheld` | §4.1, §5.4 step 4, §6.4 step 3, §10.4 step 6 | +| `objective_unresolved` | §8.3 | +| `taste_not_owner` | §8.4 | +| `objective_undisclosed` | §10.3, §10.4 step 1 | +| `objective_mismatch` | §10.2, §10.4 step 4 | +| `generation_mismatch` | §5.4 step 5, §10.4 step 6 | +| `samples_mismatch` | §6.4 step 2, §7.3, §9.4 step 2, §10.4 step 3 | +| `descriptor_mismatch` | §5.4 step 5, §6.4, §7.3, §9.4 step 2 | +| `niche_mismatch` | §5.4 step 5 | +| `score_mismatch` | §5.4 step 5 | +| `coverage_mismatch` | §5.4 step 2, §7.3 | +| `archive_replay_mismatch` | §5.4 step 6 | +| `distance_class_invalid` | §6.3, §6.4 step 1 | +| `default_mismatch` | §6.4 step 3 | +| `work_unheld` | §6.4 step 3 | +| `distance_mismatch` | §6.4 step 6 | +| `member_unheld` | §7.3 | +| `distances_mismatch` | §7.3 | +| `ranking_mismatch` | §9.4 step 3 | +| `prior_usage_unanswered` | §9.3 | +| `prior_usage_disallowed` | §9.3 | +| `archive_unheld` | §10.4 step 4 | +| `pick_not_in_archive` | §10.4 step 4 | +| `pick_not_in_set` | §10.4 step 5 | + +## 14. Conformance + +[`live-conformance/exploration/`](../live-conformance/exploration/) holds the corpus, written from +fixed seeds by `wai_exploration_vectors gen` as `vectors.json`. It has: + +- **Generations**: pictures of `wai.generate.spectral` at small sizes with their samples digests, + among them prompts whose words select each component type, a negative orientation and a + gradient, and a derived prompt: the check of Appendix A. +- **Descriptors**: buffers with their vectors, among them a single pixel, a single row and a + single column, flat buffers, a checkerboard and generated pictures. +- **Archives**: archives without an objective and under a taste prior, with modifiers and + without, replayed and elite-checked; and one refused for each defect of §5.4, among them a + niche whose descriptor does not recompute, a seed that does not regenerate its picture, an + elite dropped (which every elite check passes and replay refuses), and a prior signed by a key + other than its owner's. +- **Distances**: a measured distance of a work pulled from the defaults and of a work that is a + default (sample distance 0), an estimate and an unknown; and one refused for each defect of + §6.4, among them a distance stated wrong, a measured figure over a generator that is not exact, + and an unknown written as 0. +- **Collections**: the default set and an archive's elites as galleries; and one refused for each + defect of §7.3. +- **Taste priors and rankings**: a personal prior, a community prior with a usage statement and + an anti-aesthetic prior, each ranking the same pictures, all three written in code with + hand-set weights; a ranking from stated vectors; and one refused for each defect of §9.4, + among them a ranking that does not reproduce, a prior signed by a non-owner, a use the owner's + statement disallows and a prior file not in canonical form. +- **Picks**: picks from an archive (inheriting the elite's genome), from a set and from a + generation, under each kind of objective and undisclosed; and one refused for each defect of + §10.4, among them a pick without `objective` under a policy that requires it and a pick from a + prior-steered archive that states `none`. + +A conforming verifier gives every case the outcome, the reason, the record and the statements +the corpus states. `wai_exploration_vectors verify` and the test `tests/exploration.rs` check +that the file regenerates byte for byte, that `wai-rs` gives every case its outcome, that every +reason of §13 appears, and that §13 lists exactly the reference's codes. +`live-conformance/exploration_verify.py` is the second implementation, written from this text: +it shares no code with `wai-rs`; it implements the generator from Appendix A and the descriptors +from §3, reads usage statements with the AI usage corpus's second implementation +(`ai_usage_verify.py`), checks every signature with WAI's strict rule +(`claim-conformance/_ed25519.py`) and every link hash with BLAKE3 from +`claim-conformance/_blake3.py`; it mutates copies of the corpus and requires every copy to fail, +and drops each of its own checks in turn and requires the corpus to catch the weakened verifier. + +## 15. Security and privacy considerations + +- **Cost.** Replaying an archive costs `trials` generations at its size, and making a default + set sixteen. A verifier bounds what it will spend before it starts; a case it will not + replay under a policy that requires replay is declined, not accepted elite-checked. +- **What is proved.** An elite-checked or replayed archive proves what the generator makes from + each genome, and, replayed, that the schedule kept those pictures. A measured distance proves + how far a work is from the defaults. Neither says who made the work, which the contribution + record and [synthesis](synthesis.md) record. +- **Gaming a distance.** A work far from the defaults is not thereby original: a distance is a + measurement, not a judgement, and a collection statement shows whether many works moved away + from the defaults in the same direction. +- **Taste is personal data.** A personal prior describes what one person likes. It is signed by + that person's key, and a tool cannot publish one in the person's name without that signature + (§8.4). Its owner's usage statement travels with it, and a ranking that uses it states its use + under the owner's key-checked terms. A party that holds a ranking learns how a prior ordered + those pictures, which is what a ranking is for. +- **Undisclosed steering.** A pick without `objective` is reported undisclosed, never as `none`. + A party that steers a selection with a model and states `none` makes a false signed statement; + where the steering came from an archive the pick names, the verifier sees it (§10.2). +- **Descriptors are coarse.** Six numbers do not describe a picture. Two pictures that differ in + every way a viewer cares about can share a vector; coverage counts niches of a grid, not + ideas. + +## Appendix A. The generator, restated + +This appendix restates the reference generator of `wai.generate.spectral`, `generate.rs`, for a +second implementation. The reference governs; the corpus's generations check that the two agree +(§14). Integers here are unbounded or 64-bit as stated; ÷ divides and truncates toward zero; +*a* mod *b* for *b* > 0 is the remainder in 0 to *b* − 1; >> on a negative integer is the floor +of division by a power of two. + +**A.1 The model file** is a JSON object with: `sine_lut`, an array of `lut_size` integers; +`lut_size` (*T*); `lut_bits` (14 when absent); `freq_max`; `amp_bits`; `color_offsets`, three +integers; `base_components`; `step_components`; and `lexicon`, an object mapping a word to an +array of up to ten integers, read as `[r, g, b, freq, orient, radial, mirror, gradient, angular, +spiral]` with absent entries 0. + +**A.2 The intent.** The prompt's ASCII letters are lowered; its **tokens** are its maximal runs of +ASCII letters and digits, in order, each counted every time it occurs. Over the tokens that are +words of the lexicon, sum each of the ten entries; *n* is the number of such tokens. When *n* is +0 the intent is hue (256, 256, 256), freq 256, and every other value 0. Otherwise, with *m* the +greatest of the three colour sums and at least 1: hue*c* = sum*c* · 256 ÷ *m*; freq = sum ÷ *n*; +orient and gradient = sum ÷ *n* clamped to −256 to 256; radial, mirror, angular and spiral = sum +÷ *n* clamped to 0 to 256. + +**A.3 The draw.** *K* = `base_components` + `steps` · `step_components`. With orient < 0, +(*sx*, *sy*) = (max(256 + orient, 0), 256); otherwise (256, max(256 − orient, 0)). *F* = +max(`freq_max` · freq ÷ 256, 1); span = 2*F* + 1; *A* = 2^`amp_bits`. The PRNG is §5.2's +splitmix64, with its state starting at fnv(prompt) ⊕ seed ⊕ 0xD1B54A32D192ED03, where fnv is +64-bit FNV-1a over the prompt's bytes (offset basis 14695981039346656037, prime 1099511628211). +With *t*₁ … *t*₄ = radial, mirror, angular, spiral, *P* = max(256 − Σ*t*, 48) and total = *P* + +Σ*t*, each of the *K* components draws, in this order: pick = draw mod total; *fx* = (draw mod +span) − *F*; *fy* = (draw mod span) − *F*; amp = (draw mod *A*) + 1; phase = draw mod *T*. Its +type is plane when pick < *P*, and otherwise the first *i* from 1 to 4 with pick < *P* + *t*₁ + … + +*t*ᵢ: 1 radial, 2 mirror, 3 angular, 4 spiral. Its frequencies are: radial (max(\|*fx*\|, 2), 0); +angular (\|*fx*\| mod 11 + 2, 0); spiral (\|*fx*\| mod 9 + 2, max(\|*fy*\|, 2)); plane and mirror +(*fx* · *sx* ÷ 256, *fy* · *sy* ÷ 256). + +**A.4 The field.** *cx* = ⌊*w* / 2⌋, *cy* = ⌊*h* / 2⌋; gscale = (2^`lut_bits` · *A* · *K*) ÷ (2048 · +max(*cy*, 1)). For each channel *c* with offset *o* = `color_offsets`[*c*] and each pixel (*x*, +*y*), with *dx* = *x* − *cx*, *dy* = *y* − *cy*, *r* = ⌊√(*dx*² + *dy*²)⌋ and θ = iatan2(*dy*, *dx*): +the accumulator is gradient · (*cy* − *y*) · gscale plus, over the components, amp · +`sine_lut`[arg mod *T*], where arg is *fx* · *x* + *fy* · *y* + phase + *o* for a plane, +*fx* · *r* + phase + *o* for a radial, *fx* · \|*dx*\| + *fy* · \|*dy*\| + phase + *o* for a mirror, +*fx* · θ + phase + *o* for an angular and *fx* · θ + *fy* · *r* + phase + *o* for a spiral component. + +**A.5 iatan2(*dy*, *dx*)**, an angle in 0 to *T* − 1: when *dx* = 0, it is 0 for *dy* = 0, *T* ÷ 4 +for *dy* > 0 and 3*T* ÷ 4 otherwise; when *dy* = 0, 0 for *dx* > 0 and *T* ÷ 2 otherwise. Else, *X* += \|*dx*\| · 2^12, *Y* = \|*dy*\| · 2^12, ang = 0, and for *i* from 0 to 13 with the steps (128, 76, +40, 20, 10, 5, 3, 1, 1, 0, 0, 0, 0, 0): when *Y* > 0, (*X*, *Y*) = (*X* + (*Y* >> *i*), *Y* − (*X* >> +*i*)) and ang increases by the step; when *Y* < 0, (*X*, *Y*) = (*X* − (*Y* >> *i*), *Y* + (*X* >> +*i*)) and ang decreases by it. The angle is ang for *dx* ≥ 0 and *dy* ≥ 0, *T* ÷ 2 − ang for *dx* < 0 +and *dy* ≥ 0, *T* ÷ 2 + ang for *dx* < 0 and *dy* < 0, and *T* − ang for *dx* ≥ 0 and *dy* < 0, each +taken mod *T*. + +**A.6 The bytes.** With *g*₀ and *g*₁ the least and greatest of all 3*n* accumulators and range = +max(*g*₁ − *g*₀, 1), and *e*_c = 64 + hue_c · 192 ÷ 256: each accumulator *v* of channel *c* gives +*q* = ((*v* − *g*₀) · 255 + range ÷ 2) ÷ range and the byte min(max(*q* · *e*_c ÷ 256, 0), 255), at +the pixel's position in the `RGB8` buffer. diff --git a/wai/live-conformance/README.md b/wai/live-conformance/README.md index 34bbb7687..927406da0 100644 --- a/wai/live-conformance/README.md +++ b/wai/live-conformance/README.md @@ -20,6 +20,7 @@ and the independent verifier of each, beside it. | [`c2pa-live/`](c2pa-live/) | [live-provenance](../extensions/live-provenance.md) (`wai.live.provenance`) | `c2pa_live_verify.py` | | [`synthesis/`](synthesis/) | [synthesis](../extensions/synthesis.md) (`wai.media.synthesis`) | `synthesis_verify.py` | | [`usage/`](usage/) | [ai-usage](../extensions/ai-usage.md) (`wai.ai.usage`) | `ai_usage_verify.py` | +| [`exploration/`](exploration/) | [exploration](../extensions/exploration.md) (`wai.media.exploration`) | `exploration_verify.py` | **Provenance.** Generated here: `wai_live_events_vectors gen` writes `events/`, `wai_live_room_vectors gen` writes `rooms/`, `wai_capture_take_vectors gen` writes @@ -29,12 +30,14 @@ writes `recordings/`, `wai_timed_text_vectors gen` writes `captions/` and `steering/`, `wai_live_moderation_vectors gen` writes `moderation/`, `wai_live_watermark_vectors gen` writes `watermark/`, `wai_live_ads_vectors gen` writes `ads/`, `wai_live_provenance_vectors gen` writes `c2pa-live/`, `wai_synthesis_vectors gen` -writes `synthesis/` and `wai_ai_usage_vectors gen` writes `usage/`, each from records authored -in code, from fixed seeds (`events/README.md`, `rooms/README.md`, `takes/README.md`, -`compose/README.md`, `recordings/README.md`, `captions/README.md`, `metering/README.md`, -`steering/README.md`, `moderation/README.md`, `watermark/README.md`, `ads/README.md`, -`c2pa-live/README.md`, `synthesis/README.md`, `usage/README.md`); `c2pa-live/` cuts its media -from the packaging corpus's AV1 floor. `joule_moq_e2ee_vectors gen` (in +writes `synthesis/`, `wai_ai_usage_vectors gen` writes `usage/` and +`wai_exploration_vectors gen` writes `exploration/`, each from records authored in code, from +fixed seeds (`events/README.md`, `rooms/README.md`, `takes/README.md`, `compose/README.md`, +`recordings/README.md`, `captions/README.md`, `metering/README.md`, `steering/README.md`, +`moderation/README.md`, `watermark/README.md`, `ads/README.md`, `c2pa-live/README.md`, +`synthesis/README.md`, `usage/README.md`, `exploration/README.md`); `c2pa-live/` cuts its media +from the packaging corpus's AV1 floor, and `exploration/` makes its pictures with +`wai.generate.spectral` from the committed model file. `joule_moq_e2ee_vectors gen` (in `joule-code/joule-code-rs/crates/joule-moq-mls`) writes `e2ee/vectors.json` from fixed seeds, and `e2ee/` also holds the test vectors RFC 9605 and `draft-ietf-moq-secure-objects-01` publish, as printed (`e2ee/README.md`). One recorded record: `metering/relay-record.wmh` and @@ -60,4 +63,5 @@ python3 live_watermark_verify.py watermark python3 c2pa_live_verify.py c2pa-live python3 synthesis_verify.py synthesis python3 ai_usage_verify.py usage +python3 exploration_verify.py exploration ``` diff --git a/wai/live-conformance/exploration/README.md b/wai/live-conformance/exploration/README.md new file mode 100644 index 000000000..3f73849cc --- /dev/null +++ b/wai/live-conformance/exploration/README.md @@ -0,0 +1,37 @@ +# live-conformance/exploration — exploration and declared taste + +The corpus of [`extensions/exploration.md`](../../extensions/exploration.md) §14, in one file, +`vectors.json`: + +- `model`: the model file of `wai.generate.spectral` every generation uses, by its `path` below + `wai/` and its `sha256`; +- `generations`: a `prompt`, `seed`, `steps`, `width` and `height`, and the `sha256` of the + picture the generator makes (the check of the extension's Appendix A); +- `descriptors`: a buffer, given as `hex` or as a `generate` instruction (`prompt`, `seed`, + `steps`, `width`, `height`), its `width` and `height`, and its descriptor vector (§3); +- `cases`: each a `policy` (`replay`: `required` or `elites`; `objective`: `required` or + `optional`), its `records` in order as JSON texts, and what the verifier `held`: `models` (the + SHA-256 of each model file it holds; the one file above, or none), `priors` (each taste prior + file's text, held by the SHA-256 of its UTF-8 bytes) and `samples` (each buffer, as `hex` or a + `generate` instruction, held by its SHA-256). + +**Exploration equivalence.** For each case, a conforming verifier reaches the outcome it states: + +- `refuse`: the `reason` of §13 and the `record`, the position of the record refused; +- `accept`: the `statements` of §12.3, one per record, exactly as written. + +A verifier that reaches another outcome, reason, record or statement does not conform. + +**Provenance.** `wai_exploration_vectors gen` writes `vectors.json` from records authored in +code: every key is SHA-256 of the corpus's label and an index, every picture is made by +`wai.generate.spectral` from the committed model file `wai-rs/tests/vectors/generate/generate_spectral_model.json` +or derived from one by a rule written in the generator (a corner inverted), the remaining +buffers (a pixel, a row, a column, flat, a checkerboard, a ramp) are written as formulas there, +every time is a constant, and Ed25519 signing is deterministic, so the file is the same bytes on +every machine. The three taste priors are written in code with hand-set weights; none is trained +on anyone's choices. The generator `urn:example:generator:float-1` and the aesthetic model a pick +names stand for any generator and model that are not exact: nothing in the corpus runs them. + +``` +python3 -I ../exploration_verify.py . +``` diff --git a/wai/live-conformance/exploration/vectors.json b/wai/live-conformance/exploration/vectors.json new file mode 100644 index 000000000..80299741b --- /dev/null +++ b/wai/live-conformance/exploration/vectors.json @@ -0,0 +1,3697 @@ +{ + "about": "the conformance corpus of extensions/exploration.md §14, written by wai_exploration_vectors gen", + "model": { + "path": "wai-rs/tests/vectors/generate/generate_spectral_model.json", + "sha256": "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + }, + "generations": [ + { + "prompt": "a calm spectral horizon", + "seed": 7, + "steps": 4, + "width": 17, + "height": 11, + "sha256": "668539bc5f06369fd1bcf4521303f5630626fd46b4c92d55c5abf02a402120bf" + }, + { + "prompt": "ring target", + "seed": 1, + "steps": 2, + "width": 16, + "height": 12, + "sha256": "356c0b7ff488c51385c2e3d2e492010b0944a6a591ffd7680ef312f2f30fd635" + }, + { + "prompt": "Mirror SYMMETRY", + "seed": 2, + "steps": 3, + "width": 13, + "height": 9, + "sha256": "26011b705c443e0be7264187946cea7edf5c11deff7ee94ab7c2b79f6b08f782" + }, + { + "prompt": "sunburst, star; rays", + "seed": 3, + "steps": 1, + "width": 12, + "height": 12, + "sha256": "84fa3d44960bec2760bb2e84b6d8a87c4aeea2e9cb3b9c195ac994569d6dc2d6" + }, + { + "prompt": "spiral vortex", + "seed": 4, + "steps": 5, + "width": 15, + "height": 10, + "sha256": "6d528d758f3bc8111d753d3418206b569a7865ea452be53911daf56c71c40c18" + }, + { + "prompt": "horizon over a sunset abyss", + "seed": 5, + "steps": 3, + "width": 11, + "height": 14, + "sha256": "93fa1a9b19abd9a8d7b57ee78a202f0a9b630e45b2cd23c8014a418bf3f50bb0" + }, + { + "prompt": "tall vertical", + "seed": 6, + "steps": 2, + "width": 9, + "height": 9, + "sha256": "48c13d17b831da9d2a7b7e331ccefd3f734924a7741e43fed80ad0a9412f5900" + }, + { + "prompt": "", + "seed": 0, + "steps": 1, + "width": 1, + "height": 1, + "sha256": "8ecf552136ce820447d70662a5ea1713906c600d56c253cf2a5157cb051e4851" + }, + { + "prompt": "no lexicon words here", + "seed": 4294967295, + "steps": 64, + "width": 3, + "height": 2, + "sha256": "b092a749f0ad2db2ce3dde83db30f4d74426ad968e012f4dfc665e9ca3a36ea8" + }, + { + "prompt": "a quiet forest at night bright calm", + "seed": 123456, + "steps": 7, + "width": 10, + "height": 6, + "sha256": "a25b1084ee1895f64700048da3c4d39e17421ca2237c23265e7d375177304659" + }, + { + "prompt": "halo orb dawn", + "seed": 99, + "steps": 6, + "width": 20, + "height": 1, + "sha256": "e93ce92657208c1c5ade5913f781b8e78ca07fbdd62040971b476950cd46bad7" + }, + { + "prompt": "night night night abyss", + "seed": 42, + "steps": 2, + "width": 1, + "height": 7, + "sha256": "a20fbc1bf2d1e3af92bc9e840eab879fe480493a5ef65893cb99442e82750e1f" + } + ], + "descriptors": [ + { + "hex": "000000", + "about": "one black pixel", + "width": 1, + "height": 1, + "descriptors": [ + 0, + 0, + 0, + 0, + 512, + 512 + ] + }, + { + "hex": "ffffff", + "about": "one white pixel", + "width": 1, + "height": 1, + "descriptors": [ + 1024, + 0, + 0, + 0, + 512, + 512 + ] + }, + { + "hex": "00ff0007f8250ef14a15ea6f1ce394", + "about": "a single row", + "width": 5, + "height": 1, + "descriptors": [ + 617, + 911, + 144, + 655, + 517, + 512 + ] + }, + { + "hex": "00ff0007f8250ef14a15ea6f1ce39423dcb92ad5de", + "about": "a single column", + "width": 1, + "height": 7, + "descriptors": [ + 626, + 860, + 149, + 752, + 512, + 520 + ] + }, + { + "hex": "ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000ff0000", + "about": "flat red", + "width": 4, + "height": 3, + "descriptors": [ + 309, + 1024, + 0, + 0, + 512, + 512 + ] + }, + { + "hex": "0000ffff7f000000ffff7f000000ffff7f00ff7f000000ffff7f000000ffff7f000000ff0000ffff7f000000ffff7f000000ffff7f00ff7f000000ffff7f000000ffff7f000000ff0000ffff7f000000ffff7f000000ffff7f00", + "about": "a checkerboard", + "width": 6, + "height": 5, + "descriptors": [ + 361, + 1024, + 1024, + 512, + 523, + 512 + ] + }, + { + "hex": "00ff0007f8250ef14a15ea6f1ce39423dcb92ad5de31ce0338c7283fc04d46b9724db29754abbc5ba4e1629d0669962b708f507788757e819a857abf8c73e4936c099a652ea15e53a85778af509db649c2bd42e7c43b0ccb3431d22d56d9267be01fa0e718c5ee11ea", + "about": "a ramp", + "width": 7, + "height": 5, + "descriptors": [ + 516, + 583, + 494, + 951, + 521, + 468 + ] + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 0, + "steps": 4, + "width": 24, + "height": 24 + }, + "about": "a generated picture", + "width": 24, + "height": 24, + "descriptors": [ + 400, + 317, + 59, + 853, + 536, + 521 + ] + }, + { + "generate": { + "prompt": "sunburst", + "seed": 5, + "steps": 12, + "width": 31, + "height": 17 + }, + "about": "another generated picture", + "width": 31, + "height": 17, + "descriptors": [ + 446, + 360, + 475, + 915, + 522, + 472 + ] + } + ], + "cases": [ + { + "name": "archive-novelty", + "about": "an archive with no objective: the first trial to reach each niche keeps it; replayed", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"0690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89", + "level": "replayed", + "occupied": 11, + "cells": 16, + "objective": "none" + } + ] + }, + { + "name": "archive-taste", + "about": "an archive whose placement Alice's taste prior decides, scores stated; replayed", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":5},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[595,809,46,96,502,520],\"mods\":2,\"niche\":0,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"score\":5401,\"seed\":1476727604,\"steps\":3,\"trial\":27},{\"descriptors\":[393,687,60,457,543,514],\"mods\":2,\"niche\":1,\"samples\":\"e5e5b19afd328dcf478e3e92e8f6630337d12cf0754a86ce49bc552b955e9582\",\"score\":5613,\"seed\":3972810035,\"steps\":1,\"trial\":9},{\"descriptors\":[332,645,61,744,528,537],\"mods\":0,\"niche\":2,\"samples\":\"9316f52db846823c66cbb49439f5c602515ae6811163d307da111deec6d5dc91\",\"score\":5446,\"seed\":1254822303,\"steps\":4,\"trial\":7},{\"descriptors\":[399,381,84,850,553,516],\"mods\":1,\"niche\":3,\"samples\":\"b507703a709f7b07c4ce3a64e6cc4b49a130b5e051dad2ae406338703e3c1fdd\",\"score\":5247,\"seed\":3931188236,\"steps\":4,\"trial\":29},{\"descriptors\":[384,341,188,861,448,576],\"mods\":0,\"niche\":7,\"samples\":\"f11c5e1c66e6f7d6656c48f9a63f40885952dd94fba0fd90befcd0af2a867a31\",\"score\":4865,\"seed\":871899692,\"steps\":6,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"62707af1355cec8e2b1e338c8cc013fe6afd4758c92babc014c8bf542a0280eeb33add5018a561097e6cdc5f6efb7be9cab7bee466c864e5130e24a370a0bd05\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "fccd244286b1833791596b74dda4cfd47de304f20ba6f865caf8e184590fbdd0", + "level": "replayed", + "occupied": 5, + "cells": 16, + "objective": { + "type": "taste", + "sha256": "d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623" + } + } + ] + }, + { + "name": "archive-no-modifiers", + "about": "an archive with no modifiers: the search varies seeds and steps only; replayed", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":9,\"occupied\":9},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[354,236,147,748,510,539],\"mods\":0,\"niche\":0,\"samples\":\"f30d11e7c6cea028aa3e41a464b16bdad5d765334b11e33a59defa1731d78f6c\",\"score\":null,\"seed\":2049307848,\"steps\":3,\"trial\":2},{\"descriptors\":[316,285,206,875,516,532],\"mods\":0,\"niche\":1,\"samples\":\"0c6eb8a867a061782cf4857d84de2d8f1911d504591d80085ebea33217ce8006\",\"score\":null,\"seed\":284227427,\"steps\":3,\"trial\":4},{\"descriptors\":[353,331,263,929,519,544],\"mods\":0,\"niche\":2,\"samples\":\"6c456bbce43125ee597fec0876f2ec9d77024fb848e79cff4cf53a9bac36710e\",\"score\":null,\"seed\":4093401450,\"steps\":6,\"trial\":16},{\"descriptors\":[343,422,131,743,497,527],\"mods\":0,\"niche\":3,\"samples\":\"53ab57461abf00c0f36a3cc04687c88d990ea3424d6d2a58050bc8c0d333df00\",\"score\":null,\"seed\":2939592817,\"steps\":3,\"trial\":1},{\"descriptors\":[315,446,218,890,501,528],\"mods\":0,\"niche\":4,\"samples\":\"5bd041a59a19c0a9c2ef76ca3fad3d31158bbdf2167eaf198b077b2843aadb75\",\"score\":null,\"seed\":4172122879,\"steps\":3,\"trial\":0},{\"descriptors\":[375,382,259,914,504,513],\"mods\":0,\"niche\":5,\"samples\":\"f35285a3bda80e2469b38d20c049bf270abca0216a2f9cf8f2908d5f075a1b2a\",\"score\":null,\"seed\":784199461,\"steps\":2,\"trial\":22},{\"descriptors\":[379,512,126,800,516,515],\"mods\":0,\"niche\":6,\"samples\":\"8118a3f943cd39453d221343dc573fdb2214cbc0d559da9964c1212cdba8d864\",\"score\":null,\"seed\":1292583810,\"steps\":1,\"trial\":8},{\"descriptors\":[374,478,195,853,507,526],\"mods\":0,\"niche\":7,\"samples\":\"a1c1dfccda30f55e2e899f4a8a66aaf94bc8e7c5f16441dcd1572674e9928b4d\",\"score\":null,\"seed\":2861862458,\"steps\":1,\"trial\":20},{\"descriptors\":[292,479,270,856,507,526],\"mods\":0,\"niche\":8,\"samples\":\"d78c74bf8c58656dc3a4457bd3c552e355522bd90ec90b6ae101974700edbe56\",\"score\":null,\"seed\":3685435525,\"steps\":1,\"trial\":15}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":3,\"descriptor\":\"chroma\",\"hi\":550,\"lo\":250},{\"bins\":3,\"descriptor\":\"detail\",\"hi\":290,\"lo\":140}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[],\"objective\":\"none\",\"prompt\":\"ocean spiral vortex at dusk\",\"search\":{\"init\":6,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":13,\"trials\":24},\"sig\":\"78c770fd87e79cc45503a5bf619fcc1e118622c31b3e86a5217a3c41055557faf35e2fd594f7d4e7e5fcfac31dc9a9016ba2d93f6e6521ed008b943dd541040a\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":3,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "e53a1ca56250c05a1af5a945eb24e59310026a2bf9fb6c99034f52668bb3bb27", + "level": "replayed", + "occupied": 9, + "cells": 9, + "objective": "none" + } + ] + }, + { + "name": "archive-anti-taste", + "about": "the taste archive's request under Bob's prior, which favours the extremes: other elites", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":6},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[713,851,77,412,506,530],\"mods\":0,\"niche\":0,\"samples\":\"e254591a61cd7b16e3b5c9c02eb830911586513dc5b173517f780cd0c9911606\",\"score\":3340,\"seed\":796882670,\"steps\":4,\"trial\":2},{\"descriptors\":[659,871,50,519,511,519],\"mods\":0,\"niche\":1,\"samples\":\"86e4fb8bfd92db78468984b436e1009ffaa9ef0ec8e81c6ef7ca39b2af2318a6\",\"score\":3170,\"seed\":4072210286,\"steps\":4,\"trial\":4},{\"descriptors\":[622,723,48,779,497,513],\"mods\":2,\"niche\":2,\"samples\":\"543a7c2c74912be023093dce3df08b00b8d54ad0929968986f14a9841d4d31c1\",\"score\":2245,\"seed\":41938706,\"steps\":4,\"trial\":22},{\"descriptors\":[707,622,49,841,514,522],\"mods\":0,\"niche\":3,\"samples\":\"c92b5946b5af976cc8da32e78ca3650963ad5dcec4b17aad6119a9830f628d66\",\"score\":2165,\"seed\":2431019465,\"steps\":4,\"trial\":3},{\"descriptors\":[551,527,158,760,548,550],\"mods\":3,\"niche\":6,\"samples\":\"6de44e14d3038a923519ec0c7166cbe9b0159a623b3c9a3e7be295db45b36517\",\"score\":910,\"seed\":2574553426,\"steps\":2,\"trial\":10},{\"descriptors\":[545,356,162,852,536,565],\"mods\":3,\"niche\":7,\"samples\":\"1bb23a2cc6999765a520a0bb88627e7b08c871918f3ccc714a2951abb36e1516\",\"score\":945,\"seed\":871899692,\"steps\":4,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"bob/far\",\"sha256\":\"ab935b4db4bfe92bcaba7995bf8fd145e3db5f83095328c6a5ab25ae5579e3c6\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"1c371c256b8d3f9d0b26c8f69fa186531aaf54737d1d042ea073d5d2287c407fdf5f32e843846aca41047331674e44f6fd9cc63b72cec91784a0c5d61544330e\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"7959dcc87a97c9781f249b2610f50ff525fce1a79ed2246756eeaea3859cf55b\",\"scope\":\"personal\",\"sig\":\"ffe90ff45f05ccc8bb4b107cc1b3de3615fc3f447049e7884b9fe2b47b26b29ab72c8140a1a1df508f70ace5ee8e018bc04bc72498d5764d565ed92b9af85000\",\"signer_pubkey\":\"7959dcc87a97c9781f249b2610f50ff525fce1a79ed2246756eeaea3859cf55b\",\"terms\":[{\"at\":448,\"descriptor\":\"luma\",\"shape\":\"far\",\"weight\":5},{\"at\":448,\"descriptor\":\"chroma\",\"shape\":\"far\",\"weight\":5}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "bbc38717b3976ead34b86bfbfe6830c8c636f66d3747d7bb9d0c448403a85170", + "level": "replayed", + "occupied": 6, + "cells": 16, + "objective": { + "type": "taste", + "sha256": "ab935b4db4bfe92bcaba7995bf8fd145e3db5f83095328c6a5ab25ae5579e3c6" + } + } + ] + }, + { + "name": "archive-elites-checked", + "about": "the novelty archive under a policy that checks its elites and does not replay", + "policy": { + "replay": "elites", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"0690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89", + "level": "elites", + "occupied": 11, + "cells": 16, + "objective": "none" + } + ] + }, + { + "name": "archive-descriptor-not-recomputed", + "about": "an elite whose detail is stated one higher than its picture's", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,184,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"2c28bff1ba324ef3bf441ad70d270300d72f3740ab25addbb0104efe9b64aef7ec58fdd1a57424a77a80cd69f4ec0626866e2f42456f9cbae8bfecba68ca4e01\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "descriptor_mismatch", + "record": 0 + }, + { + "name": "archive-seed-not-regenerating", + "about": "an elite whose seed does not regenerate the picture it names", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501157,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"cf40945a6d6e7e741b52cd479ea94f34310171c6efdcb5d08f02a5b2d7e54ed1574c3cead119131e99608e65faf5a65c45a9737414870f86ca57a5fe8d23730d\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "generation_mismatch", + "record": 0 + }, + { + "name": "archive-niche-wrong", + "about": "an elite placed in the next niche, which its descriptors do not fall in", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":8,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"1b2a9019900fe21dbbb0b901dcf66790e15301cf1b1351e45bd5cd9356026c642d5c4b3af31414ef53388d2862c34a9f1dea249bd9915234e8b14862925aed0f\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "niche_mismatch", + "record": 0 + }, + { + "name": "archive-score-wrong", + "about": "an elite of the taste archive whose score is stated one higher", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":5},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[595,809,46,96,502,520],\"mods\":2,\"niche\":0,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"score\":5402,\"seed\":1476727604,\"steps\":3,\"trial\":27},{\"descriptors\":[393,687,60,457,543,514],\"mods\":2,\"niche\":1,\"samples\":\"e5e5b19afd328dcf478e3e92e8f6630337d12cf0754a86ce49bc552b955e9582\",\"score\":5613,\"seed\":3972810035,\"steps\":1,\"trial\":9},{\"descriptors\":[332,645,61,744,528,537],\"mods\":0,\"niche\":2,\"samples\":\"9316f52db846823c66cbb49439f5c602515ae6811163d307da111deec6d5dc91\",\"score\":5446,\"seed\":1254822303,\"steps\":4,\"trial\":7},{\"descriptors\":[399,381,84,850,553,516],\"mods\":1,\"niche\":3,\"samples\":\"b507703a709f7b07c4ce3a64e6cc4b49a130b5e051dad2ae406338703e3c1fdd\",\"score\":5247,\"seed\":3931188236,\"steps\":4,\"trial\":29},{\"descriptors\":[384,341,188,861,448,576],\"mods\":0,\"niche\":7,\"samples\":\"f11c5e1c66e6f7d6656c48f9a63f40885952dd94fba0fd90befcd0af2a867a31\",\"score\":4865,\"seed\":871899692,\"steps\":6,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"2610ba06cd361e6c57bf09083b0ecbd50923050f9946faa9148aff62de662dda6f070b3ba89f33f49b63c649d8f5d6240d26be11c9623fa9fa4a7540434f150e\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "refuse", + "reason": "score_mismatch", + "record": 0 + }, + { + "name": "archive-coverage-wrong", + "about": "an archive that states one more occupied niche than it lists", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":12},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"006c51f028eb9d718c240d93a101abd6f24f215b16f3e8e454b8015a9d35d472d2b608a57b1ab3f46d9f289716dfab395734cff9edb4bc0e087f8d5d94c2e10b\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "coverage_mismatch", + "record": 0 + }, + { + "name": "archive-elite-dropped", + "about": "the novelty archive without its last elite: every elite checks, and replay finds the one left out", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":10},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"a5e5faab4ae3984ff2f7a629e21c2b8481d8c41978764df1eb4a3f540a35cffa5b085d10a85fb6bfc6cdf6b5e53641588c57b19113e52db2ecf17d483d131b09\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "archive_replay_mismatch", + "record": 0 + }, + { + "name": "archive-elite-dropped-unreplayed", + "about": "the same archive, elite-checked only: accepted, and reported as not replayed", + "policy": { + "replay": "elites", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":10},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"a5e5faab4ae3984ff2f7a629e21c2b8481d8c41978764df1eb4a3f540a35cffa5b085d10a85fb6bfc6cdf6b5e53641588c57b19113e52db2ecf17d483d131b09\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "d85cc6a50ce6cdaa748f9c4fe6ad24aa8c34ed7cce17178ad9510501396203dc", + "level": "elites", + "occupied": 10, + "cells": 16, + "objective": "none" + } + ] + }, + { + "name": "archive-model-unheld", + "about": "an archive whose model file the verifier does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"0690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "model_unheld", + "record": 0 + }, + { + "name": "archive-prior-unresolved", + "about": "a taste archive whose prior the verifier does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":5},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[595,809,46,96,502,520],\"mods\":2,\"niche\":0,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"score\":5401,\"seed\":1476727604,\"steps\":3,\"trial\":27},{\"descriptors\":[393,687,60,457,543,514],\"mods\":2,\"niche\":1,\"samples\":\"e5e5b19afd328dcf478e3e92e8f6630337d12cf0754a86ce49bc552b955e9582\",\"score\":5613,\"seed\":3972810035,\"steps\":1,\"trial\":9},{\"descriptors\":[332,645,61,744,528,537],\"mods\":0,\"niche\":2,\"samples\":\"9316f52db846823c66cbb49439f5c602515ae6811163d307da111deec6d5dc91\",\"score\":5446,\"seed\":1254822303,\"steps\":4,\"trial\":7},{\"descriptors\":[399,381,84,850,553,516],\"mods\":1,\"niche\":3,\"samples\":\"b507703a709f7b07c4ce3a64e6cc4b49a130b5e051dad2ae406338703e3c1fdd\",\"score\":5247,\"seed\":3931188236,\"steps\":4,\"trial\":29},{\"descriptors\":[384,341,188,861,448,576],\"mods\":0,\"niche\":7,\"samples\":\"f11c5e1c66e6f7d6656c48f9a63f40885952dd94fba0fd90befcd0af2a867a31\",\"score\":4865,\"seed\":871899692,\"steps\":6,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"62707af1355cec8e2b1e338c8cc013fe6afd4758c92babc014c8bf542a0280eeb33add5018a561097e6cdc5f6efb7be9cab7bee466c864e5130e24a370a0bd05\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "objective_unresolved", + "record": 0 + }, + { + "name": "archive-prior-not-owner", + "about": "a taste archive whose prior names Alice as owner and is signed by another key", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":5},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[595,809,46,96,502,520],\"mods\":2,\"niche\":0,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"score\":5401,\"seed\":1476727604,\"steps\":3,\"trial\":27},{\"descriptors\":[393,687,60,457,543,514],\"mods\":2,\"niche\":1,\"samples\":\"e5e5b19afd328dcf478e3e92e8f6630337d12cf0754a86ce49bc552b955e9582\",\"score\":5613,\"seed\":3972810035,\"steps\":1,\"trial\":9},{\"descriptors\":[332,645,61,744,528,537],\"mods\":0,\"niche\":2,\"samples\":\"9316f52db846823c66cbb49439f5c602515ae6811163d307da111deec6d5dc91\",\"score\":5446,\"seed\":1254822303,\"steps\":4,\"trial\":7},{\"descriptors\":[399,381,84,850,553,516],\"mods\":1,\"niche\":3,\"samples\":\"b507703a709f7b07c4ce3a64e6cc4b49a130b5e051dad2ae406338703e3c1fdd\",\"score\":5247,\"seed\":3931188236,\"steps\":4,\"trial\":29},{\"descriptors\":[384,341,188,861,448,576],\"mods\":0,\"niche\":7,\"samples\":\"f11c5e1c66e6f7d6656c48f9a63f40885952dd94fba0fd90befcd0af2a867a31\",\"score\":4865,\"seed\":871899692,\"steps\":6,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"ca12a734fce4a5f9d7e25b71b0393ec0a49f6a9f159e4952fb7ff8c39547153c\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"d106a73ceff5f00836bbad5f029f4ded46167de1607600f1293ef8fd58e1e2a8062763075d1337206f737ae5d9f8ced520bc448700ff7f1e443a82d0f65ef205\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"d0429b03b1b7ef385d762bf528b8bd4341451477983cfe658f9dddd6eadd6506197e3153e8b837fe80cdc3892ab58a90e52d23336f70eb49c1fed884e93a8503\",\"signer_pubkey\":\"ebbb60a9e22a5d1f3f526f09df3004b7c9904077fc46d55c6de65d39e5271b0d\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "refuse", + "reason": "taste_not_owner", + "record": 0 + }, + { + "name": "archive-bad-signature", + "about": "an archive whose signature does not verify", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"1690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "bad_signature", + "record": 0 + }, + { + "name": "archive-bad-key", + "about": "an archive signed under the identity point, a key of small order", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"0690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"0100000000000000000000000000000000000000000000000000000000000000\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "bad_key", + "record": 0 + }, + { + "name": "archive-grid-empty-axis", + "about": "an archive whose axis has lo equal to hi", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":128,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"aa602290cd35803f9369b3825b1ddd441d2cf0bb0a90924d1309e9154fd7f1e939e9c543c4b4ef66a0166b0ecceee2a4acb2595db2006bcd568f06eea2c4c90b\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "record_malformed", + "record": 0 + }, + { + "name": "archive-model-objective", + "about": "an archive whose placement a model the verifier cannot run decides: it could not be replayed", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":{\"id\":\"urn:example:aesthetic-model\",\"sha256\":\"0707070707070707070707070707070707070707070707070707070707070707\",\"type\":\"model\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"f66063be82caa9a3feea68377e4eaa5a75c972e929afed7d2786e5248b211c42c092527c83d8bb6f40b800d6a0c7628f0c3dbc1ca6862aeded66a0ce91fa950a\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "record_malformed", + "record": 0 + }, + { + "name": "distance-measured-pulled", + "about": "a work made with another word, more steps and another seed: measured from the sixteen defaults", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"eaecfa060c65af22713b7ed388776cd5eac0424ee473a4f54ea46988e96c7569fc754716419c71dea2856978b541bcc1d0bab585c2e00b4011bc2f8c88d2d802\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-distance", + "link": "ca621301ae198aa49ab85fd72ca1ddb179929b9534b242e289f09712785782a1", + "class": "measured", + "descriptor_distance": 403, + "nearest_descriptor": 5, + "sample_distance": 89, + "nearest_sample": 10 + } + ] + }, + { + "name": "distance-measured-default", + "about": "a work that is default seed 3 itself: sample distance 0, nearest 3", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":0,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":3,\"nearest_sample\":3,\"prompt\":\"a quiet forest at night\",\"sample_distance\":0,\"sig\":\"4cdb08309568d416c90f7b23b5f1f4e6e794268939a819f494a268b9d3c9a1ef9d2df02ac3ea8616cf246205e6816f500bea9e076a351153fb018e227815f808\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[517,435,127,855,510,564],\"height\":24,\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 3, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-distance", + "link": "2970f2bc77d6a93dce38200dd0c43c764c10c62dcc0a6d217d6c916158d8dfdd", + "class": "measured", + "descriptor_distance": 0, + "nearest_descriptor": 3, + "sample_distance": 0, + "nearest_sample": 3 + } + ] + }, + { + "name": "distance-measured-edited", + "about": "default seed 3 with a corner inverted afterwards: near it, and not it", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":107,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":3,\"nearest_sample\":3,\"prompt\":\"a quiet forest at night\",\"sample_distance\":51,\"sig\":\"90cffef1472f1a26d70c6c08ac7da921260d5b167a305fbc196506b5763734cf0fa183f2ff7f1d7bc11d0cffa89e6c1607bcc82c12e739ad6d8be2474bb25c0d\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[538,435,158,882,498,548],\"height\":24,\"samples\":\"fcbda9073a05dfc97f83704643dc971d23daf768bf4187db81c23530e0a3f0be\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "hex": "56b3fc52b7fe4fbaff4dbdff4bbfff4ac1ff49c3ff48c4ffb73a01b63a02b53a04b23a06b03b09ad3c0caa3d0fa63f13a141179c431b9646209149258a4c2a844f317d523675563d5bacf657aff754b3f852b5f851b8f84fbaf84fbcf84ebdf7b04109b0410bae410dad410eaa4211a74314a344189f461b9b481f964a24904d288a502d8453337d5638765a3f6e5d4560a4f15da8f15aabf258aef257b1f255b3f154b4f054b6efab4811a94813a84815a64817a3491aa14a1c9d4b20994d24944f278f522c8a54318457357d5a3b775e4170614668654d659deb62a0eb5fa4eb5ea7eb5ca9ea5babe95aade85aaee7a4501aa34f1aa14f1d9f4f1f9d50229a512596532892542c8e5630895934835b397d5e3e77624270654869694e626c546a95e56799e5659ce5639fe462a2e461a4e361a6e161a7e09e57219d56239b562599572796572a93582d8f5a318c5c34875e3882603d7d634177664570694b6a6c4f6370555c745c6e8ddf6c91df6a95de6998dd689adc679cdb669ed967a0d8975e28965e2b945e2d925e308f5f338c603589613984633d8065417b6844766a49706d4e6a71526374585d785c567b627386d9718ad8708dd86e90d76e93d66d95d46d97d26d98d09166319065338e65358c653889663b86673e8269427e6b447a6d49756f4d7072516a755563785a5e7c5f567f64508369787ed47682d37586d17489d0738bce738ecc738fcb7391c98b6d388a6d3a876d3d856d40826e427f6f467b704978724d7374506e7754697959637d5d5e806257836751876b4a8b71828831848433858134867e35877b3787793987773b86763e8475408374428174457f74487c754b78764e757851717a556c7c59687e5c6381605d8465578769518b6d4b8f734593777d8f377f8c387f883a80853c81833e818041807f427f7d447e7c477d7c4a7a7c4d787c4f757d52727e566e7f596b815c6683606186645c8968568c6c518f704b93754596793f9a7e79973d7a933f7a8f417b8c427b8a457b88477a864a7a854c78844f7783517583547284576f845a6b855d688760648964608b685b8e6b56906f5194734b9777459a7b3f9e8039a284759e42759a4476974776944976914c758f4e758d50748c53738b56708b596e8b5c6c8b5e688c62668d65628f695e906b59936f5595735098774b9b7a459e7e3fa2833aa68634aa8a70a44871a14b719d4d719b4f7198527096557094586e935b6d925d6b92606892636692666393695f956c5c966f589873549a774f9d794aa07d45a38140a6843aaa8835ad8d2fb1916cab4e6da7506da4536da2566c9f596b9d5c6a9c5e689a61679a6465996763996a609a6d5d9b70599c74569e77529f7a4ea27d4aa48145a7843faa873aae8b35b18f30b5922ab99668b15368ae5668ab5968a85c67a65f66a46265a36563a16861a16a60a16e5da1715aa17457a27754a37a50a57d4ca78148a98444ac873faf8a3ab28e35b59130b8942bbc9826c09c64b85964b45c64b15f63af6263ad6561ab6960a96b5ea86e5ca8725aa87558a87755a87b51a97e4fab814bac8447ae8743b08a3fb38e3ab69135b99430bc972bc09b26c39e21c7a061be5e61ba6160b8655fb5685eb36b5db16e5cb07259af7557af7855ae7b52af7e50af824cb0844ab28746b38b42b58e3eb8913aba9335bd9731c09a2cc49d27c79f23cba31ecea65ec3645dc0675cbe6a5cbb6e5ab97159b87556b77855b67b53b57f50b5824eb6844bb68847b78b45b98e41ba913dbc9439bf9735c19a31c49d2cc79f28cba223cea51ed2a81ad5ab5ac96959c66c59c37057c17456bf7754be7b53bd7e51bc824ebc844cbc8849bc8b46bd8e43be913fc0943cc19738c39a35c69d30c89f2dcba228cea524d2a720d5aa1bd9ac17dcae57ce6e56cb7255c97654c77952c57d51c4814fc3844cc2874ac28b47c28e45c39142c4943fc5973bc69a38c89d34ca9f30cda22dcfa528d2a725d5aa21d8ac1cdcae18dfb114e3b355d37454d07752ce7b51cc7f4fcb834dca864bc98a49c88e46c89143c99341c9973dca9a3acb9d38cd9f34cfa230d1a52dd3a829d6aa25d9ac21dcae1ddfb019e2b315e6b511e9b752d77951d57d4fd3814ed2844cd0884acf8c47cf9045ce9342ce963fcf9a3dcf9d3ad09f37d2a233d3a530d5a82dd7aa29daac26dcae22dfb11ee2b31ae5b517e9b712ecb90ff0ba50dc7e4fda834cd8864bd68a49d58e47d49144d49542d4993fd49c3dd49f3ad5a236d6a533d8a830d9ab2ddbac29ddaf26e0b123e2b31fe5b61ce8b818ecb914efba10f2bc0cf6bd4fe0844cde874adc8c48db9046da9344da9741d99b3fd99e3cd9a139daa436dba733dcaa30ddac2ddfaf2ae1b126e3b423e6b620e8b81cebb919eebb16f2bc12f5be0ff8bf0bfcc1" + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-distance", + "link": "98aa84ef0ef4e58b32b54db46f202ef58d64c1a076066739b00355d4b999912b", + "class": "measured", + "descriptor_distance": 107, + "nearest_descriptor": 3, + "sample_distance": 51, + "nearest_sample": 3 + } + ] + }, + { + "name": "distance-estimate", + "about": "a generator that is not exact: its defaults are stated, and the figure is an estimate", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"estimate\",\"defaults\":[{\"descriptors\":[300,420,90,700,512,500],\"samples\":null},{\"descriptors\":[360,380,120,760,505,520],\"samples\":null},{\"descriptors\":[280,500,60,640,515,480],\"samples\":null},{\"descriptors\":[410,350,140,800,500,510],\"samples\":null}],\"descriptor_distance\":630,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"urn:example:generator:float-1\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"urn:example:model:float-1\",\"nearest_descriptor\":2,\"nearest_sample\":null,\"prompt\":\"a quiet forest at night\",\"sample_distance\":null,\"sig\":\"68e74160e315636cac0481515418965bd5de7e8c6b0d4ce3827e3c5225a984e6299ea4f1f2e2ed603695f6a4d52ed43cfd702a31b1e88c97f8900fc5074c380d\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-distance", + "link": "62e892ef623f337059ef227143a7c1cd44a3f5a87a2f27871cb26d756780188e", + "class": "estimate", + "descriptor_distance": 630, + "nearest_descriptor": 2, + "sample_distance": null, + "nearest_sample": null + } + ] + }, + { + "name": "distance-unknown", + "about": "no default set is known: every figure is null, reported unknown", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"unknown\",\"defaults\":[],\"descriptor_distance\":null,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"urn:example:generator:float-1\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"urn:example:model:float-1\",\"nearest_descriptor\":null,\"nearest_sample\":null,\"prompt\":\"a quiet forest at night\",\"sample_distance\":null,\"sig\":\"da574e845a12df8d439b5b4b38414f79225b00430a1d79a594f42e8af739df253689ff2e0137dc6bfce06e13dc698c676441931ebcc5d3e4201bd3c8cc172f01\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-distance", + "link": "85582f0597062089407550a016d8873f0b580053c9abc11669c9dcdaa0eead86", + "class": "unknown", + "descriptor_distance": null, + "nearest_descriptor": null, + "sample_distance": null, + "nearest_sample": null + } + ] + }, + { + "name": "distance-unknown-as-zero", + "about": "an unknown figure written as 0, which would state that the work is a default", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"unknown\",\"defaults\":[],\"descriptor_distance\":0,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"urn:example:generator:float-1\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"urn:example:model:float-1\",\"nearest_descriptor\":null,\"nearest_sample\":null,\"prompt\":\"a quiet forest at night\",\"sample_distance\":null,\"sig\":\"03894f0f98a6c4a9b79e89a78a5a101249add88f774763615a9f983354cf8dfa619b4d2339a6f1f9a1e23796982f1e224e29c484b89c58071cd41f430a9f0402\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "record_malformed", + "record": 0 + }, + { + "name": "distance-stated-wrong", + "about": "a measured descriptor distance stated one higher than the defaults give", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":404,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"e564bc68ec21a46a25f48cc7fedfd92a0f7b4aad118aa47f6e350c9143af35197890c36ab5fffe9e3b0f83fdf73b1ee4c67ac54beb4425b0136a1a640f490c0e\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "distance_mismatch", + "record": 0 + }, + { + "name": "distance-sample-stated-wrong", + "about": "a measured sample distance stated one lower", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":88,\"sig\":\"9a03159dcf1ccd0cf1d94559ec35fe6fcde1944601192a1a1a406b31cb78736ea30270feda8ab5c7249672357c9bb325edb3a03816cdbdded43004b928252509\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "distance_mismatch", + "record": 0 + }, + { + "name": "distance-measured-not-exact", + "about": "a measured figure over a generator that is not exact", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"urn:example:generator:float-1\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"urn:example:model:float-1\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"489d55b01a367c980619e2b63d562e28cba55a02f5dd43f2fa087f5dea7cf70a0aec00fdbb2e16652a7887a2220bbdc04221ef65f18569748e517547fe42ae00\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "distance_class_invalid", + "record": 0 + }, + { + "name": "distance-estimate-for-exact", + "about": "the exact generator's figure stated as an estimate", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"estimate\",\"defaults\":[{\"descriptors\":[300,420,90,700,512,500],\"samples\":null},{\"descriptors\":[360,380,120,760,505,520],\"samples\":null},{\"descriptors\":[280,500,60,640,515,480],\"samples\":null},{\"descriptors\":[410,350,140,800,500,510],\"samples\":null}],\"descriptor_distance\":630,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":2,\"nearest_sample\":null,\"prompt\":\"a quiet forest at night\",\"sample_distance\":null,\"sig\":\"8f538633ae774906c591a3752385a4303898b4bc14d2ca2c2b5d5210dfa9e180d5cbe5dc6784d154d06965d9687d76581b9f5e638361e89f344390ebf881e605\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "distance_class_invalid", + "record": 0 + }, + { + "name": "distance-default-wrong", + "about": "a default whose samples digest is not what seed 5 makes", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"8d7cddd34fb62d6a5cda6828ea8a8fb7308aef08936c4dbe2bcc2e8577e64b00792c4cefde5df00433a833dbb104a5d6d362e6c25f91c8a75c29d1b4c5902b0f\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "default_mismatch", + "record": 0 + }, + { + "name": "distance-work-unheld", + "about": "a measured distance whose work the verifier does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"eaecfa060c65af22713b7ed388776cd5eac0424ee473a4f54ea46988e96c7569fc754716419c71dea2856978b541bcc1d0bab585c2e00b4011bc2f8c88d2d802\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "work_unheld", + "record": 0 + }, + { + "name": "distance-work-descriptors-wrong", + "about": "a work whose luma is stated one higher than its samples give", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"1979cf81f07354829e219e7c83d0d1af59ce72fb6a52eba74c9685af18dc2e0b63b67c732816084a56e5ad5a8b0c36d29c48248d6803c71268cac3be478c810a\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[238,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "descriptor_mismatch", + "record": 0 + }, + { + "name": "distance-work-wrong-size", + "about": "a work stated one row shorter than the samples its digest names", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"41c392b660413fd5f54e123e51d751a54f1f018e0c57f9021f5b34eded62a7fad5aa343171685c20a0be273a100d3d19a8f290e5c93479499c19576f61077b0e\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":23,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "samples_mismatch", + "record": 0 + }, + { + "name": "distance-model-unheld", + "about": "a measured distance whose model file the verifier does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"class\":\"measured\",\"defaults\":[{\"descriptors\":[400,317,59,853,536,521],\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\"},{\"descriptors\":[613,842,79,205,504,533],\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\"},{\"descriptors\":[390,679,92,375,542,540],\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\"},{\"descriptors\":[517,435,127,855,510,564],\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"},{\"descriptors\":[489,410,124,896,473,539],\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\"},{\"descriptors\":[338,582,83,522,493,542],\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\"},{\"descriptors\":[357,339,189,903,473,610],\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\"},{\"descriptors\":[447,298,146,804,519,571],\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\"},{\"descriptors\":[285,522,101,825,451,540],\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\"},{\"descriptors\":[635,768,51,530,506,524],\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\"},{\"descriptors\":[242,692,87,735,552,503],\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\"},{\"descriptors\":[405,684,101,590,506,567],\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\"},{\"descriptors\":[463,478,182,878,552,574],\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\"},{\"descriptors\":[669,895,24,10,512,517],\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\"},{\"descriptors\":[545,289,44,886,503,513],\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\"},{\"descriptors\":[630,613,133,824,540,537],\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\"}],\"descriptor_distance\":403,\"descriptors\":\"wai-exploration:image6\",\"generator\":\"wai.generate.spectral\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-distance\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"nearest_descriptor\":5,\"nearest_sample\":10,\"prompt\":\"a quiet forest at night\",\"sample_distance\":89,\"sig\":\"eaecfa060c65af22713b7ed388776cd5eac0424ee473a4f54ea46988e96c7569fc754716419c71dea2856978b541bcc1d0bab585c2e00b4011bc2f8c88d2d802\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"work\":{\"descriptors\":[237,811,86,487,504,566],\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night dark", + "seed": 9001, + "steps": 9, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "model_unheld", + "record": 0 + }, + { + "name": "collection-defaults", + "about": "a gallery of the prompt's sixteen defaults: few cells, short distances", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":8},\"descriptors\":\"wai-exploration:image6\",\"distances\":{\"histogram\":[0,0,1,1,6,11,6,10,8,7,5,10,9,4,10,32],\"max\":2058,\"median\":742,\"min\":159,\"pairs\":120,\"sum\":95760,\"width\":64},\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-collection\",\"members\":[{\"descriptors\":[400,317,59,853,536,521],\"height\":24,\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"width\":24},{\"descriptors\":[613,842,79,205,504,533],\"height\":24,\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"width\":24},{\"descriptors\":[390,679,92,375,542,540],\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24},{\"descriptors\":[517,435,127,855,510,564],\"height\":24,\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\",\"width\":24},{\"descriptors\":[489,410,124,896,473,539],\"height\":24,\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\",\"width\":24},{\"descriptors\":[338,582,83,522,493,542],\"height\":24,\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\",\"width\":24},{\"descriptors\":[357,339,189,903,473,610],\"height\":24,\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\",\"width\":24},{\"descriptors\":[447,298,146,804,519,571],\"height\":24,\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\",\"width\":24},{\"descriptors\":[285,522,101,825,451,540],\"height\":24,\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\",\"width\":24},{\"descriptors\":[635,768,51,530,506,524],\"height\":24,\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\",\"width\":24},{\"descriptors\":[242,692,87,735,552,503],\"height\":24,\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\",\"width\":24},{\"descriptors\":[405,684,101,590,506,567],\"height\":24,\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\",\"width\":24},{\"descriptors\":[463,478,182,878,552,574],\"height\":24,\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\",\"width\":24},{\"descriptors\":[669,895,24,10,512,517],\"height\":24,\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\",\"width\":24},{\"descriptors\":[545,289,44,886,503,513],\"height\":24,\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\",\"width\":24},{\"descriptors\":[630,613,133,824,540,537],\"height\":24,\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\",\"width\":24}],\"scope\":\"gallery\",\"sig\":\"ffed3630c89aa0c106ca3d31ef7962e6b1976742baac79796f57d4b2f872bd37af978b7845425c457dedeb67a65efd2e1dc15aa980fbab8a1373b87766a9c207\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"subject\":\"urn:example:gallery:defaults\"}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 0, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 2, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 3, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 5, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 6, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 7, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 8, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 9, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 10, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 11, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 12, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 13, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 14, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 15, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-collection", + "link": "962f4798db0f02f8ebcc9296944a0050a558448a33fc303fc946caada6f26b70", + "members": 16, + "occupied": 8, + "cells": 16, + "distances": { + "pairs": 120, + "sum": 95760, + "min": 159, + "median": 742, + "max": 2058, + "width": 64, + "histogram": [ + 0, + 0, + 1, + 1, + 6, + 11, + 6, + 10, + 8, + 7, + 5, + 10, + 9, + 4, + 10, + 32 + ] + } + } + ] + }, + { + "name": "collection-archive", + "about": "the novelty archive's elites as a collection: one per niche", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"distances\":{\"histogram\":[0,0,0,3,2,3,1,6,5,2,9,4,4,4,5,7],\"max\":1509,\"median\":686,\"min\":217,\"pairs\":55,\"sum\":38262,\"width\":64},\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-collection\",\"members\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24},{\"descriptors\":[347,673,100,427,533,550],\"height\":24,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"width\":24},{\"descriptors\":[360,745,53,407,496,522],\"height\":24,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"width\":24},{\"descriptors\":[631,434,81,854,491,497],\"height\":24,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"width\":24},{\"descriptors\":[622,576,81,802,530,527],\"height\":24,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"width\":24},{\"descriptors\":[647,865,49,461,499,513],\"height\":24,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"width\":24}],\"scope\":\"archive\",\"sig\":\"ee70622c4ae4364afc983741ed61ea195e3e47d3413ebe2fce79dd2f6d7df6443ac85fef39549d2639fc9cce6c38741071e86a4a79cb694a8c7d8e07bc443001\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"subject\":\"c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89\"}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1213784844, + "steps": 2, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 2832323450, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 1433734301, + "steps": 7, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 595603613, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 895832808, + "steps": 8, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-collection", + "link": "99568f4580a219460e82e2b96e0857fb97a16743137f43a8cdbc0356a11e99fc", + "members": 11, + "occupied": 11, + "cells": 16, + "distances": { + "pairs": 55, + "sum": 38262, + "min": 217, + "median": 686, + "max": 1509, + "width": 64, + "histogram": [ + 0, + 0, + 0, + 3, + 2, + 3, + 1, + 6, + 5, + 2, + 9, + 4, + 4, + 4, + 5, + 7 + ] + } + } + ] + }, + { + "name": "collection-coverage-wrong", + "about": "the defaults' gallery stating one more occupied cell", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":9},\"descriptors\":\"wai-exploration:image6\",\"distances\":{\"histogram\":[0,0,1,1,6,11,6,10,8,7,5,10,9,4,10,32],\"max\":2058,\"median\":742,\"min\":159,\"pairs\":120,\"sum\":95760,\"width\":64},\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-collection\",\"members\":[{\"descriptors\":[400,317,59,853,536,521],\"height\":24,\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"width\":24},{\"descriptors\":[613,842,79,205,504,533],\"height\":24,\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"width\":24},{\"descriptors\":[390,679,92,375,542,540],\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24},{\"descriptors\":[517,435,127,855,510,564],\"height\":24,\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\",\"width\":24},{\"descriptors\":[489,410,124,896,473,539],\"height\":24,\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\",\"width\":24},{\"descriptors\":[338,582,83,522,493,542],\"height\":24,\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\",\"width\":24},{\"descriptors\":[357,339,189,903,473,610],\"height\":24,\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\",\"width\":24},{\"descriptors\":[447,298,146,804,519,571],\"height\":24,\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\",\"width\":24},{\"descriptors\":[285,522,101,825,451,540],\"height\":24,\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\",\"width\":24},{\"descriptors\":[635,768,51,530,506,524],\"height\":24,\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\",\"width\":24},{\"descriptors\":[242,692,87,735,552,503],\"height\":24,\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\",\"width\":24},{\"descriptors\":[405,684,101,590,506,567],\"height\":24,\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\",\"width\":24},{\"descriptors\":[463,478,182,878,552,574],\"height\":24,\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\",\"width\":24},{\"descriptors\":[669,895,24,10,512,517],\"height\":24,\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\",\"width\":24},{\"descriptors\":[545,289,44,886,503,513],\"height\":24,\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\",\"width\":24},{\"descriptors\":[630,613,133,824,540,537],\"height\":24,\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\",\"width\":24}],\"scope\":\"gallery\",\"sig\":\"aea563640d9773f56334e14d0f055b4bc9ae1a333b979b57d6190f4570726c83584f64c0fb4b13d551f7e34c3cbb25e19735acc0d5452bab271981965629ac05\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"subject\":\"urn:example:gallery:defaults\"}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 0, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 2, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 3, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 5, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 6, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 7, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 8, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 9, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 10, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 11, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 12, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 13, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 14, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 15, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "coverage_mismatch", + "record": 0 + }, + { + "name": "collection-median-wrong", + "about": "the defaults' gallery stating its median one higher", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":8},\"descriptors\":\"wai-exploration:image6\",\"distances\":{\"histogram\":[0,0,1,1,6,11,6,10,8,7,5,10,9,4,10,32],\"max\":2058,\"median\":743,\"min\":159,\"pairs\":120,\"sum\":95760,\"width\":64},\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-collection\",\"members\":[{\"descriptors\":[400,317,59,853,536,521],\"height\":24,\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"width\":24},{\"descriptors\":[613,842,79,205,504,533],\"height\":24,\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"width\":24},{\"descriptors\":[390,679,92,375,542,540],\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24},{\"descriptors\":[517,435,127,855,510,564],\"height\":24,\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\",\"width\":24},{\"descriptors\":[489,410,124,896,473,539],\"height\":24,\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\",\"width\":24},{\"descriptors\":[338,582,83,522,493,542],\"height\":24,\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\",\"width\":24},{\"descriptors\":[357,339,189,903,473,610],\"height\":24,\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\",\"width\":24},{\"descriptors\":[447,298,146,804,519,571],\"height\":24,\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\",\"width\":24},{\"descriptors\":[285,522,101,825,451,540],\"height\":24,\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\",\"width\":24},{\"descriptors\":[635,768,51,530,506,524],\"height\":24,\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\",\"width\":24},{\"descriptors\":[242,692,87,735,552,503],\"height\":24,\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\",\"width\":24},{\"descriptors\":[405,684,101,590,506,567],\"height\":24,\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\",\"width\":24},{\"descriptors\":[463,478,182,878,552,574],\"height\":24,\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\",\"width\":24},{\"descriptors\":[669,895,24,10,512,517],\"height\":24,\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\",\"width\":24},{\"descriptors\":[545,289,44,886,503,513],\"height\":24,\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\",\"width\":24},{\"descriptors\":[630,613,133,824,540,537],\"height\":24,\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\",\"width\":24}],\"scope\":\"gallery\",\"sig\":\"9fe90f9b2b13348c18ce8f195ab9a5ad3799c3a2ba99031e3303b402318fa03707ec46d3de0ba078d460b5db31748b42357a235436e8ed2b9c8ee4d2d638df0d\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"subject\":\"urn:example:gallery:defaults\"}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 0, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 2, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 3, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 5, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 6, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 7, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 8, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 9, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 10, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 11, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 12, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 13, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 14, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 15, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "distances_mismatch", + "record": 0 + }, + { + "name": "collection-member-unheld", + "about": "a gallery one of whose members the verifier does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":8},\"descriptors\":\"wai-exploration:image6\",\"distances\":{\"histogram\":[0,0,1,1,6,11,6,10,8,7,5,10,9,4,10,32],\"max\":2058,\"median\":742,\"min\":159,\"pairs\":120,\"sum\":95760,\"width\":64},\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-collection\",\"members\":[{\"descriptors\":[400,317,59,853,536,521],\"height\":24,\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"width\":24},{\"descriptors\":[613,842,79,205,504,533],\"height\":24,\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"width\":24},{\"descriptors\":[390,679,92,375,542,540],\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24},{\"descriptors\":[517,435,127,855,510,564],\"height\":24,\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\",\"width\":24},{\"descriptors\":[489,410,124,896,473,539],\"height\":24,\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\",\"width\":24},{\"descriptors\":[338,582,83,522,493,542],\"height\":24,\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\",\"width\":24},{\"descriptors\":[357,339,189,903,473,610],\"height\":24,\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\",\"width\":24},{\"descriptors\":[447,298,146,804,519,571],\"height\":24,\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\",\"width\":24},{\"descriptors\":[285,522,101,825,451,540],\"height\":24,\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\",\"width\":24},{\"descriptors\":[635,768,51,530,506,524],\"height\":24,\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\",\"width\":24},{\"descriptors\":[242,692,87,735,552,503],\"height\":24,\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\",\"width\":24},{\"descriptors\":[405,684,101,590,506,567],\"height\":24,\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\",\"width\":24},{\"descriptors\":[463,478,182,878,552,574],\"height\":24,\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\",\"width\":24},{\"descriptors\":[669,895,24,10,512,517],\"height\":24,\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\",\"width\":24},{\"descriptors\":[545,289,44,886,503,513],\"height\":24,\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\",\"width\":24},{\"descriptors\":[630,613,133,824,540,537],\"height\":24,\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\",\"width\":24}],\"scope\":\"gallery\",\"sig\":\"ffed3630c89aa0c106ca3d31ef7962e6b1976742baac79796f57d4b2f872bd37af978b7845425c457dedeb67a65efd2e1dc15aa980fbab8a1373b87766a9c207\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"subject\":\"urn:example:gallery:defaults\"}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 2, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 3, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 5, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 6, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 7, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 8, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 9, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 10, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 11, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 12, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 13, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 14, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 15, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "member_unheld", + "record": 0 + }, + { + "name": "collection-member-descriptors-wrong", + "about": "a member whose chroma is stated one lower than its samples give", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":8},\"descriptors\":\"wai-exploration:image6\",\"distances\":{\"histogram\":[0,0,1,1,6,11,6,10,8,7,5,10,9,4,10,32],\"max\":2058,\"median\":742,\"min\":159,\"pairs\":120,\"sum\":95760,\"width\":64},\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-collection\",\"members\":[{\"descriptors\":[400,317,59,853,536,521],\"height\":24,\"samples\":\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"width\":24},{\"descriptors\":[613,842,79,205,504,533],\"height\":24,\"samples\":\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"width\":24},{\"descriptors\":[390,678,92,375,542,540],\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24},{\"descriptors\":[517,435,127,855,510,564],\"height\":24,\"samples\":\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\",\"width\":24},{\"descriptors\":[489,410,124,896,473,539],\"height\":24,\"samples\":\"be1b87981c71727ad53e0eea041e092740fd87ab610c54b3fc91a48530afdb29\",\"width\":24},{\"descriptors\":[338,582,83,522,493,542],\"height\":24,\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\",\"width\":24},{\"descriptors\":[357,339,189,903,473,610],\"height\":24,\"samples\":\"76b6a7401db23cdf50d4a389ddacfd37a71a2453ee197eda51925a252266f175\",\"width\":24},{\"descriptors\":[447,298,146,804,519,571],\"height\":24,\"samples\":\"561dabd5a3c04d58bd23dc040cf1ee5f27d31c0afa066ed0531051d9c91198e0\",\"width\":24},{\"descriptors\":[285,522,101,825,451,540],\"height\":24,\"samples\":\"3e3ad42737f19095e267c9dda3fa3fa1be36159040e56c5508c9a1901af08f81\",\"width\":24},{\"descriptors\":[635,768,51,530,506,524],\"height\":24,\"samples\":\"91f641cc62a2459724298a93d318984f314dce918797655ac10827666fd1a60d\",\"width\":24},{\"descriptors\":[242,692,87,735,552,503],\"height\":24,\"samples\":\"d5fef7f8e0c60b499450045cb12784a7fa4152ce32802923e239f230524b76de\",\"width\":24},{\"descriptors\":[405,684,101,590,506,567],\"height\":24,\"samples\":\"ff84fcf85c21f8d9114f31ebd0bcb4f5ae3c99f8a410d5477f783719d152b8c7\",\"width\":24},{\"descriptors\":[463,478,182,878,552,574],\"height\":24,\"samples\":\"4975362af792cd6b02b71ecaf32ae68df6548564edb0c6a5f84287d716670c69\",\"width\":24},{\"descriptors\":[669,895,24,10,512,517],\"height\":24,\"samples\":\"8d752f71387aee93479f1053c9f7772592c07b5d4a3d4873d62b83e36a7e40bb\",\"width\":24},{\"descriptors\":[545,289,44,886,503,513],\"height\":24,\"samples\":\"993caceaf1046dfbc814debcf895874c1921841b8dafeaa5a5ed82e7baa1ffda\",\"width\":24},{\"descriptors\":[630,613,133,824,540,537],\"height\":24,\"samples\":\"bcf22dc925cf98db7cbabd7336b6d75b4819b4742f27ec49527c93d903981ae9\",\"width\":24}],\"scope\":\"gallery\",\"sig\":\"3ded4a9c8b349356d68077c45f9cc684fe53c394837d218ed3fd16dbbf71005af7dcfdc1a09907bbea5ac9f1e6add30c82bb8781bb9f04bc6e687337b23c0306\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"subject\":\"urn:example:gallery:defaults\"}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 0, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 2, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 3, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 5, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 6, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 7, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 8, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 9, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 10, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 11, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 12, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 13, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 14, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 15, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "descriptor_mismatch", + "record": 0 + }, + { + "name": "ranking-personal", + "about": "Alice's prior ranks six pictures; the prior carries no usage statement", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[3,2,5,4,0,1],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"scores\":[4806,4781,5414,5499,5019,5275],\"sig\":\"98345c2393302c19a7a0a861f748aafd1e01c19e28077938432a50e15bf2c584a6fcb94f9042ae1ca00df95811273c1d8a8fe29047c0466458892bb22fe42c0b\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-ranking", + "link": "9d3f7424eda1f59063665c3d89e3bf9b7e2573487085c9335f2e8d73f9c7c5a4", + "prior": "d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623", + "owner": "fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75", + "scope": "personal", + "order": [ + 3, + 2, + 5, + 4, + 0, + 1 + ], + "descriptors": "recomputed", + "usage": [] + } + ] + }, + { + "name": "ranking-community", + "about": "a community's prior ranks the same six; its statement allows ai-use, which the ranking names", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[0,4,1,2,3,5],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"community/many-colours\",\"sha256\":\"aafa999c17ae9b888112a0f6d0a83f178f552fde215a41c4c939097006a82c80\"},\"scores\":[4319,4257,4098,3479,4269,3142],\"sig\":\"aab31fc161fdb788a031198ca34ccde385b19f2460df3ac5313fcf93be456ccfea7e67089d9a0b33afd375c1d4505b1616af15fa4c17868aaed5c744ae465502\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[{\"term\":\"ai-use\",\"vocabulary\":\"aipref\"}]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"scope\":\"community\",\"sig\":\"05dd920100cc0e49e321e78d14abcbe881c92d1479bf879b90ae349693a4fa483642349687ba2e081fb601b05f09d6f813b8e8274875f0fcc0b59cdc1e531705\",\"signer_pubkey\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"terms\":[{\"at\":0,\"descriptor\":\"palette\",\"shape\":\"rise\",\"weight\":4},{\"at\":512,\"descriptor\":\"centroid_y\",\"shape\":\"near\",\"weight\":1}],\"usage\":{\"aipref\":{\"revision\":\"draft-ietf-aipref-vocab-08\",\"value\":\"train-ai=n, ai-use=y\"}}}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-ranking", + "link": "75a496f4a50f59cdcdaf110daa531df01f35eed4eb614b5c10e71dd8a4e646d1", + "prior": "aafa999c17ae9b888112a0f6d0a83f178f552fde215a41c4c939097006a82c80", + "owner": "bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c", + "scope": "community", + "order": [ + 0, + 4, + 1, + 2, + 3, + 5 + ], + "descriptors": "recomputed", + "usage": [ + { + "vocabulary": "aipref", + "term": "ai-use", + "preference": "allow" + } + ] + } + ] + }, + { + "name": "ranking-anti", + "about": "Bob's anti-aesthetic prior ranks the same six in another order", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[3,2,0,1,4,5],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"bob/far\",\"sha256\":\"ab935b4db4bfe92bcaba7995bf8fd145e3db5f83095328c6a5ab25ae5579e3c6\"},\"scores\":[1495,940,1750,1980,795,725],\"sig\":\"ea29521283ea54f04a1708b1f71ecd95e0365da2434498d6d9cac41beb198d023a30316c2c0e0ee456c206d28d2d9f8f384eecb1f77ba128d60e268ee31ed40b\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"7959dcc87a97c9781f249b2610f50ff525fce1a79ed2246756eeaea3859cf55b\",\"scope\":\"personal\",\"sig\":\"ffe90ff45f05ccc8bb4b107cc1b3de3615fc3f447049e7884b9fe2b47b26b29ab72c8140a1a1df508f70ace5ee8e018bc04bc72498d5764d565ed92b9af85000\",\"signer_pubkey\":\"7959dcc87a97c9781f249b2610f50ff525fce1a79ed2246756eeaea3859cf55b\",\"terms\":[{\"at\":448,\"descriptor\":\"luma\",\"shape\":\"far\",\"weight\":5},{\"at\":448,\"descriptor\":\"chroma\",\"shape\":\"far\",\"weight\":5}],\"usage\":null}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-ranking", + "link": "a1d77fdfb36c7eae3057efe2f82fb0d445f1469958ff7372b1d4b3e81fa2ffd5", + "prior": "ab935b4db4bfe92bcaba7995bf8fd145e3db5f83095328c6a5ab25ae5579e3c6", + "owner": "7959dcc87a97c9781f249b2610f50ff525fce1a79ed2246756eeaea3859cf55b", + "scope": "personal", + "order": [ + 3, + 2, + 0, + 1, + 4, + 5 + ], + "descriptors": "recomputed", + "usage": [] + } + ] + }, + { + "name": "ranking-stated", + "about": "Alice's prior over stated vectors: the verifier holds no candidate's samples", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[3,2,5,4,0,1],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"scores\":[4806,4781,5414,5499,5019,5275],\"sig\":\"98345c2393302c19a7a0a861f748aafd1e01c19e28077938432a50e15bf2c584a6fcb94f9042ae1ca00df95811273c1d8a8fe29047c0466458892bb22fe42c0b\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-ranking", + "link": "9d3f7424eda1f59063665c3d89e3bf9b7e2573487085c9335f2e8d73f9c7c5a4", + "prior": "d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623", + "owner": "fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75", + "scope": "personal", + "order": [ + 3, + 2, + 5, + 4, + 0, + 1 + ], + "descriptors": "stated", + "usage": [] + } + ] + }, + { + "name": "ranking-outside", + "about": "the community prior, the use stated as outside every aipref category", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[0,4,1,2,3,5],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"community/many-colours\",\"sha256\":\"aafa999c17ae9b888112a0f6d0a83f178f552fde215a41c4c939097006a82c80\"},\"scores\":[4319,4257,4098,3479,4269,3142],\"sig\":\"0db18873bee8f824cd1fdcf2945c8506b1d4203b222c7a52cbcd8491b717adc91c4f5f7f323a3395635015cc019d49fb2a137159275d8e9279069254b2afb605\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[{\"term\":null,\"vocabulary\":\"aipref\"}]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"scope\":\"community\",\"sig\":\"05dd920100cc0e49e321e78d14abcbe881c92d1479bf879b90ae349693a4fa483642349687ba2e081fb601b05f09d6f813b8e8274875f0fcc0b59cdc1e531705\",\"signer_pubkey\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"terms\":[{\"at\":0,\"descriptor\":\"palette\",\"shape\":\"rise\",\"weight\":4},{\"at\":512,\"descriptor\":\"centroid_y\",\"shape\":\"near\",\"weight\":1}],\"usage\":{\"aipref\":{\"revision\":\"draft-ietf-aipref-vocab-08\",\"value\":\"train-ai=n, ai-use=y\"}}}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-ranking", + "link": "731986aae61e45596402d59144f4c663a7a261267b1be9687cc67cf7513b08ba", + "prior": "aafa999c17ae9b888112a0f6d0a83f178f552fde215a41c4c939097006a82c80", + "owner": "bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c", + "scope": "community", + "order": [ + 0, + 4, + 1, + 2, + 3, + 5 + ], + "descriptors": "recomputed", + "usage": [ + { + "vocabulary": "aipref", + "term": null, + "preference": "outside" + } + ] + } + ] + }, + { + "name": "ranking-order-not-reproducing", + "about": "a ranking whose first two places are swapped: it does not reproduce", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[2,3,5,4,0,1],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"scores\":[4806,4781,5414,5499,5019,5275],\"sig\":\"78734cccbc9ccea287715f9bd6e6473c30710e30067a077bd100a3a355ccbf131f44010268a4b2c1975db595cf8a31a4fce8cd7ebe14acfeda3dddbfa16fa604\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "ranking_mismatch", + "record": 0 + }, + { + "name": "ranking-score-wrong", + "about": "a ranking whose first score is stated one higher", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[3,2,5,4,0,1],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"scores\":[4807,4781,5414,5499,5019,5275],\"sig\":\"9999bf6557a10e6630fb94eedd1144f60158da170d5779087a5d5af836aca6c6ec0c291c6137814fac0196a2f8319944a61bfb6697028eb0c658a488df6e860f\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "ranking_mismatch", + "record": 0 + }, + { + "name": "ranking-prior-not-owner", + "about": "a ranking under a prior that names Alice as owner and is signed by another key", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[0,1,2,3,4,5],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"ca12a734fce4a5f9d7e25b71b0393ec0a49f6a9f159e4952fb7ff8c39547153c\"},\"scores\":[0,0,0,0,0,0],\"sig\":\"13bdf8cfa5c4b08c00cfcfbb636e9c106f911a9b33da77358b0de9bcbaced3dcab059ddffd38ec536c83c3fc35f642187bda5e2c5381ace2a839720abc13dc08\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"d0429b03b1b7ef385d762bf528b8bd4341451477983cfe658f9dddd6eadd6506197e3153e8b837fe80cdc3892ab58a90e52d23336f70eb49c1fed884e93a8503\",\"signer_pubkey\":\"ebbb60a9e22a5d1f3f526f09df3004b7c9904077fc46d55c6de65d39e5271b0d\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "taste_not_owner", + "record": 0 + }, + { + "name": "ranking-prior-unresolved", + "about": "a ranking under a prior the verifier does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[3,2,5,4,0,1],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"scores\":[4806,4781,5414,5499,5019,5275],\"sig\":\"98345c2393302c19a7a0a861f748aafd1e01c19e28077938432a50e15bf2c584a6fcb94f9042ae1ca00df95811273c1d8a8fe29047c0466458892bb22fe42c0b\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "objective_unresolved", + "record": 0 + }, + { + "name": "ranking-usage-unanswered", + "about": "the community prior's statement carries aipref, and the ranking states no use in it", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[0,4,1,2,3,5],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"community/many-colours\",\"sha256\":\"aafa999c17ae9b888112a0f6d0a83f178f552fde215a41c4c939097006a82c80\"},\"scores\":[4319,4257,4098,3479,4269,3142],\"sig\":\"ab56d00019aafd84737785774805418a54756c3e583fb11fffdf33a316145106089538fb9034602848aa26252a713f221653c935e96c6077cd13063ce08c3000\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"scope\":\"community\",\"sig\":\"05dd920100cc0e49e321e78d14abcbe881c92d1479bf879b90ae349693a4fa483642349687ba2e081fb601b05f09d6f813b8e8274875f0fcc0b59cdc1e531705\",\"signer_pubkey\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"terms\":[{\"at\":0,\"descriptor\":\"palette\",\"shape\":\"rise\",\"weight\":4},{\"at\":512,\"descriptor\":\"centroid_y\",\"shape\":\"near\",\"weight\":1}],\"usage\":{\"aipref\":{\"revision\":\"draft-ietf-aipref-vocab-08\",\"value\":\"train-ai=n, ai-use=y\"}}}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "prior_usage_unanswered", + "record": 0 + }, + { + "name": "ranking-usage-disallowed", + "about": "a ranking that states train-ai, which the community's statement disallows", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[0,4,1,2,3,5],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"community/many-colours\",\"sha256\":\"aafa999c17ae9b888112a0f6d0a83f178f552fde215a41c4c939097006a82c80\"},\"scores\":[4319,4257,4098,3479,4269,3142],\"sig\":\"a9f28414f999b85f1b3f192258159ee4aec4ad7b1bce6aee4437ec82ba4e9dc1d950160efaa5857e1c9739c7ad35ae62c4b6a38d48e47bdf40a5a38f232f2405\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[{\"term\":\"train-ai\",\"vocabulary\":\"aipref\"}]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"scope\":\"community\",\"sig\":\"05dd920100cc0e49e321e78d14abcbe881c92d1479bf879b90ae349693a4fa483642349687ba2e081fb601b05f09d6f813b8e8274875f0fcc0b59cdc1e531705\",\"signer_pubkey\":\"bf44188ab92f77b54ba07d766f98fed60b4663c62d7c96ed8c545f7a8651fe9c\",\"terms\":[{\"at\":0,\"descriptor\":\"palette\",\"shape\":\"rise\",\"weight\":4},{\"at\":512,\"descriptor\":\"centroid_y\",\"shape\":\"near\",\"weight\":1}],\"usage\":{\"aipref\":{\"revision\":\"draft-ietf-aipref-vocab-08\",\"value\":\"train-ai=n, ai-use=y\"}}}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "prior_usage_disallowed", + "record": 0 + }, + { + "name": "ranking-prior-not-canonical", + "about": "a prior file with a space the canonical form does not have: its digest names other bytes than the record's", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,840,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[0,1,2,3,4,5],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"9c73e773ac92e936360e23205cacbc57e14ea9308dc3ee4b9cc513805d3f59fd\"},\"scores\":[0,0,0,0,0,0],\"sig\":\"36508efa7810a2e0cc8724b12bde4e0167e1497e184d5b006f9d78785d77b975aee7f35b2362f7ac5bcc0d48dc096c85bc516d79d0560e9c776175a6ec6ad205\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\", \"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "record_malformed", + "record": 0 + }, + { + "name": "ranking-candidate-descriptors-wrong", + "about": "a candidate whose palette is stated one higher than its samples give", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"candidates\":[{\"descriptors\":[291,306,134,841,565,577],\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24},{\"descriptors\":[274,462,183,809,543,515],\"height\":24,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"width\":24},{\"descriptors\":[299,649,51,769,480,510],\"height\":24,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"width\":24},{\"descriptors\":[308,704,47,617,491,525],\"height\":24,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"width\":24},{\"descriptors\":[435,302,111,824,514,563],\"height\":24,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"width\":24},{\"descriptors\":[334,479,64,533,478,526],\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}],\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-ranking\",\"order\":[3,2,5,4,0,1],\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"scores\":[4806,4781,5414,5499,5019,5275],\"sig\":\"a2acc08c0db7157cf0fcebf84eb6179029e72655310e638d4a50efb50b25c6596e382888ef54b480d74a580d02c570e0f347b0d434e4fa6dd82cb68c1b3e2d04\",\"signer_pubkey\":\"6a52466122e3e5cef47695bf647d6990ddaba194a53f9e93e376ff718934b4bf\",\"usage\":[]}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [ + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1391501156, + "steps": 4, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright spiral calm", + "seed": 1237077647, + "steps": 8, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 4277425985, + "steps": 3, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright calm", + "seed": 1308138946, + "steps": 12, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night bright", + "seed": 750884695, + "steps": 10, + "width": 24, + "height": 24 + } + }, + { + "generate": { + "prompt": "a quiet forest at night", + "seed": 1855656557, + "steps": 4, + "width": 24, + "height": 24 + } + } + ] + }, + "outcome": "refuse", + "reason": "descriptor_mismatch", + "record": 0 + }, + { + "name": "pick-from-archive", + "about": "a person selects an elite of the novelty archive, which nothing steered; the pick inherits its genome", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"0690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}", + "{\"act\":\"select\",\"from\":{\"archive\":\"c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89\",\"niche\":5,\"type\":\"archive\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"0a26db59397f71b13d164f944274233675e745d80f434e0d443bc55fc1fc009c5a4cdeea3eec4b10a7ca3a00758d1d289bf2d1bd81efdcb1be31c963dfd8fa08\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89", + "level": "replayed", + "occupied": 11, + "cells": 16, + "objective": "none" + }, + { + "kind": "wai-pick", + "link": "d20857e5db33e80585913beb1c6d8fc10f3140bf95bfbe9dc00bee83a884eb33", + "act": "select", + "objective": "none", + "check": "in-archive", + "genome": { + "seed": 1855656557, + "steps": 4, + "mods": 0, + "prompt": "a quiet forest at night" + } + } + ] + }, + { + "name": "pick-from-steered-archive", + "about": "a selection from the archive Alice's prior placed, naming that prior", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":5},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[595,809,46,96,502,520],\"mods\":2,\"niche\":0,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"score\":5401,\"seed\":1476727604,\"steps\":3,\"trial\":27},{\"descriptors\":[393,687,60,457,543,514],\"mods\":2,\"niche\":1,\"samples\":\"e5e5b19afd328dcf478e3e92e8f6630337d12cf0754a86ce49bc552b955e9582\",\"score\":5613,\"seed\":3972810035,\"steps\":1,\"trial\":9},{\"descriptors\":[332,645,61,744,528,537],\"mods\":0,\"niche\":2,\"samples\":\"9316f52db846823c66cbb49439f5c602515ae6811163d307da111deec6d5dc91\",\"score\":5446,\"seed\":1254822303,\"steps\":4,\"trial\":7},{\"descriptors\":[399,381,84,850,553,516],\"mods\":1,\"niche\":3,\"samples\":\"b507703a709f7b07c4ce3a64e6cc4b49a130b5e051dad2ae406338703e3c1fdd\",\"score\":5247,\"seed\":3931188236,\"steps\":4,\"trial\":29},{\"descriptors\":[384,341,188,861,448,576],\"mods\":0,\"niche\":7,\"samples\":\"f11c5e1c66e6f7d6656c48f9a63f40885952dd94fba0fd90befcd0af2a867a31\",\"score\":4865,\"seed\":871899692,\"steps\":6,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"62707af1355cec8e2b1e338c8cc013fe6afd4758c92babc014c8bf542a0280eeb33add5018a561097e6cdc5f6efb7be9cab7bee466c864e5130e24a370a0bd05\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}", + "{\"act\":\"select\",\"from\":{\"archive\":\"fccd244286b1833791596b74dda4cfd47de304f20ba6f865caf8e184590fbdd0\",\"niche\":0,\"type\":\"archive\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"sig\":\"9fade653aaee9bd8438fa9eaf13088b7b28ec8fe4f5278ce1cc9ccfd13794b7d84e8538cfb53468fb3f8b8c21d30b84e415f5b42a284eb0c59a0da317c119306\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-archive", + "link": "fccd244286b1833791596b74dda4cfd47de304f20ba6f865caf8e184590fbdd0", + "level": "replayed", + "occupied": 5, + "cells": 16, + "objective": { + "type": "taste", + "sha256": "d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623" + } + }, + { + "kind": "wai-pick", + "link": "93cb8c8782c81dae51dde94193056a1d00847e0502cbb0881086537edf479082", + "act": "select", + "objective": { + "type": "taste", + "sha256": "d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623" + }, + "check": "in-archive", + "genome": { + "seed": 1476727604, + "steps": 3, + "mods": 2, + "prompt": "a quiet forest at night mirror" + } + } + ] + }, + { + "name": "pick-generation-steered-by-a-model", + "about": "a generation a service chose with an aesthetic model it names by digest; the picture regenerates", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"generate\",\"from\":{\"generator\":\"wai.generate.spectral\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"prompt\":\"a quiet forest at night dark\",\"seed\":9001,\"steps\":9,\"type\":\"generation\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":{\"id\":\"urn:example:aesthetic-model\",\"sha256\":\"f1acff212e2b3cdddff61f46e8a68383b351ec76242cb9f7e82ace0e9e4c1b77\",\"type\":\"model\"},\"sig\":\"94cac102b57371937dc205aee49ca7e05f30e570aa23a3f886b892b2673fde740ff9777512960f36da1bd356c2e87dc405a487d958f5b13be39ee8d6a8f5af03\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-pick", + "link": "642b2c3787bb77ab2e63082a6c891c243c24e247fdb8353364f3ac05818c418b", + "act": "generate", + "objective": { + "type": "model", + "sha256": "f1acff212e2b3cdddff61f46e8a68383b351ec76242cb9f7e82ace0e9e4c1b77" + }, + "check": "regenerated", + "genome": { + "seed": 9001, + "steps": 9, + "mods": 0, + "prompt": "a quiet forest at night dark" + } + } + ] + }, + { + "name": "pick-from-set", + "about": "a selection of one of four defaults, nothing steering it", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"select\",\"from\":{\"set\":[\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"],\"type\":\"set\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"92e0014813af77ef6c0e4bd245f0fefa3413d2822444c8e6fb3e79d8edbea0c24148ce7a5d3e5b40cdfb31e2e8d945267ab5a7ad5c192683b0eaea3fa0142c02\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-pick", + "link": "bd0cb51c23de0be114333aa6c4b22cc13026a397954cfdc5c77c545ec5ab4d88", + "act": "select", + "objective": "none", + "check": "in-set", + "genome": null + } + ] + }, + { + "name": "pick-undisclosed", + "about": "a selection with no objective, under a policy that does not require one: reported undisclosed, not none", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"select\",\"from\":{\"set\":[\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"],\"type\":\"set\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"sig\":\"3e7e8f75f85a2b659599f792051787c7abf236d950a7d275267ec9b180d5a7e311e42f4aed2a9b99a8153741d91fe754488d2cab601c711ab689563de20d8a02\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-pick", + "link": "19f373f77780363ed5c73b46b11743569873630378198ee37350bd9d99a34462", + "act": "select", + "objective": "undisclosed", + "check": "in-set", + "genome": null + } + ] + }, + { + "name": "pick-generation-other", + "about": "a generation by a generator that is not exact: taken as stated", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"generate\",\"from\":{\"generator\":\"urn:example:generator:float-1\",\"model\":\"urn:example:model:float-1\",\"prompt\":\"a quiet forest at night\",\"seed\":null,\"steps\":null,\"type\":\"generation\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"74c5d628f99e0b642e8b763307bd182c042915a022360b7b562090dab8b83ddd0320b925f09605dcf28913f7911374d4bc623599519cd77de5cb1fa38a7aee0d\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "accept", + "statements": [ + { + "kind": "wai-pick", + "link": "c5a9d68a58762b805636c0fd4cdc250233bf3739b0c8f11e86b917a4ac25bf56", + "act": "generate", + "objective": "none", + "check": "stated", + "genome": null + } + ] + }, + { + "name": "pick-undisclosed-required", + "about": "a selection with no objective, under a policy that requires one", + "policy": { + "replay": "required", + "objective": "required" + }, + "records": [ + "{\"act\":\"select\",\"from\":{\"set\":[\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"],\"type\":\"set\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"sig\":\"3e7e8f75f85a2b659599f792051787c7abf236d950a7d275267ec9b180d5a7e311e42f4aed2a9b99a8153741d91fe754488d2cab601c711ab689563de20d8a02\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "objective_undisclosed", + "record": 0 + }, + { + "name": "pick-steered-archive-says-none", + "about": "a selection from the archive Alice's prior placed, stating that nothing steered it", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":5},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[595,809,46,96,502,520],\"mods\":2,\"niche\":0,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"score\":5401,\"seed\":1476727604,\"steps\":3,\"trial\":27},{\"descriptors\":[393,687,60,457,543,514],\"mods\":2,\"niche\":1,\"samples\":\"e5e5b19afd328dcf478e3e92e8f6630337d12cf0754a86ce49bc552b955e9582\",\"score\":5613,\"seed\":3972810035,\"steps\":1,\"trial\":9},{\"descriptors\":[332,645,61,744,528,537],\"mods\":0,\"niche\":2,\"samples\":\"9316f52db846823c66cbb49439f5c602515ae6811163d307da111deec6d5dc91\",\"score\":5446,\"seed\":1254822303,\"steps\":4,\"trial\":7},{\"descriptors\":[399,381,84,850,553,516],\"mods\":1,\"niche\":3,\"samples\":\"b507703a709f7b07c4ce3a64e6cc4b49a130b5e051dad2ae406338703e3c1fdd\",\"score\":5247,\"seed\":3931188236,\"steps\":4,\"trial\":29},{\"descriptors\":[384,341,188,861,448,576],\"mods\":0,\"niche\":7,\"samples\":\"f11c5e1c66e6f7d6656c48f9a63f40885952dd94fba0fd90befcd0af2a867a31\",\"score\":4865,\"seed\":871899692,\"steps\":6,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"62707af1355cec8e2b1e338c8cc013fe6afd4758c92babc014c8bf542a0280eeb33add5018a561097e6cdc5f6efb7be9cab7bee466c864e5130e24a370a0bd05\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}", + "{\"act\":\"select\",\"from\":{\"archive\":\"fccd244286b1833791596b74dda4cfd47de304f20ba6f865caf8e184590fbdd0\",\"niche\":0,\"type\":\"archive\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"271e95339f2c674d7f4021a7e0cad9d3021c56e9089b10f74c3f004ae394e9e581dfde9c42a3ca25da96c6431b37a1807581a208a12bc963babb858f4acd880a\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "refuse", + "reason": "objective_mismatch", + "record": 1 + }, + { + "name": "pick-steered-archive-undisclosed", + "about": "the same selection with no objective, under a policy that does not require one: the archive shows it was steered", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":5},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[595,809,46,96,502,520],\"mods\":2,\"niche\":0,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"score\":5401,\"seed\":1476727604,\"steps\":3,\"trial\":27},{\"descriptors\":[393,687,60,457,543,514],\"mods\":2,\"niche\":1,\"samples\":\"e5e5b19afd328dcf478e3e92e8f6630337d12cf0754a86ce49bc552b955e9582\",\"score\":5613,\"seed\":3972810035,\"steps\":1,\"trial\":9},{\"descriptors\":[332,645,61,744,528,537],\"mods\":0,\"niche\":2,\"samples\":\"9316f52db846823c66cbb49439f5c602515ae6811163d307da111deec6d5dc91\",\"score\":5446,\"seed\":1254822303,\"steps\":4,\"trial\":7},{\"descriptors\":[399,381,84,850,553,516],\"mods\":1,\"niche\":3,\"samples\":\"b507703a709f7b07c4ce3a64e6cc4b49a130b5e051dad2ae406338703e3c1fdd\",\"score\":5247,\"seed\":3931188236,\"steps\":4,\"trial\":29},{\"descriptors\":[384,341,188,861,448,576],\"mods\":0,\"niche\":7,\"samples\":\"f11c5e1c66e6f7d6656c48f9a63f40885952dd94fba0fd90befcd0af2a867a31\",\"score\":4865,\"seed\":871899692,\"steps\":6,\"trial\":13}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"detail\",\"hi\":512,\"lo\":0},{\"bins\":4,\"descriptor\":\"palette\",\"hi\":1024,\"lo\":256}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"dark\",\"mirror\"],\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":12,\"trials\":32},\"sig\":\"62707af1355cec8e2b1e338c8cc013fe6afd4758c92babc014c8bf542a0280eeb33add5018a561097e6cdc5f6efb7be9cab7bee466c864e5130e24a370a0bd05\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}", + "{\"act\":\"select\",\"from\":{\"archive\":\"fccd244286b1833791596b74dda4cfd47de304f20ba6f865caf8e184590fbdd0\",\"niche\":0,\"type\":\"archive\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"sig\":\"d6747ade98d601016a06aff3b8db7c7665711852dca2ffb77c4b5696a706757dd2664941d87c3f6ac78d0f44fadd08a10c161a3c70077d0a9268f123eddc730c\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"6c3d2c43fa2edbe33d29fbc7c9130a2cd9980d12344aed7f48844cb574e5426c\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [ + "{\"descriptors\":\"wai-exploration:image6\",\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-taste\",\"owner\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"scope\":\"personal\",\"sig\":\"2eaa11972a4832e0b94f2fe37c490039996ee298df7eb610437c5ee76519435a86c3069a6f43d49d4ae5f7331c5f53288f6b9d393cb58f526b1063fbae9c2d09\",\"signer_pubkey\":\"fceeb066d0c9e58433660f89db8a505df668118b8e71c48c73e19bac95f48f75\",\"terms\":[{\"at\":0,\"descriptor\":\"detail\",\"shape\":\"fall\",\"weight\":3},{\"at\":400,\"descriptor\":\"luma\",\"shape\":\"near\",\"weight\":2},{\"at\":0,\"descriptor\":\"chroma\",\"shape\":\"rise\",\"weight\":1}],\"usage\":null}" + ], + "samples": [] + }, + "outcome": "refuse", + "reason": "objective_mismatch", + "record": 1 + }, + { + "name": "pick-not-in-archive", + "about": "a selection of a niche the archive left empty", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"0690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}", + "{\"act\":\"select\",\"from\":{\"archive\":\"c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89\",\"niche\":8,\"type\":\"archive\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"cce97c05bc0ee645e5a93275f0751a9917a72147f3aa029e09a914840b8a11b0b86b3b0fe2d039403d662647d8a0b3a893573c4d868401e9bec39cdab8150308\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "pick_not_in_archive", + "record": 1 + }, + { + "name": "pick-wrong-elite", + "about": "a selection naming one occupied niche whose work is another niche's elite", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"coverage\":{\"cells\":16,\"occupied\":11},\"descriptors\":\"wai-exploration:image6\",\"elites\":[{\"descriptors\":[291,306,134,840,565,577],\"mods\":0,\"niche\":0,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"score\":null,\"seed\":1391501156,\"steps\":4,\"trial\":6},{\"descriptors\":[274,462,183,809,543,515],\"mods\":7,\"niche\":1,\"samples\":\"659e77eb0f7b1592be714df4ea3b2da7aa6c29b9c87205e66fc1eefd8085462e\",\"score\":null,\"seed\":1237077647,\"steps\":8,\"trial\":29},{\"descriptors\":[299,649,51,769,480,510],\"mods\":0,\"niche\":2,\"samples\":\"375fb6fa9df5ce322977105a36ca37c4d0a8548fdb9719629fc9ecf01edbe484\",\"score\":null,\"seed\":4277425985,\"steps\":3,\"trial\":8},{\"descriptors\":[308,704,47,617,491,525],\"mods\":5,\"niche\":3,\"samples\":\"1b63645c62c14b0478dc6f3674f987dbd6d904e3a99c4258d5a9f7b414e9d926\",\"score\":null,\"seed\":1308138946,\"steps\":12,\"trial\":21},{\"descriptors\":[435,302,111,824,514,563],\"mods\":1,\"niche\":4,\"samples\":\"d6498498fbac02811b19e4d874495b06630025e63c450caf77b311018b5984b4\",\"score\":null,\"seed\":750884695,\"steps\":10,\"trial\":18},{\"descriptors\":[334,479,64,533,478,526],\"mods\":0,\"niche\":5,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"score\":null,\"seed\":1855656557,\"steps\":4,\"trial\":2},{\"descriptors\":[347,673,100,427,533,550],\"mods\":0,\"niche\":6,\"samples\":\"6b09253b7d25d174b5c334c5cfc32e7eff7ea815d1de99d74ab1af1984461d82\",\"score\":null,\"seed\":1213784844,\"steps\":2,\"trial\":14},{\"descriptors\":[360,745,53,407,496,522],\"mods\":1,\"niche\":7,\"samples\":\"30ad79d49d123efbe6b758365bd47937484f87a736467fb8c259426fa417954a\",\"score\":null,\"seed\":2832323450,\"steps\":4,\"trial\":15},{\"descriptors\":[631,434,81,854,491,497],\"mods\":1,\"niche\":9,\"samples\":\"e65d85c91613f3061c1db2414cb568b76e90b75f48fca35f78a1287dce191a4a\",\"score\":null,\"seed\":1433734301,\"steps\":7,\"trial\":16},{\"descriptors\":[622,576,81,802,530,527],\"mods\":0,\"niche\":10,\"samples\":\"640ec98756a6b9bc985d0007fab88b992407d8ae0dbeac07f6173c391c314a17\",\"score\":null,\"seed\":595603613,\"steps\":4,\"trial\":0},{\"descriptors\":[647,865,49,461,499,513],\"mods\":1,\"niche\":11,\"samples\":\"76073cc9d893f0928c795de055cddd73265bf542dcda123af071588ddfa98215\",\"score\":null,\"seed\":895832808,\"steps\":8,\"trial\":31}],\"generator\":\"wai.generate.spectral\",\"grid\":[{\"bins\":4,\"descriptor\":\"luma\",\"hi\":896,\"lo\":128},{\"bins\":4,\"descriptor\":\"chroma\",\"hi\":896,\"lo\":128}],\"height\":24,\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-archive\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"modifiers\":[\"bright\",\"spiral\",\"calm\"],\"objective\":\"none\",\"prompt\":\"a quiet forest at night\",\"search\":{\"init\":8,\"schedule\":\"wai-exploration:map-elites/1\",\"seed\":11,\"trials\":40},\"sig\":\"0690d74e56b50ff7d4f9a5f5df395c782f698471fd65ff72f28ef4d48649bfe12ed2d825a226231a4165a576848c508c901002fa00a129fdaeb244bd5da09b04\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\",\"steps\":4,\"width\":24}", + "{\"act\":\"select\",\"from\":{\"archive\":\"c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89\",\"niche\":5,\"type\":\"archive\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"2f8f91d511aacbb7b9acd995ad6243d00566aaedda72a3d7e6613a4623afe54dc2bc876e585d78e25d0c4f1eb8cfb5e7a7694cb23a0df2f519c17c13eb911704\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"9b0ad8ef7c40e4678c7c7ea7eeacb58d094b72d33fdc42c6b26adafeb56d5afa\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "pick_not_in_archive", + "record": 1 + }, + { + "name": "pick-archive-unheld", + "about": "a selection from an archive the case does not give", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"select\",\"from\":{\"archive\":\"c84f0bae22ef601aea139ee89070c07abe39836fa011077ad5c7a9a844e6bd89\",\"niche\":5,\"type\":\"archive\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"0a26db59397f71b13d164f944274233675e745d80f434e0d443bc55fc1fc009c5a4cdeea3eec4b10a7ca3a00758d1d289bf2d1bd81efdcb1be31c963dfd8fa08\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"ff7906b201124b94a516103565152e0944111fb461c211d94b096d5fa277fb19\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "archive_unheld", + "record": 0 + }, + { + "name": "pick-not-in-set", + "about": "a selection of a picture the set does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"select\",\"from\":{\"set\":[\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"],\"type\":\"set\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"5deb334b495023d6b999f68b3b69e4d642e29fae9489f9c55d860275b0c207ca5768448eda8f8547d36d249d3afc237f9ce8815653531381a1cd387a4b6b520c\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"d73cadc236d1e6e8e9851cb72ad01898e068a43996af31caa3e53e4cf961c992\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "pick_not_in_set", + "record": 0 + }, + { + "name": "pick-generation-mismatch", + "about": "a generation whose seed does not regenerate the work", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"generate\",\"from\":{\"generator\":\"wai.generate.spectral\",\"model\":\"sha256:963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e\",\"prompt\":\"a quiet forest at night dark\",\"seed\":9002,\"steps\":9,\"type\":\"generation\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"e1e44cb719c35b9af0f56eae709bde218ca8508a3c07d5b6a3919dd36dfa6094dcf4d6f2ef36b8232531a1563106bb7dc004657295548dd54cf738bb7b15fe01\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"15224a329210b78b4c6dcf408ad2de602a198f62251c1703348fe5172cc4b337\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "generation_mismatch", + "record": 0 + }, + { + "name": "pick-objective-unresolved", + "about": "a selection naming a taste prior the verifier does not hold", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"select\",\"from\":{\"set\":[\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"],\"type\":\"set\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":{\"prior\":{\"determinism\":\"wai-exploration taste score: unsigned integer arithmetic, exact\",\"id\":\"alice/calm\",\"sha256\":\"d1a2ce78cd37c137bb7590b7043becc1dbe14d90fcc8205495cf1420e89ba623\"},\"type\":\"taste\"},\"sig\":\"e06f3c7314ac533fb53a34c3e1653d7759881541d3e9ff41fa144c1379556a274a4b34cc9a39ab83dc0431b9d66a23d0f18102ebbbc3017fc691b83ce0707d03\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "objective_unresolved", + "record": 0 + }, + { + "name": "pick-act-mismatch", + "about": "a generate whose source is a set", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"act\":\"generate\",\"from\":{\"set\":[\"6875cec3fec2082bcec6bccb04c4733bc9e7acc2b06eaef55843f0ce726ce012\",\"9608c9acf308cf2c0bf9a9b83b8a926b2da08b989246f029a7aa214c1eb6571d\",\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"69d8de4ff7b3e5a7d2a4b7e66f9c50bf27f5e88c7595df784f55d3c3d70c1c60\"],\"type\":\"set\"},\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-pick\",\"objective\":\"none\",\"sig\":\"3f4e47abb6da3b1f88a0a3554fa3d873001bcccf04b50081d18aa286aaab8f622d0219f74596cbd848de295523a2d68e61ff61d6ff90b3e36cc4daeb78345708\",\"signer_pubkey\":\"988ae6c23f4cf14e0065c8471253bf5039f760561106c0b525303054b13fa742\",\"work\":{\"height\":24,\"samples\":\"fb7a48ab5682965639d99d02c9494e68608dfa110cd537baf5674dd4fcb6e02b\",\"width\":24}}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "record_malformed", + "record": 0 + }, + { + "name": "record-kind-unknown", + "about": "a record of a kind this extension does not define", + "policy": { + "replay": "required", + "objective": "optional" + }, + "records": [ + "{\"issued_at\":\"2026-10-21T09:00:00Z\",\"kind\":\"wai-other\",\"sig\":\"6d735a3d19fb50e22c8ba1f1b49cf56920fb141e0d7b24ea69bddae8a0863a5c61766f7536b97faf30af50933f9627a6b1bd63247db5cc18e45d0f6371dbb003\",\"signer_pubkey\":\"ce8470171b0048ce34fd40d2b63ccff073830dd02a8836af29f3a21adebcfffe\"}" + ], + "held": { + "models": [ + "963ee634db1a964d14004618b139fd7e32598f627c023faf9526b14611504f9e" + ], + "priors": [], + "samples": [] + }, + "outcome": "refuse", + "reason": "record_malformed", + "record": 0 + } + ] +} diff --git a/wai/live-conformance/exploration_verify.py b/wai/live-conformance/exploration_verify.py new file mode 100644 index 000000000..dbf73957e --- /dev/null +++ b/wai/live-conformance/exploration_verify.py @@ -0,0 +1,1230 @@ +#!/usr/bin/env python3 +"""Second implementation of extensions/exploration.md (`wai.media.exploration`), over the corpus +`live-conformance/exploration/`. + +Written from the extension's text. It shares no code with wai-rs: it makes every picture with +the generator as Appendix A restates it, computes the descriptors of §3, runs the schedule of +§5.2, and reads every record as §2 has it read (strict JSON, the encodings of jwp-receipts +§2.4.3). It verifies every signature with WAI's strict Ed25519 rule +(claim-conformance/_ed25519.py), every link hash with BLAKE3 written from its specification +(claim-conformance/_blake3.py), and reads a taste prior's usage statement with the AI usage +corpus's second implementation (ai_usage_verify.py). It reads §13's codes from the extension. + + python3 -I exploration_verify.py + +It checks every generation and descriptor vector of the corpus, gives every case the outcome, +the reason, the record and the statements the corpus states, and checks that every reason of +§13 refuses a case. Then it mutates copies of the corpus and requires every copy to fail, and +drops each of its own checks in turn and requires the corpus to catch the weakened verifier. +Exit status 0 only if all of that holds. Python 3.8 or later; standard library only. +""" + +import copy +import hashlib +import json +import math +import os +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, HERE) +sys.path.insert(0, os.path.join(HERE, "..", "claim-conformance")) +import ai_usage_verify as AU # noqa: E402 +import _ed25519 as ED # noqa: E402 +from _blake3 import blake3 # noqa: E402 + +WAI = os.path.join(HERE, "..") +EXTENSION = os.path.join(WAI, "extensions", "exploration.md") + +SIGN_DOMAIN = b"wai:exploration\x01" # §2 +LINK_DOMAIN = b"wai:exploration-link\x01" # §2 +DESCRIPTOR_SET = "wai-exploration:image6" # §2 +SCHEDULE = "wai-exploration:map-elites/1" # §5.1 +GENERATOR = "wai.generate.spectral" # §4.1 +NAMES = ["luma", "chroma", "detail", "palette", "centroid_x", "centroid_y"] # §3.2, in order +SHAPES = ["rise", "fall", "near", "far"] # §8.2 +DEFAULT_SEEDS, DEFAULT_STEPS = 16, 4 # §6.1 +MAX_INT = (1 << 53) - 1 +M64 = (1 << 64) - 1 +VOCABULARIES = ["aipref", "cawg", "tdmrep"] # ai-usage §6.1 +AIPREF_LABELS = ["train-ai", "ai-use", "search"] +CAWG_KEYS = ["cawg.data_mining", "cawg.ai_inference", "cawg.ai_generative_training", "cawg.ai_training"] +WHITE_SPACE = set("\t\n\x0b\x0c\r \x85\xa0            " + "

   ") + +# A check named here is left out: the verifier weakened on purpose, to show the corpus catches it. +SKIP = set() + + +class Refuse(Exception): + def __init__(self, reason): + super().__init__(reason) + self.reason = reason + + +class Bad(Exception): + """A record that does not read: `record_malformed`.""" + + +def need(c): + if not c: + raise Bad() + + +def sha(b): + return hashlib.sha256(b).digest() + + +# ---------------------------------------------------------------- §2 records + +def strict_json(text): + """RFC 8259, no member named twice, no number but an unsigned integer, no boolean, no unpaired + surrogate, at most 32 levels.""" + def pairs(ps): + d = {} + for k, x in ps: + if k in d: + raise Bad() + d[k] = x + return d + + def no(s): + raise Bad() + + def integer(s): + if s.startswith("-"): + raise Bad() + return int(s) + + try: + v = json.loads(text, object_pairs_hook=pairs, parse_float=no, parse_int=integer, parse_constant=no) + except (ValueError, RecursionError): + raise Bad() + + def walk(x, depth): + if isinstance(x, (dict, list)): + need(depth <= 32) + for y in (x.values() if isinstance(x, dict) else x): + walk(y, depth + 1) + for k in (x if isinstance(x, dict) else []): + walk(k, depth) + elif isinstance(x, str): + need(not any(0xD800 <= ord(c) <= 0xDFFF for c in x)) + elif isinstance(x, bool): + raise Bad() + elif isinstance(x, int): + need(x <= MAX_INT) + walk(v, 1) + return v + + +def jstr(s): + out = ['"'] + for c in s: + o = ord(c) + if c == '"': + out.append('\\"') + elif c == "\\": + out.append("\\\\") + elif c == "\b": + out.append("\\b") + elif c == "\f": + out.append("\\f") + elif c == "\n": + out.append("\\n") + elif c == "\r": + out.append("\\r") + elif c == "\t": + out.append("\\t") + elif o < 0x20: + out.append("\\u%04x" % o) + else: + out.append(c) + out.append('"') + return "".join(out) + + +def jcs(v): + """RFC 8785 over strings, unsigned integers, null, arrays and objects.""" + if v is None: + return "null" + if isinstance(v, bool): + raise Bad() + if isinstance(v, int): + return str(v) + if isinstance(v, str): + return jstr(v) + if isinstance(v, list): + return "[" + ",".join(jcs(x) for x in v) + "]" + keys = sorted(v, key=lambda k: k.encode("utf-16-be")) + return "{" + ",".join(jstr(k) + ":" + jcs(v[k]) for k in keys) + "}" + + +def link_hash(v): + return blake3(LINK_DOMAIN + jcs(v).encode("utf-8")) + + +def signing_bytes(v): + return SIGN_DOMAIN + jcs({k: x for k, x in v.items() if k != "sig"}).encode("utf-8") + + +def is_uint(x): + return isinstance(x, int) and not isinstance(x, bool) and 0 <= x <= MAX_INT + + +def uint(x, lo=0, hi=MAX_INT): + need(is_uint(x) and lo <= x <= hi) + return x + + +def hexb(x, n): + need(isinstance(x, str) and len(x) == 2 * n and all(c in "0123456789abcdef" for c in x)) + return bytes.fromhex(x) + + +def is_term(s): + return (isinstance(s, str) and 1 <= len(s.encode("utf-8")) <= 2048 + and not any(c in WHITE_SPACE or ord(c) < 0x20 or 0x7F <= ord(c) <= 0x9F for c in s)) + + +def label(s): + need(isinstance(s, str) and 1 <= len(s.encode("utf-8")) <= 256) + return s + + +def date_time(s): + """RFC 3339 date-time, the day within its month.""" + need(isinstance(s, str) and len(s) >= 20 and s.isascii()) + d = lambda i: s[i].isdigit() + need(all(d(i) for i in (0, 1, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18))) + need(s[4] == "-" and s[7] == "-" and s[10] in "Tt" and s[13] == ":" and s[16] == ":") + yr, mo, da, hh, mi, ss = int(s[0:4]), int(s[5:7]), int(s[8:10]), int(s[11:13]), int(s[14:16]), int(s[17:19]) + leap = yr % 4 == 0 and (yr % 100 != 0 or yr % 400 == 0) + days = [31, 29 if leap else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + need(1 <= mo <= 12 and 1 <= da <= days[mo - 1] and hh <= 23 and mi <= 59 and ss <= 60) + i = 19 + if i < len(s) and s[i] == ".": + j = i + 1 + while j < len(s) and s[j].isdigit(): + j += 1 + need(j > i + 1) + i = j + rest = s[i:] + if rest in ("Z", "z"): + return + need(len(rest) == 6 and rest[0] in "+-" and rest[1:3].isdigit() and rest[3] == ":" and rest[4:6].isdigit()) + need(int(rest[1:3]) <= 23 and int(rest[4:6]) <= 59) + + +def exact(v, names): + need(isinstance(v, dict) and set(v) == set(names)) + return v + + +def read_record(text, kind, names, optional=None): + """§2: the value, its signer and its link hash; raises Bad.""" + v = strict_json(text) + need(isinstance(v, dict)) + need(set(v) == set(names) or (optional is not None and set(v) == set(names) | {optional})) + need(v["kind"] == kind) + signer = hexb(v["signer_pubkey"], 32) + hexb(v["sig"], 64) + date_time(v["issued_at"]) + return v, signer, link_hash(v) + + +SIG_MEMO = {} + + +def check_signature(v, signer): + if "signature" in SKIP: + return + key = (signer, signing_bytes(v), bytes.fromhex(v["sig"])) + if key not in SIG_MEMO: + SIG_MEMO[key] = ED.verify(*key) + if SIG_MEMO[key]: + raise Refuse(SIG_MEMO[key]) + + +# ---------------------------------------------------------------- Appendix A: the generator + +def tdiv(a, b): + q = abs(a) // abs(b) + return q if (a >= 0) == (b >= 0) else -q + + +def splitmix(state): + """§5.2: the next state and the draw.""" + state = (state + 0x9E3779B97F4A7C15) & M64 + z = state + z = ((z ^ (z >> 30)) * 0xBF58476D1CE4E5B9) & M64 + z = ((z ^ (z >> 27)) * 0x94D049BB133111EB) & M64 + return state, z ^ (z >> 31) + + +class Rng: + def __init__(self, s): + self.s = s & M64 + + def draw(self): + self.s, z = splitmix(self.s) + return z + + +ATAN = [128, 76, 40, 20, 10, 5, 3, 1, 1, 0, 0, 0, 0, 0] + + +def iatan2(dy, dx, t): + """A.5.""" + if dx == 0: + return 0 if dy == 0 else (t // 4 if dy > 0 else 3 * t // 4) + if dy == 0: + return 0 if dx > 0 else t // 2 + x, y, ang = abs(dx) << 12, abs(dy) << 12, 0 + for i, a in enumerate(ATAN): + if y > 0: + x, y = x + (y >> i), y - (x >> i) + ang += a + elif y < 0: + x, y = x - (y >> i), y + (x >> i) + ang -= a + if dx >= 0 and dy >= 0: + q = ang + elif dx < 0 and dy >= 0: + q = t // 2 - ang + elif dx < 0: + q = t // 2 + ang + else: + q = t - ang + return q % t + + +class Model: + """A.1.""" + def __init__(self, v): + self.lut = v["sine_lut"] + self.t = v["lut_size"] + self.lut_bits = v.get("lut_bits", 14) + self.freq_max = v["freq_max"] + self.amp_bits = v["amp_bits"] + self.offsets = v["color_offsets"] + self.base = v["base_components"] + self.step = v["step_components"] + self.lexicon = {w: (list(e) + [0] * 10)[:10] for w, e in v.get("lexicon", {}).items()} + + +def tokens(prompt): + out, cur = [], [] + for c in prompt.lower(): + if c.isascii() and c.isalnum(): + cur.append(c) + elif cur: + out.append("".join(cur)) + cur = [] + if cur: + out.append("".join(cur)) + return out + + +def intent(m, prompt): + """A.2.""" + s, n = [0] * 10, 0 + for tok in tokens(prompt): + e = m.lexicon.get(tok) + if e is not None: + s = [a + b for a, b in zip(s, e)] + n += 1 + if n == 0: + return [256, 256, 256], 256, 0, 0, 0, 0, 0, 0 + mx = max(max(s[0:3]), 1) + cl = lambda x, lo, hi: max(lo, min(hi, x)) + hue = [tdiv(s[c] * 256, mx) for c in range(3)] + return (hue, tdiv(s[3], n), cl(tdiv(s[4], n), -256, 256), cl(tdiv(s[5], n), 0, 256), cl(tdiv(s[6], n), 0, 256), + cl(tdiv(s[7], n), -256, 256), cl(tdiv(s[8], n), 0, 256), cl(tdiv(s[9], n), 0, 256)) + + +def fnv(b): + h = 14695981039346656037 + for x in b: + h = ((h ^ x) * 1099511628211) & M64 + return h + + +GEN_MEMO = {} + + +def gen(m, prompt, seed, steps, w, h): + """§4.1: `gen(model, prompt, seed, steps, w, h)`, as Appendix A restates it.""" + key = (id(m), prompt, seed, steps, w, h) + if key in GEN_MEMO: + return GEN_MEMO[key] + hue, freq, orient, radial, mirror, gradient, angular, spiral = intent(m, prompt) + k = m.base + steps * m.step + sx, sy = (max(256 + orient, 0), 256) if orient < 0 else (256, max(256 - orient, 0)) + f = max(tdiv(m.freq_max * freq, 256), 1) + span, amp_max = 2 * f + 1, 1 << m.amp_bits + rng = Rng(fnv(prompt.encode("ascii")) ^ seed ^ 0xD1B54A32D192ED03) + thr = [radial, mirror, angular, spiral] + plane = max(256 - sum(thr), 48) + total = plane + sum(thr) + comps = [] + for _ in range(k): + pick = rng.draw() % total + fx = rng.draw() % span - f + fy = rng.draw() % span - f + amp = rng.draw() % amp_max + 1 + phase = rng.draw() % m.t + typ, bound = 0, plane + if pick >= plane: + for i, wt in enumerate(thr): + bound += wt + if pick < bound: + typ = i + 1 + break + if typ == 1: + comps.append((1, max(abs(fx), 2), 0, amp, phase)) + elif typ == 3: + comps.append((3, abs(fx) % 11 + 2, 0, amp, phase)) + elif typ == 4: + comps.append((4, abs(fx) % 9 + 2, max(abs(fy), 2), amp, phase)) + else: + comps.append((typ, tdiv(fx * sx, 256), tdiv(fy * sy, 256), amp, phase)) + n, t, lut = w * h, m.t, m.lut + cx, cy = w // 2, h // 2 + gscale = ((1 << m.lut_bits) * amp_max * k) // (2048 * max(cy, 1)) + geo = [] + for y in range(h): + for x in range(w): + dx, dy = x - cx, y - cy + geo.append((x, y, dx, dy, math.isqrt(dx * dx + dy * dy), iatan2(dy, dx, t))) + acc = [0] * (3 * n) + for c, o in enumerate(m.offsets): + for p, (x, y, dx, dy, r, th) in enumerate(geo): + a = gradient * (cy - y) * gscale + for typ, fx, fy, amp, ph in comps: + if typ == 0: + arg = fx * x + fy * y + ph + o + elif typ == 1: + arg = fx * r + ph + o + elif typ == 2: + arg = fx * abs(dx) + fy * abs(dy) + ph + o + elif typ == 3: + arg = fx * th + ph + o + else: + arg = fx * th + fy * r + ph + o + a += amp * lut[arg % t] + acc[c * n + p] = a + g0, g1 = min(acc), max(acc) + rg = max(g1 - g0, 1) + e = [64 + tdiv(hue[c] * 192, 256) for c in range(3)] + out = bytearray(3 * n) + for c in range(3): + for p in range(n): + q = ((acc[c * n + p] - g0) * 255 + rg // 2) // rg + out[3 * p + c] = min(max(tdiv(q * e[c], 256), 0), 255) + out = bytes(out) + GEN_MEMO[key] = out + return out + + +# ---------------------------------------------------------------- §3 descriptors + +DESC_MEMO = {} + + +def descriptors(b, w, h): + """§3.2: the six, in order.""" + key = (sha(b), w, h) + if key in DESC_MEMO: + return DESC_MEMO[key] + n = w * h + assert len(b) == 3 * n + Y = [(77 * b[i] + 150 * b[i + 1] + 29 * b[i + 2] + 128) >> 8 for i in range(0, 3 * n, 3)] + luma = 1024 * sum(Y) // (255 * n) + chroma = 1024 * sum(max(b[i:i + 3]) - min(b[i:i + 3]) for i in range(0, 3 * n, 3)) // (255 * n) + P = (w - 1) * h + w * (h - 1) + D = 0 + for y in range(h): + for x in range(w): + p = y * w + x + if x + 1 < w: + D += abs(Y[p + 1] - Y[p]) + if y + 1 < h: + D += abs(Y[p + w] - Y[p]) + detail = 0 if P == 0 else min(1024, 1024 * D // (16 * P)) + k = [0] * 64 + for i in range(0, 3 * n, 3): + k[(b[i] >> 6) * 16 + (b[i + 1] >> 6) * 4 + (b[i + 2] >> 6)] += 1 + palette = 1024 * (n * n - sum(c * c for c in k)) // (n * n) + V = [y + 1 for y in Y] + SV = sum(V) + cx = 1024 * sum((2 * (p % w) + 1) * V[p] for p in range(n)) // (2 * w * SV) + cy = 1024 * sum((2 * (p // w) + 1) * V[p] for p in range(n)) // (2 * h * SV) + out = [luma, chroma, detail, palette, cx, cy] + DESC_MEMO[key] = out + return out + + +def distance(a, b): + """§3.4.""" + return sum(abs(x - y) for x, y in zip(a, b)) + + +def read_vector(x): + need(isinstance(x, list) and len(x) == 6) + return [uint(d, 0, 1024) for d in x] + + +def read_grid(x): + """§3.5.""" + need(isinstance(x, list) and 1 <= len(x) <= 4) + grid, seen = [], set() + for a in x: + exact(a, ["descriptor", "lo", "hi", "bins"]) + need(a["descriptor"] in NAMES and a["descriptor"] not in seen) + seen.add(a["descriptor"]) + lo, hi, bins = uint(a["lo"], 0, 1024), uint(a["hi"], 0, 1024), uint(a["bins"], 1, 64) + need(lo < hi) + grid.append((NAMES.index(a["descriptor"]), lo, hi, bins)) + need(cells(grid) <= 4096) + return grid + + +def cells(grid): + c = 1 + for a in grid: + c *= a[3] + return c + + +def niche(grid, d): + k = 0 + for i, lo, hi, bins in grid: + x = d[i] + k = k * bins + (0 if x < lo else bins - 1 if x >= hi else (x - lo) * bins // (hi - lo)) + return k + + +def size_ok(w, h): + return 1 <= w <= 4096 and 1 <= h <= 4096 and w * h <= 1 << 23 + + +def read_picture(x, with_d): + exact(x, ["samples", "width", "height", "descriptors"] if with_d else ["samples", "width", "height"]) + w, h = uint(x["width"]), uint(x["height"]) + need(size_ok(w, h)) + return {"samples": hexb(x["samples"], 32), "w": w, "h": h, "d": read_vector(x["descriptors"]) if with_d else None} + + +def is_prompt(s): + return isinstance(s, str) and len(s.encode("utf-8")) <= 256 and all(0x20 <= ord(c) <= 0x7E and c not in '"\\' for c in s) + + +def model_digest(s): + need(isinstance(s, str) and s.startswith("sha256:")) + return hexb(s[7:], 32) + + +# ---------------------------------------------------------------- what the verifier holds + +class Held: + def __init__(self, models, priors, samples): + self.models, self.priors, self.samples = models, priors, samples + + def model(self, digest): + if digest not in self.models: + raise Refuse("model_unheld") + return self.models[digest] + + def samples_of(self, p): + """A picture's held samples, of its size, or None.""" + b = self.samples.get(p["samples"]) + if b is None: + return None + if len(b) != p["w"] * p["h"] * 3 and "sample-size" not in SKIP: + raise Refuse("samples_mismatch") + return b + + +# ---------------------------------------------------------------- §8 taste priors and §10.1 objectives + +def read_pin(x): + exact(x, ["id", "sha256", "determinism"]) + label(x["id"]) + label(x["determinism"]) + return hexb(x["sha256"], 32) + + +def read_objective(x): + """§10.1: ("none",), ("taste", digest) or ("model", digest).""" + if x == "none": + return ("none", None) + need(isinstance(x, dict) and "type" in x) + if x["type"] == "taste": + exact(x, ["type", "prior"]) + return ("taste", read_pin(x["prior"])) + need(x["type"] == "model") + exact(x, ["type", "sha256", "id"]) + label(x["id"]) + return ("model", hexb(x["sha256"], 32)) + + +def objective_report(o): + return "none" if o[0] == "none" else {"type": o[0], "sha256": o[1].hex()} + + +TASTE = ["kind", "owner", "scope", "descriptors", "terms", "usage", "issued_at", "signer_pubkey", "sig"] + + +def read_taste(b): + """§8.1, §8.4: the prior, read and verified.""" + try: + text = b.decode("utf-8") + v, signer, _ = read_record(text, "wai-taste", TASTE) + need(jcs(v).encode("utf-8") == b or "canonical-prior" in SKIP) + owner = hexb(v["owner"], 32) + need(v["scope"] in ("personal", "community")) + need(v["descriptors"] == DESCRIPTOR_SET) + need(isinstance(v["terms"], list) and 1 <= len(v["terms"]) <= 32) + terms = [] + for t in v["terms"]: + exact(t, ["descriptor", "shape", "at", "weight"]) + need(t["descriptor"] in NAMES and t["shape"] in SHAPES) + at, weight = uint(t["at"], 0, 1024), uint(t["weight"], 1, 1024) + need(t["shape"] in ("near", "far") or at == 0) + terms.append((NAMES.index(t["descriptor"]), t["shape"], at, weight)) + usage = None + if v["usage"] is not None: + try: + usage = AU.read_statement(v["usage"]) + except AU.Refuse: + raise Bad() + except (Bad, UnicodeDecodeError, KeyError, TypeError): + raise Refuse("record_malformed") + check_signature(v, signer) + if signer != owner and "owner" not in SKIP: + raise Refuse("taste_not_owner") + return {"digest": sha(b), "owner": owner, "scope": v["scope"], "terms": terms, "usage": usage} + + +def score(prior, d): + """§8.2.""" + s = 0 + for i, shape, at, weight in prior["terms"]: + x = d[i] + s += weight * (x if shape == "rise" else 1024 - x if shape == "fall" else 1024 - abs(x - at) if shape == "near" else abs(x - at)) + return s + + +def resolve(held, digest): + """§8.3: the prior a pin names, verified.""" + if digest not in held.priors: + raise Refuse("objective_unresolved") + return read_taste(held.priors[digest]) + + +# ---------------------------------------------------------------- §4 and §5 archives + +def derived(prompt, modifiers, mods): + """§4.2.""" + return prompt + "".join(" " + modifiers[i] for i in range(len(modifiers)) if mods >> i & 1) + + +def run_schedule(m, req, prior): + """§5.2: the elites, ascending by niche.""" + rng = Rng(req["seed"]) + A, V = {}, {} + M = len(req["modifiers"]) + for t in range(req["trials"]): + if t < req["init"]: + g = (rng.draw() % (1 << 32), req["steps"], 0) + else: + O = sorted(A) + a = O[rng.draw() % len(O)] + b = O[rng.draw() % len(O)] + parent = A[b]["genome"] if V[b] < V[a] else A[a]["genome"] + mods = parent[2] + for i in range(M): + if rng.draw() % M == 0: + mods ^= 1 << i + d = rng.draw() % 8 + steps = max(1, min(64, parent[1] + (d - 4 if d < 4 else d - 3))) + g = (rng.draw() % (1 << 32), steps, mods) + pic = gen(m, derived(req["prompt"], req["modifiers"], g[2]), g[0], g[1], req["w"], req["h"]) + dv = descriptors(pic, req["w"], req["h"]) + k = niche(req["grid"], dv) + V[k] = V.get(k, 0) + 1 + s = score(prior, dv) if prior is not None else None + e = {"niche": k, "trial": t, "genome": g, "samples": sha(pic), "d": dv, "score": s} + if k not in A or (s is not None and s > A[k]["score"]): + A[k] = e + return [A[k] for k in sorted(A)] + + +ARCHIVE = ["kind", "generator", "model", "prompt", "modifiers", "width", "height", "steps", "descriptors", "grid", "search", + "objective", "elites", "coverage", "issued_at", "signer_pubkey", "sig"] + + +def read_archive(v): + need(v["generator"] == GENERATOR and v["descriptors"] == DESCRIPTOR_SET) + req = {"model": model_digest(v["model"])} + need(is_prompt(v["prompt"])) + req["prompt"] = v["prompt"] + mods = v["modifiers"] + need(isinstance(mods, list) and len(mods) <= 8) + for x in mods: + need(isinstance(x, str) and 1 <= len(x) <= 32 and all(c in "abcdefghijklmnopqrstuvwxyz0123456789" for c in x)) + req["modifiers"] = mods + need(len(derived(req["prompt"], mods, (1 << len(mods)) - 1)) <= 256) + req["w"], req["h"] = uint(v["width"]), uint(v["height"]) + need(size_ok(req["w"], req["h"])) + req["steps"] = uint(v["steps"], 1, 64) + req["grid"] = read_grid(v["grid"]) + s = exact(v["search"], ["schedule", "seed", "trials", "init"]) + need(s["schedule"] == SCHEDULE) + req["seed"], req["trials"] = uint(s["seed"]), uint(s["trials"], 1, 4096) + req["init"] = uint(s["init"], 1, req["trials"]) + req["objective"] = read_objective(v["objective"]) + need(req["objective"][0] != "model") + elites, trials = [], set() + need(isinstance(v["elites"], list) and 1 <= len(v["elites"]) <= req["trials"]) + for e in v["elites"]: + exact(e, ["niche", "trial", "seed", "steps", "mods", "samples", "descriptors", "score"]) + k = uint(e["niche"], 0, cells(req["grid"]) - 1) + t = uint(e["trial"], 0, req["trials"] - 1) + g = (uint(e["seed"], 0, (1 << 32) - 1), uint(e["steps"], 1, 64), uint(e["mods"], 0, (1 << len(mods)) - 1)) + sc = None if e["score"] is None else uint(e["score"]) + need((sc is not None) == (req["objective"][0] == "taste")) + need(t not in trials and (not elites or elites[-1]["niche"] < k)) + trials.add(t) + elites.append({"niche": k, "trial": t, "genome": g, "samples": hexb(e["samples"], 32), "d": read_vector(e["descriptors"]), "score": sc}) + c = exact(v["coverage"], ["occupied", "cells"]) + return req, elites, uint(c["occupied"]), uint(c["cells"]) + + +def verify_archive(text, case, archives): + try: + v, signer, link = read_record(text, "wai-archive", ARCHIVE) + req, elites, occupied, n_cells = read_archive(v) + except (Bad, KeyError, TypeError): + raise Refuse("record_malformed") + check_signature(v, signer) + held, policy = case["held"], case["policy"] + if (occupied != len(elites) or n_cells != cells(req["grid"])) and "coverage" not in SKIP: # §5.4 step 2 + raise Refuse("coverage_mismatch") + prior = resolve(held, req["objective"][1]) if req["objective"][0] == "taste" else None # step 3 + m = held.model(req["model"]) # step 4 + for e in elites: # step 5 + pic = gen(m, derived(req["prompt"], req["modifiers"], e["genome"][2]), e["genome"][0], e["genome"][1], req["w"], req["h"]) + if sha(pic) != e["samples"] and "regenerate" not in SKIP: + raise Refuse("generation_mismatch") + d = descriptors(pic, req["w"], req["h"]) + if d != e["d"] and "descriptors" not in SKIP: + raise Refuse("descriptor_mismatch") + if niche(req["grid"], d) != e["niche"] and "niche" not in SKIP: + raise Refuse("niche_mismatch") + if e["score"] != (score(prior, d) if prior else None) and "score" not in SKIP: + raise Refuse("score_mismatch") + if policy["replay"] and "replay" not in SKIP: # step 6 + if run_schedule(m, req, prior) != elites: + raise Refuse("archive_replay_mismatch") + archives[link] = (req, elites) + return {"kind": "wai-archive", "link": link.hex(), "level": "replayed" if policy["replay"] else "elites", + "occupied": occupied, "cells": n_cells, "objective": objective_report(req["objective"])} + + +# ---------------------------------------------------------------- §6 default-distance + +DISTANCE = ["kind", "work", "generator", "model", "prompt", "descriptors", "defaults", "class", "descriptor_distance", + "nearest_descriptor", "sample_distance", "nearest_sample", "issued_at", "signer_pubkey", "sig"] +FIGURES = ["descriptor_distance", "nearest_descriptor", "sample_distance", "nearest_sample"] + + +def nearest(xs): + best = None + for i, x in enumerate(xs): + if best is None or x < best[1]: + best = (i, x) + return best + + +def sample_distance(a, b): + """§6.2: ⌈1024 · SAD / (765 · n)⌉ = ⌈1024 · SAD / (255 · bytes)⌉.""" + sad = sum(abs(x - y) for x, y in zip(a, b)) + return -(-1024 * sad // (255 * len(a))) + + +def verify_distance(text, case): + held = case["held"] + try: + v, signer, link = read_record(text, "wai-distance", DISTANCE) + work = read_picture(v["work"], True) + need(is_term(v["generator"]) and is_term(v["model"]) and is_prompt(v["prompt"])) + need(v["descriptors"] == DESCRIPTOR_SET) + cls = v["class"] + need(cls in ("measured", "estimate", "unknown")) + need(isinstance(v["defaults"], list) and len(v["defaults"]) <= DEFAULT_SEEDS) + defaults = [] + for x in v["defaults"]: + exact(x, ["samples", "descriptors"]) + defaults.append((None if x["samples"] is None else hexb(x["samples"], 32), read_vector(x["descriptors"]))) + stated = [None if v[f] is None else uint(v[f]) for f in FIGURES] + if cls == "measured": # §6.3 + need(len(defaults) == DEFAULT_SEEDS and all(s is not None for s, _ in defaults) and all(x is not None for x in stated)) + elif cls == "estimate": + need(defaults and stated[0] is not None and stated[1] is not None and stated[2] is None and stated[3] is None) + else: + need(not defaults and all(x is None for x in stated) or "unknown-null" in SKIP) + digest = model_digest(v["model"]) if v["generator"] == GENERATOR else None + except (Bad, KeyError, TypeError): + raise Refuse("record_malformed") + check_signature(v, signer) + if (v["generator"] == GENERATOR) != (cls == "measured") and "class" not in SKIP: # §6.4 step 1 + raise Refuse("distance_class_invalid") + wb = held.samples_of(work) # step 2 + figures = list(stated) + if cls == "measured": # step 3 + m = held.model(digest) + dset = [gen(m, v["prompt"], k, DEFAULT_STEPS, work["w"], work["h"]) for k in range(DEFAULT_SEEDS)] + dvec = [descriptors(b, work["w"], work["h"]) for b in dset] + for k, (s, d) in enumerate(defaults): + if (s != sha(dset[k]) or d != dvec[k]) and "defaults" not in SKIP: + raise Refuse("default_mismatch") + if wb is None: + raise Refuse("work_unheld") + wd = descriptors(wb, work["w"], work["h"]) + if wd != work["d"] and "descriptors" not in SKIP: + raise Refuse("descriptor_mismatch") + figures = list(nearest(distance(wd, d) for d in dvec)[::-1]) + list(nearest(sample_distance(wb, b) for b in dset)[::-1]) + elif cls == "estimate": # step 4 + if wb is not None and descriptors(wb, work["w"], work["h"]) != work["d"] and "descriptors" not in SKIP: + raise Refuse("descriptor_mismatch") + figures[0:2] = nearest(distance(work["d"], d) for _, d in defaults)[::-1] + elif wb is not None and descriptors(wb, work["w"], work["h"]) != work["d"] and "descriptors" not in SKIP: # step 5 + raise Refuse("descriptor_mismatch") + if figures != stated and "figures" not in SKIP: # step 6 + raise Refuse("distance_mismatch") + out = {"kind": "wai-distance", "link": link.hex(), "class": cls} + out.update(zip(FIGURES, stated)) + return out + + +# ---------------------------------------------------------------- §7 collections + +COLLECTION = ["kind", "scope", "subject", "descriptors", "grid", "members", "coverage", "distances", "issued_at", + "signer_pubkey", "sig"] +SPREAD = ["pairs", "sum", "min", "median", "max", "width", "histogram"] + + +def spread(vs, width): + """§7.2.""" + ds = sorted(distance(vs[i], vs[j]) for i in range(len(vs)) for j in range(i + 1, len(vs))) + hist = [0] * 16 + for d in ds: + hist[min(d // width, 15)] += 1 + return {"pairs": len(ds), "sum": sum(ds), "min": ds[0], "median": ds[(len(ds) - 1) // 2], "max": ds[-1], + "width": width, "histogram": hist} + + +def verify_collection(text, case): + held = case["held"] + try: + v, signer, link = read_record(text, "wai-collection", COLLECTION) + need(v["scope"] in ("gallery", "room", "session", "archive") and is_term(v["subject"])) + need(v["descriptors"] == DESCRIPTOR_SET) + grid = read_grid(v["grid"]) + need(isinstance(v["members"], list) and 2 <= len(v["members"]) <= 256) + members = [read_picture(x, True) for x in v["members"]] + c = exact(v["coverage"], ["occupied", "cells"]) + occupied, n_cells = uint(c["occupied"]), uint(c["cells"]) + s = exact(v["distances"], SPREAD) + for f in SPREAD[:5]: + uint(s[f]) + uint(s["width"], 1, 6144) + need(isinstance(s["histogram"], list) and len(s["histogram"]) == 16) + for x in s["histogram"]: + uint(x) + except (Bad, KeyError, TypeError): + raise Refuse("record_malformed") + check_signature(v, signer) + vs = [] + for p in members: + b = held.samples_of(p) + if b is None: + raise Refuse("member_unheld") + d = descriptors(b, p["w"], p["h"]) + if d != p["d"] and "descriptors" not in SKIP: + raise Refuse("descriptor_mismatch") + vs.append(d) + if (occupied != len({niche(grid, d) for d in vs}) or n_cells != cells(grid)) and "coverage" not in SKIP: + raise Refuse("coverage_mismatch") + got = spread(vs, s["width"]) + if got != s and "spread" not in SKIP: + raise Refuse("distances_mismatch") + return {"kind": "wai-collection", "link": link.hex(), "members": len(members), "occupied": occupied, "cells": n_cells, + "distances": s} + + +# ---------------------------------------------------------------- §9 rankings + +RANKING = ["kind", "prior", "descriptors", "candidates", "scores", "order", "usage", "issued_at", "signer_pubkey", "sig"] + + +def has_term(vocabulary, t): + """ai-usage §6.2 rule 4.""" + if vocabulary == "aipref": + return t in AIPREF_LABELS + if vocabulary == "tdmrep": + return t == "tdm-reservation" + return t in CAWG_KEYS or (AU.cawg_key(t) and not t.startswith("cawg.")) + + +def read_usage(x): + need(isinstance(x, list) and len(x) <= 3) + out = [] + for e in x: + exact(e, ["vocabulary", "term"]) + need(e["vocabulary"] in VOCABULARIES) + t = e["term"] + need(t is None or (isinstance(t, str) and 1 <= len(t.encode("utf-8")) <= 255 and has_term(e["vocabulary"], t))) + need(not out or out[-1][0] < e["vocabulary"]) + out.append((e["vocabulary"], t)) + return out + + +def order_of(scores): + """§9.2.""" + return sorted(range(len(scores)), key=lambda i: (-scores[i], i)) + + +def verify_ranking(text, case): + held = case["held"] + try: + v, signer, link = read_record(text, "wai-ranking", RANKING) + digest = read_pin(v["prior"]) + need(v["descriptors"] == DESCRIPTOR_SET) + need(isinstance(v["candidates"], list) and 1 <= len(v["candidates"]) <= 256) + cands = [read_picture(x, True) for x in v["candidates"]] + need(isinstance(v["scores"], list) and len(v["scores"]) == len(cands)) + scores = [uint(x) for x in v["scores"]] + need(isinstance(v["order"], list) and len(v["order"]) == len(cands)) + order = [uint(x) for x in v["order"]] + need(sorted(order) == list(range(len(cands)))) + usage = read_usage(v["usage"]) + except (Bad, KeyError, TypeError): + raise Refuse("record_malformed") + check_signature(v, signer) + prior = resolve(held, digest) # §9.4 step 1 + recomputed = True + for p in cands: # step 2 + b = held.samples_of(p) + if b is None: + recomputed = False + elif descriptors(b, p["w"], p["h"]) != p["d"] and "descriptors" not in SKIP: + raise Refuse("descriptor_mismatch") + want = [score(prior, p["d"]) for p in cands] + if (want != scores or order_of(want) != order) and "ranking" not in SKIP: # step 3 + raise Refuse("ranking_mismatch") + st = prior["usage"] # step 4, §9.3 + if st is not None and "usage-answered" not in SKIP: + for voc in st["prefs"]: + if not any(u[0] == voc for u in usage): + raise Refuse("prior_usage_unanswered") + uses = [] + for voc, t in usage: + if t is None: + p = "outside" + elif st is None or AU.pref(st, voc, t) is None: + p = "absent" + else: + p = AU.pref(st, voc, t) + if p == "disallow" and "usage-allowed" not in SKIP: + raise Refuse("prior_usage_disallowed") + uses.append({"vocabulary": voc, "term": t, "preference": p}) + return {"kind": "wai-ranking", "link": link.hex(), "prior": digest.hex(), "owner": prior["owner"].hex(), + "scope": prior["scope"], "order": order, "descriptors": "recomputed" if recomputed else "stated", "usage": uses} + + +# ---------------------------------------------------------------- §10 picks + +PICK = ["kind", "act", "work", "from", "issued_at", "signer_pubkey", "sig"] + + +def read_from(x): + need(isinstance(x, dict) and "type" in x) + if x["type"] == "archive": + exact(x, ["type", "archive", "niche"]) + return ("archive", hexb(x["archive"], 32), uint(x["niche"], 0, 4095)) + if x["type"] == "set": + exact(x, ["type", "set"]) + need(isinstance(x["set"], list) and 1 <= len(x["set"]) <= 256) + return ("set", [hexb(s, 32) for s in x["set"]]) + need(x["type"] == "generation") + exact(x, ["type", "generator", "model", "prompt", "seed", "steps"]) + need(is_term(x["generator"]) and is_term(x["model"]) and is_prompt(x["prompt"])) + seed = None if x["seed"] is None else uint(x["seed"], 0, (1 << 32) - 1) + steps = None if x["steps"] is None else uint(x["steps"], 1, 64) + digest = model_digest(x["model"]) if x["generator"] == GENERATOR else None + return ("generation", x["generator"], digest, x["prompt"], seed, steps) + + +def verify_pick(text, case, archives): + held, policy = case["held"], case["policy"] + try: + v, signer, link = read_record(text, "wai-pick", PICK, optional="objective") + need(v["act"] in ("generate", "select")) + work = read_picture(v["work"], False) + src = read_from(v["from"]) + need((v["act"] == "generate") == (src[0] == "generation")) + objective = read_objective(v["objective"]) if "objective" in v else None + except (Bad, KeyError, TypeError): + raise Refuse("record_malformed") + check_signature(v, signer) + if objective is None and policy["objective"] and "disclosure" not in SKIP: # §10.4 step 1 + raise Refuse("objective_undisclosed") + if objective is not None and objective[0] == "taste": # step 2 + resolve(held, objective[1]) + held.samples_of(work) # step 3 + genome = None + if src[0] == "archive": # step 4 + if src[1] not in archives: + raise Refuse("archive_unheld") + req, elites = archives[src[1]] + e = [x for x in elites if x["niche"] == src[2]] + if not e or ((e[0]["samples"] != work["samples"] or (req["w"], req["h"]) != (work["w"], work["h"])) and "in-archive" not in SKIP): + raise Refuse("pick_not_in_archive") + if req["objective"][0] == "taste" and (objective is None or objective[1] != req["objective"][1]) and "inherit" not in SKIP: + raise Refuse("objective_mismatch") + g = e[0]["genome"] + genome = {"seed": g[0], "steps": g[1], "mods": g[2], "prompt": derived(req["prompt"], req["modifiers"], g[2])} + check = "in-archive" + elif src[0] == "set": # step 5 + if work["samples"] not in src[1] and "in-set" not in SKIP: + raise Refuse("pick_not_in_set") + check = "in-set" + elif src[1] == GENERATOR and src[4] is not None and src[5] is not None: # step 6 + m = held.model(src[2]) + if sha(gen(m, src[3], src[4], src[5], work["w"], work["h"])) != work["samples"] and "regenerate" not in SKIP: + raise Refuse("generation_mismatch") + genome = {"seed": src[4], "steps": src[5], "mods": 0, "prompt": src[3]} + check = "regenerated" + else: + check = "stated" + return {"kind": "wai-pick", "link": link.hex(), "act": v["act"], + "objective": "undisclosed" if objective is None else objective_report(objective), "check": check, "genome": genome} + + +# ---------------------------------------------------------------- §12 a case + +def kind_of(text): + try: + v = strict_json(text) + return v.get("kind") if isinstance(v, dict) else None + except Bad: + return None + + +def verify_case(case): + archives, statements = {}, [] + for i, text in enumerate(case["records"]): + k = kind_of(text) + try: + if k == "wai-archive": + s = verify_archive(text, case, archives) + elif k == "wai-distance": + s = verify_distance(text, case) + elif k == "wai-collection": + s = verify_collection(text, case) + elif k == "wai-ranking": + s = verify_ranking(text, case) + elif k == "wai-pick": + s = verify_pick(text, case, archives) + else: + raise Refuse("record_malformed") + except Refuse as r: + return {"outcome": "refuse", "reason": r.reason, "record": i} + statements.append(s) + return {"outcome": "accept", "statements": statements} + + +def source_bytes(m, s): + if "generate" in s: + g = s["generate"] + return gen(m, g["prompt"], g["seed"], g["steps"], g["width"], g["height"]) + return bytes.fromhex(s["hex"]) + + +def case_of(doc, c, model, model_sha): + held = Held({bytes.fromhex(d): model for d in c["held"]["models"] if bytes.fromhex(d) == model_sha}, + {sha(p.encode("utf-8")): p.encode("utf-8") for p in c["held"]["priors"]}, + {sha(b): b for b in (source_bytes(model, s) for s in c["held"]["samples"])}) + return {"records": c["records"], "held": held, + "policy": {"replay": c["policy"]["replay"] == "required", "objective": c["policy"]["objective"] == "required"}} + + +def load_model(doc): + with open(os.path.join(WAI, doc["model"]["path"]), "rb") as f: + b = f.read() + return Model(json.loads(b)), sha(b) + + +def check(doc, quiet=False, only=None): + fails = [] + model, model_sha = load_model(doc) + if model_sha.hex() != doc["model"]["sha256"]: + fails.append("the model file's SHA-256 is not the corpus's") + if only is None: + bad = [g for g in doc["generations"] + if sha(gen(model, g["prompt"], g["seed"], g["steps"], g["width"], g["height"])).hex() != g["sha256"]] + fails += ["generation %r seed %d: another picture" % (g["prompt"], g["seed"]) for g in bad] + if not quiet: + print(("PASS" if not bad else "FAIL") + " Appendix A: %d generations make their SHA-256" % len(doc["generations"])) + bad = [d for d in doc["descriptors"] if descriptors(source_bytes(model, d), d["width"], d["height"]) != d["descriptors"]] + fails += ["descriptor vector %s: another vector" % d["about"] for d in bad] + if not quiet: + print(("PASS" if not bad else "FAIL") + " §3: %d descriptor vectors recompute" % len(doc["descriptors"])) + for c in doc["cases"]: + if only is not None and c["name"] not in only: + continue + try: + got = verify_case(case_of(doc, c, model, model_sha)) + except (KeyError, TypeError, ValueError, AssertionError) as e: + got = {"outcome": "error", "error": repr(e)} + want = {k: c[k] for k in ("outcome", "reason", "record", "statements") if k in c} + ok = got == want + if not ok: + fails.append("%s: got %s" % (c["name"], json.dumps(got)[:200])) + if not quiet: + print(("PASS" if ok else "FAIL") + " %s: %s%s" % (c["name"], c["outcome"], " " + c["reason"] if "reason" in c else "")) + return fails + + +# ---------------------------------------------------------------- the corpus's own checks + +def reasons_of_extension(): + with open(EXTENSION, encoding="utf-8") as f: + text = f.read() + at = text.index("\n## 13. Reasons") + end = text.index("\n## ", at + 1) + return [line.split("`")[1] for line in text[at:end].splitlines() if line.startswith("| `")] + + +REASONS = reasons_of_extension() + + +def resign_free(doc, case, i, f): + """A copy of the corpus whose case `case` has record `i` edited by `f`, not re-signed.""" + d = copy.deepcopy(doc) + c = next(x for x in d["cases"] if x["name"] == case) + v = json.loads(c["records"][i]) + f(v) + c["records"][i] = json.dumps(v, separators=(",", ":")) + return d, case + + +def edit_case(doc, case, f): + d = copy.deepcopy(doc) + f(next(x for x in d["cases"] if x["name"] == case)) + return d, case + + +def mutations(doc): + """Copies of the corpus with one defect each, and the case each touches.""" + def setp(path, x): + def f(v): + at = v + for p in path[:-1]: + at = at[p] + at[path[-1]] = x + return f + + out = [] + out.append(("an elite's seed changed (the signature now fails)", resign_free(doc, "archive-novelty", 0, setp(["elites", 0, "seed"], 1)))) + out.append(("an archive's prompt changed", resign_free(doc, "archive-novelty", 0, setp(["prompt"], "a loud forest at noon")))) + out.append(("a distance's class changed", resign_free(doc, "distance-measured-pulled", 0, setp(["class"], "estimate")))) + out.append(("a ranking's order changed", resign_free(doc, "ranking-personal", 0, setp(["order", 0], 5)))) + out.append(("a pick's objective dropped", resign_free(doc, "pick-from-steered-archive", 1, lambda v: v.pop("objective")))) + out.append(("the model not held", edit_case(doc, "archive-novelty", lambda c: c["held"].__setitem__("models", [])))) + out.append(("the taste prior not held", edit_case(doc, "archive-taste", lambda c: c["held"].__setitem__("priors", [])))) + out.append(("the policy switched to elite checks", edit_case(doc, "archive-elite-dropped", lambda c: c["policy"].__setitem__("replay", "elites")))) + out.append(("the policy stops requiring disclosure", edit_case(doc, "pick-undisclosed-required", lambda c: c["policy"].__setitem__("objective", "optional")))) + out.append(("a pulled work's samples replaced by a default's", edit_case(doc, "distance-measured-pulled", + lambda c: c["held"]["samples"][0]["generate"].__setitem__("seed", 3)))) + out.append(("a collection member's samples dropped", edit_case(doc, "collection-defaults", lambda c: c["held"]["samples"].pop()))) + out.append(("an accepted statement's figure changed", edit_case(doc, "distance-measured-default", + lambda c: c["statements"][0].__setitem__("sample_distance", 1)))) + out.append(("a refusal's reason changed", edit_case(doc, "archive-niche-wrong", lambda c: c.__setitem__("reason", "descriptor_mismatch")))) + out.append(("a prior's text given with a trailing space", edit_case(doc, "ranking-personal", + lambda c: c["held"]["priors"].__setitem__(0, c["held"]["priors"][0] + " ")))) + return out + + +CHECKS = { + "signature": "§2 the signature", + "coverage": "§5.4 step 2 and §7.3 the coverage figures", + "regenerate": "§5.4 step 5 and §10.4 step 6 regeneration", + "descriptors": "the descriptor recomputation", + "niche": "§5.4 step 5 the niche", + "score": "§5.4 step 5 the score", + "replay": "§5.4 step 6 the replay", + "class": "§6.4 step 1 the class", + "unknown-null": "§6.3 unknown is null", + "defaults": "§6.4 step 3 the default set", + "figures": "§6.4 step 6 the figures", + "spread": "§7.3 the distances", + "ranking": "§9.4 step 3 the order", + "usage-answered": "§9.3 every vocabulary answered", + "usage-allowed": "§9.3 no disallowed use", + "owner": "§8.4 the owner's signature", + "canonical-prior": "§8.1 the canonical file", + "disclosure": "§10.3 the disclosure policy", + "inherit": "§10.2 a steered archive's objective", + "in-archive": "§10.4 step 4 the elite", + "in-set": "§10.4 step 5 the set", + "sample-size": "the held samples' size", +} + + +def main(corpus_dir): + fails = [] + st = ED._self_test() + print(("PASS" if not st else "FAIL") + " Ed25519 strict rule self-test " + ",".join(st)) + fails += ["ed25519 self-test"] if st else [] + print(("PASS" if len(REASONS) == 27 else "FAIL") + " §13 read from the extension: %d reasons" % len(REASONS)) + fails += [] if len(REASONS) == 27 else ["§13 does not read"] + with open(os.path.join(corpus_dir, "vectors.json"), encoding="utf-8") as f: + doc = json.load(f) + fails += check(doc) + extra = sorted(set(os.listdir(corpus_dir)) - {"vectors.json", "README.md"}) + print(("PASS" if not extra else "FAIL") + " no file but vectors.json and README.md") + fails += ["an extra file: %s" % n for n in extra] + given = {c["reason"] for c in doc["cases"] if c["outcome"] == "refuse"} + missing = [r for r in REASONS if r not in given] + unknown = sorted(given - set(REASONS)) + print(("PASS" if not missing and not unknown else "FAIL") + " every reason of §13 refuses a case, and no other reason does") + fails += ["no case gives %s" % r for r in missing] + ["a reason §13 does not list: %s" % r for r in unknown] + for label_, (d, case) in mutations(doc): + caught = check(d, quiet=True, only={case}) + print(("PASS" if caught else "FAIL") + " mutated copy fails: %s%s" % (label_, " (%s)" % caught[0][:90] if caught else "")) + if not caught: + fails.append("a mutated copy verifies: %s" % label_) + for name, what in CHECKS.items(): + SKIP.clear() + SKIP.add(name) + caught = check(doc, quiet=True, only={c["name"] for c in doc["cases"]}) + SKIP.clear() + print(("PASS" if caught else "FAIL") + " a verifier without %s fails the corpus%s" % (what, " (%s)" % caught[0][:70] if caught else "")) + if not caught: + fails.append("the corpus does not catch a verifier without %s" % what) + for f in fails: + print("FAIL " + f) + print(("PASS" if not fails else "FAIL") + " exploration corpus: %d generations, %d descriptor vectors, %d cases" + % (len(doc["generations"]), len(doc["descriptors"]), len(doc["cases"]))) + return 1 if fails else 0 + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("usage: exploration_verify.py ", file=sys.stderr) + sys.exit(2) + sys.exit(main(sys.argv[1])) diff --git a/wai/wai-rs/Cargo.toml b/wai/wai-rs/Cargo.toml index 1aef829b2..f57d1affa 100644 --- a/wai/wai-rs/Cargo.toml +++ b/wai/wai-rs/Cargo.toml @@ -306,6 +306,15 @@ synthesis = ["live_room"] # RFC 9651's Dictionary parser is written here. SHA-256, Ed25519 and the room's records only; # no new dependency. ai_usage = ["live_room"] +# Exploration (extensions/exploration): `wai.media.exploration` — six integer descriptors over a +# picture's RGB8 samples; quality-diversity archives (MAP-Elites over a declared grid, run by a +# pinned schedule over wai.generate.spectral, so every elite regenerates and the archive replays +# bit for bit); the default set of a prompt and a work's default-distance (measured for the exact +# generator, an estimate otherwise, unknown never zero); collection statements (coverage and +# pairwise distances); taste priors (integer ranking models, signed by their owners, carrying a +# wai.ai.usage statement), rankings under them, and the disclosure of what steered a pick. +# SHA-256, BLAKE3, Ed25519 and ai_usage's statement reader; no new dependency. +exploration = ["generate", "ai_usage"] # Timed text and live captions (extensions/timed-text): `wai.text.timed` — the cue model, # live caption revisions (`caption` events of wai.live.events with the WTX1 annotation), # and their exact mappings onto WebVTT documents and segments, the IMSC1 Text Profile, @@ -798,6 +807,11 @@ name = "wai_ai_usage_vectors" path = "src/bin/wai_ai_usage_vectors.rs" required-features = ["ai_usage"] +[[bin]] +name = "wai_exploration_vectors" +path = "src/bin/wai_exploration_vectors.rs" +required-features = ["exploration"] + [[bin]] name = "wai_timed_text_vectors" path = "src/bin/wai_timed_text_vectors.rs" @@ -1518,6 +1532,11 @@ name = "ai_usage" path = "tests/ai_usage.rs" required-features = ["ai_usage"] +[[test]] +name = "exploration" +path = "tests/exploration.rs" +required-features = ["exploration"] + [[test]] name = "timed_text" path = "tests/timed_text.rs" diff --git a/wai/wai-rs/src/bin/wai_exploration_vectors.rs b/wai/wai-rs/src/bin/wai_exploration_vectors.rs new file mode 100644 index 000000000..a68693298 --- /dev/null +++ b/wai/wai-rs/src/bin/wai_exploration_vectors.rs @@ -0,0 +1,139 @@ +//! Conformance corpus for exploration (`live-conformance/exploration/`, extensions/exploration.md §14). +//! +//! wai_exploration_vectors gen write vectors.json from fixed seeds +//! wai_exploration_vectors verify every file regenerates byte for byte, no other +//! file but README.md is there, and every case +//! gets the outcome it states +//! wai_exploration_vectors measure [trials] the archive against plain seed sampling and +//! uniform genome sampling at equal compute +//! +//! The generator and this verifier are one implementation. The corpus's second +//! implementation is `live-conformance/exploration_verify.py`, written from the extension's +//! text and sharing no code with this binary. + +use std::collections::BTreeMap; +use std::path::Path; +use wai::exploration::{self, corpus, Axis, Objective, Request}; +use wai::generate::SpectralModel; + +fn main() { + let a: Vec = std::env::args().collect(); + match (a.get(1).map(String::as_str), a.get(2)) { + (Some("gen"), Some(d)) => { + if let Err(e) = std::fs::create_dir_all(d) { + eprintln!("create {d}: {e}"); + std::process::exit(1); + } + for (name, body) in corpus::generate() { + let p = Path::new(d).join(&name); + if let Err(e) = std::fs::write(&p, body) { + eprintln!("write {}: {e}", p.display()); + std::process::exit(1); + } + } + println!("wrote {d}"); + } + (Some("verify"), Some(d)) => std::process::exit(verify(Path::new(d))), + (Some("measure"), n) => measure(n.and_then(|s| s.parse().ok()).unwrap_or(512)), + _ => { + eprintln!("usage: wai_exploration_vectors gen|verify | measure [trials]"); + std::process::exit(2); + } + } +} + +fn verify(dir: &Path) -> i32 { + let mut files = BTreeMap::new(); + let entries = match std::fs::read_dir(dir) { + Ok(e) => e, + Err(e) => { + eprintln!("read {}: {e}", dir.display()); + return 1; + } + }; + for e in entries.flatten() { + let name = e.file_name().to_string_lossy().into_owned(); + if name == "README.md" { + continue; + } + match std::fs::read_to_string(e.path()) { + Ok(s) => { + files.insert(name, s); + } + Err(err) => { + eprintln!("read {name}: {err}"); + return 1; + } + } + } + let generated: BTreeMap = corpus::generate().into_iter().collect(); + let same = files == generated; + println!("{} every file regenerates byte for byte from its seeds, and no other file is there", if same { "PASS" } else { "FAIL" }); + let fails = corpus::verify(&files); + for f in &fails { + println!("FAIL {f}"); + } + println!("{} every case gets the outcome the corpus states", if fails.is_empty() { "PASS" } else { "FAIL" }); + (!same || !fails.is_empty()) as i32 +} + +/// The measurement the pull request reports: for each prompt, the cells of one grid that plain +/// seed sampling (seeds 0, 1, 2, … at the request's steps, the prompt as written), uniform sampling +/// of the archive's genome space (a random seed, steps 1 to 16 and any modifier mask) and the +/// archive's schedule reach with the same number of generations, each of the last two summed over +/// three search seeds; and the mean pairwise descriptor distance of one representative per cell +/// reached. Informative: it changes no conformance outcome. +fn measure(trials: u64) { + let p = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/vectors/generate/generate_spectral_model.json"); + let bytes = std::fs::read(&p).expect("the committed model"); + let m = SpectralModel::from_value(&serde_json::from_slice(&bytes).expect("JSON")); + let modifiers: Vec = ["bright", "dark", "calm", "busy", "warm", "cool", "spiral", "mirror"].map(String::from).to_vec(); + let grid = vec![ + Axis { descriptor: 0, lo: 128, hi: 896, bins: 8 }, + Axis { descriptor: 1, lo: 128, hi: 896, bins: 8 }, + Axis { descriptor: 2, lo: 0, hi: 512, bins: 8 }, + ]; + let prompts = [ + "a quiet forest at night", + "ocean spiral vortex at dusk", + "a red rose", + "neon city grid", + "golden sunrise over the desert", + "portrait of a cat", + ]; + const RUNS: u64 = 3; + println!("{trials} generations each, 64x64, grid luma x chroma x detail (8 x 8 x 8 = 512 cells), modifiers {modifiers:?}"); + println!("cells reached, each column summed over {RUNS} search seeds (plain seed sampling has none: it is the same each time)"); + println!("| prompt | seeds 0..{} | uniform genome | archive | mean pair distance: seeds | uniform | archive |", trials - 1); + println!("|---|---|---|---|---|---|---|"); + let mut tot = [0u64; 3]; + for (i, prompt) in prompts.iter().enumerate() { + let mut cells = [0u64; 3]; + let mut means = [0u64; 3]; + for run in 0..RUNS { + let r = Request { + model: exploration::digest(&bytes), + prompt: prompt.to_string(), + modifiers: modifiers.clone(), + width: 64, + height: 64, + steps: 4, + grid: grid.clone(), + seed: 1 + i as u64 + 100 * run, + trials, + init: (trials / 8).max(1), + objective: Objective::None, + }; + let reach = [exploration::reach_seeds(&m, &r), exploration::reach_random(&m, &r), exploration::reach_archive(&m, &r)]; + for (k, x) in reach.iter().enumerate() { + cells[k] += x.occupied; + means[k] += x.spread.as_ref().map_or(0, |s| s.sum / s.pairs); + } + } + println!("| {prompt} | {} | {} | {} | {} | {} | {} |", cells[0], cells[1], cells[2], means[0] / RUNS, means[1] / RUNS, means[2] / RUNS); + for (t, c) in tot.iter_mut().zip(cells) { + *t += c; + } + } + println!("| all | {} | {} | {} | | | |", tot[0], tot[1], tot[2]); +} diff --git a/wai/wai-rs/src/codecs/registry.rs b/wai/wai-rs/src/codecs/registry.rs index 928acca59..1fd7aa2c0 100644 --- a/wai/wai-rs/src/codecs/registry.rs +++ b/wai/wai-rs/src/codecs/registry.rs @@ -225,6 +225,7 @@ pub const CAP_LIVE_PROVENANCE: &str = "wai.live.provenance"; pub const CAP_EDGE_DERIVATION: &str = "wai.edge.derivation"; pub const CAP_MEDIA_SYNTHESIS: &str = "wai.media.synthesis"; pub const CAP_AI_USAGE: &str = "wai.ai.usage"; +pub const CAP_MEDIA_EXPLORATION: &str = "wai.media.exploration"; /// One row per string SPEC §5 registers that is a payload, companion or record: /// `(string, SPEC section, edition, registered)`. @@ -318,6 +319,7 @@ const ROWS: &[(&str, &str, Option<&str>, &str)] = &[ (CAP_LIVE_PROVENANCE, S_INTERACTIVE, None, "2026-10-21"), (CAP_MEDIA_SYNTHESIS, S_INTERACTIVE, None, "2026-10-21"), (CAP_AI_USAGE, S_INTERACTIVE, None, "2026-10-21"), + (CAP_MEDIA_EXPLORATION, S_INTERACTIVE, None, "2026-10-21"), (CAP_AUDIO_IAMF, S_IMMERSIVE, None, "2026-06-17"), (CAP_AUDIO_AC4, S_IMMERSIVE, None, "2026-06-17"), (CAP_AUDIO_IVAS, S_IMMERSIVE, None, "2026-06-17"), @@ -374,6 +376,7 @@ const RECORDS: &[&str] = &[ CAP_EDGE_DERIVATION, CAP_MEDIA_SYNTHESIS, CAP_AI_USAGE, + CAP_MEDIA_EXPLORATION, ]; /// A named identifier SPEC uses that has the shape of a capability string but is @@ -534,6 +537,7 @@ const LIVE_ADS: &str = "extensions/live-ads.md"; const LIVE_PROVENANCE: &str = "extensions/live-provenance.md"; const DERIVING_EDGE: &str = "extensions/deriving-edge.md"; const SYNTHESIS: &str = "extensions/synthesis.md"; +const EXPLORATION: &str = "extensions/exploration.md"; const fn wire(name: &'static str, kind: WireKind, document: &'static str, section: &'static str, status: WireStatus) -> WireIdentifier { @@ -545,8 +549,8 @@ const fn wire(name: &'static str, kind: WireKind, document: &'static str, sectio /// (jwp-receipts §7), of packaging, of live events, of live rooms, of capture binding, of /// live composition, of live recording, of timed text, of live metering, of energy steering, /// of live moderation, of confidentiality, of forensic watermark sessions, of live ads, of live -/// provenance, of the deriving edge, of synthesis and of AI usage, in document order. The export -/// lists them sorted by name and kind. +/// provenance, of the deriving edge, of synthesis, of AI usage and of exploration, in document +/// order. The export lists them sorted by name and kind. pub const WIRE_IDENTIFIERS: &[WireIdentifier] = &[ wire("WAI1", WireKind::Magic, "SPEC.md", "§2", WireStatus::Defined), wire("WAI2", WireKind::Magic, "SPEC.md", "§7.1", WireStatus::Defined), @@ -644,6 +648,12 @@ pub const WIRE_IDENTIFIERS: &[WireIdentifier] = &[ wire("WAU1", WireKind::Magic, AI_USAGE, "§4.2", WireStatus::Defined), wire("wai_ai_usage", WireKind::Catalog, MOQ_FORMAT, "§4", WireStatus::Defined), wire("WAI-Usage-Claim", WireKind::HttpHeader, AI_USAGE, "§7.3", WireStatus::Proposed), + wire("wai-archive", WireKind::DocumentKind, EXPLORATION, "§5.3", WireStatus::Defined), + wire("wai-distance", WireKind::DocumentKind, EXPLORATION, "§6.3", WireStatus::Defined), + wire("wai-collection", WireKind::DocumentKind, EXPLORATION, "§7.1", WireStatus::Defined), + wire("wai-taste", WireKind::DocumentKind, EXPLORATION, "§8.1", WireStatus::Defined), + wire("wai-ranking", WireKind::DocumentKind, EXPLORATION, "§9.1", WireStatus::Defined), + wire("wai-pick", WireKind::DocumentKind, EXPLORATION, "§10.2", WireStatus::Defined), ]; /// A string with the shape of a capability that the reference implementation uses diff --git a/wai/wai-rs/src/exploration.rs b/wai/wai-rs/src/exploration.rs new file mode 100644 index 000000000..6fba5c0d3 --- /dev/null +++ b/wai/wai-rs/src/exploration.rs @@ -0,0 +1,1714 @@ +//! Exploration (`extensions/exploration.md`): the record `wai.media.exploration`. +//! +//! `wai.generate.spectral` is exact: `(model, prompt, seed, steps)` gives the same bytes on +//! every machine. That makes four things recomputable here that are otherwise estimates: +//! +//! - **Descriptors** (§3): six integer derivations over a picture's canonical samples (`RGB8`): +//! mean luma, chroma, detail, palette diversity and the two coordinates of the luma centroid, +//! each in `0..=1024`. They place a picture; they do not judge it. +//! - **Archives** (§5): a quality-diversity archive, MAP-Elites over a declared grid of +//! descriptors, run by a pinned schedule from a declared search seed. Every elite names its +//! genome (seed, steps, the modifiers it adds to the prompt), so it regenerates, and the whole +//! archive replays bit for bit. +//! - **Default-distance** (§6): the model's default for a prompt is recomputable (seeds 0 to +//! 15 at four steps), so how far a work sits from it is a signed measurement. For a generator +//! that is not exact the figure is an estimate, never a measurement; unknown is never zero. +//! - **Collection statements** (§7): descriptor coverage and pairwise distances of a gallery, +//! a room's outputs or a session's candidates: a homogenization meter that recomputes. +//! +//! Taste is a declared, owned objective (§8–§10): a **taste prior** is an integer ranking model +//! over the descriptors, signed by its owner and pinned by digest; it carries its owner's usage +//! statement ([`crate::ai_usage`]). A **ranking** under it reproduces. Every archive, ranking +//! and **pick** an aesthetic or reward model steered names that model by digest, or states +//! `none`; a policy may require it, and a selection from a steered archive cannot drop it. +//! +//! The corpus is `live-conformance/exploration/` ([`corpus`]); its second implementation is +//! `live-conformance/exploration_verify.py`. + +use std::collections::{BTreeMap, BTreeSet}; + +use ed25519_dalek::{Signer, SigningKey}; +use serde_json::{json, Map, Value}; +use sha2::{Digest, Sha256}; + +use crate::ai_usage::{Preference, Statement}; +use crate::claim_receipt::consumption::Vocabulary; +use crate::claim_receipt::{rfc3339, term_ok}; +use crate::generate::{generate, SpectralModel}; +use crate::jcs::{jcs, MAX_INTEGER}; + +pub mod corpus; + +/// The record this extension registers. +pub const CAPABILITY: &str = "wai.media.exploration"; +/// The domain every record is signed under (§2). +pub const SIGN_DOMAIN: &[u8] = b"wai:exploration\x01"; +/// The domain of a record's link hash (§2). +pub const LINK_DOMAIN: &[u8] = b"wai:exploration-link\x01"; +/// The descriptor set of §3. +pub const DESCRIPTOR_SET: &str = "wai-exploration:image6"; +/// The search schedule of §5.2. +pub const SCHEDULE: &str = "wai-exploration:map-elites/1"; +/// The one exact generator this revision recomputes (§4). +pub const GENERATOR: &str = "wai.generate.spectral"; +/// The descriptors, in the vector's order (§3). +pub const DESCRIPTORS: [&str; 6] = ["luma", "chroma", "detail", "palette", "centroid_x", "centroid_y"]; +/// The default set (§6.1): seeds `0..DEFAULT_SEEDS` at `DEFAULT_STEPS`. +pub const DEFAULT_SEEDS: u64 = 16; +pub const DEFAULT_STEPS: u64 = 4; +/// Bounds (§5.1, §7, §8, §9). +pub const MAX_MODIFIERS: usize = 8; +pub const MAX_MODIFIER: usize = 32; +pub const MAX_PROMPT: usize = 256; +pub const MAX_TRIALS: u64 = 4096; +pub const MAX_AXES: usize = 4; +pub const MAX_BINS: u64 = 64; +pub const MAX_CELLS: u64 = 4096; +pub const MAX_SIDE: u64 = 4096; +pub const MAX_PIXELS: u64 = 1 << 23; +pub const MAX_STEPS: u64 = 64; +pub const MAX_SEED: u64 = (1 << 32) - 1; +pub const MAX_MEMBERS: usize = 256; +pub const MAX_TERMS: usize = 32; +pub const MAX_LABEL: usize = 256; +pub const HISTOGRAM_BINS: usize = 16; +/// The largest descriptor distance (§3.7): six descriptors of at most 1024 each. +pub const MAX_DISTANCE: u64 = 6 * 1024; + +/// Why a case is refused (§13). +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum Reason { + RecordMalformed, + BadKey, + BadSignature, + ModelUnheld, + ObjectiveUnresolved, + TasteNotOwner, + ObjectiveUndisclosed, + ObjectiveMismatch, + GenerationMismatch, + SamplesMismatch, + DescriptorMismatch, + NicheMismatch, + ScoreMismatch, + CoverageMismatch, + ArchiveReplayMismatch, + DistanceClassInvalid, + DefaultMismatch, + WorkUnheld, + DistanceMismatch, + MemberUnheld, + DistancesMismatch, + RankingMismatch, + PriorUsageUnanswered, + PriorUsageDisallowed, + ArchiveUnheld, + PickNotInArchive, + PickNotInSet, +} + +impl Reason { + /// The codes, in §13's order. + pub const ALL: [Reason; 27] = [ + Reason::RecordMalformed, + Reason::BadKey, + Reason::BadSignature, + Reason::ModelUnheld, + Reason::ObjectiveUnresolved, + Reason::TasteNotOwner, + Reason::ObjectiveUndisclosed, + Reason::ObjectiveMismatch, + Reason::GenerationMismatch, + Reason::SamplesMismatch, + Reason::DescriptorMismatch, + Reason::NicheMismatch, + Reason::ScoreMismatch, + Reason::CoverageMismatch, + Reason::ArchiveReplayMismatch, + Reason::DistanceClassInvalid, + Reason::DefaultMismatch, + Reason::WorkUnheld, + Reason::DistanceMismatch, + Reason::MemberUnheld, + Reason::DistancesMismatch, + Reason::RankingMismatch, + Reason::PriorUsageUnanswered, + Reason::PriorUsageDisallowed, + Reason::ArchiveUnheld, + Reason::PickNotInArchive, + Reason::PickNotInSet, + ]; + + /// The conformance code. + pub fn code(self) -> &'static str { + match self { + Reason::RecordMalformed => "record_malformed", + Reason::BadKey => "bad_key", + Reason::BadSignature => "bad_signature", + Reason::ModelUnheld => "model_unheld", + Reason::ObjectiveUnresolved => "objective_unresolved", + Reason::TasteNotOwner => "taste_not_owner", + Reason::ObjectiveUndisclosed => "objective_undisclosed", + Reason::ObjectiveMismatch => "objective_mismatch", + Reason::GenerationMismatch => "generation_mismatch", + Reason::SamplesMismatch => "samples_mismatch", + Reason::DescriptorMismatch => "descriptor_mismatch", + Reason::NicheMismatch => "niche_mismatch", + Reason::ScoreMismatch => "score_mismatch", + Reason::CoverageMismatch => "coverage_mismatch", + Reason::ArchiveReplayMismatch => "archive_replay_mismatch", + Reason::DistanceClassInvalid => "distance_class_invalid", + Reason::DefaultMismatch => "default_mismatch", + Reason::WorkUnheld => "work_unheld", + Reason::DistanceMismatch => "distance_mismatch", + Reason::MemberUnheld => "member_unheld", + Reason::DistancesMismatch => "distances_mismatch", + Reason::RankingMismatch => "ranking_mismatch", + Reason::PriorUsageUnanswered => "prior_usage_unanswered", + Reason::PriorUsageDisallowed => "prior_usage_disallowed", + Reason::ArchiveUnheld => "archive_unheld", + Reason::PickNotInArchive => "pick_not_in_archive", + Reason::PickNotInSet => "pick_not_in_set", + } + } +} + +impl std::fmt::Display for Reason { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.code()) + } +} + +impl std::error::Error for Reason {} + +// --------------------------------------------------------------------------------------- +// §3 Descriptors +// --------------------------------------------------------------------------------------- + +/// A picture's descriptor vector (§3), in [`DESCRIPTORS`]' order. +pub type Vector = [u64; 6]; + +/// The luma of one `RGB8` pixel (§3.1). +fn luma_of(p: &[u8]) -> u64 { + (77 * p[0] as u64 + 150 * p[1] as u64 + 29 * p[2] as u64 + 128) >> 8 +} + +/// The descriptor vector of a `w` × `h` `RGB8` buffer (§3). `rgb` is `w·h·3` bytes, `w` and +/// `h` at least 1. +pub fn descriptors(rgb: &[u8], w: usize, h: usize) -> Vector { + assert!(w >= 1 && h >= 1 && rgb.len() == w * h * 3, "an RGB8 buffer of its size"); + let n = (w * h) as u128; + let y: Vec = rgb.chunks_exact(3).map(luma_of).collect(); + let s: u128 = y.iter().map(|&v| v as u128).sum(); + let luma = 1024 * s / (255 * n); + let c: u128 = rgb.chunks_exact(3).map(|p| (p.iter().max().unwrap() - p.iter().min().unwrap()) as u128).sum(); + let chroma = 1024 * c / (255 * n); + let mut g: u128 = 0; + for row in 0..h { + for col in 0..w { + let p = row * w + col; + if col + 1 < w { + g += y[p + 1].abs_diff(y[p]) as u128; + } + if row + 1 < h { + g += y[p + w].abs_diff(y[p]) as u128; + } + } + } + let pairs = ((w - 1) * h + w * (h - 1)) as u128; + let detail = if pairs == 0 { 0 } else { (1024 * g / (16 * pairs)).min(1024) }; + let mut counts = [0u128; 64]; + for p in rgb.chunks_exact(3) { + counts[((p[0] >> 6) as usize) * 16 + ((p[1] >> 6) as usize) * 4 + (p[2] >> 6) as usize] += 1; + } + let sq: u128 = counts.iter().map(|k| k * k).sum(); + let palette = 1024 * (n * n - sq) / (n * n); + let (mut sv, mut sx, mut sy) = (0u128, 0u128, 0u128); + for (p, &v) in y.iter().enumerate() { + let v = v as u128 + 1; + sv += v; + sx += (2 * (p % w) as u128 + 1) * v; + sy += (2 * (p / w) as u128 + 1) * v; + } + let cx = 1024 * sx / (2 * w as u128 * sv); + let cy = 1024 * sy / (2 * h as u128 * sv); + [luma as u64, chroma as u64, detail as u64, palette as u64, cx as u64, cy as u64] +} + +/// The descriptor distance of two vectors (§3.7): the sum of absolute differences. +pub fn distance(a: &Vector, b: &Vector) -> u64 { + a.iter().zip(b).map(|(x, y)| x.abs_diff(*y)).sum() +} + +/// The sample distance of two buffers of one size (§6.2): ⌈1024 · SAD / (765 · n)⌉, 0 exactly +/// when they are equal. +pub fn sample_distance(a: &[u8], b: &[u8]) -> u64 { + assert_eq!(a.len(), b.len()); + let sad: u128 = a.iter().zip(b).map(|(x, y)| x.abs_diff(*y) as u128).sum(); + let den = 255 * a.len() as u128; + (1024 * sad).div_ceil(den) as u64 +} + +/// One axis of a grid (§3.6). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Axis { + pub descriptor: usize, + pub lo: u64, + pub hi: u64, + pub bins: u64, +} + +impl Axis { + /// The bin of a descriptor value (§3.6). + pub fn bin(&self, d: u64) -> u64 { + if d < self.lo { + 0 + } else if d >= self.hi { + self.bins - 1 + } else { + (d - self.lo) * self.bins / (self.hi - self.lo) + } + } + + fn json(&self) -> Value { + json!({"descriptor": DESCRIPTORS[self.descriptor], "lo": self.lo, "hi": self.hi, "bins": self.bins}) + } +} + +/// The niche of a vector in a grid (§3.6): the bins in mixed radix, the first axis most +/// significant. +pub fn niche(grid: &[Axis], d: &Vector) -> u64 { + grid.iter().fold(0, |k, a| k * a.bins + a.bin(d[a.descriptor])) +} + +/// The number of cells of a grid. +pub fn cells(grid: &[Axis]) -> u64 { + grid.iter().map(|a| a.bins).product() +} + +// --------------------------------------------------------------------------------------- +// §4 The generator path +// --------------------------------------------------------------------------------------- + +/// The PRNG of the schedule (§5.2): splitmix64. +#[derive(Clone, Debug)] +pub struct Rng(pub u64); + +impl Rng { + pub fn next_u64(&mut self) -> u64 { + self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15); + let mut z = self.0; + z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9); + z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB); + z ^ (z >> 31) + } +} + +/// A prompt as an instruction object holds one (§4.1): 0 to 256 bytes, each 0x20 to 0x7E but +/// `"` and `\`. +pub fn prompt_ok(s: &str) -> bool { + s.len() <= MAX_PROMPT && s.bytes().all(|b| (0x20..=0x7e).contains(&b) && b != b'"' && b != b'\\') +} + +/// A modifier (§4.2): 1 to 32 bytes of `a`–`z` and `0`–`9`. +pub fn modifier_ok(s: &str) -> bool { + (1..=MAX_MODIFIER).contains(&s.len()) && s.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit()) +} + +/// The derived prompt of a modifier mask (§4.2). +pub fn derived_prompt(prompt: &str, modifiers: &[String], mods: u64) -> String { + let mut p = prompt.to_string(); + for (i, m) in modifiers.iter().enumerate() { + if mods >> i & 1 == 1 { + p.push(' '); + p.push_str(m); + } + } + p +} + +/// A genome (§4.3). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Genome { + pub seed: u64, + pub steps: u64, + pub mods: u64, +} + +/// A picture made from a genome (§4.3). +pub fn render(m: &SpectralModel, prompt: &str, modifiers: &[String], g: Genome, w: u64, h: u64) -> Vec { + generate(m, &derived_prompt(prompt, modifiers, g.mods), g.seed, g.steps as usize, h as usize, w as usize) +} + +// --------------------------------------------------------------------------------------- +// §2 Records: encodings, signature, identity +// --------------------------------------------------------------------------------------- + +fn sha256(parts: &[&[u8]]) -> [u8; 32] { + let mut h = Sha256::new(); + for p in parts { + h.update(p); + } + h.finalize().into() +} + +/// SHA-256 of samples or of a parameter set. +pub fn digest(b: &[u8]) -> [u8; 32] { + sha256(&[b]) +} + +pub fn hex(b: &[u8]) -> String { + b.iter().map(|x| format!("{x:02x}")).collect() +} + +pub fn unhex(s: &str) -> Option> { + if !s.len().is_multiple_of(2) || !s.bytes().all(|c| c.is_ascii_digit() || (b'a'..=b'f').contains(&c)) { + return None; + } + (0..s.len()).step_by(2).map(|i| u8::from_str_radix(&s[i..i + 2], 16).ok()).collect() +} + +fn hexn(v: &Value) -> Option<[u8; N]> { + unhex(v.as_str()?)?.try_into().ok() +} + +fn int(v: &Value) -> Option { + v.as_u64().filter(|&n| n <= MAX_INTEGER) +} + +fn int_in(v: &Value, lo: u64, hi: u64) -> Option { + int(v).filter(|n| (lo..=hi).contains(n)) +} + +fn nullable(v: &Value, f: impl Fn(&Value) -> Option) -> Option> { + if v.is_null() { Some(None) } else { f(v).map(Some) } +} + +fn term(v: &Value) -> Option { + let s = v.as_str()?; + term_ok(s).ok()?; + Some(s.to_string()) +} + +fn label(v: &Value) -> Option { + let s = v.as_str()?; + (!s.is_empty() && s.len() <= MAX_LABEL).then(|| s.to_string()) +} + +fn one_of(v: &Value, set: &[&str]) -> Option { + let s = v.as_str()?; + set.contains(&s).then(|| s.to_string()) +} + +/// A value the encodings admit (§2): strings, integers, `null`, arrays and objects of them. +fn subset_ok(v: &Value) -> bool { + match v { + Value::Null | Value::String(_) => true, + Value::Number(_) => int(v).is_some(), + Value::Bool(_) => false, + Value::Array(a) => a.iter().all(subset_ok), + Value::Object(o) => o.values().all(subset_ok), + } +} + +/// An object with exactly these members. +fn exact<'a>(v: &'a Value, members: &[&str]) -> Option<&'a Map> { + let o = v.as_object()?; + (o.len() == members.len() && members.iter().all(|m| o.contains_key(*m))).then_some(o) +} + +/// The bytes a record is signed over (§2). +pub fn signing_bytes(record: &Value) -> Vec { + let mut r = record.clone(); + if let Some(o) = r.as_object_mut() { + o.remove("sig"); + } + let mut m = SIGN_DOMAIN.to_vec(); + m.extend_from_slice(jcs(&r).expect("a record in the subset").as_bytes()); + m +} + +/// A record's link hash (§2). +pub fn link_hash(record: &Value) -> [u8; 32] { + let mut h = blake3::Hasher::new(); + h.update(LINK_DOMAIN); + h.update(jcs(record).expect("a record in the subset").as_bytes()); + *h.finalize().as_bytes() +} + +/// Sign a record body: adds `signer_pubkey` and `sig` (§2). +pub fn sign(mut body: Value, key: &SigningKey) -> Value { + let o = body.as_object_mut().expect("a record is an object"); + o.insert("signer_pubkey".into(), json!(hex(&key.verifying_key().to_bytes()))); + o.remove("sig"); + let sig = key.sign(&signing_bytes(&body)); + body.as_object_mut().expect("an object").insert("sig".into(), json!(hex(&sig.to_bytes()))); + body +} + +/// Read a record's text (§2): strict JSON, an object of `kind`'s exact members (`optional` +/// may be absent), the encodings, `issued_at`. Returns the value, its signer and its link. +fn read_record(text: &str, kind: &str, members: &[&str], optional: Option<&str>) -> Result<(Value, [u8; 32], [u8; 32]), Reason> { + let v = crate::claim_text::read(text).map_err(|_| Reason::RecordMalformed)?; + let full: Vec<&str> = members.iter().copied().chain(optional).collect(); + let o = exact(&v, members).or_else(|| optional.and_then(|_| exact(&v, &full))).ok_or(Reason::RecordMalformed)?; + if o.get("kind").and_then(Value::as_str) != Some(kind) || !subset_ok(&v) { + return Err(Reason::RecordMalformed); + } + let signer: [u8; 32] = hexn(&o["signer_pubkey"]).ok_or(Reason::RecordMalformed)?; + if hexn::<64>(&o["sig"]).is_none() || !o["issued_at"].as_str().is_some_and(rfc3339) { + return Err(Reason::RecordMalformed); + } + Ok((v.clone(), signer, link_hash(&v))) +} + +fn check_signature(v: &Value, signer: &[u8; 32]) -> Result<(), Reason> { + let sig: [u8; 64] = hexn(&v["sig"]).ok_or(Reason::RecordMalformed)?; + crate::sig::verify_strict(signer, &signing_bytes(v), &sig).map_err(|e| match e { + crate::sig::SigError::BadKey => Reason::BadKey, + crate::sig::SigError::BadSignature => Reason::BadSignature, + }) +} + +fn kind_of(text: &str) -> Option { + let v = crate::claim_text::read(text).ok()?; + v.get("kind")?.as_str().map(String::from) +} + +// ---- shared members ---- + +fn read_vector(v: &Value) -> Option { + let a = v.as_array()?; + if a.len() != 6 { + return None; + } + let mut d = [0u64; 6]; + for (slot, x) in d.iter_mut().zip(a) { + *slot = int_in(x, 0, 1024)?; + } + Some(d) +} + +fn size_ok(w: u64, h: u64) -> bool { + (1..=MAX_SIDE).contains(&w) && (1..=MAX_SIDE).contains(&h) && w * h <= MAX_PIXELS +} + +/// A picture named by its samples (§2): `{"samples", "width", "height"}`, and `descriptors` +/// where the record's table lists it. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Picture { + pub samples: [u8; 32], + pub width: u64, + pub height: u64, + pub descriptors: Option, +} + +fn read_picture(v: &Value, with_descriptors: bool) -> Option { + let o = if with_descriptors { + exact(v, &["samples", "width", "height", "descriptors"])? + } else { + exact(v, &["samples", "width", "height"])? + }; + let (width, height) = (int(&o["width"])?, int(&o["height"])?); + if !size_ok(width, height) { + return None; + } + let descriptors = if with_descriptors { Some(read_vector(&o["descriptors"])?) } else { None }; + Some(Picture { samples: hexn(&o["samples"])?, width, height, descriptors }) +} + +fn read_grid(v: &Value) -> Option> { + let a = v.as_array()?; + if a.is_empty() || a.len() > MAX_AXES { + return None; + } + let mut grid = Vec::new(); + let mut seen = BTreeSet::new(); + for x in a { + let o = exact(x, &["descriptor", "lo", "hi", "bins"])?; + let d = DESCRIPTORS.iter().position(|n| Some(*n) == o["descriptor"].as_str())?; + let (lo, hi, bins) = (int_in(&o["lo"], 0, 1024)?, int_in(&o["hi"], 0, 1024)?, int_in(&o["bins"], 1, MAX_BINS)?); + if lo >= hi || !seen.insert(d) { + return None; + } + grid.push(Axis { descriptor: d, lo, hi, bins }); + } + (cells(&grid) <= MAX_CELLS).then_some(grid) +} + +fn read_model_digest(v: &Value) -> Option<[u8; 32]> { + let s = v.as_str()?.strip_prefix("sha256:")?; + (s.len() == 64).then_some(())?; + unhex(s)?.try_into().ok() +} + +fn read_prompt(v: &Value) -> Option { + let s = v.as_str()?; + prompt_ok(s).then(|| s.to_string()) +} + +/// A taste prior's pin (§8.3): SPEC §3.1's members `id`, `sha256` and `determinism`. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Pin { + pub id: String, + pub sha256: [u8; 32], + pub determinism: String, +} + +fn read_pin(v: &Value) -> Option { + let o = exact(v, &["id", "sha256", "determinism"])?; + Some(Pin { id: label(&o["id"])?, sha256: hexn(&o["sha256"])?, determinism: label(&o["determinism"])? }) +} + +/// What steered a record (§10.1). +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Objective { + /// Nothing steered it. + None, + /// A taste prior of §8, which a verifier resolves and runs. + Taste(Pin), + /// Another aesthetic or reward model, by the SHA-256 of its parameter set: named, not run. + Model { sha256: [u8; 32], id: String }, +} + +impl Objective { + fn read(v: &Value) -> Option { + if v.as_str() == Some("none") { + return Some(Objective::None); + } + match v.get("type")?.as_str()? { + "taste" => Some(Objective::Taste(read_pin(&exact(v, &["type", "prior"])?["prior"])?)), + "model" => { + let o = exact(v, &["type", "sha256", "id"])?; + Some(Objective::Model { sha256: hexn(&o["sha256"])?, id: label(&o["id"])? }) + } + _ => None, + } + } + + /// The digest it names, if any. + pub fn digest(&self) -> Option<[u8; 32]> { + match self { + Objective::None => None, + Objective::Taste(p) => Some(p.sha256), + Objective::Model { sha256, .. } => Some(*sha256), + } + } + + fn report(&self) -> Value { + match self { + Objective::None => json!("none"), + Objective::Taste(p) => json!({"type": "taste", "sha256": hex(&p.sha256)}), + Objective::Model { sha256, .. } => json!({"type": "model", "sha256": hex(sha256)}), + } + } + + pub fn json(&self) -> Value { + match self { + Objective::None => json!("none"), + Objective::Taste(p) => json!({"type": "taste", "prior": {"id": p.id, "sha256": hex(&p.sha256), "determinism": p.determinism}}), + Objective::Model { sha256, id } => json!({"type": "model", "sha256": hex(sha256), "id": id}), + } + } +} + +// --------------------------------------------------------------------------------------- +// §8 Taste priors +// --------------------------------------------------------------------------------------- + +/// The shape of a taste term (§8.2). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Shape { + Rise, + Fall, + Near, + Far, +} + +impl Shape { + pub const ALL: [Shape; 4] = [Shape::Rise, Shape::Fall, Shape::Near, Shape::Far]; + pub fn name(self) -> &'static str { + match self { + Shape::Rise => "rise", + Shape::Fall => "fall", + Shape::Near => "near", + Shape::Far => "far", + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TasteTerm { + pub descriptor: usize, + pub shape: Shape, + pub at: u64, + pub weight: u64, +} + +impl TasteTerm { + /// The term's value at a descriptor value (§8.2). + pub fn value(&self, d: u64) -> u64 { + self.weight + * match self.shape { + Shape::Rise => d, + Shape::Fall => 1024 - d, + Shape::Near => 1024 - d.abs_diff(self.at), + Shape::Far => d.abs_diff(self.at), + } + } + + pub fn json(&self) -> Value { + json!({"descriptor": DESCRIPTORS[self.descriptor], "shape": self.shape.name(), "at": self.at, "weight": self.weight}) + } +} + +/// A taste prior that reads and verifies (§8). +#[derive(Clone, Debug)] +pub struct Taste { + pub digest: [u8; 32], + pub owner: [u8; 32], + pub scope: String, + pub terms: Vec, + pub usage: Option, +} + +impl Taste { + /// The score of a descriptor vector (§8.2). + pub fn score(&self, d: &Vector) -> u64 { + self.terms.iter().map(|t| t.value(d[t.descriptor])).sum() + } +} + +pub const TASTE_MEMBERS: [&str; 9] = ["kind", "owner", "scope", "descriptors", "terms", "usage", "issued_at", "signer_pubkey", "sig"]; +pub const SCOPES: [&str; 2] = ["personal", "community"]; + +/// Read and verify a taste prior's file (§8.1, §8.4). +pub fn read_taste(bytes: &[u8]) -> Result { + let bad = Reason::RecordMalformed; + let text = std::str::from_utf8(bytes).map_err(|_| bad)?; + let (v, signer, _) = read_record(text, "wai-taste", &TASTE_MEMBERS, None)?; + if jcs(&v).map_err(|_| bad)?.as_bytes() != bytes { + return Err(bad); + } + let owner: [u8; 32] = hexn(&v["owner"]).ok_or(bad)?; + let scope = one_of(&v["scope"], &SCOPES).ok_or(bad)?; + if v["descriptors"].as_str() != Some(DESCRIPTOR_SET) { + return Err(bad); + } + let ts = v["terms"].as_array().filter(|a| (1..=MAX_TERMS).contains(&a.len())).ok_or(bad)?; + let mut terms = Vec::new(); + for t in ts { + let o = exact(t, &["descriptor", "shape", "at", "weight"]).ok_or(bad)?; + let descriptor = DESCRIPTORS.iter().position(|n| Some(*n) == o["descriptor"].as_str()).ok_or(bad)?; + let shape = Shape::ALL.into_iter().find(|s| Some(s.name()) == o["shape"].as_str()).ok_or(bad)?; + let at = int_in(&o["at"], 0, 1024).ok_or(bad)?; + let weight = int_in(&o["weight"], 1, 1024).ok_or(bad)?; + if matches!(shape, Shape::Rise | Shape::Fall) && at != 0 { + return Err(bad); + } + terms.push(TasteTerm { descriptor, shape, at, weight }); + } + let usage = nullable(&v["usage"], |s| Statement::read(s).ok()).ok_or(bad)?; + check_signature(&v, &signer)?; + if signer != owner { + return Err(Reason::TasteNotOwner); + } + Ok(Taste { digest: digest(bytes), owner, scope, terms, usage }) +} + +/// Write a taste prior's file (§8.1): the canonical form of the signed record. +pub fn taste_file(owner_key: &SigningKey, signer: &SigningKey, scope: &str, terms: &[TasteTerm], usage: Option<&Value>, issued_at: &str) -> Vec { + let body = json!({ + "kind": "wai-taste", + "owner": hex(&owner_key.verifying_key().to_bytes()), + "scope": scope, + "descriptors": DESCRIPTOR_SET, + "terms": terms.iter().map(TasteTerm::json).collect::>(), + "usage": usage.cloned().unwrap_or(Value::Null), + "issued_at": issued_at, + }); + jcs(&sign(body, signer)).expect("in the subset").into_bytes() +} + +// --------------------------------------------------------------------------------------- +// What a verifier holds (§12.1) +// --------------------------------------------------------------------------------------- + +/// The parameter sets and samples a verifier holds, each found by its SHA-256. +#[derive(Default)] +pub struct Held { + pub models: BTreeMap<[u8; 32], SpectralModel>, + pub priors: BTreeMap<[u8; 32], Vec>, + pub samples: BTreeMap<[u8; 32], Vec>, +} + +impl Held { + /// Hold a model file. A file that is not a model bundle is not held. + pub fn hold_model(&mut self, bytes: &[u8]) { + if let Ok(v) = serde_json::from_slice::(bytes) + && v["sine_lut"].is_array() + { + self.models.insert(digest(bytes), SpectralModel::from_value(&v)); + } + } + + pub fn hold_prior(&mut self, bytes: Vec) { + self.priors.insert(digest(&bytes), bytes); + } + + pub fn hold_samples(&mut self, bytes: Vec) { + self.samples.insert(digest(&bytes), bytes); + } + + fn model(&self, d: &[u8; 32]) -> Result<&SpectralModel, Reason> { + self.models.get(d).ok_or(Reason::ModelUnheld) + } + + /// Resolve and verify a taste prior by its pin (§8.3). + pub fn taste(&self, pin: &Pin) -> Result { + read_taste(self.priors.get(&pin.sha256).ok_or(Reason::ObjectiveUnresolved)?) + } + + /// A picture's held samples, of its size; `None` when not held. + fn samples_of(&self, p: &Picture) -> Result>, Reason> { + match self.samples.get(&p.samples) { + None => Ok(None), + Some(b) if b.len() as u64 == p.width * p.height * 3 => Ok(Some(b)), + Some(_) => Err(Reason::SamplesMismatch), + } + } +} + +// --------------------------------------------------------------------------------------- +// §5 Archives +// --------------------------------------------------------------------------------------- + +/// What an archive is asked to explore (§5.1). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Request { + pub model: [u8; 32], + pub prompt: String, + pub modifiers: Vec, + pub width: u64, + pub height: u64, + pub steps: u64, + pub grid: Vec, + pub seed: u64, + pub trials: u64, + pub init: u64, + pub objective: Objective, +} + +/// One niche's elite (§5.3). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Elite { + pub niche: u64, + pub trial: u64, + pub genome: Genome, + pub samples: [u8; 32], + pub descriptors: Vector, + pub score: Option, +} + +impl Elite { + fn json(&self) -> Value { + json!({ + "niche": self.niche, + "trial": self.trial, + "seed": self.genome.seed, + "steps": self.genome.steps, + "mods": self.genome.mods, + "samples": hex(&self.samples), + "descriptors": self.descriptors, + "score": self.score, + }) + } +} + +/// The genome of trial `t` (§5.2), given the archive and the visits so far. +fn trial_genome(r: &Request, rng: &mut Rng, t: u64, archive: &BTreeMap, visits: &BTreeMap) -> Genome { + if t < r.init { + return Genome { seed: rng.next_u64() % (1 << 32), steps: r.steps, mods: 0 }; + } + // The parent: the less-visited of two occupied niches drawn at random, the first on a tie. + let occupied: Vec = archive.keys().copied().collect(); + let a = occupied[(rng.next_u64() % occupied.len() as u64) as usize]; + let b = occupied[(rng.next_u64() % occupied.len() as u64) as usize]; + let parent = archive[&if visits[&b] < visits[&a] { b } else { a }].genome; + // Each modifier flips with probability 1/M, the steps move by one to four, the seed renews. + let m = r.modifiers.len() as u64; + let mut mods = parent.mods; + for i in 0..m { + if rng.next_u64() % m == 0 { + mods ^= 1 << i; + } + } + let d = rng.next_u64() % 8; + let delta = if d < 4 { d as i64 - 4 } else { d as i64 - 3 }; + let steps = (parent.steps as i64 + delta).clamp(1, MAX_STEPS as i64) as u64; + Genome { seed: rng.next_u64() % (1 << 32), steps, mods } +} + +/// Run the schedule (§5.2): every trial's genome, picture, descriptors and niche, and the +/// elites it leaves, in ascending niche order. `taste` is the objective's prior, resolved. +pub fn search(m: &SpectralModel, r: &Request, taste: Option<&Taste>) -> Vec { + search_trace(m, r, taste, |_, _| ()) +} + +/// [`search`], calling `seen` with each trial's genome and descriptors. +pub fn search_trace(m: &SpectralModel, r: &Request, taste: Option<&Taste>, mut seen: impl FnMut(Genome, &Vector)) -> Vec { + let mut rng = Rng(r.seed); + let mut archive: BTreeMap = BTreeMap::new(); + let mut visits: BTreeMap = BTreeMap::new(); + for t in 0..r.trials { + let g = trial_genome(r, &mut rng, t, &archive, &visits); + let rgb = render(m, &r.prompt, &r.modifiers, g, r.width, r.height); + let d = descriptors(&rgb, r.width as usize, r.height as usize); + seen(g, &d); + let k = niche(&r.grid, &d); + *visits.entry(k).or_insert(0) += 1; + let score = taste.map(|p| p.score(&d)); + let e = Elite { niche: k, trial: t, genome: g, samples: digest(&rgb), descriptors: d, score }; + match archive.get(&k) { + None => { + archive.insert(k, e); + } + Some(old) if score.is_some() && score > old.score => { + archive.insert(k, e); + } + Some(_) => {} + } + } + archive.into_values().collect() +} + +pub const ARCHIVE_MEMBERS: [&str; 17] = [ + "kind", "generator", "model", "prompt", "modifiers", "width", "height", "steps", "descriptors", "grid", "search", "objective", + "elites", "coverage", "issued_at", "signer_pubkey", "sig", +]; + +/// The body of an archive record (§5.3), unsigned. +pub fn archive_body(r: &Request, elites: &[Elite], issued_at: &str) -> Value { + json!({ + "kind": "wai-archive", + "generator": GENERATOR, + "model": format!("sha256:{}", hex(&r.model)), + "prompt": r.prompt, + "modifiers": r.modifiers, + "width": r.width, + "height": r.height, + "steps": r.steps, + "descriptors": DESCRIPTOR_SET, + "grid": r.grid.iter().map(Axis::json).collect::>(), + "search": {"schedule": SCHEDULE, "seed": r.seed, "trials": r.trials, "init": r.init}, + "objective": r.objective.json(), + "elites": elites.iter().map(Elite::json).collect::>(), + "coverage": {"occupied": elites.len(), "cells": cells(&r.grid)}, + "issued_at": issued_at, + }) +} + +/// An archive record that reads (§5.3). +#[derive(Clone, Debug)] +pub struct Archive { + pub link: [u8; 32], + pub request: Request, + pub elites: Vec, + pub occupied: u64, + pub cells: u64, +} + +fn read_archive(v: &Value) -> Option { + if v["generator"].as_str() != Some(GENERATOR) || v["descriptors"].as_str() != Some(DESCRIPTOR_SET) { + return None; + } + let model = read_model_digest(&v["model"])?; + let prompt = read_prompt(&v["prompt"])?; + let mods = v["modifiers"].as_array().filter(|a| a.len() <= MAX_MODIFIERS)?; + let modifiers: Vec = mods.iter().map(|m| m.as_str().filter(|s| modifier_ok(s)).map(String::from)).collect::>()?; + if derived_prompt(&prompt, &modifiers, (1 << modifiers.len()) - 1).len() > MAX_PROMPT { + return None; + } + let (width, height) = (int(&v["width"])?, int(&v["height"])?); + let steps = int_in(&v["steps"], 1, MAX_STEPS)?; + if !size_ok(width, height) { + return None; + } + let grid = read_grid(&v["grid"])?; + let s = exact(&v["search"], &["schedule", "seed", "trials", "init"])?; + if s["schedule"].as_str() != Some(SCHEDULE) { + return None; + } + let seed = int(&s["seed"])?; + let trials = int_in(&s["trials"], 1, MAX_TRIALS)?; + let init = int_in(&s["init"], 1, trials)?; + let objective = Objective::read(&v["objective"])?; + if matches!(objective, Objective::Model { .. }) { + return None; + } + let n_cells = cells(&grid); + let mut elites = Vec::new(); + let mut trials_seen = BTreeSet::new(); + for e in v["elites"].as_array()? { + let o = exact(e, &["niche", "trial", "seed", "steps", "mods", "samples", "descriptors", "score"])?; + let niche = int_in(&o["niche"], 0, n_cells - 1)?; + let trial = int_in(&o["trial"], 0, trials - 1)?; + let genome = Genome { + seed: int_in(&o["seed"], 0, MAX_SEED)?, + steps: int_in(&o["steps"], 1, MAX_STEPS)?, + mods: int_in(&o["mods"], 0, (1 << modifiers.len()) - 1)?, + }; + let score = nullable(&o["score"], int)?; + if score.is_some() != matches!(objective, Objective::Taste(_)) || !trials_seen.insert(trial) { + return None; + } + if elites.last().is_some_and(|l: &Elite| l.niche >= niche) { + return None; + } + elites.push(Elite { niche, trial, genome, samples: hexn(&o["samples"])?, descriptors: read_vector(&o["descriptors"])?, score }); + } + if elites.is_empty() || elites.len() as u64 > trials { + return None; + } + let c = exact(&v["coverage"], &["occupied", "cells"])?; + let request = Request { model, prompt, modifiers, width, height, steps, grid, seed, trials, init, objective }; + Some(Archive { link: [0; 32], request, elites, occupied: int(&c["occupied"])?, cells: int(&c["cells"])? }) +} + +// --------------------------------------------------------------------------------------- +// §6 Default-distance +// --------------------------------------------------------------------------------------- + +/// The default set of a prompt at a size (§6.1): seeds 0 to 15 at four steps. +pub fn default_set(m: &SpectralModel, prompt: &str, w: u64, h: u64) -> Vec> { + (0..DEFAULT_SEEDS).map(|k| generate(m, prompt, k, DEFAULT_STEPS as usize, h as usize, w as usize)).collect() +} + +/// The lowest index of a minimum, and the minimum. +fn nearest(xs: impl IntoIterator) -> Option<(u64, u64)> { + let mut best: Option<(u64, u64)> = None; + for (i, x) in xs.into_iter().enumerate() { + if best.is_none_or(|(_, b)| x < b) { + best = Some((i as u64, x)); + } + } + best +} + +pub const DISTANCE_MEMBERS: [&str; 15] = [ + "kind", "work", "generator", "model", "prompt", "descriptors", "defaults", "class", "descriptor_distance", "nearest_descriptor", + "sample_distance", "nearest_sample", "issued_at", "signer_pubkey", "sig", +]; +pub const CLASSES: [&str; 3] = ["measured", "estimate", "unknown"]; + +/// The figures a distance states or a verifier computes (§6.2). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Figures { + pub descriptor_distance: Option, + pub nearest_descriptor: Option, + pub sample_distance: Option, + pub nearest_sample: Option, +} + +/// The figures of a work against the default set, both computed (§6.2). +pub fn measure_distance(work: &[u8], work_d: &Vector, defaults: &[Vec], defaults_d: &[Vector]) -> Figures { + let (nd, dd) = nearest(defaults_d.iter().map(|d| distance(work_d, d))).expect("a default"); + let (ns, sd) = nearest(defaults.iter().map(|d| sample_distance(work, d))).expect("a default"); + Figures { descriptor_distance: Some(dd), nearest_descriptor: Some(nd), sample_distance: Some(sd), nearest_sample: Some(ns) } +} + +// --------------------------------------------------------------------------------------- +// §7 Collection statements +// --------------------------------------------------------------------------------------- + +/// The pairwise statistics of a collection (§7.2). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Spread { + pub pairs: u64, + pub sum: u64, + pub min: u64, + pub median: u64, + pub max: u64, + pub width: u64, + pub histogram: Vec, +} + +impl Spread { + pub fn of(vs: &[Vector], width: u64) -> Spread { + let mut ds = Vec::new(); + for i in 0..vs.len() { + for j in i + 1..vs.len() { + ds.push(distance(&vs[i], &vs[j])); + } + } + ds.sort_unstable(); + let mut histogram = vec![0u64; HISTOGRAM_BINS]; + for d in &ds { + histogram[((d / width) as usize).min(HISTOGRAM_BINS - 1)] += 1; + } + Spread { + pairs: ds.len() as u64, + sum: ds.iter().sum(), + min: ds[0], + median: ds[(ds.len() - 1) / 2], + max: *ds.last().expect("a pair"), + width, + histogram, + } + } + + fn json(&self) -> Value { + json!({"pairs": self.pairs, "sum": self.sum, "min": self.min, "median": self.median, "max": self.max, "width": self.width, "histogram": self.histogram}) + } + + fn read(v: &Value) -> Option { + let o = exact(v, &["pairs", "sum", "min", "median", "max", "width", "histogram"])?; + let h = o["histogram"].as_array().filter(|a| a.len() == HISTOGRAM_BINS)?; + Some(Spread { + pairs: int(&o["pairs"])?, + sum: int(&o["sum"])?, + min: int(&o["min"])?, + median: int(&o["median"])?, + max: int(&o["max"])?, + width: int_in(&o["width"], 1, MAX_DISTANCE)?, + histogram: h.iter().map(int).collect::>()?, + }) + } +} + +/// The occupied cells of a grid (§7.2). +pub fn coverage(grid: &[Axis], vs: &[Vector]) -> u64 { + vs.iter().map(|d| niche(grid, d)).collect::>().len() as u64 +} + +pub const COLLECTION_MEMBERS: [&str; 11] = + ["kind", "scope", "subject", "descriptors", "grid", "members", "coverage", "distances", "issued_at", "signer_pubkey", "sig"]; +pub const COLLECTION_SCOPES: [&str; 4] = ["gallery", "room", "session", "archive"]; + +// --------------------------------------------------------------------------------------- +// §9 Rankings +// --------------------------------------------------------------------------------------- + +/// The order of scored candidates (§9.2): score descending, index ascending on ties. +pub fn rank(scores: &[u64]) -> Vec { + let mut idx: Vec = (0..scores.len() as u64).collect(); + idx.sort_by(|a, b| scores[*b as usize].cmp(&scores[*a as usize]).then(a.cmp(b))); + idx +} + +pub const RANKING_MEMBERS: [&str; 10] = + ["kind", "prior", "descriptors", "candidates", "scores", "order", "usage", "issued_at", "signer_pubkey", "sig"]; + +/// One use of a prior (§9.1): ai-usage §6.1's `usage` entry. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Use { + pub vocabulary: Vocabulary, + pub term: Option, +} + +fn read_usage(v: &Value) -> Option> { + let a = v.as_array().filter(|a| a.len() <= 3)?; + let mut out: Vec = Vec::new(); + for e in a { + let o = exact(e, &["vocabulary", "term"])?; + let vocabulary = Vocabulary::from_label(o["vocabulary"].as_str()?)?; + let term = nullable(&o["term"], |t| t.as_str().map(String::from))?; + if let Some(t) = &term + && (t.is_empty() || t.len() > 255 || !vocabulary.has_term(t)) + { + return None; + } + if out.last().is_some_and(|l| l.vocabulary.label() >= vocabulary.label()) { + return None; + } + out.push(Use { vocabulary, term }); + } + Some(out) +} + +// --------------------------------------------------------------------------------------- +// §10 Picks +// --------------------------------------------------------------------------------------- + +pub const PICK_MEMBERS: [&str; 7] = ["kind", "act", "work", "from", "issued_at", "signer_pubkey", "sig"]; + +/// Where a pick came from (§10.2). +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum From { + Archive { archive: [u8; 32], niche: u64 }, + Set(Vec<[u8; 32]>), + Generation { generator: String, model: String, prompt: String, seed: Option, steps: Option }, +} + +fn read_from(v: &Value) -> Option { + match v.get("type")?.as_str()? { + "archive" => { + let o = exact(v, &["type", "archive", "niche"])?; + Some(From::Archive { archive: hexn(&o["archive"])?, niche: int_in(&o["niche"], 0, MAX_CELLS - 1)? }) + } + "set" => { + let o = exact(v, &["type", "set"])?; + let a = o["set"].as_array().filter(|a| (1..=MAX_MEMBERS).contains(&a.len()))?; + Some(From::Set(a.iter().map(hexn).collect::>()?)) + } + "generation" => { + let o = exact(v, &["type", "generator", "model", "prompt", "seed", "steps"])?; + let generator = term(&o["generator"])?; + let model = term(&o["model"])?; + let seed = nullable(&o["seed"], |s| int_in(s, 0, MAX_SEED))?; + let steps = nullable(&o["steps"], |s| int_in(s, 1, MAX_STEPS))?; + if generator == GENERATOR && read_model_digest(&o["model"]).is_none() { + return None; + } + Some(From::Generation { generator, model, prompt: read_prompt(&o["prompt"])?, seed, steps }) + } + _ => None, + } +} + +// --------------------------------------------------------------------------------------- +// §12 Verification +// --------------------------------------------------------------------------------------- + +/// A verifier's policy (§12.1). +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Policy { + /// Replay every archive's schedule, not only its elites (§5.4). + pub replay: bool, + /// Every pick must carry `objective` (§10.3). + pub require_objective: bool, +} + +/// A case: the records, in order, what the verifier holds and its policy (§12.1). +pub struct Case { + pub records: Vec, + pub held: Held, + pub policy: Policy, +} + +/// The outcome of a case (§12.3). +#[derive(Clone, Debug, PartialEq)] +pub enum Outcome { + Accept(Vec), + Refuse { record: usize, reason: Reason }, +} + +/// Verify a case: each record in order (§12.2). +pub fn verify(c: &Case) -> Outcome { + let mut archives: BTreeMap<[u8; 32], Archive> = BTreeMap::new(); + let mut statements = Vec::new(); + for (i, text) in c.records.iter().enumerate() { + let r = match kind_of(text).as_deref() { + Some("wai-archive") => verify_archive(text, c, &mut archives), + Some("wai-distance") => verify_distance(text, c), + Some("wai-collection") => verify_collection(text, c), + Some("wai-ranking") => verify_ranking(text, c), + Some("wai-pick") => verify_pick(text, c, &archives), + _ => Err(Reason::RecordMalformed), + }; + match r { + Ok(s) => statements.push(s), + Err(reason) => return Outcome::Refuse { record: i, reason }, + } + } + Outcome::Accept(statements) +} + +/// Resolve an objective that names a taste prior (§10.1): the prior, verified. +fn resolve(o: &Objective, held: &Held) -> Result, Reason> { + match o { + Objective::Taste(pin) => held.taste(pin).map(Some), + _ => Ok(None), + } +} + +fn verify_archive(text: &str, c: &Case, archives: &mut BTreeMap<[u8; 32], Archive>) -> Result { + let (v, signer, link) = read_record(text, "wai-archive", &ARCHIVE_MEMBERS, None)?; + let mut a = read_archive(&v).ok_or(Reason::RecordMalformed)?; + a.link = link; + check_signature(&v, &signer)?; + let r = &a.request; + if a.occupied != a.elites.len() as u64 || a.cells != cells(&r.grid) { + return Err(Reason::CoverageMismatch); + } + let taste = resolve(&r.objective, &c.held)?; + let m = c.held.model(&r.model)?; + for e in &a.elites { + let rgb = render(m, &r.prompt, &r.modifiers, e.genome, r.width, r.height); + if digest(&rgb) != e.samples { + return Err(Reason::GenerationMismatch); + } + let d = descriptors(&rgb, r.width as usize, r.height as usize); + if d != e.descriptors { + return Err(Reason::DescriptorMismatch); + } + if niche(&r.grid, &d) != e.niche { + return Err(Reason::NicheMismatch); + } + if e.score != taste.as_ref().map(|t| t.score(&d)) { + return Err(Reason::ScoreMismatch); + } + } + if c.policy.replay && search(m, r, taste.as_ref()) != a.elites { + return Err(Reason::ArchiveReplayMismatch); + } + let statement = json!({ + "kind": "wai-archive", + "link": hex(&link), + "level": if c.policy.replay { "replayed" } else { "elites" }, + "occupied": a.occupied, + "cells": a.cells, + "objective": r.objective.report(), + }); + archives.insert(link, a); + Ok(statement) +} + +fn verify_distance(text: &str, c: &Case) -> Result { + let bad = Reason::RecordMalformed; + let (v, signer, link) = read_record(text, "wai-distance", &DISTANCE_MEMBERS, None)?; + let work = read_picture(&v["work"], true).ok_or(bad)?; + let generator = term(&v["generator"]).ok_or(bad)?; + term(&v["model"]).ok_or(bad)?; + let prompt = read_prompt(&v["prompt"]).ok_or(bad)?; + if v["descriptors"].as_str() != Some(DESCRIPTOR_SET) { + return Err(bad); + } + let class = one_of(&v["class"], &CLASSES).ok_or(bad)?; + let ds = v["defaults"].as_array().filter(|a| a.len() as u64 <= DEFAULT_SEEDS).ok_or(bad)?; + let mut defaults = Vec::new(); + for d in ds { + let o = exact(d, &["samples", "descriptors"]).ok_or(bad)?; + defaults.push((nullable(&o["samples"], hexn::<32>).ok_or(bad)?, read_vector(&o["descriptors"]).ok_or(bad)?)); + } + let n = |k: &str| nullable(&v[k], int).ok_or(bad); + let stated = Figures { + descriptor_distance: n("descriptor_distance")?, + nearest_descriptor: n("nearest_descriptor")?, + sample_distance: n("sample_distance")?, + nearest_sample: n("nearest_sample")?, + }; + // §6.3: each class's shape. + let all = |f: &Figures| [f.descriptor_distance, f.nearest_descriptor, f.sample_distance, f.nearest_sample]; + let shape_ok = match class.as_str() { + "measured" => defaults.len() as u64 == DEFAULT_SEEDS && defaults.iter().all(|d| d.0.is_some()) && all(&stated).iter().all(Option::is_some), + "estimate" => { + !defaults.is_empty() + && stated.descriptor_distance.is_some() + && stated.nearest_descriptor.is_some() + && stated.sample_distance.is_none() + && stated.nearest_sample.is_none() + } + _ => defaults.is_empty() && all(&stated).iter().all(Option::is_none), + }; + if !shape_ok { + return Err(bad); + } + let model_digest = read_model_digest(&v["model"]); + if generator == GENERATOR && model_digest.is_none() { + return Err(bad); + } + check_signature(&v, &signer)?; + if (generator == GENERATOR) != (class == "measured") { + return Err(Reason::DistanceClassInvalid); + } + let held_work = c.held.samples_of(&work)?; + let mut figures = stated.clone(); + if class == "measured" { + let m = c.held.model(&model_digest.expect("checked"))?; + let set = default_set(m, &prompt, work.width, work.height); + let set_d: Vec = set.iter().map(|b| descriptors(b, work.width as usize, work.height as usize)).collect(); + for (k, (s, d)) in defaults.iter().enumerate() { + if *s != Some(digest(&set[k])) || *d != set_d[k] { + return Err(Reason::DefaultMismatch); + } + } + let w = held_work.ok_or(Reason::WorkUnheld)?; + let wd = descriptors(w, work.width as usize, work.height as usize); + if Some(wd) != work.descriptors { + return Err(Reason::DescriptorMismatch); + } + figures = measure_distance(w, &wd, &set, &set_d); + } else if class == "estimate" { + if let Some(w) = held_work + && Some(descriptors(w, work.width as usize, work.height as usize)) != work.descriptors + { + return Err(Reason::DescriptorMismatch); + } + let wd = work.descriptors.expect("read with descriptors"); + let (nd, dd) = nearest(defaults.iter().map(|d| distance(&wd, &d.1))).expect("a default"); + figures.descriptor_distance = Some(dd); + figures.nearest_descriptor = Some(nd); + } else if let Some(w) = held_work + && Some(descriptors(w, work.width as usize, work.height as usize)) != work.descriptors + { + return Err(Reason::DescriptorMismatch); + } + if figures != stated { + return Err(Reason::DistanceMismatch); + } + Ok(json!({ + "kind": "wai-distance", + "link": hex(&link), + "class": class, + "descriptor_distance": figures.descriptor_distance, + "nearest_descriptor": figures.nearest_descriptor, + "sample_distance": figures.sample_distance, + "nearest_sample": figures.nearest_sample, + })) +} + +fn verify_collection(text: &str, c: &Case) -> Result { + let bad = Reason::RecordMalformed; + let (v, signer, link) = read_record(text, "wai-collection", &COLLECTION_MEMBERS, None)?; + one_of(&v["scope"], &COLLECTION_SCOPES).ok_or(bad)?; + term(&v["subject"]).ok_or(bad)?; + if v["descriptors"].as_str() != Some(DESCRIPTOR_SET) { + return Err(bad); + } + let grid = read_grid(&v["grid"]).ok_or(bad)?; + let ms = v["members"].as_array().filter(|a| (2..=MAX_MEMBERS).contains(&a.len())).ok_or(bad)?; + let members: Vec = ms.iter().map(|m| read_picture(m, true)).collect::>().ok_or(bad)?; + let cov = exact(&v["coverage"], &["occupied", "cells"]).ok_or(bad)?; + let (occupied, n_cells) = (int(&cov["occupied"]).ok_or(bad)?, int(&cov["cells"]).ok_or(bad)?); + let stated = Spread::read(&v["distances"]).ok_or(bad)?; + check_signature(&v, &signer)?; + let mut vs = Vec::new(); + for p in &members { + let b = c.held.samples_of(p)?.ok_or(Reason::MemberUnheld)?; + let d = descriptors(b, p.width as usize, p.height as usize); + if Some(d) != p.descriptors { + return Err(Reason::DescriptorMismatch); + } + vs.push(d); + } + if occupied != coverage(&grid, &vs) || n_cells != cells(&grid) { + return Err(Reason::CoverageMismatch); + } + let spread = Spread::of(&vs, stated.width); + if spread != stated { + return Err(Reason::DistancesMismatch); + } + Ok(json!({ + "kind": "wai-collection", + "link": hex(&link), + "members": members.len(), + "occupied": occupied, + "cells": n_cells, + "distances": spread.json(), + })) +} + +fn verify_ranking(text: &str, c: &Case) -> Result { + let bad = Reason::RecordMalformed; + let (v, signer, link) = read_record(text, "wai-ranking", &RANKING_MEMBERS, None)?; + let pin = read_pin(&v["prior"]).ok_or(bad)?; + if v["descriptors"].as_str() != Some(DESCRIPTOR_SET) { + return Err(bad); + } + let cs = v["candidates"].as_array().filter(|a| (1..=MAX_MEMBERS).contains(&a.len())).ok_or(bad)?; + let candidates: Vec = cs.iter().map(|m| read_picture(m, true)).collect::>().ok_or(bad)?; + let scores: Vec = v["scores"].as_array().filter(|a| a.len() == candidates.len()).ok_or(bad)?.iter().map(int).collect::>().ok_or(bad)?; + let order: Vec = v["order"].as_array().filter(|a| a.len() == candidates.len()).ok_or(bad)?.iter().map(int).collect::>().ok_or(bad)?; + let mut sorted = order.clone(); + sorted.sort_unstable(); + if sorted != (0..candidates.len() as u64).collect::>() { + return Err(bad); + } + let usage = read_usage(&v["usage"]).ok_or(bad)?; + check_signature(&v, &signer)?; + let taste = c.held.taste(&pin)?; + let mut held_all = true; + let mut vs = Vec::new(); + for p in &candidates { + let d = p.descriptors.expect("read with descriptors"); + match c.held.samples_of(p)? { + Some(b) => { + if descriptors(b, p.width as usize, p.height as usize) != d { + return Err(Reason::DescriptorMismatch); + } + } + None => held_all = false, + } + vs.push(d); + } + let want: Vec = vs.iter().map(|d| taste.score(d)).collect(); + if want != scores || rank(&want) != order { + return Err(Reason::RankingMismatch); + } + let mut uses = Vec::new(); + if let Some(s) = &taste.usage { + for voc in s.vocabularies() { + if !usage.iter().any(|u| u.vocabulary == voc) { + return Err(Reason::PriorUsageUnanswered); + } + } + } + for u in &usage { + let p = match (&u.term, &taste.usage) { + (None, _) => "outside", + (Some(_), None) => "absent", + (Some(t), Some(s)) => match s.preference(u.vocabulary, t) { + None => "absent", + Some(Preference::Disallow) => return Err(Reason::PriorUsageDisallowed), + Some(p) => p.label(), + }, + }; + uses.push(json!({"vocabulary": u.vocabulary.label(), "term": u.term, "preference": p})); + } + Ok(json!({ + "kind": "wai-ranking", + "link": hex(&link), + "prior": hex(&pin.sha256), + "owner": hex(&taste.owner), + "scope": taste.scope, + "order": order, + "descriptors": if held_all { "recomputed" } else { "stated" }, + "usage": uses, + })) +} + +fn verify_pick(text: &str, c: &Case, archives: &BTreeMap<[u8; 32], Archive>) -> Result { + let bad = Reason::RecordMalformed; + let (v, signer, link) = read_record(text, "wai-pick", &PICK_MEMBERS, Some("objective"))?; + let act = one_of(&v["act"], &["generate", "select"]).ok_or(bad)?; + let work = read_picture(&v["work"], false).ok_or(bad)?; + let from = read_from(&v["from"]).ok_or(bad)?; + if (act == "generate") != matches!(from, From::Generation { .. }) { + return Err(bad); + } + let objective = match v.get("objective") { + None => None, + Some(o) => Some(Objective::read(o).ok_or(bad)?), + }; + check_signature(&v, &signer)?; + if objective.is_none() && c.policy.require_objective { + return Err(Reason::ObjectiveUndisclosed); + } + if let Some(o) = &objective { + resolve(o, &c.held)?; + } + // Held samples of the work must be of its size; unheld, the checks below name it by digest. + c.held.samples_of(&work)?; + let (check, genome) = match &from { + From::Archive { archive, niche } => { + let a = archives.get(archive).ok_or(Reason::ArchiveUnheld)?; + let e = a.elites.iter().find(|e| e.niche == *niche).ok_or(Reason::PickNotInArchive)?; + if e.samples != work.samples || a.request.width != work.width || a.request.height != work.height { + return Err(Reason::PickNotInArchive); + } + if let Objective::Taste(p) = &a.request.objective + && objective.as_ref().and_then(Objective::digest) != Some(p.sha256) + { + return Err(Reason::ObjectiveMismatch); + } + let r = &a.request; + let g = json!({ + "seed": e.genome.seed, + "steps": e.genome.steps, + "mods": e.genome.mods, + "prompt": derived_prompt(&r.prompt, &r.modifiers, e.genome.mods), + }); + ("in-archive", g) + } + From::Set(set) => { + if !set.contains(&work.samples) { + return Err(Reason::PickNotInSet); + } + ("in-set", Value::Null) + } + From::Generation { generator, model, prompt, seed, steps } => match (generator.as_str(), seed, steps) { + (GENERATOR, Some(seed), Some(steps)) => { + let d = read_model_digest(&json!(model)).expect("read"); + let m = c.held.model(&d)?; + let rgb = generate(m, prompt, *seed, *steps as usize, work.height as usize, work.width as usize); + if digest(&rgb) != work.samples { + return Err(Reason::GenerationMismatch); + } + ("regenerated", json!({"seed": seed, "steps": steps, "mods": 0, "prompt": prompt})) + } + _ => ("stated", Value::Null), + }, + }; + Ok(json!({ + "kind": "wai-pick", + "link": hex(&link), + "act": act, + "objective": objective.as_ref().map_or(json!("undisclosed"), Objective::report), + "check": check, + "genome": genome, + })) +} + +// --------------------------------------------------------------------------------------- +// Measurement (informative): the archive against plain seed sampling at equal compute +// --------------------------------------------------------------------------------------- + +/// What one way of spending `trials` generations covers (§14.3 of the PR's measurement, not +/// a conformance rule): the cells its outputs occupy, and the spread of one representative +/// per occupied cell (the first output that reached it). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Reach { + pub occupied: u64, + pub spread: Option, +} + +fn reach(grid: &[Axis], outputs: &[Vector]) -> Reach { + let mut first: BTreeMap = BTreeMap::new(); + for d in outputs { + first.entry(niche(grid, d)).or_insert(*d); + } + let reps: Vec = first.into_values().collect(); + Reach { occupied: reps.len() as u64, spread: (reps.len() >= 2).then(|| Spread::of(&reps, 384)) } +} + +/// Plain seed sampling: seeds `0..trials` at the request's steps, its prompt as written. +pub fn reach_seeds(m: &SpectralModel, r: &Request) -> Reach { + let outs: Vec = (0..r.trials) + .map(|s| { + let rgb = render(m, &r.prompt, &r.modifiers, Genome { seed: s, steps: r.steps, mods: 0 }, r.width, r.height); + descriptors(&rgb, r.width as usize, r.height as usize) + }) + .collect(); + reach(&r.grid, &outs) +} + +/// Uniform sampling of the archive's genome space (seed, steps 1 to 16, any modifier mask) from +/// the request's search seed. +pub fn reach_random(m: &SpectralModel, r: &Request) -> Reach { + let mut rng = Rng(r.seed ^ 0x5EED); + let outs: Vec = (0..r.trials) + .map(|_| { + let g = Genome { seed: rng.next_u64() % (1 << 32), steps: 1 + rng.next_u64() % 16, mods: rng.next_u64() % (1 << r.modifiers.len()) }; + let rgb = render(m, &r.prompt, &r.modifiers, g, r.width, r.height); + descriptors(&rgb, r.width as usize, r.height as usize) + }) + .collect(); + reach(&r.grid, &outs) +} + +/// The archive's own schedule. +pub fn reach_archive(m: &SpectralModel, r: &Request) -> Reach { + let mut outs = Vec::new(); + search_trace(m, r, None, |_, d| outs.push(*d)); + reach(&r.grid, &outs) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn model() -> SpectralModel { + let p = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/vectors/generate/generate_spectral_model.json"); + SpectralModel::from_value(&serde_json::from_slice(&std::fs::read(p).unwrap()).unwrap()) + } + + #[test] + fn descriptors_of_flat_pictures() { + // A 1 × 1 picture has no neighbour pair: detail 0; its centroid is the frame's centre. + assert_eq!(descriptors(&[0, 0, 0], 1, 1), [0, 0, 0, 0, 512, 512]); + assert_eq!(descriptors(&[255, 255, 255], 1, 1), [1024, 0, 0, 0, 512, 512]); + // Pure red: luma (77·255 + 128) >> 8 = 77; chroma full. + let red: Vec = [255u8, 0, 0].repeat(4); + let d = descriptors(&red, 2, 2); + assert_eq!(d[0], 1024 * 77 / 255); + assert_eq!(d[1], 1024); + assert_eq!(d[3], 0, "one colour: no palette diversity"); + } + + #[test] + fn detail_and_palette_of_a_checkerboard() { + let mut b = Vec::new(); + for i in 0..16 { + let v = if (i % 4 + i / 4) % 2 == 0 { 0 } else { 255 }; + b.extend_from_slice(&[v, v, v]); + } + let d = descriptors(&b, 4, 4); + assert_eq!(d[2], 1024, "every neighbour pair steps 255 levels: detail saturates"); + assert_eq!(d[3], 512, "two colours, equally often: Gini–Simpson 1/2"); + } + + #[test] + fn centroid_follows_the_light() { + // Bright top row, dark bottom row: the centroid sits above the centre. + let mut b = [255u8, 255, 255].repeat(4); + b.extend([0u8, 0, 0].repeat(4)); + let d = descriptors(&b, 4, 2); + assert!(d[5] < 512 && d[4] == 512, "{d:?}"); + } + + #[test] + fn sample_distance_is_zero_only_when_equal() { + assert_eq!(sample_distance(&[1, 2, 3], &[1, 2, 3]), 0); + assert_eq!(sample_distance(&[1, 2, 3], &[1, 2, 4]), 2, "⌈1024·1/765⌉"); + assert_eq!(sample_distance(&[0; 3], &[255; 3]), 1024); + } + + #[test] + fn grid_bins_clamp_at_both_ends() { + let a = Axis { descriptor: 0, lo: 100, hi: 900, bins: 8 }; + assert_eq!((a.bin(0), a.bin(99), a.bin(100), a.bin(199), a.bin(200), a.bin(899), a.bin(900), a.bin(1024)), (0, 0, 0, 0, 1, 7, 7, 7)); + let g = [a.clone(), Axis { descriptor: 1, lo: 0, hi: 1024, bins: 4 }]; + assert_eq!(niche(&g, &[200, 1023, 0, 0, 0, 0]), 4 + 3); + assert_eq!(cells(&g), 32); + } + + #[test] + fn taste_terms_score_in_integers() { + let t = Taste { + digest: [0; 32], + owner: [0; 32], + scope: "personal".into(), + terms: vec![ + TasteTerm { descriptor: 0, shape: Shape::Rise, at: 0, weight: 2 }, + TasteTerm { descriptor: 1, shape: Shape::Fall, at: 0, weight: 3 }, + TasteTerm { descriptor: 2, shape: Shape::Near, at: 300, weight: 5 }, + TasteTerm { descriptor: 3, shape: Shape::Far, at: 500, weight: 7 }, + ], + usage: None, + }; + let d = [10, 20, 330, 400, 0, 0]; + assert_eq!(t.score(&d), 2 * 10 + 3 * (1024 - 20) + 5 * (1024 - 30) + 7 * 100); + assert_eq!(rank(&[5, 9, 5, 1]), vec![1, 0, 2, 3], "ties keep the lower index first"); + } + + #[test] + fn derived_prompts_append_in_modifier_order() { + let mods: Vec = ["dark", "spiral", "calm"].map(String::from).to_vec(); + assert_eq!(derived_prompt("a rose", &mods, 0), "a rose"); + assert_eq!(derived_prompt("a rose", &mods, 0b101), "a rose dark calm"); + } + + #[test] + fn the_search_replays_and_keeps_the_first_comer_without_an_objective() { + let m = model(); + let r = Request { + model: [0; 32], + prompt: "a quiet forest at night".into(), + modifiers: vec!["bright".into(), "spiral".into()], + width: 16, + height: 16, + steps: 4, + grid: vec![Axis { descriptor: 0, lo: 128, hi: 896, bins: 4 }, Axis { descriptor: 1, lo: 128, hi: 896, bins: 4 }], + seed: 7, + trials: 24, + init: 6, + objective: Objective::None, + }; + let a = search(&m, &r, None); + assert_eq!(a, search(&m, &r, None), "the schedule is a function of the request"); + assert!(a.windows(2).all(|w| w[0].niche < w[1].niche)); + // Without an objective each elite is the first trial that reached its niche. + let mut first: BTreeMap = BTreeMap::new(); + let mut t = 0; + search_trace(&m, &r, None, |_, d| { + first.entry(niche(&r.grid, d)).or_insert(t); + t += 1; + }); + assert_eq!(a.iter().map(|e| (e.niche, e.trial)).collect::>(), first.into_iter().collect::>()); + // Each elite regenerates from its genome. + for e in &a { + assert_eq!(digest(&render(&m, &r.prompt, &r.modifiers, e.genome, 16, 16)), e.samples); + } + } +} diff --git a/wai/wai-rs/src/exploration/corpus.rs b/wai/wai-rs/src/exploration/corpus.rs new file mode 100644 index 000000000..ee4899fdf --- /dev/null +++ b/wai/wai-rs/src/exploration/corpus.rs @@ -0,0 +1,1136 @@ +//! The conformance corpus of extensions/exploration.md §14: `live-conformance/exploration/`. +//! +//! [`generate`] writes it from fixed seeds: every key is SHA-256 of this corpus's label and an +//! index, every picture is made by `wai.generate.spectral` from the committed model file or +//! derived from one by a rule written here, every time is a constant, and Ed25519 signing is +//! deterministic (RFC 8032), so the file is the same bytes on every machine. The taste priors +//! are written here with hand-set weights; none is trained on anyone's choices. Each case states +//! the outcome it was written to have; the generator asserts that this module reaches it +//! before writing it, and that the corpus gives every reason of §13. +//! +//! [`verify`] checks a corpus directory's files against this module. +//! `live-conformance/exploration_verify.py` checks the same file from the extension's text, +//! sharing no code with this module. + +use super::*; + +/// The committed model file of `wai.generate.spectral`, which the corpus names by path. +const MODEL: &[u8] = include_bytes!("../../tests/vectors/generate/generate_spectral_model.json"); +const MODEL_PATH: &str = "wai-rs/tests/vectors/generate/generate_spectral_model.json"; +const ISSUED: &str = "2026-10-21T09:00:00Z"; +const DETERMINISM: &str = "wai-exploration taste score: unsigned integer arithmetic, exact"; +const OTHER_GENERATOR: &str = "urn:example:generator:float-1"; +const OTHER_MODEL: &str = "urn:example:model:float-1"; + +const SERVICE: u8 = 0; +const ALICE: u8 = 1; +const COMMUNITY: u8 = 2; +const RANKER: u8 = 3; +const PICKER: u8 = 4; +const MALLORY: u8 = 5; +const BOB: u8 = 6; + +const W: u64 = 24; +const H: u64 = 24; + +fn key(i: u8) -> SigningKey { + SigningKey::from_bytes(&sha256(&[b"wai:exploration/corpus/key\x00", &[i]])) +} + +fn text(v: &Value) -> String { + jcs(v).expect("a record in the subset") +} + +fn model() -> SpectralModel { + SpectralModel::from_value(&serde_json::from_slice(MODEL).expect("the committed model")) +} + +fn model_digest() -> [u8; 32] { + digest(MODEL) +} + +fn model_name() -> String { + format!("sha256:{}", hex(&model_digest())) +} + +/// Re-sign a record after an edit, by `who`. +fn resign(mut v: Value, who: u8) -> Value { + v.as_object_mut().expect("a record").remove("sig"); + v.as_object_mut().expect("a record").remove("signer_pubkey"); + sign(v, &key(who)) +} + +/// Set the member at `path` (object members by name, array elements by index). +fn with(mut v: Value, path: &[&str], x: Value) -> Value { + let mut at = &mut v; + for p in &path[..path.len() - 1] { + at = match p.parse::() { + Ok(i) => &mut at[i], + Err(_) => &mut at[*p], + }; + } + let last = path[path.len() - 1]; + match last.parse::() { + Ok(i) => at[i] = x, + Err(_) => at[last] = x, + } + v +} + +// ---- where a held picture comes from ---- + +/// A held sample buffer, as the corpus writes it: a generation the verifier makes, or bytes. +#[derive(Clone, Debug)] +enum Source { + Gen { prompt: String, seed: u64, steps: u64, w: u64, h: u64 }, + Bytes(Vec), +} + +impl Source { + fn bytes(&self, m: &SpectralModel) -> Vec { + match self { + Source::Gen { prompt, seed, steps, w, h } => crate::generate::generate(m, prompt, *seed, *steps as usize, *h as usize, *w as usize), + Source::Bytes(b) => b.clone(), + } + } + + fn json(&self) -> Value { + match self { + Source::Gen { prompt, seed, steps, w, h } => { + json!({"generate": {"prompt": prompt, "seed": seed, "steps": steps, "width": w, "height": h}}) + } + Source::Bytes(b) => json!({"hex": hex(b)}), + } + } + + fn read(v: &Value) -> Option { + if let Some(g) = v.get("generate") { + return Some(Source::Gen { + prompt: g["prompt"].as_str()?.to_string(), + seed: g["seed"].as_u64()?, + steps: g["steps"].as_u64()?, + w: g["width"].as_u64()?, + h: g["height"].as_u64()?, + }); + } + Some(Source::Bytes(unhex(v["hex"].as_str()?)?)) + } +} + +fn gen_src(prompt: &str, seed: u64, steps: u64) -> Source { + Source::Gen { prompt: prompt.to_string(), seed, steps, w: W, h: H } +} + +// ---- the requests and the priors ---- + +fn axis(d: usize, lo: u64, hi: u64, bins: u64) -> Axis { + Axis { descriptor: d, lo, hi, bins } +} + +const FOREST: &str = "a quiet forest at night"; +const OCEAN: &str = "ocean spiral vortex at dusk"; + +fn request(objective: Objective) -> Request { + Request { + model: model_digest(), + prompt: FOREST.into(), + modifiers: vec!["bright".into(), "spiral".into(), "calm".into()], + width: W, + height: H, + steps: 4, + grid: vec![axis(0, 128, 896, 4), axis(1, 128, 896, 4)], + seed: 11, + trials: 40, + init: 8, + objective, + } +} + +fn taste_request(objective: Objective) -> Request { + Request { + model: model_digest(), + prompt: FOREST.into(), + modifiers: vec!["dark".into(), "mirror".into()], + width: W, + height: H, + steps: 4, + grid: vec![axis(2, 0, 512, 4), axis(3, 256, 1024, 4)], + seed: 12, + trials: 32, + init: 8, + objective, + } +} + +fn plain_request() -> Request { + Request { + model: model_digest(), + prompt: OCEAN.into(), + modifiers: vec![], + width: W, + height: H, + steps: 3, + grid: vec![axis(1, 250, 550, 3), axis(2, 140, 290, 3)], + seed: 13, + trials: 24, + init: 6, + objective: Objective::None, + } +} + +fn term_(d: usize, shape: Shape, at: u64, weight: u64) -> TasteTerm { + TasteTerm { descriptor: d, shape, at, weight } +} + +/// Alice's own taste: calm, mid-dark, colourful pictures. +fn personal_terms() -> Vec { + vec![term_(2, Shape::Fall, 0, 3), term_(0, Shape::Near, 400, 2), term_(1, Shape::Rise, 0, 1)] +} + +/// A community's: many colours, light centred vertically. +fn community_terms() -> Vec { + vec![term_(3, Shape::Rise, 0, 4), term_(5, Shape::Near, 512, 1)] +} + +/// Bob's: away from the middle of luma and chroma — what most priors would rank last. +fn anti_terms() -> Vec { + vec![term_(0, Shape::Far, 448, 5), term_(1, Shape::Far, 448, 5)] +} + +fn community_usage() -> Value { + json!({"aipref": {"revision": crate::ai_usage::AIPREF_REVISION, "value": "train-ai=n, ai-use=y"}}) +} + +struct Priors { + personal: Vec, + community: Vec, + anti: Vec, + not_owner: Vec, + not_canonical: Vec, +} + +fn priors() -> Priors { + let personal = taste_file(&key(ALICE), &key(ALICE), "personal", &personal_terms(), None, ISSUED); + let mut spaced = String::from_utf8(personal.clone()).expect("UTF-8").replacen(",\"", ", \"", 1).into_bytes(); + spaced.shrink_to_fit(); + Priors { + personal, + community: taste_file(&key(COMMUNITY), &key(COMMUNITY), "community", &community_terms(), Some(&community_usage()), ISSUED), + anti: taste_file(&key(BOB), &key(BOB), "personal", &anti_terms(), None, ISSUED), + not_owner: taste_file(&key(ALICE), &key(MALLORY), "personal", &personal_terms(), None, ISSUED), + not_canonical: spaced, + } +} + +fn pin(file: &[u8], id: &str) -> Pin { + Pin { id: id.into(), sha256: digest(file), determinism: DETERMINISM.into() } +} + +fn taste_of(file: &[u8]) -> Taste { + read_taste(file).expect("a prior the corpus signs as its owner") +} + +/// An archive record of a request, signed by the service, with the taste the objective names. +fn archive(m: &SpectralModel, r: &Request, taste: Option<&Taste>) -> (Value, Vec) { + let elites = search(m, r, taste); + (sign(archive_body(r, &elites, ISSUED), &key(SERVICE)), elites) +} + +fn elite_source(r: &Request, e: &Elite) -> Source { + Source::Gen { + prompt: derived_prompt(&r.prompt, &r.modifiers, e.genome.mods), + seed: e.genome.seed, + steps: e.genome.steps, + w: r.width, + h: r.height, + } +} + +fn elite_picture(r: &Request, e: &Elite, with_d: bool) -> Value { + let mut p = json!({"samples": hex(&e.samples), "width": r.width, "height": r.height}); + if with_d { + p["descriptors"] = json!(e.descriptors); + } + p +} + +// ---- the cases ---- + +#[derive(Clone, Debug)] +enum Intent { + Accept, + Refuse(usize, Reason), +} + +#[derive(Clone)] +struct Vector { + name: &'static str, + about: &'static str, + records: Vec, + model_held: bool, + priors: Vec>, + samples: Vec, + policy: Policy, + intent: Intent, +} + +const REPLAY: Policy = Policy { replay: true, require_objective: false }; +const ELITES: Policy = Policy { replay: false, require_objective: false }; +const DISCLOSE: Policy = Policy { replay: true, require_objective: true }; + +fn v(name: &'static str, about: &'static str, records: Vec, intent: Intent) -> Vector { + Vector { name, about, records, model_held: true, priors: vec![], samples: vec![], policy: REPLAY, intent } +} + +impl Vector { + fn priors(mut self, p: &[&Vec]) -> Self { + self.priors = p.iter().map(|b| (*b).clone()).collect(); + self + } + fn samples(mut self, s: Vec) -> Self { + self.samples = s; + self + } + fn policy(mut self, p: Policy) -> Self { + self.policy = p; + self + } + fn no_model(mut self) -> Self { + self.model_held = false; + self + } +} + +use Intent::{Accept, Refuse}; + +/// A distance record's body over a work, against the default set of `prompt` (§6), every +/// figure computed; signed by the service. +fn measured_distance(m: &SpectralModel, prompt: &str, work: &[u8]) -> Value { + let set = default_set(m, prompt, W, H); + let set_d: Vec = set.iter().map(|b| descriptors(b, W as usize, H as usize)).collect(); + let wd = descriptors(work, W as usize, H as usize); + let f = measure_distance(work, &wd, &set, &set_d); + sign( + json!({ + "kind": "wai-distance", + "work": {"samples": hex(&digest(work)), "width": W, "height": H, "descriptors": wd}, + "generator": GENERATOR, + "model": model_name(), + "prompt": prompt, + "descriptors": DESCRIPTOR_SET, + "defaults": set.iter().zip(&set_d).map(|(b, d)| json!({"samples": hex(&digest(b)), "descriptors": d})).collect::>(), + "class": "measured", + "descriptor_distance": f.descriptor_distance, + "nearest_descriptor": f.nearest_descriptor, + "sample_distance": f.sample_distance, + "nearest_sample": f.nearest_sample, + "issued_at": ISSUED, + }), + &key(SERVICE), + ) +} + +type Vector6 = super::Vector; + +fn collection(scope: &str, subject: &str, grid: &[Axis], members: &[(Vec, u64, u64)], width: u64) -> Value { + let vs: Vec = members.iter().map(|(b, w, h)| descriptors(b, *w as usize, *h as usize)).collect(); + let spread = Spread::of(&vs, width); + sign( + json!({ + "kind": "wai-collection", + "scope": scope, + "subject": subject, + "descriptors": DESCRIPTOR_SET, + "grid": grid.iter().map(Axis::json).collect::>(), + "members": members.iter().zip(&vs).map(|((b, w, h), d)| json!({"samples": hex(&digest(b)), "width": w, "height": h, "descriptors": d})).collect::>(), + "coverage": {"occupied": coverage(grid, &vs), "cells": cells(grid)}, + "distances": spread.json(), + "issued_at": ISSUED, + }), + &key(SERVICE), + ) +} + +fn ranking(prior: &[u8], id: &str, candidates: &[Value], usage: Value) -> Value { + let t = read_taste(prior).ok(); + let vs: Vec = candidates.iter().map(|c| read_vector(&c["descriptors"]).expect("a vector")).collect(); + let scores: Vec = vs.iter().map(|d| t.as_ref().map_or(0, |t| t.score(d))).collect(); + let p = pin(prior, id); + sign( + json!({ + "kind": "wai-ranking", + "prior": {"id": p.id, "sha256": hex(&p.sha256), "determinism": p.determinism}, + "descriptors": DESCRIPTOR_SET, + "candidates": candidates, + "scores": scores, + "order": rank(&scores), + "usage": usage, + "issued_at": ISSUED, + }), + &key(RANKER), + ) +} + +fn pick(act: &str, work: Value, from: Value, objective: Option) -> Value { + let mut body = json!({"kind": "wai-pick", "act": act, "work": work, "from": from, "issued_at": ISSUED}); + if let Some(o) = objective { + body["objective"] = o; + } + sign(body, &key(PICKER)) +} + +fn taste_objective(file: &[u8], id: &str) -> Value { + Objective::Taste(pin(file, id)).json() +} + +/// A picture edited after generation: the top-left 8 × 8 pixels inverted. +fn edited(b: &[u8]) -> Vec { + let mut out = b.to_vec(); + for y in 0..8 { + for x in 0..8 { + for c in 0..3 { + let i = ((y * W + x) * 3 + c) as usize; + out[i] = 255 - out[i]; + } + } + } + out +} + +fn vectors() -> Vec { + let m = model(); + let p = priors(); + let (personal, _community, anti) = (taste_of(&p.personal), taste_of(&p.community), taste_of(&p.anti)); + let not_owner_terms = Taste { digest: digest(&p.not_owner), owner: personal.owner, scope: "personal".into(), terms: personal_terms(), usage: None }; + + let r1 = request(Objective::None); + let (a1, e1) = archive(&m, &r1, None); + let r2 = taste_request(Objective::Taste(pin(&p.personal, "alice/calm"))); + let (a2, e2) = archive(&m, &r2, Some(&personal)); + let r3 = plain_request(); + let (a3, _) = archive(&m, &r3, None); + let r4 = taste_request(Objective::Taste(pin(&p.anti, "bob/far"))); + let (a4, _) = archive(&m, &r4, Some(&anti)); + let r5 = taste_request(Objective::Taste(pin(&p.not_owner, "alice/calm"))); + let (a5, _) = archive(&m, &r5, Some(¬_owner_terms)); + let a1_link = hex(&link_hash(&a1)); + let a2_link = hex(&link_hash(&a2)); + + let mut out = Vec::new(); + + // ---- archives ---- + out.push(v("archive-novelty", "an archive with no objective: the first trial to reach each niche keeps it; replayed", vec![a1.clone()], Accept)); + out.push( + v("archive-taste", "an archive whose placement Alice's taste prior decides, scores stated; replayed", vec![a2.clone()], Accept) + .priors(&[&p.personal]), + ); + out.push(v("archive-no-modifiers", "an archive with no modifiers: the search varies seeds and steps only; replayed", vec![a3.clone()], Accept)); + out.push( + v("archive-anti-taste", "the taste archive's request under Bob's prior, which favours the extremes: other elites", vec![a4.clone()], Accept) + .priors(&[&p.anti]), + ); + out.push(v("archive-elites-checked", "the novelty archive under a policy that checks its elites and does not replay", vec![a1.clone()], Accept).policy(ELITES)); + let bumped = e1[1].descriptors[2] + 1; + out.push(v( + "archive-descriptor-not-recomputed", + "an elite whose detail is stated one higher than its picture's", + vec![resign(with(a1.clone(), &["elites", "1", "descriptors", "2"], json!(bumped)), SERVICE)], + Refuse(0, Reason::DescriptorMismatch), + )); + out.push(v( + "archive-seed-not-regenerating", + "an elite whose seed does not regenerate the picture it names", + vec![resign(with(a1.clone(), &["elites", "0", "seed"], json!(e1[0].genome.seed ^ 1)), SERVICE)], + Refuse(0, Reason::GenerationMismatch), + )); + let gap = (0..e1.len()).find(|&i| e1[i].niche + 1 < e1.get(i + 1).map_or(cells(&r1.grid), |n| n.niche)).expect("a free niche after an elite"); + out.push(v( + "archive-niche-wrong", + "an elite placed in the next niche, which its descriptors do not fall in", + vec![resign(with(a1.clone(), &["elites", &gap.to_string(), "niche"], json!(e1[gap].niche + 1)), SERVICE)], + Refuse(0, Reason::NicheMismatch), + )); + out.push( + v( + "archive-score-wrong", + "an elite of the taste archive whose score is stated one higher", + vec![resign(with(a2.clone(), &["elites", "0", "score"], json!(e2[0].score.expect("scored") + 1)), SERVICE)], + Refuse(0, Reason::ScoreMismatch), + ) + .priors(&[&p.personal]), + ); + out.push(v( + "archive-coverage-wrong", + "an archive that states one more occupied niche than it lists", + vec![resign(with(a1.clone(), &["coverage", "occupied"], json!(e1.len() + 1)), SERVICE)], + Refuse(0, Reason::CoverageMismatch), + )); + let mut dropped = a1.clone(); + dropped["elites"].as_array_mut().expect("elites").pop(); + dropped["coverage"]["occupied"] = json!(e1.len() - 1); + let dropped = resign(dropped, SERVICE); + out.push(v( + "archive-elite-dropped", + "the novelty archive without its last elite: every elite checks, and replay finds the one left out", + vec![dropped.clone()], + Refuse(0, Reason::ArchiveReplayMismatch), + )); + out.push(v("archive-elite-dropped-unreplayed", "the same archive, elite-checked only: accepted, and reported as not replayed", vec![dropped], Accept).policy(ELITES)); + out.push(v("archive-model-unheld", "an archive whose model file the verifier does not hold", vec![a1.clone()], Refuse(0, Reason::ModelUnheld)).no_model()); + out.push(v("archive-prior-unresolved", "a taste archive whose prior the verifier does not hold", vec![a2.clone()], Refuse(0, Reason::ObjectiveUnresolved))); + out.push( + v("archive-prior-not-owner", "a taste archive whose prior names Alice as owner and is signed by another key", vec![a5], Refuse(0, Reason::TasteNotOwner)) + .priors(&[&p.not_owner]), + ); + let mut bad_sig = a1.clone(); + let sig = bad_sig["sig"].as_str().expect("sig").to_string(); + bad_sig["sig"] = json!(format!("{}{}", if sig.starts_with('0') { "1" } else { "0" }, &sig[1..])); + out.push(v("archive-bad-signature", "an archive whose signature does not verify", vec![bad_sig], Refuse(0, Reason::BadSignature))); + let mut bad_key = a1.clone(); + bad_key["signer_pubkey"] = json!(format!("01{}", "00".repeat(31))); + out.push(v("archive-bad-key", "an archive signed under the identity point, a key of small order", vec![bad_key], Refuse(0, Reason::BadKey))); + out.push(v( + "archive-grid-empty-axis", + "an archive whose axis has lo equal to hi", + vec![resign(with(a1.clone(), &["grid", "0", "hi"], json!(128)), SERVICE)], + Refuse(0, Reason::RecordMalformed), + )); + out.push(v( + "archive-model-objective", + "an archive whose placement a model the verifier cannot run decides: it could not be replayed", + vec![resign(with(a1.clone(), &["objective"], json!({"type": "model", "sha256": hex(&[7; 32]), "id": "urn:example:aesthetic-model"})), SERVICE)], + Refuse(0, Reason::RecordMalformed), + )); + + // ---- distances ---- + let pulled = gen_src(&format!("{FOREST} dark"), 9001, 9); + let pulled_b = pulled.bytes(&m); + let default3 = gen_src(FOREST, 3, 4); + let default3_b = default3.bytes(&m); + let edited_b = edited(&default3_b); + let edited_s = Source::Bytes(edited_b.clone()); + let d_pulled = measured_distance(&m, FOREST, &pulled_b); + out.push( + v("distance-measured-pulled", "a work made with another word, more steps and another seed: measured from the sixteen defaults", vec![d_pulled.clone()], Accept) + .samples(vec![pulled.clone()]), + ); + out.push( + v("distance-measured-default", "a work that is default seed 3 itself: sample distance 0, nearest 3", vec![measured_distance(&m, FOREST, &default3_b)], Accept) + .samples(vec![default3.clone()]), + ); + out.push( + v("distance-measured-edited", "default seed 3 with a corner inverted afterwards: near it, and not it", vec![measured_distance(&m, FOREST, &edited_b)], Accept) + .samples(vec![edited_s.clone()]), + ); + let wd = descriptors(&pulled_b, W as usize, H as usize); + let stated: Vec = vec![[300, 420, 90, 700, 512, 500], [360, 380, 120, 760, 505, 520], [280, 500, 60, 640, 515, 480], [410, 350, 140, 800, 500, 510]]; + let (nd, dd) = nearest(stated.iter().map(|s| distance(&wd, s))).expect("defaults"); + let estimate = sign( + json!({ + "kind": "wai-distance", + "work": {"samples": hex(&digest(&pulled_b)), "width": W, "height": H, "descriptors": wd}, + "generator": OTHER_GENERATOR, + "model": OTHER_MODEL, + "prompt": FOREST, + "descriptors": DESCRIPTOR_SET, + "defaults": stated.iter().map(|d| json!({"samples": null, "descriptors": d})).collect::>(), + "class": "estimate", + "descriptor_distance": dd, + "nearest_descriptor": nd, + "sample_distance": null, + "nearest_sample": null, + "issued_at": ISSUED, + }), + &key(SERVICE), + ); + out.push( + v("distance-estimate", "a generator that is not exact: its defaults are stated, and the figure is an estimate", vec![estimate.clone()], Accept) + .samples(vec![pulled.clone()]), + ); + let unknown = resign( + with( + with( + with(with(with(with(estimate.clone(), &["class"], json!("unknown")), &["defaults"], json!([])), &["descriptor_distance"], Value::Null), &["nearest_descriptor"], Value::Null), + &["sample_distance"], + Value::Null, + ), + &["nearest_sample"], + Value::Null, + ), + SERVICE, + ); + out.push(v("distance-unknown", "no default set is known: every figure is null, reported unknown", vec![unknown.clone()], Accept)); + out.push(v( + "distance-unknown-as-zero", + "an unknown figure written as 0, which would state that the work is a default", + vec![resign(with(unknown, &["descriptor_distance"], json!(0)), SERVICE)], + Refuse(0, Reason::RecordMalformed), + )); + let dd_pulled = d_pulled["descriptor_distance"].as_u64().expect("measured"); + out.push( + v( + "distance-stated-wrong", + "a measured descriptor distance stated one higher than the defaults give", + vec![resign(with(d_pulled.clone(), &["descriptor_distance"], json!(dd_pulled + 1)), SERVICE)], + Refuse(0, Reason::DistanceMismatch), + ) + .samples(vec![pulled.clone()]), + ); + let sd_pulled = d_pulled["sample_distance"].as_u64().expect("measured"); + out.push( + v( + "distance-sample-stated-wrong", + "a measured sample distance stated one lower", + vec![resign(with(d_pulled.clone(), &["sample_distance"], json!(sd_pulled - 1)), SERVICE)], + Refuse(0, Reason::DistanceMismatch), + ) + .samples(vec![pulled.clone()]), + ); + out.push( + v( + "distance-measured-not-exact", + "a measured figure over a generator that is not exact", + vec![resign(with(with(d_pulled.clone(), &["generator"], json!(OTHER_GENERATOR)), &["model"], json!(OTHER_MODEL)), SERVICE)], + Refuse(0, Reason::DistanceClassInvalid), + ) + .samples(vec![pulled.clone()]), + ); + out.push( + v( + "distance-estimate-for-exact", + "the exact generator's figure stated as an estimate", + vec![resign(with(with(estimate.clone(), &["generator"], json!(GENERATOR)), &["model"], json!(model_name())), SERVICE)], + Refuse(0, Reason::DistanceClassInvalid), + ) + .samples(vec![pulled.clone()]), + ); + out.push( + v( + "distance-default-wrong", + "a default whose samples digest is not what seed 5 makes", + vec![resign(with(d_pulled.clone(), &["defaults", "5", "samples"], json!(hex(&digest(&default3_b)))), SERVICE)], + Refuse(0, Reason::DefaultMismatch), + ) + .samples(vec![pulled.clone()]), + ); + out.push(v("distance-work-unheld", "a measured distance whose work the verifier does not hold", vec![d_pulled.clone()], Refuse(0, Reason::WorkUnheld))); + let mut wrong_d = wd; + wrong_d[0] += 1; + out.push( + v( + "distance-work-descriptors-wrong", + "a work whose luma is stated one higher than its samples give", + vec![resign(with(d_pulled.clone(), &["work", "descriptors"], json!(wrong_d)), SERVICE)], + Refuse(0, Reason::DescriptorMismatch), + ) + .samples(vec![pulled.clone()]), + ); + out.push( + v( + "distance-work-wrong-size", + "a work stated one row shorter than the samples its digest names", + vec![resign(with(d_pulled.clone(), &["work", "height"], json!(H - 1)), SERVICE)], + Refuse(0, Reason::SamplesMismatch), + ) + .samples(vec![pulled.clone()]), + ); + out.push( + v("distance-model-unheld", "a measured distance whose model file the verifier does not hold", vec![d_pulled.clone()], Refuse(0, Reason::ModelUnheld)) + .samples(vec![pulled.clone()]) + .no_model(), + ); + + // ---- collections ---- + let defaults: Vec = (0..DEFAULT_SEEDS).map(|k| gen_src(FOREST, k, DEFAULT_STEPS)).collect(); + let defaults_b: Vec<(Vec, u64, u64)> = defaults.iter().map(|s| (s.bytes(&m), W, H)).collect(); + let grid = vec![axis(0, 128, 896, 4), axis(1, 128, 896, 4)]; + let c_defaults = collection("gallery", "urn:example:gallery:defaults", &grid, &defaults_b, 64); + out.push(v("collection-defaults", "a gallery of the prompt's sixteen defaults: few cells, short distances", vec![c_defaults.clone()], Accept).samples(defaults.clone())); + let elites_src: Vec = e1.iter().map(|e| elite_source(&r1, e)).collect(); + let elites_b: Vec<(Vec, u64, u64)> = elites_src.iter().map(|s| (s.bytes(&m), W, H)).collect(); + let c_archive = collection("archive", &a1_link, &grid, &elites_b, 64); + out.push(v("collection-archive", "the novelty archive's elites as a collection: one per niche", vec![c_archive.clone()], Accept).samples(elites_src.clone())); + let occ = c_defaults["coverage"]["occupied"].as_u64().expect("occupied"); + out.push( + v( + "collection-coverage-wrong", + "the defaults' gallery stating one more occupied cell", + vec![resign(with(c_defaults.clone(), &["coverage", "occupied"], json!(occ + 1)), SERVICE)], + Refuse(0, Reason::CoverageMismatch), + ) + .samples(defaults.clone()), + ); + let med = c_defaults["distances"]["median"].as_u64().expect("median"); + out.push( + v( + "collection-median-wrong", + "the defaults' gallery stating its median one higher", + vec![resign(with(c_defaults.clone(), &["distances", "median"], json!(med + 1)), SERVICE)], + Refuse(0, Reason::DistancesMismatch), + ) + .samples(defaults.clone()), + ); + out.push( + v("collection-member-unheld", "a gallery one of whose members the verifier does not hold", vec![c_defaults.clone()], Refuse(0, Reason::MemberUnheld)) + .samples(defaults[1..].to_vec()), + ); + let d2 = c_defaults["members"][2]["descriptors"][1].as_u64().expect("chroma"); + out.push( + v( + "collection-member-descriptors-wrong", + "a member whose chroma is stated one lower than its samples give", + vec![resign(with(c_defaults.clone(), &["members", "2", "descriptors", "1"], json!(d2 - 1)), SERVICE)], + Refuse(0, Reason::DescriptorMismatch), + ) + .samples(defaults.clone()), + ); + + // ---- taste priors and rankings ---- + let cands: Vec = e1.iter().take(6).map(|e| elite_picture(&r1, e, true)).collect(); + let cand_src: Vec = elites_src.iter().take(6).cloned().collect(); + let aipref = |t: Value| json!([{"vocabulary": "aipref", "term": t}]); + out.push( + v("ranking-personal", "Alice's prior ranks six pictures; the prior carries no usage statement", vec![ranking(&p.personal, "alice/calm", &cands, json!([]))], Accept) + .priors(&[&p.personal]) + .samples(cand_src.clone()), + ); + out.push( + v( + "ranking-community", + "a community's prior ranks the same six; its statement allows ai-use, which the ranking names", + vec![ranking(&p.community, "community/many-colours", &cands, aipref(json!("ai-use")))], + Accept, + ) + .priors(&[&p.community]) + .samples(cand_src.clone()), + ); + out.push( + v("ranking-anti", "Bob's anti-aesthetic prior ranks the same six in another order", vec![ranking(&p.anti, "bob/far", &cands, json!([]))], Accept) + .priors(&[&p.anti]) + .samples(cand_src.clone()), + ); + out.push( + v("ranking-stated", "Alice's prior over stated vectors: the verifier holds no candidate's samples", vec![ranking(&p.personal, "alice/calm", &cands, json!([]))], Accept) + .priors(&[&p.personal]), + ); + out.push( + v( + "ranking-outside", + "the community prior, the use stated as outside every aipref category", + vec![ranking(&p.community, "community/many-colours", &cands, aipref(Value::Null))], + Accept, + ) + .priors(&[&p.community]) + .samples(cand_src.clone()), + ); + let r_personal = ranking(&p.personal, "alice/calm", &cands, json!([])); + let mut swapped = r_personal["order"].clone(); + let o = swapped.as_array_mut().expect("order"); + o.swap(0, 1); + out.push( + v( + "ranking-order-not-reproducing", + "a ranking whose first two places are swapped: it does not reproduce", + vec![resign(with(r_personal.clone(), &["order"], swapped), RANKER)], + Refuse(0, Reason::RankingMismatch), + ) + .priors(&[&p.personal]) + .samples(cand_src.clone()), + ); + let s0 = r_personal["scores"][0].as_u64().expect("score"); + out.push( + v( + "ranking-score-wrong", + "a ranking whose first score is stated one higher", + vec![resign(with(r_personal.clone(), &["scores", "0"], json!(s0 + 1)), RANKER)], + Refuse(0, Reason::RankingMismatch), + ) + .priors(&[&p.personal]) + .samples(cand_src.clone()), + ); + out.push( + v( + "ranking-prior-not-owner", + "a ranking under a prior that names Alice as owner and is signed by another key", + vec![ranking(&p.not_owner, "alice/calm", &cands, json!([]))], + Refuse(0, Reason::TasteNotOwner), + ) + .priors(&[&p.not_owner]) + .samples(cand_src.clone()), + ); + out.push(v("ranking-prior-unresolved", "a ranking under a prior the verifier does not hold", vec![r_personal.clone()], Refuse(0, Reason::ObjectiveUnresolved)).samples(cand_src.clone())); + out.push( + v( + "ranking-usage-unanswered", + "the community prior's statement carries aipref, and the ranking states no use in it", + vec![ranking(&p.community, "community/many-colours", &cands, json!([]))], + Refuse(0, Reason::PriorUsageUnanswered), + ) + .priors(&[&p.community]) + .samples(cand_src.clone()), + ); + out.push( + v( + "ranking-usage-disallowed", + "a ranking that states train-ai, which the community's statement disallows", + vec![ranking(&p.community, "community/many-colours", &cands, aipref(json!("train-ai")))], + Refuse(0, Reason::PriorUsageDisallowed), + ) + .priors(&[&p.community]) + .samples(cand_src.clone()), + ); + out.push( + v( + "ranking-prior-not-canonical", + "a prior file with a space the canonical form does not have: its digest names other bytes than the record's", + vec![ranking(&p.not_canonical, "alice/calm", &cands, json!([]))], + Refuse(0, Reason::RecordMalformed), + ) + .priors(&[&p.not_canonical]) + .samples(cand_src.clone()), + ); + let c0 = cands[0]["descriptors"][3].as_u64().expect("palette"); + let mut cands_wrong = cands.clone(); + cands_wrong[0]["descriptors"][3] = json!(c0 + 1); + out.push( + v( + "ranking-candidate-descriptors-wrong", + "a candidate whose palette is stated one higher than its samples give", + vec![ranking(&p.personal, "alice/calm", &cands_wrong, json!([]))], + Refuse(0, Reason::DescriptorMismatch), + ) + .priors(&[&p.personal]) + .samples(cand_src.clone()), + ); + + // ---- picks ---- + let from_archive = |link: &str, niche: u64| json!({"type": "archive", "archive": link, "niche": niche}); + let e1p = &e1[e1.len() / 2]; + let e2p = &e2[0]; + let personal_obj = taste_objective(&p.personal, "alice/calm"); + out.push(v( + "pick-from-archive", + "a person selects an elite of the novelty archive, which nothing steered; the pick inherits its genome", + vec![a1.clone(), pick("select", elite_picture(&r1, e1p, false), from_archive(&a1_link, e1p.niche), Some(json!("none")))], + Accept, + )); + out.push( + v( + "pick-from-steered-archive", + "a selection from the archive Alice's prior placed, naming that prior", + vec![a2.clone(), pick("select", elite_picture(&r2, e2p, false), from_archive(&a2_link, e2p.niche), Some(personal_obj.clone()))], + Accept, + ) + .priors(&[&p.personal]), + ); + let gen_from = json!({"type": "generation", "generator": GENERATOR, "model": model_name(), "prompt": format!("{FOREST} dark"), "seed": 9001, "steps": 9}); + let other_model = json!({"type": "model", "sha256": hex(&sha256(&[b"an aesthetic model's parameter set"])), "id": "urn:example:aesthetic-model"}); + let pulled_pic = json!({"samples": hex(&digest(&pulled_b)), "width": W, "height": H}); + out.push(v( + "pick-generation-steered-by-a-model", + "a generation a service chose with an aesthetic model it names by digest; the picture regenerates", + vec![pick("generate", pulled_pic.clone(), gen_from.clone(), Some(other_model.clone()))], + Accept, + )); + let set = json!({"type": "set", "set": defaults_b.iter().take(4).map(|(b, _, _)| hex(&digest(b))).collect::>()}); + let d2pic = json!({"samples": hex(&digest(&defaults_b[2].0)), "width": W, "height": H}); + out.push(v("pick-from-set", "a selection of one of four defaults, nothing steering it", vec![pick("select", d2pic.clone(), set.clone(), Some(json!("none")))], Accept)); + out.push( + v("pick-undisclosed", "a selection with no objective, under a policy that does not require one: reported undisclosed, not none", vec![pick("select", d2pic.clone(), set.clone(), None)], Accept) + .policy(REPLAY), + ); + let other_from = json!({"type": "generation", "generator": OTHER_GENERATOR, "model": OTHER_MODEL, "prompt": FOREST, "seed": null, "steps": null}); + out.push(v( + "pick-generation-other", + "a generation by a generator that is not exact: taken as stated", + vec![pick("generate", pulled_pic.clone(), other_from, Some(json!("none")))], + Accept, + )); + out.push( + v( + "pick-undisclosed-required", + "a selection with no objective, under a policy that requires one", + vec![pick("select", d2pic.clone(), set.clone(), None)], + Refuse(0, Reason::ObjectiveUndisclosed), + ) + .policy(DISCLOSE), + ); + out.push( + v( + "pick-steered-archive-says-none", + "a selection from the archive Alice's prior placed, stating that nothing steered it", + vec![a2.clone(), pick("select", elite_picture(&r2, e2p, false), from_archive(&a2_link, e2p.niche), Some(json!("none")))], + Refuse(1, Reason::ObjectiveMismatch), + ) + .priors(&[&p.personal]), + ); + out.push( + v( + "pick-steered-archive-undisclosed", + "the same selection with no objective, under a policy that does not require one: the archive shows it was steered", + vec![a2.clone(), pick("select", elite_picture(&r2, e2p, false), from_archive(&a2_link, e2p.niche), None)], + Refuse(1, Reason::ObjectiveMismatch), + ) + .priors(&[&p.personal]), + ); + let free = (0..cells(&r1.grid)).find(|k| !e1.iter().any(|e| e.niche == *k)).expect("an empty niche"); + out.push(v( + "pick-not-in-archive", + "a selection of a niche the archive left empty", + vec![a1.clone(), pick("select", elite_picture(&r1, e1p, false), from_archive(&a1_link, free), Some(json!("none")))], + Refuse(1, Reason::PickNotInArchive), + )); + let other = e1.iter().find(|e| e.niche != e1p.niche).expect("another elite"); + out.push(v( + "pick-wrong-elite", + "a selection naming one occupied niche whose work is another niche's elite", + vec![a1.clone(), pick("select", elite_picture(&r1, other, false), from_archive(&a1_link, e1p.niche), Some(json!("none")))], + Refuse(1, Reason::PickNotInArchive), + )); + out.push(v( + "pick-archive-unheld", + "a selection from an archive the case does not give", + vec![pick("select", elite_picture(&r1, e1p, false), from_archive(&a1_link, e1p.niche), Some(json!("none")))], + Refuse(0, Reason::ArchiveUnheld), + )); + let d5pic = json!({"samples": hex(&digest(&defaults_b[5].0)), "width": W, "height": H}); + out.push(v("pick-not-in-set", "a selection of a picture the set does not hold", vec![pick("select", d5pic, set.clone(), Some(json!("none")))], Refuse(0, Reason::PickNotInSet))); + out.push(v( + "pick-generation-mismatch", + "a generation whose seed does not regenerate the work", + vec![pick("generate", pulled_pic.clone(), with(gen_from.clone(), &["seed"], json!(9002)), Some(json!("none")))], + Refuse(0, Reason::GenerationMismatch), + )); + out.push(v( + "pick-objective-unresolved", + "a selection naming a taste prior the verifier does not hold", + vec![pick("select", d2pic.clone(), set.clone(), Some(personal_obj.clone()))], + Refuse(0, Reason::ObjectiveUnresolved), + )); + out.push(v( + "pick-act-mismatch", + "a generate whose source is a set", + vec![pick("generate", d2pic.clone(), set.clone(), Some(json!("none")))], + Refuse(0, Reason::RecordMalformed), + )); + out.push(v( + "record-kind-unknown", + "a record of a kind this extension does not define", + vec![sign(json!({"kind": "wai-other", "issued_at": ISSUED}), &key(SERVICE))], + Refuse(0, Reason::RecordMalformed), + )); + out +} + +// ---- the file ---- + +fn generations() -> Vec { + let m = model(); + let list: [(&str, u64, u64, u64, u64); 12] = [ + ("a calm spectral horizon", 7, 4, 17, 11), + ("ring target", 1, 2, 16, 12), + ("Mirror SYMMETRY", 2, 3, 13, 9), + ("sunburst, star; rays", 3, 1, 12, 12), + ("spiral vortex", 4, 5, 15, 10), + ("horizon over a sunset abyss", 5, 3, 11, 14), + ("tall vertical", 6, 2, 9, 9), + ("", 0, 1, 1, 1), + ("no lexicon words here", MAX_SEED, MAX_STEPS, 3, 2), + ("a quiet forest at night bright calm", 123_456, 7, 10, 6), + ("halo orb dawn", 99, 6, 20, 1), + ("night night night abyss", 42, 2, 1, 7), + ]; + list.iter() + .map(|(prompt, seed, steps, w, h)| { + let b = crate::generate::generate(&m, prompt, *seed, *steps as usize, *h as usize, *w as usize); + json!({"prompt": prompt, "seed": seed, "steps": steps, "width": w, "height": h, "sha256": hex(&digest(&b))}) + }) + .collect() +} + +fn descriptor_vectors() -> Vec { + let m = model(); + let mut checker = Vec::new(); + for i in 0..30u64 { + let v = if (i % 6 + i / 6) % 2 == 0 { 0u8 } else { 255 }; + checker.extend_from_slice(&[v, v / 2, 255 - v]); + } + let ramp: Vec = (0..7 * 5).flat_map(|i| [(i * 7) as u8, (255 - i * 7) as u8, ((i * 37) % 256) as u8]).collect(); + let cases: Vec<(&str, Source, u64, u64)> = vec![ + ("one black pixel", Source::Bytes(vec![0, 0, 0]), 1, 1), + ("one white pixel", Source::Bytes(vec![255, 255, 255]), 1, 1), + ("a single row", Source::Bytes(ramp[..15].to_vec()), 5, 1), + ("a single column", Source::Bytes(ramp[..21].to_vec()), 1, 7), + ("flat red", Source::Bytes([255u8, 0, 0].repeat(12)), 4, 3), + ("a checkerboard", Source::Bytes(checker), 6, 5), + ("a ramp", Source::Bytes(ramp), 7, 5), + ("a generated picture", gen_src(FOREST, 0, 4), W, H), + ("another generated picture", Source::Gen { prompt: "sunburst".into(), seed: 5, steps: 12, w: 31, h: 17 }, 31, 17), + ]; + cases + .into_iter() + .map(|(about, s, w, h)| { + let b = s.bytes(&m); + let mut o = s.json(); + o["about"] = json!(about); + o["width"] = json!(w); + o["height"] = json!(h); + o["descriptors"] = json!(descriptors(&b, w as usize, h as usize)); + o + }) + .collect() +} + +fn case_json(v: &Vector) -> Map { + let mut m = Map::new(); + m.insert( + "policy".into(), + json!({ + "replay": if v.policy.replay { "required" } else { "elites" }, + "objective": if v.policy.require_objective { "required" } else { "optional" }, + }), + ); + m.insert("records".into(), json!(v.records.iter().map(text).collect::>())); + m.insert( + "held".into(), + json!({ + "models": if v.model_held { vec![hex(&model_digest())] } else { vec![] }, + "priors": v.priors.iter().map(|b| String::from_utf8(b.clone()).expect("UTF-8")).collect::>(), + "samples": v.samples.iter().map(Source::json).collect::>(), + }), + ); + m +} + +fn outcome_json(o: &Outcome) -> Map { + let mut m = Map::new(); + match o { + Outcome::Refuse { record, reason } => { + m.insert("outcome".into(), json!("refuse")); + m.insert("reason".into(), json!(reason.code())); + m.insert("record".into(), json!(record)); + } + Outcome::Accept(s) => { + m.insert("outcome".into(), json!("accept")); + m.insert("statements".into(), json!(s)); + } + } + m +} + +struct CaseIn { + records: Vec, + model_held: bool, + priors: Vec, + samples: Vec, + policy: Policy, +} + +fn case_from_json(v: &Value) -> Option { + let strs = |x: &Value| -> Option> { x.as_array()?.iter().map(|s| s.as_str().map(String::from)).collect() }; + let models = strs(&v["held"]["models"])?; + Some(CaseIn { + records: strs(&v["records"])?, + model_held: models.contains(&hex(&model_digest())), + priors: strs(&v["held"]["priors"])?, + samples: v["held"]["samples"].as_array()?.iter().map(Source::read).collect::>()?, + policy: Policy { replay: v["policy"]["replay"] == "required", require_objective: v["policy"]["objective"] == "required" }, + }) +} + +fn run(c: &CaseIn, m: &SpectralModel) -> Outcome { + let mut held = Held::default(); + if c.model_held { + held.hold_model(MODEL); + } + for p in &c.priors { + held.hold_prior(p.as_bytes().to_vec()); + } + for s in &c.samples { + held.hold_samples(s.bytes(m)); + } + super::verify(&Case { records: c.records.clone(), held, policy: c.policy }) +} + +/// The corpus: `vectors.json`. +pub fn generate() -> Vec<(String, String)> { + let m = model(); + let mut seen = BTreeSet::new(); + let mut cases = Vec::new(); + for v in vectors() { + let mut c = case_json(&v); + let got = run(&case_from_json(&Value::Object(c.clone())).expect("a case reads"), &m); + match (&v.intent, &got) { + (Intent::Accept, Outcome::Accept(_)) => {} + (Intent::Refuse(i, r), Outcome::Refuse { record, reason }) if i == record && r == reason => { + seen.insert(*r); + } + _ => panic!("vector {} does not reach the outcome it was written to have: {got:?}", v.name), + } + let mut o = Map::new(); + o.insert("name".into(), json!(v.name)); + o.insert("about".into(), json!(v.about)); + o.append(&mut c); + o.extend(outcome_json(&got)); + cases.push(Value::Object(o)); + } + for r in Reason::ALL { + assert!(seen.contains(&r), "no vector of the corpus is refused with {r}"); + } + let doc = json!({ + "about": "the conformance corpus of extensions/exploration.md §14, written by wai_exploration_vectors gen", + "model": {"path": MODEL_PATH, "sha256": hex(&model_digest())}, + "generations": generations(), + "descriptors": descriptor_vectors(), + "cases": cases, + }); + vec![("vectors.json".into(), serde_json::to_string_pretty(&doc).expect("JSON") + "\n")] +} + +/// Check the corpus's files: every generation and descriptor vector recomputes, and every case +/// gets the outcome and the statements it states. +pub fn verify(files: &BTreeMap) -> Vec { + let mut fails = Vec::new(); + let Some(doc) = files.get("vectors.json").and_then(|s| serde_json::from_str::(s).ok()) else { + return vec!["vectors.json does not read".into()]; + }; + let m = model(); + for g in doc["generations"].as_array().into_iter().flatten() { + let (Some(prompt), Some(seed), Some(steps), Some(w), Some(h)) = + (g["prompt"].as_str(), g["seed"].as_u64(), g["steps"].as_u64(), g["width"].as_u64(), g["height"].as_u64()) + else { + fails.push(format!("generation {g}: does not read")); + continue; + }; + if hex(&digest(&crate::generate::generate(&m, prompt, seed, steps as usize, h as usize, w as usize))) != g["sha256"] { + fails.push(format!("generation {prompt:?} seed {seed}: another picture")); + } + } + for d in doc["descriptors"].as_array().into_iter().flatten() { + let (Some(s), Some(w), Some(h)) = (Source::read(d), d["width"].as_u64(), d["height"].as_u64()) else { + fails.push(format!("descriptor vector {}: does not read", d["about"])); + continue; + }; + if json!(descriptors(&s.bytes(&m), w as usize, h as usize)) != d["descriptors"] { + fails.push(format!("descriptor vector {}: another vector", d["about"])); + } + } + for v in doc["cases"].as_array().into_iter().flatten() { + let name = v["name"].as_str().unwrap_or("?"); + let Some(c) = case_from_json(v) else { + fails.push(format!("{name}: the case does not read")); + continue; + }; + let got = Value::Object(outcome_json(&run(&c, &m))); + let mut want = Map::new(); + for k in ["outcome", "reason", "record", "statements"] { + if let Some(x) = v.get(k) { + want.insert(k.into(), x.clone()); + } + } + if got != Value::Object(want) { + fails.push(format!("{name}: {got}")); + } + } + fails +} diff --git a/wai/wai-rs/src/lib.rs b/wai/wai-rs/src/lib.rs index 19b48e8c5..38b3fe082 100644 --- a/wai/wai-rs/src/lib.rs +++ b/wai/wai-rs/src/lib.rs @@ -518,6 +518,14 @@ pub mod derive_edge; /// cbindgen:ignore #[cfg(feature = "ai_usage")] pub mod ai_usage; +// Exploration (extensions/exploration.md): `wai.media.exploration` — the descriptors of a +// picture, quality-diversity archives over the exact generator that replay bit for bit, a work's +// default-distance, collection statements, and taste as a declared, owned objective: taste +// priors, rankings under them and the disclosure of what steered a pick. Rust-only, like the +// live modules: its constants must not become macros in include/wai.h. +/// cbindgen:ignore +#[cfg(feature = "exploration")] +pub mod exploration; // Timed text and live captions (extensions/timed-text.md): `wai.text.timed` — the cue model // both WebVTT and the IMSC1 Text Profile express, live caption revisions as `caption` // events of `wai.live.events` with the WTX1 annotation, and the exact mappings onto WebVTT diff --git a/wai/wai-rs/tests/exploration.rs b/wai/wai-rs/tests/exploration.rs new file mode 100644 index 000000000..492050b1b --- /dev/null +++ b/wai/wai-rs/tests/exploration.rs @@ -0,0 +1,73 @@ +//! `wai.media.exploration` (extensions/exploration.md): the committed corpus +//! `live-conformance/exploration/` regenerates byte for byte from its fixed seeds, holds no other +//! file, every generation, descriptor vector and case in it gets the outcome it states, and the +//! extension's §13 lists exactly the reasons the reference reports. The generator itself asserts +//! that the corpus gives every one of them. +#![cfg(feature = "exploration")] + +use std::collections::BTreeMap; +use std::path::PathBuf; +use wai::exploration::{corpus, Reason, DESCRIPTORS}; + +fn wai_dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..") +} + +fn committed() -> BTreeMap { + let dir = wai_dir().join("live-conformance/exploration"); + std::fs::read_dir(&dir) + .expect("the committed corpus") + .flatten() + .map(|e| (e.file_name().to_string_lossy().into_owned(), e.path())) + .filter(|(n, _)| n != "README.md") + .map(|(n, p)| (n, std::fs::read_to_string(p).expect("a text file"))) + .collect() +} + +fn section(text: &str, heading: &str) -> String { + let at = text.find(heading).unwrap_or_else(|| panic!("a section {heading}")); + let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e); + text[at..end].to_string() +} + +#[test] +fn the_committed_corpus_regenerates_from_its_seeds() { + let files = committed(); + let generated: BTreeMap = corpus::generate().into_iter().collect(); + let extra: Vec<&String> = files.keys().filter(|k| !generated.contains_key(*k)).collect(); + let missing: Vec<&String> = generated.keys().filter(|k| !files.contains_key(*k)).collect(); + let differ: Vec<&String> = generated.iter().filter(|(k, v)| files.get(*k).is_some_and(|f| f != *v)).map(|(k, _)| k).collect(); + assert!(extra.is_empty() && missing.is_empty() && differ.is_empty(), "extra {extra:?}, missing {missing:?}, differ {differ:?}: run `wai_exploration_vectors gen`"); +} + +#[test] +fn every_case_gets_its_stated_outcome() { + let fails = corpus::verify(&committed()); + assert!(fails.is_empty(), "{}", fails.join("\n")); +} + +/// §13 of the extension lists exactly the codes `Reason::ALL` has, each once, in order. +#[test] +fn the_extension_lists_the_reasons() { + let text = std::fs::read_to_string(wai_dir().join("extensions/exploration.md")).expect("the extension"); + let listed: Vec = section(&text, "\n## 13. Reasons") + .lines() + .filter(|l| l.starts_with("| `")) + .filter_map(|l| l.split('`').nth(1).map(String::from)) + .collect(); + let want: Vec = Reason::ALL.iter().map(|r| r.code().to_string()).collect(); + assert_eq!(listed, want, "§13's table and Reason::ALL differ"); +} + +/// §3.2's table names the descriptors `DESCRIPTORS` holds, in its order. +#[test] +fn the_extension_names_the_descriptors() { + let text = std::fs::read_to_string(wai_dir().join("extensions/exploration.md")).expect("the extension"); + let s = section(&text, "\n### 3.2 "); + let named: Vec = s + .lines() + .filter(|l| l.starts_with("| ") && l.split('|').nth(1).is_some_and(|c| c.trim().parse::().is_ok())) + .filter_map(|l| l.split('`').nth(1).map(String::from)) + .collect(); + assert_eq!(named, DESCRIPTORS.map(String::from).to_vec(), "§3.2's table and DESCRIPTORS differ"); +} diff --git a/wai/wai-rs/tests/int_kernels_vectors.rs b/wai/wai-rs/tests/int_kernels_vectors.rs index 826edd143..f2f04b1ed 100644 --- a/wai/wai-rs/tests/int_kernels_vectors.rs +++ b/wai/wai-rs/tests/int_kernels_vectors.rs @@ -224,7 +224,7 @@ fn every_decoded_output_states_a_sha256() { ("ops-conformance", "integer operators: every operator, stage and graph vector, the lower_* decodes of the sets under sets/ among them, states its output integers in full or its refusal code, never a digest of them; certificates/ states each lowered set's SHA-256 (a parameter-set identity) and holds the lowered graphs as bytes, compared byte for byte; the output digests a capability decoded through its lowering reproduces (integer-operators §14.4) are stated by that capability's own corpus"), ("signer-conformance", "key logs, grants and statuses: signed documents, no decoded output"), ("edge-conformance", "derivation records of a deriving edge: each replicate-tier output is recomputed and compared byte for byte by its verifier, and every output is named by its content hash in the record"), - ("live-conformance", "live events, rooms, takes, compositions, recordings, captions, metering, steering, moderation, watermark sessions, ads and AI usage: signed records, commitments, packages, clips, cues and their renderings, per-hop records, ledgers and session receipts with their units and joules recomputed, steering policies and decisions with each pathway's evidence and the steering manifests recomputed byte for byte, review policies, decisions, notices and the items' timelines with each statement-of-reasons export written byte for byte, watermark tokens, session records, recovered sequences and disclosures, ad policies, breaks with their interstitial tags, events and asset lists written byte for byte and their impression receipts, usage statements with every term's preference, receipted envelopes (whose payloads are opaque test bytes no case decodes), room usage records, HTTP fields, catalogs, consumption claims and gate decisions, and their verdicts, and layouts and mixes stated in full, rectangle for rectangle and sample for sample; nothing decoded against a parameter set"), + ("live-conformance", "live events, rooms, takes, compositions, recordings, captions, metering, steering, moderation, watermark sessions, ads, AI usage and exploration: signed records, commitments, packages, clips, cues and their renderings, per-hop records, ledgers and session receipts with their units and joules recomputed, steering policies and decisions with each pathway's evidence and the steering manifests recomputed byte for byte, review policies, decisions, notices and the items' timelines with each statement-of-reasons export written byte for byte, watermark tokens, session records, recovered sequences and disclosures, ad policies, breaks with their interstitial tags, events and asset lists written byte for byte and their impression receipts, usage statements with every term's preference, receipted envelopes (whose payloads are opaque test bytes no case decodes), room usage records, HTTP fields, catalogs, consumption claims and gate decisions, and their verdicts, and layouts and mixes stated in full, rectangle for rectangle and sample for sample; nothing decoded against a parameter set but exploration's pictures of wai.generate.spectral, each named by the SHA-256 of its RGB8 samples in the records and in vectors.json's generations"), ("http-conformance", "objects and head proofs for transport: no case decodes a payload, and the component a fetch case picks is stated by its SHA-256"), ("cache-conformance", "cache rules: a driver, its controls and their reports, with no objects of its own"), ("byte-exact-conformance", "goldens over tests/vectors, whose sidecars state the SHA-256"), -- 2.54.0 (Apple Git-157) From 22fd469ec76c1a8df845b5e63724e9cd74398889 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 13:44:41 -0400 Subject: [PATCH 2/8] Registry export: wai.media.exploration and its document kinds Co-Authored-By: Claude Opus 5.5 --- wai/REGISTRY.md | 7 +++++ wai/registry/capabilities.json | 56 ++++++++++++++++++++++++++++++++++ wai/vocab/v2.ttl | 7 +++++ 3 files changed, 70 insertions(+) diff --git a/wai/REGISTRY.md b/wai/REGISTRY.md index 45caac416..ef89ab464 100644 --- a/wai/REGISTRY.md +++ b/wai/REGISTRY.md @@ -213,6 +213,7 @@ and a role are fixed once registered. | `wai.live.room` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content | | `wai.live.steering` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content | | `wai.live.watermark` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content | +| `wai.media.exploration` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content | | `wai.media.synthesis` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content | | `wai.mesh.draco` | payload | registered | volumetric | standalone | royalty-free | standard-unclassified | — | §5 Immersive audio, cinema, volumetric, haptics, HDR | | `wai.mesh.glb` | payload | registered | volumetric | standalone | royalty-free | standard-unclassified | — | §5 Interactive, temporal & computed content | @@ -366,19 +367,25 @@ and a role are fixed once registered. | `urn:wai:event:1` | scheme | defined | live-events §8.4 | | `urn:wai:event:1` | catalog | defined | live-events §8.1 | | `wai` | catalog | defined | moq-streaming-format §3 | +| `wai-archive` | document-kind | defined | exploration §5.3 | | `wai-c2pa` | catalog | defined | live-provenance §10.2 | +| `wai-collection` | document-kind | defined | exploration §7.1 | | `wai-derivation` | document-kind | defined | deriving-edge §5.1 | | `wai-detection` | document-kind | defined | synthesis §7.3 | +| `wai-distance` | document-kind | defined | exploration §6.3 | | `wai-key-status` | document-kind | defined | jwp-receipts §7.9 | | `wai-label-policy` | document-kind | defined | synthesis §10.1 | | `wai-marking` | document-kind | defined | synthesis §7.2 | | `wai-module-grant` | document-kind | defined | jwp-receipts §7.9 | | `wai-module-grants` | document-kind | defined | http-delivery §8.4 | | `wai-origin` | document-kind | defined | synthesis §3.1 | +| `wai-pick` | document-kind | defined | exploration §10.2 | | `wai-player` | document-kind | defined | synthesis §10.3 | +| `wai-ranking` | document-kind | defined | exploration §9.1 | | `wai-receipt-index` | document-kind | defined | http-delivery §8.2 | | `wai-receipts` | catalog | defined | moq-streaming-format §4.1 | | `wai-review` | document-kind | defined | synthesis §9.1 | +| `wai-taste` | document-kind | defined | exploration §8.1 | | `wai1` | codecs-prefix | defined | http-delivery §4.1 | | `wai1` | fourcc | provisional | http-delivery Appendix B | | `wai2` | codecs-prefix | defined | http-delivery §4.1 | diff --git a/wai/registry/capabilities.json b/wai/registry/capabilities.json index 2d0cb3198..322fa9ed2 100644 --- a/wai/registry/capabilities.json +++ b/wai/registry/capabilities.json @@ -784,6 +784,20 @@ "edition": null, "registered": "2026-10-20" }, + { + "capability": "wai.media.exploration", + "kind": "record", + "status": "registered", + "media": null, + "role": null, + "tier": null, + "licence": null, + "replicate": null, + "sets": [], + "spec_section": "§5 Interactive, temporal & computed content", + "edition": null, + "registered": "2026-10-21" + }, { "capability": "wai.media.synthesis", "kind": "record", @@ -2347,6 +2361,13 @@ "section": "§3", "status": "defined" }, + { + "name": "wai-archive", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§5.3", + "status": "defined" + }, { "name": "wai-c2pa", "kind": "catalog", @@ -2354,6 +2375,13 @@ "section": "§10.2", "status": "defined" }, + { + "name": "wai-collection", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§7.1", + "status": "defined" + }, { "name": "wai-derivation", "kind": "document-kind", @@ -2368,6 +2396,13 @@ "section": "§7.3", "status": "defined" }, + { + "name": "wai-distance", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§6.3", + "status": "defined" + }, { "name": "wai-key-status", "kind": "document-kind", @@ -2410,6 +2445,13 @@ "section": "§3.1", "status": "defined" }, + { + "name": "wai-pick", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§10.2", + "status": "defined" + }, { "name": "wai-player", "kind": "document-kind", @@ -2417,6 +2459,13 @@ "section": "§10.3", "status": "defined" }, + { + "name": "wai-ranking", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§9.1", + "status": "defined" + }, { "name": "wai-receipt-index", "kind": "document-kind", @@ -2438,6 +2487,13 @@ "section": "§9.1", "status": "defined" }, + { + "name": "wai-taste", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§8.1", + "status": "defined" + }, { "name": "wai1", "kind": "codecs-prefix", diff --git a/wai/vocab/v2.ttl b/wai/vocab/v2.ttl index 0078b7198..605923ee2 100644 --- a/wai/vocab/v2.ttl +++ b/wai/vocab/v2.ttl @@ -625,6 +625,13 @@ wai:wai.live.watermark a wai:Capability ; wai:specSection "§5 Interactive, temporal & computed content" ; wai:registeredOn "2026-10-20"^^xsd:date . +wai:wai.media.exploration a wai:Capability ; + rdfs:label "wai.media.exploration" ; + wai:kind wai:kind-record ; + wai:status wai:status-registered ; + wai:specSection "§5 Interactive, temporal & computed content" ; + wai:registeredOn "2026-10-21"^^xsd:date . + wai:wai.media.synthesis a wai:Capability ; rdfs:label "wai.media.synthesis" ; wai:kind wai:kind-record ; -- 2.54.0 (Apple Git-157) From f5e8ff1e3b9d7b78270f0255efbc0ddff99244c6 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 13:46:53 -0400 Subject: [PATCH 3/8] exploration: clippy notes (as_chunks, is_multiple_of, the corpus's first vector) Co-Authored-By: Claude Opus 5.5 --- wai/wai-rs/src/exploration.rs | 10 +++++----- wai/wai-rs/src/exploration/corpus.rs | 4 +--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/wai/wai-rs/src/exploration.rs b/wai/wai-rs/src/exploration.rs index 6fba5c0d3..f5dd082b9 100644 --- a/wai/wai-rs/src/exploration.rs +++ b/wai/wai-rs/src/exploration.rs @@ -189,7 +189,7 @@ impl std::error::Error for Reason {} pub type Vector = [u64; 6]; /// The luma of one `RGB8` pixel (§3.1). -fn luma_of(p: &[u8]) -> u64 { +fn luma_of(p: &[u8; 3]) -> u64 { (77 * p[0] as u64 + 150 * p[1] as u64 + 29 * p[2] as u64 + 128) >> 8 } @@ -198,10 +198,10 @@ fn luma_of(p: &[u8]) -> u64 { pub fn descriptors(rgb: &[u8], w: usize, h: usize) -> Vector { assert!(w >= 1 && h >= 1 && rgb.len() == w * h * 3, "an RGB8 buffer of its size"); let n = (w * h) as u128; - let y: Vec = rgb.chunks_exact(3).map(luma_of).collect(); + let y: Vec = rgb.as_chunks::<3>().0.iter().map(luma_of).collect(); let s: u128 = y.iter().map(|&v| v as u128).sum(); let luma = 1024 * s / (255 * n); - let c: u128 = rgb.chunks_exact(3).map(|p| (p.iter().max().unwrap() - p.iter().min().unwrap()) as u128).sum(); + let c: u128 = rgb.as_chunks::<3>().0.iter().map(|p| (p.iter().max().unwrap() - p.iter().min().unwrap()) as u128).sum(); let chroma = 1024 * c / (255 * n); let mut g: u128 = 0; for row in 0..h { @@ -218,7 +218,7 @@ pub fn descriptors(rgb: &[u8], w: usize, h: usize) -> Vector { let pairs = ((w - 1) * h + w * (h - 1)) as u128; let detail = if pairs == 0 { 0 } else { (1024 * g / (16 * pairs)).min(1024) }; let mut counts = [0u128; 64]; - for p in rgb.chunks_exact(3) { + for p in rgb.as_chunks::<3>().0 { counts[((p[0] >> 6) as usize) * 16 + ((p[1] >> 6) as usize) * 4 + (p[2] >> 6) as usize] += 1; } let sq: u128 = counts.iter().map(|k| k * k).sum(); @@ -839,7 +839,7 @@ fn trial_genome(r: &Request, rng: &mut Rng, t: u64, archive: &BTreeMap Vec { let a1_link = hex(&link_hash(&a1)); let a2_link = hex(&link_hash(&a2)); - let mut out = Vec::new(); - // ---- archives ---- - out.push(v("archive-novelty", "an archive with no objective: the first trial to reach each niche keeps it; replayed", vec![a1.clone()], Accept)); + let mut out = vec![v("archive-novelty", "an archive with no objective: the first trial to reach each niche keeps it; replayed", vec![a1.clone()], Accept)]; out.push( v("archive-taste", "an archive whose placement Alice's taste prior decides, scores stated; replayed", vec![a2.clone()], Accept) .priors(&[&p.personal]), -- 2.54.0 (Apple Git-157) From db613562889a1418dc99ad8ce28bbb3c558c1be8 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 13:55:42 -0400 Subject: [PATCH 4/8] exploration corpus: a generation whose orientation truncates toward zero, so a floored restatement of Appendix A fails Co-Authored-By: Claude Opus 5.5 --- wai/live-conformance/exploration/vectors.json | 8 ++++++++ wai/wai-rs/src/exploration/corpus.rs | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/wai/live-conformance/exploration/vectors.json b/wai/live-conformance/exploration/vectors.json index 80299741b..3b40125a9 100644 --- a/wai/live-conformance/exploration/vectors.json +++ b/wai/live-conformance/exploration/vectors.json @@ -100,6 +100,14 @@ "width": 1, "height": 7, "sha256": "a20fbc1bf2d1e3af92bc9e840eab879fe480493a5ef65893cb99442e82750e1f" + }, + { + "prompt": "water wild calm", + "seed": 8, + "steps": 6, + "width": 16, + "height": 9, + "sha256": "2afb4de30388ec4899f0ef87a7cff4d287383628ed668ac303b180a8f9d89986" } ], "descriptors": [ diff --git a/wai/wai-rs/src/exploration/corpus.rs b/wai/wai-rs/src/exploration/corpus.rs index 4bf4ac188..757e7ad92 100644 --- a/wai/wai-rs/src/exploration/corpus.rs +++ b/wai/wai-rs/src/exploration/corpus.rs @@ -924,7 +924,7 @@ fn vectors() -> Vec { fn generations() -> Vec { let m = model(); - let list: [(&str, u64, u64, u64, u64); 12] = [ + let list: [(&str, u64, u64, u64, u64); 13] = [ ("a calm spectral horizon", 7, 4, 17, 11), ("ring target", 1, 2, 16, 12), ("Mirror SYMMETRY", 2, 3, 13, 9), @@ -937,6 +937,9 @@ fn generations() -> Vec { ("a quiet forest at night bright calm", 123_456, 7, 10, 6), ("halo orb dawn", 99, 6, 20, 1), ("night night night abyss", 42, 2, 1, 7), + // An orientation sum of -230 over three words: -76 truncated toward zero, -77 floored, and + // with a horizontal frequency of ±10 the two scale it to different integers. + ("water wild calm", 8, 6, 16, 9), ]; list.iter() .map(|(prompt, seed, steps, w, h)| { -- 2.54.0 (Apple Git-157) From 5dcac6a08a449ebec4738efcbebe159b7fcaf982 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 13:58:38 -0400 Subject: [PATCH 5/8] exploration: a pick that a model steered must name it; the statements name each record's kind and a genome's members Co-Authored-By: Claude Opus 5.5 --- wai/extensions/exploration.md | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/wai/extensions/exploration.md b/wai/extensions/exploration.md index 1b539f20d..98e28b93b 100644 --- a/wai/extensions/exploration.md +++ b/wai/extensions/exploration.md @@ -534,8 +534,8 @@ samples or some were taken as stated. ### 10.1 The member `objective` -Every record that an aesthetic or reward model steered — a generation, a selection, a ranking — -names that model, or states that none steered it. The disclosure is the member `objective`: +A record of a generation, a selection or a ranking says which aesthetic or reward model steered +it, or that none did, in the member `objective`: | value | meaning | |---|---| @@ -544,8 +544,10 @@ names that model, or states that none steered it. The disclosure is the member ` | `{"type": "model", "sha256", "id"}` | another aesthetic or reward model, by the SHA-256 of its parameter set (SPEC §3.1) and a name for people: named, not run here | A **taste objective** is a value of type `taste`. An archive's `objective` (§5.1) is the -disclosure of its placement rule, and a ranking's `prior` is its objective. A record of another -extension that a model may steer carries the same member where that extension adds it (§11). +disclosure of its placement rule, and a ranking's `prior` is its objective: both are required +members. A pick (§10.2) that a model steered **MUST** carry `objective` naming the model, and one +that nothing steered **SHOULD** carry `"none"`. A record of another extension that a model may +steer carries the same member where that extension adds it (§11). ### 10.2 The pick @@ -579,9 +581,10 @@ prior, since the prior chose every elite: its `objective` MUST name the same pri ### 10.3 Policy -A missing `objective` is never read as `none`: the record is **undisclosed**, and a verifier -reports it so. A policy MAY require the member of every pick (§12.1); under it, a pick without -`objective` is `objective_undisclosed`. Every archive and ranking carries its objective by +A verifier sees steering only where a record shows it: through an archive a pick names (§10.2), +and otherwise not. So a missing `objective` is never read as `none`: the record is +**undisclosed**, and a verifier reports it so. A policy MAY require the member of every pick +(§12.1); under it, a pick without `objective` is `objective_undisclosed`. Every archive and ranking carries its objective by construction. A universal aesthetic objective therefore cannot steer a record silently: it is named by digest, or the record says that nothing steered it, or the record is undisclosed and a policy that requires disclosure refuses it. @@ -594,8 +597,8 @@ After the record reads and its signature verifies, in this order: 2. A taste objective's prior resolves and verifies (§8.3, §8.4). 3. Held samples of the work are of its size (`samples_mismatch`). 4. From an archive: the verifier holds the archive, verified earlier in the same case - (`archive_unheld`); the archive has an elite at `niche`, whose samples digest is the work's - and whose archive's size is the work's (`pick_not_in_archive`); and where the archive's + (`archive_unheld`); the archive has an elite at `niche` whose samples digest is the work's, and + the work's size is the archive's (`pick_not_in_archive`); and where the archive's objective is a taste prior, the pick's `objective` names that prior's digest (`objective_mismatch`). 5. From a set: the work's samples digest is one of the set (`pick_not_in_set`). @@ -609,9 +612,9 @@ from an archive or a regenerated generation, the genome. ## 11. The slot contribution fills -The contribution record, `wai.media.contribution`, records a creative session step by step; its `candidates` step -commits a set of pictures by samples digest and seed, and its `select` step picks one. This -revision leaves it one slot and one member, which that extension fills: +The contribution record, `wai.media.contribution`, records a creative session step by step: its +`candidates` step commits a set of pictures by samples digest and seed, and its `select` step +picks one. This revision leaves it one slot and one member, which that extension fills: - **`archive`**: a `candidates` step MAY name an archive record by its link hash. The set it commits is then the archive's elites in ascending niche order: each member's samples digest is @@ -646,7 +649,7 @@ names is held only once it has been verified, earlier in the case. ### 12.3 What an accepted case states -For each record, in order: +For each record, in order, its `kind` and: - an archive: its link hash, `replayed` or `elites`, `occupied`, `cells`, and its objective (`none`, or `{"type", "sha256"}`); @@ -656,7 +659,9 @@ For each record, in order: `stated`, and for each `usage` entry its vocabulary, term and preference (`allow`, `unknown`, `outside` for a `null` term, or `absent` when the prior's statement does not carry the vocabulary); -- a pick: its link hash, its act, its objective, its check and its genome (or `null`). +- a pick: its link hash, its act, its objective, its check, and its genome: `seed`, `steps`, + `mods` (0 for a generation) and the derived `prompt`, or `null` for a pick from a set or a + generation taken as stated. ## 13. Reasons -- 2.54.0 (Apple Git-157) From 12b39d399bdc0c49ef31c78b5d328d6b08c53b57 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 14:42:30 -0400 Subject: [PATCH 6/8] exploration: no consent requirement for a service's own mechanics; a lawful basis is a lawful-basis claim's Co-Authored-By: Claude Opus 5.5 --- wai/extensions/exploration.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/wai/extensions/exploration.md b/wai/extensions/exploration.md index 98e28b93b..997eef5b1 100644 --- a/wai/extensions/exploration.md +++ b/wai/extensions/exploration.md @@ -460,9 +460,10 @@ digest selects it, not the `id`. A pin that names a prior the verifier does not ### 8.4 Ownership and usage A prior is its owner's: it **MUST** be signed by `owner`. One signed by any other key is -`taste_not_owner`, whatever its signature: a tool can publish a person's taste only by holding -the person's signature over it. The checks run in this order: the file reads, the signature -verifies (`bad_key`, `bad_signature`), and the signer is the owner. +`taste_not_owner`, whatever its signature. The rule is one of attribution: a taste is ascribed +to a key only by that key's signature, so no tool can present a prior as someone's who did not +sign it. The checks run in this order: the file reads, the signature verifies (`bad_key`, +`bad_signature`), and the signer is the owner. The owner's usage statement governs the prior as it governs any content ([ai-usage](ai-usage.md) §5): it is the prior's signed statement, signed with it by the owner. A @@ -470,6 +471,13 @@ ranking states the use it made of the prior (§9.3), and a use the statement dis A prior that travels in a WAI envelope carries the same statement in the envelope's manifest (ai-usage §4.1), and an agent that consumes it claims its use there as for any object. +This extension sets no consent requirement for a service's own mechanics: making an archive, +measuring a distance, ranking with the prior a person chose. Using a distributor's WAI service is +the person's agreement to how that service works. The usage statement is the owner's preference, +read as ai-usage reads any statement. Where a regime asks for a lawful basis for processing a +personal prior, the service records it in a `lawful-basis` claim +([jwp-receipts](jwp-receipts.md) §2.4.6). + ### 8.5 No default objective This extension defines no taste prior of its own, ships none as a default, and ranks nothing @@ -752,11 +760,11 @@ and drops each of its own checks in turn and requires the corpus to catch the we - **Gaming a distance.** A work far from the defaults is not thereby original: a distance is a measurement, not a judgement, and a collection statement shows whether many works moved away from the defaults in the same direction. -- **Taste is personal data.** A personal prior describes what one person likes. It is signed by - that person's key, and a tool cannot publish one in the person's name without that signature - (§8.4). Its owner's usage statement travels with it, and a ranking that uses it states its use - under the owner's key-checked terms. A party that holds a ranking learns how a prior ordered - those pictures, which is what a ranking is for. +- **Taste describes a person.** A personal prior says what one person likes. It is ascribed to a + person only by that person's signature (§8.4), and its owner's usage statement travels with it. + A party that holds a ranking learns how a prior ordered those pictures, which is what a ranking + is for. Where a regime asks for a lawful basis for processing it, that is a `lawful-basis` + claim's (§8.4). - **Undisclosed steering.** A pick without `objective` is reported undisclosed, never as `none`. A party that steers a selection with a model and states `none` makes a false signed statement; where the steering came from an archive the pick names, the verifier sees it (§10.2). -- 2.54.0 (Apple Git-157) From 25c02eb934bb727216bd158f7ebceaf590f21793 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 20:38:31 -0400 Subject: [PATCH 7/8] registry export: regenerated after merging main Co-Authored-By: Claude Opus 5.5 --- wai/registry/capabilities.json | 56 ++++++++++++++++++++++++++++++++++ wai/vocab/v2.ttl | 7 +++++ 2 files changed, 63 insertions(+) diff --git a/wai/registry/capabilities.json b/wai/registry/capabilities.json index 3cb107ada..b57482574 100644 --- a/wai/registry/capabilities.json +++ b/wai/registry/capabilities.json @@ -812,6 +812,20 @@ "edition": null, "registered": "2026-10-21" }, + { + "capability": "wai.media.exploration", + "kind": "record", + "status": "registered", + "media": null, + "role": null, + "tier": null, + "licence": null, + "replicate": null, + "sets": [], + "spec_section": "§5 Interactive, temporal & computed content", + "edition": null, + "registered": "2026-10-21" + }, { "capability": "wai.media.synthesis", "kind": "record", @@ -2396,6 +2410,13 @@ "section": "§3", "status": "defined" }, + { + "name": "wai-archive", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§5.3", + "status": "defined" + }, { "name": "wai-authorship-map", "kind": "document-kind", @@ -2410,6 +2431,13 @@ "section": "§10.2", "status": "defined" }, + { + "name": "wai-collection", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§7.1", + "status": "defined" + }, { "name": "wai-contribution", "kind": "document-kind", @@ -2431,6 +2459,13 @@ "section": "§7.3", "status": "defined" }, + { + "name": "wai-distance", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§6.3", + "status": "defined" + }, { "name": "wai-key-status", "kind": "document-kind", @@ -2480,6 +2515,13 @@ "section": "§3.1", "status": "defined" }, + { + "name": "wai-pick", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§10.2", + "status": "defined" + }, { "name": "wai-player", "kind": "document-kind", @@ -2487,6 +2529,13 @@ "section": "§10.3", "status": "defined" }, + { + "name": "wai-ranking", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§9.1", + "status": "defined" + }, { "name": "wai-receipt-index", "kind": "document-kind", @@ -2522,6 +2571,13 @@ "section": "§4.1", "status": "defined" }, + { + "name": "wai-taste", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§8.1", + "status": "defined" + }, { "name": "wai1", "kind": "codecs-prefix", diff --git a/wai/vocab/v2.ttl b/wai/vocab/v2.ttl index 599b50d69..57b0e4e19 100644 --- a/wai/vocab/v2.ttl +++ b/wai/vocab/v2.ttl @@ -639,6 +639,13 @@ wai:wai.media.contribution a wai:Capability ; wai:specSection "§5 Interactive, temporal & computed content" ; wai:registeredOn "2026-10-21"^^xsd:date . +wai:wai.media.exploration a wai:Capability ; + rdfs:label "wai.media.exploration" ; + wai:kind wai:kind-record ; + wai:status wai:status-registered ; + wai:specSection "§5 Interactive, temporal & computed content" ; + wai:registeredOn "2026-10-21"^^xsd:date . + wai:wai.media.synthesis a wai:Capability ; rdfs:label "wai.media.synthesis" ; wai:kind wai:kind-record ; -- 2.54.0 (Apple Git-157) From 6e3cf81d80499a3ccc9fc87d4b47b840c23b13d3 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 23:21:13 -0400 Subject: [PATCH 8/8] registry export: regenerated after merging main Co-Authored-By: Claude Opus 5.5 --- wai/registry/capabilities.json | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/wai/registry/capabilities.json b/wai/registry/capabilities.json index 3ea123031..6b4fc39f0 100644 --- a/wai/registry/capabilities.json +++ b/wai/registry/capabilities.json @@ -840,6 +840,20 @@ "edition": null, "registered": "2026-10-21" }, + { + "capability": "wai.media.exploration", + "kind": "record", + "status": "registered", + "media": null, + "role": null, + "tier": null, + "licence": null, + "replicate": null, + "sets": [], + "spec_section": "§5 Interactive, temporal & computed content", + "edition": null, + "registered": "2026-10-21" + }, { "capability": "wai.media.synthesis", "kind": "record", @@ -2445,6 +2459,13 @@ "section": "§7.1", "status": "defined" }, + { + "name": "wai-archive", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§5.3", + "status": "defined" + }, { "name": "wai-authorship-map", "kind": "document-kind", @@ -2480,6 +2501,13 @@ "section": "§4.2", "status": "defined" }, + { + "name": "wai-collection", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§7.1", + "status": "defined" + }, { "name": "wai-contribution", "kind": "document-kind", @@ -2508,6 +2536,13 @@ "section": "§7.3", "status": "defined" }, + { + "name": "wai-distance", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§6.3", + "status": "defined" + }, { "name": "wai-key-status", "kind": "document-kind", @@ -2557,6 +2592,13 @@ "section": "§3.1", "status": "defined" }, + { + "name": "wai-pick", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§10.2", + "status": "defined" + }, { "name": "wai-player", "kind": "document-kind", @@ -2564,6 +2606,13 @@ "section": "§10.3", "status": "defined" }, + { + "name": "wai-ranking", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§9.1", + "status": "defined" + }, { "name": "wai-receipt-index", "kind": "document-kind", @@ -2613,6 +2662,13 @@ "section": "§4.1", "status": "defined" }, + { + "name": "wai-taste", + "kind": "document-kind", + "document": "extensions/exploration.md", + "section": "§8.1", + "status": "defined" + }, { "name": "wai1", "kind": "codecs-prefix", -- 2.54.0 (Apple Git-157)