Session durations come from device times, and a device clock can be off by
hours for a whole session or change in the middle of one. Every upload
carries the device send time next to the server receive time; their
difference is the device clock error. This change records the session's
start, WhiteGlove Part 2 start and end on the server clock next to the
device values. Nothing reads them yet, so no stored value and no display
changes.
- ServerTime: the rule, defined by tests/fixtures/server-time/cases.json and
run by both the backend (ServerTime.cs) and the web (lib/serverTime.ts).
- Ingest: ServerTime.Tracker, the rule fed one upload at a time, keeps its
state in the primary-only column ServerTimeState and writes
StartedAtServer and ResumedAtServer in the counter merge (no extra read
or write). It follows a session from its first upload only, and only when
that upload carries agent_started; sessions already under way when this
build arrives get their values at completion. On every upload prefix of
every followed case it gives the rule's start and Part 2 start; a retried
upload with agent_started is not counted as a restart.
- Terminal: the counter reconcile, which every terminal path runs, also
computes the rule over the same event scan and writes StartedAtServer,
ResumedAtServer and CompletedAtServer. Fail-soft: a rule failure never
costs the counter reconcile or the ingest write.
- Re-registration carries the four columns from the fresh CAS read through
the Replace (the agent's first upload often races its registration).
- SessionSummary gets the three fields; the index mirrors them, the index
merge drops primary-only columns; manifests and wire types regenerated.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>