// SPEC: PJ2026-01060505 Workbench performance; PJ2026-010401080313 Workbench realtime authority. // Responsibility: Deterministic L0 timing for session tag switching, Kafka replay, and session rail refresh. import type { ChatMessage, TraceEvent, WorkbenchSessionRecord } from "../src/types/index.ts"; import { projectWorkbenchLiveKafkaMessage, projectWorkbenchLiveKafkaUserMessage, projectWorkbenchLiveKafkaUserSession } from "../src/stores/workbench-live-kafka-event.ts"; import { createWorkbenchServerState, reduceWorkbenchServerState, selectActiveMessages, selectActiveSession, selectSessionList, type WorkbenchServerState } from "../src/stores/workbench-server-state.ts"; import { mergeSessionIntoList, sessionToSessionTab, sortSessionTabs } from "../src/stores/workbench-session.ts"; interface SampleSummary { p50: number; p95: number; max: number; } interface ReplayFixture { sessionId: string; traceId: string; events: TraceEvent[]; } const rounds = positiveInteger(process.env.HWLAB_L0_PERF_ROUNDS, 30); const warmupRounds = positiveInteger(process.env.HWLAB_L0_PERF_WARMUP, 8); const sessionScales = [40, 100, 500]; const messagesPerSession = positiveInteger(process.env.HWLAB_L0_PERF_MESSAGES, 40); const replayEventCounts = [100, 500, 1_000]; const output: Record = { contractVersion: "workbench-l0-session-performance-v1", runtime: `bun-${Bun.version}`, rounds, warmupRounds, messagesPerSession, units: "milliseconds", sessionScales: {}, replayScales: {} }; for (const sessionCount of sessionScales) { const sessions = sessionFixtures(sessionCount, messagesPerSession); const state = reduceWorkbenchServerState(createWorkbenchServerState(), { type: "session.list", sessions }); const activeIds = sessions.map((session) => session.sessionId); let switchIndex = 0; const activeSwitch = measure(() => { const activeSessionId = activeIds[switchIndex % activeIds.length] ?? null; switchIndex += 1; const activeSession = selectActiveSession(state, activeSessionId); const messages = selectActiveMessages(state, activeSessionId); const tabs = sortSessionTabs(selectSessionList(state), activeSessionId, state.sessionStatusById); consume(activeSession?.sessionId, messages.length, tabs[0]?.key); }); const projection = measure(() => { const tabs = sessions.map((session) => sessionToSessionTab(session, sessions[0]?.sessionId ?? null)); consume(tabs[0]?.label, tabs.at(-1)?.updatedAt); }); const sort = measure(() => { const tabs = sortSessionTabs(sessions, sessions[0]?.sessionId ?? null); consume(tabs[0]?.key, tabs.at(-1)?.key); }); const railRefresh = measure(() => { const refreshed = refreshRailWithUserEvent(state, sessionCount - 1); consume(refreshed.state.sessionOrder.length, refreshed.tabs[0]?.label); }); (output.sessionScales as Record)[String(sessionCount)] = { projectTabs: projection, projectAndSortTabs: sort, activeTagSwitch: activeSwitch, kafkaUserEventAndRailRefresh: railRefresh }; } for (const eventCount of replayEventCounts) { const fixture = replayFixture(eventCount); const result = measure(() => { const replayed = replayKafkaEvents(fixture); consume(replayed.state.sessionOrder.length, replayed.message?.runnerTrace?.events?.length, replayed.tabs[0]?.status); }, Math.min(rounds, eventCount >= 1_000 ? 12 : rounds), Math.min(warmupRounds, 4)); (output.replayScales as Record)[String(eventCount)] = result; } console.log(JSON.stringify(output, null, 2)); function refreshRailWithUserEvent(initial: WorkbenchServerState, targetIndex: number): { state: WorkbenchServerState; tabs: ReturnType } { const sessionId = initial.sessionOrder[targetIndex] ?? initial.sessionOrder[0] ?? "ses_perf_0"; const traceId = `trc_refresh_${targetIndex}`; const event: TraceEvent = { type: "user", eventType: "user", messageId: `msg_refresh_${targetIndex}`, userMessageId: `msg_refresh_${targetIndex}`, text: "refresh rail title", createdAt: "2026-07-20T12:00:00.000Z", sessionId, projectedSeq: 1 }; const previousMessages = initial.messagesBySessionId[sessionId] ?? []; const userMessage = projectWorkbenchLiveKafkaUserMessage({ previous: null, traceId, sessionId, event, receivedAt: "2026-07-20T12:00:00.010Z" }); if (!userMessage) throw new Error("user replay fixture did not project"); let state = reduceWorkbenchServerState(initial, { type: "message.upsert", sessionId, message: userMessage }); const sessions = selectSessionList(state); const existing = sessions.find((session) => session.sessionId === sessionId) ?? null; const projectedSession = projectWorkbenchLiveKafkaUserSession({ previous: existing, message: userMessage, sessionId }); if (!projectedSession) throw new Error("user session fixture did not project"); state = reduceWorkbenchServerState(state, { type: "session.list", sessions: mergeSessionIntoList(sessions, { ...projectedSession, messages: [...previousMessages, userMessage] }) }); return { state, tabs: sortSessionTabs(selectSessionList(state), sessionId, state.sessionStatusById) }; } function replayKafkaEvents(fixture: ReplayFixture): { state: WorkbenchServerState; message: ChatMessage | null; tabs: ReturnType } { let state = createWorkbenchServerState(); state = reduceWorkbenchServerState(state, { type: "session.detail", session: { sessionId: fixture.sessionId, messages: [] } }); let agentMessage: ChatMessage | null = null; for (const event of fixture.events) { if (event.type === "user") { const userMessage = projectWorkbenchLiveKafkaUserMessage({ previous: null, traceId: fixture.traceId, sessionId: fixture.sessionId, event, receivedAt: String(event.createdAt) }); if (!userMessage) throw new Error("replay user fixture did not project"); state = reduceWorkbenchServerState(state, { type: "message.upsert", sessionId: fixture.sessionId, message: userMessage }); const session = projectWorkbenchLiveKafkaUserSession({ previous: selectActiveSession(state, fixture.sessionId), message: userMessage, sessionId: fixture.sessionId }); if (session) state = reduceWorkbenchServerState(state, { type: "session.list", sessions: mergeSessionIntoList(selectSessionList(state), session) }); continue; } agentMessage = projectWorkbenchLiveKafkaMessage({ previous: agentMessage, traceId: fixture.traceId, sessionId: fixture.sessionId, event, receivedAt: String(event.createdAt), turnStartedAt: String(fixture.events[0]?.createdAt) }); state = reduceWorkbenchServerState(state, { type: "message.upsert", sessionId: fixture.sessionId, message: agentMessage }); } return { state, message: agentMessage, tabs: sortSessionTabs(selectSessionList(state), fixture.sessionId, state.sessionStatusById) }; } function replayFixture(eventCount: number): ReplayFixture { const sessionId = `ses_replay_${eventCount}`; const traceId = `trc_replay_${eventCount}`; const events: TraceEvent[] = [{ type: "user", eventType: "user", messageId: `msg_replay_${eventCount}_user`, userMessageId: `msg_replay_${eventCount}_user`, text: "measure retention replay", createdAt: timestamp(0), sessionId, projectedSeq: 1 }]; for (let index = 1; index < eventCount; index += 1) { const terminal = index === eventCount - 1; events.push({ type: terminal ? "result" : index % 5 === 0 ? "assistant_progress" : "event", eventType: terminal ? "terminal" : index % 5 === 0 ? "assistant_progress" : "backend", text: index % 5 === 0 ? `progress ${index}` : undefined, finalResponse: terminal ? { text: "completed replay" } : undefined, status: terminal ? "completed" : "running", terminal, createdAt: timestamp(index), projectedSeq: index + 1, sourceSeq: index + 1, source: "agentrun.event.v1", sessionId, traceId }); } return { sessionId, traceId, events }; } function sessionFixtures(sessionCount: number, messageCount: number): WorkbenchSessionRecord[] { return Array.from({ length: sessionCount }, (_, sessionIndex) => { const sessionId = `ses_perf_${sessionIndex}`; const messages = Array.from({ length: messageCount }, (_, messageIndex) => messageFixture(sessionId, sessionIndex, messageIndex)); return { sessionId, threadId: `thr_perf_${sessionIndex}`, status: sessionIndex % 11 === 0 ? "running" : "completed", lastTraceId: `trc_perf_${sessionIndex}_${messageCount - 1}`, messageCount, messages, firstUserMessagePreview: `session ${sessionIndex} title`, lastUserMessageAt: timestamp(sessionIndex * 100 + messageCount - 2), updatedAt: timestamp(sessionIndex * 100 + messageCount - 1) }; }); } function messageFixture(sessionId: string, sessionIndex: number, messageIndex: number): ChatMessage { const role = messageIndex % 2 === 0 ? "user" : "agent"; const traceId = `trc_perf_${sessionIndex}_${Math.floor(messageIndex / 2)}`; return { id: `msg_perf_${sessionIndex}_${messageIndex}`, messageId: `msg_perf_${sessionIndex}_${messageIndex}`, role, title: role === "user" ? "用户" : "Code Agent", text: role === "user" ? `session ${sessionIndex} prompt ${messageIndex}` : `response ${messageIndex}`, status: role === "user" ? "sent" : messageIndex === messagesPerSession - 1 && sessionIndex % 11 === 0 ? "running" : "completed", traceId, sessionId, createdAt: timestamp(sessionIndex * 100 + messageIndex) }; } function measure(operation: () => void, sampleRounds = rounds, warmups = warmupRounds): SampleSummary { for (let index = 0; index < warmups; index += 1) operation(); const samples: number[] = []; for (let index = 0; index < sampleRounds; index += 1) { const startedAt = Bun.nanoseconds(); operation(); samples.push((Bun.nanoseconds() - startedAt) / 1_000_000); } samples.sort((left, right) => left - right); return { p50: rounded(percentile(samples, 0.5)), p95: rounded(percentile(samples, 0.95)), max: rounded(samples.at(-1) ?? 0) }; } function percentile(samples: number[], ratio: number): number { return samples[Math.min(samples.length - 1, Math.max(0, Math.ceil(samples.length * ratio) - 1))] ?? 0; } function positiveInteger(value: string | undefined, fallback: number): number { const parsed = Number(value); return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback; } function timestamp(offsetSeconds: number): string { return new Date(Date.UTC(2026, 6, 20, 0, 0, offsetSeconds)).toISOString(); } function rounded(value: number): number { return Math.round(value * 1_000) / 1_000; } function consume(...values: unknown[]): void { if (values.length === Number.MIN_SAFE_INTEGER) console.log(values); }