Files
AutopilotMonitor/tests
Oliver Kieselbach 579291272e fix(v2): split EnrollmentFactsObserved from SessionStarted to fix JoinMode race
V2 tracker / Backend-register-session race could land SessionStarted after
ESP/Tracker signals had already advanced Stage past SessionStarted. The
HandleSessionStartedV1 dead-end-Wache then swallowed the registry-derived
profile facts (enrollmentType + isHybridJoin), leaving JoinMode=Unknown on
every affected enrollment_complete payload (Session 10c8e0bf).

Root cause was a concept mix in SessionStarted: a lifecycle anchor doing
double duty as a static-facts seed. Split into two signals:

 - SessionStarted: pure lifecycle anchor (Stage / ClassifierTick / step).
 - EnrollmentFactsObserved: stage-agnostic, idempotent, monotonic facts
   carrier. New reducer handler delegates to ApplyEnrollmentFactsObserved
   (renamed from ApplySessionStarted, with set-once reason for v1 to
   honour the documented idempotency contract).

AwaitEnrollment is transparently covered: AgentBootstrap blocks until the
MDM cert exists, so the registry is guaranteed populated by the time
PostEnrollmentFactsObserved runs; a single post per agent run suffices.

Tests:
 - DecisionCore: 234/234 (4 new fact-handler tests + idempotency + monotonicity)
 - Agent.V2.Core: 771/771 (3 new producer tests, 1 reshaped)
 - Agent.Core (V1): 507/507 sanity-check unchanged

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 09:19:34 +02:00
..