Files
AutopilotMonitor/tests/fixtures
Oliver Kieselbach 8e4faf4251 refactor(decisioncore): WhiteGlove Part 2 + Part2CompletionClassifier + 2 scenarios (M3.4)
Plan §4 M3.4 + plan §2.3 WhiteGlove Part-2 state machine: post-reboot user
sign-in is now a first-class path with a dedicated classifier, a 24h safety
deadline, and an explicit Sealed -> AwaitingUserSignIn -> CompletedPart2 /
Failed progression.

Classifier (WhiteGlovePart2CompletionClassifier : IClassifier):
 - Scoring rules NEW (no Legacy equivalent): each of the four Part-2 user
   signals (+25) — UserAadSignInComplete, HelloResolvedPart2,
   DesktopArrivedPart2, AccountSetupCompletedPart2. All four together hit
   the Confirmed threshold (100); missing one drops to Weak (75).
 - WhiteGlovePart2CompletionSnapshot implements the new IClassifierSnapshot
   interface; existing WhiteGloveSealingSnapshot was retrofit to the same
   contract so the harness anti-loop is uniform.

Handlers (DecisionEngine.WhiteGlovePart2.cs):
 - SessionRecovered (Shared.cs) now bridges a WhiteGloveSealed state into
   WhiteGloveAwaitingUserSignIn and arms the 24h WhiteGlovePart2Safety
   deadline on the recovered signal's occurredAt.
 - Four Part-2 signal handlers (UserAadSignInComplete, HelloResolvedPart2,
   DesktopArrivedPart2, AccountSetupCompletedPart2) record facts + emit a
   Part-2 RunClassifier effect; facts arriving outside the AwaitingUserSignIn
   stage are recorded but no classifier runs (prevents stray Part-2 verdicts
   on non-sealed sessions).
 - WhiteGlovePart2Safety deadline handler terminates with Failed /
   enrollment_failed reason=part2_user_absent.
 - ClassifierVerdictIssued router extended to dispatch on classifier id —
   Part-2 verdicts route to ApplyWhiteGlovePart2Verdict; Confirmed triggers
   Stage=WhiteGloveCompletedPart2 + Outcome=WhiteGlovePart2Complete +
   whiteglove_part2_complete event.

DecisionState: four new SignalFact<DateTime>? fields for the Part-2 signals
(full builder parity).

ClassifierAwareReplayHarness: anti-loop lookup now routes per classifier id
(WhiteGloveSealing <-> WhiteGloveSealing.LastClassifierVerdictId;
Part2Completion <-> WhiteGlovePart2Completion.LastClassifierVerdictId).
Snapshot hashing works through the IClassifierSnapshot interface instead
of a WhiteGloveSealingSnapshot type check.

Scenario fixtures (committed-anonymized):
 - whiteglove-part2-happy-v1.jsonl  seal Part 1, reboot, 4 Part-2 signals
                                    within minutes -> Confirmed + Part2Complete.
 - whiteglove-part2-stuck-v1.jsonl  seal Part 1, reboot, 24h passes, safety
                                    deadline fires -> Failed / part2_user_absent.

Tests (3 new in WhiteGlovePart2ScenarioTests):
 - Happy terminal state + hypotheses + all four facts + no residual deadlines
 - Stuck terminal state + Part-1 Confirmed remains, Part-2 Rejected with reason
 - Bridge check: after SessionRecovered(Sealed), Part-2 safety is active

Suite totals: 52 DecisionCore (was 49) / 507 Legacy / 557 Functions.

Plan: plans/REFACTOR_AGENT_V2.md §4 M3 sub-milestone M3.4 + §2.3 Part-2 stages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 14:21:53 +02:00
..