Name today in the HEY account's time zone - #503
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approved
The implementation consistently applies the documented policy and includes broad boundary, fallback, error, and request-count coverage.
Review effort: Balanced
Findings: None
What changed in this PR
Updates date-defaulting commands to use the HEY account’s time zone, preventing UTC-boundary errors.
Changes:
- Adds shared account-zone date resolution with safe read/write fallbacks.
- Updates calendar, habit, journal, todo, and Bubble Up behavior.
- Adds comprehensive tests and documentation.
[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or rungh pr ready --undo.
Click "Ready for review" or rungh pr readyto reengage.
| File | Description |
|---|---|
internal/cmd/account_zone.go |
Adds shared account-zone and today resolution. |
internal/cmd/account_zone_test.go |
Tests date defaults, fallbacks, errors, and request counts. |
internal/cmd/events.go |
Uses account-local today for event defaults. |
internal/cmd/events_period.go |
Sends explicit account-local dates for day/week views. |
internal/cmd/events_period_test.go |
Removes obsolete now behavior test. |
internal/cmd/events_zone.go |
Reuses shared account-zone resolution. |
internal/cmd/events_zone_test.go |
Migrates tests to the shared clock seam. |
internal/cmd/events_occurrence.go |
Uses shared zone lookup for countdown decoding. |
internal/cmd/recording_filter.go |
Supports configurable default-window dates. |
internal/cmd/calendar_commands_test.go |
Supplies identity data for event-list tests. |
internal/cmd/habit.go |
Applies account-local defaults to habit operations. |
internal/cmd/journal.go |
Applies safe account-local journal defaults. |
internal/cmd/journal_test.go |
Adds identity handling to journal fixtures. |
internal/cmd/todo.go |
Explicitly files new todos on account-local today. |
internal/cmd/todo_test.go |
Adds identity handling to todo fixtures. |
internal/cmd/mutation_test.go |
Makes an unrelated todo test date-explicit. |
internal/cmd/bubble.go |
Compares Bubble Up dates against UTC today. |
internal/cmd/bubble_test.go |
Covers UTC versus local-date scheduling. |
docs/cli.md |
Documents account-local default-date behavior. |
skills/hey/SKILL.md |
Updates agent guidance for date defaults. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
hey event day and hey event week sent "now" when no date was given, and HEY reads "now" on a JSON request in UTC, so in New York after 20:00 they showed tomorrow. hey event list, hey habit list, complete and uncomplete, and hey journal read and write took today from the machine's clock instead, and hey todo add left it to the SDK, which does the same. A server's clock and most sandboxes' are UTC, so all of them named tomorrow too. Every command that defaults to today now works it out in the account's time zone, read from the identity once and only when no date is given, and sends the date. The account-zone read moves out of the event fields into an accountZone of its own, which the event writes, the countdown decoding and the new today share. An account with no zone, or one this build does not know, is a lasting state, so a read takes the machine's today there, as HEY's web app takes the browser's, and says so on stderr. A write is refused with a hint to name the date, as an event write already is: marking the wrong day's habit done or writing over the wrong day's journal entry is not a guess to make. A failed read of the identity is refused by both, with the code it failed with, and a sign-in failure stays an auth error. hey bubble up --on compared the date with the machine's today to choose HEY's Later today slot. HEY lays every bubble-up slot out in UTC, so the comparison is with UTC's today now. hey todo list and hey journal list read years either side of today, and an event edit's search reads a year either side, so they keep the machine's clock rather than read the identity for a day's difference at the edge.
14feed4 to
0c10363
Compare
|
Fixed — clarified that resolving an omitted date makes one identity read, while a specific |



mise ~/.config/mise/config.toml tools: gh@2.101.0
Commands that default to today were naming tomorrow in the evening in New York and anywhere else west of UTC.
hey event dayandhey event weeksentnow. HEY readsnowin UTC on a JSON request, so after 20:00 in New York the command showed tomorrow's schedule.hey event list,hey habit list,completeanduncomplete, andhey journal readandwritetook today from the machine's clock.hey todo addleft the date to the SDK, which does the same thing. A server's clock and most sandboxes' clocks run on UTC, so on those machines these commands also named tomorrow.Each of these commands now works out today in the account's time zone and sends that date. This follows the pattern #498 set for event times. Resolving an omitted date reads the identity once for the account's zone; naming the date skips that read. A specific
--accountis validated by a separate identity read before the command runs, so a defaulted command with it reads identity twice and a dated command once.When the account's zone can't be used
event day/week/list,habit list,journal read)habit complete/uncomplete,journal write,todo add)An account with no zone is a lasting state. If reads refused in that case, those commands could never run without a date. Falling back to the machine's date matches what HEY's web app does when an identity has no zone: it uses the browser's zone.
Writes are stricter because a wrong guess does damage. It could mark the wrong day's habit done or overwrite another day's journal entry. #498 already refuses event writes rather than guess.
A failed identity read is temporary, so it is reported as an error with its original code and can be retried, rather than answered with a guessed day.
Also in this PR
accountZoneininternal/cmd/account_zone.go. Event writes, countdown decoding and the new today logic all use it.hey bubble up --on. It compared the date with the machine's today to decide whether to use HEY's Later today slot. HEY lays out every bubble-up slot in UTC, so it now compares with today in UTC.hey todo listandhey journal listread years either side of today, and an event edit searches a year either side. They keep the machine's clock rather than read the identity for one day's difference at the edge.The help text,
docs/cli.mdand the skill describe the new behaviour.Summary by cubic
Commands that default to today now name the HEY account's today instead of tomorrow in the evening west of UTC.
hey event dayandhey event weeksentnow, which HEY reads in UTC on a JSON request; the rest read the machine's clock (UTC on servers and sandboxes), andhey todo addleft the date to the SDK. Every command that defaults to today now reads the account's time zone at most once per command — and not at all when a date is given — and sends that day.event day/week/list,habit list,journal read) fall back to the machine's today with a notice on stderr when the account has no usable zone.habit complete/uncomplete,journal write,todo add) refuse with a hint to name the date instead of guessing.--accountadds one validation read, so a defaulted command reads the identity twice and a dated one once.hey bubble up --onnow picks HEY's Later today slot by comparing with today in UTC, HEY's clock for bubble-up slots.internal/cmd/account_zone.go;hey todo listandhey journal listkeep the machine's clock on purpose.Written for commit 5022ee5. Summary will update on new commits.