graph-flow: KanbanSessionStorage behind new kanban feature — the M25 replayable handler (D-V3-W3b)#21
Conversation
…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
There was a problem hiding this comment.
💡 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".
| Some(ExecutionStatus::WaitingForInput) | Some(ExecutionStatus::Paused { .. }) | None => { | ||
| KanbanColumn::Evaluation |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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 👍 / 👎.
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
kanbanongraph-flow, enabling path deps on the siblinggraph-flow-kanbanenvelope crate +lance-graph-contract(graph-flow is the composer; the envelope crate stays contract-only).storage_kanban::KanbanSessionStorage— implementsSessionStorage: everysave()upserts the Session snapshot AND appends reallance_graph_contract::kanban::KanbanMoves derived from the observed transition. The storage carries theMailboxId(acts on behalf of one mailbox); the Session carries nothing (DTO purity).current_task_idchanged → 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).KanbanPlanEnvelopeis 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-flowis blocked by the pre-existingAdaWorldAPI/burnsubmodule 403 (noCargo.lockin this repo forces full-workspace resolution throughepisodic-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