runtime: resume the learned stance in think, instead of discarding it #146

Merged
will.anderson merged 1 commits from fix/think-stance into dev 2026-08-16 16:44:18 +00:00
Owner

engram_think_json built a neutral stance on every call — cog_stance_init with a NULL id, all axis_gain 1.0, bias_dir NULL, reliability 0.5 — and never loaded the stance the correspondence-beat had been persisting.

That mattered because the faculty enters engram_think only through the stance: axis_gain[k] warps the per-axis extents and bias_dir seeds the steering direction. cog_stance_init stores the faculty name and nothing reads it. So reason/abduce/induce/plan/analogize were byte-identical output under different labels, and confidence was pinned to 0.5 because GeoGradient.confidence is stance->reliability.

The machinery already existed and only this call site ignored it: engram_correspondence_beat_json resumes via cog_stance_from_node and persists via cog_stance_to_node under stance-<faculty>-<hub>. Every beat’s calibration was written and thrown away on the next read. Same defect as the NULL anchor fixed in #142, one line below — a neutral argument collapsing a capability to a constant.

Verified against a clone of the production store (13,627 nodes)

step result
before any beat stance_resumed=false, confidence=0.5
beat on a non-keystone region brier 0.00458568 → 0.00329654, 28.11% reduction, n_trials 6000, reliability 0.930726, stance_written=true
after the beat stance_resumed=true, confidence=0.930726

Confidence now equals the learned reliability instead of the uninformed prior.

The keystone self-anchor correctly stays at 0.5 — calibration is deliberately refused on protected identity regions — and that refusal is now visible as resumed=true with confidence unchanged, rather than being indistinguishable from the bug.

stance_resumed is emitted for exactly that reason: confidence 0.5 from a learned-but-unreliable stance and confidence 0.5 from “no stance exists” were previously the same observation. That reporting gap is what let the neutral stance hide.

Still open, deliberately

With no learned bias_dir, the faculties remain identical in direction. What distinguishes abduce from induce geometrically is a design decision about how Neuron thinks — not a plumbing defect — and is left to Will rather than invented here.

`engram_think_json` built a **neutral** stance on every call — `cog_stance_init` with a NULL id, all `axis_gain` 1.0, `bias_dir` NULL, `reliability` 0.5 — and never loaded the stance the correspondence-beat had been persisting. That mattered because **the faculty enters `engram_think` only through the stance**: `axis_gain[k]` warps the per-axis extents and `bias_dir` seeds the steering direction. `cog_stance_init` stores the faculty *name* and nothing reads it. So `reason`/`abduce`/`induce`/`plan`/`analogize` were byte-identical output under different labels, and `confidence` was pinned to 0.5 because `GeoGradient.confidence` **is** `stance->reliability`. The machinery already existed and only this call site ignored it: `engram_correspondence_beat_json` resumes via `cog_stance_from_node` and persists via `cog_stance_to_node` under `stance-<faculty>-<hub>`. **Every beat’s calibration was written and thrown away on the next read.** Same defect as the NULL anchor fixed in #142, one line below — a neutral argument collapsing a capability to a constant. ### Verified against a clone of the production store (13,627 nodes) | step | result | |---|---| | before any beat | `stance_resumed=false`, `confidence=0.5` | | beat on a **non-keystone** region | brier `0.00458568 → 0.00329654`, **28.11% reduction**, `n_trials 6000`, `reliability 0.930726`, `stance_written=true` | | after the beat | `stance_resumed=true`, **`confidence=0.930726`** | Confidence now equals the learned reliability instead of the uninformed prior. The keystone self-anchor correctly stays at 0.5 — calibration is deliberately refused on protected identity regions — and that refusal is now *visible* as `resumed=true` with confidence unchanged, rather than being indistinguishable from the bug. `stance_resumed` is emitted for exactly that reason: confidence 0.5 from a learned-but-unreliable stance and confidence 0.5 from “no stance exists” were previously the same observation. That reporting gap is what let the neutral stance hide. ### Still open, deliberately With no learned `bias_dir`, the faculties remain identical in *direction*. What distinguishes `abduce` from `induce` geometrically is a design decision about how Neuron thinks — not a plumbing defect — and is left to Will rather than invented here.
will.anderson added 1 commit 2026-08-16 16:44:04 +00:00
runtime: resume the learned stance in think, instead of discarding it
El SDK CI - dev / build-and-test (pull_request) Failing after 4m16s
88e3008735
engram_think_json built a NEUTRAL stance on every call — cog_stance_init
with a NULL id, all axis_gain 1.0, bias_dir NULL, reliability 0.5 — and
never loaded the stance the correspondence-beat had been persisting.

That mattered because the faculty enters engram_think ONLY through the
stance: axis_gain[k] warps the per-axis extents and bias_dir seeds the
steering direction. cog_stance_init stores the faculty NAME and nothing
reads it. So with a neutral stance, reason/abduce/induce/plan/analogize
were byte-identical output under different labels, and confidence was
pinned to 0.5 because GeoGradient.confidence IS stance->reliability.

The machinery already existed and only this call site ignored it.
engram_correspondence_beat_json resumes via cog_stance_from_node and
persists via cog_stance_to_node under "stance-<faculty>-<hub>". Every
beat's calibration was written and then thrown away on the next read.
Same defect as the NULL anchor fixed in #142, one line below: a neutral
argument collapsing a capability to a constant.

Resume the same id the beat writes, so learning compounds across beats and
cold boot. Fall back to neutral only when no stance exists — a genuine
uninformed prior rather than a discarded informed one.

Also emit stance_resumed, so confidence 0.5 from a learned-but-unreliable
stance is distinguishable from confidence 0.5 from "no stance exists".
That reporting gap is what let the neutral stance hide.

Verified against a clone of the production store (13,627 nodes):

  before beat, no stance     stance_resumed=false  confidence=0.5
  beat on a NON-keystone     brier 0.00458568 -> 0.00329654
                             reduction 28.11%, n_trials 6000,
                             reliability 0.930726, stance_written=true
  after beat                 stance_resumed=true   confidence=0.930726

Confidence now equals the learned reliability instead of the uninformed
prior. The keystone self-anchor correctly stays at 0.5 — calibration is
deliberately refused on protected identity regions, and that refusal is
now visible as resumed=true with confidence unchanged, rather than being
indistinguishable from the bug.

STILL OPEN: with no learned bias_dir the faculties remain identical in
direction. What distinguishes abduce from induce geometrically is a
design decision about how Neuron thinks, not a plumbing defect, and is
deliberately left to Will.
will.anderson merged commit eb3e6d7c1f into dev 2026-08-16 16:44:18 +00:00
Sign in to join this conversation.