Problem
Team enrollment prints the first-sync deadline as a bare local time:
──────────────────────────────────────────────────────────────
PRIVACY - review before first sync
first sync to https://hypaware.hyperparam.app is Jul 23, 2026, 11:59 PM
and includes your backfilled history
to review what ships before then,
open Claude or Codex and run the hypaware-privacy skill
──────────────────────────────────────────────────────────────
Jul 23, 2026, 11:59 PM carries no zone. This is a consent surface (LLP 0100
R1): the reader has to work out how long they have to review captured history
before it leaves the machine, and a wall-clock time with no zone does not tell
them. The ambiguity bites when:
- the host clock is not in the reader's zone (CI runner, shared box, a VM left
on UTC, a laptop that travelled);
- the reader is not the person at the keyboard (pasted output, a screenshot, a
ticket);
- the string is read on a later day than it was computed -
hyp status
re-renders the same text for the life of the hold.
The deadline itself is computed correctly in local time (next local 11:59pm,
rolled a day when under the 4-hour floor) at
src/core/usage-policy/first_sync_hold.js:36. The gap is purely in rendering.
All four user-facing renders go through one formatter, so one fix covers them:
src/core/usage-policy/first_sync_hold.js:57 - formatFirstSyncDeadline,
{ dateStyle: 'medium', timeStyle: 'short' }
src/core/cli/remote_commands.js:198 - the enrolling-login message (R1)
src/core/commands/status.js:385 - the hyp status hold line (R9)
src/core/cli/wizard/index.js:329 - the hyp init privacy narration
Suggested fix
Render the zone in formatFirstSyncDeadline.
Note the implementation constraint: ECMA-402 forbids combining
dateStyle/timeStyle with timeZoneName, so simply adding the option to the
current call throws TypeError: Invalid option : option. Two shapes work:
- Explicit components in one call (recommended - no seconds noise):
new Date(deadlineMs).toLocaleString(undefined, {
year: 'numeric', month: 'short', day: 'numeric',
hour: 'numeric', minute: '2-digit', timeZoneName: 'short',
})
// Jul 23, 2026, 11:59 PM PDT
timeStyle: 'long', which also yields the zone but adds a pointless
seconds field: Jul 23, 2026, 11:59:00 PM PDT.
Option 1, same instant, on hosts in other zones (checked on Node 24):
America/Los_Angeles Jul 23, 2026, 11:59 PM PDT
UTC Jul 24, 2026, 6:59 AM UTC
Europe/London Jul 24, 2026, 7:59 AM GMT+1
Asia/Kolkata Jul 24, 2026, 12:29 PM GMT+5:30
Australia/Sydney Jul 24, 2026, 4:59 PM GMT+10
Zones with no common abbreviation fall back to a GMT offset, which still
answers the question.
The existing assertions compare against formatFirstSyncDeadline(...) rather
than literal time text (test/core/remote-login-command.test.js:888,
test/core/status-first-sync-hold.test.js:78), so a formatter change stays
green. Worth adding a case that pins the rendered deadline as carrying a zone
token at all, so the consent surface cannot silently regress to a bare time.
Secondary, while the line is open: it currently reads first sync to <url> is <time>; at <time> reads better once a zone token is attached.
Boundary
#391 is the other defect in this same printed enrollment block: the forwarding
host rendering as a clickable link that opens a generic 404. This issue is only
the deadline's missing time zone.
The 11:59pm rule and the 4-hour lead floor
(LLP 0101 #deadline) are not
in question here - only how the resulting instant is displayed.
Filed from recorded onboarding feedback. Code references against master @ dd3b438.
Problem
Team enrollment prints the first-sync deadline as a bare local time:
Jul 23, 2026, 11:59 PMcarries no zone. This is a consent surface (LLP 0100R1): the reader has to work out how long they have to review captured history
before it leaves the machine, and a wall-clock time with no zone does not tell
them. The ambiguity bites when:
on UTC, a laptop that travelled);
ticket);
hyp statusre-renders the same text for the life of the hold.
The deadline itself is computed correctly in local time (next local 11:59pm,
rolled a day when under the 4-hour floor) at
src/core/usage-policy/first_sync_hold.js:36. The gap is purely in rendering.All four user-facing renders go through one formatter, so one fix covers them:
src/core/usage-policy/first_sync_hold.js:57-formatFirstSyncDeadline,{ dateStyle: 'medium', timeStyle: 'short' }src/core/cli/remote_commands.js:198- the enrolling-login message (R1)src/core/commands/status.js:385- thehyp statushold line (R9)src/core/cli/wizard/index.js:329- thehyp initprivacy narrationSuggested fix
Render the zone in
formatFirstSyncDeadline.Note the implementation constraint: ECMA-402 forbids combining
dateStyle/timeStylewithtimeZoneName, so simply adding the option to thecurrent call throws
TypeError: Invalid option : option. Two shapes work:timeStyle: 'long', which also yields the zone but adds a pointlessseconds field:
Jul 23, 2026, 11:59:00 PM PDT.Option 1, same instant, on hosts in other zones (checked on Node 24):
Zones with no common abbreviation fall back to a GMT offset, which still
answers the question.
The existing assertions compare against
formatFirstSyncDeadline(...)ratherthan literal time text (
test/core/remote-login-command.test.js:888,test/core/status-first-sync-hold.test.js:78), so a formatter change staysgreen. Worth adding a case that pins the rendered deadline as carrying a zone
token at all, so the consent surface cannot silently regress to a bare time.
Secondary, while the line is open: it currently reads
first sync to <url> is <time>;at <time>reads better once a zone token is attached.Boundary
#391 is the other defect in this same printed enrollment block: the forwarding
host rendering as a clickable link that opens a generic 404. This issue is only
the deadline's missing time zone.
The 11:59pm rule and the 4-hour lead floor
(LLP 0101 #deadline) are not
in question here - only how the resulting instant is displayed.
Filed from recorded onboarding feedback. Code references against
master@dd3b438.