Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { appMeta, AppWithMocks } from "@/browser/stories/meta.js";
import { setupSimpleChatStory } from "@/browser/stories/helpers/chatSetup";
import { createAssistantMessage, createUserMessage } from "@/browser/stories/mocks/messages";
import { createTerminalTool } from "@/browser/stories/mocks/tools";
import { STABLE_TIMESTAMP } from "@/browser/stories/mocks/workspaces";
import { NOW, STABLE_TIMESTAMP } from "@/browser/stories/mocks/workspaces";

const meta = {
...appMeta,
Expand Down Expand Up @@ -49,7 +49,7 @@ export const BackgroundProcesses: AppStory = {
script:
"export NODE_ENV=development\nexport PORT=3000\nnpm run dev -- --host 0.0.0.0 --port $PORT",
displayName: "Dev Server",
startTime: Date.now() - 45000, // 45 seconds ago
startTime: NOW - 45000, // 45 seconds ago
monitor: {
filter: "FAILED|ERROR",
filter_exclude: false,
Expand All @@ -67,14 +67,14 @@ export const BackgroundProcesses: AppStory = {
pid: 12346,
script: "npm test -- --watch",
displayName: "Test Runner",
startTime: Date.now() - 30000, // 30 seconds ago
startTime: NOW - 30000, // 30 seconds ago
status: "running",
},
{
id: "bash_3",
pid: 12347,
script: "tail -f /var/log/app.log",
startTime: Date.now() - 120000, // 2 minutes ago
startTime: NOW - 120000, // 2 minutes ago
status: "running",
},
],
Expand Down
11 changes: 10 additions & 1 deletion src/browser/components/LeftSidebar/LeftSidebar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,16 @@ interface LeftSidebarStoryOverrides {

// Vite re-evaluates this module on story edits; use a fresh token so the shell
// can deterministically remount provider state after each hot update.
const MODULE_RENDER_TOKEN = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
const MODULE_RENDER_TOKEN = (() => {
// Vite HMR re-evaluates this module; bump hot.data so provider trees remount
// after edits. Pixel/CI has no import.meta.hot, so the token stays stable.
if (import.meta.hot) {
const nextGeneration = (Number(import.meta.hot.data.renderGeneration) || 0) + 1;
import.meta.hot.data.renderGeneration = nextGeneration;
return `storybook-left-sidebar-${NOW}-hmr-${nextGeneration}`;
}
return `storybook-left-sidebar-${NOW}`;
})();

function LeftSidebarStoryScene(props: { leftSidebarProps?: LeftSidebarStoryOverrides }) {
const { userProjects } = useProjectContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { AppStory } from "@/browser/stories/meta.js";
import { PIXEL_DUAL_THEME, appMeta, AppWithMocks } from "@/browser/stories/meta.js";
import { expandProjects } from "@/browser/stories/helpers/uiState";
import { createMockORPCClient } from "@/browser/stories/mocks/orpc";
import { createWorkspace, groupWorkspacesByProject } from "@/browser/stories/mocks/workspaces";
import { NOW, createWorkspace, groupWorkspacesByProject } from "@/browser/stories/mocks/workspaces";

const PROJECT_PATH = "/home/user/projects/my-app";

Expand Down Expand Up @@ -239,7 +239,7 @@ export const WorkflowRunGroups: AppStory = {
reviewRun("wf-claims", "claims", {
title: "Extract claims",
taskStatus: "reported",
createdAt: new Date(Date.now() - 8 * 60_000).toISOString(),
createdAt: new Date(NOW - 8 * 60_000).toISOString(),
}),
createWorkspace({
id: "wf-tests",
Expand All @@ -248,13 +248,13 @@ export const WorkflowRunGroups: AppStory = {
title: "Run test matrix",
parentWorkspaceId: "ws-main",
taskStatus: "running",
createdAt: new Date(Date.now() - 6 * 60_000).toISOString(),
createdAt: new Date(NOW - 6 * 60_000).toISOString(),
workflowTask: { runId: "wfr_legacy567890", stepId: "tests" },
}),
reviewRun("wf-verify", "verify", {
title: "Verify claims",
taskStatus: "running",
createdAt: new Date(Date.now() - 5 * 60_000).toISOString(),
createdAt: new Date(NOW - 5 * 60_000).toISOString(),
}),
createWorkspace({
id: "var-a",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { getMCPTestResultsKey } from "@/common/constants/storage";
import type { MCPServerInfo } from "@/common/types/mcp";

import { WorkspaceMCPModal } from "./WorkspaceMCPModal";
import { NOW } from "@/browser/stories/storyTime";

const PROJECT_PATH = "/Users/test/my-app";
const WORKSPACE_ID = "ws-mcp-test";
Expand Down Expand Up @@ -78,7 +79,7 @@ function setupWorkspaceMCPModalStory(options: WorkspaceMCPStoryOptions = {}): AP
for (const [serverName, tools] of Object.entries(options.testResults)) {
cachedResults[serverName] = {
result: { success: true, tools },
testedAt: Date.now(),
testedAt: NOW,
};
}

Expand Down
6 changes: 4 additions & 2 deletions src/browser/features/Messages/TranscriptDensity.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
createProposePlanTool,
createWebSearchTool,
} from "@/browser/stories/mocks/tools";
import { STABLE_TIMESTAMP } from "@/browser/stories/mocks/workspaces";
import { NOW, STABLE_TIMESTAMP } from "@/browser/stories/mocks/workspaces";
import { TRANSCRIPT_DENSITY_KEY, type TranscriptDensity } from "@/common/constants/storage";

const meta = { ...appMeta, title: "App/Chat/Transcript Density" };
Expand Down Expand Up @@ -200,7 +200,9 @@ export const HyperEdgeCaseGallery: AppStory = {
setup={() => {
collapseLeftSidebar();
setDensity("hyper");
const activeStartedAt = Date.now() - 39_000;
// Base on NOW (not STABLE_TIMESTAMP) so the active bundle stays ~39s old and
// renders seconds rather than crossing into "1m …" elapsed formatting.
const activeStartedAt = NOW - 39_000;
return setupSimpleChatStory({
messages: [
// Scenario 1: critical events remain visible in hyper density.
Expand Down
14 changes: 7 additions & 7 deletions src/browser/features/RightSidebar/GoalTab.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
} from "@/common/types/goal";

import { GoalTab } from "./GoalTab";
import { NOW } from "@/browser/stories/storyTime";

const meta: Meta<typeof GoalTab> = {
title: "Features/RightSidebar/GoalTab",
Expand Down Expand Up @@ -64,7 +65,7 @@ const STATE_VARIANTS: GalleryVariant[] = [
costCents: 0,
turnsUsed: 0,
turnCap: null,
startedAtMs: Date.now(),
startedAtMs: NOW,
},
},
{
Expand All @@ -77,7 +78,7 @@ const STATE_VARIANTS: GalleryVariant[] = [
costCents: 125,
turnsUsed: 3,
turnCap: 10,
startedAtMs: Date.now() - 90_000,
startedAtMs: NOW - 90_000,
},
},
{
Expand All @@ -90,7 +91,7 @@ const STATE_VARIANTS: GalleryVariant[] = [
costCents: 125,
turnsUsed: 3,
turnCap: null,
startedAtMs: Date.now(),
startedAtMs: NOW,
},
},
{
Expand All @@ -103,7 +104,7 @@ const STATE_VARIANTS: GalleryVariant[] = [
costCents: 525,
turnsUsed: 4,
turnCap: 10,
startedAtMs: Date.now() - 120_000,
startedAtMs: NOW - 120_000,
},
},
{
Expand All @@ -117,7 +118,7 @@ const STATE_VARIANTS: GalleryVariant[] = [
turnsUsed: 5,
turnCap: null,
completionSummary: "The lifecycle controls shipped with persistence and tests.",
startedAtMs: Date.now(),
startedAtMs: NOW,
},
},
{
Expand All @@ -130,7 +131,7 @@ const STATE_VARIANTS: GalleryVariant[] = [
costCents: 150,
turnsUsed: 2,
turnCap: null,
startedAtMs: Date.now() - 30_000,
startedAtMs: NOW - 30_000,
},
},
];
Expand Down Expand Up @@ -167,7 +168,6 @@ export const States: Story = {
// ─────────────────────────────────────────────────────────────────────────

const STORY_WORKSPACE_ID = "ws-story-goaltab";
const NOW = Date.UTC(2026, 4, 20, 12, 0, 0);

function makeBoardGoal(
overrides: Partial<GoalRecordV1> & Pick<GoalRecordV1, "goalId">
Expand Down
19 changes: 11 additions & 8 deletions src/browser/features/RightSidebar/Memory/MemoryTab.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
} from "@/common/orpc/schemas/memory";

import { EXPERIMENT_IDS, getExperimentKey } from "@/common/constants/experiments";
import { NOW } from "@/browser/stories/storyTime";
import { MemoryTab } from "./MemoryTab";

const meta: Meta<typeof MemoryTab> = {
Expand All @@ -27,22 +28,24 @@ const STORY_WORKSPACE_ID = "ws-story-memorytab";
// Multi-file fixture covering every row permutation the tree cares about:
// all three scopes, root files, a dir with multiple files, two-level nesting,
// a pinned file, with/without descriptions, and used/never-used usage stats.
// Use the storybook NOW fixture (preview also stubs Date.now) so relative
// access labels stay stable even if a path bypasses the stub.
const MEMORY_FILES: MemoryFileInfo[] = [
{
path: "/memories/global/preferences.md",
scope: "global",
description: "Coding style and tooling preferences",
pinned: true,
accessCount: 12,
lastAccessedAt: Date.now() - 3_600_000,
lastAccessedAt: NOW - 3_600_000,
},
{
path: "/memories/global/people/reviewers.md",
scope: "global",
description: "Preferred reviewers per code area",
pinned: false,
accessCount: 3,
lastAccessedAt: Date.now() - 86_400_000,
lastAccessedAt: NOW - 86_400_000,
},
{
path: "/memories/global/people/teammates.md",
Expand All @@ -58,15 +61,15 @@ const MEMORY_FILES: MemoryFileInfo[] = [
description: "High-level architecture notes",
pinned: false,
accessCount: 5,
lastAccessedAt: Date.now() - 600_000,
lastAccessedAt: NOW - 600_000,
},
{
path: "/memories/project/conventions.md",
scope: "project",
description: "Repo conventions distilled from AGENTS.md",
pinned: false,
accessCount: 7,
lastAccessedAt: Date.now() - 7_200_000,
lastAccessedAt: NOW - 7_200_000,
},
{
path: "/memories/project/testing.md",
Expand All @@ -82,12 +85,12 @@ const MEMORY_FILES: MemoryFileInfo[] = [
description: "Notes for the current branch work",
pinned: false,
accessCount: 1,
lastAccessedAt: Date.now() - 60_000,
lastAccessedAt: NOW - 60_000,
},
];

const CONSOLIDATION_RECORD: MemoryConsolidationRecordPayload = {
lastRunAt: Date.now() - 30 * 60 * 1000,
lastRunAt: NOW - 30 * 60 * 1000,
trigger: "manual",
summary: "Merged duplicate project notes",
ops: [{ command: "delete", path: "/memories/project/duplicate.md", applied: true }],
Expand All @@ -107,8 +110,8 @@ function renderTab(width: string) {
globalRecord: CONSOLIDATION_RECORD,
latestHarvestRecord: {
status: "completed",
startedAt: Date.now() - 45 * 60 * 1000,
completedAt: Date.now() - 44 * 60 * 1000,
startedAt: NOW - 45 * 60 * 1000,
completedAt: NOW - 44 * 60 * 1000,
attemptCount: 1,
boundaryKey: "summary-story",
compactionEpoch: 3,
Expand Down
5 changes: 3 additions & 2 deletions src/browser/features/RightSidebar/RightSidebar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { expect, userEvent, waitFor, within } from "@storybook/test";
import type { ComponentType, ReactNode } from "react";
import { useEffect, useRef } from "react";
import { RightSidebar } from "./RightSidebar.js";
import { NOW } from "@/browser/stories/storyTime";

const meta: Meta = {
title: "Features/RightSidebar/RightSidebar",
Expand Down Expand Up @@ -637,7 +638,7 @@ export const ReviewTabSortByLastEdit: Story = {
// Clear persisted layout to ensure review tab appears in fresh default layout
const workspaceId = "ws-review-sort";
localStorage.removeItem(getRightSidebarLayoutKey(workspaceId));
const now = Date.now();
const now = NOW;

// Set up first-seen timestamps for hunks (oldest to newest: format -> button -> client)
// We use placeholder IDs since exact hash depends on content
Expand Down Expand Up @@ -1330,7 +1331,7 @@ export const CompactionModelWarning: Story = {
* Helper to create realistic output log entries with mixed levels and locations.
*/
function createOutputLogEntries() {
const now = Date.now();
const now = NOW;

return [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { MCPOAuthAuthStatus } from "@/common/types/mcpOauth";
import type { Secret } from "@/common/types/secrets";

import { MCPSettingsSection } from "./MCPSettingsSection";
import { NOW } from "@/browser/stories/storyTime";

const MOCK_TOOLS = [
"file_read",
Expand Down Expand Up @@ -72,7 +73,7 @@ function setupMCPSettingsSectionStory(options: MCPSectionStoryOptions = {}): API
for (const [serverName, tools] of Object.entries(options.testResults)) {
cachedResults[serverName] = {
result: { success: true, tools },
testedAt: Date.now(),
testedAt: NOW,
};
}

Expand Down Expand Up @@ -400,7 +401,7 @@ export const ProjectSettingsOAuthLoggedIn: Story = {
serverUrl: "https://example.com/mcp",
isLoggedIn: true,
hasRefreshToken: true,
updatedAtMs: Date.now() - 60_000,
updatedAtMs: NOW - 60_000,
},
],
]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createMockORPCClient } from "@/browser/stories/mocks/orpc";
import type { MemoryFileInfo } from "@/common/orpc/schemas/memory";
import { MemorySection } from "./MemorySection.js";
import { SettingsSectionStory } from "./settingsStoryUtils.js";
import { NOW } from "@/browser/stories/storyTime";

// Settings → Memory only manages the global scope (no workspace context),
// so the fixture is global files only — incl. a nested path, a pinned file,
Expand All @@ -16,15 +17,15 @@ const GLOBAL_MEMORY_FILES: MemoryFileInfo[] = [
description: "Coding style and tooling preferences",
pinned: true,
accessCount: 12,
lastAccessedAt: Date.now() - 3_600_000,
lastAccessedAt: NOW - 3_600_000,
},
{
path: "/memories/global/people/reviewers.md",
scope: "global",
description: "Preferred reviewers per code area",
pinned: false,
accessCount: 3,
lastAccessedAt: Date.now() - 86_400_000,
lastAccessedAt: NOW - 86_400_000,
},
{
path: "/memories/global/glossary.md",
Expand Down
3 changes: 2 additions & 1 deletion src/browser/features/Tools/Bash/BashToolCall.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BashBackgroundTerminateToolCall } from "@/browser/features/Tools/BashBa
import { BashOutputToolCall } from "@/browser/features/Tools/BashOutputToolCall";
import { BashToolCall } from "@/browser/features/Tools/BashToolCall";
import { lightweightMeta } from "@/browser/stories/meta.js";
import { NOW } from "@/browser/stories/storyTime";

const meta = {
...lightweightMeta,
Expand Down Expand Up @@ -144,7 +145,7 @@ export const IntentExecutingSummary: Story = {
display_name: "Dev server readiness",
}}
status="executing"
startedAt={Date.now() - 1_000}
startedAt={NOW - 1_000}
/>
</ToolStoryShell>
),
Expand Down
Loading