The fix also fails
Entry 014 ended with a concrete next step: when a cell reinforces its preference for an observed token, also reinforce its preferences for tokens in the recent observation window with a spread factor. Over training, cells develop preferences over neighborhoods of related tokens rather than individual tokens. Paraphrases of the same fact would share semantic neighborhoods, activate similar cells, and the within-vs-cross cosine ratio would lift from 1.18 toward something like 2.5.
I implemented it. ADR 0020 candidate, gated by a new preference_spread_factor parameter that defaults to 0 (no spreading, original behavior preserved). When positive, every preference update for the observed token is followed by smaller updates for each other token in the current window, scaled by the spread factor. About fifteen lines of code in _apply_preference_learning. All 138 pre-existing tests pass with the new parameter off.
Then I ran the canonicalization experiment again, sweeping spread values from 0.0 to 1.0.
What happened
spread within cross ratio
0.00 0.818 ±0.033 0.756 ±0.039 1.08
0.10 0.821 ±0.034 0.761 ±0.041 1.08
0.30 0.827 ±0.036 0.770 ±0.043 1.07
0.50 0.834 ±0.037 0.779 ±0.046 1.07
1.00 0.850 ±0.040 0.804 ±0.051 1.06
The within-vs-cross ratio doesn’t lift. It drops from 1.08 to 1.06 as the spread factor increases. The fix actively makes things slightly worse.
(Note: the absolute numbers here are different from entry 014 because I also changed the signature read-out at the same time — entry 014 used the substrate’s activation vector after observing the fact’s tokens; this experiment uses a static-affinity signature that sums each cell’s preferences over the fact’s tokens. The change was meant to make the spreading mechanism’s effect more visible. It does — the static signature shows the preference structure directly — but what it reveals is that the spreading doesn’t help.)
Why it doesn’t work
The architectural reason is sharper than entry 014’s diagnosis. Spreading reinforces cells’ preferences for every token in the recent window, uniformly weighted. Most window tokens at any given step are function words (“I”, “is”, “my”, “the”, “a”) or topically-shared content tokens (“Yusuf” — present in every fact in the experiment). After enough training, cells develop preferences that look roughly like the overall token frequency of the corpus, with small variations specific to which facts that cell saw most frequently.
The signature for any fact ends up dominated by overlap with this shared corpus-wide preference structure. Two paraphrases of “user prefers tea” share the corpus-wide preference vector heavily; so do two unrelated facts about the user. The within-vs-cross gap stays small because both quantities are mostly measuring the same shared structure, not the fact-specific structure.
Worse, more spreading makes more of the cell’s preferences look like the corpus-wide distribution. So the within-vs-cross ratio drops as spreading increases. The mechanism is the architectural opposite of what I wanted it to be.
A spreading mechanism that could work would need to be selective — reinforce only for tokens that are semantically related to the observed token, not for every token in the recent window. But “semantically related” is exactly the property the substrate doesn’t have. To use it for spreading, we’d need to compute it first; the spreading itself is meant to produce that property; the circle doesn’t close.
This is the same pattern as ADR 0018’s vector-symbolic experiment: every attempt to add a semantic-similarity mechanism to the substrate without explicit embeddings runs into the chicken-and-egg problem that the substrate has no token-level similarity signal to bootstrap from. Random embeddings give random structure. Co-occurrence-based embeddings collapse toward the corpus-wide distribution. Real distributional embeddings (skip-gram, BERT, etc.) require either gradient descent or carefully engineered contrastive sampling — both of which take Reverie outside the “from observation alone, no backprop” design constraints the project was built within.
What this means
Canonicalization is not reachable from Reverie’s substrate via any small architectural addition. The negative result from entry 014 isn’t a tuning issue — it’s a structural one, and entry 015 has now confirmed that the most natural architectural patch doesn’t close it.
The productization implication from entry 014 stands and tightens: Reverie cannot be a deduplicating-canonicalizing layer in front of RAG, because the substrate’s preference structure doesn’t actually distinguish “the same fact paraphrased” from “different facts that share function words and topical content.” The product story that ran on that property is firmly closed.
What’s left is what entry 014 already listed:
- Audit/delete layer (real, cell-by-cell)
- No-embedding-model dependency (real, pure-numpy)
- Online updates without retraining (real, microsecond-cost)
- Time-decay forgetting (real via
preference_decay_rate)
None of those depend on canonicalization. All four survive entries 014 and 015. They just don’t add up to a category-defining product on their own — they justify Reverie as an open-source library someone might use for specific deployment needs, not a standalone memory-infrastructure SaaS.
Three patterns the project keeps showing
Across nineteen ADRs and now fifteen entries, three patterns have repeated enough that they’re worth naming:
First, every attempt to add semantic similarity to Reverie’s substrate fails the same way. ADR 0018’s VSA with Hebbian-learned embeddings collapsed to uniform vectors. ADR 0020’s preference spreading collapsed to the corpus-wide preference distribution. Both for the same reason: without explicit gradient-shaped or contrastively-sampled token relationships, any local Hebbian-style update converges to the marginal token statistics. Reverie’s design constraints don’t admit a fix that doesn’t break those constraints.
Second, every “headline result” the project has produced is bounded by a specific test design. ADR 0017’s 73% on held-out generalization was the easy-split crutch (entry 007). ADR 0019’s “discovered symmetry matches configured” was within the same easy-split (and Task 8 showed it’s sample-size dependent). Entry 012’s hybrid 100%/100% required operator-distinguishable prompts (and didn’t translate to Claude). Each positive result, when probed, has been bounded into a smaller claim than its first appearance suggested.
Third, every product story I’ve sketched has lost a degree of magnitude when its load-bearing claim was tested. Entries 010-013 progressively narrowed the productization framing from “Reverie alone” through “Reverie + RAG hybrid” to “Reverie as canonicalization layer” to “Reverie as audit layer.” Each step removed an empirical claim. Entry 015 removes the last one that gave the product a distinctive wedge: canonicalization.
These three patterns are themselves the project’s most durable finding. Reverie is a coherent research artifact with real architectural properties (interpretability, online learning, no-backprop). It is not a competitive language-modeling substrate at this scale, and the architectural changes that would make it one are out of scope for what Reverie is. That’s a useful conclusion. It’s the kind of conclusion a research log is supposed to produce.
What’s next
Two genuine options remain. They’re cleaner than they were before entry 015 closed the canonicalization door.
Option A. Ship Reverie into Cairn as the audit layer described in entry 013 (Option A from that entry’s design tree). The integration is small, the value is bounded but real, the framing matches Cairn’s faith-aware-personal-AI positioning. The product story is “interpretable, deletable memory for your personal AI” — modest, defensible, doesn’t require canonicalization.
Option B. Don’t ship Reverie anywhere as a product. Keep it as a research artifact at reverie.boomarche.com. The fifteen-entry log is itself the output. The benchmark code and the substrate are reproducible by anyone who finds them interesting. Move attention to Cairn or Galley or one of the other projects with clearer product market.
I don’t yet know which one I’ll pick. The Cairn integration would still be useful work even if the productization story stays internal — it would give Cairn a real cell-level audit feature that the rest of the personal-AI market doesn’t have. Whether that’s worth two days of engineering depends on whether anyone uses it. The honest answer is “I don’t know yet.”
The fifteen entries together describe what Reverie can and can’t do, what mechanisms work and which don’t, and what shape the product story has (and doesn’t have). That’s a complete research log. Whatever happens next can wait.
— Kaan, with Claude as collaborator on the build, the experiments, and these notes. ADR 0020 (preference spreading) is implemented as opt-in via preference_spread_factor; the sweep is reproducible with model/scripts/canonicalization_experiment.py --seeds 3 --sweep. Default is off because it doesn’t help.