Stamp every record with a clock that counts through sleep, and write the naps down #10

Merged
LNK merged 1 commit from claude/tick into main 2026-09-04 20:05:50 +00:00
Contributor

The second of the review's two remaining foundations: Instant stops in sleep on a Mac, so an hour asleep read as no time, and the indicator's last report looked a second old after a nap, which let content capture continue behind a pill that had not spoken since before it.

What changes. here_os::tick_ms reads the boot clock, which counts through sleep: /proc/uptime on Linux, mach_continuous_time on macOS, GetTickCount64 on Windows, a stated fallback elsewhere. Every collector stamps it beside at, the gate stores it beside the two wall stamps, and the envelope carries it as tick_ms, so records from one machine can be ordered and spaced when the wall clock stepped or was never set. The gate compares the boot clock with the process clock on every job and writes a clock.sleep decision with the length when they drift, so a nap is a record and not a hole. Indicator freshness uses the boot clock, so the first content record after a nap is held until the pill speaks again.

Proof. The tick never goes backwards, advances at the rate of time and counts from boot; an hour on the boot clock against a second awake is an hour asleep reported once; a second nap is its own report; jitter is not a nap; a record carries the tick and the envelope ships it. The nap test fails against a watch that never reports, checked by making it one. Linux verifier green on the pinned toolchain; here-os and here-win cross-check clean for Windows. Not run here: the Windows verifier and the end-to-end suite; the macOS branch of the clock is compiled only on a Mac.

The second of the review's two remaining foundations: `Instant` stops in sleep on a Mac, so an hour asleep read as no time, and the indicator's last report looked a second old after a nap, which let content capture continue behind a pill that had not spoken since before it. **What changes.** `here_os::tick_ms` reads the boot clock, which counts through sleep: `/proc/uptime` on Linux, `mach_continuous_time` on macOS, `GetTickCount64` on Windows, a stated fallback elsewhere. Every collector stamps it beside `at`, the gate stores it beside the two wall stamps, and the envelope carries it as `tick_ms`, so records from one machine can be ordered and spaced when the wall clock stepped or was never set. The gate compares the boot clock with the process clock on every job and writes a `clock.sleep` decision with the length when they drift, so a nap is a record and not a hole. Indicator freshness uses the boot clock, so the first content record after a nap is held until the pill speaks again. **Proof.** The tick never goes backwards, advances at the rate of time and counts from boot; an hour on the boot clock against a second awake is an hour asleep reported once; a second nap is its own report; jitter is not a nap; a record carries the tick and the envelope ships it. The nap test fails against a watch that never reports, checked by making it one. Linux verifier green on the pinned toolchain; `here-os` and `here-win` cross-check clean for Windows. Not run here: the Windows verifier and the end-to-end suite; the macOS branch of the clock is compiled only on a Mac.
`Instant` is the right clock for a duration inside one waking stretch and the wrong clock
for a timeline: on a Mac it stops while the lid is closed, so an hour asleep read as no time
at all, a record after the nap looked a second after the record before it, and the
indicator's last report — measured against the same clock — looked a second old, so the
gate went on capturing content behind a pill that had not spoken since before the nap.
Wall time does not stop, but it jumps when NTP steps it and lies when it was never set. A
timeline needs a counter that only goes forward, keeps going through sleep, and does not
care what the wall clock thinks: the boot clock.

Every platform has one, and `here_os::tick_ms` reads it — `/proc/uptime` on Linux, which
is `CLOCK_BOOTTIME` read rather than called so the crate stays free of a C binding;
`mach_continuous_time` on macOS; `GetTickCount64` on Windows — and falls back to the
process clock, saying so, anywhere else. Milliseconds since boot: not a time, not comparable
across machines or boots, and that is the point. Every collector stamps it beside `at`, the
gate stores it beside the two wall stamps, and the envelope carries it as `tick_ms`, so two
records from one machine can be ordered and spaced when the wall clock cannot be trusted.

The gate also watches that clock against the process clock. Awake, they advance together;
asleep, the boot clock keeps going and the process clock stops, and the gap is exactly the
nap. When the gap has grown by more than a few seconds since the gate last looked, it writes
a `clock.sleep` decision with the length — a record a fusion client can read, rather than a
hole in `ts_utc` it cannot tell from capture having stopped. On Linux the process clock does
count through sleep, so no decision is written there and the nap shows only as a jump in
`tick_ms`; the module says so.

And the indicator's freshness is measured against the boot clock now, so an hour asleep is
an hour stale, and the first content record after a nap is held until the pill has spoken
again. The staleness test the gate already had still passes; it is the same rule against a
better clock.

Tests: the tick never goes backwards, advances at the rate of time, and counts from boot;
two clocks advancing together are not a nap; an hour on the boot clock against a second
awake is an hour asleep, reported once; a second nap is its own report; jitter is not a nap;
a record carries the collector's tick and the envelope ships it. The nap test fails against
a watch that never reports — checked, by making it one.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
LNK merged commit 7559228fb5 into main 2026-09-04 20:05:50 +00:00
LNK referenced this pull request from a commit 2026-09-04 20:05:51 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
mikebrandon/here-telemetry-rnd!10
No description provided.