diff --git a/.github/workflows/wai-conformance.yml b/.github/workflows/wai-conformance.yml index 9a6104a23..ac5e7de3d 100644 --- a/.github/workflows/wai-conformance.yml +++ b/.github/workflows/wai-conformance.yml @@ -141,6 +141,10 @@ on: # reports, settlement_verify.py reads that table, and the registry's wire identifiers test # reads its sections. - 'wai/extensions/settlement.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' @@ -1279,6 +1283,29 @@ jobs: (cd wai-rs && cargo test --no-default-features --features settlement --lib settlement::) (cd wai-rs && cargo test --no-default-features --features settlement --test settlement) python3 -I live-conformance/settlement_verify.py live-conformance/settlement + # 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 49144c43e..97fe014fd 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.live.ad_presentation`: a player's signed claim that an ad was presented, and a spend that counts only presented impressions - **The extension** ([ad-presentation](extensions/ad-presentation.md)) registers the record diff --git a/wai/REGISTRY.md b/wai/REGISTRY.md index 9c47a6d8f..0143e67d9 100644 --- a/wai/REGISTRY.md +++ b/wai/REGISTRY.md @@ -63,7 +63,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 @@ -210,6 +211,7 @@ and a role are fixed once registered. | `wai.live.steering` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content | | `wai.live.watermark` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content | | `wai.media.contribution` | 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 | @@ -369,15 +371,18 @@ and a role are fixed once registered. | `urn:wai:event:1` | catalog | defined | live-events §8.1 | | `wai` | catalog | defined | moq-streaming-format §3 | | `wai-access-completeness` | document-kind | defined | access-services §7.1 | +| `wai-archive` | document-kind | defined | exploration §5.3 | | `wai-authorship-map` | document-kind | defined | contribution §7.3 | | `wai-c2pa` | catalog | defined | live-provenance §10.2 | | `wai-caption-quality` | document-kind | defined | access-services §4.7 | | `wai-caption-reference` | document-kind | defined | access-services §4.3 | | `wai-caption-sources` | document-kind | defined | access-services §4.2 | +| `wai-collection` | document-kind | defined | exploration §7.1 | | `wai-contribution` | document-kind | defined | contribution §6 | | `wai-derivation` | document-kind | defined | deriving-edge §5.1 | | `wai-description` | document-kind | defined | access-services §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 | @@ -385,7 +390,9 @@ and a role are fixed once registered. | `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 | @@ -393,6 +400,7 @@ and a role are fixed once registered. | `wai-signing` | document-kind | defined | access-services §6.1 | | `wai-signing-review` | document-kind | defined | access-services §6.4 | | `wai-step` | document-kind | defined | contribution §4.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/SPEC.md b/wai/SPEC.md index 18c5a3c8f..05c9feb96 100644 --- a/wai/SPEC.md +++ b/wai/SPEC.md @@ -1232,6 +1232,23 @@ the amount under a declared tariff in integer micro-units; a verifier recomputes the acknowledgements and refuses a statement that does not recompute. Acknowledgements map onto CDNI logging records (RFC 7937), whose fields carry no counter-signature, and a line kind is reserved for a payee that is not a hop: [`extensions/settlement.md`](extensions/settlement.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 diff --git a/wai/extensions/exploration.md b/wai/extensions/exploration.md new file mode 100644 index 000000000..997eef5b1 --- /dev/null +++ b/wai/extensions/exploration.md @@ -0,0 +1,830 @@ +# 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. 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 +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. + +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 +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` + +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 | +|---|---| +| `"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: 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 + +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 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. + +### 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 + 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`). +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, its `kind` and: + +- 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: `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 + +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 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). +- **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 9220a775d..b4e169f1b 100644 --- a/wai/live-conformance/README.md +++ b/wai/live-conformance/README.md @@ -24,6 +24,7 @@ and the independent verifier of each, beside it. | [`settlement/`](settlement/) | [settlement](../extensions/settlement.md) (`wai.delivery.settlement`) | `wai_settlement_vectors gen` | `settlement_verify.py` | | [`access/`](access/) | [access-services](../extensions/access-services.md) (`wai.access.services`) | `wai_access_services_vectors gen` | `access_services_verify.py` | | [`presentation/`](presentation/) | [ad-presentation](../extensions/ad-presentation.md) (`wai.live.ad_presentation`) | `wai_ad_presentation_vectors gen` | `ad_presentation_verify.py` | +| [`exploration/`](exploration/) | [exploration](../extensions/exploration.md) (`wai.media.exploration`) | `wai_exploration_vectors gen` | `exploration_verify.py` | **Provenance.** Generated here: each directory's corpus is written by its row's generator (`gen`, in `wai/wai-rs`), from records authored in code and from fixed seeds, and each @@ -59,4 +60,5 @@ python3 synthesis_verify.py synthesis python3 ai_usage_verify.py usage python3 contribution_verify.py contribution python3 settlement_verify.py settlement +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..3b40125a9 --- /dev/null +++ b/wai/live-conformance/exploration/vectors.json @@ -0,0 +1,3705 @@ +{ + "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" + }, + { + "prompt": "water wild calm", + "seed": 8, + "steps": 6, + "width": 16, + "height": 9, + "sha256": "2afb4de30388ec4899f0ef87a7cff4d287383628ed668ac303b180a8f9d89986" + } + ], + "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/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", diff --git a/wai/vocab/v2.ttl b/wai/vocab/v2.ttl index f034d656a..ac1a1c1ab 100644 --- a/wai/vocab/v2.ttl +++ b/wai/vocab/v2.ttl @@ -653,6 +653,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 ; diff --git a/wai/wai-rs/Cargo.toml b/wai/wai-rs/Cargo.toml index 21c2fd97b..a15d83352 100644 --- a/wai/wai-rs/Cargo.toml +++ b/wai/wai-rs/Cargo.toml @@ -330,6 +330,15 @@ ai_usage = ["live_room"] # declared bytes, per-class joules from live-metering's WMH1 and integer amount a verifier # recomputes. SHA-256, BLAKE3, Ed25519 and the room's records only; no new dependency. settlement = ["live_metering", "jwp_hash"] +# 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, @@ -845,6 +854,11 @@ name = "wai_settlement_vectors" path = "src/bin/wai_settlement_vectors.rs" required-features = ["settlement"] +[[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" @@ -1585,6 +1599,11 @@ name = "settlement" path = "tests/settlement.rs" required-features = ["settlement"] +[[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 6486c095b..afb352617 100644 --- a/wai/wai-rs/src/codecs/registry.rs +++ b/wai/wai-rs/src/codecs/registry.rs @@ -229,6 +229,7 @@ pub const CAP_AI_USAGE: &str = "wai.ai.usage"; pub const CAP_MEDIA_CONTRIBUTION: &str = "wai.media.contribution"; pub const CAP_DELIVERY_SETTLEMENT: &str = "wai.delivery.settlement"; pub const CAP_ACCESS_SERVICES: &str = "wai.access.services"; +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)`. @@ -326,6 +327,7 @@ const ROWS: &[(&str, &str, Option<&str>, &str)] = &[ (CAP_MEDIA_CONTRIBUTION, S_INTERACTIVE, None, "2026-10-21"), (CAP_DELIVERY_SETTLEMENT, S_INTERACTIVE, None, "2026-10-21"), (CAP_ACCESS_SERVICES, 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"), @@ -386,6 +388,7 @@ const RECORDS: &[&str] = &[ CAP_MEDIA_CONTRIBUTION, CAP_DELIVERY_SETTLEMENT, CAP_ACCESS_SERVICES, + CAP_MEDIA_EXPLORATION, ]; /// A named identifier SPEC uses that has the shape of a capability string but is @@ -550,6 +553,7 @@ const SYNTHESIS: &str = "extensions/synthesis.md"; const CONTRIBUTION: &str = "extensions/contribution.md"; const SETTLEMENT: &str = "extensions/settlement.md"; const ACCESS_SERVICES: &str = "extensions/access-services.md"; +const EXPLORATION: &str = "extensions/exploration.md"; const fn wire(name: &'static str, kind: WireKind, document: &'static str, section: &'static str, status: WireStatus) -> WireIdentifier { @@ -675,6 +679,12 @@ pub const WIRE_IDENTIFIERS: &[WireIdentifier] = &[ wire("wai-signing", WireKind::DocumentKind, ACCESS_SERVICES, "§6.1", WireStatus::Defined), wire("wai-signing-review", WireKind::DocumentKind, ACCESS_SERVICES, "§6.4", WireStatus::Defined), wire("wai-access-completeness", WireKind::DocumentKind, ACCESS_SERVICES, "§7.1", WireStatus::Defined), + 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..f5dd082b9 --- /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; 3]) -> 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.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.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 { + 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.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(); + 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().is_multiple_of(m) { + 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..757e7ad92 --- /dev/null +++ b/wai/wai-rs/src/exploration/corpus.rs @@ -0,0 +1,1137 @@ +//! 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)); + + // ---- archives ---- + 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]), + ); + 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); 13] = [ + ("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), + // 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)| { + 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 41b0589f1..651825446 100644 --- a/wai/wai-rs/src/lib.rs +++ b/wai/wai-rs/src/lib.rs @@ -535,6 +535,14 @@ pub mod ai_usage; /// cbindgen:ignore #[cfg(feature = "settlement")] pub mod settlement; +// 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"); +}