From 8f73e03a2421141e5eb853dabfbb7182c5fb692a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 07:21:32 +0000 Subject: [PATCH 1/8] board: post-merge hygiene for #689 (PR_ARC prepend + LATEST_STATE row; OGAR #201 companion noted) Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/board/LATEST_STATE.md | 8 ++++++++ .claude/board/PR_ARC_INVENTORY.md | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index 98c7213f..e412c2da 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -46,6 +46,14 @@ Doc-only. #695 (standards-watch + E-PRX12-STANDARDS-GROUNDING-1) MERGED same day - **`class_view::execute_defaults(targets, present, store, apply_default)`** (NEW free fn next to `execute_compute_dag`) + **`ClassView::default_targets(class) -> &[u8]`** (NEW default trait method, zero-fallback `&[]`, next to `compute_dag`). The **Default-recipe** (write-if-blank, `RecipeCentroid::Default` — the C# `if (field == null) field = new …` lazy-init idiom, 56 methods in the MedCare corpus) execution primitive: fires `apply_default(store, t)` for each target whose presence bit is CLEAR, in slice order; skips present AND already-fired positions (duplicate-safe — after a default fires the field IS populated; pins the C# `GetOrCreateChartPanel` init-only-on-create quirk, devcomponent_chart.cs:161-180); abort-at-target reusing `ExecuteComputeError::Compute` (`Cyclic` unreachable — defaults have no dependency order; a default reading a computed field is a Compute recipe). **Presence gate = `WideFieldMask`** (not `FieldMask`): every u8 position addressable, no 64-field ceiling — the wide-mask lesson the a2ui screen-addressing #205 correction paid for, applied at birth. Phase rule documented (not interleaved): defaults run BEFORE `execute_compute_dag`; the caller folds the fired list into its presence mask. One more brick, not a parallel path (the `screens_reachable_from` precedent): existing mask, existing error, same abort semantics as the Compute half. +7 unit tests (slice-order fire, present-skip, abort-keeps-earlier, empty-noop, wide-fire-past-64, duplicate-fires-once, hook-default-empty); 898 contract tests green; fmt + clippy clean (also carries the pending rustfmt reflow on `grammar/thinking_styles.rs` + `style_family.rs` — main was fmt-dirty on those two test files). Consumer witness lands in MedCare-rs (`chart_default_parity`, same arc). +## 2026-07-14 — MERGED #689 (merge `a260ff98`) — rung-content ladder ruled + persona demarcated + `contract::legacy_outliers` + `NodeGuid↔FacetCascade` bridge + D-TSC-1 alias fix + +- **Ruling doc (MANDATORY read, linked from CLAUDE.md):** `.claude/v3/knowledge/persona-vs-rung-ladder.md` — rung 0–1 observation / 2 = 144 verb atoms / 3 = the 34 tactic recipes (= THE runbooks: `contract::recipes` + ndarray `hpc/styles`) / 4 = StyleFamily macros (frozen×learned×exploration). The adjective-36 = separate unwired persona storyline, never rung 3. Open items O1–O6 live there. +- **Contract inventory adds:** `legacy_outliers::LegacyOutlier` (G1/G2/G3 grace carvings, le-contract §3a); `From for NodeGuid` + inverse + `NodeGuid::facet()` (byte-identical, no registry detour). +- **Planner:** `thinking::ThinkingStyle` deprecated alias + `PlannerStyleExt` re-exported again (old import path compiles, deprecation warning steers). +- **Probes flipped:** TD-STYLE-TABLE-RESIDUE item 3 → DORMANT; UNIFIED_STYLES tethered-not-collapsed. +- **Companion:** OGAR #201 (D‑V1‑GRACE‑CARVINGS canon mirror, merged). + ## 2026-07-12 — branch `claude/review-claude-board-files-nhqgx1` — `contract::temporal_pov::{VersionRange, TemporalPov}` — zero-dep temporal POV range filter (operator-directed) ### Current Contract Inventory — new entry diff --git a/.claude/board/PR_ARC_INVENTORY.md b/.claude/board/PR_ARC_INVENTORY.md index 4cada970..ab01761b 100644 --- a/.claude/board/PR_ARC_INVENTORY.md +++ b/.claude/board/PR_ARC_INVENTORY.md @@ -105,6 +105,31 @@ --- +## #689 lance-graph: Rung-content ladder + persona demarcation, FacetCascade bridge, legacy_outliers, D-TSC-1 alias fix, chess-arc bank + +**Status:** MERGED 2026-07-14 (merge `a260ff98`), branch `claude/review-claude-board-files-nhqgx1` (rebased onto post-#688 main after the four-repo restart), 6 commits. Companion: **OGAR #201** (D‑V1‑GRACE‑CARVINGS canon mirror, merged same day — paired-merge discipline). + +**Added:** +- `.claude/v3/knowledge/persona-vs-rung-ladder.md` — the operator-ruled **rung-content ladder** (0–1 observation / 2 = 144 verb atoms / 3 = the 34 NARS tactic **recipes = THE runbooks** / 4 = StyleFamily macros + frozen×learned×exploration triangle) + the **persona demarcation** (the adjective-36 in `contract::thinking` = separate unwired persona-modeling storyline, never rung 3). Linked as MANDATORY read from CLAUDE.md § V3 SUBSTRATE. Open items O1–O6. +- `contract::legacy_outliers` — `LegacyOutlier::{WideMixed (3×u16+2×u24), WideTriple (4×u24), WideQuad (3×u32)}`, the strongly-discouraged 96-bit grace carvings (le-contract §3a); LE round-trip + V1-degenerate-case tests. +- `NodeGuid ↔ FacetCascade` byte-identical `From` impls + `NodeGuid::facet()` — the missing bridge to the content-blind surface (adoption had voted: facet:: 8 files/28 uses vs mint_for 3 apologetic sites). +- planner `thinking/mod.rs`: re-export of the deprecated `ThinkingStyle` alias + `PlannerStyleExt` lift (D-TSC-1 regression fix — the alias was stranded in the leaf module while the old import path hard-broke). + +**Locked:** +- **The rung ladder's content reading is ruled** (ladybug-rs → thinking-engine lineage); the shipped `RungLevel` Pearl reading is causal-depth, coexisting, NOT the content wiring. +- **"Runbooks" = the 34 tactics** (`contract::recipes` + ndarray `hpc/styles`), NOT the persona-36. `E-STYLE-FAMILY-VS-RUNBOOK-1`'s label corrected append-only via `E-RUNG-CONTENT-LADDER-1`. +- **Compat aliases must be lifted to every module level the old name was reachable from** (`E-COMPAT-ALIAS-MUST-BE-LIFTED-1`); an alias-token grep is not a compat gate — the old import path must compile. +- **Wide contiguous carvings are sanctioned-but-discouraged grace shapes, never `CascadeShape` variants** (`E-V3-GRACE-WIDE-CARVINGS-1`). +- p64-bridge `STYLES[ord % 12]` **probed DORMANT** (TD-STYLE-TABLE-RESIDUE item 3 flipped); `UNIFIED_STYLES` tethered-not-collapsed (census question closed). + +**Deferred:** O1 rung↔content wiring; O2 the true `StyleFamily → recipes` edge (retarget/twin `default_runbook`, rename the persona bridge); O4 remaining D-TSC-1 residue (`api::` re-export of `PlannerStyleExt`, the self-contradictory `#[deprecated]` note wording, `wire.rs`/`auto_style.rs` tethers); O5 free `style_by_ordinal` deprecation; O6 the composed triangle macro (FUTURE-DESIGN landing zone). + +**Docs:** persona-vs-rung-ladder.md (v3/knowledge); le-contract.md §3a; CLAUDE.md V3-section link; EPIPHANIES `E-RUNG-CONTENT-LADDER-1` / `E-V3-GRACE-WIDE-CARVINGS-1` / `E-COMPAT-ALIAS-MUST-BE-LIFTED-1`; TECH_DEBT TD-STYLE-TABLE-RESIDUE item-3 flip; chess-arc bank (`E-CHESS-ARC-TO-V3-TRANSFER-1`, `E-THINKING-SPINE-CHESS-EVIDENCE-1` + spine-plan addendum). + +**Confidence (2026-07-14):** working — contract lib tests green (legacy_outliers 5, facet_bridge 1), planner builds clean, clippy clean; doc/board rulings are operator-verbatim. + +--- + ## #676 lance-graph: Post-#674 doc arc — E-NOBODY-WAITS-1 + VISION.md (graded AGI canon) + ancestry census + D-MTS-1 design inputs **Status:** MERGED 2026-07-10 (merge commit `001839e`), branch `claude/review-claude-board-files-nhqgx1` (restarted from #674's merge), 4 commits, doc-only. From 19cdda4a4472f96c30c10a1af295731ee84e2740 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 03:25:19 +0000 Subject: [PATCH 2/8] =?UTF-8?q?board+v3:=20E-ACK-VIOLATION-REGRADE-1=20?= =?UTF-8?q?=E2=80=94=20severity=20regrade=20of=20the=20ack-gated=20advance?= =?UTF-8?q?=20+=20the=20stream=20tier's=20quantified=20economics=20(operat?= =?UTF-8?q?or=20ruling,=202026-07-17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ack-gated advance is regraded from "correct code, wrong tier" to a hard architecture violation: a duplicate of the pre-existing batch-writer->kanbanstep route, built while ignoring that reasoning has no outer ack at all; operator hard-break + internal reversal. Newly banked (not in the prior four entries): the quantified arithmetic (40 ns-class stream ops vs 10-400 us acks; ractor messaging = Tokio = 1e4-1e7x, hence ractor stays compile-time-ownership-only, never belittled in code/docs); the SPO 2^3 amortization mechanism (one SPO cache load + <=8 L1-resident cycles -> CausalEdge64 NARS candidates); kanbanstep = auto-progression on the Rubicon aktionale phase (Heckhausen goalstate, Libet timing, 550->200 ms window); the ONLY ack home = the external ontology membrane (lance-graph-callcenter Supabase-realtime tickets/SLA + OGAR actionhandler queues). Live consequence: the chess/expert-iteration Phase-1 wording corrected before work starts. FUTURE-DESIGN fifth-wave row mirrors the entry. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/board/EPIPHANIES.md | 16 ++++++++++++++++ .claude/v3/FUTURE-DESIGN.md | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 5165c98e..6431b696 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,19 @@ +## 2026-07-17 — E-ACK-VIOLATION-REGRADE-1 — the ack-gated advance regraded: not "correct code, wrong tier" but a hard architecture violation (a DUPLICATE of batch-writer→kanbanstep), operator-reversed; the quantified arithmetic, the SPO 2³ amortization, and the callcenter SLA membrane banked + +**Status:** RULING sharpening + severity regrade (operator, 2026-07-17). Sharpens WITHOUT editing (append-only): E-ACK-IS-THE-KANBAN-TRIGGER-1 (its fire-and-forget clause stands; its trigger framing was the violation), E-KANBANSTEP-IS-THE-TRIGGER-1, E-ACK-HARD-GATE-VS-KANBANSTEP-STREAM-1, E-ACK-SLA-GATE-ACTIONHANDLER-QUEUE-1, E-NOBODY-WAITS-1. + +**Severity regrade (operator's words govern):** the prior entries graded `ack_and_propose` "correct code, wrong rank/tier." The operator grades it harder: the ack-gated advance **bluntly duplicated** the pre-existing batch-writer→kanbanstep route while **ignoring that reasoning has no outer ack at all** — "a brutally hard violation of the existing architecture that needed to be reversed internally," committed by an autoattended session; the operator put a **hard break** on the plan, scoping the mechanism to business-logic SLA only. The failure class joins E-FIVE-STYLE-TABLES-1 as the second measured instance of rediscovery-by-reinvention: an original demoted beyond recognition (the SurrealQL-AST carve-out obscured kanbanstep), then a later session rebuilds a second copy beside it and mis-ranks the copy canonical. + +**The arithmetic that makes the tier test non-negotiable (operator, quantified — new):** +- A stream-tier thinking operation is **~40 ns-class**. A durability ack is **10–400 µs** away. Pacing the former on the latter stalls each op by 250×–10,000× — "engineering dumbness at the highest level." +- Ractor mailbox messaging would ride Tokio (or worse): **10⁴–10⁷× slower** than the `&mut` owner surface — which is WHY the workspace hardly ever messages through ractor. **Ractor is solely the compile-time ownership guarantee**; per operator instruction the code/docs never belittle it as a "dummy" — the attestation must remain authoritative to the compiler (name the role, never the disparagement). + +**Why 40 ns-class ops are real — the SPO 2³ amortization (newly banked):** the stream tier's economics are amortization: **ONE cache load of the SPO**, then the **2³ rung-decomposition ladder runs ≤8 L1-resident cycles back-to-back**, emitting `CausalEdge64` awareness of NARS reasoning candidates. Reasoning reads run over the whole 16k–256k Lance row's versioning permutations through `temporal.rs`, processing inside the **550 ms → 200 ms window**. An ack inserted into that ladder doesn't slow it — it destroys the amortization, and with it the streaming Morton-tile inverse-pyramid perturbation-shader cascade (2bit×2bit 4×4), which requires uninterrupted streaming. The always-processing loop ("can't stop thinking") carries StreamDto → BusDto → PerturbationDto — cycles progress continuously; nothing external paces them. + +**The Rubicon/Libet reading sharpened:** kanbanstep = **auto-progression on the Rubicon aktionale phase** (Heckhausen's model supplies the goalstate structure; Libet timing governs planning and Bewerten→Commit). The ack-gated advance threw that away by making progression event-paced instead of phase-auto-progressive. The ONLY home where waiting is a feature: the **external ontology membrane** — `lance-graph-callcenter`'s Supabase-realtime transcode shape (tickets, business-logic SLA) and OGAR ticket orchestration (the actionhandler queues, E-ACK-SLA-GATE-ACTIONHANDLER-QUEUE-1). No reasoning path has an outer ack; the membrane does. + +**Live consequence (what re-fired this entry):** the chess/expert-iteration Phase-1 draft ("episode ingestion through the batch writer + M24 replay on real casts") is corrected BEFORE work starts: episode casts are storage-boundary fire-and-forget (the sink drains in background; M24 replay = crash-recovery bookkeeping, never pacing); the teacher/NARS revision loop advances kanbanstep-style, in-stream, pacing on NOTHING; nothing in the chess arc introduces an ack-paced advance. Drift signal unchanged (E-KANBANSTEP): any NEW code that paces a cycle on an ack event. + ## 2026-07-16 — E-SPRITE-IPB-HELIX-1 — moving object = HHTL-anchored splat sprite + helix motion code, mapped onto the x265 I/P/B grammar (crawl-first probe spec'd) **Status:** CONJECTURE [S/H] + PROBE SPEC (operator-directed amortization; the initial test deliberately replays the x265 GOP grammar, NOT H.268 — "not reaching for the stars"). diff --git a/.claude/v3/FUTURE-DESIGN.md b/.claude/v3/FUTURE-DESIGN.md index 649c0d8a..0d5d3fae 100644 --- a/.claude/v3/FUTURE-DESIGN.md +++ b/.claude/v3/FUTURE-DESIGN.md @@ -11,6 +11,12 @@ --- +## 2026-07-17 (fifth wave) — ack-violation regrade + the stream tier's economics named + +| Ruling | One line | Wiring queue | +|---|---|---| +| E-ACK-VIOLATION-REGRADE-1 | the ack-gated advance regraded from "correct code, wrong tier" to a hard architecture violation (duplicate of batch-writer→kanbanstep, operator hard-break + internal reversal); quantified: 40 ns-class stream ops vs 10–400 µs acks (250×–10,000× stall), ractor messaging = Tokio = 10⁴–10⁷× — ractor stays compile-time-ownership-only; NEW mechanism banked: SPO 2³ rung ladder = one SPO cache load + ≤8 L1-resident cycles → CE64 NARS candidates; kanbanstep = auto-progression on the Rubicon aktionale phase (550→200 ms window); the ONLY ack home = the external ontology membrane (callcenter Supabase-realtime tickets/SLA + OGAR actionhandler queues) | doc-only here; chess/expert-iteration Phase-1 wording corrected before start (episode casts fire-and-forget at the storage boundary; teacher/NARS loop paces on nothing); drift signal unchanged | + ## 2026-07-10 (fourth wave) — the chess arc: E-CHESS gets its measured instantiation (sibling repo) | Seed | One line | Wiring queue | From 08fa86c6ac6e64338ef5396cc8b1ed9c679b5416 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 03:36:44 +0000 Subject: [PATCH 3/8] =?UTF-8?q?v3:=20agent-proofing=20the=20kanbanstep-vs-?= =?UTF-8?q?ack=20ruling=20=E2=80=94=20trigger=20section,=20F15=20guardrail?= =?UTF-8?q?,=20/v3-audit=20check=207,=20read-through=20pointer,=20'dummy'?= =?UTF-8?q?=20wording=20retired?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four surfaces agents actually load now carry the protection (not just the board): (1) mailbox-kanban-model.md gains 'The trigger: kanbanstep, never an ack' (Rubicon aktionale auto-progression, the 40ns vs 10-400us arithmetic, the SPO 2^3 amortization, the tier test, the membrane); (2) sonnet-worker-guardrails.md F15 + STOP trigger 7 (any awaited event before an advance = STOP+report) — pasted into every worker brief; (3) /v3-audit check 7 = mechanical ack-paced-advance scan; (4) FUTURE-DESIGN read-through pointer over the superseded first-wave 'ack pumps' row (append-only, row not edited). Per operator instruction the 'compile-time ownership dummy' wording is retired in all four occurrences (kanban model, primer x2, write-on-behalf) — the role is named ('SOLELY the compile-time ownership guarantee') so the attestation stays authoritative to the compiler. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/commands/v3-audit.md | 11 ++++++++ .claude/v3/FUTURE-DESIGN.md | 10 +++++++ .claude/v3/knowledge/mailbox-kanban-model.md | 28 ++++++++++++++++++- .../v3/knowledge/sonnet-worker-guardrails.md | 5 ++++ .claude/v3/knowledge/v3-substrate-primer.md | 13 ++++++--- .claude/v3/knowledge/write-on-behalf.md | 4 +-- 6 files changed, 64 insertions(+), 7 deletions(-) diff --git a/.claude/commands/v3-audit.md b/.claude/commands/v3-audit.md index 74db62a2..e7ce256e 100644 --- a/.claude/commands/v3-audit.md +++ b/.claude/commands/v3-audit.md @@ -43,6 +43,17 @@ every hit with file:line and a one-line disposition `mint_for`'s own V1 arm (`canonical_node.rs`), and legacy-compat *reads* (`family()`/`identity()` accessors are reads, not mints). +7. **Ack-paced advance scan** (E-ACK-VIOLATION-REGRADE-1 — the ack-gated + advance was a hard architecture violation; do not let it regrow): + pattern `ack` co-occurring with `advance_phase|try_advance|KanbanMove` + in the same file, plus `\.await` or `ractor::(call!|cast)` on any path + that also matches `advance_phase|KanbanColumn|cycle`. Sanctioned: + `batch_writer.rs` (durability bookkeeping + the SLA-gate doc), + callcenter/OGAR SLA-membrane surfaces, tests, TD-MESSAGE-RESIDUE + sites already ledgered. Any NEW hit that paces a reasoning cycle on + an awaited event is a violation (kanbanstep is the only reasoning + advance). + End with a verdict per the v3-mailbox-warden vocabulary (OWNED / BOOTSTRAP-OK / ORPHAN-WRITE / RESURRECTION) plus LAYOUT-CLEAN / LAYOUT-GATED / LAYOUT-BREAK for check 5, and a one-paragraph summary. diff --git a/.claude/v3/FUTURE-DESIGN.md b/.claude/v3/FUTURE-DESIGN.md index 0d5d3fae..ef5381a1 100644 --- a/.claude/v3/FUTURE-DESIGN.md +++ b/.claude/v3/FUTURE-DESIGN.md @@ -44,6 +44,16 @@ D-TSC-1; the 5-savant fan-out surfaced the three-divergent-tables finding. ## 2026-07-10 — the ratified cognition arc (four rulings + one measured probe) +> **⊘ READ-THROUGH (2026-07-17):** the first row below +> (E-ACK-IS-THE-KANBAN-TRIGGER-1, "the Lance ack pumps the next +> KanbanMove") is read THROUGH E-KANBANSTEP-IS-THE-TRIGGER-1 and +> E-ACK-VIOLATION-REGRADE-1 (fifth wave, top of this file): the +> ack-trigger framing was a hard architecture violation, reversed — +> kanbanstep is the only reasoning advance; acks are durability +> bookkeeping; SLA-gated waiting lives only at the callcenter/OGAR +> membrane. The row's fire-and-forget clause stands; its trigger +> ranking does not. Append-only: the row is not edited. + **Rulings** (canonical: EPIPHANIES — measured results in `E-COMMA-QUORUM-MEASURED-1`; plan: `temporal-markov-and-style-classes-v1`): diff --git a/.claude/v3/knowledge/mailbox-kanban-model.md b/.claude/v3/knowledge/mailbox-kanban-model.md index bb16f93d..49148b30 100644 --- a/.claude/v3/knowledge/mailbox-kanban-model.md +++ b/.claude/v3/knowledge/mailbox-kanban-model.md @@ -27,7 +27,33 @@ proposes; the owner disposes. |---|---|---| | **Arm #1 — planner** | `lance-graph-planner/src/strategy/style_strategy.rs` | The D-MBX-A6 seam: the deferred `Outcome → Candidate/KanbanMove` adapter. Strategy outcomes (converged, cycle_count, gate verdicts) become kanban moves. | | **Arm #2 — symbiont** | `crates/symbiont` (`kanban_loop.rs` = POC) | SurrealDB-on-kv-lance executor: kanban updates as KV transactions on the same Lance substrate. Gated on the AdaWorldAPI surrealdb fork `kv-lance` feature. | -| **Structural owner** | `lance-graph-supervisor/kanban_actor.rs` | ractor actor per mailbox. **ractor is a compile-time ownership dummy** — it spawns and proves single-ownership via move semantics (`KanbanActor` with `type State = O`; the owner MOVES in at `pre_start`); it is NOT a data-plane bus and **not for messaging — it is slow** (operator, 2026-07-02). **It MAY serve as a HELPER where it makes sense** — spawn, supervision, occasional control RPC like the serialized Advance/MulAdvance (the codex #578 atomicity mechanism) — always keeping the speed difference in mind: nothing on the hot path may wait on ractor latency; hot-path dispatch belongs to the D-V3-W2e-probed ExecTarget. | +| **Structural owner** | `lance-graph-supervisor/kanban_actor.rs` | ractor actor per mailbox. **ractor is SOLELY the compile-time ownership guarantee** (name the role — the attestation must stay authoritative to the compiler; operator, 2026-07-17) — it spawns and proves single-ownership via move semantics (`KanbanActor` with `type State = O`; the owner MOVES in at `pre_start`); it is NOT a data-plane bus and **not for messaging — it is slow** (operator, 2026-07-02). **It MAY serve as a HELPER where it makes sense** — spawn, supervision, occasional control RPC like the serialized Advance/MulAdvance (the codex #578 atomicity mechanism) — always keeping the speed difference in mind: nothing on the hot path may wait on ractor latency; hot-path dispatch belongs to the D-V3-W2e-probed ExecTarget. | + +## The trigger: kanbanstep, never an ack (operator-ruled, 2026-07-10/17) + +**The canonical kanban advance is the in-stream synchronous step +("kanbanstep")**: the writer/stream fires `on_version → +try_advance_phase(&mut)` inline with the version it already holds — +auto-progression on the Rubicon **aktionale** phase (Heckhausen's model +supplies the goalstate; Libet timing governs planning and +Bewerten→Commit; 550→200 ms window). The cognitive-shader-driver +**can't stop thinking**: cycles progress continuously over +StreamDto → BusDto → PerturbationDto; the SPO 2³ rung ladder amortizes +ONE SPO cache load over ≤8 back-to-back L1-resident cycles emitting +`CausalEdge64` NARS candidates — 40 ns-class operations. + +**An ack NEVER paces a cycle.** A durability ack is 10–400 µs away — +pacing a 40 ns thinking op on it stalls 250×–10,000× and destroys the +ladder amortization (and the Morton-tile cascade streaming with it). +The ack's only job is durability bookkeeping (`unacked()` crash-replay). +The ONLY tier where waiting on an ack is a feature is the **external +ontology membrane**: lance-graph-callcenter's Supabase-realtime +transcode shape (tickets, business-logic SLA) + OGAR actionhandler +queues. Tier test before any advance-path design: *SLA/audit obligation +(ticket) → SLA gate; cycle budget (thought) → kanbanstep stream.* Never +cross-route. History + severity: `E-KANBANSTEP-IS-THE-TRIGGER-1`, +`E-ACK-VIOLATION-REGRADE-1` (the ack-gated advance was a hard +architecture violation, operator-reversed — do not rebuild it). ## The ahead-firing batch writer diff --git a/.claude/v3/knowledge/sonnet-worker-guardrails.md b/.claude/v3/knowledge/sonnet-worker-guardrails.md index 65f57a68..645a2762 100644 --- a/.claude/v3/knowledge/sonnet-worker-guardrails.md +++ b/.claude/v3/knowledge/sonnet-worker-guardrails.md @@ -94,6 +94,7 @@ exactly the row below, never a neighbor. | F12 | Test literals that only work in one classid order / one layout version (synthetic 0xAB12-style values) | test values come from the §2-sanctioned composers + realistic allocations; never hand-rolled hex composites | | F13 | Worker "fixes" a failing unrelated test to get green | out of scope (§1 rule 1): report the failure, touch nothing | | F14 | German PII labels or model identifiers in committed artifacts | never emit either in any file/commit (workspace-wide rule); chat-only | +| F15 | A cycle/phase advance paced on an ack, message, or awaited event (the ack-gated advance — a hard architecture violation, operator-reversed; E-ACK-VIOLATION-REGRADE-1) | kanbanstep is the ONLY reasoning advance (inline `on_version → try_advance_phase(&mut)`); acks = durability bookkeeping; SLA-gated waiting exists ONLY at the callcenter/OGAR membrane; ractor = compile-time ownership guarantee, never messaging (10⁴–10⁷× tax). A worker asked to await anything before an advance = STOP+report | ## §4 — Sanctioned command palette (copy these, don't improvise) @@ -123,6 +124,10 @@ appears, because each requires accumulation-tier judgment: 5. The change would add/modify a write path's ownership routing (needs v3-mailbox-warden). 6. Anything RBAC, PII-adjacent, or externally visible. +7. The change would make ANY cycle/phase advance wait on an ack, a + message, a `ractor::call!`/`cast`, or any awaited event (F15 — the + tier test is the orchestrator's call, not the worker's; the only + sanctioned waiting tier is the callcenter/OGAR SLA membrane). Cross-ref: `.claude/knowledge/autoattended-multiagent-pattern.md` (the 4-savant wave pattern these rules slot into), `v3-substrate-primer.md` diff --git a/.claude/v3/knowledge/v3-substrate-primer.md b/.claude/v3/knowledge/v3-substrate-primer.md index cd19f929..f978ce45 100644 --- a/.claude/v3/knowledge/v3-substrate-primer.md +++ b/.claude/v3/knowledge/v3-substrate-primer.md @@ -24,9 +24,13 @@ sense. The unit of cognition ownership is the **Mailbox**: **SurrealDB-on-kv-lance symbiont mode** (arm #2, `crates/symbiont` is the POC shape). `lance-graph-supervisor kanban_actor.rs` is the ractor structural owner. -- **ractor is a compile-time ownership dummy** — spawn-only, never a - hot-path bus. Rust move semantics through the actor model prove - single-ownership at compile time; that proof is the point, not the runtime. +- **ractor is SOLELY the compile-time ownership guarantee** — spawn-only, + never a hot-path bus (name the role; the attestation must stay + authoritative to the compiler — operator, 2026-07-17). Rust move + semantics through the actor model prove single-ownership at compile + time; that proof is the point, not the runtime. Messaging through it + would ride Tokio at 10⁴–10⁷× the `&mut` owner surface — hence the + workspace hardly ever messages (E-ACK-VIOLATION-REGRADE-1). - The **batch writer fires an AHEAD kanban update on write CAST** — it does not wait for the write to land. Ownership delegation is checked via cache logic at cast time (cast id vs envelope stamp). @@ -45,7 +49,8 @@ inherits mailbox ownership **up and down**: (default `0` = bootstrap per the zero-fallback ladder) stamps the owner for Lance-down provenance and consumer-up write-on-behalf. - **Iron rule (fleet-wide): every consuming crate writes ON BEHALF OF the - ractor dummy-owner mailbox.** See `write-on-behalf.md`. + ractor owner mailbox** (the compile-time ownership guarantee). See + `write-on-behalf.md`. - **The V3 atom is the 4+12 facet** (E-V3-FACET-4-PLUS-12): 4-byte prefix `[domain|appid|classview u16]` + a 96-bit payload from the sanctioned L1–L8 catalogue (rails / palette256² digital CAM_PQ / triplets / quads / diff --git a/.claude/v3/knowledge/write-on-behalf.md b/.claude/v3/knowledge/write-on-behalf.md index 8c47cb9f..4c784888 100644 --- a/.claude/v3/knowledge/write-on-behalf.md +++ b/.claude/v3/knowledge/write-on-behalf.md @@ -11,8 +11,8 @@ ## The rule -**Every consuming crate writes ON BEHALF OF the ractor dummy-owner mailbox. -Always.** No consumer writes a SoA row, tenant lane, or Lance dataset as +**Every consuming crate writes ON BEHALF OF the ractor owner mailbox (the +compile-time ownership guarantee). Always.** No consumer writes a SoA row, tenant lane, or Lance dataset as itself. The write names its owner via the envelope stamp: ```rust From debc795ac401e9a0fb2541bd0dd865c2d8e999c8 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 03:47:42 +0000 Subject: [PATCH 4/8] =?UTF-8?q?board+v3:=20E-SOA-OWN-BOARD-NO-SIDECAR-1=20?= =?UTF-8?q?=E2=80=94=20the=20second=20ack-model=20violation=20banked=20(si?= =?UTF-8?q?decar=20kanban=20state=20outside=20the=20SoA;=20M24's=20gate=20?= =?UTF-8?q?already=20forbids=20it)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Operator ruling 2026-07-17: the ack model also violates 'every SoA has its own kanban board INSIDE the SoA' — BatchWriter's board/acked BTreeMaps are a heap sidecar (not tenant bytes, not owner-serialized, not Lance-versioned, invisible to temporal.rs). M24's own mechanical gate ('grep writer-internal intent queues = zero') forbids exactly this shape; the post-ruling correction commits were doc-only. The positive ruling banked: the SoA is a self-controlling actor model — ownership proof + board + budget live in the owned rows; a sidecar reintroduces convention-kept consistency, the risk class the compile-time model deletes. Fix design recorded two-stage: Stage A excises ack_and_propose (zero production callers) and re-homes the SLA gate at the callcenter membrane; Stage B (gated on the W2a board-tenant mint) migrates the sidecar into board-tenant rows — ack = the row's LanceVersion, unacked = a temporal.rs Strict projection, M24 green. W2a priority raised: it now gates closing both ack violations. FUTURE-DESIGN fifth-wave row added. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/board/EPIPHANIES.md | 13 +++++++++++++ .claude/v3/FUTURE-DESIGN.md | 1 + 2 files changed, 14 insertions(+) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 6431b696..0517ea13 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,16 @@ +## 2026-07-17 — E-SOA-OWN-BOARD-NO-SIDECAR-1 — the ack model's SECOND violation: the BatchWriter's board/acked BTreeMaps are a sidecar kanban state OUTSIDE the SoA; the ruled model is the self-controlling actor-SoA (board inside the SoA), and M24's own gate already forbids writer-internal intent queues + +**Status:** RULING + FINDING (operator, 2026-07-17, extending E-ACK-VIOLATION-REGRADE-1 below; code receipts verified same day). Reads with M24 (ENTROPY-MILESTONES), Addendum-8 (temporal.rs = the READ side of the WAL), E-1BRC-OWNER-GRANULARITY-1. + +**The operator's ruling:** the ack model also violates "**every SoA has its own kanban board INSIDE the SoA**" — and the BatchWriter's state was never migrated in. A sidecar might be faster, "but then it needs to be extremely meticulous and explicit," a risk class the operator rejects. The positive statement banked verbatim in substance: **the SoA is an actor model controlling itself** — ownership proof (`&mut` + the ractor compile-time attestation), the kanban board, and the budget all live in the owned rows; probably unique in the Rust world in allowing a gigantic number of safe concurrent writing processes. A sidecar reintroduces a second bookkeeping surface kept consistent only by convention — exactly the risk class the compile-time model exists to delete. + +**Verified in code (`crates/lance-graph-planner/src/batch_writer.rs`):** `board: BTreeMap)>` + `acked: BTreeMap` — heap sidecar: not tenant bytes, not owner-serialized, not Lance-versioned, invisible to `temporal.rs`. **The ledger already forbids this shape:** M24's mechanical gate says "grep writer-internal intent queues = zero" — the `board` map IS a writer-internal intent queue. M24 is QUEUED; the shipped writer is the pre-M24 shape; the post-ruling correction commits (39b6818f, 793ad911) were doc-only and never touched the structure. Additional receipt: `ack_and_propose` has ZERO production callers (tests only) — the orphaned relabeled ack-pump, with the kanbanstep primitive (`VersionScheduler::on_version`) still physically wired inside the ack path (violation commit b49ccf3f; see the review in this session). + +**The fix design (composes with the excision; two stages):** +- **Stage A (unblocked):** excise `ack_and_propose` + its scheduler imports from `batch_writer.rs` (the file returns to the pure WAL it was born as, a9ed99cb); the SLA gate re-homes at the membrane (`lance-graph-callcenter` interim per D-AHG-1's "never a solo OGAR PR"; OGAR mirror rides the next batched mint); `/v3-audit` check 7's exemption narrows from "batch_writer.rs" to the membrane surfaces only. +- **Stage B (gated on the W2a board-tenant mint, T1–T6):** the sidecar maps migrate INTO the SoA — intent moves land as board-tenant writes on the owner's rows through `MailboxSoaOwner` (`&mut` = the serialization); the ack becomes the row's own `LanceVersion` (the CastId↔LanceVersion join = the row's version — Addendum-8's temporal join, now structural); `unacked()` becomes a `temporal.rs` projection (a Strict read at the pinned reference = crash-replay = time-travel, ONE mechanism); the BTreeMaps delete and M24's gate goes green. **W2a's priority rises accordingly — it is now the enabling dependency for closing both ack violations.** +- Speed honesty: the sidecar's presumed speed is unmeasured; the 1BRC lanes showed the owner-local write path IS the fast path (owner plateau 1–256; boundary copies, not witnesses, were the tax). Any claimed sidecar advantage must be measured against a tenant write into the already-hot row before it can justify the meticulousness burden. + ## 2026-07-17 — E-ACK-VIOLATION-REGRADE-1 — the ack-gated advance regraded: not "correct code, wrong tier" but a hard architecture violation (a DUPLICATE of batch-writer→kanbanstep), operator-reversed; the quantified arithmetic, the SPO 2³ amortization, and the callcenter SLA membrane banked **Status:** RULING sharpening + severity regrade (operator, 2026-07-17). Sharpens WITHOUT editing (append-only): E-ACK-IS-THE-KANBAN-TRIGGER-1 (its fire-and-forget clause stands; its trigger framing was the violation), E-KANBANSTEP-IS-THE-TRIGGER-1, E-ACK-HARD-GATE-VS-KANBANSTEP-STREAM-1, E-ACK-SLA-GATE-ACTIONHANDLER-QUEUE-1, E-NOBODY-WAITS-1. diff --git a/.claude/v3/FUTURE-DESIGN.md b/.claude/v3/FUTURE-DESIGN.md index ef5381a1..7473b104 100644 --- a/.claude/v3/FUTURE-DESIGN.md +++ b/.claude/v3/FUTURE-DESIGN.md @@ -16,6 +16,7 @@ | Ruling | One line | Wiring queue | |---|---|---| | E-ACK-VIOLATION-REGRADE-1 | the ack-gated advance regraded from "correct code, wrong tier" to a hard architecture violation (duplicate of batch-writer→kanbanstep, operator hard-break + internal reversal); quantified: 40 ns-class stream ops vs 10–400 µs acks (250×–10,000× stall), ractor messaging = Tokio = 10⁴–10⁷× — ractor stays compile-time-ownership-only; NEW mechanism banked: SPO 2³ rung ladder = one SPO cache load + ≤8 L1-resident cycles → CE64 NARS candidates; kanbanstep = auto-progression on the Rubicon aktionale phase (550→200 ms window); the ONLY ack home = the external ontology membrane (callcenter Supabase-realtime tickets/SLA + OGAR actionhandler queues) | doc-only here; chess/expert-iteration Phase-1 wording corrected before start (episode casts fire-and-forget at the storage boundary; teacher/NARS loop paces on nothing); drift signal unchanged | +| E-SOA-OWN-BOARD-NO-SIDECAR-1 | the SECOND ack-model violation: BatchWriter's `board`/`acked` BTreeMaps = a sidecar kanban state OUTSIDE the SoA — M24's own gate ("grep writer-internal intent queues = zero") already forbids the shape; the ruled model is the self-controlling actor-SoA (board INSIDE the SoA: ownership proof + board + budget in the owned rows); `ack_and_propose` = zero production callers, kanbanstep primitive still wired inside the ack path (b49ccf3f) | **Stage A (unblocked):** excise ack_and_propose from batch_writer.rs (pure WAL restored) → SLA gate re-homes at the callcenter membrane; /v3-audit check-7 exemption narrows. **Stage B (gated on the W2a board-tenant mint, T1–T6):** sidecar maps migrate into board-tenant rows (ack = the row's LanceVersion; unacked = a temporal.rs Strict projection); M24 goes green. **W2a priority RAISED — it now gates closing both violations** | ## 2026-07-10 (fourth wave) — the chess arc: E-CHESS gets its measured instantiation (sibling repo) From ab416ecfef49e3bb35f2e788ce19b2db0bc0cc23 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 04:01:25 +0000 Subject: [PATCH 5/8] =?UTF-8?q?board+v3:=20E-TASKS-SOA-AT-THE-MEMBRANE-1?= =?UTF-8?q?=20=E2=80=94=20ack=20=3D=20outer=20task-serialization=20boundar?= =?UTF-8?q?y;=20membrane=20state=20=3D=20a=20Tasks=20SoA=20at=20callcenter?= =?UTF-8?q?;=20multi-SoA=20reasoning=20first-class;=20P64=2064x64=20tenant?= =?UTF-8?q?=20era=20superseded=20by=20the=204+12=20facet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Operator ruling 2026-07-17 (third message of the ack arc): ACK's positive role is the outer serialization boundary of INCOMING tasks, which split into SoAs — inside the membrane stays kanbanstep-only. Multi-SoA reasoning is first-class: chess models a 'mirror neuron'-like opponent SoA beside the self SoA; Odoo-class business logic spans multiple reasoning loops and is never evicted from them. The membrane's own state is a Tasks SoA at the lance-graph-callcenter outer ontology zone (task = V3 row: 32-bit classid + 96-bit payload; the task board lives INSIDE the Tasks SoA — the no-sidecar rule is universal; ack = an admission advance on the task row's board; SLA audit = row Lance versions + temporal.rs reads). This revises Stage A's membrane home: a Tasks SoA design (envelope-auditor + batched-mint gated), never a module wrapping relocated BTreeMaps. P64 supersession noted: the 64x64=4096 gridlake was the tenant atom of its era; V3 tenants cast directly into the 4+12 facet — gridlake remains a measured batch topology (1BRC lane J), not the tenant shape. FUTURE-DESIGN fifth-wave row added. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/board/EPIPHANIES.md | 14 ++++++++++++++ .claude/v3/FUTURE-DESIGN.md | 1 + 2 files changed, 15 insertions(+) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 0517ea13..c012ba6e 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,17 @@ +## 2026-07-17 — E-TASKS-SOA-AT-THE-MEMBRANE-1 — ack = the OUTER serialization boundary of incoming tasks, which SPLIT into SoAs; the membrane's task state is itself a Tasks SoA at the callcenter ontology zone (no sidecar anywhere); multi-SoA reasoning is first-class; P64's 64×64 tenant assumption superseded by the V3 4+12 facet + +**Status:** RULING + design direction (operator, 2026-07-17 — third message of the ack arc; completes E-SOA-OWN-BOARD-NO-SIDECAR-1 and E-ACK-VIOLATION-REGRADE-1 below by giving the ack its POSITIVE role and the membrane state its correct shape). + +**The ack's proper job (not exile — a boundary):** ACK is the **outer serialization boundary of INCOMING tasks** — the admission point where outer work (tickets, business logic, external requests) is serialized and **split into SoAs**. Inside the membrane: kanbanstep-only, no acks (unchanged). At the membrane: acknowledging a task and decomposing it into reasoning compartments IS the job. + +**Multi-SoA reasoning is first-class (operator-named instances):** +- **Not every reasoning fits into one SoA.** Counterfactual and concurrent thinking span compartments — in chess, model a **"mirror neuron"-like SoA for the opponent's thinking**: the self-SoA and the opponent-model SoA reason concurrently, each with its own board, budget, and rung horizon. (Direct design input to the chess/expert-iteration arc: the opponent model is a sibling SoA, not a lane inside the self's SoA.) +- **Business logic needs more than one SoA.** An ERP workflow spans reasoning loops — "Odoo wouldn't be happy being evicted out of its reasoning loops." A task admitted at the membrane fans out to N inner reasoning SoAs; the task row tracks its children. + +**The membrane state's correct shape — a Tasks SoA, not a module with maps:** the corrected home for what the BatchWriter sidecar tried to be is a **Tasks SoA at the `lance-graph-callcenter` outer ontology zone**: each incoming task = a V3 row (**32-bit classid + 96-bit payload**, the 4+12 facet cast); the task's kanban board lives INSIDE the Tasks SoA (the no-sidecar rule is universal — it binds the membrane exactly as it binds reasoning); ack = an admission/phase advance on the task row's own board; the SLA audit trail = the rows' Lance versions + `temporal.rs` reads (no bespoke `acked` map — the CastId↔LanceVersion join is the row's own version); task→SoA fan-out is tracked on the row (edges/rails), and the children are inner reasoning SoAs where kanbanstep-only applies. This REVISES the Stage-A interim from E-SOA-OWN-BOARD-NO-SIDECAR-1: the SLA gate does not re-home as a module wrapping relocated BTreeMaps — it lands as the Tasks SoA design (envelope-auditor + batched-mint gated: a task-row classid rides the next mint). + +**P64 supersession note (operator):** P64 dates from the era when **every tenant was 64×64 = 4096**, the cache-friendly gridlake. V3 tenants are now **cast directly into the 4+12 facet** — the result is a 32-bit classid + 96-bit payload. The gridlake remains a MEASURED batch-topology sweet spot (1BRC lane J: 64×64 gridlake batching), but it is no longer the tenant atom; the facet is. P64-era docs claiming 64×64 as the universal tenant shape are read through this note (doc sweep queued, not urgent — MODULE-TABLE census rows unaffected). + ## 2026-07-17 — E-SOA-OWN-BOARD-NO-SIDECAR-1 — the ack model's SECOND violation: the BatchWriter's board/acked BTreeMaps are a sidecar kanban state OUTSIDE the SoA; the ruled model is the self-controlling actor-SoA (board inside the SoA), and M24's own gate already forbids writer-internal intent queues **Status:** RULING + FINDING (operator, 2026-07-17, extending E-ACK-VIOLATION-REGRADE-1 below; code receipts verified same day). Reads with M24 (ENTROPY-MILESTONES), Addendum-8 (temporal.rs = the READ side of the WAL), E-1BRC-OWNER-GRANULARITY-1. diff --git a/.claude/v3/FUTURE-DESIGN.md b/.claude/v3/FUTURE-DESIGN.md index 7473b104..de7b8208 100644 --- a/.claude/v3/FUTURE-DESIGN.md +++ b/.claude/v3/FUTURE-DESIGN.md @@ -17,6 +17,7 @@ |---|---|---| | E-ACK-VIOLATION-REGRADE-1 | the ack-gated advance regraded from "correct code, wrong tier" to a hard architecture violation (duplicate of batch-writer→kanbanstep, operator hard-break + internal reversal); quantified: 40 ns-class stream ops vs 10–400 µs acks (250×–10,000× stall), ractor messaging = Tokio = 10⁴–10⁷× — ractor stays compile-time-ownership-only; NEW mechanism banked: SPO 2³ rung ladder = one SPO cache load + ≤8 L1-resident cycles → CE64 NARS candidates; kanbanstep = auto-progression on the Rubicon aktionale phase (550→200 ms window); the ONLY ack home = the external ontology membrane (callcenter Supabase-realtime tickets/SLA + OGAR actionhandler queues) | doc-only here; chess/expert-iteration Phase-1 wording corrected before start (episode casts fire-and-forget at the storage boundary; teacher/NARS loop paces on nothing); drift signal unchanged | | E-SOA-OWN-BOARD-NO-SIDECAR-1 | the SECOND ack-model violation: BatchWriter's `board`/`acked` BTreeMaps = a sidecar kanban state OUTSIDE the SoA — M24's own gate ("grep writer-internal intent queues = zero") already forbids the shape; the ruled model is the self-controlling actor-SoA (board INSIDE the SoA: ownership proof + board + budget in the owned rows); `ack_and_propose` = zero production callers, kanbanstep primitive still wired inside the ack path (b49ccf3f) | **Stage A (unblocked):** excise ack_and_propose from batch_writer.rs (pure WAL restored) → SLA gate re-homes at the callcenter membrane; /v3-audit check-7 exemption narrows. **Stage B (gated on the W2a board-tenant mint, T1–T6):** sidecar maps migrate into board-tenant rows (ack = the row's LanceVersion; unacked = a temporal.rs Strict projection); M24 goes green. **W2a priority RAISED — it now gates closing both violations** | +| E-TASKS-SOA-AT-THE-MEMBRANE-1 | ack's POSITIVE role: the outer serialization boundary of INCOMING tasks, which split into SoAs; multi-SoA reasoning first-class (chess opponent "mirror neuron" SoA; Odoo multi-loop business logic never evicted from its reasoning loops); the membrane state = a **Tasks SoA** at lance-graph-callcenter (task = V3 row, 32-bit classid + 96-bit payload; board INSIDE the Tasks SoA; ack = admission advance on the task row's own board; SLA audit = Lance versions + temporal.rs — no bespoke acked map); P64's 64×64-tenant era superseded by the 4+12 facet cast (gridlake stays a measured batch topology, not the tenant atom) | REVISES Stage A's membrane home: Tasks SoA design (envelope-auditor + batched-mint gated — task-row classid rides the next mint), not a module with relocated maps; chess arc gains the opponent-model sibling SoA as a named Phase-1/3 element; P64-doc read-through sweep queued (low priority) | ## 2026-07-10 (fourth wave) — the chess arc: E-CHESS gets its measured instantiation (sibling repo) From 2645118057efec32d7bdf4b9fee8a5fd278bb998 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 04:09:31 +0000 Subject: [PATCH 6/8] =?UTF-8?q?board+v3:=20E-KANBAN-STAYS-INTERIOR-MEMBRAN?= =?UTF-8?q?E-IS-ACK-ONLY-1=20=E2=80=94=20retract=20the=20kanban-at-membran?= =?UTF-8?q?e=20error;=20kanban=20is=20reasoning-interior=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Operator correction 2026-07-17 ('Why did you move kanban to the outer membrane that's unacceptable'). E-TASKS-SOA-AT-THE-MEMBRANE-1's body wrongly wrote 'the task's kanban board lives INSIDE the Tasks SoA' and 'ack = an admission/phase advance on the task row's own board' — that attaches the Rubicon reasoning kanban (auto-progressive, nobody-waits) to the membrane's task rows, dragging the reasoning-tier construct out to the ticket tier and making the membrane look like it runs cognition. That re-crosses the exact boundary E-ACK-VIOLATION-REGRADE-1 set, in the opposite direction. Corrected: kanban is REASONING-INTERIOR ONLY, never at the membrane. The membrane does ACK-serialization only — admits, serializes, and SPLITS tasks into reasoning SoAs (where cognition + kanban happen). The Tasks SoA holds task-admission + SLA/ack ledger + fan-out edges in its rows (no sidecar — that rule holds); its progression is ack-gated (the SLA-gate/actionhandler-queue tier), categorically NOT a Rubicon KanbanColumn. Everything else in E-TASKS-SOA-AT-THE-MEMBRANE-1 stands (ack = outer boundary, Tasks SoA at callcenter, multi-SoA reasoning first-class, P64 4+12 supersession). A partial-retraction pointer is added over the retracted clauses (append-only; original not edited); the FUTURE-DESIGN row is corrected in place with the retraction row appended. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/board/EPIPHANIES.md | 16 ++++++++++++++++ .claude/v3/FUTURE-DESIGN.md | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index c012ba6e..60e49674 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,5 +1,21 @@ +## 2026-07-17 — E-KANBAN-STAYS-INTERIOR-MEMBRANE-IS-ACK-ONLY-1 — CORRECTION of E-TASKS-SOA-AT-THE-MEMBRANE-1: kanban does NOT move to the membrane; it is reasoning-interior ONLY. The membrane does ACK-serialization; the Tasks SoA holds admission + SLA + fan-out state (no sidecar) — the SLA-gate/actionhandler-queue tier, categorically NOT the Rubicon reasoning kanban + +**Status:** CORRECTION (operator, 2026-07-17: "Why did you move kanban to the outer membrane that's unacceptable"). Retracts TWO body clauses of E-TASKS-SOA-AT-THE-MEMBRANE-1 (below); the rest of that entry STANDS. Append-only: the original is not edited — this entry supersedes the retracted clauses. + +**What was retracted (my error):** E-TASKS-SOA-AT-THE-MEMBRANE-1 wrote "**the task's kanban board lives INSIDE the Tasks SoA**" and "**ack = an admission/phase advance on the task row's own board**." Both attach a KANBAN BOARD to the membrane's task rows. That drags the **reasoning-tier construct** (the Rubicon *aktionale*, auto-progressive, nobody-waits advance) out to the **ticket tier** — re-crossing the exact boundary E-ACK-VIOLATION-REGRADE-1 established, now in the opposite direction — and makes the membrane look like it *runs cognition*. Unacceptable. + +**The corrected model (two tiers, never conflated by name or mechanism):** +- **Kanban = the Rubicon phase machine** (Planning→CognitiveWork→Evaluation→Commit→Plan→Prune), auto-progressive, nobody-waits — is **REASONING-INTERIOR ONLY.** It lives inside every reasoning SoA and NOWHERE ELSE. It never appears at the membrane. Kanban never moves outward. +- **The membrane** (`lance-graph-callcenter` outer ontology zone) does **ACK-serialization ONLY:** it admits an incoming task, serializes it, and **SPLITS it into reasoning SoAs** — which is where cognition (and kanban) happens. The membrane delegates cognition; it never runs it. +- **The Tasks SoA** is that admission envelope, NOT a cognition board: each task = a V3 row (32-bit classid + 96-bit payload) carrying **task-admission state + SLA/ack ledger + fan-out edges to its child reasoning SoAs**, all in its rows (**no sidecar — that rule holds, unchanged**). Its progression is **ACK-GATED** — the SLA-gate / actionhandler-queue tier where waiting is a FEATURE — categorically different from the reasoning kanban's nobody-waits auto-progression. +- **Never cross-route:** reasoning advances by **kanbanstep** (interior, auto, no wait); a membrane task advances by **ACK** (external confirmation, SLA). A thought through the ack tier is E-ACK-VIOLATION-REGRADE-1; a membrane task carrying a Rubicon kanban is THIS entry's error. Both directions are the prime violation. + +**What still stands from E-TASKS-SOA-AT-THE-MEMBRANE-1:** ack = the outer serialization boundary of incoming tasks; the Tasks SoA at the callcenter zone as the admission envelope; multi-SoA reasoning first-class (chess opponent "mirror neuron" sibling SoA; Odoo multi-loop business logic never evicted); the no-sidecar rule binding the membrane's OWN state (admission/SLA/fan-out in the rows); P64's 64×64-tenant era superseded by the 4+12 facet cast. ONLY the "kanban board on the task row" clause is retracted. + ## 2026-07-17 — E-TASKS-SOA-AT-THE-MEMBRANE-1 — ack = the OUTER serialization boundary of incoming tasks, which SPLIT into SoAs; the membrane's task state is itself a Tasks SoA at the callcenter ontology zone (no sidecar anywhere); multi-SoA reasoning is first-class; P64's 64×64 tenant assumption superseded by the V3 4+12 facet +> **⊘ PARTIAL RETRACTION (2026-07-17, E-KANBAN-STAYS-INTERIOR-MEMBRANE-IS-ACK-ONLY-1, above):** the two clauses below claiming "the task's kanban board lives INSIDE the Tasks SoA" and "ack = an admission/phase advance on the task row's own board" are RETRACTED — kanban is reasoning-interior only and never moves to the membrane. Read the membrane's task state as **ACK-serialization + SLA ledger + fan-out** (the SLA-gate/actionhandler-queue tier), NOT a Rubicon kanban. Everything else in this entry stands. + **Status:** RULING + design direction (operator, 2026-07-17 — third message of the ack arc; completes E-SOA-OWN-BOARD-NO-SIDECAR-1 and E-ACK-VIOLATION-REGRADE-1 below by giving the ack its POSITIVE role and the membrane state its correct shape). **The ack's proper job (not exile — a boundary):** ACK is the **outer serialization boundary of INCOMING tasks** — the admission point where outer work (tickets, business logic, external requests) is serialized and **split into SoAs**. Inside the membrane: kanbanstep-only, no acks (unchanged). At the membrane: acknowledging a task and decomposing it into reasoning compartments IS the job. diff --git a/.claude/v3/FUTURE-DESIGN.md b/.claude/v3/FUTURE-DESIGN.md index de7b8208..32aa3c72 100644 --- a/.claude/v3/FUTURE-DESIGN.md +++ b/.claude/v3/FUTURE-DESIGN.md @@ -17,7 +17,8 @@ |---|---|---| | E-ACK-VIOLATION-REGRADE-1 | the ack-gated advance regraded from "correct code, wrong tier" to a hard architecture violation (duplicate of batch-writer→kanbanstep, operator hard-break + internal reversal); quantified: 40 ns-class stream ops vs 10–400 µs acks (250×–10,000× stall), ractor messaging = Tokio = 10⁴–10⁷× — ractor stays compile-time-ownership-only; NEW mechanism banked: SPO 2³ rung ladder = one SPO cache load + ≤8 L1-resident cycles → CE64 NARS candidates; kanbanstep = auto-progression on the Rubicon aktionale phase (550→200 ms window); the ONLY ack home = the external ontology membrane (callcenter Supabase-realtime tickets/SLA + OGAR actionhandler queues) | doc-only here; chess/expert-iteration Phase-1 wording corrected before start (episode casts fire-and-forget at the storage boundary; teacher/NARS loop paces on nothing); drift signal unchanged | | E-SOA-OWN-BOARD-NO-SIDECAR-1 | the SECOND ack-model violation: BatchWriter's `board`/`acked` BTreeMaps = a sidecar kanban state OUTSIDE the SoA — M24's own gate ("grep writer-internal intent queues = zero") already forbids the shape; the ruled model is the self-controlling actor-SoA (board INSIDE the SoA: ownership proof + board + budget in the owned rows); `ack_and_propose` = zero production callers, kanbanstep primitive still wired inside the ack path (b49ccf3f) | **Stage A (unblocked):** excise ack_and_propose from batch_writer.rs (pure WAL restored) → SLA gate re-homes at the callcenter membrane; /v3-audit check-7 exemption narrows. **Stage B (gated on the W2a board-tenant mint, T1–T6):** sidecar maps migrate into board-tenant rows (ack = the row's LanceVersion; unacked = a temporal.rs Strict projection); M24 goes green. **W2a priority RAISED — it now gates closing both violations** | -| E-TASKS-SOA-AT-THE-MEMBRANE-1 | ack's POSITIVE role: the outer serialization boundary of INCOMING tasks, which split into SoAs; multi-SoA reasoning first-class (chess opponent "mirror neuron" SoA; Odoo multi-loop business logic never evicted from its reasoning loops); the membrane state = a **Tasks SoA** at lance-graph-callcenter (task = V3 row, 32-bit classid + 96-bit payload; board INSIDE the Tasks SoA; ack = admission advance on the task row's own board; SLA audit = Lance versions + temporal.rs — no bespoke acked map); P64's 64×64-tenant era superseded by the 4+12 facet cast (gridlake stays a measured batch topology, not the tenant atom) | REVISES Stage A's membrane home: Tasks SoA design (envelope-auditor + batched-mint gated — task-row classid rides the next mint), not a module with relocated maps; chess arc gains the opponent-model sibling SoA as a named Phase-1/3 element; P64-doc read-through sweep queued (low priority) | +| E-TASKS-SOA-AT-THE-MEMBRANE-1 (⊘ partially retracted — see next row) | ack's POSITIVE role: the outer serialization boundary of INCOMING tasks, which split into SoAs; multi-SoA reasoning first-class (chess opponent "mirror neuron" SoA; Odoo multi-loop business logic never evicted from its reasoning loops); the membrane state = a **Tasks SoA** at lance-graph-callcenter (task = V3 row, 32-bit classid + 96-bit payload; SLA audit = Lance versions + temporal.rs — no bespoke acked map); P64's 64×64-tenant era superseded by the 4+12 facet cast (gridlake stays a measured batch topology, not the tenant atom) | REVISES Stage A's membrane home: Tasks SoA design (envelope-auditor + batched-mint gated — task-row classid rides the next mint), not a module with relocated maps; chess arc gains the opponent-model sibling SoA as a named Phase-1/3 element; P64-doc read-through sweep queued (low priority) | +| E-KANBAN-STAYS-INTERIOR-MEMBRANE-IS-ACK-ONLY-1 (CORRECTION) | kanban does NOT move to the membrane — it is the Rubicon reasoning advance, **reasoning-interior ONLY**. RETRACTS the previous row's "kanban board on the task row" clause: the membrane does ACK-serialization only; the Tasks SoA holds admission + SLA/ack ledger + fan-out edges (no sidecar) — the SLA-gate/actionhandler-queue tier, categorically NOT the Rubicon kanban. Cross-routing either way is the prime violation (thought→ack = E-ACK-VIOLATION-REGRADE-1; task→kanban = this) | Tasks SoA spec carries task lifecycle as an ack-gated SLA ledger, NEVER a Rubicon KanbanColumn; the reasoning kanban stays inside the child SoAs the task splits into | ## 2026-07-10 (fourth wave) — the chess arc: E-CHESS gets its measured instantiation (sibling repo) From c4f7d741e2d55acb20174f652e303539ca5dc70e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 04:36:59 +0000 Subject: [PATCH 7/8] =?UTF-8?q?eliminate=20ack=20everywhere=20(operator=20?= =?UTF-8?q?directive)=20=E2=80=94=20batch=5Fwriter=20becomes=20a=20pure=20?= =?UTF-8?q?intent=20recorder;=20doctrine,=20guards,=20and=20plans=20correc?= =?UTF-8?q?ted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code: batch_writer.rs loses ack/ack_and_propose/acked/unacked/ acked_version (zero production callers existed) and their scheduler imports; it records intent (cast/casts/intent_moves/on_behalf_of) and caches delegation — nothing else. W1e probes and the driver cast-pairing tests are rewritten to pin exactly that. Durability evidence is the written row's own LanceVersion in Lance, read through temporal.rs; crash-replay is a temporal READ comparing recorded intents against what Lance holds — never a stored ledger. Planner lib tests green (214); driver lib tests green (103); the two pre-existing nars_engine clippy deprecation errors on main are untouched. Doctrine: mailbox-kanban-model trigger section, VISION §5, INTEGRATION-PLAN Addendum-14, temporal-markov plan correction, M24 Status (PARTIAL: confirmation half deleted; intent-board collapse still gated on the W2a mint), FUTURE-DESIGN sixth-wave row. Dead with it: D-AHG-1, the 'SLA gate' and 'actionhandler queue' concepts (retired unbuilt) — the membrane admits/serializes/splits tasks with the transcode's own native semantics. Guards: /v3-audit check 7 is now the elimination scan; guardrails F15 + STOP trigger 7 ban rebuilding the mechanism under any name. Board: E-ACK-ELIMINATED-1 (terse, by design). Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/board/EPIPHANIES.md | 10 + .claude/commands/v3-audit.md | 23 +- .../temporal-markov-and-style-classes-v1.md | 11 + .claude/v3/ENTROPY-MILESTONES.md | 2 +- .claude/v3/FUTURE-DESIGN.md | 9 +- .claude/v3/INTEGRATION-PLAN.md | 18 + .claude/v3/VISION.md | 15 +- .claude/v3/knowledge/mailbox-kanban-model.md | 32 +- .../v3/knowledge/sonnet-worker-guardrails.md | 12 +- .../src/mailbox_soa.rs | 21 +- .../lance-graph-planner/src/batch_writer.rs | 328 ++++-------------- crates/lance-graph-planner/tests/w1_probes.rs | 61 ++-- 12 files changed, 188 insertions(+), 354 deletions(-) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 60e49674..f350168a 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,13 @@ +## 2026-07-17 — E-ACK-ELIMINATED-1 — the ack is removed from everywhere, completely eliminated (operator directive) + +**Status:** RULING + SHIPPED same day. Operator: "remove the ack from everywhere, completely eliminate it" — after the concept twice produced tier-crossing designs and, worse, became a lens every session saw everything through. Expelled from code, doctrine, and vocabulary; not relocated, not renamed. + +- **Code:** `batch_writer.rs` = pure intent recorder (`ack`/`ack_and_propose`/`acked`/`unacked`/`acked_version` deleted; zero production callers existed). W1e probes + driver cast-pairing tests rewritten (all green; the two pre-existing nars_engine clippy deprecation errors on main are untouched). +- **Semantics:** durability evidence = the written row's own `LanceVersion` in Lance, read through `temporal.rs`; crash-replay = a temporal READ of recorded intents vs what Lance holds — never a stored ledger. +- **Dead with it:** D-AHG-1; the "SLA gate" / "actionhandler queue" concepts (retired UNBUILT). The membrane admits/serializes/splits tasks with the transcode's own native semantics. +- **Guards:** `/v3-audit` check 7 = the elimination scan; guardrails STOP trigger 7 bans rebuilding the mechanism under any name ("retire"/"confirm"/"settle" + version map = the same thing). +- Prior `E-ACK-*` entries below are history of how it got here; live doctrine (mailbox-kanban-model, VISION §5, INTEGRATION-PLAN Addendum-14, M24 status, FUTURE-DESIGN sixth wave) now teaches the post-elimination world. + ## 2026-07-17 — E-KANBAN-STAYS-INTERIOR-MEMBRANE-IS-ACK-ONLY-1 — CORRECTION of E-TASKS-SOA-AT-THE-MEMBRANE-1: kanban does NOT move to the membrane; it is reasoning-interior ONLY. The membrane does ACK-serialization; the Tasks SoA holds admission + SLA + fan-out state (no sidecar) — the SLA-gate/actionhandler-queue tier, categorically NOT the Rubicon reasoning kanban **Status:** CORRECTION (operator, 2026-07-17: "Why did you move kanban to the outer membrane that's unacceptable"). Retracts TWO body clauses of E-TASKS-SOA-AT-THE-MEMBRANE-1 (below); the rest of that entry STANDS. Append-only: the original is not edited — this entry supersedes the retracted clauses. diff --git a/.claude/commands/v3-audit.md b/.claude/commands/v3-audit.md index e7ce256e..9377fdd5 100644 --- a/.claude/commands/v3-audit.md +++ b/.claude/commands/v3-audit.md @@ -43,16 +43,19 @@ every hit with file:line and a one-line disposition `mint_for`'s own V1 arm (`canonical_node.rs`), and legacy-compat *reads* (`family()`/`identity()` accessors are reads, not mints). -7. **Ack-paced advance scan** (E-ACK-VIOLATION-REGRADE-1 — the ack-gated - advance was a hard architecture violation; do not let it regrow): - pattern `ack` co-occurring with `advance_phase|try_advance|KanbanMove` - in the same file, plus `\.await` or `ractor::(call!|cast)` on any path - that also matches `advance_phase|KanbanColumn|cycle`. Sanctioned: - `batch_writer.rs` (durability bookkeeping + the SLA-gate doc), - callcenter/OGAR SLA-membrane surfaces, tests, TD-MESSAGE-RESIDUE - sites already ledgered. Any NEW hit that paces a reasoning cycle on - an awaited event is a violation (kanbanstep is the only reasoning - advance). +7. **Elimination scan — the ack mechanism does not exist** + (E-ACK-ELIMINATED-1, operator 2026-07-17; after E-ACK-VIOLATION-REGRADE-1 + + E-SOA-OWN-BOARD-NO-SIDECAR-1): patterns `ack_and_propose`, + `\bunacked\b`, `\backed\b`, `fn ack\b`, `\.ack\(`, `ack-gated`, + `actionhandler`, `SLA gate` in code or live doctrine — ANY hit is a + violation (there is no sanctioned home; durability evidence is the + row's own LanceVersion via temporal.rs). Also flag any NEW stored + confirmation ledger in a writer regardless of its name ("retire", + "confirm", "settle" + version map = the same mechanism), and any + `\.await`/`ractor::(call!|cast)` on a path that also matches + `advance_phase|KanbanColumn|cycle` (kanbanstep is the only advance). + Exempt: board-history entries (`E-ACK-*` names in EPIPHANIES / + PR_ARC / TECH_DEBT / plan addenda) — history is append-only. End with a verdict per the v3-mailbox-warden vocabulary (OWNED / BOOTSTRAP-OK / ORPHAN-WRITE / RESURRECTION) plus LAYOUT-CLEAN / diff --git a/.claude/plans/temporal-markov-and-style-classes-v1.md b/.claude/plans/temporal-markov-and-style-classes-v1.md index e668ba6e..6c8e086e 100644 --- a/.claude/plans/temporal-markov-and-style-classes-v1.md +++ b/.claude/plans/temporal-markov-and-style-classes-v1.md @@ -219,3 +219,14 @@ IS the signature transform" (different algebras: VSA bind+braid+bundle vs iterated integrals — braiding-by-position rhymes with order-encoding but is [S] until measured); ✗ "personality = the QualiaColumn"; ✗ treating the ~1.3× aggregate nulls as signal. Full text: `E-CHESS-ARC-TO-V3-TRANSFER-1`. + +--- + +## Correction 2026-07-17 — ACK ELIMINATED (E-ACK-ELIMINATED-1) + +The "ack-pump / `ack_and_propose` self-pumping loop" described above +(and the D-ORG-1 row) is DELETED from source per operator directive — +the mechanism twice produced tier-crossing designs. `batch_writer.rs` +is a pure intent recorder; durability evidence is the row's own +`LanceVersion` via `temporal.rs`; the kanban advance is kanbanstep +only. Read the above as history. diff --git a/.claude/v3/ENTROPY-MILESTONES.md b/.claude/v3/ENTROPY-MILESTONES.md index 2e8ed5e0..25439f21 100644 --- a/.claude/v3/ENTROPY-MILESTONES.md +++ b/.claude/v3/ENTROPY-MILESTONES.md @@ -46,7 +46,7 @@ | M21 | 3 dep-free hand-copies of the 16-byte NodeGuid LE encoder (q2 cpic, q2 fma/converge.rs, woa-rs erp/canon.rs — each "byte-identical", zero shared code) | one zero-dep `canon-node-bytes` extraction all three import | byte-parity test vs contract NodeGuid; grep local encoders = imports only | QUEUED (W5) | | M22 | 2 divergent q2 OSINT V3 bakes (crates/osint-bake canon-high 0x0700_0000 vs data/osint-v3 STALE pre-flip 0x1000_0700 dual-GUID scheme) | one canon-high bake against osint_classview.rs's 0x0700/0x0701 reservation | re-bake; grep pre-flip forms in q2 data/ = zero (or dual-alias-read only) | QUEUED (W5; latent until a reader assumes canon-high) | | M23 | 2 write-path doctrines coexisting (owner-stamped V3 writes vs smb-office-rs `LanceConnector::upsert` — the ONE live online consumer write, no stamp/classid/envelope) | all online consumer writes routed through the batch-writer cast | consumer-map §2 table shows zero ORPHAN-WRITE rows; warden green fleet-wide | QUEUED (W5 first live migration; medcare-soa writer BORN stamped as the prevention half) | -| M24 | 2 write-intent bookkeepers (batch-writer internal state vs kanban board AHEAD update) | ONE: the kanban board IS the write-ahead log — cast = move = intent record; ack = confirmation | kill-after-cast-before-ack replay test green; grep writer-internal intent queues = zero; cast carries descriptor never bytes (zero-copy sink through NodeRowPacket); stacked-casts-never-refused test (melden macht frei — Addendum-7; sink coalesces naturally via live-store reads) | QUEUED (shapes W1b from first line; operator ruling Addendum-6: eager drain + mutual masking via phase machine) | +| M24 | 2 write-intent bookkeepers (batch-writer internal state vs kanban board AHEAD update) | ONE: the kanban board IS the write-ahead log — cast = move = intent record; ack = confirmation | kill-after-cast-before-ack replay test green; grep writer-internal intent queues = zero; cast carries descriptor never bytes (zero-copy sink through NodeRowPacket); stacked-casts-never-refused test (melden macht frei — Addendum-7; sink coalesces naturally via live-store reads) | PARTIAL 2026-07-17 (E-ACK-ELIMINATED-1: the second bookkeeper's confirmation half is DELETED — batch_writer.rs is a pure intent recorder; "ack = confirmation" in this row is history — confirmation = the row's own LanceVersion via temporal read; remaining collapse = the intent board into SoA rows, gated on the W2a mint) | | M25 | 2 persistence surfaces for orchestration state (graph-flow SessionStorage backend vs mailbox kanban board) | ONE: KanbanSessionStorage — Session transitions ARE KanbanMoves via the W1b writer; replay = rebuild from board | kill-mid-graph replay test: session resumes identically from board-recorded moves; grep non-kanban SessionStorage impls in lance-graph = zero | SHIPPED v1 2026-07-02 (rs-graph-llm graph-flow `kanban` feature: KanbanSessionStorage, snapshot+move-log; kill-mid-graph replay test GREEN — no repeats/gaps, pinned Rubicon column sequence; grep gate holds: no non-kanban SessionStorage impl in lance-graph) | ## The meta-rule (why this ledger exists) diff --git a/.claude/v3/FUTURE-DESIGN.md b/.claude/v3/FUTURE-DESIGN.md index 32aa3c72..cb368e4f 100644 --- a/.claude/v3/FUTURE-DESIGN.md +++ b/.claude/v3/FUTURE-DESIGN.md @@ -11,6 +11,12 @@ --- +## 2026-07-17 (sixth wave) — ACK ELIMINATED everywhere (operator directive) + +| Ruling | One line | Wiring queue | +|---|---|---| +| E-ACK-ELIMINATED-1 | "remove the ack from everywhere, completely eliminate it" — the concept is expelled from code, doctrine, and vocabulary (it twice produced tier-crossing designs and became a lens distorting every session). SHIPPED: `batch_writer.rs` = pure intent recorder (`ack`/`ack_and_propose`/`acked`/`unacked`/`acked_version` deleted; zero production callers existed); probes + driver tests rewritten; durability evidence = the written row's own LanceVersion via temporal.rs; crash-replay = a temporal READ of intents vs Lance. D-AHG-1 is DEAD; the SLA-gate / actionhandler-queue concepts are retired UNBUILT; the membrane admits/serializes/splits tasks with the transcode's own native semantics (no confirmation abstraction of ours). /v3-audit check 7 = the elimination scan; guardrails trigger 7 bans rebuilding the mechanism under any name | none — the elimination is the wiring. Rows below referencing ack/SLA-gate/actionhandler are HISTORY, read through this row | + ## 2026-07-17 (fifth wave) — ack-violation regrade + the stream tier's economics named | Ruling | One line | Wiring queue | @@ -53,7 +59,8 @@ D-TSC-1; the 5-savant fan-out surfaced the three-divergent-tables finding. > E-ACK-VIOLATION-REGRADE-1 (fifth wave, top of this file): the > ack-trigger framing was a hard architecture violation, reversed — > kanbanstep is the only reasoning advance; acks are durability -> bookkeeping; SLA-gated waiting lives only at the callcenter/OGAR +> bookkeeping (and since 2026-07-17, E-ACK-ELIMINATED-1: no such +> bookkeeping exists at all); SLA-gated waiting lives only at the callcenter/OGAR > membrane. The row's fire-and-forget clause stands; its trigger > ranking does not. Append-only: the row is not edited. diff --git a/.claude/v3/INTEGRATION-PLAN.md b/.claude/v3/INTEGRATION-PLAN.md index 44dd238e..b9460a21 100644 --- a/.claude/v3/INTEGRATION-PLAN.md +++ b/.claude/v3/INTEGRATION-PLAN.md @@ -708,3 +708,21 @@ non-overlapping walker; `array_windows` is the overlapping GEMM sibling, deliberately unused); `simd_soa.rs::SoaBytes` remains an OPEN follow-up (natural carrier for vectorized sink sweeps + batch tables). Note: probe target/debug purged mid-round (disk full at 100%); gates re-run green. + +### Addendum-14 2026-07-17 — ACK ELIMINATED (operator directive; E-ACK-ELIMINATED-1) + +"Remove the ack from everywhere, completely eliminate it." Shipped same +day: `batch_writer.rs` is a pure intent recorder (`ack` / +`ack_and_propose` / `acked` / `unacked` / `acked_version` deleted — zero +production callers existed); W1e probes + driver cast-pairing tests +rewritten to pin intent recording + delegation caching only. Durability +evidence is the written row's own `LanceVersion` in Lance, read through +`temporal.rs`; crash-replay is a temporal READ comparing recorded +intents against what Lance holds — never a stored ledger. D-AHG-1 is +dead; the SLA-gate / actionhandler-queue concepts are retired unbuilt; +the membrane admits/serializes/splits incoming tasks with the +transcode's own native semantics. Every ack/unacked reference in the +addenda above (Addendum-1 W1e row, Addendum-6 §3, Addendum-7, Addendum-8 +§3) is HISTORY read through this addendum. Guardrails STOP trigger 7 + +`/v3-audit` check 7 enforce that the mechanism is not rebuilt under any +name. diff --git a/.claude/v3/VISION.md b/.claude/v3/VISION.md index 65b1c2ee..356c6e1c 100644 --- a/.claude/v3/VISION.md +++ b/.claude/v3/VISION.md @@ -142,16 +142,17 @@ The kanban is not a task board — it is **volition, typed** Σ-commit (the Rubicon crossing, Libet-anchored — intention forms before the conscious act); Planning → Prune is the pre-Rubicon veto ("free won't"); Evaluation's 3-way is the postactional reckoning; Plan → Planning -re-deliberates carrying the witness. The cast records intent AHEAD of the ack -— crossing at intent formation: Rubicon-conformant **by construction of the -mapping** [RULING] (the −550 ms is Libet's literature value stamped onto the -transition as the budget anchor, not a quantity measured on this system). +re-deliberates carrying the witness. The cast records intent at intent +formation, ahead of any storage write completing: Rubicon-conformant **by +construction of the mapping** [RULING] (the −550 ms is Libet's literature +value stamped onto the transition as the budget anchor, not a quantity +measured on this system). And beneath it, the prime invariant [RULING E-NOBODY-WAITS-1]: **nobody waits for anything or any scheduling.** Writes are fire-and-forget ("melden macht -frei"); the Lance ack itself proposes the next move (`ack_and_propose` — -orchestration is self-updating, postactional evidence of cycle N seeding the -deliberation of cycle N+1); updates reprioritize, never gate; absorbing views +frei"); durability evidence is the written row's own LanceVersion, read +through temporal.rs — no confirmation bookkeeping exists anywhere +[RULING E-ACK-ELIMINATED-1, 2026-07-17]; updates reprioritize, never gate; absorbing views rest the loop, never deadlock it; ractor exists solely as the compile-time ownership guarantee — `&mut` IS the serialization, no messages, no actors, no scheduler anyone blocks on. Any message path found in the tree is redundancy diff --git a/.claude/v3/knowledge/mailbox-kanban-model.md b/.claude/v3/knowledge/mailbox-kanban-model.md index 49148b30..16eeaa0f 100644 --- a/.claude/v3/knowledge/mailbox-kanban-model.md +++ b/.claude/v3/knowledge/mailbox-kanban-model.md @@ -29,7 +29,7 @@ proposes; the owner disposes. | **Arm #2 — symbiont** | `crates/symbiont` (`kanban_loop.rs` = POC) | SurrealDB-on-kv-lance executor: kanban updates as KV transactions on the same Lance substrate. Gated on the AdaWorldAPI surrealdb fork `kv-lance` feature. | | **Structural owner** | `lance-graph-supervisor/kanban_actor.rs` | ractor actor per mailbox. **ractor is SOLELY the compile-time ownership guarantee** (name the role — the attestation must stay authoritative to the compiler; operator, 2026-07-17) — it spawns and proves single-ownership via move semantics (`KanbanActor` with `type State = O`; the owner MOVES in at `pre_start`); it is NOT a data-plane bus and **not for messaging — it is slow** (operator, 2026-07-02). **It MAY serve as a HELPER where it makes sense** — spawn, supervision, occasional control RPC like the serialized Advance/MulAdvance (the codex #578 atomicity mechanism) — always keeping the speed difference in mind: nothing on the hot path may wait on ractor latency; hot-path dispatch belongs to the D-V3-W2e-probed ExecTarget. | -## The trigger: kanbanstep, never an ack (operator-ruled, 2026-07-10/17) +## The trigger: kanbanstep. There is no ack — the concept is ELIMINATED (operator, 2026-07-10/17) **The canonical kanban advance is the in-stream synchronous step ("kanbanstep")**: the writer/stream fires `on_version → @@ -42,18 +42,24 @@ StreamDto → BusDto → PerturbationDto; the SPO 2³ rung ladder amortizes ONE SPO cache load over ≤8 back-to-back L1-resident cycles emitting `CausalEdge64` NARS candidates — 40 ns-class operations. -**An ack NEVER paces a cycle.** A durability ack is 10–400 µs away — -pacing a 40 ns thinking op on it stalls 250×–10,000× and destroys the -ladder amortization (and the Morton-tile cascade streaming with it). -The ack's only job is durability bookkeeping (`unacked()` crash-replay). -The ONLY tier where waiting on an ack is a feature is the **external -ontology membrane**: lance-graph-callcenter's Supabase-realtime -transcode shape (tickets, business-logic SLA) + OGAR actionhandler -queues. Tier test before any advance-path design: *SLA/audit obligation -(ticket) → SLA gate; cycle budget (thought) → kanbanstep stream.* Never -cross-route. History + severity: `E-KANBANSTEP-IS-THE-TRIGGER-1`, -`E-ACK-VIOLATION-REGRADE-1` (the ack-gated advance was a hard -architecture violation, operator-reversed — do not rebuild it). +**The ack concept does not exist in this architecture** (operator +directive 2026-07-17, `E-ACK-ELIMINATED-1` — expelled from code, +doctrine, and vocabulary after it twice produced tier-crossing designs). +There is no confirmation bookkeeping anywhere: **durability evidence is +the written row's own `LanceVersion` in Lance**, read through +`temporal.rs` (`QueryReference::at` + deinterlace); crash-replay is a +temporal READ comparing recorded intents against what Lance holds. +Nothing advances on a completion event: not a thought (a stall of +250×–10,000× on a 40 ns op, and the death of the ladder amortization), +and not anything else — the batch writer records intent and nothing +more. The membrane (lance-graph-callcenter) admits, serializes, and +splits incoming tasks into reasoning SoAs using the transcode's own +native semantics (Supabase-realtime); we build no confirmation +abstraction for it. Do not reintroduce the mechanism under any name — +"retire", "confirm", "settle" wrapping a stored completion ledger is +the same thing wearing a new word. History: `E-KANBANSTEP-IS-THE-TRIGGER-1`, +`E-ACK-VIOLATION-REGRADE-1`, `E-SOA-OWN-BOARD-NO-SIDECAR-1`, +`E-ACK-ELIMINATED-1`. ## The ahead-firing batch writer diff --git a/.claude/v3/knowledge/sonnet-worker-guardrails.md b/.claude/v3/knowledge/sonnet-worker-guardrails.md index 645a2762..3eddc790 100644 --- a/.claude/v3/knowledge/sonnet-worker-guardrails.md +++ b/.claude/v3/knowledge/sonnet-worker-guardrails.md @@ -94,7 +94,7 @@ exactly the row below, never a neighbor. | F12 | Test literals that only work in one classid order / one layout version (synthetic 0xAB12-style values) | test values come from the §2-sanctioned composers + realistic allocations; never hand-rolled hex composites | | F13 | Worker "fixes" a failing unrelated test to get green | out of scope (§1 rule 1): report the failure, touch nothing | | F14 | German PII labels or model identifiers in committed artifacts | never emit either in any file/commit (workspace-wide rule); chat-only | -| F15 | A cycle/phase advance paced on an ack, message, or awaited event (the ack-gated advance — a hard architecture violation, operator-reversed; E-ACK-VIOLATION-REGRADE-1) | kanbanstep is the ONLY reasoning advance (inline `on_version → try_advance_phase(&mut)`); acks = durability bookkeeping; SLA-gated waiting exists ONLY at the callcenter/OGAR membrane; ractor = compile-time ownership guarantee, never messaging (10⁴–10⁷× tax). A worker asked to await anything before an advance = STOP+report | +| F15 | A cycle/phase advance paced on a completion/confirmation event, message, or awaited anything — or a stored confirmation ledger added to a writer (the eliminated ack mechanism; E-ACK-VIOLATION-REGRADE-1 → E-ACK-ELIMINATED-1) | kanbanstep is the ONLY advance (inline `on_version → try_advance_phase(&mut)`); the ack concept DOES NOT EXIST — durability evidence is the row's own LanceVersion via temporal.rs; ractor = compile-time ownership guarantee, never messaging (10⁴–10⁷× tax). A worker asked to await anything before an advance, or to add confirmation bookkeeping under ANY name = STOP+report | ## §4 — Sanctioned command palette (copy these, don't improvise) @@ -124,10 +124,12 @@ appears, because each requires accumulation-tier judgment: 5. The change would add/modify a write path's ownership routing (needs v3-mailbox-warden). 6. Anything RBAC, PII-adjacent, or externally visible. -7. The change would make ANY cycle/phase advance wait on an ack, a - message, a `ractor::call!`/`cast`, or any awaited event (F15 — the - tier test is the orchestrator's call, not the worker's; the only - sanctioned waiting tier is the callcenter/OGAR SLA membrane). +7. The change would make ANY cycle/phase advance wait on a completion + or confirmation event, a message, a `ractor::call!`/`cast`, or any + awaited event — or would add ANY stored confirmation ledger to a + writer (the eliminated mechanism, E-ACK-ELIMINATED-1; durability + evidence is the row's own LanceVersion read via temporal.rs, and no + equivalent may be rebuilt under any name). Cross-ref: `.claude/knowledge/autoattended-multiagent-pattern.md` (the 4-savant wave pattern these rules slot into), `v3-substrate-primer.md` diff --git a/crates/cognitive-shader-driver/src/mailbox_soa.rs b/crates/cognitive-shader-driver/src/mailbox_soa.rs index 8e78408a..5b6d85c6 100644 --- a/crates/cognitive-shader-driver/src/mailbox_soa.rs +++ b/crates/cognitive-shader-driver/src/mailbox_soa.rs @@ -716,9 +716,9 @@ impl MailboxSoA { /// Payload-generic like the writer itself (DTO purity: the writer never /// inspects `P`; `P` carries NO ownership fields — `BusDto` is the /// canonical rung-B payload in `with-engine` builds). The intent is - /// visible on the board AHEAD of any storage ack; deltas stay in this - /// SoA's backing store and the sink reads them at flush (zero-copy, - /// Addendum-6). + /// visible immediately — AHEAD of any storage write completing; deltas + /// stay in this SoA's backing store and the sink reads them at flush + /// (zero-copy, Addendum-6). pub fn cast_on_behalf

( &self, writer: &mut lance_graph_planner::batch_writer::BatchWriter

, @@ -1628,18 +1628,15 @@ mod w4a_cast_pairing_tests { Some(77), "on_behalf must be the carrier's mailbox_id, read from &self" ); - // AHEAD semantics: the intent is on the board before any ack. - assert_eq!(writer.unacked(), vec![cast]); - writer.ack(cast, 41); - assert!(writer.unacked().is_empty(), "acked cast leaves the WAL"); - assert_eq!(writer.acked_version(cast), Some(41)); + // AHEAD semantics: the intent is recorded immediately. + assert_eq!(writer.casts(), vec![cast]); } #[test] fn stacked_casts_never_refused_melden_macht_frei() { // Addendum-7: casting is reporting — a second cast on the same - // mailbox while the first is unacked is a stacked WAL entry with its - // own id, never a refusal. + // mailbox is a stacked intent record with its own id, never a + // refusal. let mb: MailboxSoA<8> = MailboxSoA::new(9, 1, 1.0); let mut writer: BatchWriter = BatchWriter::new(); let d = DirtyRange { @@ -1650,7 +1647,7 @@ mod w4a_cast_pairing_tests { let c1 = mb.cast_on_behalf(&mut writer, vec![], d); let c2 = mb.cast_on_behalf(&mut writer, vec![], d); assert_ne!(c1, c2); - assert_eq!(writer.unacked(), vec![c1, c2], "stacked, in cast order"); + assert_eq!(writer.casts(), vec![c1, c2], "stacked, in cast order"); assert_eq!(writer.on_behalf_of(c2), Some(9)); } @@ -1676,6 +1673,6 @@ mod w4a_cast_pairing_tests { let cast = mb.cast_on_behalf(&mut writer, vec![], bus); assert_eq!(writer.on_behalf_of(cast), Some(1024)); - assert_eq!(writer.unacked(), vec![cast], "intent AHEAD of ack"); + assert_eq!(writer.casts(), vec![cast], "intent recorded AHEAD"); } } diff --git a/crates/lance-graph-planner/src/batch_writer.rs b/crates/lance-graph-planner/src/batch_writer.rs index fc3cbd63..26134704 100644 --- a/crates/lance-graph-planner/src/batch_writer.rs +++ b/crates/lance-graph-planner/src/batch_writer.rs @@ -1,10 +1,15 @@ -//! W1b ahead-firing batch writer — the kanban board IS the write-ahead log (M24). +//! W1b ahead-firing batch writer — intent recording, nothing else. //! -//! `cast()` records intent moves AHEAD of any storage ack; `ack()` confirms -//! at the `LanceVersion` the sink assigned (the CastId↔LanceVersion join -//! wiring the WAL into the temporal classifier; see `crate::temporal`); -//! `unacked()` is the crash-replay surface. Payload-generic: the writer never -//! inspects `P` (DTO purity — ownership rides the cast pairing, never the DTO). +//! `cast()` records intent moves AHEAD of any storage write completing. +//! Payload-generic: the writer never inspects `P` (DTO purity — ownership +//! rides the cast pairing, never the DTO). +//! +//! **There is no confirmation bookkeeping here — by ruling (operator, +//! 2026-07-17, E-ACK-ELIMINATED-1).** Durability evidence is the written +//! row's own `LanceVersion` in Lance, read through `crate::temporal` +//! (`QueryReference::at` + deinterlace). Crash-replay is a temporal READ — +//! compare recorded intents against what Lance holds — never a stored +//! ledger in this struct. Do not add a confirmation method under any name. //! //! **Zero-copy sink (operator ruling, plan Addendum-6):** `P` is a DESCRIPTOR //! — (mailbox, dirty row-range, cycle) — never owned delta bytes. Deltas stay @@ -12,14 +17,17 @@ //! `NodeRowPacket::as_le_bytes` at flush time. The sink drains EAGERLY //! (ASAP on cast, background), and the write masks the thinking and vice //! versa: the thinker reports (casts) and moves on — "melden macht frei" — -//! it is NEVER refused because earlier casts are unacked. Stacked casts on -//! the same row are stacked WAL entries; the sink reads the LIVE store at -//! flush, so one physical flush coalesces all earlier intents for a row -//! (last-state-wins; the move log keeps the full ordered history). +//! it is NEVER refused. Stacked casts on the same row are stacked intent +//! records; the sink reads the LIVE store at flush, so one physical flush +//! coalesces all earlier intents for a row (last-state-wins; the move log +//! keeps the full ordered history). +//! +//! The kanban advance is the in-stream synchronous kanbanstep +//! (`VersionScheduler::on_version → try_advance_phase(&mut)`), fired inline +//! by whoever already holds the version — never from this module. //! //! Uses the REAL shipped kanban contract types //! ([`lance_graph_contract::kanban::KanbanMove`], -//! [`lance_graph_contract::kanban::KanbanColumn`], //! [`lance_graph_contract::collapse_gate::MailboxId`]) — this module does not //! mint a parallel `KanbanMove`; see the D-MBX-A6 Outcome adapter context in //! `crate::strategy::style_strategy`. @@ -27,38 +35,27 @@ use std::collections::{BTreeMap, HashMap}; use lance_graph_contract::collapse_gate::MailboxId; -use lance_graph_contract::kanban::{ExecTarget, KanbanMove}; -use lance_graph_contract::scheduler::{DatasetVersion, VersionScheduler}; -use lance_graph_contract::soa_view::MailboxSoaView; - -use crate::temporal::LanceVersion; +use lance_graph_contract::kanban::KanbanMove; -/// Identity of one `cast()` — a write-ahead intent record on the kanban board. +/// Identity of one `cast()` — a write-ahead intent record. /// /// `next_id` is monotonically increasing, so `CastId`'s derived `Ord` gives -/// insertion order — this is what lets `board`/`acked` use `BTreeMap` and -/// have `unacked()` iterate in cast order for free. +/// insertion order — this is what lets `board` use `BTreeMap` and iterate +/// in cast order for free. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct CastId(pub u64); -/// Ahead-firing batch writer: intent (`cast`) is visible on the board before -/// any ack; `unacked()` is the M24 crash-replay surface; `resolve_owner` is -/// the W1c delegation cache (resolve-once, cache-hit thereafter). +/// Ahead-firing batch writer: intent (`cast`) is visible immediately; +/// `resolve_owner` is the W1c delegation cache (resolve-once, cache-hit +/// thereafter). Confirmation state does not exist here (module doc). pub struct BatchWriter

{ /// Monotonic id generator for the next cast. next_id: u64, - /// Board: intent moves recorded per cast, keyed by `CastId`, alongside the - /// mailbox the cast was recorded on behalf of. Visible between `cast()` - /// and `ack()` (and beyond, for crash-replay via `unacked()`). - /// `BTreeMap` (not `HashMap`) so iteration is in ascending `CastId` order - /// — i.e. cast (insertion) order, matching `unacked()`'s ordering contract. + /// Intent moves recorded per cast, keyed by `CastId`, alongside the + /// mailbox the cast was recorded on behalf of. `BTreeMap` (not + /// `HashMap`) so iteration is in ascending `CastId` order — i.e. cast + /// (insertion) order. board: BTreeMap)>, - /// Casts that have been confirmed (acked), mapped to the `LanceVersion` - /// the sink assigned when it flushed — the CastId↔LanceVersion join - /// wiring the WAL into the temporal classifier (see `crate::temporal`). - /// A cast present in `board` but absent from `acked` is the crash-replay - /// surface (`unacked()`). - acked: BTreeMap, /// W1c delegation cache: `on_behalf` mailbox -> resolved owner mailbox. delegation_cache: HashMap, /// Payloads recorded per cast (payload-generic; the writer never inspects `P`). @@ -77,18 +74,17 @@ impl

BatchWriter

{ Self { next_id: 0, board: BTreeMap::new(), - acked: BTreeMap::new(), delegation_cache: HashMap::new(), pending_payloads: Vec::new(), } } - /// AHEAD: records the intent (moves visible on the board) BEFORE any ack. - /// Returns the cast id. + /// AHEAD: records the intent (moves visible immediately). Returns the + /// cast id. /// /// "Melden macht frei" (plan Addendum-7): casting is REPORTING, never - /// refused because earlier casts on the same mailbox are still unacked — - /// stacked casts are stacked WAL entries, each with its own `CastId`. + /// refused — stacked casts are stacked intent records, each with its + /// own `CastId`. pub fn cast(&mut self, on_behalf: MailboxId, moves: Vec, payload: P) -> CastId { let cast = CastId(self.next_id); self.next_id += 1; @@ -97,110 +93,21 @@ impl

BatchWriter

{ cast } - /// Confirmation — marks the cast acked at the Lance version the sink - /// assigned (the CastId↔LanceVersion join wiring the WAL into the - /// temporal classifier; see planner `temporal.rs`). - pub fn ack(&mut self, cast: CastId, version: LanceVersion) { - self.acked.insert(cast, version); - } - - /// **The SLA gate (operator rulings, 2026-07-10/11): - /// an ack-gated advance for SLA/audit-bearing work.** Records the ack, - /// then lowers the assigned `LanceVersion` to the next legal - /// [`KanbanMove`] proposal via the provided [`VersionScheduler`] over - /// `view`. - /// - /// **Tier note (E-ACK-HARD-GATE-VS-KANBANSTEP-STREAM-1; name refined to - /// "SLA gate" 2026-07-11):** this is the TICKET tier — work items that - /// want an explicit SLA and an auditable goalstate advance only on - /// confirmed durability, and the WAL board + `acked` map is their audit - /// trail. The STREAM/reasoning tier (the kanbanstep) never routes through - /// here: a writer that already holds the version it committed fires - /// `on_version → try_advance_phase(&mut)` inline — thinking never waits on - /// an ack. This SLA-gate mechanism is preserved (not retired) and is - /// repurposed on the OGAR consumer side as the **actionhandler queue** — - /// where action handlers (tickets, e-mails, …) wait for their durability - /// ack before advancing. - /// - /// The loop this closes — the StreamDto "can't stop thinking" lineage: - /// - /// ```text - /// think → cast (fire-and-forget: the thinker is freed at once) - /// → sink drains async → Lance ack - /// → THIS method: ack ⇒ next-move proposal (version tick) - /// → owner disposes it → the board reprioritizes the live set - /// → thinking, which never stopped, sees the new priorities - /// ``` - /// - /// The cognitive-shader-driver NEVER waits on scheduling or writing: - /// `cast` returns immediately ("melden macht frei"), the write is async, - /// and the board update is a *consequence of the write completing*, not - /// something the thinker schedules. Orchestration is self-updating — - /// every completed write releases the next kanban update through the - /// gate. - /// - /// Propose-don't-dispose is preserved: the writer only PROPOSES; the - /// owner (`MailboxSoaOwner` / the KanbanActor) applies the move — the - /// sole-mutator proof is untouched. `None` = the view is absorbing or - /// policy-filtered (the loop rests; a no-op tick is suppressed, never an - /// error). A `Planning → CognitiveWork` proposal carries the Libet - /// anchor, so `elevation::cycle::CycleBudget::from_move` opens the next - /// cycle's window from this same proposal (M12). - /// - /// **At-least-once delivery (codex P2 on #674):** only the FIRST - /// unacked→acked transition releases a proposal. A duplicate ack (async - /// sink retry, version-watcher replaying the same `CastId`) returns - /// `None` WITHOUT overwriting the first recorded version — first ack - /// wins, keeping the CastId↔LanceVersion temporal join stable. A stray - /// `CastId` (never cast on this board) also returns `None` and records - /// nothing. The low-level [`ack`](Self::ack) stays the unconditional - /// recording primitive; dedup lives at the gate, because the gate is - /// what would otherwise multiply lifecycle moves. - pub fn ack_and_propose( - &mut self, - cast: CastId, - version: LanceVersion, - scheduler: &S, - view: &V, - exec: ExecTarget, - ) -> Option - where - S: VersionScheduler, - V: MailboxSoaView, - { - if !self.board.contains_key(&cast) || self.acked.contains_key(&cast) { - return None; - } - self.ack(cast, version); - scheduler.on_version(view, DatasetVersion(version), exec) - } - - /// The `LanceVersion` a cast was acked at, if it has been acked. - #[must_use] - pub fn acked_version(&self, cast: CastId) -> Option { - self.acked.get(&cast).copied() - } - - /// Crash-replay surface (M24): casts recorded but not yet acked, in - /// ascending `CastId` (cast) order. + /// Recorded casts, in ascending `CastId` (cast) order. #[must_use] - pub fn unacked(&self) -> Vec { - self.board - .keys() - .filter(|cast| !self.acked.contains_key(cast)) - .copied() - .collect() + pub fn casts(&self) -> Vec { + self.board.keys().copied().collect() } - /// Board read: intent moves recorded for a cast (visible between cast and ack). + /// Intent moves recorded for a cast. #[must_use] pub fn intent_moves(&self, cast: CastId) -> Option<&[KanbanMove]> { self.board.get(&cast).map(|(_, moves)| moves.as_slice()) } - /// Board read: the mailbox a cast was recorded ON BEHALF OF — the - /// delegation-audit surface (W4a cast pairing: consumers pair the owner - /// at cast; wardens verify the pairing here, never on the DTO). + /// The mailbox a cast was recorded ON BEHALF OF — the delegation-audit + /// surface (W4a cast pairing: consumers pair the owner at cast; wardens + /// verify the pairing here, never on the DTO). #[must_use] pub fn on_behalf_of(&self, cast: CastId) -> Option { self.board.get(&cast).map(|(on_behalf, _)| *on_behalf) @@ -224,154 +131,37 @@ impl

BatchWriter

{ #[cfg(test)] mod tests { use super::*; - use lance_graph_contract::kanban::KanbanColumn; - use lance_graph_contract::scheduler::NextPhaseScheduler; - - /// Minimal view at a given phase (mirrors elevation::cycle's PhaseView). - struct PhaseView(KanbanColumn); - impl MailboxSoaView for PhaseView { - fn mailbox_id(&self) -> MailboxId { - 7 - } - fn n_rows(&self) -> usize { - 0 - } - fn w_slot(&self) -> u8 { - 7 - } - fn current_cycle(&self) -> u32 { - 0 - } - fn phase(&self) -> KanbanColumn { - self.0 - } - fn energy(&self) -> &[f32] { - &[] - } - fn edges_raw(&self) -> &[u64] { - &[] - } - fn meta_raw(&self) -> &[u32] { - &[] - } - fn entity_type(&self) -> &[u16] { - &[] - } - } #[test] - fn ack_is_the_next_kanban_trigger_and_the_thinker_never_waited() { + fn casting_is_fire_and_forget_and_stacks_freely() { let mut w: BatchWriter = BatchWriter::new(); - // Fire-and-forget: the thinker casts and is freed at once — no ack - // exists yet, nothing to wait on, and further casts stack freely. + // The thinker casts and is freed at once — nothing to wait on, + // and further casts stack freely as independent intent records. let c1 = w.cast(7, vec![], 0); let c2 = w.cast(7, vec![], 1); - assert_eq!(w.unacked(), vec![c1, c2], "thinking never blocked on I/O"); - - // The async sink completes c1: the ack ITSELF proposes the next - // kanban update (Planning → CognitiveWork), carrying the Libet - // anchor — orchestration self-updates off write completions. - let mv = w - .ack_and_propose( - c1, - 41, - &NextPhaseScheduler, - &PhaseView(KanbanColumn::Planning), - ExecTarget::Native, - ) - .expect("write completion triggers the next board update"); - assert_eq!(mv.from, KanbanColumn::Planning); - assert_eq!(mv.to, KanbanColumn::CognitiveWork); - assert!(mv.libet_offset_us < 0, "Σ-commit opens the next window"); - assert_eq!(w.acked_version(c1), Some(41), "the ack was recorded"); - assert_eq!(w.unacked(), vec![c2], "c2 still in flight, still no wait"); + let c3 = w.cast(7, vec![], 2); + assert_eq!(w.casts(), vec![c1, c2, c3], "cast (insertion) order"); + assert_eq!(w.on_behalf_of(c2), Some(7)); } #[test] - fn ack_gated_chain_walks_the_arc_off_write_completions_alone() { - // Three async write completions, each triggering the next update: - // the board walks Planning → CognitiveWork → Evaluation → Commit - // with NO scheduler call from the thinker's side. + fn intent_moves_stay_readable_for_replay_comparison() { + // Crash-replay is a temporal READ elsewhere; this struct's only + // job is that recorded intents remain readable to compare against + // what Lance holds. let mut w: BatchWriter = BatchWriter::new(); - let mut phase = KanbanColumn::Planning; - for (i, expected) in [ - KanbanColumn::CognitiveWork, - KanbanColumn::Evaluation, - KanbanColumn::Commit, - ] - .into_iter() - .enumerate() - { - let cast = w.cast(7, vec![], i as u8); - let mv = w - .ack_and_propose( - cast, - i as u64 + 1, - &NextPhaseScheduler, - &PhaseView(phase), - ExecTarget::Native, - ) - .expect("non-absorbing view advances"); - assert_eq!(mv.to, expected); - phase = mv.to; // the owner disposed the proposal; next view reflects it - } - - // At the absorbing column the gate rests: ack recorded, no proposal, - // no error — the no-op tick is suppressed, never a deadlock. - let last = w.cast(7, vec![], 9); - let rest = w.ack_and_propose( - last, - 99, - &NextPhaseScheduler, - &PhaseView(KanbanColumn::Commit), - ExecTarget::Native, - ); - assert!(rest.is_none(), "absorbing view: the loop rests"); - assert_eq!(w.acked_version(last), Some(99)); + let cast = w.cast(7, vec![], 0); + assert!(w.intent_moves(cast).is_some(), "intent remains readable"); + assert_eq!(w.intent_moves(CastId(9999)), None, "stray id: nothing"); } - /// codex P2 on #674: at-least-once sink delivery must not multiply - /// lifecycle moves — only the FIRST unacked→acked transition proposes; - /// duplicate acks keep the first version; stray casts record nothing. #[test] - fn duplicate_and_stray_acks_never_release_twice() { + fn delegation_cache_resolves_once_then_hits() { let mut w: BatchWriter = BatchWriter::new(); - let c1 = w.cast(7, vec![], 0); - - // First transition: proposes. - let first = w.ack_and_propose( - c1, - 41, - &NextPhaseScheduler, - &PhaseView(KanbanColumn::Planning), - ExecTarget::Native, - ); - assert!(first.is_some(), "first unacked->acked transition releases"); - - // Sink retry / watcher replay of the same CastId: NO second - // proposal, and the first recorded version wins (the temporal - // join stays stable even if the retry carries a later version). - let dup = w.ack_and_propose( - c1, - 42, - &NextPhaseScheduler, - &PhaseView(KanbanColumn::Planning), - ExecTarget::Native, - ); - assert!(dup.is_none(), "duplicate ack must not release a second move"); - assert_eq!(w.acked_version(c1), Some(41), "first ack wins"); - - // Stray CastId (never cast on this board): no proposal, no record. - let stray = CastId(9999); - let ghost = w.ack_and_propose( - stray, - 77, - &NextPhaseScheduler, - &PhaseView(KanbanColumn::Planning), - ExecTarget::Native, - ); - assert!(ghost.is_none(), "stray cast id is ignored"); - assert_eq!(w.acked_version(stray), None, "nothing recorded for it"); + let (owner, hit) = w.resolve_owner(3, |_| 11); + assert_eq!((owner, hit), (11, false), "first resolve is a miss"); + let (owner, hit) = w.resolve_owner(3, |_| unreachable!("cached")); + assert_eq!((owner, hit), (11, true), "second resolve is a cache hit"); } } diff --git a/crates/lance-graph-planner/tests/w1_probes.rs b/crates/lance-graph-planner/tests/w1_probes.rs index 6a67e527..9f892373 100644 --- a/crates/lance-graph-planner/tests/w1_probes.rs +++ b/crates/lance-graph-planner/tests/w1_probes.rs @@ -1,8 +1,13 @@ -//! D-V3-W1e probe-first: four probes for the W1b ahead-firing batch writer + +//! D-V3-W1e probe-first: probes for the W1b ahead-firing batch writer + //! W1c delegation cache, pinned against //! `lance_graph_planner::batch_writer::BatchWriter`. //! -//! Live (W1b implementation landed) — all four run and pass. +//! There is no confirmation bookkeeping in the writer (operator ruling +//! 2026-07-17, E-ACK-ELIMINATED-1): durability evidence is the written +//! row's own `LanceVersion` in Lance, read through `temporal.rs`; replay +//! is a temporal READ comparing recorded intents against what Lance holds. +//! These probes therefore pin exactly two things: intent recording and +//! delegation caching. //! //! Uses the REAL shipped kanban contract types //! (`lance_graph_contract::kanban::{KanbanColumn, KanbanMove, ExecTarget}`, @@ -25,8 +30,8 @@ fn make_move(mailbox: u32, from: KanbanColumn, to: KanbanColumn, witness: u32) - } } -/// Probe 1 (W1b): cast() makes intent moves visible on the board AHEAD of any -/// ack; ack() then removes the cast from unacked(). +/// Probe 1 (W1b): cast() makes intent moves visible immediately — AHEAD of +/// any storage write completing. #[test] fn probe_ahead_update_ordering() { let mut writer: BatchWriter<()> = BatchWriter::new(); @@ -39,20 +44,15 @@ fn probe_ahead_update_ordering() { let cast = writer.cast(7, moves.clone(), ()); - // AHEAD: intent is visible on the board BEFORE any ack. + // AHEAD: intent is visible immediately. assert_eq!(writer.intent_moves(cast), Some(moves.as_slice())); - - writer.ack(cast, 1); - - // After ack, the cast is no longer in the unacked (crash-replay) surface. - assert!(!writer.unacked().contains(&cast)); - - // The CastId<->LanceVersion join: the ack recorded the assigned version. - assert_eq!(writer.acked_version(cast), Some(1)); + assert_eq!(writer.casts(), vec![cast]); } -/// Probe 2 (M24): a cast that is never acked stays on the crash-replay -/// surface (`unacked()`), and its intent moves remain replayable. +/// Probe 2 (M24): recorded intents stay readable after a simulated crash — +/// replay compares them against what Lance holds (a temporal READ, done +/// elsewhere); the writer's only obligation is that the intent record +/// survives and stays readable. #[test] fn probe_kill_after_cast_replay() { let mut writer: BatchWriter<()> = BatchWriter::new(); @@ -65,14 +65,12 @@ fn probe_kill_after_cast_replay() { )]; let cast = writer.cast(11, moves.clone(), ()); - // Deliberately no ack() — simulates a crash between cast and ack. - - let unacked = writer.unacked(); - assert_eq!(unacked, vec![cast]); + // Simulates a crash right after cast: nothing else happens. + assert_eq!(writer.casts(), vec![cast]); let replayed = writer .intent_moves(cast) - .expect("unacked cast must still have replayable intent moves"); + .expect("cast must still have replayable intent moves"); assert!(!replayed.is_empty()); assert_eq!(replayed, moves.as_slice()); } @@ -112,39 +110,30 @@ fn probe_delegation_miss_then_hit() { assert_eq!(owner_first, owner_second); } -/// Probe 4 (M24 / operator ruling "melden macht frei", plan Addendum-7): +/// Probe 4 (operator ruling "melden macht frei", plan Addendum-7): /// casting is REPORTING, and reporting frees the thinker — the writer NEVER -/// refuses a cast because earlier casts on the same mailbox are still -/// unacked. Three stacked casts are three WAL entries: distinct ids, full -/// ordered history retained, acks retire independently. (Physical sink +/// refuses a cast. Three stacked casts on the same mailbox are three intent +/// records: distinct ids, full ordered history retained. (Physical sink /// coalescing — one flush of the live store satisfying all earlier intents -/// for a row — is sink-side behavior, exercised in the W1b implementation -/// tests, not at this API surface.) +/// for a row — is sink-side behavior, not at this API surface.) #[test] fn probe_stacked_casts_never_refused() { let mut writer: BatchWriter<()> = BatchWriter::new(); let mv = |w| make_move(7, KanbanColumn::Planning, KanbanColumn::CognitiveWork, w); - // Three stacked writes on the SAME mailbox, zero acks in between. + // Three stacked writes on the SAME mailbox, nothing in between. let c1 = writer.cast(7, vec![mv(0)], ()); let c2 = writer.cast(7, vec![mv(1)], ()); let c3 = writer.cast(7, vec![mv(2)], ()); - // No refusal: three distinct WAL entries, cast order preserved. + // No refusal: three distinct intent records, cast order preserved. assert_ne!(c1, c2); assert_ne!(c2, c3); - assert_eq!(writer.unacked(), vec![c1, c2, c3]); + assert_eq!(writer.casts(), vec![c1, c2, c3]); // Every stacked intent stays independently replayable. assert!(writer.intent_moves(c1).is_some()); assert!(writer.intent_moves(c2).is_some()); assert!(writer.intent_moves(c3).is_some()); - - // Acks retire independently and in any order. - writer.ack(c2, 1); - assert_eq!(writer.unacked(), vec![c1, c3]); - writer.ack(c1, 2); - writer.ack(c3, 3); - assert!(writer.unacked().is_empty()); } From d4f12c6021ba17e10a16569533bd052855733c7c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 07:42:21 +0000 Subject: [PATCH 8/8] review: address codex + CodeRabbit findings on the ack-elimination PR (valid subset) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed (all confirmed against current code): - /v3-audit check-7: regex typo \backed\b -> \bbacked\b; the confirmation-ledger check is now STRUCTURAL (a persisted id->version writer field, by shape) not a keyword list; the await check flags an awaited call!/response a cycle-advance depends on, NOT a bare fire-and-forget cast; and v3-audit.md exempts its own rule block from the scan (was self-flagging by construction). - guardrails F15 + STOP trigger 7: distinguish the sanctioned fire-and-forget BatchWriter::cast (owner-stamped intent recording, never waits) from an awaited response — only the latter is forbidden. - mailbox-kanban step 4: cast RECORDS proposed intent, does not mutate the board; advance_phase stays the sole mutator. Durability paragraph narrowed: the writer's intent list is ephemeral staging, not a durable WAL; the durable record is the Lance row's version; recovery is a temporal read, not a replay from the struct. - batch_writer.rs: module doc narrowed likewise; added drain_pending_payloads() so the documented eager drain is real and the staging vector cannot grow unbounded (+ test). - ENTROPY-MILESTONES M24: removed the retired 'kill-after-cast-before-ack replay test' evidence; the gate is now the pinned-reference temporal.rs read. Skipped with reason: - 'move #689 board entries to the end': this repo's append-only convention is PREPEND newest-first (CLAUDE.md 'APPEND-ONLY (prepend new entries)'); the chronological placement is correct, the bot misread the convention. - 'persist intents before cast() returns (durable WAL)': the whole point of E-ACK-ELIMINATED-1 is that durability is Lance's row version, not the writer's — narrowing the doc claim (done above) is the correct response, not building a second WAL. Planner lib batch_writer tests 4/4, w1_probes 4/4, fmt clean. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/commands/v3-audit.md | 36 +++++++++++++------ .claude/v3/ENTROPY-MILESTONES.md | 2 +- .claude/v3/knowledge/mailbox-kanban-model.md | 16 ++++++--- .../v3/knowledge/sonnet-worker-guardrails.md | 12 ++++--- .../lance-graph-planner/src/batch_writer.rs | 32 +++++++++++++++-- 5 files changed, 74 insertions(+), 24 deletions(-) diff --git a/.claude/commands/v3-audit.md b/.claude/commands/v3-audit.md index 9377fdd5..8715c654 100644 --- a/.claude/commands/v3-audit.md +++ b/.claude/commands/v3-audit.md @@ -45,17 +45,31 @@ every hit with file:line and a one-line disposition 7. **Elimination scan — the ack mechanism does not exist** (E-ACK-ELIMINATED-1, operator 2026-07-17; after E-ACK-VIOLATION-REGRADE-1 - + E-SOA-OWN-BOARD-NO-SIDECAR-1): patterns `ack_and_propose`, - `\bunacked\b`, `\backed\b`, `fn ack\b`, `\.ack\(`, `ack-gated`, - `actionhandler`, `SLA gate` in code or live doctrine — ANY hit is a - violation (there is no sanctioned home; durability evidence is the - row's own LanceVersion via temporal.rs). Also flag any NEW stored - confirmation ledger in a writer regardless of its name ("retire", - "confirm", "settle" + version map = the same mechanism), and any - `\.await`/`ractor::(call!|cast)` on a path that also matches - `advance_phase|KanbanColumn|cycle` (kanbanstep is the only advance). - Exempt: board-history entries (`E-ACK-*` names in EPIPHANIES / - PR_ARC / TECH_DEBT / plan addenda) — history is append-only. + + E-SOA-OWN-BOARD-NO-SIDECAR-1). The mechanism is gone from source; the + scan prevents it regrowing. Two sub-checks, different because the tokens + legitimately appear in prose that DOCUMENTS the removal. **This file + (`.claude/commands/v3-audit.md`) is itself exempt — it defines the + patterns, so its matches are rule text, not findings.** + - **Code (`crates/**/*.rs` only):** literal patterns `ack_and_propose`, + `\bunacked\b`, `\bbacked\b`, `fn ack\b`, `\.ack\(`, `ack-gated`, + `actionhandler`, `SLA gate` — ANY hit is a violation (no sanctioned + home; durability evidence is the row's own LanceVersion via + temporal.rs). **Structural check (not keyword):** flag any NEW writer + field that is a persisted `CastId`/id → version map (a confirmation + ledger by SHAPE, whatever it is named). **Await check:** flag a + `ractor::call!` or an `.await` on a response that a cycle-advance path + (`advance_phase|KanbanColumn|cycle`) then depends on — NOT a bare + `ractor::cast` or the sanctioned fire-and-forget `BatchWriter::cast` + (owner-stamped intent recording, which never waits and is allowed). + - **Doctrine (`.claude/**/*.md`):** the tokens appear legitimately in + board history AND in the docs that document the elimination itself + (FUTURE-DESIGN / INTEGRATION-PLAN / mailbox-kanban-model / VISION rows + describing what was removed and why). Do NOT flag those. Flag only + NEW doctrine that **prescribes** the mechanism — text designing an + advance that waits on a completion/confirmation event, or a stored + confirmation ledger. The test is **prescription, not mention**: a row + saying "the ack is eliminated / retired unbuilt" is compliant; a row + saying "advance the cycle when the write acks" is a violation. End with a verdict per the v3-mailbox-warden vocabulary (OWNED / BOOTSTRAP-OK / ORPHAN-WRITE / RESURRECTION) plus LAYOUT-CLEAN / diff --git a/.claude/v3/ENTROPY-MILESTONES.md b/.claude/v3/ENTROPY-MILESTONES.md index 25439f21..43b8b3a6 100644 --- a/.claude/v3/ENTROPY-MILESTONES.md +++ b/.claude/v3/ENTROPY-MILESTONES.md @@ -46,7 +46,7 @@ | M21 | 3 dep-free hand-copies of the 16-byte NodeGuid LE encoder (q2 cpic, q2 fma/converge.rs, woa-rs erp/canon.rs — each "byte-identical", zero shared code) | one zero-dep `canon-node-bytes` extraction all three import | byte-parity test vs contract NodeGuid; grep local encoders = imports only | QUEUED (W5) | | M22 | 2 divergent q2 OSINT V3 bakes (crates/osint-bake canon-high 0x0700_0000 vs data/osint-v3 STALE pre-flip 0x1000_0700 dual-GUID scheme) | one canon-high bake against osint_classview.rs's 0x0700/0x0701 reservation | re-bake; grep pre-flip forms in q2 data/ = zero (or dual-alias-read only) | QUEUED (W5; latent until a reader assumes canon-high) | | M23 | 2 write-path doctrines coexisting (owner-stamped V3 writes vs smb-office-rs `LanceConnector::upsert` — the ONE live online consumer write, no stamp/classid/envelope) | all online consumer writes routed through the batch-writer cast | consumer-map §2 table shows zero ORPHAN-WRITE rows; warden green fleet-wide | QUEUED (W5 first live migration; medcare-soa writer BORN stamped as the prevention half) | -| M24 | 2 write-intent bookkeepers (batch-writer internal state vs kanban board AHEAD update) | ONE: the kanban board IS the write-ahead log — cast = move = intent record; ack = confirmation | kill-after-cast-before-ack replay test green; grep writer-internal intent queues = zero; cast carries descriptor never bytes (zero-copy sink through NodeRowPacket); stacked-casts-never-refused test (melden macht frei — Addendum-7; sink coalesces naturally via live-store reads) | PARTIAL 2026-07-17 (E-ACK-ELIMINATED-1: the second bookkeeper's confirmation half is DELETED — batch_writer.rs is a pure intent recorder; "ack = confirmation" in this row is history — confirmation = the row's own LanceVersion via temporal read; remaining collapse = the intent board into SoA rows, gated on the W2a mint) | +| M24 | 2 write-intent bookkeepers (batch-writer internal state vs kanban board AHEAD update) | ONE: the durable record is the Lance row's own LanceVersion — the writer stages ephemeral intent, Lance holds the truth (the "kanban board IS the WAL / ack = confirmation" framing is retired with the ack, see PARTIAL note) | recovery = a pinned-reference temporal.rs read of the row's version (`QueryReference::at` + deinterlace), NOT a replay from writer state; grep writer-internal id→version maps = zero; cast carries descriptor never bytes (zero-copy sink through NodeRowPacket); stacked-casts-never-refused test (melden macht frei — Addendum-7; sink coalesces naturally via live-store reads) | PARTIAL 2026-07-17 (E-ACK-ELIMINATED-1: the second bookkeeper's confirmation half is DELETED — batch_writer.rs is a pure intent recorder; "ack = confirmation" in this row is history — confirmation = the row's own LanceVersion via temporal read; remaining collapse = the intent board into SoA rows, gated on the W2a mint) | | M25 | 2 persistence surfaces for orchestration state (graph-flow SessionStorage backend vs mailbox kanban board) | ONE: KanbanSessionStorage — Session transitions ARE KanbanMoves via the W1b writer; replay = rebuild from board | kill-mid-graph replay test: session resumes identically from board-recorded moves; grep non-kanban SessionStorage impls in lance-graph = zero | SHIPPED v1 2026-07-02 (rs-graph-llm graph-flow `kanban` feature: KanbanSessionStorage, snapshot+move-log; kill-mid-graph replay test GREEN — no repeats/gaps, pinned Rubicon column sequence; grep gate holds: no non-kanban SessionStorage impl in lance-graph) | ## The meta-rule (why this ledger exists) diff --git a/.claude/v3/knowledge/mailbox-kanban-model.md b/.claude/v3/knowledge/mailbox-kanban-model.md index 16eeaa0f..f08d2fba 100644 --- a/.claude/v3/knowledge/mailbox-kanban-model.md +++ b/.claude/v3/knowledge/mailbox-kanban-model.md @@ -47,8 +47,13 @@ directive 2026-07-17, `E-ACK-ELIMINATED-1` — expelled from code, doctrine, and vocabulary after it twice produced tier-crossing designs). There is no confirmation bookkeeping anywhere: **durability evidence is the written row's own `LanceVersion` in Lance**, read through -`temporal.rs` (`QueryReference::at` + deinterlace); crash-replay is a -temporal READ comparing recorded intents against what Lance holds. +`temporal.rs` (`QueryReference::at` + deinterlace). The `BatchWriter`'s +intent list is **ephemeral staging, not a durable WAL** — after a +process restart it is gone, and there is nothing to "replay" from it. +The durable record IS the Lance row: a crash mid-write leaves the row at +an older `LanceVersion`, and recovery is simply a pinned-reference read +of what Lance actually holds. Reconciliation is Lance's, never the +writer's. Nothing advances on a completion event: not a thought (a stall of 250×–10,000× on a 40 ns op, and the death of the ladder amortization), and not anything else — the batch writer records intent and nothing @@ -72,8 +77,11 @@ The batch writer is where thinking is masked behind persistence: 3. **At cast time** (not at write-landed time) it checks the **delegation cache**: does the caster hold ownership, need delegation, or already have it? Mismatch (cast id ≠ envelope stamp) is the cache-logic case. -4. It fires the **AHEAD kanban update immediately on cast** — the kanban - board reflects intent before the write lands. No waiting. +4. It **records the proposed `KanbanMove` intent immediately on cast** + (before the write lands), where it is visible for reading. It does NOT + mutate the board or the tenant — `MailboxSoaOwner::advance_phase` is the + sole mutator (kanbanstep applies the move inline); the writer only + stages the proposal. No waiting. 5. Lance's columnar I/O writes the LE bytes from the in-place backing store (zero-copy; the store never serializes). diff --git a/.claude/v3/knowledge/sonnet-worker-guardrails.md b/.claude/v3/knowledge/sonnet-worker-guardrails.md index 3eddc790..f23cae70 100644 --- a/.claude/v3/knowledge/sonnet-worker-guardrails.md +++ b/.claude/v3/knowledge/sonnet-worker-guardrails.md @@ -94,7 +94,7 @@ exactly the row below, never a neighbor. | F12 | Test literals that only work in one classid order / one layout version (synthetic 0xAB12-style values) | test values come from the §2-sanctioned composers + realistic allocations; never hand-rolled hex composites | | F13 | Worker "fixes" a failing unrelated test to get green | out of scope (§1 rule 1): report the failure, touch nothing | | F14 | German PII labels or model identifiers in committed artifacts | never emit either in any file/commit (workspace-wide rule); chat-only | -| F15 | A cycle/phase advance paced on a completion/confirmation event, message, or awaited anything — or a stored confirmation ledger added to a writer (the eliminated ack mechanism; E-ACK-VIOLATION-REGRADE-1 → E-ACK-ELIMINATED-1) | kanbanstep is the ONLY advance (inline `on_version → try_advance_phase(&mut)`); the ack concept DOES NOT EXIST — durability evidence is the row's own LanceVersion via temporal.rs; ractor = compile-time ownership guarantee, never messaging (10⁴–10⁷× tax). A worker asked to await anything before an advance, or to add confirmation bookkeeping under ANY name = STOP+report | +| F15 | A cycle/phase advance paced on a completion/confirmation event, an awaited `ractor::call!` response, or any awaited I/O — or a persisted id→version confirmation ledger added to a writer (the eliminated ack mechanism; E-ACK-VIOLATION-REGRADE-1 → E-ACK-ELIMINATED-1). NOT this: the sanctioned fire-and-forget `BatchWriter::cast` (owner-stamped intent recording — it never waits and is the allowed contract) | kanbanstep is the ONLY advance (inline `on_version → try_advance_phase(&mut)`); the ack concept DOES NOT EXIST — durability evidence is the row's own LanceVersion via temporal.rs; ractor = compile-time ownership guarantee, never messaging (10⁴–10⁷× tax). A worker asked to await a response before an advance, or to add id→version confirmation bookkeeping = STOP+report | ## §4 — Sanctioned command palette (copy these, don't improvise) @@ -125,11 +125,13 @@ appears, because each requires accumulation-tier judgment: v3-mailbox-warden). 6. Anything RBAC, PII-adjacent, or externally visible. 7. The change would make ANY cycle/phase advance wait on a completion - or confirmation event, a message, a `ractor::call!`/`cast`, or any - awaited event — or would add ANY stored confirmation ledger to a - writer (the eliminated mechanism, E-ACK-ELIMINATED-1; durability + or confirmation event, an awaited `ractor::call!` response, or any + awaited I/O — or would add a persisted id→version confirmation ledger + to a writer (the eliminated mechanism, E-ACK-ELIMINATED-1; durability evidence is the row's own LanceVersion read via temporal.rs, and no - equivalent may be rebuilt under any name). + equivalent may be rebuilt whatever it is named). A bare fire-and-forget + `BatchWriter::cast` / `ractor::cast` that nothing awaits is NOT this — + it is the sanctioned intent-recording contract. Cross-ref: `.claude/knowledge/autoattended-multiagent-pattern.md` (the 4-savant wave pattern these rules slot into), `v3-substrate-primer.md` diff --git a/crates/lance-graph-planner/src/batch_writer.rs b/crates/lance-graph-planner/src/batch_writer.rs index 26134704..910ae3d2 100644 --- a/crates/lance-graph-planner/src/batch_writer.rs +++ b/crates/lance-graph-planner/src/batch_writer.rs @@ -7,9 +7,13 @@ //! **There is no confirmation bookkeeping here — by ruling (operator, //! 2026-07-17, E-ACK-ELIMINATED-1).** Durability evidence is the written //! row's own `LanceVersion` in Lance, read through `crate::temporal` -//! (`QueryReference::at` + deinterlace). Crash-replay is a temporal READ — -//! compare recorded intents against what Lance holds — never a stored -//! ledger in this struct. Do not add a confirmation method under any name. +//! (`QueryReference::at` + deinterlace). The intent records in this struct +//! are **ephemeral staging, not a durable WAL**: after a restart they are +//! gone and there is nothing to replay from them. The durable record is +//! the Lance row — a crash mid-write leaves it at an older `LanceVersion`, +//! and recovery is a pinned-reference read of what Lance holds, never a +//! replay from this struct. Do not add a confirmation ledger (a persisted +//! id→version map) under any name. //! //! **Zero-copy sink (operator ruling, plan Addendum-6):** `P` is a DESCRIPTOR //! — (mailbox, dirty row-range, cycle) — never owned delta bytes. Deltas stay @@ -126,6 +130,15 @@ impl

BatchWriter

{ self.delegation_cache.insert(on_behalf, owner); (owner, false) } + + /// Hand the staged payloads to the sink and clear them, preserving + /// cast order. This is the eager-drain handoff (module doc): the sink + /// reads the LIVE backing store for the bytes, so draining a payload + /// only releases the descriptor — it never serializes or copies the + /// deltas. Without this the staging vector would grow unbounded. + pub fn drain_pending_payloads(&mut self) -> impl Iterator + '_ { + self.pending_payloads.drain(..) + } } #[cfg(test)] @@ -164,4 +177,17 @@ mod tests { let (owner, hit) = w.resolve_owner(3, |_| unreachable!("cached")); assert_eq!((owner, hit), (11, true), "second resolve is a cache hit"); } + + #[test] + fn draining_payloads_hands_them_off_in_cast_order_and_clears() { + let mut w: BatchWriter = BatchWriter::new(); + let c0 = w.cast(7, vec![], 10); + let c1 = w.cast(7, vec![], 20); + let drained: Vec<_> = w.drain_pending_payloads().collect(); + assert_eq!(drained, vec![(c0, 10), (c1, 20)], "cast order preserved"); + // Second drain is empty — the staging vector was cleared. + assert_eq!(w.drain_pending_payloads().count(), 0, "drain clears"); + // Intent records are independent of payload staging and survive. + assert_eq!(w.casts(), vec![c0, c1]); + } }