From ab90423b2ce296a9882d67b527479a5f0dac43e4 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Fri, 5 Jun 2026 15:15:21 +0200 Subject: [PATCH] fix(sessions): mirror FailureSource + AdminMarkedAction in ETag force-write UpdateSessionStatusAsync force-write fallback (after ETag retries are exhausted) mirrored most fields but silently dropped FailureSource and AdminMarkedAction. Under ETag contention at the terminal transition (e.g. WhiteGlove drain racing an admin Mark Succeeded/Failed), this neutralized the admin-driven AdminAction trigger sent to agents and lost the failure attribution. Mirror both fields analogous to the existing FailureSnapshotJson mirror. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Services/TableStorageService.Sessions.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs index a9552939..04215fda 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs @@ -1556,6 +1556,20 @@ namespace AutopilotMonitor.Functions.Services if (status == SessionStatus.Failed && !string.IsNullOrEmpty(failureSnapshotJson)) forceUpdate["FailureSnapshotJson"] = failureSnapshotJson; + // Mirror FailureSource (failure attribution: agent / rule: / manual) + // from the regular path — otherwise the force-merge fallback silently + // drops the origin of a Failed status under ETag contention. + if (status == SessionStatus.Failed && !string.IsNullOrEmpty(failureSource)) + forceUpdate["FailureSource"] = failureSource; + + // Mirror AdminMarkedAction — the authoritative trigger for the + // AdminAction response-field sent to agents (set only by Mark + // Succeeded/Failed). Dropping it here would silently neutralize an + // administrator-driven terminal override exactly when ETag retries + // are exhausted at the terminal transition. + if (!string.IsNullOrEmpty(adminMarkedAction)) + forceUpdate["AdminMarkedAction"] = adminMarkedAction; + if (isPreProvisioned.HasValue) forceUpdate["IsPreProvisioned"] = isPreProvisioned.Value;