diff --git a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Integration/ScenarioTests.cs b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Integration/ScenarioTests.cs index 5711a67c..5cfb2d5f 100644 --- a/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Integration/ScenarioTests.cs +++ b/src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Integration/ScenarioTests.cs @@ -253,6 +253,29 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.Integration f.Stop(); } + // ================================================================ 14) UserDriven-v1 Hello-Skipped (real-world replay) + + [Fact] + public void Scenario14_UserDriven_HelloSkipped_completes_with_skipped_outcome() + { + // Anonymized replay of session df7abbc2 — UserDriven v1 happy variant where the + // Hello-for-Business policy was enabled but the per-user enrollment ultimately + // resolved as "skipped" (not "Success"). Verifies that the AND-gate (Desktop + + // Hello) accepts any terminal Hello outcome and still routes through Finalizing + // → Completed (project memory: feedback_hello_policy_wait_not_completion). + using var f = new EnrollmentOrchestratorFixture(); + f.Start(); + f.PostFixture("userdriven-hello-skipped-v2.jsonl"); + + Assert.True(f.WaitForStage(DefaultTerminalTimeoutMs, SessionStage.Completed)); + Assert.Equal(SessionOutcome.EnrollmentComplete, f.Orchestrator.CurrentState.Outcome); + Assert.Equal("skipped", f.Orchestrator.CurrentState.HelloOutcome?.Value); + // ImeUserSessionCompleted at signal 21 promotes ScenarioProfile.Mode to Classic. + Assert.Equal(EnrollmentMode.Classic, f.Orchestrator.CurrentState.ScenarioProfile.Mode); + + f.Stop(); + } + // ================================================================ Pipeline smoke (Telemetry) [Fact] diff --git a/tests/fixtures/enrollment-sessions/README.md b/tests/fixtures/enrollment-sessions/README.md index 027d2bf3..f154c4ed 100644 --- a/tests/fixtures/enrollment-sessions/README.md +++ b/tests/fixtures/enrollment-sessions/README.md @@ -36,9 +36,14 @@ A fixture may only land here when **all** of the following hold: ## Fixtures -| Filename | Category | Terminal Stage | EnrollmentType | WhiteGlove | Notes | -|---|---|---|---|---|---| -| _(empty — populated during M3 bring-up)_ | | | | | | +Authoritative terminal-state expectations live in the paired scenario tests, not in this +table — see [`AutopilotMonitor.Agent.V2.Core.Tests/Integration/ScenarioTests.cs`](../../../src/Agent/AutopilotMonitor.Agent.V2.Core.Tests/Integration/ScenarioTests.cs) +and [`AutopilotMonitor.DecisionCore.Tests/Scenarios/`](../../../src/Agent/AutopilotMonitor.DecisionCore.Tests/Scenarios/). +Add a row below for any new fixture so reviewers can spot coverage gaps at a glance. + +| Filename | Category | Terminal Stage | EnrollmentType | Notes | +|---|---|---|---|---| +| `userdriven-hello-skipped-v2.jsonl` | userdriven-happy (variant) | Completed | v1 | Real-world anon replay of session df7abbc2. HelloOutcome=skipped (not Success); ScenarioProfile.Mode=Classic via ImeUserSessionCompleted. 23 decision signals. | ## Ordering diff --git a/tests/fixtures/enrollment-sessions/userdriven-hello-skipped-v2.jsonl b/tests/fixtures/enrollment-sessions/userdriven-hello-skipped-v2.jsonl new file mode 100644 index 00000000..8aa65636 --- /dev/null +++ b/tests/fixtures/enrollment-sessions/userdriven-hello-skipped-v2.jsonl @@ -0,0 +1,30 @@ +# Scenario: UserDriven-v1 with Hello=skipped (real-world replay, anon df7abbc2) +# Expected terminal: Stage=Completed, Outcome=EnrollmentComplete, HelloOutcome=skipped +# ScenarioProfile.Mode=Classic (reason=ime_user_session_completed at signal 21). +# Stage transitions: SessionStarted -> EspDeviceSetup (sig 3) -> EspAccountSetup (sig 14) +# -> Finalizing (sig 22, HelloResolved) -> Completed (auto-fired FinalizingGrace). +# Source: anonymized signal-log tail of session df7abbc2 (UserDriven v1 happy with Hello skip). +# Plan: §4.x M4.4.5.g — V2 Agent end-to-end runtime fixture. +{"SessionSignalOrdinal":0,"SessionTraceOrdinal":0,"Kind":"EspConfigDetected","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:16:29.3818966Z","SourceOrigin":"EnrollmentOrchestrator","Evidence":{"Kind":"Raw","Identifier":"esp_config_detected_bootstrap","Summary":"SkipUser=False, SkipDevice=False","RawPointer":null,"DerivationInputs":{"skipUserEsp":"false","skipDeviceEsp":"false","source":"registry_firstsync_bootstrap"}},"Payload":{"skipUserEsp":"false","skipDeviceEsp":"false"},"TypedPayload":null} +{"SessionSignalOrdinal":1,"SessionTraceOrdinal":1,"Kind":"AadUserJoinedLate","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:16:29.890837Z","SourceOrigin":"AadJoinWatcher","Evidence":{"Kind":"Derived","Identifier":"aad-join-watcher-v1","Summary":"Late AAD user join detected (JoinInfo registry key)","RawPointer":null,"DerivationInputs":{"registryKey":"HKLM\\SYSTEM\\CurrentControlSet\\Control\\CloudDomainJoin\\JoinInfo"}},"Payload":{"userDomain":"tenant-anon-0010.example","hasThumbprint":"true"},"TypedPayload":null} +{"SessionSignalOrdinal":2,"SessionTraceOrdinal":2,"Kind":"EspConfigDetected","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:16:30.554347Z","SourceOrigin":"DeviceInfoCollector","Evidence":{"Kind":"Raw","Identifier":"esp_config_detected","Summary":"SkipUser=False, SkipDevice=False","RawPointer":null,"DerivationInputs":{"skipUserEsp":"false","skipDeviceEsp":"false","source":"registry_firstsync"}},"Payload":{"skipUserEsp":"false","skipDeviceEsp":"false"},"TypedPayload":null} +{"SessionSignalOrdinal":3,"SessionTraceOrdinal":3,"Kind":"EspPhaseChanged","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:16:36.8550942Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"IME log phase transition → DeviceSetup","RawPointer":null,"DerivationInputs":{"detectionSource":"IME log regex pattern","phase":"DeviceSetup"}},"Payload":{"phase":"DeviceSetup"},"TypedPayload":null} +{"SessionSignalOrdinal":4,"SessionTraceOrdinal":4,"Kind":"SessionStarted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:16:39.0446464Z","SourceOrigin":"Program.RunAgent","Evidence":{"Kind":"Synthetic","Identifier":"register_session_success","Summary":"Session registration handshake succeeded; posting SessionStarted anchor for reducer.","RawPointer":null,"DerivationInputs":null},"Payload":{"enrollmentType":"v1","isHybridJoin":"false","validatedBy":"AutopilotV1","agentVersion":"2.0.350+anon","isBootstrapSession":"false"},"TypedPayload":null} +{"SessionSignalOrdinal":5,"SessionTraceOrdinal":5,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:17:16.4365775Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0001 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0001","previousState":"Downloading","newState":"Installed"}},"Payload":{"appId":"app-anon-0001","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":6,"SessionTraceOrdinal":6,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:17:47.6211306Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0002 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0002","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0002","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":7,"SessionTraceOrdinal":7,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:18:12.0202837Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0003 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0003","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0003","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":8,"SessionTraceOrdinal":8,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:18:45.1764398Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0004 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0004","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0004","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":9,"SessionTraceOrdinal":9,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:19:14.1717549Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0005 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0005","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0005","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":10,"SessionTraceOrdinal":10,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:19:35.3622313Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0006 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0006","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0006","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":11,"SessionTraceOrdinal":11,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:20:03.0215524Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0007 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0007","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0007","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":12,"SessionTraceOrdinal":12,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:20:28.929159Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0008 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0008","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0008","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":13,"SessionTraceOrdinal":13,"Kind":"EspPhaseChanged","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:20:38.6074186Z","SourceOrigin":"EspAndHelloTracker","Evidence":{"Kind":"Derived","Identifier":"esp-and-hello-tracker-v1","Summary":"ESP Finalizing phase triggered (coordinator-forwarded)","RawPointer":null,"DerivationInputs":{"subSource":"ShellCoreTracker","phaseReason":"esp_exiting"}},"Payload":{"phase":"FinalizingSetup","reason":"esp_exiting"},"TypedPayload":null} +{"SessionSignalOrdinal":14,"SessionTraceOrdinal":14,"Kind":"EspPhaseChanged","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:20:45.1047908Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"IME log phase transition → AccountSetup","RawPointer":null,"DerivationInputs":{"detectionSource":"IME log regex pattern","phase":"AccountSetup"}},"Payload":{"phase":"AccountSetup"},"TypedPayload":null} +{"SessionSignalOrdinal":15,"SessionTraceOrdinal":15,"Kind":"DeviceSetupProvisioningComplete","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:21:04.0280353Z","SourceOrigin":"EspAndHelloTracker","Evidence":{"Kind":"Derived","Identifier":"esp-and-hello-tracker-v1","Summary":"DeviceSetupCategory provisioning completed (coordinator-forwarded)","RawPointer":null,"DerivationInputs":{"subSource":"ProvisioningStatusTracker","deviceSetupResolved":"unknown"}},"Payload":{"deviceSetupResolved":"unknown"},"TypedPayload":null} +{"SessionSignalOrdinal":16,"SessionTraceOrdinal":16,"Kind":"DesktopArrived","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:21:36.2632926Z","SourceOrigin":"DesktopArrivalDetector","Evidence":{"Kind":"Derived","Identifier":"desktop-arrival-detector-v1","Summary":"Desktop arrival observed (explorer.exe under real user)","RawPointer":null,"DerivationInputs":{"detectionSource":"explorer.exe process poll","part2Mode":"false"}},"Payload":null,"TypedPayload":null} +{"SessionSignalOrdinal":17,"SessionTraceOrdinal":17,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:23:01.9875745Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0009 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0009","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0009","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":18,"SessionTraceOrdinal":18,"Kind":"HelloPolicyDetected","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:23:49.6934975Z","SourceOrigin":"EspAndHelloTracker","Evidence":{"Kind":"Derived","Identifier":"esp-and-hello-tracker-v1","Summary":"Hello policy detected (helloEnabled=true, source=CSP/Intune (user-scoped))","RawPointer":null,"DerivationInputs":{"subSource":"HelloTracker","helloEnabled":"true","policySource":"CSP/Intune (user-scoped)"}},"Payload":{"helloEnabled":"true","policySource":"CSP/Intune (user-scoped)"},"TypedPayload":null} +{"SessionSignalOrdinal":19,"SessionTraceOrdinal":19,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:24:58.052023Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0010 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0010","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0010","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":20,"SessionTraceOrdinal":20,"Kind":"AppInstallCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:26:24.6622419Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"App app-anon-0011 → Installed","RawPointer":null,"DerivationInputs":{"appId":"app-anon-0011","previousState":"Installing","newState":"Installed"}},"Payload":{"appId":"app-anon-0011","newState":"Installed"},"TypedPayload":null} +{"SessionSignalOrdinal":21,"SessionTraceOrdinal":21,"Kind":"ImeUserSessionCompleted","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:26:41.072284Z","SourceOrigin":"ImeLogTracker","Evidence":{"Kind":"Derived","Identifier":"ime-log-tracker-v1","Summary":"IME user session completed (all user-scope apps finished)","RawPointer":null,"DerivationInputs":{"detectionSource":"IME log pattern (UserSessionCompleted)"}},"Payload":null,"TypedPayload":null} +{"SessionSignalOrdinal":22,"SessionTraceOrdinal":22,"Kind":"HelloResolved","KindSchemaVersion":1,"OccurredAtUtc":"2026-04-25T20:27:03.8209855Z","SourceOrigin":"EspAndHelloTracker","Evidence":{"Kind":"Derived","Identifier":"esp-and-hello-tracker-v1","Summary":"Hello resolved via coordinator (outcome=skipped)","RawPointer":null,"DerivationInputs":{"subSource":"HelloTracker","outcome":"skipped"}},"Payload":{"outcome":"skipped"},"TypedPayload":null}