Refusable Divergence
A divergence between two implementations is refused by name, not passed in silence.
- Standing
- WITNESSED CHECKABLE RUNNABLE EXECUTED STAGED PUBLISHED REPRODUCED
- Last checked
- 2026-09-11 15:25:45 UTC
- Source
WRL/test/conformance.mjs@32160fec77a1· bytese1f1e313eefe0001…- Limit
- WRL's conformance suite passes; the 'agree on the name of every refusal' half is STACK_COMPLETION.md:73's wording and is NOT verified by this build. WRL/HANDOFF_D8_PATH_B.md:1424 warns that two refusals can both be drift — two-sidedness is necessary and not sufficient.
- Next rung
live_local— the WRL playground has no negative corpus, so no tamper can be refused in a browser today. Staging one is the work.
Why this page says WITNESSED — the derivation, not the word
- ✓ a witness is named
- ✓ its evidence kind is one the ledger already uses (constructive_witness)
- ✓ the witness path resolves in this tree
- ✓ its rung is in_tree or above (in_tree)
- ✓ a run is recorded for these exact bytes
- ✓ no claim is cited that could be REFUTED
- ✓ a counterexample is shipped (required once WITNESSED)
- ✗ not staged on this site, so it cannot run from the page
WITNESSED requires every line above to hold. The label is computed from them by build.mjs and cannot be typed into the registry — the build refuses a record that carries it.
Intent
Put only claims on the wire — no flags, no prose. Every receiver recomputes the claims from the bytes. Two verifiers in two languages then either agree or refuse, and a refusal names what it refused. A negative corpus of tampered records is part of the artifact, so 'refuses' is something you can run.
Technical register
WRL §D8.19, the projection on the wire. deriveRuntimeProjection makes the V1→V2 downgrade in-band. Conformance: 924 checks passing today (STACK_COMPLETION recorded 890 in August). Negative corpus: 15 tampered records stored as final bytes, refused by both verifiers; a consumer must check the wire differs from its base before trusting a refusal, and whether refusal codes are normative is an open question the corpus states itself.
Problem
Two implementations of one format drift. The usual defence is a version flag and a prose note, and both are things a receiver is asked to believe. When the implementations disagree, the disagreement passes silently and shows up later as data that two systems read differently.
Solution
Seal the artifact (Meaning Is a Hash). Put the recomputable claims on the wire and nothing else. Keep a negative corpus as final bytes beside the positive vectors. Run two independent verifiers and require both to refuse every tamper; report code disagreement separately from the refusal.
Real-world analogy
Two auditors who each recompute the total from the receipts rather than reading the number at the bottom of the page. If the page lies, both say so, and each says which line.
Structure — on the surface
An illustration on a compute surface: loci above, carriers below. Press Play or Step; the takeaways collect as you go. Nothing here is evidence — the witness section is.
The chapter in WRL — and the chain so far
Chapter 12 of 32 — the fragment _patterns/wrl/chain/refusable-divergence.wrl, sealed alone by wrl.js
; REFUSABLE DIVERGENCE — a claim naming a target the world does not have is Rejected(unknown_spinner) by
; name, with a receipt. rd_in is the entry, fed by the grant router.
[relay:rd_in]{sig_in, sig_out}
[spinner:rd_real](w=16, n=8, rotor=quarter_turn_z, configurable){sig_in, socket}
[orb:rd_view]{pose}
[rd_in] --sig--> [rd_real]
[rd_real] --socket--> [rd_view]Its test bench _patterns/wrl/chain/refusable-divergence.bench.wrl — drives the entry for this chapter's own film; never part of the chain
; TEST BENCH — drives this chapter's entry alone; the chain replaces it with a wire from an earlier chapter
[pulser:rd_bench](every 1){sig_out}
[rd_bench] --sig--> [rd_in]module + bench seal to → sem-a2734400042b9cdbd440169056b0bd05d0523aad1438197cec5b60aae9533dd5
Run inputs — a ScenarioV1, the forge's own document, bound to this world's id and never part of it (D3) · ScenarioDigest scen-9298d883d98dceb0734… (the run inputs' own identity, computed by the forge)
| epoch | writer · seq | op | target | rotor | label |
|---|---|---|---|---|---|
| 1 | w1 s1 | SetRotor | rd_ghost | 1.2.3.4 | SetRotor rd_ghost 1.2.3.4 |
| 2 | w1 s2 | SetRotor | rd_real | 255.0.0.0 | SetRotor rd_real 255.0.0.0 |
Reduced by the native reducer (ic32); the reference reducer reproduces every epoch's film hash (33.047s).
Receipts in the last epoch's Film
receipt:w=1,s=1,accepted=ee,apkey=0.1.1.2.3.4,epoch=1,outcome=Rejected(unknown_spinner) receipt:w=1,s=2,accepted=3f,apkey=0.0.255.0.0.0,epoch=2,outcome=Applied
The Film, epoch by epoch (6)
epoch 1 · sha256:2b6a0aef7f941303d098ab0ebb474b720f4bfe62852358f1b32b6a34acb624bb
FILM v0.7 t=1 spinner:rd_real:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,rotor=00b5,0000,0000,00b5,socket=rd_view,config=configurable orb:rd_view:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,pose=0100,0000,0000,0000,controller=rd_real,fault=0 pulser:rd_bench:mode=periodic,p=1,phase=0,armed=0,done=0,nf=1 relay:rd_in:cur_out=0,next_out=1 wire:w__rd_bench__rd_in:cur=1,nxt=1 wire:w__rd_in__rd_real:cur=0,nxt=0 admit:policy=admit_candidate_min_firstreceipt_v1,fact_capacity_fault=0,receipt_capacity_fault=0,capacity_fault=0 claim:w=1,s=1,digest=ee,pkey=0.1.1.2.3.4,payload=SetRotor:#?:1.2.3.4 receipt:w=1,s=1,accepted=ee,apkey=0.1.1.2.3.4,epoch=1,outcome=Rejected(unknown_spinner) recognition:w=1,s=1,state=unambiguous
epoch 2 · sha256:2087fc22b1ff12345b0e8d706dcb97c83b2225e5efc778b8acf5d6daf61df10d
FILM v0.7 t=2 spinner:rd_real:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,rotor=00ff,0000,0000,0000,socket=rd_view,config=configurable orb:rd_view:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,pose=0100,0000,0000,0000,controller=rd_real,fault=0 pulser:rd_bench:mode=periodic,p=1,phase=0,armed=0,done=0,nf=1 relay:rd_in:cur_out=1,next_out=1 wire:w__rd_bench__rd_in:cur=1,nxt=1 wire:w__rd_in__rd_real:cur=0,nxt=1 admit:policy=admit_candidate_min_firstreceipt_v1,fact_capacity_fault=0,receipt_capacity_fault=0,capacity_fault=0 claim:w=1,s=1,digest=ee,pkey=0.1.1.2.3.4,payload=SetRotor:#?:1.2.3.4 claim:w=1,s=2,digest=3f,pkey=0.0.255.0.0.0,payload=SetRotor:rd_real:255.0.0.0 receipt:w=1,s=1,accepted=ee,apkey=0.1.1.2.3.4,epoch=1,outcome=Rejected(unknown_spinner) receipt:w=1,s=2,accepted=3f,apkey=0.0.255.0.0.0,epoch=2,outcome=Applied recognition:w=1,s=1,state=unambiguous recognition:w=1,s=2,state=unambiguous
epoch 3 · sha256:85abb23b842d0355bf821007be8d7f6332e4b22478bf9185bb561dcaf37ff795
FILM v0.7 t=3 spinner:rd_real:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,rotor=00ff,0000,0000,0000,socket=rd_view,config=configurable orb:rd_view:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,pose=00ff,0000,0000,0000,controller=rd_real,fault=0 pulser:rd_bench:mode=periodic,p=1,phase=0,armed=0,done=0,nf=1 relay:rd_in:cur_out=1,next_out=1 wire:w__rd_bench__rd_in:cur=1,nxt=1 wire:w__rd_in__rd_real:cur=1,nxt=1 admit:policy=admit_candidate_min_firstreceipt_v1,fact_capacity_fault=0,receipt_capacity_fault=0,capacity_fault=0 claim:w=1,s=1,digest=ee,pkey=0.1.1.2.3.4,payload=SetRotor:#?:1.2.3.4 claim:w=1,s=2,digest=3f,pkey=0.0.255.0.0.0,payload=SetRotor:rd_real:255.0.0.0 receipt:w=1,s=1,accepted=ee,apkey=0.1.1.2.3.4,epoch=1,outcome=Rejected(unknown_spinner) receipt:w=1,s=2,accepted=3f,apkey=0.0.255.0.0.0,epoch=2,outcome=Applied recognition:w=1,s=1,state=unambiguous recognition:w=1,s=2,state=unambiguous
epoch 4 · sha256:fffc8f2fd6a1fe601bbb811ba8041a50b4ff32683caec8f13de9aa7940278fef
FILM v0.7 t=4 spinner:rd_real:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,rotor=00ff,0000,0000,0000,socket=rd_view,config=configurable orb:rd_view:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,pose=00fe,0000,0000,0000,controller=rd_real,fault=0 pulser:rd_bench:mode=periodic,p=1,phase=0,armed=0,done=0,nf=1 relay:rd_in:cur_out=1,next_out=1 wire:w__rd_bench__rd_in:cur=1,nxt=1 wire:w__rd_in__rd_real:cur=1,nxt=1 admit:policy=admit_candidate_min_firstreceipt_v1,fact_capacity_fault=0,receipt_capacity_fault=0,capacity_fault=0 claim:w=1,s=1,digest=ee,pkey=0.1.1.2.3.4,payload=SetRotor:#?:1.2.3.4 claim:w=1,s=2,digest=3f,pkey=0.0.255.0.0.0,payload=SetRotor:rd_real:255.0.0.0 receipt:w=1,s=1,accepted=ee,apkey=0.1.1.2.3.4,epoch=1,outcome=Rejected(unknown_spinner) receipt:w=1,s=2,accepted=3f,apkey=0.0.255.0.0.0,epoch=2,outcome=Applied recognition:w=1,s=1,state=unambiguous recognition:w=1,s=2,state=unambiguous
epoch 5 · sha256:5b399c598188f59b3aef5c0cf34caabfe096f2ecd7003a5c1e50e38cac9b3ac1
FILM v0.7 t=5 spinner:rd_real:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,rotor=00ff,0000,0000,0000,socket=rd_view,config=configurable orb:rd_view:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,pose=00fd,0000,0000,0000,controller=rd_real,fault=0 pulser:rd_bench:mode=periodic,p=1,phase=0,armed=0,done=0,nf=1 relay:rd_in:cur_out=1,next_out=1 wire:w__rd_bench__rd_in:cur=1,nxt=1 wire:w__rd_in__rd_real:cur=1,nxt=1 admit:policy=admit_candidate_min_firstreceipt_v1,fact_capacity_fault=0,receipt_capacity_fault=0,capacity_fault=0 claim:w=1,s=1,digest=ee,pkey=0.1.1.2.3.4,payload=SetRotor:#?:1.2.3.4 claim:w=1,s=2,digest=3f,pkey=0.0.255.0.0.0,payload=SetRotor:rd_real:255.0.0.0 receipt:w=1,s=1,accepted=ee,apkey=0.1.1.2.3.4,epoch=1,outcome=Rejected(unknown_spinner) receipt:w=1,s=2,accepted=3f,apkey=0.0.255.0.0.0,epoch=2,outcome=Applied recognition:w=1,s=1,state=unambiguous recognition:w=1,s=2,state=unambiguous
epoch 6 · sha256:425fa543cc61aaabc1a7ed14d871be21e5ba2f6c35294b8f3fa644ab84bee51d
FILM v0.7 t=6 spinner:rd_real:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,rotor=00ff,0000,0000,0000,socket=rd_view,config=configurable orb:rd_view:policy=forge_motor_widemac_tz_sat_v1,quat4,w=16,n=8,pose=00fc,0000,0000,0000,controller=rd_real,fault=0 pulser:rd_bench:mode=periodic,p=1,phase=0,armed=0,done=0,nf=1 relay:rd_in:cur_out=1,next_out=1 wire:w__rd_bench__rd_in:cur=1,nxt=1 wire:w__rd_in__rd_real:cur=1,nxt=1 admit:policy=admit_candidate_min_firstreceipt_v1,fact_capacity_fault=0,receipt_capacity_fault=0,capacity_fault=0 claim:w=1,s=1,digest=ee,pkey=0.1.1.2.3.4,payload=SetRotor:#?:1.2.3.4 claim:w=1,s=2,digest=3f,pkey=0.0.255.0.0.0,payload=SetRotor:rd_real:255.0.0.0 receipt:w=1,s=1,accepted=ee,apkey=0.1.1.2.3.4,epoch=1,outcome=Rejected(unknown_spinner) receipt:w=1,s=2,accepted=3f,apkey=0.0.255.0.0.0,epoch=2,outcome=Applied recognition:w=1,s=1,state=unambiguous recognition:w=1,s=2,state=unambiguous
A refused world beside it _patterns/wrl/refusable-divergence.refused.wrl
profile forge.world.core.v1
; a record that asserts a route the port table does not allow — refused by name, not by prose
[relay:r0]{sig_in, sig_out}
[door:d]{sig_in}
[orb:ob]{pose}
[r0] --sig--> [d]
[d] --sig--> [ob]✗ WRL_ILLEGAL_PORT_PAIR — d (Door) has no out-port sig_out for a SignalWire
Composes with the 11 chapters before it
The chain through this chapter — every earlier fragment, this one, and the links — seals to sem-8ae9abf1764308bf9f3fef7a108568a920abc1b486f151c18eb6e944e964451e: 37 objects, 36 edges (was 34 / 33; every earlier object and edge is still present — checked, or the build refuses).
Links only the chain carries
[cc_grant] --sig--> [rd_in]
How to read this board
Five kinds of object, two kinds of wire, and one band per Part of the book. Signal flows left to right: it starts at a clock, travels through relays, and ends at a door — or turns a spinner, which drives an orb. Nothing below is the book's own vocabulary; each line is quoted from where the definition lives.
| shape | is | and so |
|---|---|---|
| a clock; the only source of signal | Every signal on the board starts at one of these. Nothing else can make one. | |
| a pass-through, so signal can travel | One arrives, any number leave — a relay that fans out is the board's router. | |
| a sink; signal arrives and stops | It latches what reached it and passes nothing on. A door is where a path ends. | |
| rotation: takes signal, drives a pose | The only object on the board that holds a value a claim can rewrite — and only if its config says configurable. | |
| the thing that gets moved | It is driven, never driving: an orb is what you watch to see whether anything happened. | |
| not a WRL role — the book's own drawing of the receipts in the epoch's Film | It counts what the run admitted, and turns red on a Rejected outcome. | |
| SignalWire | signal: a sig_out to a sig_in | Legal from a Pulser or Relay, into a Relay, Door or Spinner. This is how the board moves. |
| SocketControl | control: a socket to a pose | Legal only from a Spinner into an Orb. At most one may land on any input port — fan-in is a typed refusal. |
Hover any object for what it is, which chapter put it there, and every field of its line in that epoch's Film — split into what it is doing now and how it was built. Click to pin the readout, then click a wired name to follow the signal. The field definitions come from TRVM/forge/film.py (the emitter), TRVM/forge/forge_state.py (nf, derived from the decoded counter and never from t), TRVM/forge/lower_e2a.py (the commit/react law), TRVM/FORGE_SEMANTIC_IR_v1_MEASURE.md §1.3; the shapes from WRL/learn.html and WRL/docs/spec/README.md. The build refuses if a Film emits a field this key does not explain.
The board so far: one band per Part, signal flowing left to right; relays that fan out are routers, doors are switches, pulsers are clock domains. Hover an object — or click the board and walk it with the arrow keys — for its role, its Part and what it is wired to. This board is the chain’s sealed shape; no Film drives it, so it has no state to report, and the whole board in the conclusion is where every object’s state is read epoch by epoch. Wheel zooms · drag pans · double-click fits.
Syntax — quoted from the tree at build time
The first tamper in the negative corpus — the record lies about its own world id WRL/test/projection-negative-vectors.json:7
"name": "a-lying-semantic-world-id",
"why": "The record asserts a world id its own artifact does not hash to.",
"base": "named-relations",The corpus's own rule for consumers (verbatim from the fixture's note) WRL/test/projection-negative-vectors.json:3
"note": "Negative vectors for the D8.19 projection wire. Each entry is a complete tampered record, stored as final bytes rather than as an edit recipe, because a recipe that matches nothing is a fixture that passes while asserting nothing. A consumer MUST check that `wire` differs from the named `base` in projection-vectors.json before trusting a refusal, and MUST require a refusal for every vector. `refusal_codes` records what the reference verifier produced; whether a code is normative is an open question, so a consumer should report code disagreement separately from the refusal itself.",
Forces
Recomputing claims costs a receiver work it could skip by trusting a flag. A negative corpus is only evidence if each tamper actually differs from its base — a recipe that matches nothing is a fixture that passes while asserting nothing. And two refusals can both be drift: agreement on a refusal is weaker than agreement on the bytes.
Applicability
Any format with more than one implementation: wire protocols, certificate formats, manifests, the projection vectors between WRL and TRVM Forge. Not for a single implementation that can only agree with itself.
Transformations
- adding a verifier in a third language
- adding a tamper to the corpus (with its base named)
- downgrading a projection in-band, so the receiver sees the downgrade as a claim
- a flag or a prose note that a receiver is asked to trust
- a fixture that is an edit recipe rather than final bytes
- collapsing two refusals into one because they agree
A refusing transformation is not one that is discouraged: it is one that, applied, makes the invariant above false. The word is the tree's, and it is the same word the join uses.
Consequences
Interoperability becomes a property with a witness: two repos, two languages, one corpus. The remaining honesty is in the corpus's own note — code normativity is open — and in WRL's handoff warning that two implementations can both have drifted.
Failure mode it answers
Replica Theater — Calling independent mutable copies 'the same thing'. Paid for at: CLAUDE.md: the served box-and-box copy is a MANUAL COPY and nothing syncs it
Witness
Source identity: WRL/test/conformance.mjs · shape side-effect · evidence kind constructive_witness · rung in_tree (STACK_COMPLETION.md:73; two verifiers in two languages (WRL js, TRVM Forge python))
Execution identity: 2026-09-11T15:25:45.285Z on PX13 · bytes e1f1e313eefe0001… · repo HEAD 32160fec77a1
Not staged on this site: the page cannot run this witness. It runs from the command line: node test/conformance.mjs in WRL.
Counterexample
Fixture WRL/test/projection-negative-vectors.json: 15 vectors, each expected REFUSED.
What to take away
- from the animationA tampered record is refused by both verifiers, and each names what it refused.
- from the syntaxTampers are stored as final bytes, not edit recipes, because a recipe that matches nothing passes while asserting nothing.
- from the literatureContent addressing (Merkle, Nix) makes the seal; the contribution here is the refusal name on the wire and the shared negative corpus across two implementations.
- from the witness924 conformance checks ran today; this page cannot run them yet (the suite is not staged), and says so under Witness.
Prior art — and what is not claimed
| work | relation | what it shares | where it differs |
|---|---|---|---|
| Content addressing; Nix | antecedent | divergence is detectable because names are derived from content | detection is the antecedent; agreeing on the NAME of the refusal is the part under test |
| WRL/PACKET_README.md:109 — 'refused by BOTH sides' | partial overlap | the tree's own wording for the two-sided requirement | WRL/HANDOFF_D8_PATH_B.md:1424 warns that two refusals can both be drift; two-sidedness is necessary, not sufficient |
Novelty not claimed. Detecting divergence by hash is standard. 'Agree on the name of every refusal' is STACK_COMPLETION.md:73's wording and is NOT verified by this build.
Realizations in the tree
- WRL/relation-v2.js:2363 deriveRuntimeProjection
Relations with other patterns
Identity Is a Seal WITNESSED · Meaning Is a Hash WITNESSED · Projection, Not Duplication WITNESSED