Repository navigation
fix(sleep): compare the harvest cutoff with transcript times as instants - #389
Yifan Yang (Yif-Yang) merged 2 commits into
Conversation
The nightly cycle stores its harvest cutoff with state._now_iso, which
writes local time with no offset. Claude Code, Codex and Pi transcripts
record UTC ("...Z"), and their harvesters compared the two as strings,
which shifts the cutoff by the host's UTC offset. East of UTC, a session
that ended in the hours after a harvest compared as older than the
cutoff and was never harvested; west of UTC, sessions were harvested
again.
Parse both sides to epoch seconds (a naive value in the host timezone,
"Z" as UTC), as the Copilot, Cursor and OpenCode harvesters already do,
and keep the string comparison only for values that cannot be parsed.
test_a_source_still_skips_what_it_already_harvested wrote local time
with a "Z" suffix, which only passed because of this bug; it now writes
UTC.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Muhammad Abdullah Butt (@1AbdullahButt) please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
Keep both CHANGELOG entries; no other change.
|
Merged, thank you. The harvest cutoff is now compared with transcript timestamps as instants rather than as strings, so a host in a non-UTC timezone no longer skips or re-reads sessions near the checkpoint, with a string-comparison fallback for unparseable values. On |
Fixes #387
The nightly cycle stores its harvest cutoff with
state._now_iso, which writes local time with no offset. Claude Code, Codex and Pi transcripts record UTC (...Z), and their harvesters compared the two as strings. That shifts the cutoff by the host's UTC offset:The fix adds
_iso_epoch/_ended_beforetoharvest.pyand uses them in the Claude Code, Codex and Pi harvesters. Both values are parsed to epoch seconds: a naive value is read in the host timezone, andZas UTC. This is what the Copilot, Cursor and OpenCode harvesters already do. Values that cannot be parsed fall back to the old string comparison.test_a_source_still_skips_what_it_already_harvestedwrotedatetime.now()(local time) with aZsuffix, which only passed because of this bug. Its fixture now writes UTC.Tests
tests/test_harvest_cutoff_timezone.pypins the process timezone to UTC+5 withtime.tzset()(or runs on a host east of UTC wheretzsetis missing, otherwise skips). For each of the three harvesters, it checks that a session ending one minute after the cutoff is kept and one ending one minute before is dropped. All 3 fail onmainand pass with this change, both on Windows at UTC+5 and on Linux (python:3.11-slim, UTC host viatzset).python -m pytest -q: All 3 new tests fail onmainand pass here. Full suite on Linux (python:3.11-slim): 2077 passed; the same 11 tests fail on unmodifiedmainin that container (Devin installer, run-sleep fallback, reproducibility CLI: environment-dependent, unrelated). On Windows the harvest and sleep-engine tests pass apart from failures that also occur onmain.This change was written with Claude Code.
🤖 Generated with Claude Code