diff --git a/.claude/board/AGENT_LOG.md b/.claude/board/AGENT_LOG.md index 6b8765da..55bbee76 100644 --- a/.claude/board/AGENT_LOG.md +++ b/.claude/board/AGENT_LOG.md @@ -1,3 +1,43 @@ +## [Main thread / Opus, autoattended] 5-agent dev council → D-ATOM-4/RawEdge shipped (① Heel-compose REFUTED, ② RawEdge built, ③ deferred) + +**Branch:** claude/jolly-cori-clnf9. **Cargo:** contract lib **550 green** (+5 counterfactual); default clippy clean. User: "use the 5 agent development council." Convened R1–R5 (Opus, read-only); consolidated + auto-resolved + built. + +**Verdict:** **①** DROP Heel-compose — R4(critic) + my own full-file reads: `Heel.plasticity` COOLS (`revise_truth`), not on the EW64 SoA, wrong edge encoding → phantom join (`E-BASIN-NOT-EDGE-PLASTICITY`, the 4th-strike object conflation). Coarse strength = MRU slot-order (shipped); per-edge Hebbian = per-plane `PlasticityState` (gated). **②** SHIPPED RawEdge: wired orphaned `counterfactual` mod (R5 P0), `RawEdge(i8)` not u64 (R5 P0, `size_of==1` structural guarantee), impl `EpisodicEdge`, filled `deposit_counterfactual` v2 (−6 on split), +3 latent scaffold fixes (SplitPoles Eq-with-f32; 2 v3-stub unused-params). Closes the counterfactual seam (not the prefetch loop — R4). **③** deferred (firewall-placement). + +**Process:** `E-READ-NOT-GREP` (user) — review agents must READ full files not grep/head/tail (fragments produced the 4 wrong framings). Baked into the agent-brief template (pattern §Rule 7). Spec §9; council consolidation `board/reviews/ew64-decisions-council.md`. Next: update #449 + subscribe stays active. + +--- + +## [Main thread / Opus, autoattended] ① RESOLVED-IN-PRINCIPLE — per-plane clinical model verified REAL in causal-edge/src; coarse-first→per-plane-later + +Grep'd causal-edge/src (read, not built — owning the meta-lesson). Per-plane independence CONFIRMED: plasticity.rs freeze_s/heat_s + "established clinical pattern" (:16); edge.rs:713 live freeze_s; :750 pathological-plane count; lib.rs:46/52. Layout confirmed: plasticity 50-52 (PLAST_SHIFT=50), mantissa 46-49; v1/v2 minefield live (edge.rs 49 vs 50). RESOLUTION: ① is a build ORDER not either/or — (1) coarse NOW (per-basin Heel.plasticity × EW64 MRU, both offline; = #2 coarse + #1 compose), (2) per-plane PlasticityState = real, already-built, GATED clinical layer (phase 2). RawEdge = consensus first-build; sense-candidate = firewall-placement slice. Captured spec §8. Holding for @jan. + +--- + +## [Main thread / Opus, autoattended] ① plasticity GROUNDED in high_heel.rs (owned the meta-flag); feedback #2 captured; HOLDING + +Read `high_heel.rs:135–187` directly (owning #2's meta-flag — ① was narrated from the board 3 turns running). CONFIRMED: `Heel::plasticity()` = a **per-basin u8** (0=frozen..3=hot), ONE per `HighHeelBGZ` (≤240 edges), **already shipped in contract** (offline). So ① is NOT "Heel-scalar vs PlasticityState" (different objects) — it's **GRANULARITY**: per-basin u8 (coarse, exists) vs per-edge-plane 3-bit (fine, gated). **Synthesis:** compose the EXISTING per-basin `Heel.plasticity` × the shipped `EpisodicEdges64` MRU slot-order — no new field (reconciles #1 "don't store" + #2 "u8 already bought"); default coarse, go per-plane only if S/P/O harden independently (clinical-patterns hint, unverified). #2 also: sense-candidate = a firewall-PLACEMENT question, not a menu pick; RawEdge mantissa-only = both-session consensus. Captured spec §7. Decisions remain @jan's — holding. + +--- + +## [Main thread / Opus, autoattended] other-session feedback #1 captured — 3 decisions grounded vs causal-edge/layout.rs; HOLDING for @jan + +**Captured** (spec §6, #449) session-#1's grounded resolutions (verified `causal-edge/src/layout.rs`: per-plane plasticity 50–52, mantissa i4 46–49, Heel = 128-byte container): **①** per-plane (50–52) NOT Heel scalar — and DON'T store a graded weight; compose strength from MRU-slot × signed-mantissa × per-plane (RISC, avoids drift). **②** `RawEdge` mantissa-only as a TYPE (structural one-writer-per-field, like `MailboxSoaView`), not a convention. **③** sense-candidates = reuse proposer layer (VSA16k/aerial `TopKDistance`) as ⟨f,c⟩ proposals, top-k upstream, substrate sees only resolved opaque edge; lowest priority. + +**Held, not acted:** the decisions are @jan's (reserved as "THREE DECISIONS for @jan"; feedback explicitly "no action"; the ① compose-don't-store reframe is architecturally significant). Build queue now clarified: ② RawEdge type + the ①-compose `strength` fn are buildable-now (contract, offline); the plasticity WRITE stays gated. Awaiting @jan's pick. Also corrected §2's imprecise "PLAST_SHIFT 49 vs 50" → plasticity 50–52, mantissa 46–49. + +--- + +## [Main thread / Opus, autoattended] episodic-witness64-ce64-prefetch SPEC — consolidates shipped hot tier + gated phases + 3 user decisions + +**Branch:** claude/jolly-cori-clnf9 (synced; #447 + #448 merged). Both overnight slices landed: the white-matter HOT TIER is complete in main — D-EW64-2 (promote/MRU), D-EW64-3 (coldest/contains), D-EW64-4 (DemotionSink + promote_into). Safe-unblocked queue EXHAUSTED. + +**Shipped (this turn):** `.claude/specs/episodic-witness64-ce64-prefetch.md` — the queued seam spec. Phase A SHIPPED; Phase B (plasticity-write co-fire) GATED, Phase C (surreal/LanceDB-LIVE wingman) GATED on OQ-11.6, Phase D (EpisodicWitness64 SoA column) GATED offline, Phase E (comprehension↔arcuate ±5 wire) NEEDS-DESIGN. Frames the **3 decisions for @jan**: (1) plasticity model — `Heel` scalar vs `PlasticityState` per-plane; (2) `RawEdge` mantissa-only scope (D-EW64-5); (3) sense-candidate source for the comprehension wire. + +**Holding** code construction for those 3 decisions (no gated/minefield work unattended). PR + subscribe next; this is the morning handover artifact. + +--- + ## [Main thread / Opus, autoattended] D-EW64-3/4 review LAND + CodeRabbit contains nit applied (#448) Opus review agent: **LAND** — no P0/P1 (exhaustively verified: coldest == eviction victim for every word, no holes, promote_into word == promote().0 + sink gets exactly the eviction; firewall + API clean; 545 green). 2 optional editorial P2s NOT applied (don't block). CodeRabbit: 1 nit (💤 low value) — `contains` → `self.iter().any(|x| x == e)` (more idiomatic, reuses iter; equivalent) — APPLIED. episodic_edges tests still green; default clippy clean. #448 CI re-runs on this push. diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 2430fe27..97d2fbef 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,15 @@ +## 2026-06-01 — E-READ-NOT-GREP — judgment-critical review agents must READ full files, not grep/sed/head/tail; fragments invalidate judgment + +**Status:** IRON RULE (process; user-stated 2026-06-01). Across the EW64 council + the 3 prior relayed sessions, every wrong framing came from narrating off grep/head fragments rather than reading the type. The council's R3 even found a grep-induced mis-citation (`edge.rs:750 concern_level` reads `direction()`, not `PlasticityState`). **RULE:** when a review/council/grounding agent's VERDICT depends on a type's semantics, its brief MUST instruct it to READ the relevant files in full (the Read tool), NOT grep/sed/head/tail. A fragment seen out of context produces a confident-but-wrong judgment — **grep is for LOCATING, reading is for JUDGING.** Baked into the agent-brief template (`autoattended-multiagent-pattern.md` §Rule 7). Cross-ref: `E-BASIN-NOT-EDGE-PLASTICITY` (the conflation grep-fragments produced). + +--- + +## 2026-06-01 — E-BASIN-NOT-EDGE-PLASTICITY — the 4th-strike object conflation: per-basin `Heel.plasticity` (a NARS-confidence COOLING knob, not on the EW64 hot path) is NOT coarse edge-plasticity; the Hebbian edge weight is per-plane `PlasticityState` (gated) or the MRU slot-order (shipped) + +**Status:** FINDING (5-agent council-resolved + orchestrator source-verified, 2026-06-01). R4(critic) + my own full-file reads killed the "compose `Heel.plasticity` × MRU" resolution that spec §6/§8 (relayed from 2 prior sessions) walked into. **Verified by reading the source:** (a) `MailboxSoaView` (the EW64 hot path) has **NO** Heel/plasticity column (only `energy`/`edges_raw`/`meta_raw`/`entity_type`) — Heel is unreachable from the EW64 edges; (b) `Heel.plasticity`'s only writer is `revise_truth()`, which **COOLS** as NARS confidence rises (`high_heel.rs:252` "Cool plasticity as confidence rises"; `is_frozen = plasticity==0 && conf>0.8`) — **opposite polarity** to Hebbian fire→hot; (c) `HighHeelBGZ.edges` are `CausalEdge64` u64s, EW64 slots are `EdgeRef` — different encodings, no index map. So "compose Heel × MRU" is a **phantom join of anti-correlated signals on the wrong edge set.** **RESOLUTION:** coarse strength = the MRU slot-order (#447, shipped); the real per-edge Hebbian weight = per-plane `PlasticityState` co-fire (GATED, phase B); no Heel, no new field. **The 4th strike** (after CausalEdge64-lens / per-plane-axis / Heel-vs-PlasticityState): same-word-different-**OBJECT** — "plasticity" names BOTH a cold-path basin cooling knob AND a hot-path per-edge Hebbian state; they don't compose. Cross-ref: D-ATOM-4/RawEdge (shipped), spec §9, `E-READ-NOT-GREP`. + +--- + ## 2026-06-01 — E-EW64-STRENGTH CORRECTION — "W15 0..3 plasticity" is `high_heel::Heel` (128-byte container field), NOT the 64-bit `CausalEdge64`; the 64-bit edge's plasticity is the 3-bit-per-plane `PlasticityState` **Status:** CORRECTION (factual, Plan-agent-grounded against source 2026-06-01). Refines `E-EW64-STRENGTH-IS-CE64-PLASTICITY`'s mechanism claim; does NOT change D-EW64-2 (MRU slot-order strength stores NO plasticity — it stands regardless). diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index f83920b4..67dd7bf3 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -498,3 +498,5 @@ PR sequence: #360 → #361 → post-#360 substrate-sweep (this PR). - **`crates/lance-graph-arm-discovery`** (NEW, **excluded** standalone zero-dep crate; build via `cargo test --manifest-path crates/lance-graph-arm-discovery/Cargo.toml`). The **Aerial+** Rust transcode (Karabulut 2025, 2504.19354v1) — the upstream runtime-data proposer leg of `streaming-arm-nars-discovery-v1`. Public surface: `encode::{FeatureSpec, Dataset}`, `rule::{Item, CandidateRule, Proposer}`, `translator::{arm_to_nars, NarsTruth, CandidateTriple, FeedProjector, DebugProjector, NARS_PERSONALITY_K}`, `ndjson::to_ndjson`, and (feature `aerial`, default-on) `aerial::{Rng, AerialAutoencoder, AerialParams, AerialProposer, extract_rules, ExtractParams}`. 35/35 tests, clippy `-D warnings` clean. Emits the `{"s","p","o","f","c"}` ndjson the SPO store loader reads; `(f,c)` == `TruthValue::new(f,c)` == `ruff_spo_triplet::Triple{f,c}`. Determinism boundary: nondeterministic AE is seeded + feature-gated + emits *proposals* only. Synergy map: `.claude/knowledge/aerial-arm-ruff-spo-codegen-synergies.md`. Status board: D-ARM-13 (Shipped on branch) + D-ARM-SYN-1/2/3 (Queued). **Not** in `lance-graph-contract` yet — `rule`/`translator` are the local seam until D-ARM-1/2 land the shared carriers. > **2026-06-01 — PR-in-flight (autoattended)** (D-EW64-3/4): `lance_graph_contract::episodic_edges` gains `EpisodicEdges64::{coldest, contains, promote_into}` + the `DemotionSink` trait. `coldest()` = the eviction victim (symmetric to `strongest()`); `contains()` = family-discriminating membership; `promote_into(e, sink)` = `promote` routing the evicted (coldest) edge to a `DemotionSink` — the hot→cold connectome exit. `DemotionSink` impls (surreal/LanceDB-LIVE "wingman", `E-SUBSTRATE-IS-THE-SCHEDULER`) are deferred + GATED on OQ-11.6. Zero-dep; contract lib 545 green; default clippy clean; `episodic_edges.rs` pedantic+nursery clean. + +> **2026-06-01 — Shipped (autoattended, 5-agent council)** (D-ATOM-4/RawEdge): `contract::counterfactual` wired into `lib.rs` (was orphaned); `RawEdge(i8)` mantissa-only **structural** impl of `EpisodicEdge` (`size_of==1` — a u64 newtype could read plasticity 50–52); `deposit_counterfactual` v2 filled (−6 on split). Closes the counterfactual seam (NOT the prefetch loop). +3 latent scaffold fixes. 550 contract lib green, clippy clean. The council REFUTED the prior "compose `Heel.plasticity` × MRU" ① resolution (`E-BASIN-NOT-EDGE-PLASTICITY`): coarse strength = MRU slot-order (shipped); per-edge Hebbian = per-plane `PlasticityState` (gated). diff --git a/.claude/board/reviews/ew64-decisions-council.md b/.claude/board/reviews/ew64-decisions-council.md new file mode 100644 index 00000000..d6ba9c3c --- /dev/null +++ b/.claude/board/reviews/ew64-decisions-council.md @@ -0,0 +1,13 @@ +# 5-agent dev council — EW64↔CE64 decisions (2026-06-01) + +User: "use the 5 agent development council." Five Opus read-only reviewers; orchestrator adjudicated against full-file source reads (not the board). + +| reviewer | ① plasticity | ② RawEdge | ③ sense-candidate | +|---|---|---|---| +| R1 architectural | CONFIRM *pattern* (compose-not-store; method-on-carrier caveat) | CONFIRM (projection newtype) | CONFIRM (firewall-placement) | +| R2 iron-rule | CONFIRM firewall-safe (Heel ≠ CE64 reclaim zone) + mandatory field-isolation test | CONFIRM (impl-carrier for existing trait) | CONFIRM (arcuate Binary16K invariant) | +| R3 type-accuracy | CONFIRM types; flagged `edge.rs:750` mis-citation | CONFIRM (trait BLOCKED, no RawEdge dup) | CONFIRM | +| **R4 critic** | **HOLD — drop Heel half** (no SoA home; `revise_truth` cools; wrong edge type) | LAND-w-rev (write-scoped; counterfactual seam ≠ prefetch loop) | LAND (defer) | +| R5 build-order | (compose buildable but) | LAND-w-rev (i8 not u64; wire orphaned module — 2 P0s) | defer | + +**Adjudication (orchestrator, source-verified):** R4 wins ① — `MailboxSoaView` has no Heel column; `high_heel.rs:252` `revise_truth` COOLS; `HighHeelBGZ.edges` are `CausalEdge64` ≠ `EdgeRef`. R1/R3 endorsed the pattern/types, not the join. **① = MRU-is-coarse-strength (shipped) + per-plane gated; drop Heel.** **② RawEdge(i8) SHIPPED** (D-ATOM-4) with R5's two P0s applied. **③ defer.** Findings → `E-BASIN-NOT-EDGE-PLASTICITY`, `E-READ-NOT-GREP`; spec §9. diff --git a/.claude/knowledge/autoattended-multiagent-pattern.md b/.claude/knowledge/autoattended-multiagent-pattern.md index 7bff7fb8..9c1e810c 100644 --- a/.claude/knowledge/autoattended-multiagent-pattern.md +++ b/.claude/knowledge/autoattended-multiagent-pattern.md @@ -337,3 +337,7 @@ This workspace's existing knowledge docs and conventions that overlap with the p - **Append-only zones in lance-graph:** `crates/lance-graph-contract/src/lib.rs` (re-export list), `crates/lance-graph/Cargo.toml` (`[features]` table), `crates/lance-graph/src/graph/mod.rs` (graph backend registry). Workers touching these must declare them in their slice brief. - **Harvest tools:** lance-graph already has some — `docs/UNIFIED_INVENTORY.md`, `docs/TYPE_DUPLICATION_MAP.md`, `docs/SEMIRING_ALGEBRA_SURFACE.md`. These map to §7's "reference indexes" role and should be re-harvested after any wave that adds a new type or semiring. - **5th savant for SIMD invariants:** lance-graph (and any consumer of the ndarray fork) extends the project-agnostic 4-savant taxonomy in §3 with a workspace-specific `simd-savant` whose card lives at `.claude/agents/simd-savant.md`. Its scope is **the SIMD source-of-truth invariant — all SIMD must come from `ndarray::simd` via the polyfill (`simd.rs` + `simd_ops.rs` > `simd_{type}.rs` per-arch)**. It runs PRE-SPAWN (verifies worker brief routes through the polyfill), DURING-IMPL (commit-level grep for raw `_mm*` / `vld1q_*` outside `ndarray/src/simd_*`), and PRE-MERGE (gate on any PR with SIMD code). 8-entry AP-SIMD-N anti-pattern catalogue covers the common violations. Hand-offs: UB/OOB → PP-13; missing primitive → file `TD-NDARRAY-SIMD-` and route to ndarray maintainer; spec-drift → PP-16; cross-crate aliasing → PP-15. Workspace-specific because SIMD source-of-truth depends on having a polyfill repo to be the source — not all projects do, so this savant is an adapter, not a transferable §3 slot. + +### Rule 7 — judgment agents READ, don't grep (added 2026-06-01) + +When a review/council/grounding agent's **verdict** depends on a type's semantics, its brief MUST instruct it to **READ the relevant files in full** (the Read tool), NOT grep/sed/head/tail. A fragment out of context produces a confident-but-wrong judgment — **grep is for LOCATING, reading is for JUDGING.** Belegt: 4 successive wrong plasticity framings (CausalEdge64-lens / per-plane-axis / Heel-vs-PlasticityState / Heel-compose) all came from narrating off grep fragments; the EW64 council's R3 found a grep-induced mis-citation (`edge.rs:750`). Cross-ref EPIPHANIES `E-READ-NOT-GREP`. diff --git a/.claude/specs/episodic-witness64-ce64-prefetch.md b/.claude/specs/episodic-witness64-ce64-prefetch.md new file mode 100644 index 00000000..29a3f54c --- /dev/null +++ b/.claude/specs/episodic-witness64-ce64-prefetch.md @@ -0,0 +1,204 @@ +# Spec — EpisodicWitness64 ↔ CausalEdge64 prefetch seam (the white-matter connectome) + +**READ BY:** integration-lead, truth-architect; anyone wiring the EW64↔CE64 +"fire together → wire together" prefetch loop. +**Status:** SPEC (2026-06-01). **Phase A SHIPPED** (#446/#447/#448 merged); +Phases B–E are GATED / needs-design. This doc consolidates the shipped hot tier, +the remaining phases with their gates, and the **three decisions** that unblock +the next code. +**Grounds:** `E-PLANNING-IS-WHITE-MATTER`, `E-EW64-STRENGTH-IS-CE64-PLASTICITY` +(+ its 2026-06-01 correction), `E-EW64-IS-PREDICTIVE-PREFETCH`, +`E-SUBSTRATE-IS-THE-SCHEDULER`, `E-ARIGRAPH-IS-AN-ISLAND`. Authored from the +2026-06-01 Plan-agent roadmap (all file:lines verified against source there). + +--- + +## 0. Purpose + +The episodic connectome is the system's **white matter**: the CE64 (causal) + +EW64 (episodic) edges between the 64k mailboxes (the **grey matter** = compute). +**Planning lives here** — a plan is the Hebbian-strengthened path through the +connectome (recency + plasticity), retrieved by prefetch — **not** an OTP/BEAM +scheduler over isolated processes (`KanbanMove`/`VersionScheduler` are grey-matter +*coordination*, not the planner). This spec covers the hot tier (shipped) and the +loop that grows + prunes the wiring. + +```text +GREY (compute) WHITE (connectome / planning) COLD (persist + re-prefetch) +64k mailbox SoA ──fire──► EpisodicEdges64 hot 4-slot MRU ──demote──► DemotionSink impl +(Fingerprint/Qualia/Meta) (slot order = strength; promote) (surreal/LanceDB-LIVE "wingman") + ▲ │ + └───────────── prefetch (re-promote) ──────┘ +``` + +--- + +## 1. Phase A — SHIPPED (the hot tier), `contract::episodic_edges` + +Zero-dep, offline-tested, firewall-clean. The hot 4-slot MRU word + its read/write +surface + the cold-tier exit seam. + +| D-id | symbol | what | PR | +|---|---|---|---| +| D-EW64-1 | `EpisodicEdges64(u64)` = 4×`EdgeRef{family:u8, local:u16}` | AriGraph episodic edges; `family==0` intra-basin (~98.6%, #444), `1..=15` cross-family nibble | #446 | +| D-EW64-2 | `promote(e) -> (Self, Option)`, `strongest()` | MRU: fire→slot 0, survivors shift down, full+fresh evicts coldest (returned); slot order = strength | #447 | +| D-EW64-3 | `coldest()`, `contains(e)` | the eviction victim (= the next demotion); family-discriminating membership | #448 | +| D-EW64-4 | `trait DemotionSink { fn demote(&mut self, EdgeRef); }`, `promote_into(e, sink)` | the hot→cold exit seam; impls deferred (dependency-inversion, like `MailboxSoaOwner`) | #448 | + +**Invariant established (review-verified, exhaustive):** `coldest()` == the edge +`promote` evicts on full+fresh; `promote` never creates a hole; `promote_into` +word == `promote().0` with the sink receiving exactly the eviction. + +**What "strength" is here:** *recency only* — the slot index. No per-edge weight +is stored in the 64-bit word. The Hebbian *weight* (Phase B) is the co-addressed +CE64's plasticity; this spec keeps them separate (register-laziness). + +--- + +## 2. The phased plan (B–E) — each GATED or needs-design + +### Phase B — Hebbian co-fire (the "wire together" weight-bump) — **GATED** +Goal: when an edge fires, bump the co-addressed `CausalEdge64`'s plasticity toward +hot, so repeated co-firing consolidates a path (procedural memory). +**Gate (3 counts):** (1) `causal-edge` does NOT build offline (anstream uncached); +(2) **plasticity-model mismatch** (Decision 1 below); (3) `I-LEGACY-API-FEATURE-GATED` +— the v1 `PLAST_SHIFT=49` vs v2 `=50` boundary, codex-caught 5× in sprint-11. +A correctly-v2-gated getter/setter exists (`causal-edge::edge.rs:471/483`); driving +it from a co-fire op is the gated work. + +### Phase C — cold connectome `DemotionSink` impl (the "wingman") — **GATED on OQ-11.6** +Goal: persist demoted edges + re-prefetch them into the hot tier when their basin +re-activates (`E-SUBSTRATE-IS-THE-SCHEDULER`: surreal-LIVE over the version arc is +the inbound scheduler). The contract seam (`DemotionSink`) is shipped; the impl +(surreal-LIVE or the LanceDB-LIVE fallback) is gated on the `surreal_container` +fork + Lance-6 pin (OQ-11.6) and lancedb-offline. A zero-dep **in-memory +ring** `DemotionSink` reference impl is buildable now if a testable cold tier is +wanted before the substrate lands (optional, low-priority). + +### Phase D — `EpisodicWitness64` SoA column — **GATED (offline)** +Goal: make the hot word a real SoA column the cognitive shader borrows +(`soa_view.rs:77` `episodic_witness()` is a deferred accessor). Gate: needs +`cognitive-shader-driver`'s `MailboxSoA` (workspace crate, doesn't build +offline). + +### Phase E — comprehension ↔ arcuate ±5 ambiguity wire — **NEEDS-DESIGN** +Goal: the Wernicke faculty (`deepnsm::comprehension`) resolves coreference via the +arcuate ±5 chain before routing fact/story. Blocker: `SentenceStructure` +(`parser.rs:57-66`) carries no ambiguity/candidate signal — only +triples/modifiers/negations/temporals. The sense-candidate source is net-new and +firewall-sensitive (Decision 3). + +--- + +## 3. THREE DECISIONS for @jan (each unblocks a phase) + +1. **Plasticity model (unblocks Phase B).** "Co-addressed CE64 plasticity" is + ambiguous — two models exist: `high_heel::Heel` (`high_heel.rs:168`, W15 byte-3 + **scalar 0=frozen..3=hot**, a 128-byte container field) vs + `causal-edge::PlasticityState` (`plasticity.rs`, **3 bits, one per S/P/O plane**). + The hot-tier MRU (Phase A) is unaffected either way. **Which model is the Hebbian + weight the co-fire bumps?** (Recommendation: the per-plane `PlasticityState` is + the 64-bit-edge-native one; `Heel` is the container roll-up.) + +2. **`RawEdge` / `EpisodicEdge` impl-location, mantissa-only? (unblocks D-EW64-5).** + `counterfactual.rs:175 EpisodicEdge` is a trait BLOCKED on where its impl lands. + A zero-dep `RawEdge(u64)` newtype could resolve it **scoped to the inference + mantissa nibble only — NO plasticity write** (which would re-enter Phase B's + minefield). **Confirm: build `RawEdge` mantissa-only?** + +3. **Sense-candidate source for the comprehension wire (unblocks Phase E).** Where + do the ±5 disambiguation candidates originate — `vocabulary.rs` neighbors, + `similarity.rs` top-k, or net-new? They are language-side and must sign-binarize + to `Binary16K` before crossing (as `arcuate.rs` already does). **Which source?** + +--- + +## 4. Firewall invariants (hold across all phases) + +- EW64/CE64 store **opaque handles** (`EdgeRef{family,local}`, `spo_fact_ref:u64`, + mantissa) — never COCA `rank:u16`. Language stays upstream in DeepNSM. +- `DemotionSink` and any cold-tier impl carry opaque `EdgeRef` only. +- Float (the splat/VSA) stays offline/upstream; the connectome is integer. +- The ~4096 story basins (`local` 12-bit) ≠ COCA-4096 (`OQ-BASIN-COUNT`). + +--- + +## 5. Test plan per phase + +- **A (done):** MRU promote/evict/dedup/idempotence; `coldest`==eviction-victim + invariant; `promote_into` sink routing; family discrimination. 26 tests, green. +- **B:** field-isolation matrix tests across the v1/v2 PLAST_SHIFT boundary + (MANDATORY per I-LEGACY); co-fire idempotence; plasticity monotonic toward hot. +- **C:** fake-substrate `DemotionSink` round-trip (demote→persist→re-prefetch); + the in-memory ring as the offline reference. +- **D:** SoA borrow round-trip via `MailboxSoaView` (gated). +- **E:** coreference resolution over a ±5 fixture; firewall (no COCA crosses; only + `Binary16K` + the resolved referent). + +--- + +*Cross-ref:* `episodic_edges.rs` (Phase A), `causal-edge::{edge.rs:471/483, +plasticity.rs}` + `high_heel.rs:168` (Phase B), `soa_view.rs:77` (Phase D), +`deepnsm::{comprehension.rs, arcuate.rs}` + `parser.rs:57-66` (Phase E), +`I-LEGACY-API-FEATURE-GATED`, OQ-11.6. + +--- + +## 6. Decision resolutions — grounded recommendations (other-session feedback #1 + verified `causal-edge/src/layout.rs`, 2026-06-01; **PENDING @jan ratification** — the decisions remain @jan's) + +**Verified locked layout** (corrects §2's imprecise "PLAST_SHIFT 49 vs 50"): per-plane **plasticity = 3 bits (S/P/O) at bits 50–52**; **mantissa = signed i4 at bits 46–49**; **`Heel` = the 128-byte `high_heel` container** (a roll-up, not the 64-bit edge). + +**① Plasticity model → per-plane, and DON'T store a graded field.** Reject the `Heel` scalar `0..3` — a CISC collapse: a single scalar throws away SPO directionality (S×P co-fire ≠ P×O co-fire, which the signed mantissa already encodes per-edge). Pick the **per-plane 3-bit (50–52)** — but **binary hot/cold, not graded**: gradedness already lives in three *shipped* signals — **MRU slot-order (#447) × signed mantissa (direction/magnitude) × per-plane hot/cold** — so **compose** "strength" from those dumb signals rather than storing a weight (a stored graded scalar duplicates it and can drift out of sync with slot-order — the RISC answer). Only a *proven* need for a graded-per-plane weight flips this → then 3 graded values in `Heel`, never one collapsed scalar. **Reshapes Phase B:** the co-fire sets the per-plane binary bit; "strength" = a **zero-dep `compose(slot_order, mantissa, per_plane)`** function — NOT a stored weight. + +**② `RawEdge` mantissa-only → make it STRUCTURAL, not conventional.** Yes mantissa-only; the addition: `RawEdge` is a newtype that **structurally cannot read/write plasticity/W/truth/temporal** (exposes only the i4 at 46–49) — a *type guarantee*, the way the `MailboxSoaView`/`Owner` split made "read-only" structural. One-writer-per-field, enforced by the type, so "mantissa-only" can't rot into "mantissa-mostly." + +**③ Sense-candidate source → reuse the proposer layer; lowest priority.** `vocabulary` neighbors / `similarity` top-k is the right source AND already legal: sense-disambiguation is a **proposal, not an addressing act** (CAM-vs-ANN firewall — similarity lives in the proposer layer). So **don't build net-new** — reuse the proposer machinery (VSA16k role-candidates / aerial `TopKDistance`), emit sense-candidates as proposals carrying ⟨f,c⟩. Firewall: top-k runs upstream in comprehension; the substrate only ever sees the resolved opaque `(family, local)` edge, never the COCA/sense vectors. **Rank last** — least load-bearing for closing the loop. + +**Net for the build queue (pending @jan's pick):** ② `RawEdge` mantissa-only **type** and the ①-**compose** `strength` fn are both **buildable now** (contract, zero-dep, offline). The plasticity **WRITE** stays gated (causal-edge offline + I-LEGACY field-isolation tests). ③ is proposer-layer *reuse*, lowest priority. Decisions remain @jan's — these are grounded recommendations, not a resolution. + +--- + +## 7. ① plasticity — GROUND TRUTH (read directly from `high_heel.rs`, correcting §3/§6) + feedback #2 + +**Owned meta-flag:** ① was narrated from the board across three turns; now grounded by reading `high_heel.rs:135–187` directly. Confirmed: +- `Heel::plasticity()` (`high_heel.rs:169`) = **W15 byte-3 u8 (`0=frozen..3=hot`) — ONE per-basin scalar** on the 128-byte `Heel`, governing a `HighHeelBGZ` container of **up to 240 edges** (`MAX_EDGES=240`). **Already shipped in the contract** (offline); `new()` defaults it to 3/hot. +- `CausalEdge64 PlasticityState` = **per-edge, 3-bit per S/P/O plane**, in `causal-edge` (offline-gated + I-LEGACY minefield). + +**So it was never "Heel-scalar vs PlasticityState" (different objects) — ① is a GRANULARITY choice** for the Hebbian weight's home: + +| | granularity | where | status | +|---|---|---|---| +| **coarse** | per-**basin** u8 (1 weight / ≤240 edges) | `Heel.plasticity` | **shipped, offline, zero new freeze** | +| **fine** | per-**edge per-plane** 3-bit | `CE64 PlasticityState` | offline-gated + v1/v2 minefield | + +**Synthesis (reconciles #1 + #2):** the weight need NOT be a new field — **two hardening signals already exist, both shipped + offline:** per-basin `Heel.plasticity` (coarse) × `EpisodicEdges64` MRU slot-order (#447, per-edge recency). **Compose** those — which *satisfies* #1's "don't store, compose" precisely *by reusing* #2's already-bought per-basin u8 + the shipped MRU. **Default coarse;** drop to per-edge-plane `PlasticityState` ONLY if S/P/O planes must harden **independently per edge** — the "frozen planes = clinical patterns" hint (`lib.rs`, flagged by #2; **unverified here** — the one thing to confirm before going fine). Going fine unprovenly = over-engineering + the minefield. + +**Sense-candidate (#2 sharpening of decision 3):** don't pick from the menu — the load-bearing question is **firewall placement** (prove the producer stays UPSTREAM of language→substrate, like `markov_soa`'s opaque-u16-ranks + injected distance), not which top-k. If forced: similarity-top-k computed **in DeepNSM** emitting already-resolved **opaque ranks** is the only obviously-leak-proof shape — but a design slice to ratify, not an overnight default. + +**RawEdge (decision 2):** both sessions agree — mantissa-only (i4, 46–49), structural one-writer-per-field. The **consensus item**; buildable on @jan's go. + +--- + +## 8. ① RESOLVED-IN-PRINCIPLE — per-plane clinical model is REAL (verified in `causal-edge/src`); coarse-first → per-plane-later + +Grep of `causal-edge/src` (reading, not building) settles #2's "confirm before going fine": +- **Per-plane independence is real + already implemented:** `plasticity.rs` `freeze_s()`/`heat_s()` per-plane ops, `hot_count()`, `ALL_FROZEN` = "Established clinical pattern" (`:16`); `edge.rs:713` freezes the S-plane at a live call site; `edge.rs:750` "Clinical concern level: count of pathological planes"; `lib.rs:46/52` "3 bits per-plane … Frozen planes are established clinical patterns." **S/P/O DO harden independently.** +- **Layout confirmed:** plasticity bits **50–52** (`layout.rs:37 PLAST_SHIFT=50`), mantissa i4 **46–49** (`v2_layout_tests.rs:185`); v1/v2 minefield LIVE (`edge.rs:129` v1=49 vs `:146` v2=50). + +**Resolution (reconciles #1 + #2 — not either/or; two granularities, two phases):** +1. **Coarse, NOW (offline):** per-basin `Heel.plasticity` u8 × `EpisodicEdges64` MRU slot-order (#447) — both shipped + offline + zero new freeze; sufficient for the EW64 prefetch "wire together." (= #2's coarse-first, achieved via #1's compose-don't-store-a-new-field.) +2. **Per-plane `PlasticityState` = the real, already-built, finer clinical layer (GATED):** NOT over-engineering (it's used), but *writing* it is the gated work (causal-edge offline + the v1/v2 PLAST_SHIFT minefield ⇒ mandatory field-isolation tests). The co-fire drives it in **phase 2**. + +**Bottom line for @jan:** ① is a build **order**, not an either/or — coarse-first (offline, now) → per-plane-clinical (gated, later). RawEdge (decision 2) stays the consensus first-build; sense-candidate (decision 3) stays a firewall-placement design slice. + +--- + +## 9. COUNCIL VERDICT (5-agent dev council, 2026-06-01) — supersedes §8's Heel-compose + +R1 architectural / R2 iron-rule / R3 type-accuracy / R4 critic / R5 build-order, all read-only; orchestrator-adjudicated against full-file source reads. +- **① DROP the Heel-compose** (`E-BASIN-NOT-EDGE-PLASTICITY`): `Heel.plasticity` is a per-basin NARS-confidence COOLING knob, **not** on the EW64 SoA hot path, on the wrong edge encoding — "compose Heel × MRU" is a phantom join. **RESOLVED:** coarse strength = MRU slot-order (#447, shipped); per-edge Hebbian = per-plane `PlasticityState` (gated phase B). No Heel, no new field. (R1/R3 endorsed the compose-not-store *pattern* + types; R4 + source killed the specific Heel *join*; R5's own `edge_strength(heel,edges)` signature exposed the no-valid-caller problem.) +- **② BUILD RawEdge — SHIPPED** (D-ATOM-4/RawEdge): wired the orphaned `counterfactual` module into `lib.rs` (R5 P0: it wasn't compiled); `RawEdge(i8)` not u64 (R5 P0: i8 ⇒ mantissa-only structurally unforgeable, `size_of==1`); impl the existing `EpisodicEdge` WRITE trait; filled `deposit_counterfactual` v2 (writes −6 on split). Closes the **counterfactual** seam (not the prefetch loop — R4 honesty). 5 tests + 3 latent scaffold fixes; 550 contract green, clippy clean. +- **③ DEFER** (unanimous) — sense-candidate = firewall-placement design slice. +- **Citation fix (R3):** §8's `edge.rs:750 concern_level` reads `direction()` (pathological-dim0), not `PlasticityState`; the per-plane claim stands via `plasticity.rs freeze_s/heat_s` + `lib.rs:46/52`. + +**Build order now:** [coarse = MRU shipped] → **D-ATOM-4/RawEdge (DONE)** → per-plane `PlasticityState` co-fire (GATED phase B). diff --git a/crates/lance-graph-contract/src/counterfactual.rs b/crates/lance-graph-contract/src/counterfactual.rs index cd67488b..4d84a5db 100644 --- a/crates/lance-graph-contract/src/counterfactual.rs +++ b/crates/lance-graph-contract/src/counterfactual.rs @@ -73,7 +73,7 @@ pub const SPAWN_DISSONANCE_THRESHOLD: f32 = 0.55; /// The exact type for pole positions (`i8` vs a newtype from D-ATOM-1's `I4x32`) /// is **BLOCKED** on D-ATOM-1 (the I4-32D atom basis). Using `i8` here as a /// conservative placeholder — the range `[-8, +7]` is i4-compatible. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq)] // not Eq: `dissonance` is f32 pub struct SplitPoles { /// The axis index (0-31 in the I4-32D basis, per D-ATOM-1). /// @@ -148,10 +148,13 @@ pub fn deposit_counterfactual( // For now the interface is expressed via the `EpisodicEdge` trait below. edge: &mut dyn EpisodicEdge, ) -> bool { - todo!( - "v2 deposit: if split.split, call edge.set_inference_mantissa(-6) \ - (InferenceType::Counterfactual.to_mantissa()); return whether deposit was made" - ) + if split.split { + // `InferenceType::Counterfactual.to_mantissa() == -6` — the road-not-taken nibble. + edge.set_inference_mantissa(-6); + true + } else { + false + } } // ═══════════════════════════════════════════════════════════════════════════ @@ -248,6 +251,7 @@ impl CounterfactualMailbox { /// /// Only call when `dissonance > SPAWN_DISSONANCE_THRESHOLD` (the spawn /// gate in [`should_spawn_mailbox`]). + #[allow(unused_variables)] // scaffold stub — BLOCKED on D-PERSONA-5 (ractor outer-swarm) pub fn new(poles: SplitPoles, committed_free_energy: f32) -> Result { todo!( "v3 spawn: register with D-PERSONA-5 ractor outer-swarm; \ @@ -339,6 +343,7 @@ impl FreeEnergyComparison { /// is cleared after successful revision. /// - `awareness`: opaque handle to the NARS revision surface. /// **BLOCKED: type unknown** — placeholder `&mut dyn AwarenessRevise` below. +#[allow(unused_variables)] // scaffold stub — BLOCKED on D-PERSONA-5 (awareness.revise signature) pub fn revise_if_minority_wins( mailbox: CounterfactualMailbox, edge: &mut dyn EpisodicEdge, @@ -431,3 +436,107 @@ pub enum RevisionOutcome { /// The majority pole held; no revision was performed. MajorityHolds, } + +// ═══════════════════════════════════════════════════════════════════════════ +// RawEdge — the zero-dep, mantissa-only structural impl of EpisodicEdge +// ═══════════════════════════════════════════════════════════════════════════ + +/// A **mantissa-only** episodic edge: holds ONLY the signed i4 inference nibble +/// (the bits 46–49 of a `CausalEdge64`), and **structurally nothing else**. +/// +/// It wraps an `i8`, not a `u64`: a `u64` newtype could *read* the plasticity +/// bits 50–52, so "mantissa-only" would be a convention, not a guarantee. Wrapping +/// the i4 alone makes it unforgeable — `size_of::() == 1`, with no room +/// for plasticity / W / truth / temporal. Same one-writer-per-field structural +/// split as `MailboxSoaView`/`MailboxSoaOwner`, applied to the inference nibble. +/// It is the zero-dep stand-in that unblocks the `EpisodicEdge` impl-location; +/// a real `impl EpisodicEdge for CausalEdge64` stays deferred to the +/// `causal-edge-v2-layout` crate (which `lance-graph-contract` does not depend on). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub struct RawEdge(i8); + +impl RawEdge { + /// New `RawEdge`, clamping `m` into the signed-i4 range `[-8, 7]`. + #[must_use] + pub const fn new(m: i8) -> Self { + Self(clamp_i4(m)) + } + + /// The held i4 mantissa. + #[must_use] + pub const fn mantissa(self) -> i8 { + self.0 + } +} + +impl EpisodicEdge for RawEdge { + fn set_inference_mantissa(&mut self, m: i8) { + self.0 = clamp_i4(m); + } + fn inference_mantissa(&self) -> i8 { + self.0 + } +} + +/// Clamp to the signed 4-bit range `[-8, 7]` (the inference-nibble domain). +const fn clamp_i4(m: i8) -> i8 { + if m < -8 { + -8 + } else if m > 7 { + 7 + } else { + m + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::escalation::{CollapseHint, CouncilVerdict}; + + fn verdict(split: bool) -> CouncilVerdict { + CouncilVerdict { hint: CollapseHint::Flow, confidence: 0.9, split } + } + + #[test] + fn raw_edge_is_one_byte_mantissa_only() { + // The structural guarantee: no room for plasticity/W/truth/temporal bits. + assert_eq!(core::mem::size_of::(), 1); + } + + #[test] + fn raw_edge_clamps_to_i4_range() { + assert_eq!(RawEdge::new(-6).mantissa(), -6); + assert_eq!(RawEdge::new(7).mantissa(), 7); + assert_eq!(RawEdge::new(8).mantissa(), 7); // saturates high + assert_eq!(RawEdge::new(-9).mantissa(), -8); // saturates low + assert_eq!(RawEdge::new(127).mantissa(), 7); + assert_eq!(RawEdge::new(-128).mantissa(), -8); + } + + #[test] + fn raw_edge_roundtrips_through_trait_object() { + let mut e = RawEdge::default(); + let dyn_e: &mut dyn EpisodicEdge = &mut e; + dyn_e.set_inference_mantissa(-6); + assert_eq!(dyn_e.inference_mantissa(), -6); + dyn_e.set_inference_mantissa(99); // clamps + assert_eq!(dyn_e.inference_mantissa(), 7); + } + + #[test] + fn deposit_counterfactual_writes_minus_six_on_split() { + let mut e = RawEdge::default(); + let made = deposit_counterfactual(&verdict(true), &mut e); + assert!(made, "split verdict deposits"); + assert_eq!(e.mantissa(), -6, "Counterfactual nibble = -6"); + } + + #[test] + fn deposit_counterfactual_noops_on_non_split() { + let mut e = RawEdge::new(3); + let made = deposit_counterfactual(&verdict(false), &mut e); + assert!(!made, "non-split is a no-op"); + assert_eq!(e.mantissa(), 3, "edge untouched"); + } +} diff --git a/crates/lance-graph-contract/src/lib.rs b/crates/lance-graph-contract/src/lib.rs index 8799a785..09c94a5c 100644 --- a/crates/lance-graph-contract/src/lib.rs +++ b/crates/lance-graph-contract/src/lib.rs @@ -47,6 +47,7 @@ pub mod codegen_spine; pub mod cognitive_shader; pub mod collapse_gate; pub mod container; +pub mod counterfactual; pub mod crystal; pub mod cycle_accumulator; pub mod distance;