feat(dashboard): align base refresh to wall-clock minute boundary

Instead of a fixed 60s interval from an arbitrary start offset, the base status
refresh now fires on each wall-clock minute boundary (:00), keeping the
minute-precision timestamp shown in the message accurate. Event-driven updates
(new message / agent activity) still refresh in between. Adds
msUntilNextMinuteBoundary with tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-08-21 13:01:02 +09:00
parent 65ef6e8830
commit d57dd68fc0
2 changed files with 29 additions and 1 deletions

View File

@@ -840,6 +840,16 @@ export function createCoalescingTrigger(
};
}
/**
* Milliseconds from `nowMs` until the next wall-clock minute boundary (:00).
* Minute boundaries align across timezones (offsets are whole minutes), so this
* is timezone-agnostic. Exactly on a boundary returns a full minute.
*/
export function msUntilNextMinuteBoundary(nowMs: number): number {
const rem = nowMs % 60_000;
return rem === 0 ? 60_000 : 60_000 - rem;
}
export async function startUnifiedDashboard(
opts: UnifiedDashboardOptions,
): Promise<void> {
@@ -989,7 +999,15 @@ export async function startUnifiedDashboard(
);
}
setInterval(updateStatus, opts.statusUpdateInterval);
// Base periodic refresh fires on each wall-clock minute boundary (:00) so the
// minute-precision timestamp shown in the status message stays accurate.
const scheduleMinuteBoundaryUpdate = () => {
setTimeout(() => {
void updateStatus();
scheduleMinuteBoundaryUpdate();
}, msUntilNextMinuteBoundary(Date.now()));
};
scheduleMinuteBoundaryUpdate();
setInterval(() => {
if (!isRenderer || !statusMessageId) return;
void cleanupDashboardDuplicateMessages(opts, statusMessageId);