test: fix time-of-day flake in the durable-headline project-filter tests - #875
Conversation
…day proof The tests added in getagentseal#864 seeded today's live session at a fixed wall-clock hour (12:00 local). The periods they build end at `new Date()`, and the suite runs under TZ=UTC, so for any run before 12:00 UTC that timestamp is in the FUTURE and the range filter correctly drops it. The live half of the cache/live union then contributes nothing, and the one assertion that needs a non-zero headline — the unattributed-cost footnote — fell into renderOverview's "No usage found" early return and went red. Half of every day was a failing window; a769b50 fixed the start-of-month flake but this one survived it. Verified by bisecting the fixture on the unpatched test: moving the seeded hour from 12:00 to 01:00 (past, at a 03:38 UTC run) turns the same 12 tests green, so the timestamp's position relative to `now` is the whole cause. - Seed the session a few minutes BEFORE now, clamped to today's midnight, so it is always both inside today and already in the past. - Stop the footnote test depending on the live parse at all: seed a second, attributable cached day so the headline is non-zero from the cache alone. The test now exercises the footnote instead of the fixture's timing.
iamtoruk
left a comment
There was a problem hiding this comment.
Correct — this fixes a real second flake that survived my #864 test fix (a769b50), not a duplicate of it. The tests seeded today's live session at a fixed 12:00 local while the periods end at new Date(), so under TZ=UTC any run before noon put that timestamp in the future, the range filter dropped it, and the live half of the cache/live union contributed $0 — which sent the unattributedCostUSD footnote test into renderOverview's "No usage found" early return.
Reproduced the mechanism deterministically (a future-dated live session → durable.data.cost=0, unattributedCostUSD=100), and confirmed your fix: relative-and-clamped live timestamps stay in the past at every hour, and seeding a second attributable cached day keeps the headline non-zero from the cache alone so the footnote assertion no longer depends on the live parse. All 12 pass; tsc clean; test-only. Good to merge.
Summary
12:00local) while the periods they build end atnew Date(), and the suite runs underTZ=UTC— so on any run before 12:00 UTC that timestamp is in the future, the range filter correctly drops it, and the live half of the cache/live union contributes nothing.$0, the one assertion that needs a non-zero total — theunattributedCostUSDfootnote — hitsrenderOverview'sNo usage foundearly return and goes red. a769b50 fixed the start-of-month flake in the same file; this one survived it.Testing
npm testpassesnpm run buildsucceedsnpm test: 2,537 passed, 5 failed — none in this file; the 12 tests here are green. The 5 areparser.test.ts×2 (the pre-existing pair you already noted),cli-durable-totals.test.ts"resolves provider filters identically" (fails onmain, unrelated —parseAllSessionsreturns nothing for a today-only range once the on-disk session cache is warm), andcache-refresh-lock.test.ts×2 (lock/timing, flaky here run-to-run).npx tsc --noEmitclean.Evidence
Bisected the fixture on the unpatched test file, at a 03:38 UTC run:
now12:00(as merged)1 failed | 11 passed01:0012 passedNothing else changed, so the timestamp's position relative to
nowis the entire cause. A direct probe ofparseAllSessionsconfirms the mechanism — same fixture, same run:I also tried to demonstrate this across timezones and got misled:
TZ=...has no effect because the vitest config pinsTZ=UTC, so every "timezone" run was the same 03:37 UTC morning. The bisect above is the reliable evidence.Fix
max(today's midnight, now − 10min), so the session is always inside today and already in the past, at every hour.Sorry for the follow-up on my own tests; this was mine to catch, not yours.