Repository navigation
#476: the two halves of a run share a lifecycle - #567
Merged
Merged
Conversation
A durable run is split across .nodus/graphs/ (graph state + checkpoint) and the workflow store (run record), and nothing kept them in step: workflow cleanup removed graph state and left records accumulating forever; the store's opt-in max_terminal_runs cap deleted records and left graph state orphaned; and a resume whose record was gone -- while the state sat on disk -- reported "not found" (reproduced on main: the issue's rm -rf on the runs directory made a live waiting run permanently unresumable behind that message). Now: cleanup deletes the run record with the graph state, unless the record says the run is still live and --force was not given (the mark_waiting administrative shape is live state, not cleanup's to take); the record cap prunes graph state and checkpoint with the record; stores gained delete_run -- a concrete no-op default on the WorkflowStore ABC so host implementations keep working, overridden by Local and SQLite (via a new _exec_rowcount helper, keeping the #516 cursor discipline); and the missing-record resume names the real situation with category "run_record_missing". CLAUDE.md's "rm -rf .nodus/workflow_framework/runs is safe" note is corrected -- it was this issue's repro. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QBC6mwW25PMi72GqL9Q9vX
This was referenced Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #476 — options (1) and (2) of its fix direction, both directions of each.
Reproduced on
mainfirst: the issue's repro (rm -rf .nodus/workflow_framework/runs— the cleanup CLAUDE.md described as safe) made a live waiting run permanently unresumable behindWorkflow run '…' not found, with its graph state and checkpoint sitting on disk.Symmetric cleanup (option 1), both directions:
nodus workflow cleanupnow deletes the run record with the graph state, reported asrun_records_removedin its output. Guard: if the record says the run is still live (the administrativemark_waitingshape — a waiting record over a completed snapshot), it is not cleanup's to take without--force.max_terminal_runscap now prunes the graph state and checkpoint with the record it deletes — a host that caps records wants the run gone, not half of it.delete_run(run_id) -> bool— a concrete no-op default on theWorkflowStoreABC (an abstract method would break every host store implementation to gain a capability only cleanup uses), overridden byLocalWorkflowStoreandSQLiteWorkflowStore. The SQLite version goes through a new_exec_rowcounthelper: the existing#516source-assertion (conn.executeonly inside the cursor-owning helpers) caught my first cut callingconn.executedirectly, which is that test doing exactly its job.Honest diagnosis (option 2): a resume whose record is missing while
load_graph_statefinds state now says so — "has graph state under .nodus/graphs but no run record in the workflow store — the two halves of the run were cleaned independently" — withcategory: "run_record_missing", plus the recovery hint (workflow cleanup --forcefor the orphaned state). An id with neither half still saysnot found, pinned by a falsifiability control.Option (3) (one owner) not taken — recorded on the issue as the long-term shape, with #380 the natural companion.
CLAUDE.md's "safe to
rm -rf" note is corrected; it was this issue's repro.Test plan
tests/test_run_store_lifecycle.py(# closes: #476): cleanup removes both halves and reports both lists; the issue's rm-the-records repro now yields the honest diagnosis instead ofnot found; unknown ids still saynot found; the record cap prunes graph state with the record (timestamp-tie made deterministic); SQLitedelete_runround-trip.[Unreleased]issues.🤖 Generated with Claude Code
https://claude.ai/code/session_01QBC6mwW25PMi72GqL9Q9vX