diff --git a/apps/mcp-server/src/tui/dashboard-app.spec.tsx b/apps/mcp-server/src/tui/dashboard-app.spec.tsx
index 2b4070da..9940ddf0 100644
--- a/apps/mcp-server/src/tui/dashboard-app.spec.tsx
+++ b/apps/mcp-server/src/tui/dashboard-app.spec.tsx
@@ -159,6 +159,25 @@ describe('DashboardApp', () => {
expect(frame).not.toContain('/from-state');
});
+ it('memoizes now based on tick to avoid non-deterministic re-renders', () => {
+ const dateNowSpy = vi.spyOn(Date, 'now').mockReturnValue(1700000000000);
+
+ const state = createInitialDashboardState();
+ const { lastFrame, rerender } = render();
+ const frame1 = lastFrame() ?? '';
+
+ // Advance Date.now() by 1 minute — but tick has NOT changed (still 0 from mock)
+ dateNowSpy.mockReturnValue(1700000060000);
+ rerender();
+ const frame2 = lastFrame() ?? '';
+
+ // With useMemo([tick]): now stays cached → frames identical
+ // Without useMemo: now = Date.now() changes → time display differs
+ expect(frame1).toBe(frame2);
+
+ dateNowSpy.mockRestore();
+ });
+
it('should use externalState when provided (multi-session mode)', () => {
const mockState = createInitialDashboardState();
// Modify some fields to verify they propagate
diff --git a/apps/mcp-server/src/tui/dashboard-app.tsx b/apps/mcp-server/src/tui/dashboard-app.tsx
index 1e849ae8..352726ff 100644
--- a/apps/mcp-server/src/tui/dashboard-app.tsx
+++ b/apps/mcp-server/src/tui/dashboard-app.tsx
@@ -27,7 +27,7 @@ export function DashboardApp({
}: DashboardAppProps): React.ReactElement {
const { columns, rows, layoutMode } = useTerminalSize();
const tick = useTick(1000);
- const now = Date.now();
+ const now = useMemo(() => Date.now(), [tick]);
const internalState = useDashboardState(externalState ? undefined : eventBus);
const state = externalState ?? internalState;
const focusedAgent = state.focusedAgentId