From 76299a4e44758cfd7398599df5b5ce9ec6a1b4a0 Mon Sep 17 00:00:00 2001 From: iliya Date: Sun, 31 May 2026 00:14:16 +0300 Subject: [PATCH] fix(team): align runtime telemetry tests with process rows --- src/main/services/team/TeamTaskReader.ts | 4 +- .../TeamAgentLaunchMatrix.safe-e2e.test.ts | 120 +++++++++++------- 2 files changed, 79 insertions(+), 45 deletions(-) diff --git a/src/main/services/team/TeamTaskReader.ts b/src/main/services/team/TeamTaskReader.ts index 11b97a52..df565c57 100644 --- a/src/main/services/team/TeamTaskReader.ts +++ b/src/main/services/team/TeamTaskReader.ts @@ -48,8 +48,8 @@ interface CachedTaskFile { task: TeamTask | null; } -function cloneTasks(tasks: T[]): T[] { - return structuredClone(tasks); +function cloneTasks(tasks: readonly T[]): T[] { + return structuredClone([...tasks]); } function cloneTask(task: TeamTask): TeamTask { diff --git a/test/main/services/team/TeamAgentLaunchMatrix.safe-e2e.test.ts b/test/main/services/team/TeamAgentLaunchMatrix.safe-e2e.test.ts index 102765b6..2d79bf35 100644 --- a/test/main/services/team/TeamAgentLaunchMatrix.safe-e2e.test.ts +++ b/test/main/services/team/TeamAgentLaunchMatrix.safe-e2e.test.ts @@ -78,13 +78,33 @@ const WORKSPACE_TRUST_TEST_ENV_NAMES = [ type WorkspaceTrustTestEnvName = (typeof WORKSPACE_TRUST_TEST_ENV_NAMES)[number]; type RuntimeUsageStatsForTest = { rssBytes: number; cpuPercent?: number }; +type RuntimeUsageProcessRowForTest = RuntimeUsageStatsForTest & { + pid: number; + ppid: number; + command: string; + runtimeTelemetrySource?: 'native' | 'wsl' | 'windows-host'; +}; type RuntimeUsageStatsStubTarget = { - readRuntimeProcessRowsForUsageSnapshot: () => Promise; + aliveRunByTeam?: Map; + provisioningRunByTeam?: Map; + runs?: Map; + getLiveTeamAgentRuntimeMetadata?: ( + teamName: string + ) => Promise>; + readRuntimeProcessRowsForUsageSnapshot: ( + teamName: string + ) => Promise; readProcessUsageStatsByPid: ( pids: readonly number[] ) => Promise>; }; +function addRuntimeUsagePidForTest(pids: Set, pid: unknown): void { + if (typeof pid === 'number' && Number.isFinite(pid) && pid > 0) { + pids.add(pid); + } +} + function createRuntimeUsageStatsMap( entries: readonly (readonly [number, number])[] ): Map { @@ -93,23 +113,53 @@ function createRuntimeUsageStatsMap( function stubRuntimeUsageStatsByPid( service: TeamProvisioningService, - entries: readonly (readonly [number, number])[] + entries: readonly (readonly [number, number])[] = [] ): void { - const statsByPid = createRuntimeUsageStatsMap(entries); + const configuredStatsByPid = createRuntimeUsageStatsMap(entries); const target = service as unknown as RuntimeUsageStatsStubTarget; - target.readRuntimeProcessRowsForUsageSnapshot = async () => null; + + target.readRuntimeProcessRowsForUsageSnapshot = async (teamName: string) => { + const statsByPid = new Map(configuredStatsByPid); + const candidatePids = new Set(); + const runId = target.aliveRunByTeam?.get(teamName) ?? target.provisioningRunByTeam?.get(teamName); + const run = runId ? target.runs?.get(runId) : undefined; + addRuntimeUsagePidForTest(candidatePids, run?.child?.pid); + + const liveMetadataByMember = await target.getLiveTeamAgentRuntimeMetadata?.(teamName); + for (const metadata of liveMetadataByMember?.values() ?? []) { + addRuntimeUsagePidForTest(candidatePids, metadata.pid); + addRuntimeUsagePidForTest(candidatePids, metadata.metricsPid); + } + + for (const pid of candidatePids) { + if (!statsByPid.has(pid)) { + statsByPid.set(pid, { rssBytes: pid * 1_000 }); + } + } + + return [...statsByPid].map(([pid, stats]) => ({ + pid, + ppid: 0, + command: `test-runtime-${pid}`, + ...stats, + runtimeTelemetrySource: 'native' as const, + })); + }; + target.readProcessUsageStatsByPid = async (pids: readonly number[]) => { const requestedPids = new Set(pids); - return new Map([...statsByPid].filter(([pid]) => requestedPids.has(pid))); + return new Map( + [...pids] + .filter((pid) => Number.isFinite(pid) && pid > 0) + .map((pid) => [ + pid, + configuredStatsByPid.get(pid) ?? { rssBytes: pid * 1_000 }, + ] as const) + .filter(([pid]) => requestedPids.has(pid)) + ); }; } -function createRuntimeUsageStatsByPid( - pids: readonly number[] -): Map { - return createRuntimeUsageStatsMap(pids.map((pid) => [pid, pid * 1_000] as const)); -} - describe('Team agent launch matrix safe e2e', () => { let tempDir: string; let tempClaudeRoot: string; @@ -14709,8 +14759,7 @@ describe('Team agent launch matrix safe e2e', () => { ['alice', { alive: true, pid: 64102, model: 'haiku-stale' }], ['bob', { alive: true, pid: 64103, model: 'sonnet-stale' }], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const staleSnapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(staleSnapshot).toMatchObject({ @@ -14758,8 +14807,7 @@ describe('Team agent launch matrix safe e2e', () => { ['alice', { alive: true, pid: 64502, model: 'haiku-before-stop' }], ['bob', { alive: true, pid: 64503, model: 'sonnet-before-stop' }], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const beforeStop = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(beforeStop).toMatchObject({ @@ -14885,8 +14933,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const afterSwitch = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(afterSwitch).toMatchObject({ @@ -14935,8 +14982,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const afterSwitch = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(afterSwitch).toMatchObject({ @@ -14976,8 +15022,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const snapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(snapshot.members.alice).toMatchObject({ @@ -15014,8 +15059,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const snapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(snapshot.members.alice).toMatchObject({ @@ -15050,8 +15094,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const snapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(snapshot.members.bob).toMatchObject({ @@ -15086,8 +15129,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const snapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(snapshot.members.bob).toMatchObject({ @@ -15131,8 +15173,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const snapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(snapshot.members.reviewer).toMatchObject({ @@ -15176,8 +15217,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const snapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(snapshot.members.reviewer).toMatchObject({ @@ -15312,8 +15352,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const afterSwitch = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(afterSwitch).toMatchObject({ @@ -15362,8 +15401,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const afterSwitch = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(afterSwitch).toMatchObject({ @@ -15406,8 +15444,7 @@ describe('Team agent launch matrix safe e2e', () => { }, ], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const snapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(snapshot).toMatchObject({ @@ -15451,8 +15488,7 @@ describe('Team agent launch matrix safe e2e', () => { ['bob', { alive: true, pid: 64704, model: 'opencode/minimax-stale' }], ['tom', { alive: true, pid: 64705, model: 'opencode/nemotron-stale' }], ]); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const staleSnapshot = await svc.getTeamAgentRuntimeSnapshot(teamName); expect(staleSnapshot).toMatchObject({ @@ -15576,8 +15612,7 @@ describe('Team agent launch matrix safe e2e', () => { ['bob', { alive: true, pid: 50203, model: 'sonnet-runtime' }], ] ); - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const firstSnapshot = await svc.getTeamAgentRuntimeSnapshot(firstTeamName); const secondSnapshot = await svc.getTeamAgentRuntimeSnapshot(secondTeamName); @@ -15656,8 +15691,7 @@ describe('Team agent launch matrix safe e2e', () => { ] ); }; - (svc as any).readProcessUsageStatsByPid = async (pids: number[]) => - createRuntimeUsageStatsByPid(pids); + stubRuntimeUsageStatsByPid(svc); const beforeStop = await svc.getTeamAgentRuntimeSnapshot(stoppedTeamName); expect(beforeStop.members['team-lead']).toMatchObject({