Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .claude/board/AGENT_LOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## [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)`.

**Dispatch resolution lives in callcenter** — the contract stays an untouched inheritance vow (no `namespace` field added to `Savant`). `resolve_savant(kind, namespace)` filters the roster by kind; for ambiguous kinds it splits via `DISPATCH_NS` (the `Other(RECONCILE_MATCH)` 19-vs-21 split per #419: `erp.k3.reconcile_match` / `erp.k3.payment_reconcile`) then by `namespace == savant.name`.

**Scope:** all 25 dispatch through the 4 impls; the 14 `NEEDS-INPUT` savants dispatch fine here (they're blocked on woa-rs *evidence feeds*, not the impl). Row-level column fusion is deferred to when woa-rs supplies materialized evidence — v1 fusion is coverage-based + monotone-in-evidence.

**Tests:** 8 new (`savant_reasoners::tests`) — resolution, RECONCILE_MATCH namespace split, single-candidate, strategy↔inference, monotone confidence, async-trait dispatch, kind-mismatch — all green; 137 prior callcenter tests pass; `zone_serialize_check` (no-JSON guard) clean.

**Branch:** `claude/activate-lance-graph-att-k2pHI`, synced to main via merge `20da477` (preserving the `with_jsonl_audit → Result<Self,AuditError>` fix + the `Policy`/`smb_policy` re-export). `cargo test -p lance-graph-callcenter --features jsonl` green. This was the follow-on PR gated on the dispatch-shape review that #419 resolved.

---

## [Main-thread → woa-rs HANDOFF] Odoo savant AXIS-B evidence-contract scaffold (carve-out request)

Wrote `.claude/odoo/savants/_SCAFFOLD-EVIDENCE-CONTRACT.md` — a self-contained handover asking the **woa-rs session** (roster/evidence-schema owner) to carve out the **4 AXIS-B slots per savant** (Arrow `EvidenceRef` schema · odoo field→signal map · property-level OWL alignment · the decision in evidence terms) so lance-graph can implement the `Reasoner` impls (D-ODOO-2 / D-ODOO-SAV-4) in one pass without cross-session ping-pong. Includes the fixed dispatch tuple for all 25 (priority-tiered) + the target `Reasoner` shape + the open dispatch-shape question (N impls vs savant-config registry). Hand-back: fill per-savant docs + note here. No code; doc only. On branch `splat3d-cpu-simd-renderer-MAOO0` (PR #416).
Expand Down
11 changes: 11 additions & 0 deletions .claude/board/EPIPHANIES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 2026-05-27 — E-AUDIT-1 — `with_jsonl_audit` jsonl-feature build break: a default-feature `cargo check` masks feature-gated error-type mismatches

**Status:** FINDING

**Click:** `UnifiedBridge::with_jsonl_audit` (added in PR #366 as the OQ-7-3 opt-in constructor, `#[cfg(feature = "jsonl")]`) was typed `-> std::io::Result<Self>`, but its body is `JsonlAuditSink::new(...)?` and `JsonlAuditSink::new -> Result<Self, AuditError>`. `AuditError` carries `Io(#[from] std::io::Error)` (the io→AuditError direction) but there is **no** reverse `From<AuditError> for std::io::Error`, so the `?` could not coerce `AuditError` into the declared `io::Error` return — E0277. The **default-feature `cargo check` skips this path entirely** (the constructor is feature-gated), so the break only surfaced when CI built `--features jsonl`.

**Fix (commit `ea2a378`, branch `claude/activate-lance-graph-att-k2pHI`):** one line — return the honest error type `Result<Self, crate::audit_sink::AuditError>`. Two equivalent ~3-line forms existed: (1) change the return type to `Result<Self, AuditError>` [taken — "W2's instinct"]; (2) add a crate-wide `impl From<AuditError> for std::io::Error` and keep the `io::Result` signature. Form 1 chosen: the form-2 coercion would lossily flatten `ChannelFull` / `Serialize` / `SchemaMigration` / `Lance` / `Arrow` into `io::Error::other`, lying about the failure class for every future caller. Zero callers depended on the old signature (grep across all cloned repos: only the def + one doc-comment mention), so the signature change broke nothing. `cargo check/test -p lance-graph-callcenter --features jsonl` clean (137 tests).

**Lesson (generalizes):** a `#[cfg(feature = …)]` fn whose body uses `?` across two error types is invisible to a default-feature `cargo check`. Any crate with optional-feature error paths needs a CI matrix that builds each feature (or `--all-features`), else these E0277s ship to whoever first enables the feature — here, the still-queued MedCare-rs sprint-2 item 5 that consumes this constructor. And: error-type honesty beats `From`-coercion convenience — return the real domain error rather than a lossy `into()` to a narrower std type.

**Cross-ref:** PR #366 (constructor introduction, OQ-7-2/7-3 locks); `audit_sink/mod.rs::AuditError`; TD-SDR-AUDIT-PERSIST-1 in TECH_DEBT.md (the JSON-as-debt reframe — orthogonal to this signature fix).
## 2026-05-27 — E-RUBICON-RACTOR — the Σ10 Rubicon commit IS the Heckhausen action-phase crossing; ractor start/stop = crossing/closing the Rubicon; Libet "free won't" = the pre-commit veto; the kanban is a SurrealDB VIEW over leading LanceDB storage

**Status:** CONJECTURE / design-grounding. Names the psychological origin of the *already-shipped* Σ10 Rubicon doctrine. **Provenance note:** "Σ10 Rubicon" is canonical and implemented (`SigmaTierRouter` Rubicon-resonance dispatch, `D-CSV-10` shipped PR #388; origin `linguistic-epiphanies-2026-04-19.md` E21), but **"Libet" and "Heckhausen" appear nowhere in the board/code/transcripts** — that grounding was a different session or verbal, recorded here now.
Expand Down
10 changes: 10 additions & 0 deletions .claude/board/INTEGRATION_PLANS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 2026-05-27 — multi-server-cognition-expansion-v1 (legacy-stack displacement + Raft-log / SoA-state-machine)

**Status:** PROPOSAL — §2 displacement is current-state; §3 multi-server expansion is unbuilt, gated on the §4 determinism probe
**Confidence:** HIGH vs JanusGraph + Cassandra; Zitadel displaced by Ory (Kratos+Hydra) for authN; HIGH the log-replicated-SoA shape is correct; LOW it is proven (determinism unproven)
**Plan file:** `.claude/plans/multi-server-cognition-expansion-v1.md`
**Predecessors:** `cognitive-substrate-convergence-v1` (belief-delta log = the episodic arc); `surrealdb/core/src/kvs/lance` (the LSM-on-lance engine the WAL-as-Raft-log rides)

### Scope

Kills the "for multiple servers we need JanusGraph / Cassandra / Zitadel" argument. (1) Component displacement: distributed graph + CP via SurrealDB-on-TiKV + lance-graph; Cassandra's AP is the wrong consistency model for a belief substrate; **Ory** (Kratos+Hydra) fills the one real gap (authN/IdP), binary stays verification-only. (2) Multi-server path: Raft replicates the **belief-delta / episodic LOG**, the zero-copy SoA is the per-node **state machine**, the Rubikon `commit_gate` is the Raft **append point**; TiKV-the-log sits *under* lance-the-state (not "instead of"). Hard prerequisite: byte-deterministic NARS apply (`reencode_safety` / D-SDR-26) — **unproven**; next deliverable is the determinism probe, not more synthesis. authN (Ory) is orthogonal to the consensus layer.
## 2026-05-27 — bindspace-singleton-to-mailbox-soa-v1 (dissolve the shared `Arc<BindSpace>` into per-mailbox `MailboxSoA<N>` ephemeral thoughtspace)

**Status:** PROPOSAL / design (migration spec; NOT yet implemented). **Plan file:** `.claude/plans/bindspace-singleton-to-mailbox-soa-v1.md`. **Epiphany:** `E-MAILBOX-IS-BINDSPACE`.
Expand Down
9 changes: 9 additions & 0 deletions .claude/board/PR_ARC_INVENTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@

---

## callcenter/audit-fix — fix(callcenter): `with_jsonl_audit` returns `Result<Self, AuditError>` (branch work)

**Status:** On branch `claude/activate-lance-graph-att-k2pHI` (HEAD `ea2a378`, not yet a PR). 1-line `.rs` change + this board record (EPIPHANIES E-AUDIT-1, prepended 2026-05-27).

- **Added** — nothing new; retypes `UnifiedBridge::with_jsonl_audit` return from `std::io::Result<Self>` → `Result<Self, crate::audit_sink::AuditError>` (`unified_bridge.rs:315`). Resolves an E0277 that only the `--features jsonl` build surfaced (the default `cargo check` skips the feature-gated path).
- **Locked** — audit constructors return the **domain** error (`AuditError`), not `io::Result`. **No** crate-wide `From<AuditError> for std::io::Error` coercion (rejected: lossy across the non-`Io` variants `ChannelFull`/`Serialize`/`SchemaMigration`/`Lance`/`Arrow`). Optional-feature error paths must be CI-checked under their feature, not just default-feature (E-AUDIT-1).
- **Deferred** — none. MedCare-rs sprint-2 item 5 (first real caller) consumes the `AuditError` signature directly; any caller needing `io::Result` interop adds a local `map_err`, not a crate-wide `From`.
- **Docs** — EPIPHANIES E-AUDIT-1.
- **Confidence (2026-05-27):** working — `cargo check/test -p lance-graph-callcenter --features jsonl` clean at commit time (137 tests); tree clean; zero callers depend on the old signature.
Comment on lines +38 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Status claim inconsistent with PR context and file governance rules.

Line 40 states "not yet a PR" but this entry is being added as part of PR #420 (per PR objectives). Additionally, the file header (lines 3-6) states this tracks "Every merged PR", yet this entry is being prepended pre-merge.

This violates the historical-record contract:

  • Pre-merge entries risk becoming stale if the PR changes or is abandoned
  • The APPEND-ONLY rule (line 8) prevents correction beyond confidence annotations
  • The "not yet a PR" claim contradicts the current PR #420 context

Recommendation: Either update line 40 to reference PR #420 explicitly, or defer adding this entry until after PR #420 merges. The append-only discipline works best when entries are truly immutable historical facts, not in-flight documentation.

Suggested fix
-**Status:** On branch `claude/activate-lance-graph-att-k2pHI` (HEAD `ea2a378`, not yet a PR). 1-line `.rs` change + this board record (EPIPHANIES E-AUDIT-1, prepended 2026-05-27).
+**Status:** In PR `#420` (branch `claude/activate-lance-graph-att-k2pHI`, HEAD `ea2a378`). 1-line `.rs` change + this board record (EPIPHANIES E-AUDIT-1, prepended 2026-05-27).

Alternatively, consider moving this entire entry addition to a post-merge housekeeping commit so it becomes a true historical record per the file's stated purpose.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/board/PR_ARC_INVENTORY.md around lines 38 - 46, The board entry
incorrectly claims "not yet a PR" although this change is part of PR `#420` and
violates the file's "Every **merged** PR" and APPEND-ONLY rules; fix by editing
the prepended entry in .claude/board/PR_ARC_INVENTORY.md: either replace the
"not yet a PR" text (the tuple containing claude/activate-lance-graph-att-k2pHI
and commit ea2a378) with an explicit reference to "PR `#420`" and keep the rest
intact, or remove/defer this new entry entirely and add it in a post-merge
housekeeping commit so the file remains an immutable record.

## PR #411 — Cognitive substrate: locked 33-TSV atom layer + 34-tactic recipes + escalation loop (MERGED 2026-05-27 → main)

**Status:** MERGED. Branch `claude/splat3d-cpu-simd-renderer-MAOO0` → `main`, 39 commits.
Expand Down
75 changes: 75 additions & 0 deletions .claude/board/TECH_DEBT.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,81 @@ filter discipline — agents pull their own debt by `@`-mention.
(Seeded with known deferrals from recent PRs. New items PREPEND
with today's date.)

## 2026-05-27 — TD-ARIGRAPH-EPISODIC-FIDELITY-1: AriGraph episodic retrieval was transcoded as the RAG baseline the paper beats, not the paper's structural search

**Status:** Open
**Priority:** P1 (the transcoded substrate silently behaves as the baseline AriGraph outperforms; correctness-of-port, not a crash)
**Scope:** crate:lance-graph domain:arigraph domain:retrieval D-CSV-6 D-CSV-7
**Introduced by:** the Python→Rust AriGraph transcode (`crates/lance-graph/src/graph/arigraph/`, per `.claude/knowledge/integration-plan-grammar-crystal-arigraph.md` E11)
**Payoff estimate:** Option A ~150-250 LOC in-place; Option B = D-CSV-6 (~600) + D-CSV-7 (~350), substrate change

### What (ground truth: arxiv 2407.04363 §2 + Alg.1 + eq.1)

The paper's world model is `G = (V_s, E_s, V_e, E_e)`: semantic vertices/edges (triplets) + episodic vertices (observations) + **episodic edges** `e^t_e = (v^t_e, E^t_s)` linking each observation to the triplets extracted at that step. Retrieval is **two-stage and structural**: semantic search returns `E^Q_s`; episodic search then scores each episode by triplet-incidence `rel(v^i_e) = (n_i / max(N_i,1)) · log(max(N_i,1))` (single-triplet observations weighted 0).

The transcode diverged on **both** stages:
- `episodic.rs::EpisodicMemory::top_k` ranks episodes by **Hamming distance between observation fingerprints** (`label_fp`) — RAG-style similarity on raw observation text, *decoupled* from the semantic hits. The structural `n_i/N_i` relevance is absent.
- `retrieval.rs::OsintRetriever` semantic search is exact `entity_index` **name** lookup + BFS (no embedding retrieval; loses the paper's "grill"→"grilling" generalization).
- The **episodic edge `E_e` does not exist as a structure**: the transcoded `triplet_graph.rs` `Triplet` is `{subject, object, relation, truth, timestamp}` — the W5-spec `witness_ref: u64` (the W-slot) was **dropped**. `Episode.triplets: Vec<String>` is used only for unbundle/rebundle, never retrieval.
- Net: **three disconnected episodic/provenance representations** — `episodic.rs` (fingerprint-RAG), `witness_corpus.rs` (`WitnessIndexHashMap` spo→positions + `WitnessIndexCamPq`, wired to neither Triplet nor episodic), and the dropped W-slot.

### Options (types kept in both; this is a mechanism fix, not a deletion — "fix from the beginning")

- **Option A — narrow in-place eq.1 fix.** Add a triplet-id link from `Episode` to `E_s`; couple episodic search to consume `E^Q_s`; replace `top_k` fingerprint scoring with eq.1 incidence relevance (zero-weight single-triplet episodes). Keeps `Episode`/`EpisodicMemory`. Lower risk, no substrate change. **Leaves `witness_corpus.rs` still disconnected** (its own residual debt). Semantic-search embedding generalization still open.
- **Option B — mailbox / W-slot convergence (recommended end-state; = existing plan).** Restore the W-slot on `Triplet`/`CausalEdge64` (v2 layout `[53:58]`, the "discourse corpus-root handle"); make `witness_corpus.rs` (already CAM-PQ + HashMap indexed) THE episodic store = the per-`MailboxId` "spatial-temporal meaning accumulator" (`contract::collapse_gate::MailboxId`); retire `episodic.rs`'s fingerprint-RAG. The episodic edge `E_e` = `triplet.W-slot → MailboxId`; eq.1 `n_i/N_i` falls out of `WitnessIndexHashMap::lookup(spo)` incidence. Collapses the three stores into one and stays serialization-free ("the `(source_mailbox, chain_position)` tuple is the wire"). **This is `cognitive-substrate-convergence-v1` D-CSV-6 (`WitnessCorpus`) + D-CSV-7 (`MailboxSoA` W-slot)** — already planned, HIGH risk, gated on the CSV OQ ratification.

**Recommendation:** B is the architecturally-correct convergence and is already the planned direction; A is a legitimate interim that makes retrieval *faithful to the paper* without waiting on the substrate change, at the cost of leaving the `witness_corpus.rs` duplication for B to collapse later.

### Cross-references

- Paper source: arxiv 2407.04363 §2 "AriGraph World Model" + Alg.1 (Memory Graph Search) + eq.1 (episodic relevance).
- `crates/lance-graph/src/graph/arigraph/{episodic.rs, retrieval.rs, triplet_graph.rs, witness_corpus.rs}`
- `.claude/plans/cognitive-substrate-convergence-v1.md` D-CSV-6 (`WitnessCorpus` replaces `SpoWitnessChain<32>`) + D-CSV-7 (`MailboxSoA` W-slot) + §6 v2 layout `[53:58]` W slot
- `.claude/knowledge/spo-schema-and-mailbox-sidecar.md` (SPO-W tetrahedron; `MailboxId` = meaning accumulator); `.claude/knowledge/integration-plan-grammar-crystal-arigraph.md` E11 (transcode provenance)

---

## 2026-05-27 — TD-JSON-SERIALIZATION-SITES-1: JSON/serde occurrences catalogued; internal-substrate serde is debt, outer-boundary ingestion is not

**Status:** Open
**Priority:** P2 (no crash; violates the single-binary no-serialization invariant where it occurs internally)
**Scope:** crate:lance-graph crate:lance-graph-callcenter domain:serialization domain:invariant
**Introduced by:** AriGraph transcode (serde-on-substrate) + D-SDR-4/5 audit sinks (JSON egress)
**Payoff estimate:** substrate serde-derive strip ~per-file small; audit JSON→binary canonical_bytes is the larger item (tracked separately)

### The invariant

lance-graph compiles every "program" into **one statically-linked binary** — there is no internal IPC/network boundary, so serialization between in-binary parts is meaningless. The rule (BOOT.md #6): **"No JSON serialization in types. Serde stays debug-only."** Serialization is legitimate ONLY at the **outer ingestion boundary** — post-compile input that must be parsed: files / REST / a query language / external tokens. JSON is excluded everywhere else because the canonical bytes (`canonical_bytes()` / Arrow columns / the CAM bar-code) *are* the value; JSON would be a redundant second representation.

### Acceptable — outer-boundary ingestion (serde correct by design, NOT debt)

| Site | Boundary |
|---|---|
| `lance-graph/src/{ast.rs, logical_plan.rs}` | Cypher text → AST → plan IR feeding DataFusion (cold-path parse) |
| `lance-graph/src/parameter_substitution.rs` | `HashMap<String, serde_json::Value>` query params (post-compile input) |
| `lance-graph/src/config.rs` | TOML config load at startup |
| `lance-graph-callcenter/src/auth.rs` | JWT claims (`serde_json::from_slice`) — JWT is base64url-JSON by RFC 7519 |
| `lance-graph-catalog/src/unity_catalog.rs` | Databricks Unity Catalog REST (external service) |
| `cognitive-shader-driver/src/wire.rs`, `lance-graph-callcenter/src/postgrest.rs`, `*/serve.rs` | post-compile REST ingestion points (lab/research surface per `lab-vs-canonical-surface.md`) |
| `lance-graph-contract/src/literal_graph.rs::ingest_aiwar_json` | physical parser for an external `.json` data file (zero-dep, hand-rolled) |

### Debt — internal / substrate / egress (no boundary; violates the invariant)

1. **serde derived on AriGraph cognitive substrate types** — `graph/arigraph/orchestrator.rs` (`MetaOrchestrator`, `StyleTopology`, `TopologyEdge`, `MulAssessment`, `DkPosition`, `TrustTexture`, `FlowState`, `GraphSensorium`, …) and `graph/arigraph/sensorium.rs` (`GraphSensorium`/`GraphBias`/`HealingAction`/`HealingType`, also intra-crate-duplicated with orchestrator.rs) + `graph/spo/truth.rs::TruthValue`. These are hot-path substrate (transcode cruft from the Python source's dicts). The only legitimate egress is the `/mri` `OrchestratorSnapshot`/`TopologyEdgeSnapshot` DTOs — serde belongs **only** on those boundary DTOs, stripped from the core types. (CONJECTURE: the `/mri` HTTP handler that serializes the snapshot was not located this session; confirm before stripping.)
2. **Audit log emitted as JSON** — `lance-graph-callcenter/src/audit_sink/jsonl_sink.rs` (JSON lines) and `lance_sink.rs:151` (a JSON string stuffed into an Arrow column), read back by `bin/audit_verify.rs`; reachable via `UnifiedBridge::with_jsonl_audit`. The audit event's canonical form is already the 26-byte binary `UnifiedAuditEvent::canonical_bytes()` that the merkle chain hashes — JSON is a redundant second representation. Canonical egress should be the binary append-log or typed Arrow columns, not JSON. **Reframes TD-SDR-AUDIT-PERSIST-1** (which treats the JSONL sink as owed *work*; under this invariant the JSON form itself is the debt).

`serde_json` is an **optional** dep gated behind `jsonl`/`realtime`/`auth-jwt`/`lance-sink`; the default callcenter build pulls zero JSON.

### Cross-references

- `BOOT.md` #6 (serde-out-of-types); `.claude/knowledge/integration-plan-grammar-crystal-arigraph.md:166` ("serde kept out of types by project convention")
- `TD-SDR-AUDIT-PERSIST-1` (the JSONL-sink-as-deliverable entry this reframes)
- `crates/lance-graph-callcenter/src/audit_sink/{jsonl_sink.rs, lance_sink.rs}`, `bin/audit_verify.rs`, `unified_bridge.rs::with_jsonl_audit`
- `crates/lance-graph/src/graph/arigraph/{orchestrator.rs, sensorium.rs}`, `graph/spo/truth.rs`

---


## 2026-05-13 — TD-Q2-STUBS-DEDUP-1: q2 carries local `lance-graph` + `q2-ndarray` stubs that must be replaced with re-exports from the canonical crates before FMA demo can compile

**Status:** Open
Expand Down
Loading
Loading