Abstract
A model that keeps adapting after deployment needs a limit on how far it can drift, and the limit has to be something a program can check. ML Weft treats each model as a cell. The cell proposes candidate weight updates, and an update is committed only if three things hold: the candidate’s Frobenius distance from a saved baseline is within a radius , a resource budget covers the step, and a provenance watermark held in a frozen core is still intact. This paper states the gate, explains why it measures distance from a fixed baseline rather than comparing sizes or bounding each step, and reports experiments that run the project’s tested code. A norm-preserving move passes a size comparison at all 37 angles we tried, while the distance gate rejects 34 of them. Over 10 seeds and 12 generations, a 256×256 cell cuts its target error by 72%, with exactly zero drift in its frozen core and full watermark retention. Sweeping shows the gate trading adaptation for proximity, as intended. The experiments also expose real limits. At the default radius the gate never binds. One of the two candidate lineages always wins. A rank-1 overwrite of the watermark passes the distance gate and is caught only by the watermark check. We report these as findings, not footnotes.
Keywords: adaptive models, AI safety, weight-space constraints, continual learning, provenance, watermarking
1. Introduction
Most deployed models are frozen. They change only when someone retrains or fine-tunes them, and the size of that change is rarely bounded by anything a program checks. Models that keep adapting online (to a user, a device or a task) are attractive, but they raise an obvious question: how far is the model allowed to move, and who checks?
ML Weft’s answer starts from a metaphor and ends in a predicate. The metaphor is that a model is a cell. It has a boundary, a protected core, a limited metabolic budget, and it reproduces by trying out variants and keeping the one that fits. The predicate is what makes the metaphor accountable. A candidate update is committed only if
where is a saved baseline, is a fixed radius, is the remaining budget and is the cost of the step. The same predicate is implemented in Python, C11 and JavaScript. Python and JavaScript are tested against one JSON file of conformance vectors—Python all twelve cases, JavaScript the six weight-update cases—and the C11 header is tested against hand-written copies of most of them (§5.5).
This paper makes four contributions:
- A precise statement of the cell contract: what a cell may change, how candidates are chosen, and the conditions under which a candidate is committed (§2–3).
- An argument for measuring distance from a fixed baseline rather than comparing weight sizes or bounding each step, with a construction that defeats size comparison exactly (§4).
- Experiments that run the tested implementation (§5): the size-comparison trap, the full cell cycle, a watermark threat sweep, a radius sweep, and cross-language conformance.
- An honest account of what the experiments do not show (§6), including three places where the current implementation falls short of the design.
The biological names (cell, mitosis, core, membrane, homeostasis) are the project’s vision language. They name the behaviour we aim for. In this paper each one is tied to the specific mechanism that implements it today, and none of them claims more than that mechanism does.
2. The cell
A cell owns one weight matrix inside a fixed shared-memory arena. In the current implementation weft/runtime/plasm sets , and the arena is 540,688 bytes:
| Region | Shape | Bytes | Role today |
|---|---|---|---|
| Header | u64 + f64 | 16 | generation epoch, tension |
| Focal workspace | float32 [256, 256] | 262,144 | the cell’s weights |
| Sympathetic ring | float32 [1024] | 4,096 | scalar telemetry array |
| Hippocampal lattice | float32 [64, 1024] | 262,144 | a recency buffer used for a novelty term |
| Reserved | bytes | 12,288 | lock storage; no synchronisation protocol yet |
The layout is specified as interface I4. Mapped CPU views share the bytes. Tensor reads copy explicitly, so “zero-copy” applies to the mapping and not to the whole experiment.
Core and periphery. The first rows of form the core, which is frozen. A plasticity mask is zero on core rows. On periphery rows it takes values in , scaled down for columns with large magnitude. Every update has the form , so core rows cannot change.
Provenance watermark. A unit trigger vector is supported only on core rows, and a target response has norm 3. Both are derived deterministically from a seed. Embedding applies a rank-1 correction so that :
Retention is checked on every candidate. The candidate passes if its response has cosine similarity at least 0.85 with , and its relative drift from the baseline response, , is at most 0.35.
Proposition 1 (periphery updates cannot move the mark). If is supported on the core rows and is zero on those rows, then .
Proof. . Every term vanishes, because off the core and on it. ∎
So under the cell’s own update rule, watermark retention is guaranteed by construction. The retention check guards against other writes: updates that skip the mask, and deliberate overwrites (§5.3).
3. One generation
Each generation, the cell proposes two candidates (two “lineages”) and keeps at most one.
- Propose. With inputs and target outputs , form the residual direction . The cautious lineage α moves along , and the exploratory lineage β along , where is Gaussian noise with scale . Both are masked and scaled by .
- Score the exact candidates. Each candidate is scored as plus times a normalised novelty term computed from the hippocampal lattice. The score is computed on the very matrix that would be committed, not on a proxy.
- Gate. The higher-scoring candidate is committed only if all of the following hold:
- the distance gate accepts it ( and );
- the watermark is retained;
- the tension bound holds;
- its target error is no worse than the parent’s.
- Regulate. A feedback rule adjusts . If tension is above the band , shrinks by 25%. If tension is below the band, grows by 10%.
In the current code, “tension” is not measured. It is defined as , and the tension bound requires it to be at most 85. Tension therefore adds a second distance cap of , independent of . We report this because it means the effective radius is , not .
4. Why measure distance from a fixed baseline
There are three natural ways to bound how much a model changes:
- Compare sizes: accept if . The original design notes did this.
- Bound each step: accept if relative to the current weights.
- Bound distance from a saved baseline: accept if . This is Weft’s gate.
Comparing sizes is not a bound on change. Two matrices can have identical norms and be arbitrarily far apart.
Proposition 2. Let satisfy and , and set . Then for every , and .
Proof. Expand both norms using and equal norms. The first gives times . The second gives times . ∎
At the candidate is , the furthest point on the sphere, and the size comparison still reports zero change. Experiment E1 runs exactly this construction.
Per-step bounds compound. If each step is limited to relative to the parent, then after accepted steps the model can be from where it started. Random steps typically reach , which still grows without limit. A bound measured from a fixed composes differently: every committed state lies in the ball , however many steps were taken.
Proposition 3. If every committed candidate satisfies , then every reachable committed state lies in , and at most updates are ever committed.
Proof. The first claim is the acceptance condition applied to each commit. Only commits spend budget, by exactly , and the precondition stops commits once the budget runs out. ∎
The price is that the baseline becomes something to protect. If can be rewritten, the bound means nothing. In Weft the baseline is held outside the update path, and the watermark lives in the frozen core of both and .
5. Experiments
All results come from papers/01-models-as-cells/experiments.py. The script imports the tested modules in weft/runtime/plasm and weft/runtime/invariants and writes results.json and the figures. Runs used commit a18fc40 on an x86-64 Linux CPU with Python 3.13 and PyTorch 2.15 (CPU build). Each run seeds PyTorch, and the cycle is forced onto the CPU, so the numbers below are reproducible. Apple MPS results have not been measured and are not claimed.
5.1 E1: equal sizes, large moves
We draw with , construct as in Proposition 2, and evaluate (37 cases) with .
The size change never exceeded , which is floating-point noise. The measured distance matched the closed form to within .
| Check | Accepted | Accepted beyond |
|---|---|---|
| Size comparison | 37 / 37 | 34 |
| Weft gate | 3 / 37 | 0 |
The gate first rejects at , where . This is the same case the interactive demo on w3ft.org shows with its Flip signs button.
5.2 E2: the cell cycle
We run the full cycle for 12 generations on each of 10 seeds with the default settings ().
| Measure | Result |
|---|---|
| Runs passing the cycle’s own checks | 10 / 10 |
| Final target error ÷ initial | 0.278 mean (0.276–0.280) |
| Core-row drift | 0 exactly, in every generation |
| Watermark cosine alignment | 1.0 minimum; response drift 0 |
| Proposals committed | 120 / 120 |
| Lineage chosen | α 120, β 0 |
| Largest distance from baseline | 0.463 |
| Tension range | 20.3–21.2, inside the band, so was never adjusted |
| Budget | 100 → 70 (12 commits × 2.5) |
| Wall time per 12-generation run | 95 ms median (CPU) |
The cell adapts steadily, and the frozen core and watermark behave exactly as Proposition 1 predicts. The table also shows what this configuration fails to test. The gate never rejected anything, the feedback rule never acted, and the exploratory lineage never won. Its update () is a strictly worse direction than α’s under this score, so selection between lineages is not exercised.
5.3 E3: the watermark under attack
We embed the watermark in a fresh matrix and apply perturbations of growing size , either through the mask (periphery only) or to all rows.
Periphery-only perturbations left the response drift at exactly 0 up to , as Proposition 1 requires. Unmasked perturbations were retained up to 12 (cosine 0.964, drift 0.281) and flagged at 16 (drift 0.375). The drift check fires before the cosine check, which first fails at 32 (cosine 0.813).
Targeted rank-1 overwrite. An attacker who knows the trigger can replace its response with one of their choosing, . The watermark check catches this: cosine alignment drops to −0.04. But the overwrite moves the weights only , so the distance gate at the default accepts it. Distance from the baseline limits how much a model changes, not which directions it changes in. Provenance needs its own check, and Weft runs both.
5.4 E4: the gate inside the loop
To make the gate bind, we rerun E2 with smaller radii. We report the error of the weights the cell actually holds at the end.
| Commits (of 12) | Held error ÷ initial | Largest committed distance | |
|---|---|---|---|
| 0.05 | 0 | 1.000 | 0 |
| 0.10 | 0 | 1.000 | 0 |
| 0.20 | 2 | 0.777 | 0.162 |
| 0.30 | 5 | 0.547 | 0.290 |
| 0.40 | 8 | 0.400 | 0.379 |
| 0.50 | 12 | 0.278 | 0.463 |
| 120 | 12 | 0.278 | 0.463 |
Every committed distance stays below , as Proposition 3 requires. Once a proposal is rejected, the next one starts from the same weights and the same residual, so the cell stops at the boundary rather than probing past it.
A reporting defect found by this experiment. run_weft_plasm_cycle reports final_target_error from the last candidate, whether or not it was committed. With it reports a ratio of 0.880, a 12% improvement, when no update was ever committed. With full acceptance the two agree. The table above uses the held weights. The defect is tracked as issue #63.
5.5 E5: one rule, three languages
The gate’s conformance vectors (weft/runtime/invariants/vectors.json) contain 6 weight-update cases, 4 tension cases and 2 metering cases. They include the matching-sizes trap, non-finite candidates, and budget and cost preconditions. Continuous integration checks all three implementations on every change:
| Implementation | How it is tested | Coverage |
|---|---|---|
Python reference (invariants.py) |
reads vectors.json |
all 12 cases |
Browser port (invariant-gate.js) |
reads vectors.json |
the 6 weight-update cases |
C11 header (weft_invariants.h), built with -Wall -Wextra -Werror |
hand-written copies of the cases | 5 of the 6 weight-update cases, plus tension and metering checks |
All three agree wherever they are tested. The C test does not yet read the JSON file and does not cover the non-positive-budget case. Running one corpus across Python and C is tracked as issue #42.
6. What this does not show
- Scale. The cell is one 256×256 linear map fitted to a synthetic target. Nothing here shows behaviour on a trained network, a language model, or a real task.
- Calibration. The default is about 260 times larger than any distance the default cycle reaches, and the tension cap (26) is 56 times larger. A useful must be set relative to the task, for example as a fraction of or from a held-out tolerance. We have not done that yet.
- Selection. With one lineage dominating by construction, the A/B mechanism is plumbing rather than evidence of selection. A real test needs lineages whose relative merit depends on the data.
- Tension. Tension is a function of distance, not an independent measurement of the cell’s state, and the feedback rule never acted in E2.
- Adversaries. The watermark is an integrity check against the cell’s own update path and simple overwrites. It is not a robust ownership watermark against an adversary who controls training. The distance gate does not stop a small, targeted edit (§5.3).
- Isolation. Shared memory gives a cell a fixed boundary in bytes. It is not process isolation, and nothing here stops another process with access to the mapping from writing to it.
- Hardware. No Apple MPS, Metal or other accelerator results are included. The Mac entry points in the repository are wrappers around this CPU path.
7. Next experiments
- Calibrate relative to task tolerance on a small trained network, and report accuracy against distance.
- Real periphery. Treat low-rank adapters as the periphery and a pretrained model as the core, so the gate bounds adapter drift.
- Meaningful lineages. Use two update rules whose ranking changes with the data, and measure selection.
- Measured tension. Derive tension from validation loss or another independent signal, and test whether the feedback rule keeps it in band.
- Mechanised proof. Prove Propositions 2 and 3 and the gate’s precondition order in Lean, against the conformance vectors.
- MPS runs. Repeat E2 and E4 on Apple Silicon, recording device, versions and tolerances.
Reproducing this paper
git clone https://github.com/Moissanite-Labs/weft && cd weft
git checkout a18fc40e31e71325aec507258fb80bb26f125c7c
python3 -m venv .venv && . .venv/bin/activate
pip install numpy torch matplotlib
python3 papers/01-models-as-cells/experiments.py # writes results.json and figures/
python3 -m unittest discover -s weft/runtime/invariants -p 'test_*.py'
python3 -m unittest discover -s weft/runtime/plasm -p 'test_*.py'
node --test weft/runtime/aywa/test_invariant_gate.mjsWall-clock times will differ by machine. Every other number in §5 should match exactly.
References
- ML Weft. Interface I4: shared-memory layout.
docs/interfaces/I4-shared-memory.md. - ML Weft. Claims register and safety index.
docs/corpus/. - ML Weft. Paper 0: ML Weft, an overview. https://w3ft.org/papers/overview/.
- Kirkpatrick, J. et al. (2017). Overcoming catastrophic forgetting in neural networks. PNAS 114(13).
- Hu, E. J. et al. (2022). LoRA: Low-rank adaptation of large language models. ICLR.
- Uchida, Y., Nagai, Y., Sakazawa, S., Satoh, S. (2017). Embedding watermarks into deep neural networks. ICMR.
- Mordvintsev, A., Randazzo, E., Niklasson, E., Levin, M. (2020). Growing neural cellular automata. Distill.
Cite this paper
@techreport{mlweft2026paper1,
title = {{Models as Cells: Self-modification bounded by distance from a saved baseline}},
author = {{ML Weft contributors, Moissanite Labs}},
institution = {Moissanite Labs},
type = {ML Weft Paper},
number = {1},
year = {2026},
month = nov,
note = {Version 1.0},
url = {https://w3ft.org/papers/models-as-cells/}
}
Version 1.0, 8 November 2026. Describes repository commit
a18fc40.
Text and figures are licensed under CC BY 4.0, and the code is licensed under Apache-2.0.
Found an error? Open an issue.