Skip to content

D-MBX-A6-P4: cycle loop-closure driver — sparse seal/apply + MUL-gate thought seam (control-loop contract) - #879

Merged
AdaWorldAPI merged 6 commits into
mainfrom
claude/medcare-rs-continue-ufsazd
Aug 2, 2026
Merged

D-MBX-A6-P4: cycle loop-closure driver — sparse seal/apply + MUL-gate thought seam (control-loop contract)#879
AdaWorldAPI merged 6 commits into
mainfrom
claude/medcare-rs-continue-ufsazd

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Aug 2, 2026

Copy link
Copy Markdown
Owner

What this is

Makes the merged #878 persist_sink cycle/WAL bootstrap load-bearing — its first caller — and closes the cycle control loop:

owners cast sparse intents → seal (one WAL write, Vn+1) + expose the sealed
paired-transition set → apply ONLY the sealed sparse transitions (represented
owners advance one legal step + watermark; unrepresented owners byte-identical)
→ CognitiveWork runs the MUL gate → owner_adapter casts the next intent →
held/Hold owners reschedule → loop → recover

Honesty ledger (what this PR proves vs does NOT)

  • Control-loop contract: PROVEN — 19 falsifiers over contract-probe fakes.
  • Actor-owned production wiring: NOT provenMailboxFleet + its HashMap impl is the probe/registry fleet; bridging the sealed sparse set into KanbanActor-owned state is open. Per the ratified sparse-cycle ruling, apply is writer-fires-inline (no message bus) by design.
  • cognitive-shader-driver / MailboxSoA thought: NOT proven — the P4c thought body is the real MUL gate (gate_decision_i4advance_on_gate), but its qualia/mantissa inputs come from a caller extractor (the deferred MailboxSoaView::qualia() seam), not a live SoA dispatch.
  • Durability: FAKE — contract-probe WalSink until the concrete LanceShardSink lands (compile+test green ≠ storage proven).

The load-bearing rule (enforced in code)

A DatasetVersion is global knowledge, NOT permission to advance every mailbox. Only owners with a sealed paired_move advance; the version tick never fans a step across the fleet (E-COMPLETE-CYCLE-IS-PHYSICALLY-SPARSE-…-1, E-D-MBX-SPINE-IS-STRAIGHT-TRACK-…-1).

Review round (grain-of-salt audit, commit 71d1db1)

Each finding was verified against code; all accepted items were real defects:

  1. Retry-safe seal — a WAL failure previously LOST the drained cycle. seal_cycle → Result<SealedCycle, Box<SealFailure>> now returns the complete frozen cast set byte-identical for retry. Falsifier: failed commit → zero owner mutation → same-cycle retry → exactly one version, no cast lost/duplicated.
  2. Restart-stable stream positionsstream_position = CastId was the P3d-documented trap ("cast_id is provenance only"): a reconstructed BatchWriter restarts at 0 and recover_and_apply silently skips positions ≤ watermark. collect_casts now takes the caller's durable position_base cursor; SealedCycle.next_position_base carries it forward. Restart falsifier pins the exact failure mode.
  3. Watermark-coupled applyapply_sealed_transitions advances the per-owner recovery watermark WITH the phase (one rule shared with recovery). Falsifier: normal apply → crash → recovery replays NOTHING (previously: replay → permanent StalePhase stall).
  4. ≤1-move/owner enforced PRE-seal — the old deferred counter sealed a durable move and then never applied it (recovery WOULD — divergent semantics). Extras (same cast or later casts; also kills the silent moves.first() truncation) return as HeldIntent, re-staged via restage_held. Sealed set == applied set; recovery-agrees falsifier.
  5. Mid-apply prefix preservedErr((partial, cause)), mirroring recover_and_apply; the prefix's watermarks survive.
  6. Hold = reschedule, never strandCognitiveWorkOutcome.held_owners + run_cognitive_work[_gated]_over re-poll; falsifier wakes a Held owner on a later cycle.
  7. recover_fleet partitions history once — O(history + Σtails), not O(fleet×history).
  8. P4d honesty — wait-free at the cast/cycle boundary (sequential pass); strengthened falsifier: two represented owners, A unfinished, B casts + advances without waiting. Concurrent per-owner execution is the actor leg, explicitly out of driver scope.

Declined with reason: routing P4b through KanbanActor mailboxes — contradicts the operator-ratified writer-fires-inline sparse ruling (no message bus for P4a/P4b). The honesty half is taken in docs instead (MailboxFleet is not a production-ownership claim).

Falsifiers (19 lib tests, cargo test -p lance-graph-supervisor --features cycle-driver)

  • 64k/17 headline — 65 536 mailboxes, 17 sealed → exactly 17 advance, 65 519 byte-identical, one WAL write, zero dataset reads, 17 watermarks.
  • Failed-seal → byte-identical retry · restart-stable positions across writer reconstruction · normal-apply-advances-watermark (no replay after crash) · held-move-lands-next-cycle + recovery-agrees · multi-move no-truncation · mid-apply prefix preservation.
  • MUL-gate discriminates — three distinct outputs for three inputs (Flow→Evaluation / Block→Prune / Hold→rescheduled-and-woken), None at absorbing columns.
  • P4e idempotence + load-bearing-watermark negative control · P4f O(dirty)-not-O(fleet) (640 resolves over a 64k fleet).

clippy (feature) + fmt clean; default (no-feature) supervisor build unchanged. Mints no new semantic/temporal/rung/witness type — composes SweepSlot/CycleFrame/KanbanMove/DatasetVersion/PersistError/StrategyOutcome/recover_and_apply/emit_bootstrap_intent/MailboxSoaOwner/gate_decision_i4.

Plan: .claude/plans/cycle-loop-closure-driver-v1.md (status synced). Board: STATUS_BOARD D-MBX-A6-P4 + LATEST_STATE honesty ledger.

🤖 Generated with Claude Code

claude added 5 commits August 2, 2026 08:46
…#878 follow-up)

Documentation-only. No Rust code, tests, public APIs, persist_sink.rs,
temporal.rs, or the persistence implementation change.

1) Sparse-delta ruling (persistence-cycle-wal-bootstrap-v1.md §2, NEW):
   "complete logical cycle ≠ full physical dataset rewrite". A globally-complete
   cycle persists ONLY its coalesced dirty-row delta + required durable
   transition metadata; unchanged rows are inherited from the sealed base
   version, never re-serialized because they participated. Records the verbatim
   storage invariant, the participation-vs-mutation split (a no-mutation
   participant needs no 512-byte row), the honest in-memory payload-duplication
   limitation (concrete sink must not persist both per-landing bytes AND the
   coalesced image), the capacity/backpressure ruling (dense cycle = explicit
   capacity event), and 5 concrete-sink falsifiers (sparse / no-op-policy /
   coalescing / dense-capacity / retention). Status: RATIFIED architecture,
   UNIMPLEMENTED in a concrete Lance sink. Preserves the horizontal(temporal.rs)
   / vertical(DatasetVersion) / revision.rs split — density only. Sections
   renumbered (§2 inserted; §3–§7 shifted, all internal §-refs updated).

2) Loop-closure driver plan (cycle-loop-closure-driver-v1.md, NEW): the seam
   that makes the merged persist_sink load-bearing at 64k — persist_sink has
   zero production callers today, so the loop is open. Closes collect →
   persist_cycle → sealed version → sync inline fan-step (on_version +
   try_advance_phase, NOT 64k async drive_once) → CognitiveWork → owner_adapter
   → next cycle. Mints no new types. Deliverables D-MBX-A6-P4a..f, probe-first.
   Home: lance-graph-supervisor.

Board: EPIPHANIES E-COMPLETE-CYCLE-IS-PHYSICALLY-SPARSE-NOT-A-FULL-REWRITE-1
(prepend); INTEGRATION_PLANS cycle-loop-closure-driver v1 (prepend); STATUS_BOARD
D-MBX-A6-P4 row + P3d flipped to Merged (#878, reshaped to cycle/WAL + sparse
ruling). Branch restarted from main after #878 merged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
…ed-transition application

Architecture/plan reconciliation before implementing the cycle-loop closure.
Documentation-only — no Rust code, tests, public APIs, or persistence
implementation changed (verified: zero .rs in changeset). Crate deps verified
against Cargo.toml, not asserted from memory.

1) THE CORRECTION (ChatGPT feedback, accepted — it caught a real same-session
   contradiction). The loop-closure plan's P4 had the supervisor FAN
   NextPhaseScheduler::on_version across the whole fleet → advance every
   non-absorbing mailbox per sealed version. That makes almost the entire fleet
   dirty every cycle, directly violating the sparse-cycle ruling
   (E-COMPLETE-CYCLE-IS-PHYSICALLY-SPARSE-NOT-A-FULL-REWRITE-1). Corrected model
   throughout §2/§3/§4/§6: a DatasetVersion is GLOBAL KNOWLEDGE, not permission
   to advance every mailbox. Owners think over Vn; owners that produce material
   updates emit sparse fire-and-forget intents; planner collects/coalesces/seals
   (one WAL → Vn+1) and exposes the sealed paired-transition set; the supervisor
   applies ONLY the sealed sparse transitions (represented owners advance one
   legal step; unrepresented owners byte-identical), inline (no dataset re-read;
   NOT 64k async drive_once). on_version becomes the intent-time lowering policy,
   not an apply-time fan; SymbiontBoard.step-advances-every-board is the SLICE
   shape-prover, not the production rule. Interim rule: <=1 durable phase
   transition per owner per sealed cycle. P4b falsifier is now the sparse shape:
   64k mailboxes / 17 sealed transitions -> exactly 17 advance, rest
   byte-identical, no second dataset read, one version. P4a..P4f re-scoped to
   supervisor-side sparse application.

2) RATIFIED OWNERSHIP MAP (§9, verified deps): contract = canonical types (zero
   fleet ownership); cognitive-shader-driver = MailboxSoA type/layout home +
   anatomy (not the runtime lifecycle); planner = decides + persistence contract
   (never mutates a supervisor-owned SoA, never deps supervisor); supervisor =
   exclusive runtime owner + P4 loop + applies only sealed sparse transitions;
   lance = storage substrate + external-reader subscription + future
   LanceShardSink. Dep direction verified: supervisor->contract, planner->contract,
   planner does NOT dep supervisor/symbiont/rs-graph-llm; supervisor->planner is
   the planned acyclic P4 edge; shader has an optional feature-gated planner dep
   (debug DTOs, not fleet ownership). NO cycles found.

3) ADJACENT-CRATES DOCTRINE (§10): symbiont = golden-image + bystander research
   lab (forbidden as authoritative owner/scheduler/WAL/version/required dep);
   rs-graph-llm = optional capability basement (client/capability provider
   returning Outcomes, never owns the standing wave); ogar-* = AST/declaration/
   adapter basement (describes behaviour, never owns the cycle). Subagent
   anti-drift guardrail with STOP+report triggers (§11).

4) DRIFT AUDIT: the only genuine conflict was the P4 fan-step introduced this
   session (fixed). Other 'fan'/symbiont hits are corrected text, append-only
   AGENT_LOG history, or SymbiontBoard-slice / ractor-compile-time-argument
   descriptions in sibling plans (not production-ownership claims; now governed
   by the §10 doctrine).

Board: EPIPHANIES E-D-MBX-SPINE-IS-STRAIGHT-TRACK-VERSION-IS-NOT-A-FLEET-STEP-SIGNAL-1
(prepend); INTEGRATION_PLANS + STATUS_BOARD P4 row corrected to sparse.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
…st_sink's first production caller)

Closes the ZERO-caller gap on the merged #878 persist_sink: nothing drove the
seal→apply loop, so the sealed version never advanced any owner. New module
`lance-graph-supervisor::cycle_driver`, behind the `cycle-driver` feature
(optional ONE-WAY `lance-graph-planner` path-dep — planner never deps supervisor,
verified acyclic; default supervisor build stays light, no planner/ractor).

Mints NO domain types — composes the shipped organs:
- P4a: `collect_casts(writer, cycle, row_of)` drains a `BatchWriter<Vec<u8>>`'s
  staged casts into `Vec<SweepSlot>` (one slot/cast; stream_position = CastId;
  paired_move = first intended move). `seal_cycle(sink, frame, casts)` reads out
  the SPARSE `SealedTransition` set (only slots with a move, stream-ordered) then
  `persist_cycle` -> exactly one WAL write, one DatasetVersion.
- P4b: `apply_sealed_transitions(fleet, &SealedCycle)` iterates ONLY the sealed
  sparse set, resolves each owner via the `MailboxFleet` trait (blanket-impl'd
  for HashMap<MailboxId, O>), applies one legal `try_advance_phase`; EVERY
  unrepresented owner stays byte-identical (never resolved). Interim rule: <=1
  durable transition per owner per cycle (2nd same-owner move -> `deferred`);
  unknown owner -> `missing` (counted, not a crash); StalePhase/OwnerMismatch
  guards; reads NO dataset (version already sealed — no scan_sealed/versions/
  drive_once). `run_cycle` = P4a->P4b convenience.

The load-bearing rule, enforced in code: a DatasetVersion is GLOBAL KNOWLEDGE,
NOT permission to advance every mailbox — only the sealed sparse set advances
(E-D-MBX-SPINE-IS-STRAIGHT-TRACK-VERSION-IS-NOT-A-FLEET-STEP-SIGNAL-1 +
E-COMPLETE-CYCLE-IS-PHYSICALLY-SPARSE-NOT-A-FULL-REWRITE-1).

Tests: 7 cycle_driver lib tests (10 total in the crate), headline = the 64k/17
falsifier — 65_536 mailboxes, 17 sealed transitions -> exactly 17 advance, the
other 65_519 byte-identical, one WAL write, ZERO dataset reads. Plus
one-WAL-write amortization, empty-sparse-set-advances-nobody, interim-defer,
StalePhase corruption, missing-owner-counted, run_cycle round-trip. clippy
(--features cycle-driver) exit 0, fmt clean; default (no-feature) build
unchanged. Durability leg stays the contract-probe fake (FakeWalSink) — control
loop closed, storage NOT proven (Ladybug rule); concrete LanceShardSink still
deferred.

Cargo.lock updated for the new optional supervisor->planner dep. Plan
`.claude/plans/cycle-loop-closure-driver-v1.md`; STATUS_BOARD D-MBX-A6-P4 ->
P4a+P4b Shipped (slice); LATEST_STATE prepended. Remaining: P4c (CognitiveWork
thought body + cast round-trip), P4d/P4e/P4f.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
… driver (seal→step→think→cast→recover)

Extends the P4a/P4b driver in `lance-graph-supervisor::cycle_driver` to the full
control loop. Still mints NO domain types — reuses StrategyOutcome,
owner_adapter::emit_bootstrap_intent, recover_and_apply, LandedSlot.

- P4c `run_cognitive_work(fleet, applied, writer, think)`: owners that just
  entered CognitiveWork run a PLUGGABLE thought seam
  `think(&Owner) -> Option<(StrategyOutcome, payload)>` (NOT the shader) and route
  the Outcome into the next cycle's casts via owner_adapter (bootstrap-sentinel
  rebind → write-on-behalf cast). No mailbox mutation (the step is P4b, post-seal).
  MailboxFleet gained a read accessor `owner()`.
- P4d wait-free: a completed owner casts + advances with no synchronous neighbour
  wait; an incomplete owner never blocks a completed one (structural — fire-and-
  forget cast, no per-owner barrier; the cycle boundary is the WAL-amortization
  barrier, not a neighbour wait). Proven by falsifier.
- P4e `recover_fleet(sink, fleet, ids, watermarks)`: composes recover_and_apply
  per owner over scan_sealed; replays only the pending tail above each owner's
  durable watermark (idempotent); keeps the earned watermark on a mid-owner error.
  FleetRecovery{total_applied, owners_recovered}.
- P4f sparse-routing scale probe: CountingFleet proves apply cost is O(dirty),
  not O(fleet) — 640 owner-resolutions over a 65_536-owner fleet.

11 cycle_driver lib tests green (--features cycle-driver): the 64k/17 headline +
P4c round-trip (a CognitiveWork Outcome cast in cycle N advances the owner one
further legal step in N+1) + P4d wait-free + P4e idempotence with a load-bearing-
watermark NEGATIVE CONTROL (watermark lost → acyclic re-drive StalePhase-stalls)
+ P4f O(dirty). clippy clean on cycle_driver.rs, fmt clean; default (no-feature)
supervisor build unchanged. The test FakeWalSink now stores landings for P4e.
Durability leg still the contract-probe fake — control loop closed, storage NOT
proven (Ladybug rule); concrete LanceShardSink deferred.

The MedCare first-thought loop is code-complete on the control side. Remaining
before a real first thought: (a) a concrete LanceShardSink (durability, gated on
crash falsifiers) and (b) a real CognitiveWork thought body plugged into the P4c
seam (the shader/StyleStrategy — exists). STATUS_BOARD D-MBX-A6-P4 → P4a–P4f
Shipped (slice); LATEST_STATE prepended.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
The P4c CognitiveWork thought body was a pluggable seam; wire the REAL
shader — the MUL cognitive gate — into it, minting no new decision logic.

- shade_owner(owner, qualia, mantissa, reliability): reads the owner's
  current phase, runs contract::mul::i4_eval::gate_decision_i4 (the i4
  TrustTexture x FlowState gate), lowers via KanbanColumn::advance_on_gate
  (Flow->forward, Block->Prune-where-legal, Hold->rest). Composes
  kanban_actor::mul_target for the driver. Returns a bootstrap-sentinel
  StrategyOutcome so owner_adapter rebinds + casts write-on-behalf; no
  mailbox mutated (the durable step is P4b, next cycle).
- run_cognitive_work_gated: the shader-wired form of run_cognitive_work;
  a caller-supplied read_gate extractor supplies (qualia, mantissa,
  reliability, payload) and the gate decides. Delegates to
  run_cognitive_work (single routing path).
- The qualia seam: MailboxSoaView does not yet expose qualia() (deferred);
  P4c is the first consumer, so the extractor bridges it without touching
  the trait — the MailboxSoa contract stays unchanged.

Tests: +3 (11 -> 14). shade_owner Flow/Block/Hold discriminate (three
distinct outputs), absorbing-column yields None (DAG respected), and a
gated round-trip proves a Flow-qualia owner casts + advances to Evaluation
next cycle while a Hold-qualia owner rests at CognitiveWork. clippy+fmt
clean; default build unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds a feature-gated cycle driver. It seals staged casts into one WAL cycle, applies sparse owner transitions, stages cognitive-work intents, evaluates MUL gates, and performs watermark-based fleet recovery. Documentation records the architecture and remaining concrete sink limitations.

Changes

Cycle loop closure

Layer / File(s) Summary
Architecture and integration contracts
.claude/board/*, .claude/plans/*
Documents the cycle-driver flow, sparse persistence rules, ownership boundaries, recovery requirements, and implementation status.
Cycle driver wiring and sparse application
crates/lance-graph-supervisor/Cargo.toml, crates/lance-graph-supervisor/src/lib.rs, crates/lance-graph-supervisor/src/cycle_driver.rs
Adds the feature, cycle contracts, cast collection, single-cycle sealing, and legal sparse owner transitions.
Cognitive work, MUL gating, and recovery
crates/lance-graph-supervisor/src/cycle_driver.rs
Adds intent staging, qualia-based gating, bootstrap handling, and watermark-based fleet recovery.
Cycle-driver validation
crates/lance-graph-supervisor/src/cycle_driver.rs
Adds fake persistence and tests for sparse execution, scale, gating, round trips, and recovery idempotence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BatchWriter
  participant CycleDriver
  participant WalSink
  participant MailboxFleet
  BatchWriter->>CycleDriver: Drain staged casts
  CycleDriver->>WalSink: Persist one sealed cycle
  WalSink-->>CycleDriver: Return sparse transitions
  CycleDriver->>MailboxFleet: Apply represented transitions
  MailboxFleet-->>CycleDriver: Return application counts
Loading

Possibly related PRs

Suggested reviewers: claude

Poem

I hop through cycles, neat and bright,
Seal sparse casts before the night.
Owners move when records say,
Quiet mailboxes stay in place.
MUL gates guide the thought’s next flight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the cycle loop-closure driver and its main sparse seal/apply and MUL-gate changes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c2134c1. Configure here.

.map_err(PersistError::Illegal)?;
applied.push(step);
advanced.insert(t.owner);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Deferred moves never advance again

Medium Severity

apply_sealed_transitions (and thus run_cycle) applies only one sealed transition per owner per cycle, deferring any subsequent ones. These durable, deferred transitions are not re-evaluated or applied in subsequent normal cycles, effectively stalling them until a recovery scan is performed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c2134c1. Configure here.

let casts = collect_casts(writer, frame.cycle, row_of);
let sealed = seal_cycle(sink, frame, casts).await?;
let applied = apply_sealed_transitions(fleet, &sealed)?;
Ok((sealed, applied))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Apply path never updates watermarks

High Severity

After apply_sealed_transitions updates an owner's phase, it doesn't advance the associated stream_position watermark. This means recover_fleet can attempt to replay already-applied moves, leading to a PersistError::StalePhase error because the owner's phase has already progressed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c2134c1. Configure here.

let casts = collect_casts(writer, frame.cycle, row_of);
let sealed = seal_cycle(sink, frame, casts).await?;
let applied = apply_sealed_transitions(fleet, &sealed)?;
Ok((sealed, applied))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Retry after seal loses casts

High Severity

collect_casts drains BatchWriter payloads before persist_cycle succeeds, and run_cycle always collects first. On a retryable PersistError::Write, a caller that re-invokes run_cycle gets an empty drain while intent rows remain on the writer board, so those casts never reach the WAL unless the caller kept the earlier Vec&lt;SweepSlot&gt; and retries seal_cycle alone.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c2134c1. Configure here.

Some(SweepSlot {
cycle,
stream_position: cast.0,
owner,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CastId breaks stream watermarks

Medium Severity

collect_casts sets SweepSlot::stream_position to the per-writer CastId, which resets when BatchWriter::new() is used. That violates the persist contract that stream_position stay monotonic per owner across cycles, so recovery can skip new landings when an old watermark dominates restarted cast ids.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c2134c1. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c2134c159e

ℹ️ 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".

Comment on lines +151 to +154
Some(SweepSlot {
cycle,
stream_position: cast.0,
owner,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use a restart-stable stream position

Do not use the in-memory CastId directly as the durable watermark key. BatchWriter::new() resets next_id to zero after a restart, while recover_and_apply skips every landing whose stream_position <= the previously persisted watermark. Consequently, casts sealed after a restart can reuse old positions and be silently skipped during the next recovery; the position must remain monotonic across writer instances, as required by SweepSlot's contract.

Useful? React with 👍 / 👎.

Comment on lines +275 to +276
let casts = collect_casts(writer, frame.cycle, row_of);
let sealed = seal_cycle(sink, frame, casts).await?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Retain drained casts when sealing fails

Preserve or return the collected casts when seal_cycle reports a retryable PersistError::Write. At this point collect_casts has drained pending_payloads, and seal_cycle consumes the only remaining payload copies, so a transient WAL failure drops every staged update; retrying run_cycle with the same writer sees an empty batch and can seal an empty cycle instead of the intended data.

Useful? React with 👍 / 👎.

Comment on lines +222 to +226
// Interim ≤1-per-owner: a later sealed move for an already-advanced owner
// waits for the next sealed horizon.
if advanced.contains(&t.owner) {
deferred += 1;
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Carry deferred transitions into the next horizon

Actually retain the transition when a second same-owner cast is deferred. The branch only increments a counter and discards the transition reference; AppliedCycle returns no deferred moves and run_cycle does not stage them again. Thus, when stacked casts contain sequential moves for one owner, the later durable move never executes during normal operation despite the comment claiming it waits for the next sealed horizon.

Useful? React with 👍 / 👎.

Comment on lines +396 to +399
run_cognitive_work(fleet, applied, writer, |owner| {
let (qualia, mantissa, reliability, payload) = read_gate(owner)?;
let outcome = shade_owner(owner, &qualia, mantissa, reliability)?;
Some((outcome, payload))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reschedule owners when the gate holds

Requeue an owner when shade_owner returns None for Hold or for a blocked CognitiveWork phase. run_cognitive_work only evaluates owners present in AppliedCycle because they just entered CognitiveWork; casting nothing means that owner is absent from every subsequent cycle and the gate is never evaluated again, so common Hold decisions permanently strand the mailbox instead of resting for one cycle and re-evaluating.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
crates/lance-graph-supervisor/src/cycle_driver.rs (3)

797-832: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for the OwnerMismatch branch.

The tests cover StalePhase and the missing-owner count. The OwnerMismatch guard at lines 233-238 and the Illegal mapping at lines 246-248 have no test. persist_cycle rejects cross-owner moves at seal time, so this guard is only reachable through a directly constructed SealedCycle. That is exactly what a test can build.

💚 Proposed test
+    // ── P4b: a cross-owner sealed move is rejected (defence in depth) ──────────
+    #[test]
+    fn p4b_cross_owner_move_is_an_owner_mismatch() {
+        let mut fleet: HashMap<MailboxId, FakeOwner> =
+            HashMap::from([(7, FakeOwner::at(7, KanbanColumn::Planning))]);
+        let sealed = SealedCycle {
+            version: DatasetVersion(1),
+            transitions: vec![SealedTransition {
+                stream_position: 0,
+                owner: 7,
+                // the move claims mailbox 8 while landing on owner 7
+                mv: mv(8, KanbanColumn::Planning, KanbanColumn::CognitiveWork),
+            }],
+        };
+        assert!(matches!(
+            apply_sealed_transitions(&mut fleet, &sealed),
+            Err(PersistError::OwnerMismatch { .. })
+        ));
+    }

Based on coding guidelines: "Add Rust unit tests alongside implementations via #[cfg(test)] modules; prefer focused scenarios over broad integration tests".

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

In `@crates/lance-graph-supervisor/src/cycle_driver.rs` around lines 797 - 832,
Add a focused #[tokio::test] alongside the existing apply_sealed_transitions
tests that constructs a SealedCycle containing a directly created
SealedTransition whose owner differs from the move’s embedded owner, then assert
apply_sealed_transitions returns PersistError::OwnerMismatch. Also add coverage
for the Illegal mapping if it is a separate reachable branch, using the existing
test helpers and error-matching style without changing production behavior.

Source: Coding guidelines


356-377: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move the gate inference onto the carrier object.

shade_owner is a free function that receives the carrier (owner) and its cognitive state (qualia, mantissa) as separate arguments. Put the inference on the carrier instead, through an extension trait with a blanket impl. The call site then reads owner.shade(&qualia, mantissa, reliability). When MailboxSoaView::qualia() lands, the trait method can drop the extra arguments without changing the call shape.

♻️ Proposed extension trait
+/// Carrier-side MUL gate inference. Blanket-implemented for every
+/// `MailboxSoaOwner`; collapses to `shade(reliability)` once
+/// `MailboxSoaView::qualia()` lands.
+pub trait ShadeOwner: MailboxSoaOwner {
+    fn shade(
+        &self,
+        qualia: &QualiaI4_16D,
+        mantissa: i8,
+        reliability: f32,
+    ) -> Option<StrategyOutcome> {
+        let phase = self.phase();
+        let to = phase.advance_on_gate(&gate_decision_i4(qualia, mantissa))?;
+        Some(StrategyOutcome {
+            reliability,
+            intended_move: Some(KanbanMove {
+                mailbox: 0,
+                from: phase,
+                to,
+                witness_chain_position: 0,
+                exec: ExecTarget::Native,
+            }),
+        })
+    }
+}
+impl<O: MailboxSoaOwner> ShadeOwner for O {}

Then run_cognitive_work_gated calls owner.shade(&qualia, mantissa, reliability)?.

Based on coding guidelines: "Keep cognitive state and inference behavior on the carrier object: prefer methods such as trajectory.resolve() over free functions that separately receive the carrier state."

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

In `@crates/lance-graph-supervisor/src/cycle_driver.rs` around lines 356 - 377,
Move the logic from the free function shade_owner onto the carrier via an
extension trait with a blanket impl for MailboxSoaOwner. Define the trait method
shade and have it perform the existing gate_decision_i4, phase advancement, and
StrategyOutcome construction; update run_cognitive_work_gated to call
owner.shade(&qualia, mantissa, reliability)? while preserving the current
sentinel move behavior.

Source: Coding guidelines


433-433: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider a version floor for scan_sealed.

recover_fleet always calls scan_sealed(None), so it materializes the entire sealed history into memory on every pass. The history grows with every cycle, so recovery time and peak memory grow without bound. Recovery becomes slower as the system runs longer.

Accept an optional from: Option<DatasetVersion> floor derived from the lowest persisted watermark, or plan a WAL truncation point before the concrete LanceShardSink lands.

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

In `@crates/lance-graph-supervisor/src/cycle_driver.rs` at line 433, Update
recover_fleet and the scan_sealed call to avoid materializing the entire sealed
history: derive the lowest persisted watermark as a DatasetVersion floor and
pass it through the optional from parameter. Ensure recovery still includes
every sealed entry needed from that floor onward; if the sink cannot support
this yet, establish a WAL truncation point before introducing LanceShardSink.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/board/INTEGRATION_PLANS.md:
- Around line 1-35: Synchronize the plan metadata with the shipped P4a–P4f
implementation: in .claude/board/INTEGRATION_PLANS.md lines 1-35, mark the entry
historical or implemented and link the feature-gated driver; in
.claude/plans/cycle-loop-closure-driver-v1.md lines 3-13, replace the
planned/unshipped status, lines 42-52, mark the zero-production-caller statement
as historical, and lines 345-347, clarify that status discipline distinguishes
design history from implementation status.

In @.claude/plans/persistence-cycle-wal-bootstrap-v1.md:
- Line 269: Align the section numbering in the persistence-cycle document:
update the headings currently labeled “2.1” and “2.2” to “3.1” and “3.2” to
match the reference at §3.1, or consistently change the reference back to
§2.1/§2.2. Ensure all related cross-references use the same numbering scheme.
- Line 80: Update every diagram-only Markdown fence to declare the text language
for MD040 compliance: .claude/plans/persistence-cycle-wal-bootstrap-v1.md lines
80, 95, 122, 154, and 165, plus .claude/plans/cycle-loop-closure-driver-v1.md
lines 94 and 260. Add text to each opening fence without changing the diagram
contents.

In `@crates/lance-graph-supervisor/src/cycle_driver.rs`:
- Around line 232-251: Update apply_sealed_transitions to return the
already-built AppliedCycle together with PersistError on every OwnerMismatch,
StalePhase, or Illegal early return, constructing it from applied, deferred, and
missing. Align the result shape with persist_sink::recover_and_apply, then
update run_cycle to unpack/map the error tuple while preserving the recovered
applied prefix for callers to persist.
- Around line 433-457: Update the recovery flow around recover_fleet and
recover_and_apply to partition sealed landings by owner once before iterating
fleet_ids, then pass each owner’s grouped landings into recover_and_apply
instead of the full sealed slice. Preserve the existing per-owner ordering,
watermark updates, partial-error handling, and recovery counters.
- Around line 128-161: Document on collect_casts or its surrounding API that the
same BatchWriter instance must be reused across cycles, because
SweepSlot::stream_position derives from cast.0 and must remain monotonic per
owner for durable recovery watermarks; clarify that drain_pending_payloads only
clears staged payloads and does not permit recreating the writer with a reset
counter.

---

Nitpick comments:
In `@crates/lance-graph-supervisor/src/cycle_driver.rs`:
- Around line 797-832: Add a focused #[tokio::test] alongside the existing
apply_sealed_transitions tests that constructs a SealedCycle containing a
directly created SealedTransition whose owner differs from the move’s embedded
owner, then assert apply_sealed_transitions returns PersistError::OwnerMismatch.
Also add coverage for the Illegal mapping if it is a separate reachable branch,
using the existing test helpers and error-matching style without changing
production behavior.
- Around line 356-377: Move the logic from the free function shade_owner onto
the carrier via an extension trait with a blanket impl for MailboxSoaOwner.
Define the trait method shade and have it perform the existing gate_decision_i4,
phase advancement, and StrategyOutcome construction; update
run_cognitive_work_gated to call owner.shade(&qualia, mantissa, reliability)?
while preserving the current sentinel move behavior.
- Line 433: Update recover_fleet and the scan_sealed call to avoid materializing
the entire sealed history: derive the lowest persisted watermark as a
DatasetVersion floor and pass it through the optional from parameter. Ensure
recovery still includes every sealed entry needed from that floor onward; if the
sink cannot support this yet, establish a WAL truncation point before
introducing LanceShardSink.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ed2db7f4-0d99-440f-92d8-9a70ab441df0

📥 Commits

Reviewing files that changed from the base of the PR and between 18b5b65 and c2134c1.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • .claude/board/EPIPHANIES.md
  • .claude/board/INTEGRATION_PLANS.md
  • .claude/board/LATEST_STATE.md
  • .claude/board/STATUS_BOARD.md
  • .claude/plans/cycle-loop-closure-driver-v1.md
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md
  • crates/lance-graph-supervisor/Cargo.toml
  • crates/lance-graph-supervisor/src/cycle_driver.rs
  • crates/lance-graph-supervisor/src/lib.rs

Comment on lines +1 to +35
## 2026-08-02 — cycle-loop-closure-driver v1 — PLANNED / CONJECTURE (the seam that makes persist_sink load-bearing at 64k) — main thread

**Plan:** `.claude/plans/cycle-loop-closure-driver-v1.md`
The loop-closure driver: the missing seam that turns the merged `persist_sink`
cycle/WAL bootstrap into a running loop at 64k concurrency. Today
`persist_sink::{persist_cycle, WalSink, versions}` has **zero production
callers** — the loop is open. The driver closes: owners think over the sealed
`Vn`; owners that produce material updates emit **sparse** fire-and-forget
intents; the planner collects/coalesces/freezes one cycle (one WAL, `Vn+1`) and
exposes the **sealed paired-transition set**; the supervisor applies **ONLY the
sealed sparse transitions** (each represented owner advances one legal step;
**all unrepresented owners stay byte-identical**); owners entering CognitiveWork
run the thought and cast the next intent via `owner_adapter`. **Correctness
pivot (corrects the earlier draft): a `DatasetVersion` is global knowledge, NOT
permission to advance every mailbox** — the earlier "fan `on_version` across the
whole fleet" model violated the sparse-cycle ruling and is removed. The sealed
transitions are applied INLINE by the writer (no dataset re-read; NOT 64k async
`LanceVersionScheduler::drive_once`, which is the reader-that-did-not-write
variant). Interim rule: ≤1 durable phase transition per owner per sealed cycle.
Mints NO new types — composes `KanbanMove`/`DatasetVersion`/`SweepSlot`/
`BatchWriter`/`NextPhaseScheduler`/`KanbanActor`/`owner_adapter`/
`recover_and_apply`. Deliverables D-MBX-A6-P4a (drain+seal) → P4b (apply sealed
sparse set; falsifier: 64k mailboxes / 17 sealed transitions → exactly 17
advance, rest byte-identical) → P4c (CognitiveWork+cast round-trip) → P4d
(wait-free emit) → P4e (recovery composition) → P4f (sparse-routing scale
16k/64k, W2a-gated), each probe-first. Home: `lance-graph-supervisor` (structural
fleet owner; new one-way planner path-dep, verified acyclic) with a planner
fallback. Also carries the D-MBX crate-responsibility map (§9), the
adjacent-crates doctrine for symbiont / rs-graph-llm / ogar-* (§10), and the
subagent anti-drift guardrail (§11). HONEST: the CONTROL loop closes; the
durability leg stays the contract-probe fake until the concrete `LanceShardSink`
lands. Board-as-tenant (D-V3-W2a) is a SCALE gate, not a control-loop blocker.
Companion to `persistence-cycle-wal-bootstrap-v1.md` §2 sparse-delta ruling
(EPIPHANIES `E-COMPLETE-CYCLE-IS-PHYSICALLY-SPARSE-NOT-A-FULL-REWRITE-1`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Synchronize the design-plan status with the shipped implementation.

Both documents retain pre-implementation wording while the current board records P4a–P4f as shipped.

  • .claude/board/INTEGRATION_PLANS.md#L1-L35: mark the entry historical or implemented, and link the feature-gated driver.
  • .claude/plans/cycle-loop-closure-driver-v1.md#L3-L13: update the planned/unshipped status.
  • .claude/plans/cycle-loop-closure-driver-v1.md#L42-L52: mark the zero-caller statement as historical.
  • .claude/plans/cycle-loop-closure-driver-v1.md#L345-L347: update the status discipline to distinguish design history from implementation status.
📍 Affects 2 files
  • .claude/board/INTEGRATION_PLANS.md#L1-L35 (this comment)
  • .claude/plans/cycle-loop-closure-driver-v1.md#L3-L13
  • .claude/plans/cycle-loop-closure-driver-v1.md#L42-L52
  • .claude/plans/cycle-loop-closure-driver-v1.md#L345-L347
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/board/INTEGRATION_PLANS.md around lines 1 - 35, Synchronize the plan
metadata with the shipped P4a–P4f implementation: in
.claude/board/INTEGRATION_PLANS.md lines 1-35, mark the entry historical or
implemented and link the feature-gated driver; in
.claude/plans/cycle-loop-closure-driver-v1.md lines 3-13, replace the
planned/unshipped status, lines 42-52, mark the zero-production-caller statement
as historical, and lines 345-347, clarify that status discipline distinguishes
design history from implementation status.

**"One complete cycle image" must NEVER be read as serializing every row merely
because every participant belonged to the cycle.** The load-bearing distinction:

```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make all Markdown diagram fences explicit.

The same MD040 lint issue affects diagram-only fences in both plans.

  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L80-L80: add text to the opening fence.
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L95-L95: add text to the opening fence.
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L122-L122: add text to the opening fence.
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L154-L154: add text to the opening fence.
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L165-L165: add text to the opening fence.
  • .claude/plans/cycle-loop-closure-driver-v1.md#L94-L94: add text to the opening fence.
  • .claude/plans/cycle-loop-closure-driver-v1.md#L260-L260: add text to the opening fence.
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 80-80: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

📍 Affects 2 files
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L80-L80 (this comment)
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L95-L95
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L122-L122
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L154-L154
  • .claude/plans/persistence-cycle-wal-bootstrap-v1.md#L165-L165
  • .claude/plans/cycle-loop-closure-driver-v1.md#L94-L94
  • .claude/plans/cycle-loop-closure-driver-v1.md#L260-L260
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/plans/persistence-cycle-wal-bootstrap-v1.md at line 80, Update every
diagram-only Markdown fence to declare the text language for MD040 compliance:
.claude/plans/persistence-cycle-wal-bootstrap-v1.md lines 80, 95, 122, 154, and
165, plus .claude/plans/cycle-loop-closure-driver-v1.md lines 94 and 260. Add
text to each opening fence without changing the diagram contents.

Source: Linters/SAST tools

> The version table performs **vertical** frame succession and lookup **only**.
> It does **not** perform horizontal causal ordering — that is the horizontal
> dimension's job (§2.1). Conflating the two is the error this section forecloses.
> dimension's job (§3.1). Conflating the two is the error this section forecloses.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the section references resolve.

The updated reference at Line 269 points to §3.1, but the corresponding headings remain ### 2.1 and ### 2.2. Rename those headings to 3.1 and 3.2, or keep all references at 2.1 and 2.2. The current mixed numbering breaks navigation.

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

In @.claude/plans/persistence-cycle-wal-bootstrap-v1.md at line 269, Align the
section numbering in the persistence-cycle document: update the headings
currently labeled “2.1” and “2.2” to “3.1” and “3.2” to match the reference at
§3.1, or consistently change the reference back to §2.1/§2.2. Ensure all related
cross-references use the same numbering scheme.

Comment thread crates/lance-graph-supervisor/src/cycle_driver.rs
Comment thread crates/lance-graph-supervisor/src/cycle_driver.rs
Comment thread crates/lance-graph-supervisor/src/cycle_driver.rs
…s + scope honesty

Grain-of-salt review of PR #879; each finding verified against code before
acting. All accepted items were real defects:

- Retry-safe seal: seal_cycle -> Result<SealedCycle, Box<SealFailure>>; a
  WAL failure returns the complete frozen cast set byte-identical for
  retry (previously the drained cycle was simply lost). Falsifier: failed
  commit -> zero owner mutation -> same-cycle retry -> one version.
- Restart-stable stream positions: collect_casts now takes the caller's
  durable position_base cursor; SealedCycle.next_position_base carries it
  forward (computed over ALL slots). Raw CastId was the P3d-documented
  'cast_id is provenance only' trap: a reconstructed BatchWriter restarts
  at 0 and recover_and_apply silently skips positions <= watermark.
  Restart falsifier pins the exact failure mode.
- Watermark-coupled apply: apply_sealed_transitions advances the per-owner
  recovery watermark WITH the phase (one rule shared with recovery); a
  crash after normal apply no longer replays into a StalePhase stall.
- <=1-move/owner enforced PRE-seal: extras (same cast or later casts;
  also fixes the silent moves.first() truncation) return as HeldIntent,
  re-staged via restage_held into a future cycle. Sealed set == applied
  set, so recovery and normal operation agree; the old seal-then-defer
  counter (which discarded durable moves) is demoted to defence-in-depth.
- Mid-apply errors return the applied prefix Err((partial, cause)),
  mirroring recover_and_apply.
- Hold = reschedule, never strand: CognitiveWorkOutcome.held_owners +
  run_cognitive_work[_gated]_over re-poll; falsifier wakes a Held owner.
- recover_fleet partitions sealed history once (O(history), not
  O(fleet x history)).
- Scope honesty: module honesty ledger (control-loop contract proven;
  actor-owned production wiring NOT proven — MailboxFleet HashMap is the
  probe/registry fleet, KanbanActor bridging open; shader-driver/SoA
  thought NOT proven — the MUL gate is real, inputs extractor-fed;
  durability fake). P4d reworded to wait-free-at-the-cast-boundary with a
  two-represented-owners falsifier (A unfinished, B casts regardless).

Declined: routing P4b through KanbanActor mailboxes — contradicts the
ratified writer-fires-inline sparse ruling; the honesty half is taken in
docs instead.

19 lib tests green (was 14); clippy + fmt clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
@AdaWorldAPI AdaWorldAPI changed the title D-MBX-A6-P4: cycle loop-closure driver + the real MUL gate plugged into the thinking seam D-MBX-A6-P4: cycle loop-closure driver — sparse seal/apply + MUL-gate thought seam (control-loop contract) Aug 2, 2026
@AdaWorldAPI
AdaWorldAPI merged commit 130d7b2 into main Aug 2, 2026
6 checks passed
AdaWorldAPI pushed a commit that referenced this pull request Aug 2, 2026
…ive plan

Six-agent read-only investigation + unshallowed git history (5 grafted
roots -> 4162 commits) established that lance-graph holds TWO MedCare
lineages, not one incomplete runtime:

- LIVE (consumer-pull): MedCare-rs medcare-bridge -> vendored
  lance-graph-ogar -> MedcareBridge = UnifiedBridge<HealthcarePort> ->
  OGAR canonical Health codebook 0x0901..0x090C. Bridge migration
  COMPLETED at ddb6c84 (2026-06-21); deprecated alias only. Contract
  codebook mirror verified in sync slot-for-slot; the 7-alias-vs-12-slot
  gap is intentional (harvest mints, no OGIT entity).
- DEAD (host-side scaffold): modules/medcare/manifest.yaml ->
  CallcenterSupervisor -> MedcareConsumerActor, frozen since birth
  2026-05-13. Manifest compile-time parsed but runtime-orphaned (one
  caller: a test); entity codes / action_capabilities / message_type
  discarded pre-codegen; medcare_policy nonexistent; StubConsumerActor
  hard-coded; Dispatch rejected before any child; MedCareActor /
  MedCareMessage exist in NEITHER repository.

New ACTIVE plan medcare-consumer-pull-thinking-proof-v1: prove one real
medical thought over the live consumer-pull path (HealthcarePort
classids -> cognitive-shader-driver + real MailboxSoA -> owner_adapter
cast -> the #879 sparse cycle loop), falsifiers F1-F4 including the
currently-absent Healthcare fail-closed unknown-actor test. ogar-obo
(MONDO/HPO/Uberon/PATO, verified real, zero consumer edges) is an
optional slice. Older MedCare plans classified (completed / dormant-
decision-required / stale-but-unmarked); open decisions carried, not
blocked on (OQ-2 retention 2190/3650, Ueberweisung/Anamnese canon gap,
dead-lineage retire-vs-revive, .grok lineage, NoopAuditSink default).

Documentation-only: no Rust, no tests, no manifests changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
AdaWorldAPI pushed a commit that referenced this pull request Aug 2, 2026
…ive plan

Six-agent read-only investigation + unshallowed git history (5 grafted
roots -> 4162 commits) established that lance-graph holds TWO MedCare
lineages, not one incomplete runtime:

- LIVE (consumer-pull): MedCare-rs medcare-bridge -> vendored
  lance-graph-ogar -> MedcareBridge = UnifiedBridge<HealthcarePort> ->
  OGAR canonical Health codebook 0x0901..0x090C. Bridge migration
  COMPLETED at ddb6c84 (2026-06-21); deprecated alias only. Contract
  codebook mirror verified in sync slot-for-slot; the 7-alias-vs-12-slot
  gap is intentional (harvest mints, no OGIT entity).
- DEAD (host-side scaffold): modules/medcare/manifest.yaml ->
  CallcenterSupervisor -> MedcareConsumerActor, frozen since birth
  2026-05-13. Manifest compile-time parsed but runtime-orphaned (one
  caller: a test); entity codes / action_capabilities / message_type
  discarded pre-codegen; medcare_policy nonexistent; StubConsumerActor
  hard-coded; Dispatch rejected before any child; MedCareActor /
  MedCareMessage exist in NEITHER repository.

New ACTIVE plan medcare-consumer-pull-thinking-proof-v1: prove one real
medical thought over the live consumer-pull path (HealthcarePort
classids -> cognitive-shader-driver + real MailboxSoA -> owner_adapter
cast -> the #879 sparse cycle loop), falsifiers F1-F4 including the
currently-absent Healthcare fail-closed unknown-actor test. ogar-obo
(MONDO/HPO/Uberon/PATO, verified real, zero consumer edges) is an
optional slice. Older MedCare plans classified (completed / dormant-
decision-required / stale-but-unmarked); open decisions carried, not
blocked on (OQ-2 retention 2190/3650, Ueberweisung/Anamnese canon gap,
dead-lineage retire-vs-revive, .grok lineage, NoopAuditSink default).

Documentation-only: no Rust, no tests, no manifests changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
AdaWorldAPI pushed a commit that referenced this pull request Aug 2, 2026
…t to deterministic regeneration; re-home the proof to the live consumer

Round-2 grain-of-salt realignment (operator-ruled), post-#879-merge.

1) Pre-commit failure contract. The authoritative rule is deterministic
   regeneration, not retained-batch retry:

     sealed Vn + unchanged Kanban task + deterministic computation
       = the same provisional intent on the next sweep

   Commit fails before Vn+1 exists -> publish nothing, mutate no owner,
   advance no watermark, discard provisional slots / held moves /
   planning results, rerun the unchanged task from Vn.

   - SealFailure{casts} reclassified: OPTIONAL retry cache /
     implementation convenience only — never the correctness mechanism,
     never a provisional-planning ledger; dropping it is always sound.
   - recover_fleet doc-pinned as COMMITTED-HISTORY recovery ONLY
     (Vn+1 exists, application/restart interrupted); explicitly
     separated from ordinary pre-commit write failure — no shared state.
   - HeldIntent doc-pinned as within-success scheduling convenience,
     discarded on a failed seal, regenerated by the next thought pass.
   - NEW authoritative falsifier
     pre_commit_failure_discards_everything_and_regenerates_from_vn:
     derive cycle C deterministically from Vn, inject commit failure,
     DROP the SealFailure cache, assert no version/phase/watermark
     change, rerun the unchanged task from Vn, assert the same SEMANTIC
     sparse cycle regenerates, allow commit, assert exactly one Vn+1 and
     one advance per represented owner. Object identity of the first
     heap batch deliberately not asserted.
   - The prior byte-identical-retry test demoted to an optional-cache
     probe (secondary, convenience path).

   20 cycle_driver tests green; clippy + fmt clean. Latency figures in
   review prose are operator-provided measurements, not
   workspace-reproduced benchmarks; their values are not restated.

2) Proof re-homed (medcare-consumer-pull-thinking-proof-v1 section 4):
   primary home = MedCare-rs (the live composition root); lance-graph
   contributes only genuinely-missing GENERIC seams — no MedCare-shaped
   host adapter here (that would rebuild the dead lineage in miniature).
   Hard requirement: the proof must invoke the existing
   cognitive-shader-driver + MailboxSoA operational unit; shade_owner
   only as the driver's existing downstream gate, never a substitute.
   Trace-and-report obligation added; F1 strengthened to a
   discriminating driver outcome.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCGhDYoQBXs3poaR7sFuqp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants