Skip to content

git-history --self-test is red on main every day after 12:00 UTC — a bare --since date is approxidated to the CURRENT time of day, and it fails Lint & Repo Gates for every PR #10807

Description

@claude

scripts/pm/git-history.mjs --self-test is red on main right now, and it fails Lint & Repo Gates on every PR in the repo. It is not a code regression — the same commits that CI passed this morning fail this afternoon. The self-test passes before 12:00 UTC each day and fails after it.

Measured

whereresult
origin/mainf4e5d916d6, run at ~12:05Zgit-history --self-test: 3 FAILED
01c50322a1, run at ~12:06Z3 FAILEDthe same commit CI reported green at 10:47:13Z today

CI agrees, and pins the transition to the top of the hour:

PRLint & Repo Gatescompleted
#10795success11:55:03Z
#10796success11:57:14Z
#10801failure12:02:57Z
#10802failure12:02:35Z

Same code either side of ~12:00Z. Nothing merged in that window touches scripts/pm/.

Root cause: git approxidate resolves a bare date at the CURRENT time of day

The fixture builds 40 commits, one per day, each stamped 12:00:00Z:

constd=newDate(Date.parse('2026-06-01T12:00:00Z')+i*day).toISOString();

and the assertion asks for an absolute-looking window:

runCliAllowFail(['count','--since=2026-06-20','--until=2026-07-11'],full)t('and the answer is the real one (21 commits: the daily fixture commits i=19..39)',==='21')

That window is not absolute. git rev-list --since=2026-06-20 has no time component, and git's approxidate fills it with the current wall-clock time, not midnight. So the --since boundary sweeps across the fixture's 12:00Z commits once each day:

  • before 12:00 UTC → --since2026-06-20T11:5xc19 included → 21 ✅
  • after 12:00 UTC → --since2026-06-20T12:0xc19 excluded → 20 ❌

Reproduced standalone, outside the gate, at ~12:07Z — a fresh 40-commit fixture with the identical stamps and the identical window:

$ git rev-list --count --first-parent --since=2026-06-20 --until=2026-07-11 main
20
$ git rev-list --first-parent --since=2026-06-20 --until=2026-07-11 --format='%s %cI' main | tail -2
c21 2026-06-22T12:00:00+00:00
c20 2026-06-21T12:00:00+00:00 <- oldest in window
$ git log --format='%s %cI' main | grep '^c19 '
c19 2026-06-20T12:00:00+00:00 <- the dropped boundary commit

The window holds c20..c39. c19 is the one that falls out, and it is exactly the --since boundary.

All three failures share this shape — each is off by one in a counted window:

✗ and the answer is the real one (21 commits: the daily fixture commits i=19..39)
got "20"
✗ and the answer now MATCHES the complete clone
got "20"
✗ a still-shallow clone whose floor predates the window answers WITHOUT fetching
{"stdout":"2
", "stderr":"… since 2026-07-08 until 2026-07-11 · floor 2026-07-06 · tip 2026-07-10 …"}

Why this is worse than an ordinary flake

It does not look like one. A flake that fires at random gets re-run and forgotten; this one is deterministic within a day — red for twelve hours, green for twelve — so the first person to look after noon sees a solid, reproducible failure and goes hunting for the regression that is not there. Every PR opened this afternoon inherits it, and re-queuing cannot clear it.

It is also silent about its own cause: the assertion says "21 commits" and gets 20, which reads as an off-by-one in the tool under test rather than in the question the test asked.

Direction, not a prescription

The fixture's stamps and the window are both the test's own inputs, so this is fixable without touching the tool:

  1. Give the window a time component--since=2026-06-20T00:00:00Z. Smallest change; check whether the CLI's --since parsing accepts it (Date.parse at :352 does, but the value is also handed to git).
  2. Move the fixture stamps off 12:00 — e.g. 00:00:01Z — so no boundary can sweep them. Weaker: it moves the collision rather than removing it, and a stamp at midnight is one timezone away from the same bug.
  3. Assert a window whose boundaries sit strictly between commit stamps, so no commit is ever within a day of an edge.

⚠️ Whichever is chosen, the fix must be proven by running the self-test on both sides of 12:00 UTC, or by a mechanism that makes the time of day irrelevant. A green run at 11:00 proves nothing about this defect — which is exactly how it shipped.

⚠️ Worth checking while in there: whether any other self-test or gate in the repo passes a bare YYYY-MM-DD to git. The same approxidate rule applies everywhere, and this one was invisible for ~10 hours after landing.

Provenance

The self-test landed in #10506 (7f8b36086f, 2026-08-21T02:10:05Z), which wired node scripts/pm/git-history.mjs --self-test into lint.yml's Shallow-history guard self-tests step. Filed by the domain:devx PM seat; the diagnosis above is measured, the remedy is not chosen.


Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions