Pre-registered — not yet run. Does hot load, unload and reconfigure of research components leave the harness indistinguishable from a fresh process, and does every unmet need show up as a named inactive component instead of silently doing nothing? 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
- In time. When components route every runtime mutation through ctx.effect, does hot load, unload and reconfigure leave the harness observationally equivalent to a fresh process with the same active set?
- In space. Does an unmet need always surface as `inactive: missing <key>`, and never as silent inertness?
The kernel is our kernel implementing Cordis semantics: a small subset, written here, that uses Cordis (github.com/cordiverse/cordis) as the semantic reference only. It is not a dependency, and nothing here claims Cordis's guarantees. The kernel is pinned by sha256 in the file map. Inspired by arXiv 2608.25512.
The components
lint: EXP 005's lint, as a componentgrep: a pattern search servicemlx.model: a local model server child process: Llama-3.2-3B, swapped by reconfigure to Qwen3-1.7B; EXP 008's pinned weights, read only; its prefix cache is an internal effectyesno-gate: EXP 008's readout at stratum Smemo-cache: decisions keyed by item sha256spend-counter: a stub with no network access
The items
200 items: EXP 005 (60 items) and EXP 008-X (140 items). Corpus identity sha256 4d0273836696f751272276fe1004ebfc8312d5397fbdaa09ee58232ac48c5acd; sha256 over the ordered "set\tid\tstateSha256\n" lines, computed by harness/services/corpus.mjs, which asserts every item state by its committed sha256. The study measures equivalence, not accuracy: the runner never opens a labels file, and earlier exposure to these items cannot bias an equality.
The arms
| Arm | What runs |
|---|---|
| R0 | A fresh process per (active set, pin, item), cached: the reference. |
| H1 | One long-lived kernel. Each trial runs 20 seeded operations (at least 25% of them reconfigures, including pin swaps) with 40 evaluations interleaved. |
| H2 | The same component specs on a plain registry with hand-written register and unregister, written by a blind author (secondary). |
| K1 | H1 plus 12 pre-registered planted leaks (for example a raw setInterval, a listener outside ctx, a stale prefix cache after a pin swap, an MLX child that was never reified): the teeth. |
| K2 | The K1 effects routed through reifying coeffects. |
The schedule
- seed = sha256 of the merge commit id of the odin-rnd pull request that publishes this record as frozen (the 40-character lower-case hex string, UTF-8). The seed is unknowable when the record is frozen.
- 400 trials of 20 operations (at least 25% reconfigures) with 40 evaluations each.
- Block size
10trials; per-trial wall time199s. Trials run in window-held blocks of blockSize, in seed order. A block that cannot start within the max-wait is retried; the trials themselves never change.
The claims
P1, equivalence in time. H1 diverges from R0 in 0 of n = 400 trials. Any difference, after any operation, in a decision, in p to 6 decimal places, or in any inside-boundary snapshot field: the component registry and statuses, provided services, listeners, timers, memo keys and prefix-cache keys. With 0 divergences in 400, the 95% Wilson upper bound is 0.95% (at most 1% from n = 381). Refuted by: Any single divergence.
P2, soundness in space. On the blind-authored corpus of 120 configurations, the kernel's census shows 0 silent-inert components and 0 false-inactive components. A component the census reports active although, by the corpus construction, a need it has is unmet (or its provider was withdrawn). A component the census reports inactive although, by construction, every need it has is met. absent ⇔ excluded: the kernel never loads a plugin that is not enabled and unloads a withdrawn one, so either is absent from the census, which the corpus calls "excluded". Every other status compares one to one (analysis/SPEC.md §P2). Refuted by: Any silent-inert or false-inactive kernel configuration among the 120.
P2 was computed before registration
P2 has no seed and is deterministic, so its outcome was computable before this record. It was computed once, before registration: while validating the pipeline on the real corpus, the instrument author ran it a single time, with output to the terminal only and nothing committed. What it showed: the kernel was correct on 120 of 120 configurations, with 0 silent-inert and 0 false-inactive; against the baseline, McNemar b = 60, c = 0. P2 is registered for the record. Its evidential weight rests on the blind authorship of the 120 configurations (written by a history-free agent from the corpus spec alone, fence audit above) and on the real, unmodified filter baseline, not on any claim about an unseen outcome. Only P1 (seeded from the merge commit of this record) and the validity gates are predictive: they test outcomes that are unknown when this record is frozen. Source: experiments/composable-harness/analysis/SPEC.md §P2 "Disclosure".
- The 120 configurations (60 faulty, 60 clean): tree sha256
48546709c0c64c2931e5151930225b5c1328bac06029023a0df48ec3515756d8(123 files), spec sha2561cce4517d80ecdfac6d4fd8903f47587962c523f3d3e1b2408a84ab4bb2852ba. Written by a history-free agent from the spec alone; fence audit FENCE-HELD (author A) and FENCE-HELD (author B). - Baseline. odin-agent's real extension filter and its proven-core floor, run unchanged at pinned odin-suite commits. Only its outputs and the source sha256s are published; the source is private. pre: commit
d6431af9bad7,extension-filter.ts20876c03901a…,proven-core.ts3c126d5a665c…; current: commit2d522f505380,extension-filter.ts20876c03901a…,proven-core.ts14ad55c5fd35…. At freeze it signalled 0 of 60 faulty and 0 of 60 clean configurations, and kept exactly the spec-enabled set in 120 of 120. An exact two-sided McNemar test on kernel-correct against baseline-correct per configuration: the binomial test on the discordant pairs (b, c). Secondary; it decides nothing.
Secondary, deciding nothing
- S1. H2 leaves residue (any inside- or outside-boundary difference from R0) in at least 10% of trials.
- S2. The outside-boundary probes (active handles, child pids, open files, MLX active memory, the temp directory) catch K1's unreified leaks and show 0 in K2.
- S3. H1 and R0 time-to-ready. A block that recorded a memory-window breach has its S3 timings excluded and counted; nothing else is excluded for a breach.
Secondary results decide nothing; they are reported as they come out.
When a result is uninformative
- K1 detects at least 11 of its 12 planted leaks.
- A seeded 10% re-run of R0 is byte-identical.
- R0 is self-equivalent across a process restart.
- pins.mjs --verify passes, and the kernel sha256 is in this record's file map.
- Every measured block held a memory-window lease (its sidecar is committed with the run).
If any gate fails, the result is published as uninformative, never as a pass.
The analysis
The confirmatory analysis is the pinned analyse.mjs, frozen in this record with its synthetic-row tests. No analysis is added after freeze; a change to it is a dated amendment that resets the not-before. Spec experiments/composable-harness/analysis/SPEC.md (sha256 8a1a48269b1a49354bdcab968f740745b8085a395e1749b6e886350535eb1558). File experiments/composable-harness/analysis/analyse.mjs (sha256 436b434ff3ef59fa082ea1f991a1e52181a2e1480ec7e55c2e086354cea0394d), tests scripts/composable-harness-analyse.test.mjs (sha256 a69c72cf6868b2c2948ae01326933ee6645f7b9c36f1e545b35d8bd35aa4de90).
- P1: count trials with any divergence (definition above); report x of 400 and the 95% Wilson upper bound (z = 1.959964).
- P2: per configuration, map the census onto every registered name (absent ⇔ excluded) and compare with the corpus "expected"; a configuration's outcome is its worst plugin outcome, silent-inert > false-inactive > mislabelled > correct (analysis/SPEC.md §P2).
- McNemar: kernel-correct against baseline-correct per configuration; exact two-sided binomial on the discordant pairs (b, c). The baseline row is correct when a clean configuration is not signalled and a faulty one is.
- S1: share of H2 trials with any residue. S2: per planted leak, detected in K1 and absent in K2. S3: median time-to-ready per arm, breach blocks excluded and counted.
- Gates: evaluated first; any failure makes the run uninformative before P1 or P2 is read.
Fences
- Seed: sha256(prereg merge commit), as above.
- One counted run: iteration happens only on practice seeds. The counted run is single and append-only.
- Frozen here: the probe observation set, analyse.mjs and its synthetic-row tests (EXP 008's lesson: an analysis amendment resets the clock).
- Synthetic configurations only: no tenant names.
- Live arms only: no replay arms.
- No other experiment's files change: EXP 005–008 stay untouched, enforced by the frozen-path census test.
Memory, spend and the not-before
- Every measured block runs under
mac-memory-window.sh run --label <block> --max-wait 12h -- <block command> (odin-labs): a window opens when free memory ≥ 50% and load1 < 8 for 3 consecutive readings, 60 s apart; free < 50% or load1 ≥ 12 during a block: recorded, never acted on; one measured run holds the lease machine-wide. Unload memory tolerance0.35GB. - Inference is local and unpriced: its cost is recorded as unknown, with the reason local-unpriced, never as zero. Paid spend is refutes and lane overhead only, under the program cap.
- No attempt of the counted run starts before 24 hours after the merge of the odin-rnd pull request that publishes this record as frozen. This covers every attempt: a restarted, resumed or re-queued block is an attempt and is held to the same time. The time is recorded after publication. Practice seeds do not wait for it.
What this does not establish
- n = 400 supports "at most 1% of trials" (95% Wilson upper bound 0.95% at zero divergences), not zero.
- One kernel, one language, one Mac.
- Equivalence says nothing about accuracy.
- The P2 corpus is synthetic, written from a spec whose fault classes we chose; the real filter keeps exactly the spec-enabled set in all 120 configurations, which shows the spec models its enable rule, not that the classes are representative.
- The baseline filter has no notion of needs, so it is the no-census condition, not a competing census.
- P2's outcome was computed once before registration (see the P2 disclosure): P2 is registered for the record, its weight rests on the blind authorship and the real filter baseline, and only P1 and the validity gates are predictive.
Provenance
This page is rendered from preregistration.json, the committed record at experiments/composable-harness/preregistration.json, whose sha256 is d25f7f3fe9f802b19ed5caa9a437126109b20f83fe993086854a20bb902e7e7e. 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 188 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.