SCA-364: render Desktop Chat SQL timestamps in the user timezone - #12326
SCA-364: render Desktop Chat SQL timestamps in the user timezone#12326Git-on-my-level wants to merge 3 commits into
Conversation
execute_sql dumped UTC-naive SQLite DATETIME cells, so Desktop Chat quoted 7:59 PM for a 3:59 PM Eastern event. Convert timestamp/*At cells in the tool result, keep filters UTC-vs-UTC, and put the live clock only on the per-turn # Current Time prefix. Failure-Class: FC-machine-timezone-timestamp-in-prompt Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
The new formatter is used by execute_sql result projection on the chat-hermetic path; list it so the flow-coverage ratchet stays closed. Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
origin/main currently fails desktop-swiftlint on the IUO added with the owner-fenced history seed. Use a regular optional so the lint gate can run on this branch. Failure-Class: none Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
| const parsed = Date.parse(`${naive[1]}T${naive[2]}Z`) | ||
| if (Number.isFinite(parsed)) return new Date(parsed) | ||
| } | ||
| const iso = Date.parse(trimmed) |
There was a problem hiding this comment.
On Windows this turns a date-only cell into the previous calendar day: formatSqlTimestampCell('captureDate', '2026-08-27', 'America/New_York') returns 2026-08-26 8:00:00 PM EDT. The Swift parser only accepts values that include a time, so please keep date-only values unchanged (or render them as calendar dates without timezone conversion) and add this fixture.
| lines.push( | ||
| row | ||
| .map((cell, index) => { | ||
| const formatted = formatSqlTimestampCell(columns[index] ?? '', cell, timeZone) |
There was a problem hiding this comment.
This per-cell path constructs two Intl.DateTimeFormat instances. On this Windows machine, 20,000 timestamp cells (200 rows x 100 model-controlled aliases) took 2.09 seconds synchronously; because execute_sql caps rows but not columns and runs in Electron main, prompt-injected SQL can freeze the UI. Please cap columns or total rendered cells and cache formatter instances by timezone.
| * Eastern event (#12321). Always convert in an injected IANA zone and label it. | ||
| */ | ||
|
|
||
| const TIMESTAMP_COLUMN = /^(timestamp|ts|.*(?:At|_at|Date|_date))$/ |
There was a problem hiding this comment.
TIMESTAMP and TS are not recognized here because this regex is case-sensitive, while Swift explicitly matches them case-insensitively. A model can alias ts AS TIMESTAMP and leave the exact unlabeled-UTC bug on Windows; a case-insensitive match plus a parity fixture would close it.
|
#12349 has now landed the narrower formatter. While validating its interaction with this PR's macOS changes, I reproduced the remaining double-localization/local-day boundary gap as #12350 and opened #12351 as a focused post-merge follow-up, including a pinned non-UTC fixture and runtime SELECT-projection guard; this PR still contains the broader cross-surface work. |
Summary
Desktop Chat treated UTC-naive SQLite DATETIME cells as local wall-clock, so “when did I last open Claude?” quoted 7:59:51 PM for a 3:59:51 PM EDT instant.
This PR converts
timestamp/*Atcells inexecute_sql(and the matching Windows renderer) into the user’s timezone with an explicit IANA/offset label, repairs SQL “today/yesterday” examples so filters stay UTC-vs-UTC, and keeps the live clock on the per-turn# Current Timeprefix instead of the cached system prompt.Test plan
2026-08-27T19:59:51Z+America/New_York:execute_sql/formatRowscontain3:59:51 PMand a zone token; must not present unlabeled7:59:51 PMChatPromptsTests— cached desktop prompt has no{current_datetime_str}; SQL examples compare UTC columns to UTC boundsdesktopChatPrompt.test.ts+sql.test.ts(88 tests)make preflighton this branchLine-Count-Exception: desktop/macos/Desktop/Sources/Providers/ChatToolExecutor.swift | 3439 -> 3441 | thread display timezone through execute_sql and keep daily-recap bounds UTC-vs-UTC
Product invariants affected
Failure-Class: FC-machine-timezone-timestamp-in-prompt
Closes #12321
Related: #4643, #12236 (do not close)
SCA-364