Skip to content

diag(0.9.1): Roy-3c-bisect — wire merges did not cause Roy-3 priming regression#266

Merged
dennys246 merged 5 commits into
mainfrom
feat/0-9-1-roy-3c-bisect
May 26, 2026
Merged

diag(0.9.1): Roy-3c-bisect — wire merges did not cause Roy-3 priming regression#266
dennys246 merged 5 commits into
mainfrom
feat/0-9-1-roy-3c-bisect

Conversation

@dennys246
Copy link
Copy Markdown
Owner

Summary

  • Six-commit linear bisect of the 0.9.1 wire merges (cd51be56610566) names the cause of the Roy-3 priming-side cluster_reward_bias regression. Verdict: the wires did not cause it.
  • The regression decomposes into two axes with two distinct outside causes:
    • Key count (6 → 2): pre-window environmental, almost certainly the MAXIM_SUBSTRATE_PATH=1 env-var regime change between the 5/12 historical baseline and 5/14 cd51be5.
    • Bias magnitude (saturated → partial): Wire-A's pre-merge fold commit bee42ca intentionally added NAc.decay_cluster_reward_biases() per-tick decay in response to a Critical bio-fidelity review finding ("by-accretion contamination of the substrate-voice thesis"). Not a regression — a fix.

Routing impact

  • Affordance-replay bridge: no longer load-bearing for the priming-side count. Stays a 1.1+ candidate only on a separate diagnostic.
  • Wire-A "strongly rewarding" render floor: reframes from "biases regressed below threshold" to a tuning question about priming repetition × reward strength × decay rate.
  • Roy-3 re-validation: unnecessary against this verdict. The 2-key partial pattern Roy-3a/3b observed is the bio-correct substrate state under MAXIM_SUBSTRATE_PATH=1 + Wire-A decay.

Full writeup: docs/experiments/29_roy_3c_bisect.md

Optional disambiguating diagnostics (neither required for verdict)

  • A1 confirm key-count cause: re-run Roy-2 at cd51be5 without MAXIM_SUBSTRATE_PATH=1. If 6 keys appear, env-var hypothesis confirmed. ~20 min wall.
  • A2 confirm magnitude cause: re-run Steps 0/1 + Step 2 three times each to bound run-to-run variance. ~3 hours wall.

Test plan

  • Roy-2 bisect runs at all six commits complete; data captured in ~/.maxim/roy/roy-2-bisect-<commit_short>/ for audit
  • EC threshold == 0.40 verified at every bisect step (pre-EC-drift-fix)
  • Wire-A bee42ca decay introduction verified in git show of the fold commit
  • Both reward-bias keys at every step confirmed to be interoception-modality EC nodes (matches PR fix(roy-5a): MAXIM_SUBSTRATE_PATH=1 was the missing env var #251's earlier analysis
  • No source code changes; diagnostic-only PR

Authorization status

Per kickoff: standing authorization to push, no merge without confirmation.

🤖 Generated with Claude Code
EOF
)

dennys246 and others added 2 commits May 24, 2026 17:24
…regression

Roy-3c-bisect ran the six-commit linear bisect window prescribed by
the kickoff: cd51be5 (pre-wires, jepa docs) through 6610566 (PR #257
Wire 1), pinning EC threshold at 0.40 across all steps for apples-to-
apples comparison with the historical 5/12-5/13 baseline.

Roy-3a's spec was authored 2026-05-23 (after the bisect window).
Roy-2's spec exists at every bisect commit and has byte-identical
multi-arc priming structure (2 x cradle_prelinguistic + 2 x cradle +
1 x cradle_prelinguistic, 50 turns total). The 5/12 historical 6-key
baseline IS the Roy-2 spec, making it the right probe.

Results decompose into two distinct axes with two distinct causes,
neither attributable to a wire merge:

Axis 1 - key count (6 -> 2): pre-window environmental.

  Step 0 (cd51be5, docs-only) already shows 2 keys. All five
  subsequent wire merges hold at 2 keys. The only src/maxim/
  decisions, proprioception, similarity commit between Roy-5a
  (2026-05-13) and cd51be5 (2026-05-14) is 0ec3f95 (PR #248), and
  it only adds sim_reports persistence write-paths. No runtime code
  change in the window can explain the key-count drop.

  Primary suspect: MAXIM_SUBSTRATE_PATH=1 env-var regime change. PR
  #251 documented it as load-bearing on 5/14; the 5/12 historical
  baseline almost certainly ran without it. Different substrate
  routing regime explains different cluster shape. Both 2 reward-bias
  keys at every bisect step are interoception-modality EC nodes (12
  text-modality nodes exist but are not food-bearing) -- matches PR
  #251's analysis verbatim.

Axis 2 - bias magnitude (saturated -> partial): Wire-A's intentional
bio-fidelity fix.

  Step 2 (Wire-A merge) is where saturated +1.0 -> partial appears.
  The Wire-A pre-merge fold commit (bee42ca) explicitly added
  NAc.decay_cluster_reward_biases() per-tick decay, wired into
  agent_loop.py alongside decay_reward_biases() and
  decay_goal_reward_biases(). Per the fold commit description:
  "_cluster_reward_bias had no per-tick decay. Without it, Wire-A's
  annotation becomes a permanent fossil of every reward the substrate
  ever saw -- claiming 'from prior experience' while actually being
  'from forever ago.'"

  This is a Critical bio-fidelity finding folded BEFORE Wire-A's PR
  opened, per feedback_review_before_ship.md. Treating the partial-
  bias observation as a regression to fix would unwind a load-bearing
  bio-fidelity correction (the thesis-erosion pattern in
  feedback_interim_contamination.md).

Routing impact for the post-Roy-3 agenda:

  1. Affordance-replay bridge: no longer load-bearing for the priming-
     side count. The 6->2 drop is environmental, not a learning-rate
     problem. Stays 1.1+ candidate only on a separate diagnostic.
  2. Wire-A "strongly rewarding" render floor: reframes from "biases
     regressed below threshold" to "what priming repetition x reward
     strength x decay rate keeps end-priming clusters above 0.5
     band?" Tuning question, not a structural NAc fix.
  3. Roy-3 re-validation: unnecessary against this verdict. The 2-key
     partial pattern Roy-3a/3b observed is the bio-correct substrate
     state under MAXIM_SUBSTRATE_PATH=1 + Wire-A decay.

Disambiguating diagnostics (optional, neither required for verdict):

  A1 confirm key-count cause: re-run Roy-2 at cd51be5 WITHOUT
     MAXIM_SUBSTRATE_PATH=1. If 6 keys appear, env-var hypothesis
     confirmed. ~20 min wall.
  A2 confirm magnitude cause: re-run Steps 0/1 + Step 2 three times
     each to bound run-to-run variance. ~3 hours wall.

Headline: the 0.9.1 wires did NOT cause the Roy-3 regression. Two
axes, two outside causes, both bio-correct.

Files:
- docs/experiments/29_roy_3c_bisect.md (verdict writeup)
- Backups at ~/.maxim/roy/roy-2-bisect-COMMIT_SHORT/ for all six
  steps and ~/.maxim/sim_reports/bisect-COMMIT-SID/ report dirs

Cost: ~3 hours wall, $0 LLM (local leader).
No source changes. Diagnostic-only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ecay CONFIRMED

A1 result: env-var hypothesis REFUTED.

  Re-ran Roy-2 at cd51be5 with MAXIM_SUBSTRATE_PATH removed from the
  environment. Result: still 2 saturated reward-bias keys, identical
  to Step 0 with the env var on. The env var DOES affect EC substrate
  shape (12 text nodes added with it on vs 0 with it off), but NAc
  reward attribution lands on the same 2 interoception clusters either
  way -- no text-modality cluster is food-bearing in this priming.

  Revised key-count suspect: LLM narrator drift on the leader between
  5/13 and 5/23 (qwen2.5-14b per user_hardware_setup). Different
  narrator output -> different food-bearing percepts -> different EC
  clusters -> different reward attribution. Not testable by code
  bisect; testable by snapshotting cradle narrator outputs.

A2 result: Wire-A decay CONFIRMED behaviorally.

  Re-ran cd51be5 / 242235a / 629745a 2 more times each (n=3 per step).
  Pre-decay commits (cd51be5 + 242235a, n=7 total runs including
  earlier bisect + A1): all 7 produced saturated +1.0/+1.0.
  Post-decay 629745a (n=3 runs including original Step 2): all 3
  produced {partial, +0.98}, partial values +0.15 / +0.21 / +0.22.

  Zero overlap between pre- and post-decay magnitude distributions
  across 10 independent runs. Wire-A's bee42ca fold introducing
  NAc.decay_cluster_reward_biases() is the named causal mechanism
  for the magnitude axis.

User's "latent issue surfaced by the fix" hypothesis (post-mortem):

  Count axis: NO. Steps 0/1 run on the codebase BEFORE decay was
    wired and still produce 2 keys (n=7 runs). Decay cannot be what
    prunes 6 down to 2. The 6->2 gap is environmental, full stop.
  Magnitude axis: YES. Without decay every rewarded cluster sits at
    +1.0 forever, hiding the fact that priming under-reinforces most
    clusters. Decay makes the under-reinforcement visible. The
    partial-bias clusters are the substrate honestly representing
    "I saw this cluster once 40 turns ago and it hasn't fired since."
    Bio-correct; should be preserved.

Updated verdict (one line): the 0.9.1 wires did NOT cause the Roy-3
priming regression. The 6->2 key-count drop is environmental and (per
A1's refutation of the env-var hypothesis) most likely LLM narrator
drift, NOT MAXIM_SUBSTRATE_PATH=1. The saturated->partial magnitude
shift is Wire-A's intentional bio-fidelity decay correction (bee42ca),
confirmed behaviorally by A2.

Files:
- docs/experiments/29_roy_3c_bisect.md (writeup updated)
- ~/.maxim/roy/roy-2-bisect-<commit>-{A1,A2-r2,A2-r3}/ backups for
  the 7 new runs

Cost: ~3 hours wall, $0 LLM. No source changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dennys246
Copy link
Copy Markdown
Owner Author

A1+A2 disambiguations ran. Pushed 3f18d0d.

A1 — env-var hypothesis REFUTED. Roy-2 at cd51be5 with MAXIM_SUBSTRATE_PATH explicitly removed from the environment still produces 2 saturated reward-bias keys. The env var DOES add 12 text-modality EC nodes (vs 0 with it off), but NAc reward attribution lands on the same 2 interoception clusters either way — no text-modality cluster is food-bearing in this priming. Updated suspect for the 6→2 count axis: LLM narrator drift on the leader (qwen2.5-14b) between 5/13 and 5/23.

A2 — Wire-A decay CONFIRMED behaviorally. 3 extra runs at each of cd51be5 / 242235a / 629745a:

Commit Wire-A decay Runs Magnitudes
cd51be5 (n=4 incl. A1+r2+r3) OFF 4 all +1.0, +1.0
242235a (n=3 incl. r2+r3) OFF 3 all +1.0, +1.0
629745a (n=3 incl. r2+r3) ON 3 all {partial, +0.98}

Zero overlap between pre- and post-decay magnitude distributions across 10 independent runs. Wire-A's bee42ca fold introducing NAc.decay_cluster_reward_biases() is the named cause for the magnitude axis.

Latent-issue hypothesis answer:

  • Count axis (6→2): NO — Steps 0/1 run pre-decay and still produce 2 keys (n=7). Not surfaced by the fix; environmental.
  • Magnitude axis (saturated → partial): YES — without decay every rewarded cluster sits at +1.0 forever, hiding the fact that priming under-reinforces most clusters. Decay makes the under-reinforcement visible. Bio-correct.

…2 cause is non-code encoder-layer drift

Background: A1 refuted the env-var hypothesis. The post-A1 working
hypothesis was LLM narrator drift on the leader between 5/13 and
5/23, producing different cradle scene text -> different food-bearing
percepts -> different EC clusters. A3 ran the narrator capture to
test that hypothesis.

A3 result: narrator-drift hypothesis REFUTED.

  Captured the structured event stream at cd51be5 via
  MAXIM_LOG_FILE=/tmp/roy_3c_narrator_capture.jsonl. Three findings
  from the 39,121-event log:

  1. There is NO narrator scene text reaching the AUT during cradle
     priming. Every tick logs "Imagination skipped: no percept_text
     (obs keys: [])". Substrate-primary AUT in cradle priming arcs
     does not consume narrator-generated text.

  2. The 12 text-modality EC nodes come from substrate-INTERNAL state
     strings (drive:hunger(0.51), bias=+1.00, causal, cluster, pos=0.99,
     ->food, sense_food_source), not LLM scenes. These are
     deterministically generated from the substrate's own causal-link
     active_goal text every tick.

  3. AUT behavior is byte-identical between 5/12 historical and 5/24
     Step 0: 138 vs 139 sense_food_source calls, byte-identical tool
     output on every call ({'portions': 5.0, 'freshness': 0.9}), 667
     vs 664 hippocampus memories, 2001 vs 1992 NAc total_observations.
     The agent does the exact same activity volume with the exact
     same byte-level tool outputs. Only EC cluster attribution differs.

Updated key-count axis: non-code environmental drift in encoder layer.

  Ruled out: wire merges (bisect), env var (A1), narrator drift (A3),
  AUT behavior shift (A3). Across 4 cd51be5 runs today, interoception
  EC count is rock-stable at 2 (text varies 10-13 — the reward-bias
  keys are interoception-modality). Historical 5/12-5/13 produced 6
  interoception clusters for the same priming activity. With no
  clustering-affecting code change between 5/12 and 5/14 (only
  PR #246 EC instrumentation, PR #248 sim_reports persistence,
  PR #251 docs), remaining suspects are all non-code:

  - paraphrase-mpnet weight state (HF revision drift)
  - SensorEncoder SHA-basis depending on process startup state
    (PYTHONHASHSEED, numpy random state)
  - Persistent state in ~/.maxim/ affecting encoder warmup
  - CPU/numpy floating-point determinism between hosts/dates

  Closing this axis requires historical encoder-output snapshots
  that don't exist (PR #248 added EC persistence to sim_reports on
  5/14, AFTER the historical baseline runs).

Memory hygiene:
- feedback_narrator_state_confound.md updated to clarify that the
  rule applies to llm-primary AUT modes (generative campaigns) but
  NOT to substrate-primary AUT cradle priming, where no narrator
  text flows through the percept channel.
- project_roy_3c_bisect_verdict.md updated with the A3 refutation.

Magnitude axis unchanged: Wire-A's bee42ca decay is the confirmed
cause (A2 already proved this; A3 doesn't touch magnitude).

Files:
- docs/experiments/29_roy_3c_bisect.md (writeup updated with A3 section)
- ~/.maxim/roy/roy-2-bisect-cd51be5-NARRATOR-CAP/ + structured
  capture at /tmp/roy_3c_narrator_capture.jsonl

Cost: ~17 min wall (single A3 run). No source changes. Diagnostic-only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dennys246
Copy link
Copy Markdown
Owner Author

A3 disambiguation ran. Pushed c9ca491.

A3 — narrator-drift hypothesis REFUTED. Captured the structured event stream at cd51be5 via MAXIM_LOG_FILE. Three findings:

  1. No narrator text reaches the AUT during cradle priming. Every tick logs Imagination skipped: no percept_text (obs keys: []). Substrate-primary AUT in cradle priming doesn't consume narrator scenes.
  2. The 12 text-modality EC nodes come from substrate-internal state strings (drive:hunger(0.51), bias=+1.00, causal, cluster, pos=0.99, →food), not LLM scenes. Deterministically generated from causal-link active_goal text every tick.
  3. AUT behavior is byte-identical between 5/12 historical and 5/24 Step 0:
Metric 5/12 historical 5/24 Step 0
Tool calls 138 sense_food_source 139 sense_food_source
Tool output (every call) {'portions': 5.0, 'freshness': 0.9} byte-identical
Hippocampus memories 667 664
NAc total_observations 2001 1992
cluster_reward_bias keys 6 2

Same activity volume, byte-identical tool outputs — only EC cluster attribution differs.

Final key-count axis verdict: non-code environmental drift in encoder layer. Ruled out: wire merges (bisect), env var (A1), narrator drift (A3), AUT behavior shift (A3). Remaining suspects are all non-code (paraphrase-mpnet weights, SensorEncoder SHA-basis state, ~/.maxim/ persistent state, CPU/numpy float determinism). Closing this axis requires historical encoder-output snapshots that don't exist — PR #248 added EC persistence to sim_reports on 5/14, AFTER the historical baseline runs.

Magnitude axis unchanged: Wire-A's bee42ca decay is the confirmed cause via A2.

Implications for the routing decisions are unchanged from the A1+A2 update. The 6→2 count axis being non-code environmental drift (rather than env-var or narrator) doesn't change the conclusion that affordance-replay isn't load-bearing for it. Render-floor and re-validation reframes hold.

Roy-3c-bisect (PR #266) cleanly named Wire-A's bee42ca decay as the
magnitude-axis cause of the Roy-3 priming-side observation, AND
surfaced that the chosen tau was inherited by accident from
reward_bias_decay_tau=50.0 (sized for EC threshold modulation per
tick, NOT multi-turn substrate-voice annotation). Wire-A's annotation
was wired end-to-end but the LLM saw [neutral / mixed] at test time
(max(|bias|) = 0.036 / 0.098, below the 0.1 floor) because the decay
crushed the bias within Wire-A's render window.

This commit tees up the substantive Tier 2 work as a focused plan
doc. The plan supersedes Roy-3 follow-up item 2 ("decide whether
Wire-A's render needs a raw priming snapshot floor") with a cleaner,
bio-fidelity-respecting fix: split cluster_reward_bias_decay_tau from
reward_bias_decay_tau and tune the cluster-specific value to a
bio-plausible timescale for associative-memory extinction.

Same pattern Wire 2's percept_valence_decay_tau=200.0 already used.
The pre-merge bio-fidelity review B2 fold deliberately decoupled
percept valence from the inherited reward bias tau for the same
reason. Wire-A's bee42ca fold reused the inherited tau without
re-justifying it for the new use case.

Math: at tau=300, priming-end +0.98 bias decays to ~+0.51 at 225
ticks (mid-test-arm in Roy-3-shape iterations) — just above the 0.5
"strongly rewarding" band. Partial-bias +0.20 cluster decays to
~+0.10 at the same point — just at the 0.1 "mildly rewarding" floor.
Both classes stay expressive at Wire-A's render time without
becoming permanent fossils over many sessions.

Plan structure:
- Phase 1: add cluster_reward_bias_decay_tau field, default 300.0
- Phase 2: regression test guards
- Phase 3: Roy-3a-retry validating Wire-A becomes expressive
- Phase 4: companion experiment doc 30_wire_a_tau_validation.md
- Phase 5: fold verdict into release_0_9_1.md + v1_refinement.md

Total: ~270 LOC src+tests, ~1 runner day, low risk.

Files:
- docs/plans/cluster_reward_bias_decay_tau_split.md (new plan)
- docs/plans/README.md (Active list entry)
- docs/plans/release_0_9_1.md (Stage 5 outcome section folds the
  bisect verdict + supersedes the raw-snapshot floor follow-up item)

0.9.1 release status unchanged: ships per Roy-3's original
recommendation. The tau-split work is independent and is 0.9.2 / 1.0
follow-up — does NOT gate the version bump.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dennys246
Copy link
Copy Markdown
Owner Author

Tier 2 plan teed up. Pushed 4aab123.

docs/plans/cluster_reward_bias_decay_tau_split.md — DRAFT plan that supersedes Roy-3 follow-up item 2 ("raw priming snapshot floor") with a cleaner bio-fidelity-respecting fix:

The architectural smell. Wire-A's bee42ca decay fold reused reward_bias_decay_tau=50.0 for _cluster_reward_bias without re-justifying it for the new use case. The 50.0 was sized for EC threshold modulation per tick — fast adaptation so EC's recognition threshold tracks recent reward signal. Wire-A uses cluster reward bias for multi-turn substrate-voice annotation across a test phase — fundamentally different timescale concern.

The codebase already solved this same pattern once: Wire 2's percept_valence_decay_tau=200.0 was deliberately split off from reward_bias_decay_tau by the pre-merge bio-fidelity review B2 fold. Wire-A inherits the un-tuned default by accident, not by design.

The fix. Add cluster_reward_bias_decay_tau: float = 300.0 to NACConfig, point decay_cluster_reward_biases at it. Calibration: at tau=300, the priming-end +0.98 bias decays to ~+0.51 at mid-test-arm (225 ticks) — just above the 0.5 "strongly rewarding" band; partial +0.20 cluster decays to ~+0.10 — at the 0.1 "mildly rewarding" floor.

Five phases, ~270 LOC + ~1 runner day, low risk. Phase 3 is a Roy-3a-retry validating Wire-A becomes expressive (Arm A produces ≥1 sense_food_source call, vs Roy-3a baseline 0).

Preserves the bee42ca bio-fidelity correction. Decay still runs — just at a tau appropriate for Wire-A's substrate-voice annotation timescale, not EC's threshold-modulation timescale. Doesn't introduce a "raw snapshot" mechanism. One timeline, easier to reason about.

0.9.1 release status unchanged. Per Roy-3's original recommendation, 0.9.1 ships unchanged. This plan is 0.9.2 / 1.0 follow-up — does NOT gate the version bump.

release_0_9_1.md Stage 5 outcome section now folds the bisect verdict + tau-split plan reference. README.md Active plans list updated.

…s separate follow-up

User reviewed the three open questions in cluster_reward_bias_decay_tau_split.md:

Q1 (tau=300 default): RESOLVED. Confirmed at 300 as the starting
  calibration. Plan + memory now carry "subject to change" framing
  with explicit instructions: when decay feels wrong, this field
  is where to look first. New memory entry codifies the rule.

Q2 (env override clamp): RESOLVED at [50, 1000] for the tau-split
  plan, but the user surfaced a DEEPER bio-fidelity question that's
  separate from the clamp: should decay be wall-clock or SCN-tied
  rather than per-tick? It currently fires per agent_loop tick from
  section 8.5, which means effective decay-per-wall-second is
  hardware-dependent by ~10x across deployments (fast GPU + local
  LLM at ~15Hz vs slow CPU + cloud LLM at ~1-2Hz). All five NAc
  decay functions share this concern. SCN is the right home for
  the fix (already wall-clock-anchored, already integrated with
  NAc for B2 anticipatory pre-activation). Sequencing: tau split
  ships first (closes Roy-3 follow-up item 2); SCN-tying ships
  independently after — tau=300 ticks becomes tau=300 SCN-anchored
  units, calibration math preserved.

Q3 (Phase 3 n=1): RESOLVED. n=1 confirmed with extra log vigilance.
  Plan now specifies the four concrete logs to inspect on every
  Phase 3 run: Stage 0c sim_recommend_action JSONL for Wire-A
  annotation values, cluster_reward_bias decay trajectory across
  the test arm, cross-arm tool call distribution sanity, and
  Concept reinforced events for sense_food_source freshness.

Changes:
- docs/plans/cluster_reward_bias_decay_tau_split.md: tau=300
  subject-to-change language, new "Known limitation: decay is
  tick-anchored, not SCN-tied" section, Phase 3 log-vigilance
  subsection with the four concrete log surfaces, Open questions
  section now shows all three resolved.
- memory feedback_nac_decay_tau_is_calibration_knob.md: codifies
  the "tune the tau, do NOT bypass at consumer layer" rule with
  the Wire-A inheritance bug as the canonical anti-pattern.
- memory feedback_decay_is_tick_anchored_not_wall_clock.md: tracks
  the bio-fidelity gap + SCN-tying as the proper fix sequenced
  after the tau split.
- memory MEMORY.md: index entries for the two new feedback memories.

No source code changes. Plan + memory only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dennys246 dennys246 merged commit 374a581 into main May 26, 2026
5 checks passed
@dennys246 dennys246 deleted the feat/0-9-1-roy-3c-bisect branch May 26, 2026 02:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant