You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .claude/board/AGENT_LOG.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,17 @@
1
+
## [Main-thread] D-ODOO-SAV-4 — odoo-savant Reasoner layer (4 impls, one per ReasoningKind)
2
+
3
+
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)`.
4
+
5
+
**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`.
6
+
7
+
**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.
**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.
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).
**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`.
6
+
7
+
**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).
8
+
9
+
**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.
10
+
11
+
**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).
1
12
## 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
2
13
3
14
**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.
**Status:** PROPOSAL — §2 displacement is current-state; §3 multi-server expansion is unbuilt, gated on the §4 determinism probe
4
+
**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)
**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)
7
+
8
+
### Scope
9
+
10
+
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.
1
11
## 2026-05-27 — bindspace-singleton-to-mailbox-soa-v1 (dissolve the shared `Arc<BindSpace>` into per-mailbox `MailboxSoA<N>` ephemeral thoughtspace)
**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).
41
+
42
+
-**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).
43
+
-**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).
44
+
-**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`.
45
+
-**Docs** — EPIPHANIES E-AUDIT-1.
46
+
-**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.
Copy file name to clipboardExpand all lines: .claude/board/TECH_DEBT.md
+75Lines changed: 75 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -253,6 +253,81 @@ filter discipline — agents pull their own debt by `@`-mention.
253
253
(Seeded with known deferrals from recent PRs. New items PREPEND
254
254
with today's date.)
255
255
256
+
## 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
257
+
258
+
**Status:** Open
259
+
**Priority:** P1 (the transcoded substrate silently behaves as the baseline AriGraph outperforms; correctness-of-port, not a crash)
**Introduced by:** the Python→Rust AriGraph transcode (`crates/lance-graph/src/graph/arigraph/`, per `.claude/knowledge/integration-plan-grammar-crystal-arigraph.md` E11)
262
+
**Payoff estimate:** Option A ~150-250 LOC in-place; Option B = D-CSV-6 (~600) + D-CSV-7 (~350), substrate change
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).
267
+
268
+
The transcode diverged on **both** stages:
269
+
-`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.
270
+
-`retrieval.rs::OsintRetriever` semantic search is exact `entity_index`**name** lookup + BFS (no embedding retrieval; loses the paper's "grill"→"grilling" generalization).
271
+
- 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.
272
+
- 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.
273
+
274
+
### Options (types kept in both; this is a mechanism fix, not a deletion — "fix from the beginning")
275
+
276
+
-**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.
277
+
-**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.
278
+
279
+
**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.
280
+
281
+
### Cross-references
282
+
283
+
- Paper source: arxiv 2407.04363 §2 "AriGraph World Model" + Alg.1 (Memory Graph Search) + eq.1 (episodic relevance).
**Payoff estimate:** substrate serde-derive strip ~per-file small; audit JSON→binary canonical_bytes is the larger item (tracked separately)
297
+
298
+
### The invariant
299
+
300
+
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.
301
+
302
+
### Acceptable — outer-boundary ingestion (serde correct by design, NOT debt)
303
+
304
+
| Site | Boundary |
305
+
|---|---|
306
+
|`lance-graph/src/{ast.rs, logical_plan.rs}`| Cypher text → AST → plan IR feeding DataFusion (cold-path parse) |
|`lance-graph-contract/src/literal_graph.rs::ingest_aiwar_json`| physical parser for an external `.json` data file (zero-dep, hand-rolled) |
313
+
314
+
### Debt — internal / substrate / egress (no boundary; violates the invariant)
315
+
316
+
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.)
317
+
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).
318
+
319
+
`serde_json` is an **optional** dep gated behind `jsonl`/`realtime`/`auth-jwt`/`lance-sink`; the default callcenter build pulls zero JSON.
320
+
321
+
### Cross-references
322
+
323
+
-`BOOT.md`#6 (serde-out-of-types); `.claude/knowledge/integration-plan-grammar-crystal-arigraph.md:166` ("serde kept out of types by project convention")
324
+
-`TD-SDR-AUDIT-PERSIST-1` (the JSONL-sink-as-deliverable entry this reframes)
## 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
0 commit comments