Skip to content

graph-flow: KanbanSessionStorage behind new kanban feature — the M25 replayable handler (D-V3-W3b)#21

Merged
AdaWorldAPI merged 2 commits into
mainfrom
claude/v3-substrate-migration-review-o0yoxv
Jul 2, 2026
Merged

graph-flow: KanbanSessionStorage behind new kanban feature — the M25 replayable handler (D-V3-W3b)#21
AdaWorldAPI merged 2 commits into
mainfrom
claude/v3-substrate-migration-review-o0yoxv

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

The orchestration lane's keystone: every graph-flow execution becomes replayable from the kanban board — graph-flow's persisted-cursor state model + the V3 board's WAL, composed (the answer to the queue-vs-state debate: the board is both).

What

  • New optional cargo feature kanban on graph-flow, enabling path deps on the sibling graph-flow-kanban envelope crate + lance-graph-contract (graph-flow is the composer; the envelope crate stays contract-only).
  • storage_kanban::KanbanSessionStorage — implements SessionStorage: every save() upserts the Session snapshot AND appends real lance_graph_contract::kanban::KanbanMoves derived from the observed transition. The storage carries the MailboxId (acts on behalf of one mailbox); the Session carries nothing (DTO purity).
  • V1 Rubicon mapping (doc-pinned, revisable, tests pin it): first save → Planning; current_task_id changed → CognitiveWork; waiting/paused → Evaluation; completed → Commit; error → Prune. save_with_status() for precise terminal columns; moves() / replay() expose the WAL trail. witness_chain_position = log length (monotonic).
  • Envelope note: KanbanPlanEnvelope is used as the state carrier; moves are recorded directly to its public fields rather than through its Rubicon FSM gate (the gate is for live advancement, not post-hoc journaling — documented inline).

Gate (M25) — GREEN

m25_kill_mid_graph_replay_resumes_without_repeats_or_gaps: 3-task linear graph, runner dropped after task 2 ("kill"), fresh runner over an identically-built graph resumes from the same storage, completes with trace [task1, task2, task3] — no repeats, no gaps — and the recorded move-log column sequence matches the pinned [CognitiveWork, Evaluation, Commit]. Plus mapping-per-status and monotonic-witness unit tests.

Verification note

In-repo cargo test -p graph-flow is blocked by the pre-existing AdaWorldAPI/burn submodule 403 (no Cargo.lock in this repo forces full-workspace resolution through episodic-arc-task/surreal-lance; stash-verified identical failure on the clean branch). Verified instead in an isolated two-crate workspace with the orthogonal surreal-lance edge stripped: 16 + 59 tests green, feature on. CI environments with normal egress resolve the real graph.

Companion lance-graph PR (same branch name): AdaWorldAPI/lance-graph#634 (W2b real-owner probe + W2a LAYOUT-GATED ruling + boards).

🤖 Generated with Claude Code

https://claude.ai/code/session_01MLBnPuScZy6w9di2QEjsXM


Generated by Claude Code

claude added 2 commits July 2, 2026 12:16
…096 (W2e input)

4-task no-op linear chain, InMemorySessionStorage, both FlowRunner paths.
Steady-state: ~408-471 ns/step (continue_and_execute) vs ~512-538 ns/step
(stepwise; the ~80-100 ns delta = per-step storage get+save round-trip).
Note: workspace-root builds hit a 403 wall on the AdaWorldAPI/burn git
submodule via surreal-lance's optional deps; file runs via an isolated
path-dep crate until network/lockfile lands (header explains).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MLBnPuScZy6w9di2QEjsXM
…the M25 replayable-handler storage (D-V3-W3b)

Snapshot upsert + append-only real-KanbanMove log per save; V1 Rubicon
mapping (first-save->Planning, task-change->CognitiveWork,
waiting->Evaluation, completed->Commit, error->Prune; doc-pinned,
revisable); save_with_status() for precise terminal columns; moves()/
replay() expose the WAL trail. The envelope crate is the carrier
(graph-flow composes it); moves are recorded directly (the envelope's
Rubicon FSM gate is for live advancement, not post-hoc journaling —
documented inline). witness_chain_position = log length (monotonic).

Gate green (M25): m25_kill_mid_graph_replay_resumes_without_repeats_or_gaps
— 3-task graph killed after task 2, resumed from the same storage on a
fresh runner, completes with trace [task1,task2,task3] and move columns
[CognitiveWork, Evaluation, Commit] pinned. + mapping-per-status +
monotonic-witness tests. Verified in an isolated two-crate workspace
(16+59 tests green) because in-repo cargo resolution is blocked by the
pre-existing AdaWorldAPI/burn submodule 403 (stash-verified unrelated
to this diff; no Cargo.lock in this repo forces full-workspace
resolution).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MLBnPuScZy6w9di2QEjsXM

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

ℹ️ 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 +167 to +168
Some(ExecutionStatus::WaitingForInput) | Some(ExecutionStatus::Paused { .. }) | None => {
KanbanColumn::Evaluation

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 Keep saves from skipping CognitiveWork

When a seeded session is saved again with the same current_task_id—for example a one-task graph that ends or waits for input, because FlowRunner calls save() with status == None—this maps directly to Evaluation while the envelope is still in its initial Planning column. I checked graph-flow-kanban::illegal_transition_fails_closed, which rejects Planning -> Evaluation as skipping CognitiveWork; because save_inner then records the returned column as a move, moves() can emit an invalid WAL transition for these common flows.

Useful? React with 👍 / 👎.

// move-log length before this push — monotonic per session, per
// the brief's explicit instruction.
witness_chain_position: record.envelope.moves.len() as u32,
libet_offset_us: 0,

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 the Libet anchor on cognitive-work moves

For any first task hop, from is Planning and to is CognitiveWork, but this hard-codes libet_offset_us to 0. KanbanPlanEnvelope::record_move in the sibling crate stamps -550_000 for that exact crossing and its tests assert that contract, so moves emitted by this storage lose the timing anchor consumers expect from KanbanMove; compute the offset from (from, to) instead of always using zero.

Useful? React with 👍 / 👎.

@AdaWorldAPI AdaWorldAPI merged commit 00eb946 into main Jul 2, 2026
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