Pre-registered — not yet run. Two small open-weight models from different families, with different tokenizers. The sender reads a change and the rules once; the receiver must make the EXP 005 gate decision from the sender's KV cache, mapped into its own, without a forward pass over that context. EXP 008 measures whether that matches text re-prefill closely enough, and fast enough, to be worth having, on public baselines only. Written, hashed and published before the counted run. Nothing in this record may change after publication; a later change is a new, dated amendment, refuted and published first, and it resets the not-before.
The question
On the 60 EXP 005 changes and 140 new EXP 008-X changes, can a receiver model from another family, with another tokenizer, make the EXP 005 gate decision from a sender's mapped KV cache, with no forward pass over the context, nearly as accurately as text re-prefill, and faster once the mapping time is counted?
A lab handoff the factory could adopt, not a measurement of the factory: no KV-compatible sender-receiver pair is deployed on the floor today. The local decoders the factory runs are hybrids (some layers attention, some recurrent or feed-forward only), and their non-attention state has no published mapping. Where this sits in the longer plan: the factory-intelligence horizon.
The changes
- 60 EXP 005 changes (c001..c060; 30 RED, 30 GREEN). Reused by sha256 assertion only: the builder refuses any other corpus, inputs, labels or rules on disk. Corpus sums sha256
a83b222a1a4a64cc81ac755c827a47009baa2bb91b036e351e71422cc8d526a9, inputs6bfb2b8d52376cbd22c8a34f5f986fe67ad68a0c587da862ba6b56e77e966a34, labels36af1422755e56af56f4af267411a4a8e6535d08e6fc9d7aa3734aa005e4412a. - 140 EXP 008-X changes (c061..c200; 70 RED, 70 GREEN). Authored to the EXP 005 family quotas, labelled by bce, with a blind second pass and an overlap fence against EXP 005; hashed before this record. Sums sha256
f0199c9d0209900012c25c28fe1e2ef755de725e09cc3411b6260d923e47b77e, labels5068ef5ea06aafe7ec508d313779ba1705f2362356bc3b51ac39c4b148883d62. - 200 items are run. Every claim and validity gate is computed on the 175 items not seen before this record (136 of the 140 EXP 008-X items and 39 of EXP 005's c021–c060). c001–c020 and c029, c081, c097, c112, c144 were seen (see exposures and limits): they are run in the counted run but excluded from P1, S1–S3 and every gate, and reported separately. If the refute of this record (or a dated amendment before the not-before) finds EXP 008-X invalid, by a label error or a leak through the overlap fence, the run uses the 60 EXP 005 items alone and is refute-only: a P1 that holds on the 39 analysed EXP 005 items (c021–c060 without c029) is reported as "not refuted", never as met.
- Seen before this record: c001–c005. run end to end in the harness smoke test (pair D1, strata S and L, arms A0, A1 and C1–C3) to check the plumbing, C1 against A0; their mapper readouts (A2a and A2b probabilities, unlabelled and unscored) were also viewed during port debugging; and c001 was run in the memory-footprint runs (D1 A2a and A2b; D1′ every arm), stratum L.
- Seen before this record: c006–c020. mapper readouts (A2a and A2b probabilities, unlabelled and unscored) viewed during port debugging, before freeze.
- Seen before this record: c029, c081, c097, c112, c144. used as the C2 donors of c001–c005 in the harness smoke test (pair D1, strata S and L) and of c001 in the D1′ memory-footprint run (c081). C2 reads the receiver out on the donor's own context with the question, so a receiver readout (p(YES) and decision, unlabelled and unscored) on each of them was recorded before this record. The stratum S smoke rows were not committed; their donors follow from the 200-item strata manifest and are the same five.
- Committed rows from before this record (all on seen items):
footprint-d1-L-c001-a2.rows.jsonl(D1; A2a, A2b; c001);practice-d1-L-01.rows.jsonl(D1; A0, A1, C1, C2, C3; c001, c002, c003, c004, c005);footprint-d1p-L-c001-a2.rows.jsonl(D1′; A2a, A2b; c001);footprint-d1p-L-c001.rows.jsonl(D1′; A0, A1, C1, C2, C3; c001).
Three lengths of context
One builder makes every context from hashed parts (manifest sha256 2b8746a8491a5e644ff470658c11afbe8ff86e79c9b7a1b3af67379655ae3ae5): S is rules + "\n\n" + diff (276–796 tokens), M is rules + "\n\n" + base/ + "\n\n" + diff (3159–3704), L is rules + "\n\n" + base/ + "\n\n" + distractor header + distractor lines + "\n\n" + diff (15744–16245). L is primary. L is padding: each L context is M plus the first lines of a public, lint-clean library file, sized to 16K tokens. The padding is 77–80% of every L context. L tests the mechanism at length, not a real factory context of that size. The padding is the start of lodash.js 4.17.21 (MIT, sha256 52f2358d3c8eccc8f030fab6acf868f46b8b88045898589391f1630d2e1ed95c). The lint found 0 problems in 600 contexts.
The models
| Pair | Sender | Receiver | Use |
|---|---|---|---|
| D1 | Qwen/Qwen3-1.7B at 70d244cc86cc (28 layers × 8 KV heads × 128; upstream) | unsloth/Llama-3.2-3B-Instruct at 006f5dcd1393 (28 layers × 8 KV heads × 128; unsloth mirror (approved 2026-10-01)) | primary |
| D1′ | Qwen/Qwen3-4B at 1cfa9a720891 (36 layers × 8 KV heads × 128; upstream) | unsloth/Llama-3.1-8B-Instruct at 4699cc75b550 (32 layers × 8 KV heads × 128; unsloth mirror (approved 2026-10-01)) | pre-stated fallback; replaces D1 only by the pair-lock rule |
| D2 | unsloth/Llama-3.2-3B-Instruct at 006f5dcd1393 (28 layers × 8 KV heads × 128; unsloth mirror (approved 2026-10-01)) | Qwen/Qwen3-1.7B at 70d244cc86cc (28 layers × 8 KV heads × 128; upstream) | reported only |
| D3 | Qwen/Qwen3-1.7B at 70d244cc86cc (28 layers × 8 KV heads × 128; upstream) | unsloth/gemma-3-1b-it at 5b11413a10db (26 layers × 1 KV heads × 256; unsloth mirror (approved 2026-10-01)) | reported only |
- Every model is pinned by Hugging Face revision and by the sha256 of every source and converted (BF16, MLX) file; pins.mjs --verify recomputes every hash before a run.
- Within every pair the sender and receiver vocabularies must differ (sha256 of the vocabulary): pins.mjs --verify throws otherwise, and its output is committed with the results of the counted run. A control pair that shares Llama-3 ids (SmolLM3-3B and Llama-3.2-3B) must make it throw.
- Byte-identity to the upstream weights cannot be verified: the gated upstream repos (meta-llama, google) mask its LFS sha256s. Only model.safetensors.index.json matches the upstream git oid. Llama-3.2-3B, Llama-3.1-8B and Gemma-3-1B are pinned from unsloth mirrors (2026-10-01).
- Pins file sha256
e485cbc114f859f4931f250acce73738597570e7f4d916e4cc0ce7aa9e2d84bb; MLX 0.31.2, mlx-lm 0.31.3.
Which pair is counted. After this record is frozen and before the not-before, A0 is measured for D1 on stratum L, with the frozen readout and the current render, on the practice set c001–c020 (seen items, excluded from every claim and gate). If D1's A0 gets fewer than 15 of the 20 right (accuracy below 0.75), D1′ (Qwen3-4B → Llama-3.1-8B) replaces D1, mechanically; otherwise D1 stays. The decision and its rows are written to pair-lock.json before the not-before. No other rule chooses the pair. An earlier 5-item D1 practice run (stratum L, an older render, c001, c002, c003, c004, c005) is not the lock test: its A0 answered ACCEPT on all 5 (3 of 5 correct). Applied after this record was frozen: D1's A0 on stratum L got 11 of 20 practice items (c001–c020) right, with 0 abstentions, below the bar of 15, so D1′ (Qwen3-4B → Llama-3.1-8B) is the counted pair. The rows and the decision are in experiments/latent-handoff/pair-lock.json. In the lock run, D1's A0 answered ACCEPT on all 20 practice items, so its 11 right answers are the 11 GREEN items. The record was edited after the lock run started: see the edits after the lock run started.
- D1: One Apple-silicon Mac (128 GB unified memory), MLX, BF16. Every arm of a pair runs on the same machine, so the TTFT ratios are within-hardware.
- D1′: The same Mac. No rented GPU is provisioned for EXP 008; if the Mac cannot run D1′, the run is reported as uninformative (pair lock failed), not run elsewhere.
- Memory: Measured peak memory on practice items c001–c020 only (and their C2 donors), per pair: D1 21.91 GB over A0, A1, A2a, A2b, C1, C2, C3, under the 24 GB design bound; D1′ 36.89 GB over A0, A1, A2a, A2b, C1, C2, C3, so its bound was raised to 48 GB on that measurement, before this record (24 GB would rule D1′ out by construction; 48 GB is the most the gate admits consistently: at 50% free a 128 GB Mac has 64 GB available, and peak + 16 GB must fit).
The decision
The gate question in the receiver's own chat template. The decision is the softmax over the two single-token answers at the first assistant position: REJECT when p(YES) / (p(YES) + p(NO)) ≥ 0.5. No sampling. An out-of-memory error, or a probability that is not a number, is an abstention and counts as a wrong answer for its arm. The question is EXP 005's: “Does this change break any of these rules?” followed by “Answer with exactly one word: YES or NO.” Readout sha256 8c4c78285bb6c09ec5ce3c560344a20985013fadef57faaf3e7dc5e4cab74f24; receiver chat templates by sha256: llama-3.2-3b 5816fce10444…, llama-3.1-8b e10ca381b1cc…, qwen3-1.7b a55ee1b16601…, gemma-3-1b 7de1c58e208e….
The arms
The transfer interface is transfer(senderCache, senderTokenOffsets, contextText) → receiverCache. A transfer may read the context text to align tokens; it may not run any forward pass over the context. The zero-prefill counter wraps the receiver: in a KV arm the receiver forwards exactly the suffix (the question and the chat-template tail) and nothing else, or the run fails.
| Arm | What the receiver gets |
|---|---|
| A0 | text re-prefill of the whole prompt |
| A1 | sender summary (<= 256 tokens, frozen prompt, lint-checked) as the context |
| A2a | Char-boundary token alignment plus a per-layer ridge map from sender to receiver K and V. Our extension of arXiv 2608.03893, labelled as ours wherever it appears. |
| A2b | Procrustes alignment, our simplified reimplementation of HeteroFold (arXiv 2609.32259), closed-form fit, without its output-aware calibration stage. Built from the paper's description: the authors released no code, so no authors' mappers were available at the freeze and none are used. |
| A3 | Reserved: a slot for any further transfer method behind the same interface. No method is assigned to it, and this record makes no claim about one. Using it needs a dated amendment. |
| C1 | the receiver's own prefix cache through the transfer plumbing; must match A0 at KL < 1e-3 |
| C2 | a deranged cache: the receiver's prefix cache of another item (seed 8008) |
| C3 | no context: the question alone |
| B | EXP 005's model-free baselines, run unchanged: heuristic lint 0.9833 and heuristic grep 0.7 accuracy on EXP 005's 60 items; on EXP 008-X by corpus-x/baselines-x.mjs. |
A2a and A2b are our own implementations: A2a is our extension of one published method; A2b is our simplified reimplementation of HeteroFold (arXiv 2609.32259), closed-form fit, without its output-aware calibration stage. No authors' mappers were available for either. A weak result from ours says nothing about the published methods themselves. transfer() is Engine.transfer in runner.py; its maths is kvmap.py (an MLX port of a torch reference). Calibration runs on the Mac (MLX, BF16) on public, MIT-licensed code text fetched by URL at pinned commits and checked by sha256, disjoint from EXP 005, EXP 008-X and the L distractor. No rented GPU (the pre-stated fallback when none is available); disclosed in limits. Mapper weights are hashed, not published (v1).
- A2a: our extension of arXiv 2608.03893 (per-head ridge, RoPE-stripped keys) to a cross-tokenizer pair
- A2b: Our simplified reimplementation of HeteroFold (arXiv 2609.32259), closed-form fit, without its output-aware calibration stage; built from the paper's description, the authors' repository had no released code, so no authors' mappers were available at freeze
The parity gate. p01–p20: segments of the pinned held-out public file in calib-sources.json parityHeldOut, minus every calibration and evaluation line; never an EXP 005 / 008-X item. Mapping: kvmap MLX port on the GPU (split-precision float32 matmul) vs kvmap torch reference, float32 CPU. Readout: receiver and cache in float32 on MLX's CPU stream (true float32). Pass: decision agreement 20/20 AND max |p_mlx - p_torch| <= 1e-3, for each mapper; any mismatch fails the run. The gate proves the PORT is correct. A float32 readout removes the receiver's own rounding noise (bf16 activations, reduced-precision GPU float32 matmul), which would otherwise dominate a 1e-3 bar regardless of the port; the run-time bf16 sensitivity is recorded separately as a descriptive property of the arms, never as a gate. Result at freeze: D1: A2a 20/20, max |Δp| 8.3e-6, A2b 20/20, max |Δp| 1.3e-5; D1′: A2a 20/20, max |Δp| 5.0e-6, A2b 20/20, max |Δp| 8.3e-6. Both pairs passed this gate before this record was frozen; whichever pair the pair lock chooses is read out with the mappers bound here.
- calib-sources.json gained only its parityHeldOut entry between the D1 and D1' calibrations; the calibration text (textSha256) is identical for both pairs.
- Footprint bounds (footprints.json): D1 at the 24 GB design bound (measured 21.9 GB); D1' alone raised to 48 GB on measurement (measured 36.9 GB with A2b on L).
- The shorter A2b labels in arms.mjs, calibrate.py, kvmap.py and mapper-freeze.json are hash-bound by the mapper freeze and stay as they are; the label above supersedes them.
Every file that still carries a shorter A2b label (each hash-bound, so it stays as it is, and the label above supersedes it): arms.mjs, calibrate.py, kvmap.py, mapper-freeze.json, mappers-D1.json, mappers-D1p.json, evidence/mappers-D1-attempt1-gpu-reduced-precision.json.
kvmap.py:6725630bc5c7150c47b0cd82bd3436d3d1ce0f0cc78182431e68de25d33ab1c5calibrate.py:501beee874d2403040430b76745c6c19046fb4455adc5caefb51b5ea1ce291b8parity.py:9943fd2afbb5c3d3c061fd2edc4f4a536dcd948fe5219b5f45ec88a54179c3fecalib-sources.json:2f9998352768492952665bb2a8b4594d6a8365fde03ccb8067ca453d4ef456b3mapper_freeze.py:dad71286cfc3ddf13d43a67b2ea8426122a5a493fa047393bd18a7481ea6836bmapper-freeze.json:d9ed0d6f3dd33c69478051c1fbdb4be1b4d7a1ba36641b0f125954fc0310e30bfootprints.py:6cbe3fac05d7fc7d42376411a8f7998b17b19f3920818005d89c68837946ee35footprints.json:886cab9ddfed1189bcd05ab3c9b1fb1705d682ded3c512f69f45f7907c8bbe3eserved.py:8e3c891d473e333c92dfde69403e3c3c2293d5904d087e3aaa9ef787c42d778fmappers-D1.json:a3f94751214dbd8e34787eb026f2bc951c381f43224fe412e45c3dd149b38605parity-D1.json:29a33e3d1f96a8a4d6fac3a6a87f6b014cd1a9bd05e3f0c6ff2996ab5e71a76abf16-decision-stability-D1.json:3c0d84d5fb4a0c0fbbd7d5444be7f28124dcccce3952b33636670e4396588005mappers-D1p.json:a5078a3bfaca7e0696054490baf75842849732466ec945e3602cdb8add659853parity-D1p.json:c761d42bbc95d15071c05308d64ff52665f930fbf7ca8400208281f5a0a31af5bf16-decision-stability-D1p.json:fdd3ef0bd4a476d4a8f423531dd9a26ed1e108a62acb66ea9551c78b2ff8d51b- Calibration text:
7b856f5100c972446d129096b0dd51e8c6aa5a9c3b359b8984245bcd6a8986e2(Mac-only calibration (no GPU account), per pre-stated fallback; Apple M5 Max, 128 GB; 125176 receiver tokens) - D1: mapper record
a3f94751214dbd8e34787eb026f2bc951c381f43224fe412e45c3dd149b38605, mapper weights73548d54c23c0dc954261adb64e1a2cfe1c0f270418acbefb87f6f07eeedb876, parity record29a33e3d1f96a8a4d6fac3a6a87f6b014cd1a9bd05e3f0c6ff2996ab5e71a76a - D1′: mapper record
a5078a3bfaca7e0696054490baf75842849732466ec945e3602cdb8add659853, mapper weights03133fd709afd0d1efd9ea2373d6a6fb2642571a6fc05ea1859469fd8c9948c6, parity recordc761d42bbc95d15071c05308d64ff52665f930fbf7ca8400208281f5a0a31af5 - Freeze record:
mapper-freeze.jsond9ed0d6f3dd33c69478051c1fbdb4be1b4d7a1ba36641b0f125954fc0310e30b. mapper_freeze.py refuses to write it unless the binding parity gate passes on the pinned mapper weights.
The claim: P1
On arm A2b, stratum L, the locked pair (D1, or D1′ by the pair-lock rule):
- Decision agreement with A0, item by item over the analysed items, has a two-sided 95% Wilson score interval whose lower bound is ≥ 0.90. An item where either arm abstains counts as a disagreement; the denominator is every analysed item.
- The ratio median(A2b receiver TTFT, mapping time included) / median(A0 TTFT), over the items where both arms answered and neither is timing-unstable, has a 95% percentile-bootstrap interval (10,000 paired item resamples, seed 8008) whose upper bound is ≤ 0.5. The sender's own prefill is excluded (in a handoff the sender has already read the context for its own work) and reported separately. Timing follows the protocol below. The excluded items are counted and reported; if more than 10% of the analysed items are excluded, the TTFT criterion is uninformative.
P1 holds only if both criteria hold and every validity gate passes. Refuting P1 is the expected outcome, and it is published the same way.
Secondary claims
- S1. On stratum S, neither A2a nor A2b reaches a 1.2× TTFT speed-up over A0 (median A0 TTFT / median arm TTFT, mapping included). Predicted to hold; it locates the crossover.
- S2. Round trip, on D1 and its reverse D2 only (A → B → A; not estimable if D1′ is locked, since its reverse is not pinned): decision agreement with A0 after the round trip is below the product of the two one-hop agreements.
- S3. An intrinsic signal (next-token KL, cycle-consistency error or attention-output cosine) predicts disagreement with A0 at AUROC ≥ 0.70 and beats KV cosine by ≥ 0.05. Recorded as "not estimable" if there are fewer than 15 disagreements.
Reported, never a gate.
- R1. Decision stability under bf16 rounding, reported for A2a and A2b on the locked pair, never a gate. At run time the receiver computes in bf16, where near p = 0.5 one logit step moves p by about 0.03. On the held-out parity items, float32-level cache differences (largest key difference 1.4e-4 on D1) left D1: A2a 20/20, A2b 20/20 decisions unchanged (max Δp 0.030 and 0.031); D1′: A2a 20/20, A2b 20/20 decisions unchanged (max Δp 0.019 and 0.025). The larger cache differences of a superseded reduced-precision D1 port attempt (largest key difference 0.025, read out on c001–c020) gave 19/20 (A2a) and 18/20 (A2b). The counted run reports, per arm, how many decisions sit within 0.03 of the threshold. Evidence:
bf16-decision-stability-D1.json3c0d84d5fb4a0c0fbbd7d5444be7f28124dcccce3952b33636670e4396588005,bf16-decision-stability-D1p.jsonfdd3ef0bd4a476d4a8f423531dd9a26ed1e108a62acb66ea9551c78b2ff8d51b.
Secondary claims are directional and decide nothing.
When a result is uninformative
- Global: A0 accuracy ≥ 0.75 on stratum L of the locked pair. Below it the receiver cannot do the gate, and the result is "small receivers cannot do this gate", not a test of transfer.
- Global: C1 matches A0, KL < 0.001 on every item; a C1 abstention counts as a mismatch. Otherwise the run stops.
- Global: zero prefill, the receiver's forwarded-token count equals the suffix length on every KV-arm item.
- Global: the seeded 10% re-run is byte-identical (see leakage fences).
- Per arm: MLX-vs-CPU-torch parity for that arm's ported mapper (above).
- Per arm: manipulation check, (arm accuracy − C2 accuracy) ≥ 0.15 on the stratum claimed, and |C2 − C3| ≤ 0.10 there.
Failing a global gate makes every result uninformative; failing a per-arm gate makes that arm's results uninformative. P1 needs every global gate and A2b's per-arm gates. Uninformative is never a pass.
score.mjs scores rows; the confirmatory analysis (the exclusions, Wilson interval, paired bootstrap, A2b-vs-A0 agreement, gates and the re-run comparison) is a script written after this record, before the not-before, that implements exactly the definitions here. It is added by a dated amendment that changes no other field, is refuted and published before any counted item runs, and resets the not-before.
Fences against leakage
- The runner reads only the contexts and the readout; an audit hook refuses any label, manifest, adjudication or second-pass file. score.mjs is the only step that reads labels.
- No calibration text shares a line with an EXP 005 or EXP 008-X base file or change (overlap-x.mjs --calibration).
- Iteration happens on practice items only. There is one counted run, append-only.
- A seeded 10% re-run: the 18 analysed items with the smallest sha256("8008:" + item id), run again on the locked pair, every stratum and every arm (c027, c034, c038, c054, c089, c096, c103, c111, c136, c153, c168, c177, c181, c184, c191, c192, c196, c198). Under the 39-item fallback the set is the 4 analysed EXP 005 items picked the same way (c027, c034, c038, c054). Decisions and readout probabilities (to 6 decimals) must be byte-identical. Timings are excluded from byte identity and reported separately. A difference makes the run uninformative.
- lint.mjs (EXP 005's) checks every context and every A1 summary; a summary that fails it is an abstention.
Memory, timing and spend
- Checked before every invocation and every item. It proceeds only when memory_pressure reports ≥ 50% free, available memory ≥ the practice peak + 16 GB, swap has not grown, no mlx_lm.server is resident, the 1-minute load is below the bound, and the pair footprint is within the bound. Otherwise it waits, backing off from 30 s to 10 min. It never stops or re-prioritises another process.
- Per item, the arm order is a seeded random permutation; each arm gets 1 warm-up and 5 timed repetitions and reports the median. The gate is read before and after each item; an item whose readings drifted is re-queued at most twice, then marked timing-unstable. TTFT includes the mapping time.
- Every arm row is also emitted as an ffr.v1 handoff event, validated against the vendored schema. Local compute is unpriced: its cost is recorded as unknown, with the reason local-unpriced, never as zero.
- Every paid call (a refute round, an API call, rented compute) is reserved before it is made; a reservation is refused when the committed total plus max(the largest call so far, $5, this call) would exceed $100. Never a $0 line; an unknown cost stays charged at its upper bound. Enforced in code (spend8.mjs). Stage 1 budget $40: Pre-registration refute $2, results refute $26, publication $2, and $10 held back that EXP 008 does not plan to spend: D1′ runs on the Mac or not at all. The counted run is local and unpriced.
- No counted item runs before 24 hours after the merge of the odin-rnd pull request that publishes this record as frozen. That time is recorded after publication; every counted item must start after it. Practice items do not wait for it.
Edits after the lock run started
The lock run started seconds after the record was frozen. The record on this page is not byte-identical to the one in force then: it was revised afterwards, in disclosure, wording and date fields only. One of those disclosures, a third exposure found by a refute, shrank the analysed set from 180 to 175 items (and the fallback from 40 to 39). The pair-lock rule, its bar, its practice set and the files the run used are unchanged and are checked against this record. The lock's committed record, pair-lock.json, lists every edit; its last note gives the sha256 of the record in force when the run started. The commit that held that record is not on a public branch.
- Run pairlock-d1-L-01 (A0 only, timing protocol: 1 warm-up, 5 reps) started 2026-10-02T05:05:50Z, 7 s after the record was frozen at b5543ab; c001-c015 wrote rows by 05:15:49Z, then the driving session ended and the run was killed while c016 was in progress (c016 had written no row). It was resumed at about 05:20Z for c016-c020 only, same run id and attempt 0, appending to the same rows file; the first 15 lines are byte-identical to before the resume (sha256 of those 15 lines cc2f044729e7eb5cf192f2c4f0423a20694173b67e6c354fe52d58d47fb2d54e). c016 was started twice; no item has two rows.
- c002 started at 05:09:58Z, about 3.5 min after c001 finished: the memory/load gate held the run between items (its readings are in the row's gate field).
- Because the resume named only c016-c020, the driver's timing re-queue check covered those five (none drifted, no attempt-1 rows); c001-c015 were not re-checked for timing drift. The lock reads decisions, not timings, so this does not touch the decision.
- After the lock run started, the record was edited in disclosure and wording fields only: exposure reasons and exposureEvidence, a third exposure (c029, c081, c097, c112, c144: C2-donor readouts recorded before the record, found by a refute; analysed n 180 to 175, fallback 40 to 39; none is in the practice set) with a fail-closed pre-record scan, the footprint statement (naming the C2 donors), pairLockResult (this lock's outcome, stated plainly in the record from these rows), the A2b label, the R1 wording, mapper notes, the analysis note, and pairLockEarlierPractice, which split the earlier-practice sentence out of pairLock and added that earlier run's own result (A0 ACCEPT on all 5, 3 of 5 correct; derivable from rows and labels committed before the record, first computed after the lock run). The operative pairLock text, the bar, the practice set, and the runner, readout, strata and scorer hashes above are unchanged and are checked against the record. The always-ACCEPT score (alwaysAccept above) was computed after the lock outcome and is kept out of the record.
- At publication (2026-10-02) the record was edited once more, in wording and date fields only: freeze.frozenOn (2026-10-02, the date the page carries), one sentence in the C2-donor exposure reason (the stratum S smoke rows were not committed; their donors follow from the strata manifest), and a mapper note that the record's A2b label supersedes the shorter hash-bound labels. experiments/latent-handoff/README.md, which the record pins, gained the full A2b label and a line naming the five C2 donors, so its hash in the record changed. arms.mjs and the other files under run.code are byte-unchanged.
- The hashes under run.code are the record's bound hashes, checked against the files on disk when this file is built, not when the run ran: the rows carry no code hash. Those eight files are byte-identical at b5543ab, where the run started, and at this build.
- The record in force when the run started is commit b5543ab, experiments/latent-handoff/preregistration.json sha256 d5b1f81db88b8e4c33c690075a888f837a726c023f1492084ace0ed865358e56; record above is the current record.
The practice set is 11 GREEN and 9 RED, so a receiver that always answers ACCEPT scores 11 of 20. Computed here, after the lock run, not part of the frozen record.
Amendment 01: the confirmatory analysis script
Amended 02 Oct 2026, before any counted run. The pre-registration's analysis field reads: “score.mjs scores rows; the confirmatory analysis (the exclusions, Wilson interval, paired bootstrap, A2b-vs-A0 agreement, gates and the re-run comparison) is a script written after this record, before the not-before, that implements exactly the definitions here. It is added by a dated amendment that changes no other field, is refuted and published before any counted item runs, and resets the not-before.” This is that amendment. No counted item has run: nothing of the counted run exists when it is written, and its tests use synthetic rows only. No field of the pre-registration changes. Its not-before is replaced by the later one below, as its analysis field requires.
The script is experiments/latent-handoff/analyse.mjs (sha256 bc7e0b560f7ac6b7a96c8b5e6528d9b5b0346102c98aaab0f1e68635b32fac2b); its tests are scripts/latent-handoff-analysis.test.mjs (sha256 9858ef4358326822b313800534852692d22a15cc64872eda352b03baca794bab). It reads the counted and re-run rows, the labels through score.mjs, the pre-registration, this amendment and pair-lock.json. Before it analyses anything it checks against its sha256 every file the pre-registration binds (its files and mapper code, the EXP 005 corpus sums, inputs, labels and rules, the EXP 008-X sums, the strata manifest, the pins, the readout, the pair-lock rows and the exposure and R1 evidence) and the script and tests this amendment binds. The amendment is published byte for byte as amendment-01.json, sha256 cf96ee3871282fdbf1a6b6d3b4ab1381dcc4305ac992e0a366f6f044bfb49f83; each clause there quotes the pre-registration's own words beside its implementation.
- exclusions (
corpus.analysed,corpus.fallback): The analysed items are every labelled item (score.mjs's labels, 200 items) minus corpus.exposedItems, asserted to be the record's count (175). Every claim, gate, secondary and descriptive figure is computed on them. The seen items are run and reported separately (seenItems: accuracy per stratum and arm), and enter nothing else. The 60-item fallback is not implemented: the pre-registration's refute did not trigger it, so it can now be triggered only by a dated amendment before the not-before, which would carry its own analysis of that run. - one-run (
leakageFences.2): The counted run is exactly these run ids on the locked pair (read from pair-lock.json): counted-d1p-S-01, counted-d1p-M-01, counted-d1p-L-01; the re-run is rerun-d1p-S-01, rerun-d1p-M-01, rerun-d1p-L-01. Any row of another run id or pair is refused. Any row of another stratum, a duplicate attempt or a row for an item outside the run is refused too; a refusal stops the analysis (it is not a gate result), and its cause is disclosed and settled by a dated amendment before any result is read. The latest attempt counts per (item, arm); the driver re-queues whole items, so the arms of one item come from the same attempt. The run is analysed once, when it has finished or stopped; a paused run is resumed under the same run id first. Global gate complete: per stratum, the latest timing attempt of every (item, arm) exists for all 200 items × the 7 stage 1 arms (A0, A1, C1, C2, C3, A2a, A2b) in the counted run and for the re-run items in the re-run; an abstention is a row. A gap (for example, a run the runner stopped on a C1 mismatch) fails it, and then nothing else is computed: the result is uninformative. - not-before (
notBefore): The not-before is 24 hours after the GitHub mergedAt of the odin-rnd pull request that publishes this amendment, passed to the script as --amendment-merged-at. Every row of the counted run and of the re-run, of every timing attempt (a superseded attempt included), must have its item start (the memory-gate reading taken before the item, gate.ts) after it; otherwise the global gate not-before fails and the run is uninformative. - a0-accuracy (
validityGates.0): A0 on stratum L, analysed items, scored by score.mjs (an abstention is a wrong answer): passes when 100 × correct ≥ 75 × n. When it fails, the result is reported with the record's own reading: small receivers cannot do this gate, not a test of transfer. - c1 (
validityGates.1): score.mjs's C1 check on every stratum, analysed items: every C1 row must be answered, with klVsA0 < c1KlMax (0.001) and the same decision as A0 on that item; a C1 abstention is a failure. The gate passes only if all three strata pass. - zero-prefill (
validityGates.2,interface.rule): For every answered row of a KV arm (C1, C2, A2a, A2b) on the analysed items, every stratum: the sum of the receiver's recorded forward calls (forwardCalls) equals suffixLen. Abstained rows have no forward count; they are counted and reported. - rerun (
validityGates.3,leakageFences.3): The re-run set is recomputed (the analysed items with the smallest sha256("8008:" + id)) and must equal the record's list. For every stratum, item and arm of the re-run, the key (abstain, decision, pYes to 6 decimals, pYesBin to 6 decimals) must equal the counted run's, string for string. Timings are not compared. Any difference fails the gate. - parity (
validityGates.4): Per KV claim arm (A2a, A2b): the record's own parity result for the locked pair (mappers.pairs.<pair>.parityBinding.<arm>.pass) must be true. A1 is a text arm and has no ported mapper: not applicable. - manipulation (
validityGates.5): Per claim arm (A1, A2a, A2b) and per stratum, on the analysed items: 100 × (correct(arm) − correct(C2)) ≥ 15 × n and 100 × |correct(C2) − correct(C3)| ≤ 10 × n. P1 reads A2b on stratum L. - p1-agreement (
primary.P1.criteria.0.statement): A2b and A0 on stratum L agree on an item when both answered and their decisions are equal; any abstention is a disagreement; n is every analysed item. The interval is the two-sided Wilson score interval with z = 1.959963984540054. The criterion holds when its lower bound ≥ 0.9. - p1-ttft (
primary.P1.criteria.1.statement,timing.rule): TTFT is the row's ttftMs: the median of the 5 timed repetitions, which for A2b is the receiver side (the transfer plus the suffix, mapping included) and for A0 the whole prefill. Included items: analysed items where A0 and A2b both answered on stratum L and the item is not timing-unstable there (a timing-unstable line of the run names it). If 100 × excluded > 10 × n the criterion is uninformative. Ratio = median(A2b) / median(A0) over the included items. The bootstrap draws 10000 resamples of the included items with replacement, each an index floor(u × m) used for both arms (paired), u from mulberry32 seeded with 8008; the 95% interval is the sorted resampled ratios at 0-based positions 250 and 9749. The criterion holds when the upper bound ≤ 0.5. The sender's own prefill (senderMs) is reported separately as a median over the included items. - p1-verdict (
primary.P1.rule,validityRule): In this order: any global gate failed → uninformative; an A2b per-arm gate failed on stratum L → uninformative; the agreement criterion failed, or the TTFT criterion was informative and failed → refuted; the TTFT criterion uninformative → uninformative; otherwise holds. When a gate makes the verdict uninformative, the two criteria are shown with their numbers but no holds value (not in force). Every other figure (S1, R1, the accuracy and timing tables) carries informative false when a global gate failed, or, for a claim arm (A1, A2a, A2b), when its per-arm gate on that stratum failed. - s1 (
secondary.0.statement): On stratum S, per arm A2a and A2b: speed-up = median(A0 TTFT) / median(arm TTFT) over the analysed items both answered and not timing-unstable there. S1 holds when both speed-ups are below 1.2. It is uninformative (no holds value) when any global gate fails or the per-arm gate of A2a or A2b on stratum S fails. Directional; it decides nothing. - s2 (
secondary.1.statement): The locked pair is D1′ (pair-lock.json), so S2 is reported as not estimable, as the record says. - s3 (
secondary.2.statement): The frozen runner (runner.py, hash-bound) records none of the three intrinsic signals and no KV cosine for a mapper arm (for a mapper arm it records only the YES and NO log-probabilities, lpYes and lpNo, not a next-token distribution), so S3 is reported as not estimable, with the count of A2b-vs-A0 disagreements on stratum L (also not estimable below 15). This amendment changes no runner to add them. - r1 (
descriptive.0.statement): Per arm A2a and A2b, per stratum, analysed items: the number of answered rows with |pYesBin − 0.5| ≤ 0.03, out of the answered rows, flagged informative only when every global gate and that arm's per-arm gate on that stratum pass. Never a gate.
The run. The counted run goes stratum by stratum in this order, then the re-run in the same order, each through arms.mjs (its timing protocol, seeded arm order and memory gate unchanged). --peak-gb is the measured D1′ practice peak in footprints.json (36.89 GB). A paused run is resumed under the same run id; nothing is ever re-run to change a result. Counted: counted-d1p-L-01 (L), counted-d1p-M-01 (M), counted-d1p-S-01 (S); re-run: rerun-d1p-L-01 (L), rerun-d1p-M-01 (M), rerun-d1p-S-01 (S).
The not-before. No counted item runs before 24 hours after the merge of the odin-rnd pull request that publishes this amendment (its GitHub mergedAt). That time is recorded after publication. This replaces the pre-registration's not-before, which it can only move later. If any item of the counted run or the re-run started earlier, the analysis fails its global gate not-before and the whole result is uninformative.
- The not-before time is an input to the script (the merge time). The script checks every item start against it; that the input is the true merge time is checked against GitHub by the results refute, not by the script.
- S2 and S3 are not estimable in this run (see clauses s2 and s3). Neither was a primary claim.
- The 60-item fallback has no analysis here (see clause exclusions).
- The tests use synthetic rows on real item ids with invented decisions, probabilities and timings; no counted data existed when this was written.
Amendment 02: the zero-prefill counter fix and a fresh counted run
Amended 09 Oct 2026, before any analysed item has run. In the runner, every arm resets the receiver's forward counter before it runs, except one call: when an item's seeded arm order puts C1 before A0, the runner first computes A0 once, untimed, as C1's reference, and reset the counter only after that call. Its zero-prefill check then also counted the previous item's last arm, and stopped the run with a false zero-prefill violation. The model computation was unaffected (that call builds a fresh cache); only the count was stale. The first item after a process start has an empty counter, so it passed. The first counted attempt (counted-d1p-L-01) stopped 9 times, each time at that reference A0. The excesses over the prompt were 24 tokens five times, 54 three times and 15811 once, and each equals the previous item's last arm: a KV arm's 24-token suffix, C3's 54-token prompt, or a whole A0 prompt (that stop read 31624 tokens against a 15813-token prompt, after an item that ended on A0).
The fix. engine.receiver.reset() is called immediately before the untimed reference a0() in run_item (the existing reset after it is kept). Nothing else in the runner changes. A regression test, test_the_counter_does_not_carry_over_into_the_next_items_reference_a0 in experiments/latent-handoff/test_runner.py, covers it: Item N ends on a text arm, so its forward calls stay in the counter; item N+1 puts C1 before A0. The reference A0 must be checked on its own calls only. It fails on the old runner (a zero-prefill violation on that A0) and passes on the fixed one. The record binds runner.py by sha256, and its own rule reads: “Written, hashed and published before the counted run. Nothing in this record may change after publication; a later change is a new, dated amendment, refuted and published first, and it resets the not-before.” So this is a dated amendment. It rebinds experiments/latent-handoff/runner.py (95152adafb73 → 6d41e10b9670), experiments/latent-handoff/analyse.mjs (bc7e0b560f7a → a8013f13d72c), scripts/latent-handoff-analysis.test.mjs (9858ef435832 → 5d2fb88f7d2c); every other bound file is unchanged. analyse.mjs binds this amendment (its pin, the pre-registration as parent and amendment 01, by sha256, as the prior amendment), checks runner.py at the hash rebound below with every other file the record binds unchanged, reads the -02 run ids, and takes the not-before from this amendment's merge. Every statistical clause of amendment 01 is unchanged, byte for byte.
The run. Counted: counted-d1p-L-02 (L), counted-d1p-M-02 (M), counted-d1p-S-02 (S); re-run: rerun-d1p-L-02 (L), rerun-d1p-M-02 (M), rerun-d1p-S-02 (S). The attempt counted-d1p-L-01 ran under the old runner and recorded 133 rows (19 items × 7 arms), on c001–c019 only: seen items, which corpus.analysed excludes from every claim and gate. It is void. Its rows are never scored and never analysed (the analysis refuses its run id), and no score or analysis of them exists; they were read only to diagnose the stops (the token counts above). Each stored row passed its own zero-prefill check after its own reset; the 9 stops were false positives of the mechanism above. They are disclosed with it here and on the results page.
The not-before. No counted item runs before 24 hours after the merge of the odin-rnd pull request that publishes this amendment (its GitHub mergedAt). That time is recorded after publication. This replaces amendment 01's not-before, which it can only move later. If any item of the counted run or the re-run started earlier, the analysis fails its global gate not-before and the whole result is uninformative.
- The void attempt stopped 9 times and was resumed after each stop under the same run id: the scheduler wrapper treated a stop with progress as a pause. A stop on an error now ends the run and is escalated, never resumed; that wrapper lives outside this repository and is not bound here. The attempt ended when the host restarted; no row of c020 or a later item exists.
- Under the old runner an item with C1 before A0 could complete only as the first item after a process start, so the void attempt's items are not a random sample of arm orders. Under the fix every item resets the counter first, so this pattern cannot recur; the void rows enter nothing.
- The not-before time is an input to the script (the merge time). The script checks every item start against it; that the input is the true merge time is checked against GitHub by the results refute, not by the script.
- The regression test runs the real run_item on a fake engine, without any model.
The amendment is published byte for byte as amendment-02.json, sha256 8d5f1f0761118d1ecc886f97cbc0c9716a295e19ad56b70381cce1c9ea41f6ec; each clause it touches quotes the pre-registration's or amendment 01's own words beside the change.
What this does not establish
- L is padding (see strata): it tests the mechanism at 16K tokens, not a real factory context of that size.
- The mapper calibration runs on one Mac, not on a rented GPU; the torch reference for the parity gate is CPU torch on the same machine.
- Llama-3.2-3B, Llama-3.1-8B and Gemma-3-1B come from public unsloth mirrors. Their byte-identity to the gated upstream weights cannot be verified (the upstream repositories mask their file hashes); only model.safetensors.index.json matches an upstream git object id.
- 200 items are run and 175 analysed; 39 and refute-only if EXP 008-X is set aside (see corpus).
- A lab handoff the factory could adopt: no KV-compatible pair is deployed on the factory floor today, so nothing here measures the factory itself.
- Two small models on authored changes and mechanical architecture rules; nothing here generalises to other tasks, larger models or other hardware.
- A2a is our extension of a published method and A2b is our simplified reimplementation of HeteroFold (arXiv 2609.32259), closed-form fit, without its output-aware calibration stage; no authors' mappers were available. A weak A2a or A2b result is ours and does not show that the cited methods fail.
- c001–c005 were seen before this record: run end to end in the harness smoke test (pair D1, strata S and L, arms A0, A1 and C1–C3) to check the plumbing, C1 against A0; their mapper readouts (A2a and A2b probabilities, unlabelled and unscored) were also viewed during port debugging; and c001 was run in the memory-footprint runs (D1 A2a and A2b; D1′ every arm), stratum L. They are excluded from every claim and gate (see corpus) and serve as the pair-lock practice set.
- c006–c020 were seen before this record: mapper readouts (A2a and A2b probabilities, unlabelled and unscored) viewed during port debugging, before freeze. They are excluded from every claim and gate (see corpus) and serve as the pair-lock practice set.
- c029, c081, c097, c112, c144 were seen before this record: used as the C2 donors of c001–c005 in the harness smoke test (pair D1, strata S and L) and of c001 in the D1′ memory-footprint run (c081). C2 reads the receiver out on the donor's own context with the question, so a receiver readout (p(YES) and decision, unlabelled and unscored) on each of them was recorded before this record. The stratum S smoke rows were not committed; their donors follow from the 200-item strata manifest and are the same five. They are excluded from every claim and gate (see corpus).
- Under bf16 at run time, cache differences at the level of one rounding step can move p(YES) by about 0.03 near the threshold, enough to flip a borderline decision; this is reported as a descriptive property (R1), not hidden and not gated.
- The parity gate is judged in float32 (a float32 CPU readout of the MLX port against a float32 torch reference) because it tests the port, not the run-time precision; MLX's float32 GPU matmul runs at reduced precision, which made the first attempt fail at about 2e-3, and the port now uses a split-precision matmul, with a regression test.
- The timings come from one machine under whatever load the memory gate admits; they are recorded with the gate readings, and their ratios are within-hardware only.
Provenance
This page is rendered from preregistration.json, the committed record at experiments/latent-handoff/preregistration.json, whose sha256 is 638d1dda53e8ae6c9c129d34e6b83fa6642f7ef60b30de8da71e7660082f7f6c. The site publishes that file byte for byte, and a repository test re-renders this page from it and fails if they differ. A validator rebuilds the record from the harness files and refuses any difference; it pins 30 files by sha256.
The counted run has not started. The results, when they exist, will be judged against this record as published, and reported as they come out.