mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 13:39:47 +00:00
45b5a8cde8
A Patrol run that planned a fix and then failed, normally on its final model call, was never finalized. Core's run goroutine returned on the error before it rebuilt the investigation record, published the unified finding and sent the approval push, so the record kept showing the run as running and nobody was asked to approve the queued fix. Manual re-investigations never reached that goroutine, even when they succeeded, and a run a restart interrupted was only marked closed. Core now finalizes a run when its close lands on the finding or when the stuck-run sweep recovers it with a closed session. It first reconciles the run's action from the action audit, because the orchestrator writes the action back as planned and an approval or expiry during the final model call may have overtaken it. For the same reason a close no longer moves a finding back to fix_queued from an outcome the action reached during the run. Finalization skips a run the finding no longer names and asks for approval once per action. An action's outcome keeps its single push from transition reconciliation, so a close no longer sends a second fix-completed notification. The action inbox and decision-queue expiry sweeps also publish the plans they expire, as a single action's expiry already was, so a Patrol finding's queued fix moves to needs_attention when its plan expires. Reconciliation follows refresh lineage to ignore a transition for a plan that the investigation's current action replaced, so the expiry of a refreshed plan cannot take the investigation back.