Skip to content

S3 IN-leg driver — version tick → owner forward-arc advance (no-op suppressed)#579

Merged
AdaWorldAPI merged 2 commits into
mainfrom
claude/jirak-math-theorems-harvest-rfii13
Jun 21, 2026
Merged

S3 IN-leg driver — version tick → owner forward-arc advance (no-op suppressed)#579
AdaWorldAPI merged 2 commits into
mainfrom
claude/jirak-math-theorems-harvest-rfii13

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

What

The actor-side half of S3 (the IN-direction Rubicon seam,
E-SUBSTRATE-IS-THE-SCHEDULER), mirroring the S2 atomic MulAdvance
pattern in lance-graph-supervisor::kanban_actor (feature supervisor).

A substrate version tick → next legal KanbanMove → owner applies it →
no-op ticks suppressed. The OUT-leg already had the owner-advance (#576),
delivery edge (#577), and S2 MUL driver (#578); this is the IN-leg driver.

How

  • KanbanMsg::Tick { at, reply } — the atomic in-actor realization of
    the contract's NextPhaseScheduler: a version tick advances the owner along
    the Rubicon forward arc (phase().next_phases().first()) in ONE serialized
    message, reading the phase at the instant of mutation. Absorbing column
    (Commit/Prune) → None: the no-op tick is suppressed, not an error.
    No error variant — the forward arc is legal by construction, so the infallible
    advance_phase is correct here. This applies the codex feat(supervisor): S2 driver — MUL gate → owner advance (drive_mul_advance) #578 atomicity
    lesson
    to the IN-leg (no stale-phase TOCTOU window).
  • drive_version_tick(actor, at) — thin async wrapper over Tick.
  • drive_scheduled_tick(scheduler, view, at, exec, actor) — generic consumer
    that drives the existing VersionScheduler trait ("propose, don't
    dispose": the scheduler proposes from a view, the owner disposes via
    Advance, None suppresses). For custom policies (version-delta gating,
    Plan/Prune over the forward arc, batching) that read a richer view than the
    owner computes internally; documented as advisory — the proposal is
    computed outside the owner message, so it may relay a typed Illegal rather
    than silently corrupt.

No new contract types — composes the existing VersionScheduler /
NextPhaseScheduler / MailboxSoaView / MailboxSoaOwner surface.

Tests (+3, light — no lance/datafusion/disk)

cargo test -p lance-graph-supervisor --features supervisor --lib12 passed / 0 failed

  • version_tick_advances_forward_arc_then_suppresses_at_absorbing — Planning→CognitiveWork→Evaluation→Commit, then the next tick is a suppressed no-op (phase stays Commit).
  • concurrent_version_ticks_serialize_along_the_arc — two concurrent ticks chain along the arc, neither lost, no stale-phase collision.
  • custom_scheduler_proposes_and_owner_disposes — drives NextPhaseScheduler propose→dispose and suppresses an absorbing proposal.

clippy clean (no supervisor-crate warnings — only pre-existing ontology/callcenter), fmt clean.

Remaining S3 (lance/disk-gated, not in this PR)

Wire the LIVE source — lance-graph::graph::scheduler::LanceVersionScheduler::drive_at_latest
over a real VersionedGraph::versions() — to feed at into drive_version_tick
(or a custom policy into drive_scheduled_tick). The apply + no-op-suppress loop
is done; only the live versions() poll remains.

Board hygiene

  • .claude/plans/capstone-out-leg-wiring-v1.md — S3 status annotated (apply+suppress driver shipped; remaining = live source).
  • .claude/board/AGENT_LOG.md — cont.³⁴ prepended.

🤖 Generated with Claude Code


Generated by Claude Code

… advance

The actor-side half of S3 (E-SUBSTRATE-IS-THE-SCHEDULER), mirroring the S2
atomic MulAdvance pattern in lance-graph-supervisor::kanban_actor:

- KanbanMsg::Tick { at, reply } — atomic in-actor realization of the contract's
  NextPhaseScheduler: a substrate version tick advances the owner along the
  Rubicon forward arc (phase().next_phases().first()) in ONE serialized message,
  reading the phase at the instant of mutation. Absorbing column -> None: the
  no-op tick is suppressed (forward arc is legal by construction, so the
  infallible advance_phase is used; no error path). This applies the codex #578
  atomicity lesson to the IN-leg.
- drive_version_tick(actor, at) — thin async wrapper over Tick.
- drive_scheduled_tick(scheduler, view, at, exec, actor) — generic consumer that
  drives the EXISTING VersionScheduler trait ("propose, don't dispose": the
  scheduler proposes from a view, the owner disposes via Advance, None
  suppresses). For custom policies that read a richer view than the owner
  computes internally; documented as advisory (proposal computed outside the
  owner message, so it may relay a typed Illegal rather than corrupt).

+3 tests (12 passed/0 failed under --features supervisor --lib): forward-arc
chain then suppress at absorbing; two concurrent ticks serialize along the arc
(no stale-phase collision); generic consumer drives NextPhaseScheduler
propose->dispose + suppresses an absorbing proposal. clippy + fmt clean; light
build (no lance/datafusion, no disk gate).

Remaining S3 (lance/disk-gated): wire the LIVE
LanceVersionScheduler::drive_at_latest over a real VersionedGraph::versions() to
feed `at`. The apply + no-op-suppress loop is done; only the live versions()
poll remains.

Board hygiene: plan S3 status annotated; AGENT_LOG cont.34 prepended.

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

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@AdaWorldAPI, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 18 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cbda5954-6b73-40a7-8ca6-feafbc5f487c

📥 Commits

Reviewing files that changed from the base of the PR and between c29b580 and fd1d58f.

📒 Files selected for processing (3)
  • .claude/board/AGENT_LOG.md
  • .claude/plans/capstone-out-leg-wiring-v1.md
  • crates/lance-graph-supervisor/src/kanban_actor.rs

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 and usage tips.

@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: 2f5ed3d0f9

ℹ️ 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 +325 to +327
let inner = ractor::call!(actor, |reply| KanbanMsg::Advance {
to: proposed.to,
reply

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve non-Native exec targets in scheduled moves

When callers use drive_scheduled_tick with ExecTarget::Jit, SurrealQl, or Elixir, scheduler.on_version(...) stamps that backend onto the proposed KanbanMove, but this RPC sends only proposed.to and returns the owner-generated move instead. The current owner implementations hard-code ExecTarget::Native, so the scheduled move is reported/routed as Native even though the scheduler selected a different backend.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in fd1d58ff. drive_scheduled_tick now keeps the owner's emitted move (authoritative phase transition, witness position, libet anchor — from the real mutation) but overlays proposed.exec, so a Jit/SurrealQl/Elixir selection survives instead of being flattened to the owner's Native default. Regression test scheduled_tick_preserves_non_native_exec_target asserts all three non-Native targets round-trip (13 tests green, clippy + fmt clean).

(Note: the atomic drive_version_tick/Tick path is unaffected — it has no scheduler choosing a backend, so the owner's Native is correct there.)


Generated by Claude Code

…ck (codex #579)

The scheduler stamps the chosen backend onto proposed.exec, but the consumer
sent only proposed.to and returned the owner's move — and owners default to
ExecTarget::Native, so a Jit/SurrealQl/Elixir selection was silently reported
and routed as Native.

Fix: keep the owner's emitted move (authoritative phase transition, witness
position, libet anchor from the real mutation) but overlay proposed.exec — the
backend routing tag is the policy's decision, which the owner can't make.

+1 test (13 total green): scheduled_tick_preserves_non_native_exec_target
asserts Jit/SurrealQl/Elixir survive round-trip. clippy + fmt clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
@AdaWorldAPI AdaWorldAPI merged commit 98d5d2f into main Jun 21, 2026
6 checks passed
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