Files
pulse/internal/actionlifecycle
rcourtman 45b5a8cde8 Finalize Patrol runs when they close, failed runs included
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.
2026-10-23 21:15:25 +01:00
..