(utc, sourceSignalOrdinal);
return this;
}
@@ -236,6 +256,8 @@ namespace AutopilotMonitor.DecisionCore.State
espAdvisoryFailureRecordedUtc: EspAdvisoryFailureRecordedUtc,
imeUserSessionCompletedUtc: ImeUserSessionCompletedUtc,
completionWaitingFingerprint: CompletionWaitingFingerprint,
- helloWizardStartedUtc: HelloWizardStartedUtc);
+ helloWizardStartedUtc: HelloWizardStartedUtc,
+ espAdvisoryFailureResolvedUtc: EspAdvisoryFailureResolvedUtc,
+ espAdvisoryFailureCategory: EspAdvisoryFailureCategory);
}
}
diff --git a/src/Shared/AutopilotMonitor.Shared/Constants.cs b/src/Shared/AutopilotMonitor.Shared/Constants.cs
index 48d47949..4f0f0f76 100644
--- a/src/Shared/AutopilotMonitor.Shared/Constants.cs
+++ b/src/Shared/AutopilotMonitor.Shared/Constants.cs
@@ -539,6 +539,17 @@ namespace AutopilotMonitor.Shared
public const string EspFailureSettleRecovered = "esp_failure_settle_recovered"; // The failed subcategory left the "failed" state during the settle window (e.g. ESP "Try again" retry, session c071e92b) — the terminal EspFailureDetected fire is suppressed and monitoring continues; a subsequent failure re-arms a fresh settle window.
public const string EspAppxFailureAnalysis = "esp_appx_failure_analysis"; // One-shot AppXDeploymentServer/Operational scan during the ESP failure settle window: candidate MSIX/Store packages behind an "Apps (0x…)" subcategory failure invisible to ImeLogTracker (session 2bc884b6). Assessment, not a confirmed root cause.
public const string EspProvisioningRaw = "esp_provisioning_raw";
+ // Recovery story AFTER a terminally fired ESP failure (session 4910a5a5, 2026-07-23 —
+ // DeviceSetup/Apps failed, user pressed "Try again" ~23 min later, apps re-ran to
+ // 10/10). Distinct from EspFailureSettleRecovered, which covers recovery INSIDE the
+ // 30s settle window (terminal fire suppressed); these fire when the failure already
+ // went terminal (advisory/enrollment_failed) and the registry later disproves it.
+ public const string EspFailureRetryDetected = "esp_failure_retry_detected"; // failed subcategory left "failed" post-terminal — consistent with the user pressing "Try again"
+ public const string EspFailureRecovered = "esp_failure_recovered"; // previously failed category reached all-subcategories-succeeded post-terminal
+ // DecisionEngine counterpart (survives reboots via snapshot, unlike the in-run tracker
+ // pair above): the category behind a defanged esp_failure_advisory later resolved to
+ // success — the advisory no longer blocks; re-arm/rebase guards apply again.
+ public const string EspFailureAdvisoryResolved = "esp_failure_advisory_resolved";
public const string EspFailure = "esp_failure";
public const string EspExiting = "esp_exiting";
diff --git a/src/Web/autopilot-monitor-web/app/gather-rules/eventTypes.ts b/src/Web/autopilot-monitor-web/app/gather-rules/eventTypes.ts
index 5f20b209..7414e1b0 100644
--- a/src/Web/autopilot-monitor-web/app/gather-rules/eventTypes.ts
+++ b/src/Web/autopilot-monitor-web/app/gather-rules/eventTypes.ts
@@ -98,6 +98,12 @@ export const KNOWN_EVENT_TYPES: EventTypeEntry[] = [
description: "ESP reported a subcategory failure but the device had already progressed to AccountSetup with ContinueAnyway enabled — non-terminal advisory, the agent continues monitoring." },
{ value: "esp_appx_failure_analysis", label: "esp_appx_failure_analysis", category: "esp",
description: "AppX deployment log scan during the ESP failure settle window: suspected MSIX/Store package candidates behind an Apps-subcategory failure (assessment, not a confirmed root cause)." },
+ { value: "esp_failure_retry_detected", label: "esp_failure_retry_detected", category: "esp",
+ description: "After a terminally reported ESP failure, the failed subcategory left the failed state — consistent with the user pressing 'Try again' on the ESP failure page." },
+ { value: "esp_failure_recovered", label: "esp_failure_recovered", category: "esp",
+ description: "The ESP category behind a terminally reported failure later completed successfully — the earlier failure recovered (e.g. after a user retry)." },
+ { value: "esp_failure_advisory_resolved", label: "esp_failure_advisory_resolved", category: "esp",
+ description: "DecisionEngine: the category behind a defanged esp_failure_advisory resolved to success — the advisory no longer blocks completion." },
// -------- App installs --------
{ value: "app_install_started", label: "app_install_started", category: "app",
diff --git a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/components/EventTimeline.tsx b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/components/EventTimeline.tsx
index 59b340aa..f117b56b 100644
--- a/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/components/EventTimeline.tsx
+++ b/src/Web/autopilot-monitor-web/app/sessions/[sessionId]/components/EventTimeline.tsx
@@ -521,6 +521,46 @@ function EventRow({ event, showScriptOutput }: { event: EnrollmentEvent; showScr
subcategory: {String(sub)}
)}
+ {event.data?.likelyCulpritApps && (
+
+ Likely app: {String(event.data.likelyCulpritApps)}
+
+ )}
+
+ );
+ })()}
+ {/* Recovery-story badges (session 4910a5a5): a terminally reported ESP failure that
+ later un-happened — the user retried ("Try again"), the failed step re-ran and
+ recovered. Green/teal palette so the timeline visually closes the earlier red/amber
+ failure arc. */}
+ {(event.eventType === "esp_failure_retry_detected" || event.eventType === "esp_failure_recovered" || event.eventType === "esp_failure_advisory_resolved") && (() => {
+ const isRetry = event.eventType === "esp_failure_retry_detected";
+ const label = isRetry ? "User retry" : "Recovered";
+ const badgeCls = isRetry ? "bg-sky-100 text-sky-800" : "bg-emerald-100 text-emerald-800";
+ const cat = event.data?.category;
+ const sub = event.data?.subcategory ?? event.data?.failedSubcategory;
+ const mins = event.data?.minutesSinceFailure ?? event.data?.minutesSinceAdvisory;
+ return (
+
+
+ {label}
+
+ {cat && (
+
+ {String(cat)}{sub ? <> / {String(sub)}> : null}
+
+ )}
+ {mins !== undefined && mins !== null && (
+ {String(mins)} min after the failure
+ )}
);
})()}