Problem
saveRun persists a run as a plain whole-file writeJson of state + manifest + report with no compare-and-swap and no locking (dist/runtime/flow-run-store.js:160-164 in 1.3.0/1.4.x), and consumers hold no mutex around evaluate. Two concurrent evaluations of the same run — e.g. an in-process REST evaluate racing an out-of-process flow CLI against the same .flow/runs/<id>/ — are last-write-wins: one evaluation's recorded gate outcomes and transitions can be silently clobbered by the other's stale snapshot.
This is a run-integrity hazard (lost outcomes in the file of record), distinct from any consumer-side staleness. Found while reviewing a downstream consumer's post-evaluation read path; the consumer's own exposure is bounded (its read strictly follows its own write and can only observe newer true state), but the underlying store cannot protect two writers from each other.
Suggested direction
Either CAS on a run revision (reject the save if the on-disk revision moved; caller re-reads and re-applies), or an advisory lock file per run dir held across read-evaluate-write. Even detection-only (warn on revision mismatch) beats silent clobber.
Problem
saveRunpersists a run as a plain whole-filewriteJsonof state + manifest + report with no compare-and-swap and no locking (dist/runtime/flow-run-store.js:160-164in 1.3.0/1.4.x), and consumers hold no mutex around evaluate. Two concurrent evaluations of the same run — e.g. an in-process REST evaluate racing an out-of-processflowCLI against the same.flow/runs/<id>/— are last-write-wins: one evaluation's recorded gate outcomes and transitions can be silently clobbered by the other's stale snapshot.This is a run-integrity hazard (lost outcomes in the file of record), distinct from any consumer-side staleness. Found while reviewing a downstream consumer's post-evaluation read path; the consumer's own exposure is bounded (its read strictly follows its own write and can only observe newer true state), but the underlying store cannot protect two writers from each other.
Suggested direction
Either CAS on a run revision (reject the save if the on-disk revision moved; caller re-reads and re-applies), or an advisory lock file per run dir held across read-evaluate-write. Even detection-only (warn on revision mismatch) beats silent clobber.