jouleclaw-graph: a node in flight survives the process, and an interrupted one is held rather than silently run again #333
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/jouleclaw-graph-dispatch-before-run"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The defect
A JouleClaw run journal (
jouleclaw-graph) recorded a node only when it completed (NodeRecorded). Nothing recorded that a node had begun. A process that died in the middle of a node therefore left no trace of it, and a restarted run found the node ready again:JCP §4.11 requires the decision to be recorded before the action runs and forbids silently retrying one whose outcome is unknown. jcp-orchestrate, mesh and the
jcp/1endpoint already do this; the run journal did not.What prompted it: a comparison with durable agent harnesses. The common shape commits a tool call's intent before running it, reruns calls declared
safe, and tells the model anunsafeone "may have partly run". Published crash tests of that default show its weakness: a model retried an interrupted write it could not see and left a duplicate. Here, an interruptednevernode is not left to a model. It is held until someone settles it.The fix
Replay { Safe, Never }, withNeverthe default.RunEvents:NodeDispatched { attempt, replay }, written before work begins;NodeInterrupted { attempt, observed_uj };RerunApproved { approved_by }.Node, so every graph's content address and every persisted journal are unchanged.Run::dispatchrecords the dispatch and returns the attempt number. A node in flight is not ready, so it is not dispatched twice.Run::recovermarks every node still in flight after a restart as interrupted, keeping the energy observed for the attempt as a lower bound.Safenode is ready again, as a new attempt.Nevernode is held (held_nodes) until it is recorded, approved for a rerun by a named party (approve_rerun), or the run fails.recoverleaves the node in flight and out ofready_nodes, so it stalls rather than repeating work.recordwithout a priordispatchworks as before, so existing consumers are unaffected.Checked
On the build host:
ready_nodesignoring in-flight and held nodesdispatchignoring a held nodeNot in this change
jouleclaw-missiondispatches features rather than graph nodes and has no resume of its own. Wiring its workers throughdispatch/recoveris the next step.🤖 Generated with Claude Code
4fa2a0d6f235b7bd3972