Skip to content
36 changes: 36 additions & 0 deletions .claude/board/AGENT_LOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
## [Agent-A4 / Sonnet] D-MBX-A4 — append §10 architectural refinements to bindspace→mailbox plan

**D-id:** D-MBX-A4 | **Commit:** 0f448730 (cherry-picked from worktree `worktree-agent-a1961cf1d2ca1db93` f5cdcbe8) | **Branch:** claude/lance-surrealdb-analysis-LXmug
**Files touched:** `.claude/plans/bindspace-singleton-to-mailbox-soa-v1.md` (+36 lines, new §10 at end). 36 insertions, 0 deletions — no existing text modified.
**Markers:** 9 `<!-- ///work -->` comments placed (7 refinement bullets + 2 OQ entries); orchestrator removed all 9 in review pass.
**Outcome:** DONE. §10 captures: (1) SoA Lance container ≠ cascade; (2) cascade is NOT index space; (3) 64K-256K envelope; (4) W-slot mailbox-witness table semantics; (5) cascade granularities = CPU/cache boundaries; (6) `simd_soa.rs` introspection framework; (7) SoA invariant spawn→commit. Surviving open questions: OQ-MBX-8 (`persisted_row` vs Lance versioning) + OQ-MBX-15′ (container scoping).

---

## [Agent-A3 / Sonnet] D-MBX-A3 — WitnessTable column-type primitive (W-slot resolver)

**D-id:** D-MBX-A3 | **Commit:** ef848a34 | **Branch:** claude/lance-surrealdb-analysis-LXmug
**Files touched:** `crates/lance-graph-contract/src/witness_table.rs` (new, +185 lines); `crates/lance-graph-contract/src/lib.rs` (+2 lines, `pub mod witness_table`)
**Tests:** `cargo test -p lance-graph-contract --lib witness_table` → 3/3 passed; `cargo check -p lance-graph-contract` → `Finished dev` 0 errors 0 warnings
**Outcome:** DONE. `WitnessEntry` + `WitnessTable<N=64>` declared; zero new dependencies; `/// work` markers on all pub items.

---

## [Agent-A1 / Sonnet] D-MBX-A1 — add thoughtspace columns to MailboxSoA<N>

**D-id:** D-MBX-A1 | **Commit:** 1df12eca | **Branch:** claude/lance-surrealdb-analysis-LXmug
**Files touched:** `crates/cognitive-shader-driver/src/mailbox_soa.rs` (+103 lines)
**cargo check:** `Finished dev` — 0 errors; pre-existing warnings only (causal-edge/p64-bridge/ontology — none in mailbox_soa.rs). `--features hpc-extras` absent from this crate; ran with default features.
**Outcome:** SUCCESS — added 4 SoA fields (edges/qualia/meta/entity_type), 8 getter/setter methods, updated new() + reset_row(). All new items marked `/// work`.

---

## [Agent-A2 / Sonnet] D-MBX-A2 — transitional per-mailbox routing field+builder on ShaderDriver

**D-id:** D-MBX-A2 | **Commit:** 61b641d5 | **Branch:** claude/lance-surrealdb-analysis-LXmug
**Files touched:** `crates/cognitive-shader-driver/src/driver.rs` (+42 lines)
**cargo check:** `Finished dev` — 0 errors; pre-existing warnings only (causal-edge/p64-bridge/ontology deprecations — none in cognitive-shader-driver). Note: `--features hpc-extras` absent from this crate; check ran with default features.
**Outcome:** SUCCESS — added `HashMap<MailboxId, MailboxSoA<1024>>` field on `ShaderDriver`, `with_mailbox` builder setter on `CognitiveShaderBuilder`, `mailbox()` read accessor. Singleton `Arc<BindSpace>` untouched. All new items marked `/// work`.

---

## [Main-thread] D-ODOO-SAV-4 — odoo-savant Reasoner layer (4 impls, one per ReasoningKind)

Implemented `crates/lance-graph-callcenter/src/savant_reasoners.rs`: `SavantConclusion { savant_id, query_strategy, confidence: NarsTruth, rationale }` (suggestion-only, **no serde** — the one-binary contract; JSON only at the MedCareV2 FFI boundary) + the 4 `Reasoner` impls per the dispatch decision pinned in PR #419: `CustomerCategoryReasoner` / `PostingAnomalyReasoner` / `NextBestActionReasoner` / `OtherReasoner`, covering all 25 savants in `contract::savants::SAVANTS`. Each resolves the concrete savant from `(kind, namespace)`, selects `QueryStrategy` via `InferenceType::default_strategy()`, and fuses evidence-ref coverage into a NARS `(frequency, confidence)`.
Expand Down
2 changes: 2 additions & 0 deletions .claude/board/LATEST_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

## Current Contract Inventory (lance-graph-contract)

> **2026-05-28 — PR-in-flight addition** (bindspace→mailbox migration wave A1-A4): `lance_graph_contract::witness_table::{WitnessEntry, WitnessTable<N=64>}` — column-type primitive resolving the 6-bit W-slot in `CausalEdge64 v2` into a per-cohort `(mailbox_ref: u32, spo_fact_ref: Option<u64>)` table (`mailbox_ref` carries the full canonical `MailboxId`, NOT a truncated cohort-local index — see PR #427 Codex P2 fix). Zero-dep, 3 unit tests, `WitnessTable::{new, get, set, default}`. Cross-ref: `.claude/plans/bindspace-singleton-to-mailbox-soa-v1.md` §10 (architectural refinements landed in same wave). Also in same wave: `cognitive-shader-driver::MailboxSoA<N>` gains four thoughtspace columns (`edges: [CausalEdge64; N]`, `qualia: [QualiaI4_16D; N]`, `meta: [MetaWord; N]`, `entity_type: [u16; N]`) + 8 row accessors; `ShaderDriver` gains transitional `mailboxes: HashMap<MailboxId, MailboxSoA<1024>>` + `with_mailbox()` builder + `mailbox()` read accessor (sibling-shape, additive — singleton untouched). 457 contract+driver tests pass.

Types that EXIST — do NOT re-propose them:

**`grammar/`**: `FailureTicket`, `PartialParse`, `CausalAmbiguity`, `TekamoloSlots`, `TekamoloSlot`, `WechselAmbiguity`, `WechselRole`, `FinnishCase`, `finnish_case_for_suffix`, `NarsInference`, `inference_to_style_cluster`, `ContextChain` (with coherence_at / total_coherence / replay_with_alternative / disambiguate / DisambiguationResult / WeightingKernel), `RoleKey` + 47 `LazyLock<RoleKey>` instances + `Tense` enum + `finnish_case_key / tense_key / nars_inference_key` lookups, **`RoleKey::bind/unbind/recovery_margin`** (slice-masked XOR), **`Vsa10k`** + `VSA_ZERO` + `vsa_xor` + `vsa_similarity`, **`GrammarStyleConfig`** + **`GrammarStyleAwareness`** + `revise_truth` + `ParseOutcome` + `divergence_from`, **`FreeEnergy`** + **`Hypothesis`** + **`Resolution`** (Commit / Epiphany / FailureTicket) + `from_ranked` + thresholds.
Expand Down
27 changes: 27 additions & 0 deletions .claude/plans/bindspace-singleton-to-mailbox-soa-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,30 @@ accumulator), `EPIPHANIES.md` (`E-BATON-1`, `E-CE64-MB-4`, `E-LADDER-SERVES-MAIL
`I-VSA-IDENTITIES`, `I-LEGACY-API-FEATURE-GATED`), `.claude/surreal/RECONCILIATION_with_canonical_plan.md`
(Vsa16kF32-deprecation contradiction flag), code: `crates/cognitive-shader-driver/src/{bindspace.rs,
mailbox_soa.rs, driver.rs, engine_bridge.rs, bin/serve.rs}`.

---

## §10 — 2026-05-28 architectural refinements (post-PR-#423 sync)

The following refinements were ratified after the initial plan was written. They are
append-only findings; no prior section has been modified.

1. **SoA Lance container ≠ cascade.** The cascade is resolution-laddered superposition over per-axis granularities; the SoA Lance container is the materialized data substrate (same SoA the cognitive-shader-driver handles, same SoA the singleton BindSpace updated). One cascade resolves to one or more SoA Lance containers via top-k emission (Gaussian splat / CAM-PQ top-k). The container is the StreamDTO operand variable; the cascade is the resolver function.

2. **Cascade is NOT an index space.** L1-L4 (`64²/256²/4096²/16384²`) are per-axis granularities on the same semantic axis (causal / palette / COCA codebook / outcome), superposed and streamed like x265 cascaded prediction levels. No level is fully materialized; only the emission (rendered SoA container) reaches downstream.

3. **64K-256K mailbox envelope** (~360 MB - 1.4 GB total working set at 6 KB per mailbox). The whole population is RAM-resident on any reasonable server. No hot/warm/cold tier split needed. Tombstone retention is free at this scale; eviction is moot.

4. **W-slot resolves into a per-cohort witness table** of `(mailbox_ref, spo_fact_ref)` entries — NOT a witness-corpus pointer to a static repository. Active mailboxes carry a mailbox-ref alone (spo_fact_ref = None); once the belief crystallizes via Rubicon commit, the spo_fact_ref binds to the SPO triple. Tombstones stay reachable through their mailbox-ref. The chain of W-references across edges forms a Markov belief-update arc via AriGraph episodic-reference vectors (AriGraph today is a transcode; the chaining engine is the target shape).

5. **Cascade granularities are CPU/cache boundaries, not abstract resolutions.** 64 = AVX-512 i8 register / cache line; 256 = AMX tile row; 4096 = page (4 KiB); 16384 = L1d cache (16 KiB). The ladder is hardware-natural so SIMD sweeps stay register/cache/page-aligned by construction.

6. **`simd_soa.rs` (ndarray) is the SoA dispatch framework.** It adapts to any SoA shape by introspecting members; consumers declare their own column tuple via derive/const-generic and get SIMD sweeps for free. The MailboxSoA migration is positional, not structural — the framework already swallows the column shape.

7. **SoA invariant from spawn → commit.** The same SoA byte layout runs end-to-end: cognitive-shader-driver creates a mailbox + SoA via cascade hot path → traverse cold path with gridlake SIMD ops → commit via one of two egress modes: **external** (REST / sea-orm SQL via tokio, backpressure expected) or **internal** (SurrealDB → LanceDB or RocksDB, no backpressure). No marshalling at any boundary; Lance columnar IS the repr.

### Open Questions surviving these refinements

- **OQ-MBX-8** — `persisted_row` stub vs Lance native versioning (load-bearing; evidence at `REFACTOR_NOTES.md:129` + `driver.rs:458`).

- **OQ-MBX-15′** — container scoping: per-cognitive-cycle, per-shader-dispatch, or per-mailbox-cohort?
36 changes: 36 additions & 0 deletions crates/cognitive-shader-driver/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ use p64_bridge::cognitive_shader::CognitiveShader;

use crate::auto_style;
use crate::bindspace::{BindSpace, WORDS_PER_FP};
use crate::mailbox_soa::MailboxSoA;
use lance_graph_contract::collapse_gate::MailboxId;

// ═══════════════════════════════════════════════════════════════════════════
// ShaderDriver — holds everything the shader needs to drive
Expand Down Expand Up @@ -72,6 +74,14 @@ pub struct ShaderDriver {
/// Lives in `causal-edge` (zero-dep), so attaching it does NOT pull
/// the planner into shader-driver.
pub(crate) nars_tables: Option<Arc<NarsTables>>,
/// Transitional per-mailbox routing surface (slice A2).
///
/// Consumers can opt into per-mailbox routing by inserting
/// `MailboxSoA<1024>` instances here via the builder's
/// `with_mailbox` method. The singleton `Arc<BindSpace>` (above)
/// is unchanged — this field is purely additive and does not alter
/// any existing dispatch semantics. Removed at cutover (plan S3).
pub(crate) mailboxes: std::collections::HashMap<MailboxId, MailboxSoA<1024>>,
}

impl ShaderDriver {
Expand All @@ -92,6 +102,7 @@ impl ShaderDriver {
default_style,
awareness: RwLock::new(awareness),
nars_tables: None,
mailboxes: std::collections::HashMap::new(),
}
}

Expand All @@ -111,6 +122,17 @@ impl ShaderDriver {
self.nars_tables.as_ref()
}

/// Return a read reference to the `MailboxSoA<1024>` registered under
/// `id`, or `None` if no mailbox with that id has been inserted via
/// the builder's `with_mailbox` method.
///
/// The singleton `Arc<BindSpace>` is unchanged by this accessor.
/// This is the transitional per-mailbox routing read surface (slice A2).
#[inline]
pub fn mailbox(&self, id: MailboxId) -> Option<&MailboxSoA<1024>> {
self.mailboxes.get(&id)
}

/// Borrow the underlying BindSpace (read-only).
#[inline]
pub fn bindspace(&self) -> &BindSpace { &self.bindspace }
Expand Down Expand Up @@ -596,6 +618,9 @@ pub struct CognitiveShaderBuilder {
planes: Option<[[u64; 64]; 8]>,
default_style: u8,
nars_tables: Option<Arc<NarsTables>>,
/// Transitional per-mailbox routing map populated by `with_mailbox`.
/// Forwarded into `ShaderDriver::mailboxes` at `build()` time.
mailboxes: std::collections::HashMap<MailboxId, MailboxSoA<1024>>,
}

impl CognitiveShaderBuilder {
Expand All @@ -606,6 +631,7 @@ impl CognitiveShaderBuilder {
planes: None,
default_style: auto_style::DELIBERATE,
nars_tables: None,
mailboxes: std::collections::HashMap::new(),
}
}

Expand Down Expand Up @@ -635,6 +661,15 @@ impl CognitiveShaderBuilder {
self
}

/// Register a `MailboxSoA<1024>` for transitional per-mailbox routing
/// (slice A2). The mailbox is keyed by `id`; a second call with the
/// same `id` replaces the previous entry. Multiple mailboxes are
/// supported. The singleton `Arc<BindSpace>` is not affected.
pub fn with_mailbox(mut self, id: MailboxId, soa: MailboxSoA<1024>) -> Self {
self.mailboxes.insert(id, soa);
self
}

pub fn build(self) -> ShaderDriver {
let awareness = (0..12)
.map(|ord| GrammarStyleAwareness::bootstrap(ord_to_thinking_style(ord)))
Expand All @@ -646,6 +681,7 @@ impl CognitiveShaderBuilder {
default_style: self.default_style,
awareness: RwLock::new(awareness),
nars_tables: self.nars_tables,
mailboxes: self.mailboxes,
}
}
}
Expand Down
91 changes: 91 additions & 0 deletions crates/cognitive-shader-driver/src/mailbox_soa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
//! gated steps: `.claude/plans/bindspace-singleton-to-mailbox-soa-v1.md`.

use causal_edge::CausalEdge64;
use lance_graph_contract::cognitive_shader::MetaWord;
use lance_graph_contract::collapse_gate::{CollapseGateEmission, MailboxId, MergeMode};
use lance_graph_contract::qualia::QualiaI4_16D;

/// Spatial-temporal accumulator for per-row baton receipts.
///
Expand Down Expand Up @@ -57,6 +59,29 @@ pub struct MailboxSoA<const N: usize> {
/// if `last_emission_cycle[row] == current_cycle`, emission is suppressed.
pub last_emission_cycle: [u32; N],

// ── NEW: migrated thoughtspace columns (per-mailbox owned, D-MBX-A1) ──

/// Per-row LE baton edge (`CausalEdge64`, 8 B/row).
/// Migrated from `BindSpace.edges` (EdgeColumn).
/// This IS the LE contract / baton edge for this mailbox row.
pub edges: [CausalEdge64; N],

/// Per-row affective role vector (`QualiaI4_16D`, 8 B/row).
/// Migrated from `BindSpace.qualia` (QualiaI4Column).
/// 16 signed i4 dimensions (arousal/valence/tension/…); 9× compression vs f32.
pub qualia: [QualiaI4_16D; N],

/// Per-row packed meta word (`MetaWord`, 4 B/row).
/// Migrated from `BindSpace.meta` (MetaColumn).
/// Layout: `thinking(6) + awareness(4) + nars_f(8) + nars_c(8) + free_e(6)`.
pub meta: [MetaWord; N],

/// Per-row OGIT entity-type index (`u16`, 2 B/row).
/// Migrated from `BindSpace.entity_type`.
/// 1-based index into the shared (immutable) ontology registry.
/// The registry itself stays `Arc<OntologyRegistry>` (cold Zone-2, not owned here).
pub entity_type: [u16; N],

/// Monotonic cycle stamp; advanced by `tick()`.
pub current_cycle: u32,

Expand Down Expand Up @@ -97,6 +122,11 @@ impl<const N: usize> MailboxSoA<N> {
current_cycle: 0,
w_slot,
threshold,
// ── NEW thoughtspace columns — zero-initialised (D-MBX-A1) ──
edges: [CausalEdge64::ZERO; N],
qualia: [QualiaI4_16D::ZERO; N],
meta: [MetaWord(0); N],
entity_type: [0u16; N],
}
}

Expand Down Expand Up @@ -189,6 +219,11 @@ impl<const N: usize> MailboxSoA<N> {
// Restore the "never emitted" sentinel so the row can emit immediately
// on the next cycle without triggering the same-cycle guard.
self.last_emission_cycle[row] = u32::MAX;
// ── NEW thoughtspace columns reset (D-MBX-A1) ──
self.edges[row] = CausalEdge64::ZERO;
self.qualia[row] = QualiaI4_16D::ZERO;
self.meta[row] = MetaWord(0);
self.entity_type[row] = 0;
}

// ── Read-only inspectors ──────────────────────────────────────────────────
Expand Down Expand Up @@ -227,6 +262,62 @@ impl<const N: usize> MailboxSoA<N> {
.filter(|&&e| e.abs() >= self.threshold)
.count()
}

// ── Thoughtspace column accessors (D-MBX-A1) ─────────────────────────────

/// Return the `CausalEdge64` baton edge for `row`.
///
/// Panics (debug) / wraps (release) on out-of-bounds; callers
/// should stay within `[0, N)`.
#[inline]
pub fn edge(&self, row: usize) -> CausalEdge64 {
self.edges[row]
}

/// Set the `CausalEdge64` baton edge for `row`.
///
/// Panics (debug) / wraps (release) on out-of-bounds; callers
/// should stay within `[0, N)`.
#[inline]
pub fn set_edge(&mut self, row: usize, e: CausalEdge64) {
self.edges[row] = e;
}

/// Return the packed `QualiaI4_16D` affective vector for `row`.
#[inline]
pub fn qualia_at(&self, row: usize) -> QualiaI4_16D {
self.qualia[row]
}

/// Set the packed `QualiaI4_16D` affective vector for `row`.
#[inline]
pub fn set_qualia(&mut self, row: usize, q: QualiaI4_16D) {
self.qualia[row] = q;
}

/// Return the packed `MetaWord` for `row`.
#[inline]
pub fn meta_at(&self, row: usize) -> MetaWord {
self.meta[row]
}

/// Set the packed `MetaWord` for `row`.
#[inline]
pub fn set_meta(&mut self, row: usize, m: MetaWord) {
self.meta[row] = m;
}

/// Return the OGIT entity-type index for `row` (1-based, shared ontology).
#[inline]
pub fn entity_type_at(&self, row: usize) -> u16 {
self.entity_type[row]
}

/// Set the OGIT entity-type index for `row`.
#[inline]
pub fn set_entity_type(&mut self, row: usize, t: u16) {
self.entity_type[row] = t;
}
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions crates/lance-graph-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub mod splat;
pub mod tax;
pub mod thinking;
pub mod vsa;
pub mod witness_table;
pub mod world_map;
pub mod world_model;

Expand Down
Loading
Loading