Skip to content

Windows shell: read daemon createdAt as reference-date seconds - #641

Merged
coneilen merged 1 commit into
mainfrom
coneilen-fix-windows-loop-age-epoch
Oct 6, 2026
Merged

coneilen merged 1 commit into
mainfrom
coneilen-fix-windows-loop-age-epoch

Conversation

@coneilen

@coneilen coneilen commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

In the Windows shell, a loop created seconds earlier showed idle 11323d in the sidebar and elapsed >1h in the loop bar. That was seen on the beta10 Dev Box qualification. The daemon encodes Date with JSONEncoder's default strategy, which writes seconds since 2001-01-01, and the shell read createdAt as Unix seconds. 11323 days is the 978,307,200-second gap between the two epochs. This PR converts the value to Unix seconds where GraphModel parses it, so the sidebar, loop cards, attention rail, loop detail start time, and workspace loop bar all show the correct age.

Changes

  • GraphModel.zig: createdAt now goes through unixSecondsFromReferenceDate, which parses the number as a float, floors fractional seconds, and adds 978,307,200. These values decode as unknown (null): 0, which is the reference date itself and the placeholder that StarterTemplates.swift stamps; negative values; non-numeric values; and values whose Unix result would reach 1e12. Before this change, -1 and non-numbers were already unknown.
  • I checked the label helpers' millisecond heuristic (GraphCanvas.elapsedLabel/startTimeLabel, TerminalSurface.elapsedLabel). They multiply values below 1e12 by 1000. Converted values are always Unix seconds below 1e12, so the heuristic stays correct and I left it unchanged. TerminalSurface.zig is not modified. It reads the same converted Node.created_at.
  • I checked other daemon Date fields. Quick chats' createdAt is not parsed. lastOpenedAt is only validated in WorkspaceManager/Forms and never displayed. Activity timestamps come from the local std.time.timestamp(). WorkspaceLifecycle creation times come from Windows APIs. None of these changed.
  • Tests: three new tests, one each in GraphModel, Sidebar, and GraphCanvas. Two existing GraphModel expectations were written assuming Unix seconds; createdAt 12.5 and 123 now expect 978307212 and 978307323. Shared Swift (GraphcodeKit/) is unchanged, and macOS is unaffected.

Test plan

All commands ran from graphcode-windows with Zig 0.15.2 ($env:GRAPHCODE_ZIG0152), using the flags that Tools/windows/Tests/WindowsShell.Tests.ps1 uses for each root. The include dir is C:\gc-providers\winghostty\include.

RED: zig test src\Sidebar.zig -target x86_64-windows-msvc -lc -luser32 -lgdi32 -I...\winghostty\include --test-filter "loop row age reads" -> 1/1 FAIL, expected "5s", instead found "11323d"
GREEN: same Sidebar command, plus zig test src\GraphModel.zig --test-filter "reference-date" and zig test src\GraphCanvas.zig -target x86_64-windows-msvc -lc -I...\winghostty\include --test-filter "just-created daemon" -> each 1/1 passed
REGRESSION: full unfiltered roots zig test src\GraphModel.zig, src\Sidebar.zig, src\GraphCanvas.zig with the same flags -> 154/154, 185/185, 206/206 passed

The other two RED runs failed the same way before the fix:

  • GraphModel --test-filter "reference-date": expected 1791219880, found 812912680.
  • GraphCanvas --test-filter "just-created daemon": expected 0m, found >1d.

Limits:

  • These are unit tests only. No live UI was observed, and GraphCode is not installed on the test machine.
  • I did not run the TerminalSurface.zig and App.zig test roots locally because they need a built ghostty-vt-static.lib. CI covers them.
  • I did not run zig build of the shell or validate.ps1 -Task windows-shell.
  • I did not run make test or make check because this change is Windows-only Zig.

Checklist

  • I have read the Contributing Guidelines
  • I have signed off my commits (git commit -s) per the DCO
  • Tests pass locally (make test): not run, because this is a Windows-only Zig change. The focused Zig roots above pass.
  • Code follows the existing style (make check): not run, because make check lints Swift only. The change follows the surrounding Zig style.
  • I added the test/contract before the implementation and observed the intended RED failure

The daemon encodes Date with JSONEncoder's default strategy, seconds since
2001-01-01, but the Windows shell treated a loop's createdAt as Unix seconds.
A loop created moments earlier therefore showed "idle 11323d" in the sidebar
and "elapsed >1h" in the loop bar: 11323 days is the 978,307,200-second gap
between the two epochs.

Convert at the GraphModel parse boundary so every consumer sees Unix seconds.
Fractional values are floored; the reference date itself (the starter-template
placeholder), earlier values, out-of-range values and non-numbers stay unknown.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Colin Neilens <coneilen@microsoft.com>
@coneilen
coneilen force-pushed the coneilen-fix-windows-loop-age-epoch branch from d509f1f to a0cacc0 Compare October 6, 2026 23:31
@coneilen
coneilen merged commit 194a34c into main Oct 6, 2026
30 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant