[feedback] Model: timestamps get invented from elapsed work; compaction summaries carry them forward as facts

Status Open
Maintainer reply None cached
Activity 4 comments · opened Sep 28, 2026

Context. Solo-operator project using Claude Code (desktop app, Windows 11) with a lead session on Claude Fable 5.1 orchestrating Opus 5.5 / Sonnet subagents (in-process, worktree-isolated), a JSON task store (~1,100 records), PreToolUse/SubagentStop hooks and a harvest-train commit flow. Everything below was measured on 2026-09-28 in one session of ~20 dispatches, two blind judge pairs and nine commits. Numbers are from tool output, not recollection; no secrets or private paths included.

Finding. The lead model (Fable 5.1) labelled rulings and log lines with times estimated from elapsed work instead of reading a clock, twice in one day and after a written lesson; a compaction summary then repeated the invented times with full confidence and the next context re-used them.

Evidence (measured). Labels ran 20-40 minutes ahead of date -u at 05:2x-06:1xZ; pre-compaction labels ran hours ahead (a '13:0x local' label for a 04:40Z run). The only true record was the timestamp field a hook wrote on each board write.

Reproduction. Ask the model to log a timestamped decision after ~20 minutes of work without telling it to read a clock; compare with the wall clock. Compact; ask for that decision's time.

Ask. (1) A model that writes a time reads a clock in the same step (or the harness injects the time). (2) A compaction summary grades each fact MEASURED or RECALLED and carries the source for measured ones. (3) After compaction, the model re-measures any clock or count before re-using it.

View original on GitHub ↗

3 Comments

Studytempest · 16 days ago

Independent confirmation from a different setup (macOS, not Windows), with transcript-derived numbers. Adds a day-level case where a compaction summary carried a wrong date forward, not only wrong times.

Setup. Claude Code on macOS (Darwin 25.6), versions 2.1.247 to 2.1.283, single user, long research sessions that write dated log lines, status headings and commit messages. Models seen in the affected turns: claude-fable-5-1, claude-opus-5, claude-opus-5-5. The machine clock is fine (about 8 s off NTP); git author/committer times are all consistent with the transcript timestamps. The problem is only in times the model types into files and commit messages.

Method. For every assistant tool_use (Bash command, Write content, Edit new_string) in the session JSONL files, extract each YYYY-MM-DD HH:MM stamp and compare it with that record's own timestamp field converted to local time (UTC+8). A stamp more than 3 minutes after the moment it was written cannot be a record of a past event. Stamps that are genuinely about the future (appointments, deadlines, scheduled jobs, quota reset times) were excluded by keyword and by hand; stamps suffixed Z were counted separately.

Minute-level result (2026-08-30 to 2026-09-28, 12 main sessions, subagents not included).

  • Of 560 minute-level stamps written within the window from 3 h before to 48 h after the writing moment, 136 were more than 3 min ahead of the clock at the moment of writing.
  • Median lead 11 min; 87 were 3 to 15 min ahead, 38 were 15 to 60 min ahead, 11 were more than 60 min ahead, the largest was exactly one day ahead (09-06 09:30 written at 09-05 09:29).
  • Typical shape: the user sends a message at 19:52:45 local; 58 s later the model commits a log row "owner 2026-09-18 20:05". The last date output in context was from about 2.5 h earlier.
  • 3 more stamps were local wall time labelled as UTC (...Z), i.e. 16 h off.
  • It recurs after written corrections: the same workspace has a project rule "the date in a new file name or heading is the output of date", written after the day-level incident below; minute-level leads still appear up to today.

Day-level result (one afternoon/evening, 2026-09-14 local).

  • From 14:18 local the model began labelling the user's rulings "2026-09-15 early"; the clock said 09-14.
  • A compaction at 20:55 local produced a summary whose file names and headings already said 09-15; about an hour later the model advanced the label to "2026-09-16 early" (21:56) and kept using it.
  • Between 12:00 and 24:00 that day, 81 of 237 commit subjects and 423 committed file paths carry 09-15 or 09-16. The model noticed it at 22:50, right after a date call, and wrote an erratum; the files were left unrenamed so existing path citations stay valid, so the wrong dates are now permanent in the history.

Why this matters. These stamps are written in the same form as measured facts ("owner 2026-09-18 20:05", "checked 2026-09-27 23:55"), so later sessions, compaction summaries and other agents read them as provenance. The day-level case shows the compaction summary turning a guessed date into the date the next context works from.

Ask (agreeing with the above, plus one point).

  1. Inject the current local time with offset on every user turn (as proposed in #75281), not only the date at session start.
  2. A compaction summary should not restate a date or time unless it came from tool output, and should say which it is.
  3. After compaction, re-anchor the date from the clock rather than from the summary.

Related: #92732 (same class, macOS, Opus 5), #75281 (per-turn time injection).

eyeskull2220 · 8 days ago

Update, 8 days later, same project, same effect, now with a mechanism that catches it.

After the original report we wrote the rule "read the clock before typing a time" into memory and a lesson file. It kept recurring. Counts come from the typed text compared with the git commit timestamps of the same work (Windows 11, Claude Code 2.1.290 at the time of this comment):

  • 5 Oct: clock times written from memory, about one hour off (the incident that produced the lesson).
  • 6 Oct, 5 incidents in about 3 h 10 min:
  1. ~20:15: six ruling rows, 11 times typed 5-15 minutes ahead of the real time, with the label "clock read" written next to estimated times.
  2. 22:12: "fixed 22:20" written at 22:12 (8 minutes in the future).
  3. 22:21-22:23: three times (22:25, 22:27, 22:31) typed into a brief, a task and a status report.
  4. 23:21: a log row stamped 23:25.
  5. 23:25: a log line stamped 23:27, two minutes after the model had just corrected incident 4 in the same file.
  • Denominator: 6 incidents in 2 days; 4 of them came after the lesson was written that same evening, and incident 5 came right after the model had fixed incident 4.

New vs the issue: a written rule did not hold, even when it was in context. The model fills the time from its sense of elapsed work, and that drifts ahead. What does work for us now is a mechanical check: before every commit, a small script reads the added lines, and any time on today's date that lies after the system clock is refused (a time written down can never be later than the commit that records it). It caught the next slip at once. It cannot catch a guessed time in the past.

This agrees with the macOS data above (136 of 560 stamps ahead): the error is directional (ahead), which fits "estimated from elapsed work" rather than random noise.

Ask unchanged: when the model writes a time, it should read a clock in that same step; or the harness should inject the local time with offset every turn (#75281), so the estimate is never needed.

eyeskull2220 · 8 days ago

Thank you for the careful numbers; they are stronger than ours, and the macOS data answers the "Windows only?" question. Your point that it recurs after a written rule matches ours exactly: 6 incidents in 2 days, 4 of them after we had written the lesson that same evening (details in the comment above). Our errors are also all ahead of the clock, like your 136 of 560. We agree with all three asks, in particular per-turn local time with offset (#75281). What finally holds for us is mechanical, not a rule: a pre-commit check that refuses any time on today's date that lies after the system clock.

Showing cached comments. Read the full discussion on GitHub ↗