Chemosensory associative-memory probe (T7) — working-memory separation confirmed - #261
Conversation
Proposal/design/spec/tasks for the chemosensory associative-memory probe — the biological remember-and-use twin of bit-memory, extending its scaffolding with an outcome/valence channel + two-cue conditioning + probabilistic within-trial reversal (working-memory UPDATE, the load-bearing demand bit-memory can't test). Reviewed via /nematode-review-spec (3 structural fixes) + reversal folded in per design discussion. openspec validate --strict clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the OUTCOME sensory module (ModuleName.OUTCOME + registry + extractor) and the BrainParams.outcome_signal field — the one new channel the associative-memory probe needs beyond the reused bit-memory cue/go channels. Carries each conditioning cue's valence (+1 rewarded / -1 not; flipped in a reversal block), 0 during delay/response, None when disabled. Tests: [cue, outcome, go] is exactly 3-dim, outcome lands at index 2, unset → zeros. Ticks §1.1–1.3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… (§2) Mirror the bit-memory config surface: AssociativeMemoryTaskConfig (enabled, trials, cond_steps_per_cue, reversal_prob, delay/response, reward pinned to 1/0 for the count-metric, worst-case-span window warning), the associative_memory_task env field, and assert_associative_observation_clean + its config-resolve invariant (exactly [cue, outcome, go_signal] = 3-dim, no STAM/gradient leak — fail loud). 10 config tests. Ticks §2.1–2.4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
env/associative_memory.py: AssociativeMemoryTask phase machine mirroring BitMemoryTask — conditioning (two cues, one rewarded) → probabilistic reversal (flipped outcomes → current rewarded cue flips) → delay → response, with the binary readout scored against the CURRENT rewarded cue and reversal/non-reversal accuracy split. Wired end-to-end: env.associative_memory + get_associative_signals, _attach_associative_memory_task, agent injection of cue/outcome/go into BrainParams, runner _run_associative_memory_step (foraging bypassed) + reset + rebind across the per-run env recreation (the fix that kept runs 2+ from reverting to foraging). 13 phase-machine tests; integration smoke: 5/5 runs complete via the task at chance (untrained MLP). Ticks §3.1–3.6. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Six per-arm cells under configs/scenarios/associative_memory/ (mlpppo baseline + lstmppo/cfcppo/transformerppo/mingruppo/minlstmppo), mirroring the proven bit-memory arm configs: sensory_modules [cue, outcome, go_signal], the associative_memory_task block (within-window defaults), max_steps 280 for the worst-case reversal span. Connectome skipped (at-chance on bit-memory). Smoke: all 6 load + run headless, completing via the task. Ticks §4.1–4.2. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t (§5) scripts/analysis/associative_memory_separation.py mirrors the bit-memory harness (overall accuracy = reward/num_responses, plateau-tail, paired-seed Wilcoxon + bootstrap + BH-FDR verdict) and adds the reversal/non-reversal split — parsed from a printed AssocMemory line the runner now emits to the .out. At reversal_prob 0.5 a hold-only policy is at chance, so above-chance overall accuracy requires genuine working-memory UPDATE; the split shows the hold-vs-update breakdown per arm. 5 tests (metric, split parsing, separation + null verdicts). Ticks §5.1–5.2. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lidated Transformer (the reliable detector) learns the full task incl. working-memory UPDATE (default reversal_prob 0.5, delay 8): plateau accuracy 0.99 with the reversal-split at 0.98 (genuine update, not hold-only). Basic hold also learnable (easy no-reversal → 0.93). Default params well-calibrated; no retune. Ready for the §7 panel (all arms × paired seeds) pending user greenlight. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Naturalistic chemosensory associative-memory probe (the "remember-and-use" twin of the bit-memory control 030; the follow-on to the ARS null 032). Within-episode delayed-associative-match with probabilistic within-trial reversal — a working-memory UPDATE demand (at reversal_prob 0.5 a hold-only policy is at chance). Panel (6 arms × 8 paired seeds × 1500 episodes): all five memory arms clear the 0.80 update threshold and beat the memoryless MLP (0.490, at chance on both reversal and non-reversal) at BH-FDR q=0.007 — Transformer 0.989 ≫ CfC 0.914 > minGRU 0.860 ≈ minLSTM 0.852 ≈ LSTM 0.811. The reversal split separates genuine updaters (Transformer/CfC/LSTM) from hold-biased minimal-RNNs (minGRU 0.99/0.73, minLSTM 0.99/0.71 — a converged plateau, plausibly the 031 retention-gate init). Resolves the memory-separation question with 030 + 032: given a genuine naturalistic memory demand the arms separate → the ARS null was the environment's under-demand, not architectural incapacity. Logbook 033 + committed supporting artefacts (separation.json + per-seed CSV + forensics), README row, tracker tick (T7.separation.associative_memory RESOLVED: SEPARATION), AGENTS.md associative_memory family docs, §7/§8 tasks ticked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pre-push `pre-commit run -a` normalisation (no content change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Change complete + evaluated (SEPARATION, Logbook 033). Archived to openspec/changes/archive/2026-07-02-add-associative-memory-probe/ with all tasks ticked (§1–§9); the associative-memory-probe capability spec is applied to openspec/specs/ (Purpose written + heading spacing fixed post-archive). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThis PR adds a config-gated associative-memory probe with a new outcome channel, a delayed/reversal phase machine, config and runtime wiring, per-architecture scenarios, separation analysis, tests, and matching OpenSpec and experiment documentation. ChangesCore implementation
Sequence Diagram(s)sequenceDiagram
participant Runner as StandardEpisodeRunner
participant Agent as QuantumNematodeAgent
participant Env as BaseEnvironment
participant Task as AssociativeMemoryTask
Runner->>Task: reset() at episode start
loop each step
Runner->>Agent: run associative-memory step
Agent->>Env: get_associative_signals()
Env->>Task: signals()
Task-->>Agent: cue, outcome, go
Agent->>Task: record_response(turn)
Task->>Task: score vs current_rewarded_cue
Agent->>Task: take_reward()
Task-->>Runner: done?
Runner->>Task: advance()
end
Runner->>Runner: log accuracy, set success
Specs and experiment documentation
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
packages/quantum-nematode/tests/quantumnematode_tests/env/test_associative_memory.py (1)
142-153: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winWeak/tautological assertions in the reversal-split test.
Since every response in this loop is deliberately correct (
turn=task.current_rewarded_cue),reversal_accuracy/non_reversal_accuracycan only ever resolve to0.0(no trials of that type occurred) or1.0(all correct) — the assertions hold even if the reversal/non-reversal split assignment in_split_accuracywere broken (e.g., inverted). Consider also asserting that both splits have at least one recorded response (e.g., forcing a mixed seed/reversal_prob, or checkinglen(task._responses) > 0for both categories) to actually exercise the split-correctness path.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/quantum-nematode/tests/quantumnematode_tests/env/test_associative_memory.py` around lines 142 - 153, The assertions in test_reversal_and_non_reversal_split are too weak because the loop only records correct responses, so the reversal/non-reversal split in _split_accuracy could be wrong and the test would still pass. Update this test to ensure both categories actually receive responses by using a setup that yields a mixed reversal/non-reversal sequence or by explicitly checking the recorded response buckets in AssociativeMemoryTask before asserting accuracy. Keep the existing response_accuracy check, but make the reversal_accuracy and non_reversal_accuracy assertions depend on exercising both paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@openspec/changes/phase6-tracking/tasks.md`:
- Line 417: The tracker entry in the phase6 task list is future-dated, so update
the `T7.separation.associative_memory` item to use the actual completion date if
known or remove the date stamp altogether until it is final. Keep the resolution
note and links intact, but avoid any timestamp that would imply the work was
completed before the review context; this change is localized to the `tasks.md`
entry for `T7.separation.associative_memory`.
In `@openspec/specs/associative-memory-probe/spec.md`:
- Around line 39-43: The observation contract for the task observation is
contradictory between the conditioning and reversal behavior. Update the spec
section that defines the cue-identity, outcome (valence), and go-signal channels
so it explicitly states when cue-identity and outcome are available during
reversal, and align that wording with the reversal requirement that reuses these
channels. Keep the phase-specific behavior clear in the associative-memory-probe
spec so the channel availability rules are consistent across the conditioning
and reversal descriptions.
In `@packages/quantum-nematode/quantumnematode/agent/agent.py`:
- Around line 1153-1164: The memory-task wiring in agent.py currently assumes
only one of bit memory or associative memory is active, but both can be enabled
through EnvironmentConfig. Add a load-time validation in the BrainParams
construction path around get_bit_memory_signals/get_associative_signals so it
fails fast when bit_memory_task and associative_memory_task are both set,
instead of mixing scoring and signal injection. Use the existing environment
checks on self.env, and keep the guard close to the
cue_signal/go_signal/outcome_signal assembly.
---
Nitpick comments:
In
`@packages/quantum-nematode/tests/quantumnematode_tests/env/test_associative_memory.py`:
- Around line 142-153: The assertions in test_reversal_and_non_reversal_split
are too weak because the loop only records correct responses, so the
reversal/non-reversal split in _split_accuracy could be wrong and the test would
still pass. Update this test to ensure both categories actually receive
responses by using a setup that yields a mixed reversal/non-reversal sequence or
by explicitly checking the recorded response buckets in AssociativeMemoryTask
before asserting accuracy. Keep the existing response_accuracy check, but make
the reversal_accuracy and non_reversal_accuracy assertions depend on exercising
both paths.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 34cafe41-4ae1-4eea-9888-b6a0c64d632c
⛔ Files ignored due to path filters (1)
docs/experiments/logbooks/supporting/033-associative-memory-probe/accuracy-per-seed.csvis excluded by!**/*.csv
📒 Files selected for processing (31)
AGENTS.mdconfigs/scenarios/associative_memory/cfcppo_small_associative_memory.ymlconfigs/scenarios/associative_memory/lstmppo_small_associative_memory.ymlconfigs/scenarios/associative_memory/mingruppo_small_associative_memory.ymlconfigs/scenarios/associative_memory/minlstmppo_small_associative_memory.ymlconfigs/scenarios/associative_memory/mlpppo_small_associative_memory.ymlconfigs/scenarios/associative_memory/transformerppo_small_associative_memory.ymldocs/experiments/README.mddocs/experiments/logbooks/033-associative-memory-probe.mddocs/experiments/logbooks/supporting/033-associative-memory-probe/details.mddocs/experiments/logbooks/supporting/033-associative-memory-probe/separation.jsonopenspec/changes/archive/2026-07-02-add-associative-memory-probe/.openspec.yamlopenspec/changes/archive/2026-07-02-add-associative-memory-probe/design.mdopenspec/changes/archive/2026-07-02-add-associative-memory-probe/proposal.mdopenspec/changes/archive/2026-07-02-add-associative-memory-probe/specs/associative-memory-probe/spec.mdopenspec/changes/archive/2026-07-02-add-associative-memory-probe/tasks.mdopenspec/changes/phase6-tracking/tasks.mdopenspec/specs/associative-memory-probe/spec.mdpackages/quantum-nematode/quantumnematode/agent/agent.pypackages/quantum-nematode/quantumnematode/agent/runners.pypackages/quantum-nematode/quantumnematode/brain/arch/_brain.pypackages/quantum-nematode/quantumnematode/brain/modules.pypackages/quantum-nematode/quantumnematode/env/associative_memory.pypackages/quantum-nematode/quantumnematode/env/env.pypackages/quantum-nematode/quantumnematode/report/dtypes.pypackages/quantum-nematode/quantumnematode/utils/config_loader.pypackages/quantum-nematode/tests/quantumnematode_tests/analysis/test_associative_memory_separation.pypackages/quantum-nematode/tests/quantumnematode_tests/brain/test_modules.pypackages/quantum-nematode/tests/quantumnematode_tests/env/test_associative_memory.pypackages/quantum-nematode/tests/quantumnematode_tests/utils/test_config_loader.pyscripts/analysis/associative_memory_separation.py
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
- spec: the cue-identity/outcome channel-availability contract said "non-zero only during the conditioning phase", contradicting the reversal requirement (and the code) that re-presents the cues with flipped outcomes during the reversal phase. Corrected to "conditioning and reversal phases; zero during delay and response" (applied spec + archived change delta). - config: add an explicit EnvironmentConfig mutual-exclusion guard for bit_memory_task vs associative_memory_task. Both-enabled was already unreachable (each pins the sensory modules to its own exact set, so the channel invariants are contradictory), but it surfaced a confusing module-mismatch error; now it fails fast with a clear message, enforcing the single-active-task invariant agent.py assumes. + a regression test. - test: strengthen test_reversal_and_non_reversal_split — the `in (0.0, 1.0)` assertion passed even if a bucket was never exercised. Now answers non-reversal correctly and reversal wrongly so the buckets must diverge (reversal 0.0 / non-reversal 1.0), and asserts both buckets are non-empty. - tracker: align the associative_memory resolution date to the archive date (2026-07-02). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
The naturalistic chemosensory associative-memory probe — the biological "remember-and-use" twin of the bit-memory positive control (Logbook 030) and the follow-on to the ARS null (Logbook 032). A within-episode delayed-associative-match with probabilistic within-trial reversal — a working-memory update demand: two cues are conditioned (one rewarded), with probability
reversal_proba reversal block flips the outcomes, then after a delay the agent gives a binary readout of the current rewarded cue. The observation is exactly[cue, outcome, go](no STAM, no gradients), so the association must be held — and overwritten on reversal — in internal recurrent state. Atreversal_prob 0.5a hold-only policy is at chance, so above-chance accuracy requires genuine update.Result — SEPARATION
Panel: 6 arms × 8 paired seeds × 1500 episodes (headless,
OMP_NUM_THREADS=1).Non-gating (Gate 3 / the 029 ranking unchanged). Full write-up: Logbook 033.
What's in it
OUTCOMEobservation channel;AssociativeMemoryTaskphase machine (conditioning → probabilistic reversal → delay → binary readout) mirroringenv/bit_memory.py; the no-external-aid contract (fails loudly on a leaked STAM/gradient); config validator pinning the count-metric reward; runner integration.scripts/analysis/associative_memory_separation.py— plateau-tail accuracy + reversal/non-reversal split + the paired-seed Wilcoxon / bootstrap / BH-FDR layer reused from the arch ranking.configs/scenarios/associative_memory/.phase6-trackingtick, AGENTS.mdassociative_memoryfamily docs.Gates
openspec validate --strict→ valid; change archived, capability spec applied.pytest -m "not nightly"→ 4059 passed, 1 skipped, 2 xfailed.pre-commit run -a→ clean.Limitations
Single-shot within-episode pairing compresses the real associative timescale (biologically-inspired, not faithful — slow-forming plasticity is phase-7). The current arms already solve the probe → limited headroom for further memory candidates (e.g. modified-S5) without a harder demand. Recurrent-PPO seed instability persists (LSTM). The retention-gate-init → hold-bias attribution is a hypothesis (an ablation would confirm it).
🤖 Generated with Claude Code
Summary by CodeRabbit