Recovery primitive: given a run's suspended RunSummary, heals every
CURRENTLY suspended step whose exact (suspendedAt, resumeCount)
fingerprint has no approval record of ANY status, then files it fresh.
Safe to call on every status() read of a suspended run, rather than only
after a confirmed bridge failure, because per step:
any record (any status) already bound to the CURRENT fingerprint means
nothing to do — a matching pending/claimed/escalated record makes
queueApprovalForSuspension's own idempotent create() a no-op anyway
(this skips the round-trip), and a matching DECIDED record means the
decision landed but its resume has not (yet, or ever, on the wedge path
this exists for) re-queued the next gate — re-filing would double-file
a gate correctly waiting on its own resume, the decide -> resume
in-flight window;
otherwise, every STALE OPEN record for that step (pending/claimed/
escalated, bound to a suspension the step has since moved past —
produced e.g. by the raw grant-free resume route re-suspending the step
while an earlier request still sits open) is SUPERSEDED first
(ApprovalService.supersedeStale: a CAS transition straight to
'rejected', system-attributed, audited as approval.supersede, never
through decide() — so it never touches the run) before the fresh file,
closing the loop where a stale-but-open record otherwise never heals
(every poll re-lists, finds the same open record via the open-step
uniqueness index, and re-files nothing). A stale DECIDED record needs
no supersede — it is already terminal and excluded from grant
derivation by its own (non-'approved', or fingerprint-mismatched)
status.
if a supersede loses its CAS (a real decision won the race between the
list() above and the supersede), this step is left alone for this
round entirely — no fresh file — rather than clobbering or
double-filing over a decision that just landed; the next status() read
re-evaluates against a fresh summary and a fresh list().
Delegates the actual filing to queueApprovalForSuspension against a copy of
summary narrowed to only the healed paths, so a step with a live or
in-flight record is never touched. requestedBy defaults to the SYSTEM
principal because generic workflow reconciliation cannot reliably recover the
initiating principal. Agent hosts persist the original requester and pass
that id explicitly so separation of duties survives eviction and filing
retries.
Recovery primitive: given a run's suspended RunSummary, heals every CURRENTLY suspended step whose exact (suspendedAt, resumeCount) fingerprint has no approval record of ANY status, then files it fresh. Safe to call on every status() read of a suspended run, rather than only after a confirmed bridge failure, because per step:
Delegates the actual filing to queueApprovalForSuspension against a copy of
summarynarrowed to only the healed paths, so a step with a live or in-flight record is never touched.requestedBydefaults to the SYSTEM principal because generic workflow reconciliation cannot reliably recover the initiating principal. Agent hosts persist the original requester and pass that id explicitly so separation of duties survives eviction and filing retries.