Migrate version_watcher to std::sync; add CycleAccumulator; document Single-Binary Topology#337
Conversation
The original stub claimed it would "call lance-graph's parser::parse_cypher_query()".
That path is architecturally blocked: lance-graph already depends (optionally) on
lance-graph-planner via the `planner` feature, so making the planner depend back
on lance-graph would create a Cargo cycle.
This commit:
- Extracts the keyword/lexical feature-detection into pub fn extract_features().
- Has CypherParse::plan delegate to it, so the strategy is now the single source
of truth for query-text feature extraction.
- (Companion lib.rs change in next commit) drops the duplicated inline copy in
PlannerAwareness::plan_auto.
- Replaces the misleading TODO with a precise note describing the two real
unblock paths for full AST handoff:
(a) extract the Cypher parser from lance-graph into a zero-dep crate that
both lance-graph and lance-graph-planner can depend on, or
(b) thread a pre-parsed AST through PlanContext via a trait/type defined in
lance-graph-contract, with lance-graph as the caller.
…eatures
Removes the inline keyword-detection copy in PlannerAwareness::plan_auto that
was a copy-paste of the CypherParse logic ("Pass 1: detect features via
CypherParse" comment was already acknowledging the duplication).
After this commit the only place lexical feature detection lives is
strategy::cypher_parse::extract_features. Future tightening (richer pattern
analysis, real AST handoff) only has to update one site.
Reverts the dedup refactor of PlannerAwareness::plan_auto. Per user instruction: changes must be additive or refactoring with confirmation, no handwaving deletion of existing logic. The extract_features helper added in cypher_parse.rs remains in place as an unused additive helper. plan_auto continues to use its inline keyword-detection block byte-for-byte as before.
…es helper Restores cypher_parse.rs byte-for-byte to its pre-edit state — the original module docstring, the original CypherParse impl with its inline feature detection, and the original "Real implementation: call lance-graph's parser::parse_cypher_query()" comment. Then APPENDS, additively: - pub fn extract_features(query: &str) -> QueryFeatures Single-source-of-truth helper future callers can use; identical behaviour to the inline block in CypherParse::plan and PlannerAwareness::plan_auto. - A small #[cfg(test)] module exercising extract_features. Nothing existing is removed. The dedup refactor (having plan/plan_auto call extract_features) is deferred until explicit confirmation. The architectural note about Cargo cycles preventing a direct lance-graph dependency is also deferred — it would need to replace the existing TODO comment, which is a deletion that requires confirmation.
Adds cognitive-shader-driver::spo_bridge as the single place every input format collapses into BindSpace SoA rows. Every language (Cypher, GQL, SPARQL, Gremlin, NARS, DeepNSM Markov, raw SPO triplets, 1D Redis tree, 2D SQL row, 5D Gaussian splat scenario hydration) reduces to a stream of (S, P, O) triples + a per-triple SpoWitness, then calls project_into. Reuses canonical types — no parallel definitions: - MetaWord / MetaFilter from lance-graph-contract::cognitive_shader - InferenceType from lance-graph-contract::nars - BindSpace SoA columns from crate::bindspace Fingerprint convention (documented in module-level rustdoc): - topic = expand(subject) - angle = expand(predicate) - content = expand(subject) XOR expand(object) expand_to_fingerprint is deterministic splitmix64; no allocations beyond the [u64; 256] array. cycle plane and qualia column are intentionally NOT written — those are emitted by the cognitive shader during dispatch, not during ingestion. 10 tests covering: all-three-planes-written, content=topic XOR object identity, MetaWord packing of witness fields, temporal/expert/edge/ entity_type write-through, row isolation (other rows stay zero), cycle and qualia untouched, splitmix64 determinism, splitmix64 diversification across adjacent seeds, truth-flavour quantile sanity, OOB panic. Pure addition: zero edits to existing modules; lib.rs gets a single "pub mod spo_bridge;" line in the canonical surface section.
Adds:
- `pub mod spo_bridge;` in the canonical surface block (alongside bindspace,
driver, auto_style, engine_bridge, sigma_rosetta) so it is always
compiled, never gated behind serve/grpc/with-* features.
- `pub use spo_bridge::{SpoTriple, SpoWitness, expand_to_fingerprint, project_into};`
matching the EmbedAnything-style flat re-export pattern used by the
other canonical modules.
Pure addition. No existing declarations or re-exports modified.
User direction: revert until I have read PR_ARC_INVENTORY, lab-vs-canonical-surface, cognitive-shader-architecture, and arigraph/triplet_graph.rs. The premature spo_bridge risked duplicating or competing with the existing AriGraph SPO substrate (1064 LOC at lance-graph/src/graph/arigraph/triplet_graph.rs) and the DeepNSM → SPO pipeline documented in deepnsm_integration_map.md.
…d + re-exports)
Restores cognitive-shader-driver/src/lib.rs byte-for-byte to its
pre-A1.alpha state. Removes the `pub mod spo_bridge;` declaration in the
canonical surface block and the `pub use spo_bridge::{SpoTriple, SpoWitness,
expand_to_fingerprint, project_into};` re-export.
Companion to the spo_bridge.rs deletion. Branch HEAD goes back to additive
`extract_features` helper in cypher_parse.rs only.
Reason: I committed without consulting BOOT.md → LATEST_STATE.md →
PR_ARC_INVENTORY.md → lab-vs-canonical-surface.md, and without checking the
existing AriGraph SPO substrate. Reverting until those reads are done.
Drops the additive extract_features helper + 5 tests added earlier in this branch. Branch HEAD now has zero diff vs main for cognitive-shader-driver and lance-graph-planner. Only lingering branch artefact is the dev branch itself, with a clean revert log. Reason: incomplete reads of the canonical state docs (BOOT, PR_ARC_INVENTORY, lab-vs-canonical-surface, cognitive-shader-architecture, arigraph) before proposing changes. Per user direction.
…ts, name CycleAccumulator distinct from per-row CollapseGate Canonical reference for the architecture so future sessions stop re-inventing the conflation between the two ontologies. Pins: - Three nested layers in one binary (BindSpace SoA / callcenter ecosystem ontology / outbound sinks past tokio) - Four invariants: I-1 single binary + full lance-graph dep, I-2 tokio outbound only, I-3 BBB compile-time enforced (external_membrane.rs:7-13), I-4 per-row vs per-cadence gates are distinct primitives - Names CycleAccumulator (new, missing primitive) distinct from existing collapse_gate::GateDecision (per-row, 2-byte airgap) — closes the third GATE-namespace clash before it lands as an entropy-ledger row - Locates the four in-flight integration plans on the diagram - Cross-references PR #29 (smb-office-rs SmbMembraneGate) as the first concrete POLICY-1 closure on the consumer side Driven by feedback from another session that watched three different "where does the consumer live" framings emerge over two weeks. Pinning the names now while PR #29 is fresh as a reference point.
Add the canonical-architecture topology doc to the Cross-references list so future sessions land on it before re-inventing one of the three "where does the consumer live" framings settled in 0eeb72d. Single-line append to the Cross-references section. No plan-entry text touched (append-only governance preserved).
…uch the topology PR_ARC_INVENTORY.md is scoped to lance-graph PRs only (Added/Locked/Deferred semantics rooted here). Cross-repo PRs need their own trail because they validate or extend lance-graph design from outside; they don't add types here. Three entries: - MedCareV2#7 — out-of-MCP-scope; placeholder citation pending paste/allowlist extension. Located on L3 caller-side (C# .NET 4.8 desktop probe). - q2#35 — Phase 2B canonical R1 surface migration. Validates I-1/I-3/I-4 of the topology in real code. Resolves THINK-1 / TRUTH-1 / MOCK-DRIVER-IS- CONTRACT-CITIZEN ledger rows for q2. - smb-office-rs#29 — SmbMembraneGate. Closes POLICY-1/MEMBRANE-GATE-1 on the SMB consumer side. Three open TD caveats flagged. Append-only governance; new entries prepend.
Pins q2 PR #35 as the canonical first-mover example for consumer-side L1 surface migration, with four sub-points the topology doc now uses as reference shape: 1. THINK-1 closed for q2 — first concrete consumer-side L1 surface adoption. Reference shape for the remaining THINK-1/TRUTH-1 closures across consumers. 2. Wire-shape compaction as I-3 enforcement evidence — three concrete shrinks ([u64;256]→u64, [f32;32]→u8, tuple-of-tuples→structured) showing how the BBB compile-time rule bites in real wire output. 3. Phase 3 → CycleAccumulator load-bearing argument — at 100 ns/cycle the real BgzShaderDriver produces 3M cycles per 300ms window; SSE/HTTP/browser cannot absorb that. CycleAccumulator is the architectural prerequisite for shipping the real driver. 4. Gotham parity scope cross-ref to q2-foundry-integration-v1.md, with Q2 component → Gotham analog → wire-source mapping table and OSINT-adjacency note. Also added CROSS_REPO_PRS.md to the Cross-references list per the trail-keeping pattern from earlier this session.
… MCP scope) Same-day follow-up to MedCareV2#7 in the LanceProbe arc (#4 → #5 → R2-R6 → #7 → #8). Cannot fetch diff — MedCareV2 is outside the MCP allowlist; placeholder entry preserves the trail. Two same-day MedCareV2 PRs are kept as separate entries (do not collapse) per the appended note in the file. If/when the diff is paste-shared or allowlist extended, promote Confidence from "Cannot verify" to FINDING with concrete delta.
…-only sync primitives
Per topology I-2 (tokio outbound only), the version_watcher is a Layer-2
in-process primitive that must not pull in async runtime. Reimplemented using
std::sync::{Arc, RwLock, Mutex, Condvar} + AtomicUsize for receiver tracking.
Semantic shape preserved:
- Always-latest snapshot (Arc<RwLock<Arc<CognitiveEventRow>>>)
- Slow-subscribers-skip-intermediates (version counter + wait_while predicate)
- bump() returns true iff at least one subscriber is listening
API surface:
- LanceVersionWatcher::{new, bump, subscribe, receiver_count}
- WatchReceiver::{current, wait_changed, wait_changed_timeout, try_changed}
- WatchReceiver::Drop decrements receiver_count
Tests migrated + extended:
- 4 original tests (subscribe_observes_initial, bump_delivers_latest,
bump_without_subscribers_returns_false, receiver_count_tracks_subscribers)
- 3 new tests for blocking semantics (wait_changed_blocks_until_bump,
wait_changed_timeout_fires_on_no_bump, wait_changed_timeout_returns_value_on_bump)
- 1 compile-time invariant proof (watcher_is_send_sync_without_runtime)
Next commit updates lance_membrane.rs Subscription type to WatchReceiver.
…sync WatchReceiver Drops `tokio::sync::watch::Receiver<CognitiveEventRow>` as the realtime Subscription type; now uses the std-sync `WatchReceiver` from version_watcher.rs (landed in 19a1521). Surface change is purely tokio-removal: - `type Subscription = WatchReceiver` (was: `watch::Receiver<CognitiveEventRow>`) - `fn subscribe() -> WatchReceiver` (was: `-> watch::Receiver<CognitiveEventRow>`) - Test `subscribe_receives_on_project` migrated from `rx.borrow()` to `rx.current()` (returns `Arc<CognitiveEventRow>`; deref auto-magic preserves call-site shape) I-2 invariant now holds in lance-graph-callcenter: - L2 membrane primitives are sync (no async fn, no tokio types in field set) - Tokio dep stays under `realtime` feature for DM-5 PhoenixServer (L3 outbound) but the watcher itself no longer drags it in No semantic changes: - Always-latest snapshot via `current()` (cheap Arc clone) - Slow-subscribers-skip-intermediates preserved (version-counter wakeup) - Per-project bump still happens on pass_filter && pass_gate - All other tests untouched
…er (I-4)
New zero-dep primitive in lance-graph-contract for the L1↔L3 speed-ratio
absorber per .claude/board/SINGLE_BINARY_TOPOLOGY.md § Per-cadence gate.
Distinct from collapse_gate::GateDecision per I-4:
- collapse_gate is per-row write airgap (Xor/Bundle/Superposition/AlphaFrontToBack)
- cycle_accumulator is per-cadence flush gate (rows-since-flush OR ms-since-flush)
Pure data + decision logic; no callbacks (caller drives flush via drain()).
This keeps the contract crate zero-dep and gives lance-graph-callcenter full
control over the flush mechanism (which lives in L3 alongside tokio).
API:
- CycleAccumulator::new(threshold_rows, threshold_ms)
- push(commit) -> AccumulatorAction { Hold, Flush }
- drain() -> Vec<C>
- pending_len(), is_empty(), pending_age_ms(), threshold_rows(), threshold_ms()
10 tests covering:
- Below-threshold Hold behaviour (push_below_row_threshold_holds)
- At-threshold Flush behaviour (push_at_row_threshold_flushes)
- drain returns batch and resets (drain_returns_batch_and_resets)
- ms threshold triggers Flush (ms_threshold_triggers_flush)
- ms threshold resets on drain (ms_threshold_resets_on_drain)
- threshold_rows=0 disables count path (rows_threshold_zero_disables_count_path)
- threshold_ms=0 flushes immediately (ms_threshold_zero_flushes_immediately)
- pending_age_ms grows then resets (pending_age_ms_grows_then_resets)
- drain on empty is safe (drain_empty_is_safe)
- accessors return construction values (threshold_accessors_return_construction_values)
- I-4 structural invariant: no callback field (pure_data_no_callback_field)
Why this is load-bearing for q2 Phase 3: at real BgzShaderDriver speed
(~10⁷ cycles/sec) the cockpit-server SSE stream produces ~3M cycles per
300 ms window. Without an accumulator that batches before the L3 outbound
edge, the SSE pipe / browser cannot absorb the load. CycleAccumulator
is the prerequisite type for shipping the real driver.
Next commit wires the module into lib.rs.
Adds `pub mod cycle_accumulator;` between `crystal` and `distance` (alphabetical order). Updates the module-layout doc comment to enumerate the two distinct gate primitives (collapse_gate per-row, cycle_accumulator per-cadence) per topology I-4.
… 30-LOC mirror) Documents the workspace-shape mismatch discovered while attempting to mirror smb-office-rs PR #29 onto the medcare consumer side: medcare-rs lacks the prerequisite scaffolding crates (medcare-realtime + medcare-rbac) that smb-office-rs already had. Total estimated scope: ~800 LOC across 3-stage scaffolding sequence: 1. medcare-rbac crate scaffold (~300 LOC) — Policy/Role/Operation/AccessDecision 2. medcare-realtime crate skeleton (~200 LOC) — feature gates, MedCareStack 3. MedCareMembraneGate impl (~300 LOC) — the gate itself, mirroring PR #29 Three options surfaced (no decision yet): full scaffolding sprint, defer until DM-7+DM-8 land, or parallel-track Stage 1 only. Marker file so future sessions don't re-discover the gap mid-PR. Cross-refs the topology doc's "~30 LOC" estimate which needs correction once this scaffolding decision is made.
…int (12 + 3 agents) Creates the coordination surface for the 3-stage MedCare scaffolding sprint: 12 worker agents (4 per stage) + 3 meta agents (1 per stage), each writing append-only log entries to .claude/board/sprint-log/agents/ (the GitHub-MCP equivalent of `tee -a /var/log/sprint.log`). Sprint manifest pins: - Goal: close MEDCARE_POLICY_GAP.md Stages 1+2+3 in one sprint - Branch: claude/lance-datafusion-integration-gv0BF on both medcare-rs and lance-graph (worker commits go to medcare-rs, sprint-log + meta reviews go to lance-graph) - References each agent uses (lance-graph-rbac, smb-realtime, PR #29) - Per-round acceptance criteria + per-agent file ownership Append-only governance: per-agent files immutable; revisions spawn new files. Status table at the top is the only mutable surface in this file.
…ITICAL fixes required) Meta-1 review surfaces 10 findings; 2 CRITICAL fixes block Round 2 opening: CRITICAL #1: Doctor.Anamnese Full predicate-write violates BMV-Ä §57 append-only → fix: empty writable_predicates, keep only "append" action CRITICAL #2: Receptionist clinical-blind fails safety (no Identity-read for allergy/triage lookup before scheduling) → fix: merge Patient permission to Detail-depth + 3 demographic writes, add Identity-read on Diagnosis + LabResult HIGH #3-#4 (defer to Round 3 gate.rs): Diagnosis finalize/retract Escalate + Patient anonymize/merge/delete Escalate (GDPR Art.17 + §35 BDSG) MEDIUM #5-#8 (backlog): Missing entities (Termin, Recall, ePA) + audit trail hook LOW #9-#10 (backlog): PKV/GKV modulation + dynamic reason strings Round 2 implications surfaced for W5/W8. Round 3 implications surfaced for W9/W12 (Escalate wrapping + §73 SGB V test). Concrete diff for W3-revision-2 included at end of file. Next commit: W3-revision-2 applies the two CRITICAL fixes.
…edCare upstream dep flagged)
…1 CRITICAL fix path) Meta-2 review surfaces 5 findings; 1 CRITICAL flagged for verification: CRITICAL #1: W7 hard-depends on StepDomain::MedCare which may not exist upstream → Recommended fix path: fetch lance-graph-contract/src/orchestration.rs to verify DomainProfile shape, then either confirm variant exists OR commit W7-revision-2 with inline-constructed DomainProfile fallback MEDIUM #2: MedCareStack empty struct doc-comment overclaims as "facade" → Doc-only fix; defer to next field-growth commit MEDIUM #3: Missing with_default_policies() builder → Backlog; lands when rls_registry field lands LOW #4-#5: Cross-crate test + dev-deps deferred Round 3 implications surfaced: - W9 imports list (medcare_rbac::{policy, role, access}) - W10 lib.rs gate re-export shape - W12 §73 SGB V tests must include BtM Escalate + Ueberweisung row visibility (Meta-1 carry-forward) Sprint orchestrator: verify upstream StepDomain::MedCare before committing W7-revision-2, OR apply fail-safe inline construction.
…e (sprint closure) Meta-3 final review surfaces 5 findings; ZERO CRITICAL: HIGH #1: Action operations (Operation::Act) unreachable via gate → Doc note recommended; orchestration layer is the right home for action gating HIGH #2: BtM Escalate "v1 limitation" tests use loose is_allowed() assertions → Recommend tightening to explicit assert_eq!(AccessDecision::Allow) for clearer future test-failure messages MEDIUM #3: Three name paths for Policy (rbac, gate, lib) → Backlog; doc-only canonicalization MEDIUM #4: 20-200 ns gate decision claim unbenchmarked → Backlog; criterion-based gate-bench follow-up LOW #5: TD-MEMBRANE-FIRST-VS-ANY untested → Backlog; vacuous in v1 without divergence case Sprint-wide closure: - Round 1 (medcare-rbac): 26 tests, solid, 2 CRITICAL fixes applied - Round 2 (medcare-realtime skeleton): 5 tests, 1 CRITICAL casing+HIPAA fix - Round 3 (gate impl): 33 tests, 2 HIGH documentation gaps - Total: 64 tests across 3 crates VERDICT: Ship. POLICY-1 medcare-side seam CLOSED for v1. Topology I-1/I-2/I-3/I-4 upheld. PR #29 three TD caveats honestly carried forward.
…closure 12 workers + 3 metas across 3 rounds, 4 CRITICAL fixes applied as inline revisions (W3-rev2, W4-rev2, W7-rev2). Meta-3 final verdict: SHIP. Total shipped: - medcare-rs: 14 commits, 13 files, ~1,865 LOC, 64 tests - lance-graph sprint-log: 21 commits (12 agent logs + 3 meta reviews + scaffolding + this synthesis) POLICY-1 / MEMBRANE-GATE-1 medcare-side seam: SHIPPED v1 - Mirror of smb-office-rs#29 with regulatory adaptations - Three TD caveats from PR #29 honestly carried forward - Topology I-1/I-2/I-3/I-4 invariants preserved Outstanding from Meta-3 (backlog): - HIGH #1: Action ops doc note (5 min) - HIGH #2: Tighten v1-limit assertions (10 min) - MEDIUM #3-#4: Policy name canonicalization + bench harness - LOW #5: TD-MEMBRANE-FIRST-VS-ANY test (vacuous in v1) Synthesis includes: - Findings summary (4 CRITICAL applied + 2 HIGH backlog) - Topology invariant preservation table - Upstream gaps surfaced (StepDomain verified, BMV-Ä retention, BtM Escalate) - Test posture per-crate - Recommended follow-up sprint scope (~half day) - What the cca2a pattern validated this run - Full branch state at sprint closure (commit lists for both repos) Ready for CI verification + PR to medcare-rs main.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c1fc1e5ad6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .latest | ||
| .write() | ||
| .unwrap_or_else(|e| e.into_inner()); | ||
| *latest = Arc::new(row); |
There was a problem hiding this comment.
Keep watcher version and snapshot updates atomic
When two bump() calls happen close together, storing latest before taking the version mutex lets a woken receiver read the second row while recording the first bump's version. For example, bump A increments/notifies, bump B replaces latest before incrementing version, and wait_changed() can return row B with seen = 1; the next wake for version 2 then returns row B again. This breaks the watch semantics by duplicating the latest row and losing the A→B association under concurrent publishes, so update latest and version under a single ordering/lock boundary before notifying.
Useful? React with 👍 / 👎.
| /// driven outbound runtime). | ||
| pub fn drain(&mut self) -> Vec<C> { | ||
| self.last_flush = Instant::now(); | ||
| std::mem::take(&mut self.pending) |
There was a problem hiding this comment.
Preserve accumulator capacity after drains
For the high-rate Phase 3 path described in this module, std::mem::take replaces pending with a zero-capacity Vec, so after every flush the next batch has to grow from scratch despite new() explicitly preallocating threshold_rows.max(64) to avoid steady-state reallocations. With large row thresholds or frequent flushes this turns the accumulator into a repeated allocation hot spot; replace the drained buffer with a pre-sized vector or change the API so the hot buffer is retained.
Useful? React with 👍 / 👎.
…PY_LEDGER Append-only update to the entropy ledger per its own Update Protocol. Records: State changes: - WATCHER-1: Stalled → Wired (sync, std-only) per topology I-2. Evidence: PR #337 (commit c1fc1e5). Transport layer correct; MVCC bind to Dataset::checkout_latest().version() still pending. Entropy 4 → 3. - POLICY-1 / MEMBRANE-GATE-1: Stalled → Wired on BOTH consumer sides via newtype-bridge pattern. SMB side (smb-office-rs#29 — SmbMembraneGate over Arc<lance_graph_rbac::Policy>) + medcare side (medcare-rs#98 — MedCareMembraneGate over Arc<medcare_rbac::Policy>, with 12+3 agent sprint trail at .claude/board/sprint-log/). 4 CRITICAL fixes applied during sprint (BMV-Ä §57 Anamnese append-only, receptionist clinical- blind safety, StepDomain::Medcare casing + HIPAA values, policy.rs test alignment). Entropy 4 → 2 / 3 → 2. - SPLAT-1: stage advance via PR #336 + #344. 22 splat tests now passing. New rows: - CYCLE-ACCUM-1: per-cadence flush gate, distinct from collapse_gate per topology I-4. Wired in PR #337 with 11 tests. Entropy 2. - LADYBUG-EQUIV-1: ladybug-rs ↔ lance-graph equivalence closure. Documented mapping (clam_path ≅ cam_pq, nsm_substrate ≅ deepnsm, sentence_crystal ≅ holograph, DN-tree binding ≅ holograph::dntree, etc.). Verdict: harvest empty. Entropy 1 (clean closure). Workspace crate inventory expansion: prior models tracked ~5 crates; canonical inventory is ~22 (lance-graph + lance-graph-contract + lance-graph-planner + lance-graph-callcenter + lance-graph-rbac + lance-graph-archetype + lance-graph-catalog + lance-graph-cognitive + cognitive-shader-driver + deepnsm + holograph + bgz-tensor + highheelbgz + reader-lm + jc + thinking-engine + neural-debug + learning + causal-edge + medcare-rs/{medcare-rbac,medcare-realtime,...} + smb-office-rs/{smb-realtime,...} + q2/cockpit-server). Cross-references: .claude/patterns.md (NEW, commit cd95da9) — graph- traversal usability guide. SINGLE_BINARY_TOPOLOGY.md — three-layer invariants. MEDCARE_POLICY_GAP.md — scoping. CROSS_REPO_PRS.md — append-only external-repo log. sprint-log/ — 12+3 agent sprint trail. Open seams: 8 → 5 (3 closed via PR #337 + #29 + #98). Pre-work checklist for future sessions added — the load-bearing surface that prevents the discovery-loop cost this session paid (~10 rounds of "is X new?" → "no, X exists at Y"). [Note: this branch's pre-existing ledger state was stale; this commit writes [main_content + 2026-05-06 dated append] so the user-side merge keeps everything from main plus the new section.]
#353); append 2026-05-07 CYCLE-ACCUM-1 + LADYBUG-EQUIV-1 + crate inventory 22→23 Rebases the ledger so it begins with current main's content (commit a6797ad with all six 2026-05-06/2026-05-07 dated sections from PRs #345/#346/#347/#348) and then appends a single dated section "2026-05-07 — CYCLE-ACCUM-1 + LADYBUG-EQUIV-1 introductions + crate inventory expansion (post-#353)" containing only the unique findings not already absorbed by those merged PRs: - CYCLE-ACCUM-1 row introduction (per-cadence flush gate, R2, shipped via PR #337, entropy 2) - LADYBUG-EQUIV-1 row introduction (ladybug-rs ↔ lance-graph equivalence map; harvest is empty, entropy 1, full mapping table for clam_path, nsm_substrate, sentence_crystal, spo_harvest, causal_trajectory, gestalt, nsm_primes, crystal_lm, dn-tree) - Crate inventory expanded 22 → 23 (sigker added by PR #348) - Cross-references include PR #109 medcare-rs (?source=lance toggle exercising per-request RlsRewriter+ColumnMaskRewriter pattern) + PR #353 (palantir-parity-cascade-v2 + soa-dto-dependency-ledger) - Open question flagged: .claude/pattern.md (singular, PR #345) vs .claude/patterns.md (plural, this session) filename collision awaiting user resolution State-change blocks for WATCHER-1 / POLICY-1 / MEMBRANE-GATE-1 / SPLAT-1 are NOT duplicated here — the corresponding 2026-05-06 entries from PR #345/#346 already cover those state changes. Original branch authoring is preserved at commit 0dd0f56 for archaeology.
Direct commit to main (per user 2026-05-07). Replaces main's ledger with the rebased version that absorbs: - PR #355 (palantir-cascade, merged 13:40 UTC): SPO-1 closure, 8 new rows (ONTOLOGY-REGISTRY-SOA-1 / MUL-THRESHOLD-1 / CASCADE-COLS-1 / OBJECT-VIEW-1 / BUSDTO-BRIDGE-1 / CERT-OFFICER-1 / CONTEXT-ID-1 / DTO-CLASS-CHECK-1), Per-row-context cluster (highest-leverage single-fix unlock, 3 rows entropy 3→2 via 200-300 LOC PR), open- seams update (R6/R0 ontology-as-SoA closed; 2 new open seams). - CYCLE-ACCUM-1 introduction (per-cadence flush gate, R2, shipped via PR #337, entropy 2; companion to collapse_gate per topology I-4). - LADYBUG-EQUIV-1 row (entropy 1, harvest-empty closure with full module mapping for clam_path / nsm_substrate / sentence_crystal / spo_harvest / causal_trajectory / gestalt / nsm_primes / crystal_lm / dn-tree). - Crate inventory expanded 22 → 23 (sigker added by PR #348). Aggregate: 41 rows (2026-05-05 baseline) → 53 rows tracked. Entropy delta from this session work alone: SPO-1 (4→2) and 8 new rows averaging 2.875 (lower than the 3.46 snapshot mean — Wave-3 BLOCKER discipline reflected in the numbers). Pre-existing 2026-05-06/2026-05-07 dated sections from PRs #345/#346/#347/#348 preserved verbatim per APPEND-ONLY governance.
Summary
This PR establishes the architectural foundation for the Single-Binary Topology by:
LanceVersionWatcherfromtokio::sync::watchtostd::syncprimitives to enforce the Layer-2/Layer-3 boundary (Invariant I-2)CycleAccumulatoras the per-cadence flush gate to absorb the ~10,000× speed ratio between Layer 1 (20–200 ns) and Layer 3 (2–200 ms)Key Changes
crates/lance-graph-callcenter/src/version_watcher.rstokio::sync::watch::Sender/Receiverdependencystd::sync::{Arc, RwLock, Mutex, Condvar}primitivesWatcherInnerholdinglatest(Arc-wrapped snapshot),version(monotonic counter),cond(Condvar), andreceivers(live count)crates/lance-graph-contract/src/cycle_accumulator.rs(new file)CycleAccumulator<C>— generic per-cadence batching gateAccumulatorAction::{Hold, Flush}returned bypush().claude/board/SINGLE_BINARY_TOPOLOGY.md(new file)lance-graphCollapseGate(per-row) andCycleAccumulator(per-cadence) are distinct primitivesSprint documentation (
.claude/board/sprint-log/)https://claude.ai/code/session_01PjcbSTd9zdVPkta9qwkVKo