# Roy-4 — Cross-modal binding validation prereq (1.1 plan gate)

**Date:** 2026-05-13 (run completed 2026-05-13 18:26 local)
**Plan:** [release_0_9_1.md § Stage 0d](../plans/release_0_9_1.md) · [cross_modal_substrate_binding.md § Stage 1](../plans/cross_modal_substrate_binding.md) · [persona_convergence_crucible.md § "Iteration log"](../plans/persona_convergence_crucible.md)
**Companion:** [20_roy_2c.md](20_roy_2c.md) (H1 confirmation that motivates Roy-4) · [19_roy_2pc.md](19_roy_2pc.md)
**Spec:** [scenarios/roy/roy_4_iteration.yaml](../../scenarios/roy/roy_4_iteration.yaml)
**Engineered fixture:** [scenarios/roy/roy_2pc_holdout.yaml](../../scenarios/roy/roy_2pc_holdout.yaml) (reused unchanged from Roy-2pc / Roy-2c)
**Reproduction:** [protocols/21_roy_4_reproduction.md](protocols/21_roy_4_reproduction.md)
**Analyzer:** [scripts/analyze_roy_4_coactivation.py](../../scripts/analyze_roy_4_coactivation.py)

## Status

**FAIL.** Hebbian binding alone cannot close the Roy-2c gap. The priming-acquired EC clusters and the test-phase active nodes are structurally disjoint AND the priming food clusters fire in near-isolation during priming (61 ticks where any food cluster fires, 1 tick co-firing with a non-food node), so there is no temporal-coincidence signal for the proposed binding rule to harvest.

**Per [cross_modal_substrate_binding.md § Risk register](../plans/cross_modal_substrate_binding.md), this is the canceling outcome:** Stages 2-6 of the 1.1 cross-modal binding plan are NOT greenlit. The 1.1 design needs to be replaced or substantially re-scoped; the recommended redirect is a 1.2+ encoder-replacement research direction.

The FAIL is robust across the entire reasonable parameter sweep (`min_cofire ∈ {1, 2, 3, 5}` × `min_weight ∈ {0.01, 0.1, 0.5}`). Even the most permissive rule — "ANY two nodes that fired in the same tick at least once" with a vanishing weight floor — generates 256 priming would-have-bound edges, NONE of which connect a priming `sense_food_source` cluster to any arm A test-phase active node.

## Pre-registered diagnostic logic

| Outcome | Diagnosis |
|---|---|
| At least one test-phase active node has a would-have-bound edge to a priming `sense_food_source` cluster | **PASS** — Hebbian binding would have closed the Roy-2c gap. Greenlight [cross_modal_substrate_binding.md](../plans/cross_modal_substrate_binding.md) Stages 2-6 for 1.1. |
| **No would-have-bound edges between priming and test clusters under the proposed rule** | **FAIL** — encoder alignment is too severe for Hebbian binding alone. Cancel Stages 2-6; redirect to a 1.2+ encoder-replacement research direction. |

The recorded run on 2026-05-13 produced **FAIL across all sweep parameters**, including the most permissive `(min_cofire=1, min_weight=0.01)`.

## What shipped

- [`scenarios/roy/roy_4_iteration.yaml`](../../scenarios/roy/roy_4_iteration.yaml) — re-run of Roy-2c spec with `MAXIM_EC_TRACE_ACTIVATIONS=1` in the runner environment.
- `MAXIM_EC_TRACE_ACTIVATIONS` env-var gate + `_emit_ec_activation` helper at `similarity/ec.py` (Stage 0d of [release_0_9_1.md](../plans/release_0_9_1.md)).
- `conftest.py` autouse scrub fixture `_isolate_maxim_ec_trace_env`.
- 30 unit tests in [`tests/unit/test_ec_trace_activations.py`](../../tests/unit/test_ec_trace_activations.py) covering env-var resolver, modality_tag derivation, emission gating, multi-agent isolation, end-to-end via `pattern_complete_or_separate`.
- [`scripts/analyze_roy_4_coactivation.py`](../../scripts/analyze_roy_4_coactivation.py) — post-hoc analyzer with proposed Hebbian rule + parameter overrides.
- CLAUDE.md env-var table entry.

## Result

Wall: **1547.5s (~25.8 min)** — same shape as Roy-2c (1284s). Pre-flight clean (`outcome: ok`, `latency_ms: 235.9`). Priming completed all 5 stages × 10 turns; arm a/b/c each completed 10 turns.

### Per-arm

| Arm | Substrate | system_prompt | session_id | turns | duration_s | finish |
|---|---|---|---|---|---|---|
| a | from_priming | neutral | `20260513_181049` | 10 | 307.38 | cancel |
| b | blank | "You are a hungry infant" | `20260513_181557` | 10 | 321.87 | cancel |
| c | blank | neutral | `20260513_182119` | 10 | 307.24 | cancel |

### Headline pairwise diffs

| Pair | `cluster_reward_bias_l2` | (keys) | `causal_link_Δ` | `episodes_Δ` | `valence_KS` (p) |
|---|---|---|---|---|---|
| **a_vs_b** | **2.4678** | 10 | +151 | +650 | 0.998 (0.006) |
| **a_vs_c** | **2.4678** | 10 | +151 | +650 | 0.998 (0.006) |
| b_vs_c | 0.3000 | 4 | 0 | 0 | 0.000 (1.000) |

Cluster wire reproduces SEVENTH iteration in a row (Roy-0 → Roy-1a → Roy-1b → Roy-2 → Roy-2pc → Roy-2c → Roy-4), all priming-side `cluster_reward_bias_l2` values within 5%.

### EC activation instrumentation — capture summary

| Phase | Sessions | EC events | Unique nodes | Linguistic | Drive |
|---|---|---|---|---|---|
| Priming (5 stages) | 5 | 148 | 37 | 68 | 80 |
| Arm A | 1 | 47 | 10 | 23 | 24 |
| Arm B | 1 | 69 | 13 | — | — |
| Arm C | 1 | 42 | 9 | — | — |

Both linguistic (LinguisticEncoder → EC) and drive (SensorEncoder → EC) modalities fire in every phase. **The structural disjointness is symmetric across modalities** — not a "priming used sensors, test used text" artifact.

### Node-set overlap (the load-bearing structural finding)

| Phase | Unique nodes | Overlap with priming | Overlap with 6 priming food clusters |
|---|---|---|---|
| Priming | 37 | — | 6 / 6 |
| Arm A | 10 | **0** | **0** |
| Arm B | 13 | **0** | **0** |
| Arm C | 9 | **0** | **0** |

**Zero EC node ID is shared between priming and any test arm.** Roy-2c inferred this from the cluster-key differences in NAc's `cluster_reward_bias`; Roy-4 confirms it at the per-tick EC instrumentation level. The priming substrate's EC region (37 nodes) and the test-phase EC regions (10/13/9 nodes per arm) are structurally separate populations.

### Food-cluster co-firing analysis (the binding-rule diagnostic)

| Metric | Value |
|---|---|
| Total ticks where any priming food cluster fired | 61 |
| Ticks where a food cluster co-fired with a non-food node | **1** |
| Unique non-food co-firing partners across priming | 7 |
| Of those 7 partners, how many also fire in arm A test phase | **0** |

The food clusters fire in near-isolation during priming — only 1 of 61 food-firing ticks had any other node co-firing in the same tick window. Of the 7 partner nodes that DID co-fire with a food cluster anywhere in priming, zero appear in arm A's test-phase active set. **The temporal-coincidence signal the Hebbian rule depends on does not exist in the priming data.**

### Parameter sweep — FAIL across the entire reasonable range

| `min_cofire` | `min_weight` | Priming would-have-bound edges | Matching priming↔test edges |
|---|---|---|---|
| 1 | 0.01 | 256 | **0** |
| 1 | 0.1 | 256 | **0** |
| 1 | 0.5 | 233 | **0** |
| 2 | 0.01 | 5 | **0** |
| 2 | 0.1 | 5 | **0** |
| 2 | 0.5 | 5 | **0** |
| 3 | 0.01 | 3 | **0** |
| 3 | 0.1 | 3 | **0** |
| 3 | 0.5 | 3 | **0** |
| 5 (default) | 0.5 (default) | 2 | **0** |

The default rule (`min_cofire=5, min_weight=0.5`) yields 2 priming bound edges; the most permissive (`min_cofire=1, min_weight=0.01`) yields 256. **At every sweep point, zero of those bound edges connect a priming food cluster to a test-phase active node.** No reasonable parameter tuning rescues the binding hypothesis.

## What this proves

**The Hebbian-binding-via-temporal-coincidence rule cannot rescue the Roy-2c gap.** The mechanism's load-bearing assumption — that priming-acquired clusters co-fire with the nodes that test-phase percepts will later activate — is empirically false on this priming + fixture pair. Two independent observations carry the conclusion:

1. **Zero node overlap.** None of the 37 priming nodes are activated in any arm's test phase. The encoder embeds priming substrate input (sensor/drive readings + cradle-stage narrator output) and test-fixture percepts ("you sense food nearby") into structurally non-overlapping regions of EC, even within the same modality channel. This reproduces Roy-2c's cluster-disjointness finding at per-tick resolution.
2. **Priming food clusters fire in near-isolation.** Of 61 ticks where a food cluster activates during priming, only 1 has a non-food co-firing partner. Even if we hypothetically extended the binding mechanism to bind any partner ever observed with a food cluster, those 7 partner nodes never appear in any arm's test phase. The signal Hebbian binding would need to harvest doesn't exist in the priming trajectory.

### Definitively proved

- The instrumentation hook (`MAXIM_EC_TRACE_ACTIVATIONS=1` → `_emit_ec_activation` → `sim_log("EC_TRACE", ...)`) fires end-to-end in both pattern-completion and pattern-separation branches across all 8 sessions of a Roy iteration (148 priming + 158 test events captured).
- Roy-4's per-tick EC trace reproduces Roy-2c's cluster-disjointness finding at the instrumentation level.
- Across the proposed Hebbian rule's parameter range, zero priming-cluster ↔ test-cluster edges form. The rule cannot close the Roy-2c gap on this priming + fixture pair.

### Cleanly refuted

- The hypothesis that priming-cluster ↔ test-cluster pairs would have been linked under any reasonable Hebbian binding rule (the PASS criterion). At every sweep point we tested, the result is zero matching edges.

### Still unfalsified (but secondary to the FAIL signal)

- Whether a *different* priming arc — one that explicitly produces co-firing between the substrate-encoded food clusters and the linguistic clusters the test fixture activates — would close the gap. Roy-4 used the same cradle-prelinguistic + cradle priming as Roy-2c; that priming pattern produces clusters that don't co-fire with test-fixture-style percepts. Untested whether a redesigned priming arc could rescue the binding mechanism.
- Whether a NEW encoder (replacing `LinguisticEncoder`) would produce structurally aligned priming + test embeddings, eliminating the disjointness problem upstream of any binding mechanism. This is the 1.2+ encoder-replacement research direction the FAIL outcome redirects toward.

## What this means for the 1.1 plan

**Cancel Stages 2-6 of [cross_modal_substrate_binding.md](../plans/cross_modal_substrate_binding.md)** as currently scoped. The plan's framing rule ("the binding mechanism ships only if a prior instrumentation experiment (Roy-4) confirms that priming-cluster ↔ test-cluster pairs WOULD have been linked under a proposed Hebbian rule") explicitly anticipates this disposition.

The redirection per the 1.1 plan's "Risk register" + "What this plan does NOT do" sections:

> **No replacement for `LinguisticEncoder`.** Encoder alignment is the underlying problem; binding routes around it. A 1.2+ research direction could replace `LinguisticEncoder` with an aligned multimodal encoder, but that's out of scope here.

Roy-4 promotes this aside from "potential 1.2+ direction" to "the actual structural fix the architecture needs." The cross-modal binding plan should be archived with the negative-result reference; the 1.2+ research surface becomes the next-priority architectural question for substrate-primary persona convergence.

**No 0.9.1 plan changes required.** Roy-4 was the design-validation gate for 1.1, not for 0.9.1. Wire-A (Stage 2 of [release_0_9_1.md](../plans/release_0_9_1.md)) is unaffected — it remains the interim signal-surfacing fix that bypasses the EC retrieval path entirely by rendering tool-name aggregated bias at the LLM prompt. Roy-3 (Stage 5 of 0.9.1) is unchanged as the next validation iteration.

**Secondary observations:**

- **The instrumentation is reusable.** Future Roy iterations that want to characterize substrate dynamics at per-tick resolution can flip `MAXIM_EC_TRACE_ACTIVATIONS=1` and get the same per-tick co-activation matrix. The analyzer's `--min-cofire-count` / `--min-weight` knobs let downstream iterations sweep different binding criteria without re-running the sim.
- **The priming substrate is doing real work** despite the test-phase disjointness — 37 unique nodes activated across 5 priming stages, with 256 pairwise co-activations under the most permissive rule. The disjointness is specifically between priming clusters and test-fixture clusters, not a general signal-poverty issue.
- **Both modality channels (linguistic, drive) reproduce the disjointness.** This is NOT an artifact of "priming used sensors, test used text" — Roy-4 captures both modalities at per-tick resolution and the test-phase populations are disjoint from priming in BOTH channels. The encoder-alignment problem is symmetric across modalities.

## What this still does NOT prove

- **Whether the redesigned priming arc** (one that deliberately produces priming-cluster ↔ test-fixture co-firing) would change the outcome. Out of 0.9.1 scope; revisit if the 1.2+ encoder direction stalls.
- **Whether a different EC pattern_complete_threshold** would have made priming and test percepts pattern-complete onto the same nodes. The current threshold is `0.40` (paraphrase-mpnet, P1 sweep-tuned); a lower threshold would collapse more, but at cost of cluster discrimination during priming itself. Out of Roy-4 scope.
- **Whether SCN phase-aligned co-activation** would change the diagnostic. The current Hebbian rule uses same-tick co-firing; SCN circadian phase wasn't part of the proposed rule. Adding phase alignment could only further filter (fewer bound edges), so it would not rescue the FAIL.

## Reproduction

See [protocols/21_roy_4_reproduction.md](protocols/21_roy_4_reproduction.md).

## Recommendation

**Cancel [cross_modal_substrate_binding.md](../plans/cross_modal_substrate_binding.md) Stages 2-6** as the 1.1 architectural-fix direction. Archive the plan with a "superseded by Roy-4 FAIL" front-matter note pointing to this experiment.

**Promote encoder replacement to the 1.2+ research-direction priority.** The bio-grounded language acquisition surface ([grounded_language_acquisition.md](../plans/grounded_language_acquisition.md)) is the natural carrier for that work — its Phase 1 token-binding registry was originally scoped to consume cross-modal binding edges this experiment was meant to validate; with binding off the table, Phase 1's design rebalances onto a different mechanism.

**Keep the Roy-4 instrumentation surface.** `MAXIM_EC_TRACE_ACTIVATIONS` + `scripts/analyze_roy_4_coactivation.py` are useful for any future substrate-dynamics characterization. No deprecation needed; the env var is off by default and pays zero runtime cost when unset.

**No Roy-5 planned on the binding-rule track.** Roy-5 was scoped as the post-implementation validation for `cross_modal_substrate_binding.md`. With Stage 2-6 cancelled, Roy-5 is cancelled too. A future Roy iteration (Roy-5+ on a new encoder track, or Roy-3a/b on the 0.9.1 wires once they ship) is the next harness work.

## PR

(filled in after PR open)
