mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 05:29:45 +00:00
a4bfca4d32
Three gaps remained in how Pulse projects a Patrol investigation's action and closes its runs. Projections of one investigation could interleave: the transition callback, an investigation read and a run's close each read the action audit and applied it, so one that read an older state could land after one that read a newer state, and an approval could land between a run's reconciliation and its finalization. All of them now read and apply under the investigation's lock, and a close finalizes before it releases it. The projection replaced the whole session through Update, so it could undo run progress the orchestrator saved in between. It now writes only the changed action and outcome when the store offers SetAction (aicontracts.InvestigationActionStore), and the reference it writes carries the broker's canonical result and verification status and the model's causal attribution, which the audit does not hold. A run that hung past its limit without closing was recovered by the stuck-run sweep but never finalized. The sweep now finalizes it with a copy of its session marked failed, leaving the orchestrator's session as it is. A later real close is finalized instead, and a refresh no longer reopens a record that finalization closed.