mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 05:29:45 +00:00
a408736bc4
The private investigation orchestrator writes a finding's investigation fields through orchestratorFindingsAdapter, and every write was applied unconditionally. A run still in flight when its finding was resolved and detected again, or when the stuck-run sweep gave it up and a retry started another run, overwrote the newer state with its own session, status, outcome and attempts when it finished. A stale "resolved" made the regressed occurrence terminal, so Patrol stopped investigating it. Closing writes now go through FindingsStore.CompleteInvestigation, which records them only while the finding still names the run: the session must be the finding's current one and the run must not predate the finding's latest regression. Admission goes through StartInvestigation, which refuses a run whose session started before that regression, so a delayed admission cannot install an earlier occurrence's attempt count or replace a newer run. Both compare a run's start only with an occurrence start this process observed: a regression, or the finding's removal by ClearAll or Cleanup, kept unpersisted with the clock's monotonic reading for a day. A regression an earlier process recorded predates every run of this one, so a clock set back across a restart cannot make every new run look stale. Records and action outcomes keep comparing with LastRegressionAt, since they also judge sessions of earlier processes. The adapter takes each run's start from the orchestrator's session store, so the aicontracts boundary and the enterprise orchestrator are unchanged.