The time attribution shows the OOBE quality update only once a session ended. While it runs, the web now derives it from the events it already holds: - lib/osUpdateLive.ts ports the calculator's update interval for the current window and labels it from positive evidence that the update finished: running (restarting), waiting for sign-in from 2 min after its end, or failed/skipped without a restart. A package waiting for its restart keeps the update running whatever the page reported. - Session page: a line under the phase timeline, shown after the first complete walk of the event pages, with a note when the device has been silent for 15 minutes. - Progress Portal: the headline says that Windows is installing updates and asks the user to sign in after the update's restart. - OobeUpdateVocabulary (Shared) is the one vocabulary of the agent, the calculator and the web (manifest section oobeUpdate); same strings on the wire, no behaviour change. - tests/fixtures/os-update-live/cases.json pins the calculator and the port (TimeAttributionOsUpdateLiveParityTests, lib/__tests__/osUpdateLive.test.ts). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
OOBE update interval and live label — shared cases
While a session runs, the portal shows the OOBE quality update live; once the session ended,
the time attribution shows it as its os_update and awaiting_sign_in segments. Both read the
same interval, and cases.json is the one definition that every implementation runs:
- Backend — the update interval of
TimeAttributionCalculatorinsrc/Backend/AutopilotMonitor.Functions/Helpers/TimeAttributionCalculator.cs(test:TimeAttributionOsUpdateLiveParityTests.cs) - Web —
computeOsUpdateIntervaland the live label (deriveOsUpdateLive,osUpdateLiveState) insrc/Web/autopilot-monitor-web/lib/osUpdateLive.ts(test:lib/__tests__/osUpdateLive.test.ts)
A scenario is a session (startedAt; for WhiteGlove also resumedAt and isPreProvisioned) and
its events, listed in the order the agent sent them, which is their sequence. t is the event
time. arrives marks an event that reached the backend later than it happened: a backfill, or a
restart the agent reported after the boot. phase is an EnrollmentPhase name.
A cut is the session at now, with the events that had arrived before it:
interval— what the time attribution reports for the current part (fromresumedAt, elsestartedAt) if the session had ended atnow: begin, end, restarts, outcome and KBs. It is null when there is no update. The backend computes it throughTimeAttributionCalculator.Compute.live— the label the portal shows atnow:updating(withrestartingwhile a restart is pending),awaiting_sign_inorended. It is null when the portal shows none. Only the web reads it.
A change to the update logic goes into cases.json first; the two tests then say which side is
behind. The calculator computed the expected intervals and each one was checked by hand; the
labels are written by hand.