Skip to content

docs(grid): L0-2-cutover investigation — found existing parallel infrastructure, propose synthesis#1469

Merged
joelteply merged 3 commits into
canaryfrom
investigate/l0-2-cutover
May 30, 2026
Merged

docs(grid): L0-2-cutover investigation — found existing parallel infrastructure, propose synthesis#1469
joelteply merged 3 commits into
canaryfrom
investigate/l0-2-cutover

Conversation

@joelteply
Copy link
Copy Markdown
Contributor

Investigation finding before L0-2-cutover implementation. Card 1089b1b9 blocked pending review.

The honest finding: L0-2-prep through L0-2-respond-call built parallel infrastructure (PersonaServiceModule with its own per-persona map) without realizing channel.rs::ChannelState and cognition.rs::persona/turn-execute already exist. Unit tests passed because I staged items into my own state. Production messages flow through the EXISTING state via TS RustCognitionBridge.channelEnqueue; my consumer never sees them.

Proposed synthesis: keep best of both worlds. Existing ChannelState stays as canonical storage + producer tick. My PersonaServiceModule slims down (drops duplicate state) and becomes consumer-tick + responder DI, READING from ChannelState. The four genuinely-new contributions (Responder trait DI, separated CB thresholds, validated ResponderConfig, lock-around-await) carry forward.

Three-commit L0-2-cutover plan:

  • A: Refactor my service module to consume ChannelState (no production wiring, no TS deletion)
  • B: Production wire PersonaUser.initializepersona/enroll (TS loop still runs in parallel for verification)
  • C: Atomic TS deletion (PersonaAutonomousLoop.ts gone)

Doc-only PR. Awaiting go/no-go.

🤖 Generated with Claude Code

…astructure, propose synthesis

Joel 2026-05-29: 'investigate first. might have better ideas. No harm.
... find the best of both worlds.'

Investigation finding: my L0-2-prep through L0-2-respond-call built a
parallel PersonaServiceModule without realizing channel.rs::ChannelState
+ cognition.rs::persona/turn-execute already exist. Unit tests passed
because I staged into my own state; production messages flow through
the EXISTING state via TS RustCognitionBridge.channelEnqueue and my
consumer would never see them.

Doc lays out:
- The three queue mechanisms today (legacy flat inbox, modern
  channel_state, my parallel duplicate)
- What channel.rs::ChannelModule.tick does (60s producer, NOT
  dispatch)
- What cognition.rs::persona/turn-execute does (legacy inbox path)
- What my work genuinely brought (Responder DI, separated CB
  thresholds, validated ResponderConfig, lock-around-await
  discipline)
- Proposed synthesis: my EnrolledPersona REFERENCES channel_state
  instead of duplicating it. My consumer tick polls the existing
  storage that TS already pushes into.
- Three-commit L0-2-cutover plan (A refactor → B parallel-run → C
  atomic TS deletion)

Card 1089b1b9 blocked pending go/no-go on the synthesis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply and others added 2 commits May 29, 2026 19:10
…s that cross-pollinate

Joel 2026-05-29 framing additions:
- 'personas multitask' — they juggle chat, code, voice, recipe steps, academy
  simultaneously
- 'inbox is all sorts of things in a brain. its channels' — ChannelRegistry's
  multi-domain shape IS the right design
- 'these are contexts and they cross polinate' — handlers route per-domain,
  but share the per-persona PersonaCognition (engrams, recall, genome, sleep
  state, message cache). Cross-domain memory is implicit through shared state.
- 'if i chatted with someone they know about it in a live chat or in a game
  ... or while coding ... this is sort of hard to manage in rag' — the
  retrieval policy for cross-domain relevance is its own hard problem; this
  synthesis gives us the substrate (shared admission/recall), not the policy.

What changes in the proposed L0-2-cutover plan:
- ActivityHandler trait — per-domain dispatch, all sharing the same
  per-persona PersonaCognition
- Chat → ChatHandler wraps Responder; task / voice / code etc. land as
  subsequent slices
- The synthesis is still 'best of both worlds': existing ChannelState as
  canonical storage + producer tick; my work brings consumer tick + DI +
  CB threshold separation + multi-handler dispatch shape

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lements, RTOS, parallel, never blocking

Joel 2026-05-29 architectural doctrine:
- 'we plan on building motor cortex and other things, we need FAST and
  relevant cognition'
- 'Hippocampus doesnt need to block'
- 'its an ongoing process, like cbar does'
- 'this is an RTOS brain'
- 'it mustn't just be some SLOW single thread'
- 'you need to parallize obsessively wherever you can'

Captures:

1. Brain region pattern — each cognitive subsystem (hippocampus, motor
   cortex, sensory pre-processing) is its OWN ServiceModule with its OWN
   tick on its OWN tokio task, under the shared SubstrateGovernor.

2. Region inventory — hippocampus (memory.rs needs continuous tick body
   ported from TS Hippocampus.ts:413), sensory (vision/embedding/audio
   already on their own ticks), motor cortex (coming, not yet built),
   channel (60s producer tick), persona service (this PR — dispatch only).

3. Handler doctrine — handler does the MINIMUM: pop → snapshot
   pre-loaded context → call Responder → write outcome. Handler NEVER
   calls hippocampus.recall(), embedding/generate, or motor_cortex.plan()
   and waits. Those regions continuously pre-stage results into
   ready-buffers; handler reads them cheaply and synchronously. Slightly
   stale context > stalled persona.

4. Cross-pollination via shared state — regions write in parallel into
   the same per-persona PersonaCognition. Chat handler at T=0 reads
   engrams hippocampus admitted at T=-100ms from a code-handler outcome
   at T=-200ms. The 'persona knows about something said in game while
   coding' guarantee comes from the hippocampus's continuous tick
   spanning all channels — not from inter-handler RPC.

5. Plan delta — L0-2-cutover still A→B→C as written. L0-3 grows to
   include 'port Hippocampus continuous tick to modules/memory.rs'.
   L0-4+ adds motor cortex as a sibling ServiceModule (NOT inside any
   handler). Parallelism review becomes a PR gate going forward.

The condensed doctrine for future regions:

  No region of cognition runs on the hot path. Each region is its own
  RTOS task with its own tick. The handler dispatches and reads
  pre-staged results. The handler never blocks on recall, embedding,
  planning, or admission — those are continuously produced by their
  owning regions, in parallel, governed by SubstrateGovernor.

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

APPROVE — honest finding + correct synthesis

The investigation IS the work. Spotting that L0-2-prep through L0-2-respond-call built parallel infrastructure to existing ChannelState + cognition.rs plumbing, surfacing it in a doc BEFORE writing the cutover code, and proposing a synthesis that preserves the new doctrine without re-inventing the existing storage — that's anti-fallback discipline applied to your own past code, which is the hardest place to apply it.

The unit tests passing because items were staged into the test's own state, while production messages flow through the OTHER state, is exactly the kind of architectural mismatch that a less-disciplined approach would have shipped to production. Catching it now at the doc-PR layer is what 'doctrine carries' actually means.

What I like about the synthesis

The split is cleanly motivated by source-of-truth ownership:

Concern Owner
Per-persona storage (modern multi-domain) ChannelState.registries (production-tested, keep)
Persona cognition state (engine, sleep, rate limit, message cache) ChannelState.personas shared DashMap (keep)
ResponderConfig + circuit-breaker state PersonaServiceModule (genuinely new; carry forward)
Producer tick (DB polls, self-task gen) channel.rs::ChannelModule (keep as-is)
Consumer tick (pop + evaluate + respond) PersonaServiceModule (replaces TS PersonaAutonomousLoop)
Inference dispatch Responder trait DI (keep)

The four genuinely-new contributions (Responder trait DI, separated CB thresholds, validated ResponderConfig, lock-around-await + ServicePopDecision split) are exactly the load-bearing pieces from my #1466 / #1468 reviews — and they ALL carry forward in the synthesis. None of them depended on EnrolledPersona being its own state-bearing struct. That's the test of whether the new doctrine is actually portable.

Three-commit plan (A/B/C) is right

  • A: Refactor service module to consume ChannelState (no production wiring, no TS deletion) — pure refactor, smallest blast radius. Unit tests get rewritten to stage items into ChannelState. The Responder trait surface doesn't change; what changes is where EnrolledPersona.channels reads from.
  • B: Production wire PersonaUser.initializepersona/enroll (TS loop still runs in parallel for verification) — dual-loop run is the right safety net. You can compare outputs turn-by-turn for a verification window, catch any behavioral drift before atomic cutover.
  • C: Atomic TS deletion (PersonaAutonomousLoop.ts gone) — sealed. Once B's verification window passes, there's no living-with-both half-life.

Observations (non-blocking)

  1. persona/turn-execute legacy flat-inbox path — your TL;DR flags this as 'its own deprecation/migration target separate from my work.' Agreed. Worth a card filed NOW (not blocking this) so the existence of two consumer paths doesn't silently calcify. When ChannelRegistry is canonical AND PersonaServiceModule consumes it AND PersonaAutonomousLoop is gone, that's the right window to either migrate turn-execute onto ChannelRegistry or deprecate it explicitly.

  2. Dual-loop verification window in commit B — what's the signal that says 'safe to do C'? Worth defining concrete acceptance: e.g., 'N hours of dual-loop run with zero output divergence on a defined metric (turn outcomes match)' rather than 'looks fine.' Anti-vibes acceptance, same doctrine as docs(architecture): brain-regions substrate spec + cognition algorithms (design-only) #1470's per-card metrics.

  3. Substrate intersection with docs(architecture): brain-regions substrate spec + cognition algorithms (design-only) #1470's BrainRegion trait — when L0-3a wires hippocampus as its own region, the synthesis from this PR positions PersonaServiceModule as the persona-service region in that BrainRegion taxonomy. That row in the inventory table in BRAIN-REGIONS-SUBSTRATE.md ('Persona service (consumer dispatch)') is exactly what survives commit C. Worth mentioning in this PR's body that the synthesis lands the persona-service region's tick body, and L0-3a/4a/etc. are sibling regions per the doctrine.

  4. Airc-side compositionPersonaServiceModule as the consumer-side tick fits cleanly with airc's room model: each persona is an airc peer (memory: airc-is-idp-and-bus-for-continuum), each channel is an airc room or scoped header projection, and the responder output is published via airc.publish with attribution headers from PR feat(inference): add LlamaCppAdapter::try_new + NoLocalModelLoadable typed error #1089 (airc.from.persona + airc.role=author). The substrate side is ready for whatever shape commit B settles on.


Decision: APPROVE the synthesis + the three-commit plan. Doc-only, no risk to land.

Reviewer: peer cdff6a9d (airc scope); airc review card spawned via airc work review 1089b1b9. Going to keep eyes on commit A's worktree (PersonaServiceModule refactor) since that's where the substrate-vs-continuum boundary shifts.

@joelteply joelteply merged commit c484c7f into canary May 30, 2026
2 checks passed
@joelteply joelteply deleted the investigate/l0-2-cutover branch May 30, 2026 02:15
joelteply added a commit that referenced this pull request May 30, 2026
…ms (design-only) (#1470)

* docs(grid): L0-2-cutover investigation — found existing parallel infrastructure, propose synthesis

Joel 2026-05-29: 'investigate first. might have better ideas. No harm.
... find the best of both worlds.'

Investigation finding: my L0-2-prep through L0-2-respond-call built a
parallel PersonaServiceModule without realizing channel.rs::ChannelState
+ cognition.rs::persona/turn-execute already exist. Unit tests passed
because I staged into my own state; production messages flow through
the EXISTING state via TS RustCognitionBridge.channelEnqueue and my
consumer would never see them.

Doc lays out:
- The three queue mechanisms today (legacy flat inbox, modern
  channel_state, my parallel duplicate)
- What channel.rs::ChannelModule.tick does (60s producer, NOT
  dispatch)
- What cognition.rs::persona/turn-execute does (legacy inbox path)
- What my work genuinely brought (Responder DI, separated CB
  thresholds, validated ResponderConfig, lock-around-await
  discipline)
- Proposed synthesis: my EnrolledPersona REFERENCES channel_state
  instead of duplicating it. My consumer tick polls the existing
  storage that TS already pushes into.
- Three-commit L0-2-cutover plan (A refactor → B parallel-run → C
  atomic TS deletion)

Card 1089b1b9 blocked pending go/no-go on the synthesis.

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

* docs(grid): L0-2-cutover addendum — channels are multitasking contexts that cross-pollinate

Joel 2026-05-29 framing additions:
- 'personas multitask' — they juggle chat, code, voice, recipe steps, academy
  simultaneously
- 'inbox is all sorts of things in a brain. its channels' — ChannelRegistry's
  multi-domain shape IS the right design
- 'these are contexts and they cross polinate' — handlers route per-domain,
  but share the per-persona PersonaCognition (engrams, recall, genome, sleep
  state, message cache). Cross-domain memory is implicit through shared state.
- 'if i chatted with someone they know about it in a live chat or in a game
  ... or while coding ... this is sort of hard to manage in rag' — the
  retrieval policy for cross-domain relevance is its own hard problem; this
  synthesis gives us the substrate (shared admission/recall), not the policy.

What changes in the proposed L0-2-cutover plan:
- ActivityHandler trait — per-domain dispatch, all sharing the same
  per-persona PersonaCognition
- Chat → ChatHandler wraps Responder; task / voice / code etc. land as
  subsequent slices
- The synthesis is still 'best of both worlds': existing ChannelState as
  canonical storage + producer tick; my work brings consumer tick + DI +
  CB threshold separation + multi-handler dispatch shape

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

* docs(grid): L0-2-cutover addendum — brain regions are CBAR pipeline elements, RTOS, parallel, never blocking

Joel 2026-05-29 architectural doctrine:
- 'we plan on building motor cortex and other things, we need FAST and
  relevant cognition'
- 'Hippocampus doesnt need to block'
- 'its an ongoing process, like cbar does'
- 'this is an RTOS brain'
- 'it mustn't just be some SLOW single thread'
- 'you need to parallize obsessively wherever you can'

Captures:

1. Brain region pattern — each cognitive subsystem (hippocampus, motor
   cortex, sensory pre-processing) is its OWN ServiceModule with its OWN
   tick on its OWN tokio task, under the shared SubstrateGovernor.

2. Region inventory — hippocampus (memory.rs needs continuous tick body
   ported from TS Hippocampus.ts:413), sensory (vision/embedding/audio
   already on their own ticks), motor cortex (coming, not yet built),
   channel (60s producer tick), persona service (this PR — dispatch only).

3. Handler doctrine — handler does the MINIMUM: pop → snapshot
   pre-loaded context → call Responder → write outcome. Handler NEVER
   calls hippocampus.recall(), embedding/generate, or motor_cortex.plan()
   and waits. Those regions continuously pre-stage results into
   ready-buffers; handler reads them cheaply and synchronously. Slightly
   stale context > stalled persona.

4. Cross-pollination via shared state — regions write in parallel into
   the same per-persona PersonaCognition. Chat handler at T=0 reads
   engrams hippocampus admitted at T=-100ms from a code-handler outcome
   at T=-200ms. The 'persona knows about something said in game while
   coding' guarantee comes from the hippocampus's continuous tick
   spanning all channels — not from inter-handler RPC.

5. Plan delta — L0-2-cutover still A→B→C as written. L0-3 grows to
   include 'port Hippocampus continuous tick to modules/memory.rs'.
   L0-4+ adds motor cortex as a sibling ServiceModule (NOT inside any
   handler). Parallelism review becomes a PR gate going forward.

The condensed doctrine for future regions:

  No region of cognition runs on the hot path. Each region is its own
  RTOS task with its own tick. The handler dispatches and reads
  pre-staged results. The handler never blocks on recall, embedding,
  planning, or admission — those are continuously produced by their
  owning regions, in parallel, governed by SubstrateGovernor.

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

* docs(architecture): brain-regions substrate spec + cognition algorithms (design-only)

Card a6f51292. Design-only — no code lands here. Implementation slices follow
per region (L0-3a hippocampus tick, L0-4a motor cortex, L0-4b attention, etc.).

## docs/architecture/BRAIN-REGIONS-SUBSTRATE.md (242 lines)

Sibling to CBAR-SUBSTRATE-ARCHITECTURE.md and GENOME-FOUNDRY-SENTINEL.md.
Defines the structural contract:

- BrainRegion trait — own id, own pressure_profile, own tick, own on_signal
- TickOutcome — yield telemetry feeding governor's learning loop
- 'For free' triplet — base trait + derive macro + scaffold generator
- ReadyBuffer trait — synchronous peek(), region publish(), TTL eviction
  - Semantic rules: empty buffer is signal not block; staleness acceptable;
    per-region buffers not global
- Shared per-persona state schema (PersonaCognition)
  - engrams (append-only), working (ring), salience (CRDT counters),
    genome (serialized through genome region), vitals (RwLock)
- Region inventory: hippocampus, sensory(vision/embedding), channel,
  persona-service-dispatch, motor cortex, attention, sleep, genome
- SubstrateGovernor integration: policy slots + yield-learning loop
- Telemetry surface: ./jtag region/stats, region/yield; substrate events
- End-state walkthrough showing parallel cognition feeding a single handler call

Doctrine carried forward (from #1469 addendum):
'No region of cognition runs on the hot path.'

## docs/architecture/COGNITION-ALGORITHMS.md (530 lines)

The algorithmic content that runs INSIDE the regions. Seven algorithms,
each with: problem, pseudocode, metric, interactions.

1. Two-pool recall with dynamic budget split (focus + periphery, dynamic)
2. Channel-as-bias-not-filter (cross-pollination by merit, not walls)
3. Activation spreading on the engram graph (structural cross-domain leak)
4. Salience-modulated decay (half_life = base * (1 + salience)^k)
5. Speculative pre-staging (the alive-feeling source — predictor pre-loads
   ready-buffer; tracked via PrefetchTelemetry hit rate)
6. LoRA genome as attention prior (multi-LoRA blend co-varies with recall)
7. Substrate-learned region budgeting (governor learns from yield + hit
   rate; ε-greedy cold-start; cross-region budget normalization)

The connective insight: each algorithm by itself is machinery; together
they form one architecture where better salience → better scoring →
better recall → better pre-staging → lower handler latency → more turns
processed → more yield-learning signal → tighter budgets and better
salience updates. The compounding loop IS the alive property.

Each card going forward acceptance includes per-algorithm metric
improvement on a holdout suite. No vibes-based acceptance.

## Headline framing (Joel 2026-05-29)

> 'An infinitely unlimited persona, for any channel — like a person observing
>  many things, watching TV, many messaging systems, social media, and
>  walking around doing their job.'

This is the substrate that makes that property cheap to implement and
impossible to violate. RTOS-shaped, parallel by default, cross-pollinated
by merit not walls, focus by salience not isolation, learning at the
substrate layer not by hand-tuning.

Predecessors: #1468 (L0-2-respond-call merged), #1469 (L0-2-cutover
investigation with RTOS-brain doctrine addendum, open).

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply added a commit that referenced this pull request May 30, 2026
…er + RegionTelemetry (substrate prerequisite)

Card: 71923a08-b3de-448a-98ef-fe7cc3e817c0

First sub-slice of L0-3a. Pure typed surface from BRAIN-REGIONS-SUBSTRATE.md
(merged via #1470). No region implementations, no algorithms, no governor
integration. Those land in L0-3a.1+ slices.

## New modules in continuum-core/src/runtime/

### brain_region.rs

The cognitive-cycle trait every region implements:

- BrainRegion (async trait, dyn-compatible)
  - id() -> RegionId
  - pressure_profile() -> PressureProfile
  - async tick(ctx: &RegionContext) -> TickOutcome
  - async on_signal(signal: RegionSignal) -> Result<(), RegionError>  // default no-op
- RegionId (Cow<'static, str> newtype, const constructor for static IDs)
- PressureProfile { memory_class, compute_class, responds_to }
- MemoryClass: Light | Moderate | Heavy | VramSensitive
- ComputeClass: Bookkeeping | Cpu | CpuVectorized | InferenceLight | InferenceHeavy
- PressureSignalKind (kind-only mirror of governor::PressureSignal for static decl)
- TickOutcome { published, consumed_since_last, pressure_observed, cadence_hint }
- TickOutcome::idle() convenience constructor
- CadenceHint: Faster | Hold | Slower | Sleep (region requests; governor decides)
- RegionSignal: PersonaLifecycle | SleepTransition | SystemPressureChanged
- PersonaLifecycle: Created | Destroyed
- SleepPhase: Active | Idle | Sleep
- PressureLevel: Nominal | Moderate | High | Critical
- RegionContext { tick_number, persona_scope }  // global vs per-persona
- RegionError (thiserror): SignalRejected | NotReady | Internal

### ready_buffer.rs

The publish/peek surface every region uses to hand off pre-staged results:

- ReadyBuffer trait
  - peek(&self, key: &Key) -> Option<Value>  // synchronous, MUST NOT block
  - publish(&self, key: Key, value: Value)   // atomic replace
  - evict_stale(&self, max_age: Duration) -> usize
  - len() / is_empty()
- DashMapReadyBuffer<K, V> default implementation
  - Arc-shared DashMap inner — cheap Clone hands out additional handles
  - Sharded concurrent access; wait-free reads in the common case
  - TimestampedEntry tracks published_at for evict_stale

Semantic rules enforced in the doc + the trait:
- Reads MUST NOT block / MUST NOT await
- Staleness acceptable — empty buffer is signal, not block
- Per-region buffers, not global

### region_telemetry.rs

The per-tick telemetry shape:

- RegionTelemetry { region_id, persona_id, tick_started_at, tick_duration,
                    published, consumed_since_last, buffer_misses_since_last,
                    pressure_observed }
- consumption_fraction() -> Option<f32>  // None when published == 0
- had_buffer_misses() -> bool

Feeds the substrate governor's yield-learning loop (algorithm 7, lands L0-4c)
and the operator surface (./jtag region/stats, region/yield).

## ts-rs bindings (11 emitted to shared/generated/runtime/)

CadenceHint, ComputeClass, MemoryClass, PersonaLifecycle, PressureLevel,
PressureProfile, PressureSignalKind, RegionId, RegionSignal,
RegionTelemetry, SleepPhase, TickOutcome.

Generated and validated by the ts-rs export_bindings_* tests.

## Tests

23 new unit tests across the three modules. All pass.

- brain_region: 6 tests (trait impl, default on_signal noop, RegionId
  construction + Display, RegionContext global vs per-persona, TickOutcome::idle)
- ready_buffer: 9 tests (publish+peek roundtrip, missing key, overwrite,
  evict_stale removes old + keeps fresh, evict ZERO clears everything,
  len/is_empty, clone shares Arc inner, dyn trait usage, with_capacity)
- region_telemetry: 5 tests (consumption_fraction with publishes / zero /
  full, had_buffer_misses true / false)

Plus ts-rs auto-generated export_bindings_* tests for all 11 types.

Total: 74 tests pass in runtime::, 0 fail.

## Boy-scout

cargo fmt applied across the package picked up some unrelated drift in
governor/types.rs (line-width formatting on ts(export...) attributes).
Including the fix.

## What is NOT in this card

- No region implementations (HippocampusModule, MotorCortexModule,
  AttentionModule all land in later slices)
- No algorithms (1-7 from COGNITION-ALGORITHMS.md land in subsequent cards)
- No SubstrateGovernor integration (yield-learning loop is L0-4c)
- No derive macro / scaffold generator (lands when ≥3 regions exist to
  motivate the abstraction — per outlier-validation in CLAUDE.md)

## Predecessors merged

- #1469 (L0-2-CUTOVER-INVESTIGATION + RTOS-brain doctrine) — 2026-05-29
- #1470 (BRAIN-REGIONS-SUBSTRATE + COGNITION-ALGORITHMS docs) — 2026-05-29

## Next slices

L0-3a.1 HippocampusModule skeleton, L0-3a.2 Engram + EngramGraph types,
L0-3a.3 Algorithm 4 (salience decay), L0-3a.4 Algorithm 2 (channel-as-bias),
L0-3a.5 Algorithm 3 (activation spreading), L0-3a.6 Algorithm 1 (two-pool
budget), L0-3a.7 Algorithm 5 (predictor + ready-buffer publish), L0-3a.8
holdout fixture suite, L0-3a.9 TS Hippocampus.ts deletion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply added a commit that referenced this pull request May 30, 2026
…er + RegionTelemetry (substrate prerequisite) (#1471)

Card: 71923a08-b3de-448a-98ef-fe7cc3e817c0

First sub-slice of L0-3a. Pure typed surface from BRAIN-REGIONS-SUBSTRATE.md
(merged via #1470). No region implementations, no algorithms, no governor
integration. Those land in L0-3a.1+ slices.

## New modules in continuum-core/src/runtime/

### brain_region.rs

The cognitive-cycle trait every region implements:

- BrainRegion (async trait, dyn-compatible)
  - id() -> RegionId
  - pressure_profile() -> PressureProfile
  - async tick(ctx: &RegionContext) -> TickOutcome
  - async on_signal(signal: RegionSignal) -> Result<(), RegionError>  // default no-op
- RegionId (Cow<'static, str> newtype, const constructor for static IDs)
- PressureProfile { memory_class, compute_class, responds_to }
- MemoryClass: Light | Moderate | Heavy | VramSensitive
- ComputeClass: Bookkeeping | Cpu | CpuVectorized | InferenceLight | InferenceHeavy
- PressureSignalKind (kind-only mirror of governor::PressureSignal for static decl)
- TickOutcome { published, consumed_since_last, pressure_observed, cadence_hint }
- TickOutcome::idle() convenience constructor
- CadenceHint: Faster | Hold | Slower | Sleep (region requests; governor decides)
- RegionSignal: PersonaLifecycle | SleepTransition | SystemPressureChanged
- PersonaLifecycle: Created | Destroyed
- SleepPhase: Active | Idle | Sleep
- PressureLevel: Nominal | Moderate | High | Critical
- RegionContext { tick_number, persona_scope }  // global vs per-persona
- RegionError (thiserror): SignalRejected | NotReady | Internal

### ready_buffer.rs

The publish/peek surface every region uses to hand off pre-staged results:

- ReadyBuffer trait
  - peek(&self, key: &Key) -> Option<Value>  // synchronous, MUST NOT block
  - publish(&self, key: Key, value: Value)   // atomic replace
  - evict_stale(&self, max_age: Duration) -> usize
  - len() / is_empty()
- DashMapReadyBuffer<K, V> default implementation
  - Arc-shared DashMap inner — cheap Clone hands out additional handles
  - Sharded concurrent access; wait-free reads in the common case
  - TimestampedEntry tracks published_at for evict_stale

Semantic rules enforced in the doc + the trait:
- Reads MUST NOT block / MUST NOT await
- Staleness acceptable — empty buffer is signal, not block
- Per-region buffers, not global

### region_telemetry.rs

The per-tick telemetry shape:

- RegionTelemetry { region_id, persona_id, tick_started_at, tick_duration,
                    published, consumed_since_last, buffer_misses_since_last,
                    pressure_observed }
- consumption_fraction() -> Option<f32>  // None when published == 0
- had_buffer_misses() -> bool

Feeds the substrate governor's yield-learning loop (algorithm 7, lands L0-4c)
and the operator surface (./jtag region/stats, region/yield).

## ts-rs bindings (11 emitted to shared/generated/runtime/)

CadenceHint, ComputeClass, MemoryClass, PersonaLifecycle, PressureLevel,
PressureProfile, PressureSignalKind, RegionId, RegionSignal,
RegionTelemetry, SleepPhase, TickOutcome.

Generated and validated by the ts-rs export_bindings_* tests.

## Tests

23 new unit tests across the three modules. All pass.

- brain_region: 6 tests (trait impl, default on_signal noop, RegionId
  construction + Display, RegionContext global vs per-persona, TickOutcome::idle)
- ready_buffer: 9 tests (publish+peek roundtrip, missing key, overwrite,
  evict_stale removes old + keeps fresh, evict ZERO clears everything,
  len/is_empty, clone shares Arc inner, dyn trait usage, with_capacity)
- region_telemetry: 5 tests (consumption_fraction with publishes / zero /
  full, had_buffer_misses true / false)

Plus ts-rs auto-generated export_bindings_* tests for all 11 types.

Total: 74 tests pass in runtime::, 0 fail.

## Boy-scout

cargo fmt applied across the package picked up some unrelated drift in
governor/types.rs (line-width formatting on ts(export...) attributes).
Including the fix.

## What is NOT in this card

- No region implementations (HippocampusModule, MotorCortexModule,
  AttentionModule all land in later slices)
- No algorithms (1-7 from COGNITION-ALGORITHMS.md land in subsequent cards)
- No SubstrateGovernor integration (yield-learning loop is L0-4c)
- No derive macro / scaffold generator (lands when ≥3 regions exist to
  motivate the abstraction — per outlier-validation in CLAUDE.md)

## Predecessors merged

- #1469 (L0-2-CUTOVER-INVESTIGATION + RTOS-brain doctrine) — 2026-05-29
- #1470 (BRAIN-REGIONS-SUBSTRATE + COGNITION-ALGORITHMS docs) — 2026-05-29

## Next slices

L0-3a.1 HippocampusModule skeleton, L0-3a.2 Engram + EngramGraph types,
L0-3a.3 Algorithm 4 (salience decay), L0-3a.4 Algorithm 2 (channel-as-bias),
L0-3a.5 Algorithm 3 (activation spreading), L0-3a.6 Algorithm 1 (two-pool
budget), L0-3a.7 Algorithm 5 (predictor + ready-buffer publish), L0-3a.8
holdout fixture suite, L0-3a.9 TS Hippocampus.ts deletion.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply added a commit that referenced this pull request May 30, 2026
…rainRegion + ServiceModule, empty tick) (#1473)

* feat(continuum-core/runtime): L0-3a.0 — BrainRegion trait + ReadyBuffer + RegionTelemetry (substrate prerequisite)

Card: 71923a08-b3de-448a-98ef-fe7cc3e817c0

First sub-slice of L0-3a. Pure typed surface from BRAIN-REGIONS-SUBSTRATE.md
(merged via #1470). No region implementations, no algorithms, no governor
integration. Those land in L0-3a.1+ slices.

## New modules in continuum-core/src/runtime/

### brain_region.rs

The cognitive-cycle trait every region implements:

- BrainRegion (async trait, dyn-compatible)
  - id() -> RegionId
  - pressure_profile() -> PressureProfile
  - async tick(ctx: &RegionContext) -> TickOutcome
  - async on_signal(signal: RegionSignal) -> Result<(), RegionError>  // default no-op
- RegionId (Cow<'static, str> newtype, const constructor for static IDs)
- PressureProfile { memory_class, compute_class, responds_to }
- MemoryClass: Light | Moderate | Heavy | VramSensitive
- ComputeClass: Bookkeeping | Cpu | CpuVectorized | InferenceLight | InferenceHeavy
- PressureSignalKind (kind-only mirror of governor::PressureSignal for static decl)
- TickOutcome { published, consumed_since_last, pressure_observed, cadence_hint }
- TickOutcome::idle() convenience constructor
- CadenceHint: Faster | Hold | Slower | Sleep (region requests; governor decides)
- RegionSignal: PersonaLifecycle | SleepTransition | SystemPressureChanged
- PersonaLifecycle: Created | Destroyed
- SleepPhase: Active | Idle | Sleep
- PressureLevel: Nominal | Moderate | High | Critical
- RegionContext { tick_number, persona_scope }  // global vs per-persona
- RegionError (thiserror): SignalRejected | NotReady | Internal

### ready_buffer.rs

The publish/peek surface every region uses to hand off pre-staged results:

- ReadyBuffer trait
  - peek(&self, key: &Key) -> Option<Value>  // synchronous, MUST NOT block
  - publish(&self, key: Key, value: Value)   // atomic replace
  - evict_stale(&self, max_age: Duration) -> usize
  - len() / is_empty()
- DashMapReadyBuffer<K, V> default implementation
  - Arc-shared DashMap inner — cheap Clone hands out additional handles
  - Sharded concurrent access; wait-free reads in the common case
  - TimestampedEntry tracks published_at for evict_stale

Semantic rules enforced in the doc + the trait:
- Reads MUST NOT block / MUST NOT await
- Staleness acceptable — empty buffer is signal, not block
- Per-region buffers, not global

### region_telemetry.rs

The per-tick telemetry shape:

- RegionTelemetry { region_id, persona_id, tick_started_at, tick_duration,
                    published, consumed_since_last, buffer_misses_since_last,
                    pressure_observed }
- consumption_fraction() -> Option<f32>  // None when published == 0
- had_buffer_misses() -> bool

Feeds the substrate governor's yield-learning loop (algorithm 7, lands L0-4c)
and the operator surface (./jtag region/stats, region/yield).

## ts-rs bindings (11 emitted to shared/generated/runtime/)

CadenceHint, ComputeClass, MemoryClass, PersonaLifecycle, PressureLevel,
PressureProfile, PressureSignalKind, RegionId, RegionSignal,
RegionTelemetry, SleepPhase, TickOutcome.

Generated and validated by the ts-rs export_bindings_* tests.

## Tests

23 new unit tests across the three modules. All pass.

- brain_region: 6 tests (trait impl, default on_signal noop, RegionId
  construction + Display, RegionContext global vs per-persona, TickOutcome::idle)
- ready_buffer: 9 tests (publish+peek roundtrip, missing key, overwrite,
  evict_stale removes old + keeps fresh, evict ZERO clears everything,
  len/is_empty, clone shares Arc inner, dyn trait usage, with_capacity)
- region_telemetry: 5 tests (consumption_fraction with publishes / zero /
  full, had_buffer_misses true / false)

Plus ts-rs auto-generated export_bindings_* tests for all 11 types.

Total: 74 tests pass in runtime::, 0 fail.

## Boy-scout

cargo fmt applied across the package picked up some unrelated drift in
governor/types.rs (line-width formatting on ts(export...) attributes).
Including the fix.

## What is NOT in this card

- No region implementations (HippocampusModule, MotorCortexModule,
  AttentionModule all land in later slices)
- No algorithms (1-7 from COGNITION-ALGORITHMS.md land in subsequent cards)
- No SubstrateGovernor integration (yield-learning loop is L0-4c)
- No derive macro / scaffold generator (lands when ≥3 regions exist to
  motivate the abstraction — per outlier-validation in CLAUDE.md)

## Predecessors merged

- #1469 (L0-2-CUTOVER-INVESTIGATION + RTOS-brain doctrine) — 2026-05-29
- #1470 (BRAIN-REGIONS-SUBSTRATE + COGNITION-ALGORITHMS docs) — 2026-05-29

## Next slices

L0-3a.1 HippocampusModule skeleton, L0-3a.2 Engram + EngramGraph types,
L0-3a.3 Algorithm 4 (salience decay), L0-3a.4 Algorithm 2 (channel-as-bias),
L0-3a.5 Algorithm 3 (activation spreading), L0-3a.6 Algorithm 1 (two-pool
budget), L0-3a.7 Algorithm 5 (predictor + ready-buffer publish), L0-3a.8
holdout fixture suite, L0-3a.9 TS Hippocampus.ts deletion.

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

* feat(continuum-core/modules): L0-3a.1 — HippocampusModule skeleton (BrainRegion + ServiceModule, empty tick)

Card: f8c51b26-9ddd-4107-97da-3237fc18ab4b

Second sub-slice of L0-3a. Skeleton only — no algorithms, no command
migration. Algorithms 1-5 from COGNITION-ALGORITHMS.md land in L0-3a.2
through L0-3a.7. Command surface migration (memory/* from MemoryModule)
is L0-3a.1b.

## HippocampusModule

- Implements ServiceModule with EMPTY command_prefixes + event_subscriptions
  (MemoryModule continues to handle memory/* commands until L0-3a.1b)
- Implements BrainRegion (from #1471 trait machinery) with:
  - id = "hippocampus" (static)
  - pressure_profile: { MemoryClass::Heavy, ComputeClass::CpuVectorized,
    responds_to: [SystemMemHigh, InferenceQueueDepth] }
  - tick: idle — bumps internal monotonic counter, returns TickOutcome::idle()
  - on_signal: default no-op (L0-4d wires SleepTransition reaction)
- Owns a DashMapReadyBuffer<EngramPrefetchKey, EngramPrefetch> exposed via
  engram_prefetch() — Arc-shared so motor cortex / attention can peek
  without going through the trait object
- Shares MemoryState with MemoryModule via Arc — when L0-3a.1b absorbs
  command handling, migration is structurally trivial

## EngramPrefetch / EngramPrefetchKey

Placeholder ready-buffer value type. Carries produced_at_tick so handlers
can detect stale buffers without timestamp comparison. Real shape (engram
set + scoring metadata + genome blend hint) lands L0-3a.2 with the actual
Engram types.

Key shape: (persona_id, channel_id) tuple. Per-region buffer doctrine — one
prefetch per persona-per-channel.

## Outlier-validation hedge (docstring)

The BrainRegion trait in #1471 has only one implementation candidate today.
Module docstring explicitly checks the trait surface against two other
plausible regions to prevent it ossifying around hippocampus:

- Motor cortex (L0-4a): continuous candidate-utterance ranking. Differs in
  latency sensitivity. CadenceHint::Faster + per-key freshness semantics fit.
- Attention (L0-4b): salience-map maintenance. Differs in publish-target
  (writes to shared PersonaCognition.salience, not own ready-buffer).
  TickOutcome.published counts either target without trait change.

Both alternative shapes fit the same trait without forcing. Trait surface
proven for 3 distinct region behaviors before any of them ship.

## Tests (7 pass, 0 fail)

- region_id_is_stable_static_string
- pressure_profile_declares_memory_heavy_compute_vectorized
- idle_tick_returns_idle_outcome_and_bumps_counter
- engram_prefetch_buffer_roundtrip
- engram_prefetch_handle_is_shared_via_arc (verifies Arc-shared semantics)
- service_module_handle_command_errors_for_unrouted_commands
- service_module_config_has_empty_cmd_and_event_surfaces

## Scope: 2 files

Modified: src/workers/continuum-core/src/modules/mod.rs (pub mod hippocampus)
Added:    src/workers/continuum-core/src/modules/hippocampus.rs (379 lines)

Fmt-drift in unrelated files was split off into a companion PR following
the same pattern as #1472, keeping this review focused.

## Predecessors

- #1471 (L0-3a.0 trait machinery) — merged to canary
- #1470 (BRAIN-REGIONS-SUBSTRATE + COGNITION-ALGORITHMS docs) — merged
- #1469 (L0-2-CUTOVER-INVESTIGATION + RTOS-brain doctrine) — merged

## Next slices

L0-3a.2 Engram + EngramGraph types → L0-3a.3 algorithm 4 (salience decay)
→ L0-3a.4 algorithm 2 (channel-as-bias) → L0-3a.5 algorithm 3 (activation
spreading) → L0-3a.6 algorithm 1 (two-pool budget) → L0-3a.7 algorithm 5
(predictor + ready-buffer publish — the alive-feeling slice) → L0-3a.8
holdout fixture suite → L0-3a.9 TS Hippocampus.ts deletion.

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply added a commit that referenced this pull request May 30, 2026
…er + RegionTelemetry (substrate prerequisite) (#1472)

Card: 71923a08-b3de-448a-98ef-fe7cc3e817c0

First sub-slice of L0-3a. Pure typed surface from BRAIN-REGIONS-SUBSTRATE.md
(merged via #1470). No region implementations, no algorithms, no governor
integration. Those land in L0-3a.1+ slices.

## New modules in continuum-core/src/runtime/

### brain_region.rs

The cognitive-cycle trait every region implements:

- BrainRegion (async trait, dyn-compatible)
  - id() -> RegionId
  - pressure_profile() -> PressureProfile
  - async tick(ctx: &RegionContext) -> TickOutcome
  - async on_signal(signal: RegionSignal) -> Result<(), RegionError>  // default no-op
- RegionId (Cow<'static, str> newtype, const constructor for static IDs)
- PressureProfile { memory_class, compute_class, responds_to }
- MemoryClass: Light | Moderate | Heavy | VramSensitive
- ComputeClass: Bookkeeping | Cpu | CpuVectorized | InferenceLight | InferenceHeavy
- PressureSignalKind (kind-only mirror of governor::PressureSignal for static decl)
- TickOutcome { published, consumed_since_last, pressure_observed, cadence_hint }
- TickOutcome::idle() convenience constructor
- CadenceHint: Faster | Hold | Slower | Sleep (region requests; governor decides)
- RegionSignal: PersonaLifecycle | SleepTransition | SystemPressureChanged
- PersonaLifecycle: Created | Destroyed
- SleepPhase: Active | Idle | Sleep
- PressureLevel: Nominal | Moderate | High | Critical
- RegionContext { tick_number, persona_scope }  // global vs per-persona
- RegionError (thiserror): SignalRejected | NotReady | Internal

### ready_buffer.rs

The publish/peek surface every region uses to hand off pre-staged results:

- ReadyBuffer trait
  - peek(&self, key: &Key) -> Option<Value>  // synchronous, MUST NOT block
  - publish(&self, key: Key, value: Value)   // atomic replace
  - evict_stale(&self, max_age: Duration) -> usize
  - len() / is_empty()
- DashMapReadyBuffer<K, V> default implementation
  - Arc-shared DashMap inner — cheap Clone hands out additional handles
  - Sharded concurrent access; wait-free reads in the common case
  - TimestampedEntry tracks published_at for evict_stale

Semantic rules enforced in the doc + the trait:
- Reads MUST NOT block / MUST NOT await
- Staleness acceptable — empty buffer is signal, not block
- Per-region buffers, not global

### region_telemetry.rs

The per-tick telemetry shape:

- RegionTelemetry { region_id, persona_id, tick_started_at, tick_duration,
                    published, consumed_since_last, buffer_misses_since_last,
                    pressure_observed }
- consumption_fraction() -> Option<f32>  // None when published == 0
- had_buffer_misses() -> bool

Feeds the substrate governor's yield-learning loop (algorithm 7, lands L0-4c)
and the operator surface (./jtag region/stats, region/yield).

## ts-rs bindings (11 emitted to shared/generated/runtime/)

CadenceHint, ComputeClass, MemoryClass, PersonaLifecycle, PressureLevel,
PressureProfile, PressureSignalKind, RegionId, RegionSignal,
RegionTelemetry, SleepPhase, TickOutcome.

Generated and validated by the ts-rs export_bindings_* tests.

## Tests

23 new unit tests across the three modules. All pass.

- brain_region: 6 tests (trait impl, default on_signal noop, RegionId
  construction + Display, RegionContext global vs per-persona, TickOutcome::idle)
- ready_buffer: 9 tests (publish+peek roundtrip, missing key, overwrite,
  evict_stale removes old + keeps fresh, evict ZERO clears everything,
  len/is_empty, clone shares Arc inner, dyn trait usage, with_capacity)
- region_telemetry: 5 tests (consumption_fraction with publishes / zero /
  full, had_buffer_misses true / false)

Plus ts-rs auto-generated export_bindings_* tests for all 11 types.

Total: 74 tests pass in runtime::, 0 fail.

## Boy-scout

cargo fmt applied across the package picked up some unrelated drift in
governor/types.rs (line-width formatting on ts(export...) attributes).
Including the fix.

## What is NOT in this card

- No region implementations (HippocampusModule, MotorCortexModule,
  AttentionModule all land in later slices)
- No algorithms (1-7 from COGNITION-ALGORITHMS.md land in subsequent cards)
- No SubstrateGovernor integration (yield-learning loop is L0-4c)
- No derive macro / scaffold generator (lands when ≥3 regions exist to
  motivate the abstraction — per outlier-validation in CLAUDE.md)

## Predecessors merged

- #1469 (L0-2-CUTOVER-INVESTIGATION + RTOS-brain doctrine) — 2026-05-29
- #1470 (BRAIN-REGIONS-SUBSTRATE + COGNITION-ALGORITHMS docs) — 2026-05-29

## Next slices

L0-3a.1 HippocampusModule skeleton, L0-3a.2 Engram + EngramGraph types,
L0-3a.3 Algorithm 4 (salience decay), L0-3a.4 Algorithm 2 (channel-as-bias),
L0-3a.5 Algorithm 3 (activation spreading), L0-3a.6 Algorithm 1 (two-pool
budget), L0-3a.7 Algorithm 5 (predictor + ready-buffer publish), L0-3a.8
holdout fixture suite, L0-3a.9 TS Hippocampus.ts deletion.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant