Files
AutopilotMonitor/tests
Oliver Kieselbach 5eb95868d8 fix(decisioncore): defang SelfDeploying terminal via 5-min deadline + UI phase coverage
Session 88a53223-9795-4188-8352-7df9f0af9bb7 (v1 Classic UserDriven, AAD
Joined, SkipUserStatusPage=false) was wrongly classified as mode=SelfDeploying
after the ProvisioningStatusTracker 30-s fallback fired DeviceSetupProvisioningComplete
before Windows transitioned DeviceSetup -> AccountSetup. The signal alone was
terminal in the old reducer; the absence of AccountSetupEnteredUtc at signal
time was sufficient to commit terminal SelfDeploying.

New rule: DeviceSetupProvisioningComplete is no longer terminal. It records a
new DeviceSetupResolvedUtc anchor and (cancel-then-)arms the DeviceOnlyEspDetection
deadline for 5 min. The deadline-fired handler is the sole SelfDeploying-terminal
entry point and re-checks six guards (stale: no-anchor / not-armed / DueAtUtc-mismatch;
race: Stage-terminal / AccountSetup-entered / monotonic Mode conflict) before
classifying. Any dead-end after the DueAtUtc match state-side CancelDeadline()s
the past-due deadline so snapshot reload doesn't re-arm via the scheduler.

RealmJoin-deferred release (CompleteIfDeferredOrBookkeep) re-checks the same
guards, resets DeviceOnlyDeployment hypothesis to Unknown on bailout, and
operates on preparedBuilder.* (not state.*) so WithResolved / WithTimeoutOutcome
facts survive the bailout.

UI phase coverage closed: phase_transition(FinalizingSetup) and
phase_transition(Complete) emitted at every terminal-success site (Classic
FinalizingGrace, SelfDeploying deadline-terminal, AdminPreemption-Succeeded,
RJ-deferred completion) so the Web timeline opens Finalizing + Complete bars
universally - was missing entirely for SelfDeploying / AdminPreemption paths.

Other changes:
- Removed ApplyDeviceSetupProvisioningComplete (dead code under defang), added
  ApplySelfDeployingDeadlineConfirmed with monotonic guard.
- New RealmJoinFacts.ClearSelfDeployingDeferred() for the RJ-bailout path.
- DecisionState schema bumped v3 -> v4 with additive nullable
  DeviceSetupResolvedUtc field. StateSerializer v3-deserialize-compat verified.
- DeviceSetupProvisioningComplete added to DecisionStateSignalCensus so the
  enrollment_complete audit trail surfaces the anchor.

Test coverage:
- New SelfDeployingDeadlineTerminalTests.cs (12 scenarios): happy path, all
  six guards including snapshot-migration rollout race + DueAtUtc cancel-rearm
  race, replay idempotency, audit-census wiring, RJ-deferred release races
  (AccountSetup-arrives / monotonic / Timeout-variant).
- Updated 9 existing test files for new semantics; 2 fixtures now drive
  DeadlineFired terminal explicitly.
- ReplayHarness + ClassifierAwareReplayHarness set AgentBootUtc to the first
  signal's OccurredAtUtc so fixture scenarios run in their own time-bubble
  (replay-safety floor still tested directly by BootAnchorDeadlineFloorTests).

Tests: DecisionCore 345, V2.Core 1135, Backend 1937 - all green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 23:42:10 +02:00
..