mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 20:53:06 +00:00
caa573678f
Session 4fa5a2d4 in tenant c9787ba2 hit 199/202 false-positive enrollment_failed events: ESP
profile sets BlockInStatusPage=6 (ContinueAnyway=true), Windows transitioned to AccountSetup,
then wrote DeviceSetupCategory=failed (Certificates) 13 min later — the reducer terminated
even though the device demonstrably kept progressing. PR1 Tier-1 defang downgrades these
EspTerminalFailure signals to a non-terminal esp_failure_advisory event while keeping
monitoring armed (Hello/Desktop/IME completion paths continue to drive the session).
DecisionEngine:
- New SignalFact<DateTime>? EspAdvisoryFailureRecordedUtc on DecisionState as the fire-once
gate (additive ctor param, optional at end — preserves Newtonsoft positional-binding for
pre-PR1 v4 snapshots).
- HandleEspTerminalFailureV1: when ScenarioObservations.EspAllowContinueAnyway==true AND
AccountSetupEnteredUtc!=null, emit esp_failure_advisory (severity=Warning,
advisoryReason=esp_failure_defanged_continueanyway_with_accountsetup) instead of
transitioning to Failed. Stage / deadlines / outcome stay untouched.
- Duplicate handling: a second EspTerminalFailure dead-ends UNLESS the duplicate carries
registry-specific keys (errorCode/failedSubcategory/category) — those only appear in the
ProvisioningStatusTracker path and indicate enrichment of an earlier ShellCoreTracker
advisory. failureType alone is NOT a registry marker (both adapters emit it).
- New BuildEspFailureAuditTrail helper merges a whitelisted set of failure-context keys into
the audit-trail typedPayload so HRESULT/subcategory survive the wire. Closes a pre-existing
gap on the enrollment_failed path too.
Bootstrap:
- EnrollmentOrchestrator.PostEspConfigDetectedBootstrap switched from EspSkipConfigurationProbe.
Read() (tuple SkipUser/SkipDevice) to ReadFull() so EspAllowContinueAnyway +
EspSyncFailureTimeoutMinutes are synchronously available before any EspTerminalFailure
signal — defeats the fire-and-forget DeviceInfoCollector.CollectAll race that would have
left Tier 1 with ScenarioObservations.EspAllowContinueAnyway==null.
Tests:
- EspFailureAdvisoryDefangTests (9 new): advisory path, fire-once idempotency, enrichment
on registry-detail second-fire, dead-end on ShellCore-only duplicate, three negative paths
(ContinueAnyway false / unknown / no AccountSetup), TypedPayload whitelist merge on both
advisory + Failed paths.
- SerializationTests: backcompat test for old v4 snapshots without EspAdvisoryFailureRecordedUtc.
- DecisionStateSnapshotBuilderTests: fact count bumped from 14 to 15.
- EdgeScenarioTests + esp-failure-advisory-continueanyway-v1.jsonl: end-to-end replay against
the canonical Session 4fa5a2d4 signal stream including a duplicate dead-end.
- EnrollmentOrchestratorEspConfigBootstrapTests: 4 existing tests migrated to ScopedFullOverride,
4 new tests cover ContinueAnyway + SyncFailureTimeout propagation, class gated behind
[Collection("SerialThreading")] since the override targets a static probe slot.
UI:
- EventTimeline renders esp_failure_advisory with an amber "Advisory (ContinueAnyway)" badge
alongside the HRESULT/subcategory chips so analysts can distinguish defanged from real
failures at a glance.
- gather-rules/eventTypes.ts mirrors the new constant for autocomplete.
Build: dotnet build AutopilotMonitor.sln green; xUnit Backend(1937) + V2.Core(1139) +
Agent.Core(538) + DecisionCore(357) + SummaryDialog(44) = 4015 passed, 0 failed.
Web tsc clean, vitest 384/384 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>