Symmetric slot binding — collapsing operand permutations onto one learned key
Decision 0017: Symmetric slot binding
Date: 2026-05-25 Status: Accepted Builds on: ADR 0014 (variable binding via slot cells) Motivated by: Entries 002 → 005 — Task 2 held-out generalization stuck at 3-17% across every configuration tried
Context
ADR 0014 introduced slot cells to give Reverie variable binding. A slot cell has a template with wildcard positions; when a window matches, the wildcards bind to concrete values, and the cell stores per-binding preference vectors in _slot_prefs[c][binding]. For the arithmetic template (*, +, *, =) and the observation 1 + 2 = 3, the cell’s binding becomes (1, 2) and _slot_prefs[c][(1, 2)] accumulates a preference for 3.
ADR 0014 itself flagged the limitation: “the bindings (1, 2) and (2, 1) are distinct dictionary keys. Learning one doesn’t reach the other.” Entry 002’s benchmark confirmed this empirically — held-out generalization on 6 unseen facts after training on 30 produced 3.3% accuracy, indistinguishable from chance. Entry 003 read the failure as a fundamental representation gap. Entry 004 narrowed that diagnosis to Task 2 specifically (Task 1 was just a capacity ceiling). Entry 005 confirmed the wall extended to non-symbolic prose.
The fix tried in this ADR is the smallest possible test of the binding hypothesis: if the wildcards in a slot template represent interchangeable roles (e.g., the operands of a commutative operation), the architect should be able to opt into sorting the bound-value tuple before it’s used as the per-cell dictionary key. (1, 2) and (2, 1) then map to the same multiset, share storage, and share learning. Training on 1+2=3 automatically propagates to 2+1=?.
This is honestly a bit of a cheat — the architecture isn’t discovering commutativity, it’s being told by the architect that the wildcards are interchangeable. But it cleanly isolates whether the rest of ADR 0014’s binding machinery is sound. If accuracy lifts under this flag, the architecture’s only missing assumption was symmetry; if it doesn’t, the binding mechanism itself is broken and the substrate needs a deeper change (vector-symbolic binding, learned slot structure — both deferred to follow-up ADRs).
Decision
New parameter
slot_binding_symmetric: bool = False. Default off preserves ADR 0014’s behavior exactly; nothing else about slot cells or any other mechanism changes.
Mechanism
Inside _check_slot_matches, the binding is built as before by walking the wildcard positions and reading the corresponding window values. The only change is one branch:
if self.slot_binding_symmetric:
self._slot_bindings[c] = tuple(sorted(binding))
else:
self._slot_bindings[c] = tuple(binding)
Lookups in _slot_prefs[c] use whatever key _slot_bindings[c] carries, so the read side is unchanged — the sorted key is consistent across write and read.
Scope
The flag is global, not per-template. Reverie’s current architecture supports a single shared slot template, so a global flag is sufficient. If the substrate ever grows to multiple templates with mixed commutative/non-commutative semantics, the flag would need to become per-template.
Soundness condition
The flag is only sound for templates whose wildcards represent interchangeable roles. The architect opts in by setting the flag; the substrate does not verify the assumption. Misusing the flag — e.g., enabling it for a (*, -, *, =) subtraction template — would produce wrong learning, since 3 - 1 = 2 and 1 - 3 = -2 would share the bound key (1, 3) and the learned preferences would average across two contradicting target tokens.
What this fixes and what it does not
Fixes
- Task 2 (compositional generalization): lifted from 3.3% ± 7.5 to 73.3% ± 14.9 across five seeds with symmetric=True on the standard
(*, +, *, =)arithmetic template. The new number is identical to the transformer’s 73.3% ± 14.9 to the second decimal — both architectures are now bumping up against the same algorithmic ceiling (held-out facts whose commutative partner is also in the held-out set, ora+afacts whose partner is themselves).
That is the entire claim. The flag fixes exactly the thing it was designed to fix, and the size of the lift validates ADR 0014’s binding mechanism as architecturally sound — the gap to the transformer was a single assumption, not a structural defect.
Does not fix
- Task 1 (memorization): unchanged. Symmetric binding has no effect on raw fact recall — memorization isn’t about role-symmetric generalization. Task 1 remains capacity-bound (entry 004’s lesson still applies; bumping
initial_cellsis the lever). - Tasks 4 and 5 (continual learning, online adaptation): unchanged. Both are about plasticity in the context-cell pool; the slot-cell change is orthogonal.
- Reverie’s failure on prose (entry 005): unchanged. Prose has no commutative slot structure for the symmetric flag to exploit.
The flag is a sharply targeted improvement, not a general one. The remaining capacity and plasticity problems are real and still need architectural answers.
What this means about the substrate
Two things worth keeping for the long-term reading.
First, ADR 0014’s design was right; the failure was an under-specification, not a mis-specification. Slot cells do support compositional generalization the moment you tell them which roles are interchangeable. This is the first piece of empirical evidence that the substrate’s variable-binding mechanism is structurally sound.
Second, the architecture is still architect-configured rather than self-discovering. The next honest step toward “from observation alone” would be a mechanism that discovers which wildcards are interchangeable from the observation stream itself — letting the substrate notice that 1+2=3 and 2+1=3 co-occur often enough to mark the operand wildcards as a symmetric pair. That’s a deferred ADR (closer to approach C from entry 006’s design discussion).
Behavioral predictions
Tests in tests/test_slot_cells.py:
test_symmetric_binding_off_by_default— the flag is False on a default Reverie.test_symmetric_binding_collapses_permutations— with the flag on,(*, +, *, =)windows for1 + 2 = …and2 + 1 = …produce identical sets of slot bindings.test_asymmetric_binding_keeps_permutations_distinct— with the flag off, the two windows produce distinct bindings (the ADR 0014 behavior is preserved).test_symmetric_binding_shares_learned_preferences— end-to-end: training on1 + 2 = 3produces a slot preference for3keyed under the sorted multiset, so a later query under the(2, 1)window can retrieve it.
All four pass. The full pre-ADR test suite (115 tests) is untouched and continues to pass.
Open questions deferred
- Discoverable symmetry. A mechanism for the substrate to learn which wildcard positions are interchangeable based on co-occurrence statistics. Closer in spirit to ADR 0014’s original promise. Real research; weeks.
- Vector-symbolic binding. Each token gets a learned vector, roles get fixed vectors, and binding is via circular convolution / element-wise multiplication. Generalizes far beyond symmetry; weeks of work. Discussed as design option B in entry 006’s preamble.
- Multi-template configurations. Current substrate has one global
slot_template. Multiple templates with mixed commutative/non-commutative semantics would need per-template symmetric flags. - Higher-arity symmetry. Templates with three or more wildcards where any permutation is valid. The sorting trick generalizes to multiset keys naturally; no code change needed if a future template uses three operand wildcards.