From 6de618315a4264ee0e7f4a26f16f2422d8649947 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 28 Jul 2026 14:07:02 -0400 Subject: [PATCH] refactor: centralize isolated agent test ownership (#115340) --- scripts/lib/ci-node-test-plan.mjs | 26 ++-- scripts/run-vitest.mjs | 23 +-- scripts/test-projects.test-support.mjs | 81 +++++----- test/scripts/ci-node-test-plan.test.ts | 27 ++-- test/scripts/test-projects.test.ts | 4 +- test/vitest-projects-config.test.ts | 27 ++++ test/vitest-scoped-config.test.ts | 4 +- .../vitest.agents-core-isolated.config.ts | 9 +- test/vitest/vitest.agents-core.config.ts | 11 +- ...s-embedded-agent-incomplete-turn.config.ts | 9 +- ...bedded-agent-overflow-compaction.config.ts | 9 +- ...vitest.agents-embedded-agent-run.config.ts | 9 +- .../vitest.agents-embedded-agent.config.ts | 18 +-- test/vitest/vitest.agents-paths.d.mts | 34 +++-- test/vitest/vitest.agents-paths.mjs | 142 ++++++++++++++---- test/vitest/vitest.agents-support.config.ts | 11 +- test/vitest/vitest.agents-tools.config.ts | 9 +- test/vitest/vitest.agents.config.ts | 9 +- test/vitest/vitest.config.ts | 10 +- test/vitest/vitest.test-shards.mjs | 11 +- 20 files changed, 290 insertions(+), 193 deletions(-) diff --git a/scripts/lib/ci-node-test-plan.mjs b/scripts/lib/ci-node-test-plan.mjs index 3343fe8000db..008fbbda6aec 100644 --- a/scripts/lib/ci-node-test-plan.mjs +++ b/scripts/lib/ci-node-test-plan.mjs @@ -1,6 +1,9 @@ // Builds CI node/Vitest shard plans from the full suite configuration. import { relative } from "node:path"; -import { agentsCoreIsolatedTestFiles } from "../../test/vitest/vitest.agents-paths.mjs"; +import { + agentVitestProjectOwners, + embeddedAgentVitestProjectOwners, +} from "../../test/vitest/vitest.agents-paths.mjs"; import { commandsLightTestFiles } from "../../test/vitest/vitest.commands-light-paths.mjs"; import { fullSuiteVitestShards } from "../../test/vitest/vitest.test-shards.mjs"; import { toolingIsolatedTestFiles } from "../../test/vitest/vitest.tooling-isolated-paths.mjs"; @@ -523,7 +526,7 @@ function resolveAgentCoreShardName(file) { } function createAgentCoreSplitShards() { - const isolatedTests = new Set(agentsCoreIsolatedTestFiles); + const isolatedTests = new Set(agentVitestProjectOwners.coreIsolated.include); const groups = new Map(); for (const file of listTestFiles("src/agents")) { const name = relative("src/agents", file).replaceAll("\\", "/"); @@ -553,7 +556,7 @@ function createAgentCoreSplitShards() { if (shardName === "agentic-agents-core-runner-cli") { return createStripedBatches(includePatterns, AGENTS_CORE_RUNNER_CLI_STRIPES).map( (batch, index) => ({ - configs: ["test/vitest/vitest.agents-core.config.ts"], + configs: [agentVitestProjectOwners.core.config], includePatterns: batch, requiresDist: false, shardName: `${shardName}-${index + 1}`, @@ -562,7 +565,7 @@ function createAgentCoreSplitShards() { } return [ { - configs: ["test/vitest/vitest.agents-core.config.ts"], + configs: [agentVitestProjectOwners.core.config], includePatterns, requiresDist: false, shardName, @@ -574,8 +577,8 @@ function createAgentCoreSplitShards() { return [ ...sharedShards, { - configs: ["test/vitest/vitest.agents-core-isolated.config.ts"], - includePatterns: agentsCoreIsolatedTestFiles, + configs: [agentVitestProjectOwners.coreIsolated.config], + includePatterns: agentVitestProjectOwners.coreIsolated.include, requiresDist: false, shardName: "agentic-agents-core-isolated", }, @@ -1192,23 +1195,18 @@ const SPLIT_NODE_SHARDS = new Map([ ...createAgentCoreSplitShards(), { shardName: "agentic-agents-embedded", - configs: [ - "test/vitest/vitest.agents-embedded-agent.config.ts", - "test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts", - "test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts", - "test/vitest/vitest.agents-embedded-agent-run.config.ts", - ], + configs: embeddedAgentVitestProjectOwners.map((owner) => owner.config), env: AGENTS_EMBEDDED_AGENT_ENV, requiresDist: false, }, { shardName: "agentic-agents-support", - configs: ["test/vitest/vitest.agents-support.config.ts"], + configs: [agentVitestProjectOwners.support.config], requiresDist: false, }, { shardName: "agentic-agents-tools", - configs: ["test/vitest/vitest.agents-tools.config.ts"], + configs: [agentVitestProjectOwners.tools.config], requiresDist: false, }, { diff --git a/scripts/run-vitest.mjs b/scripts/run-vitest.mjs index b7dfd5f860b7..e6c436717c00 100644 --- a/scripts/run-vitest.mjs +++ b/scripts/run-vitest.mjs @@ -5,6 +5,7 @@ import fs from "node:fs"; import { createRequire } from "node:module"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import { embeddedAgentVitestProjectOwners } from "../test/vitest/vitest.agents-paths.mjs"; import { toolingIsolatedTestFiles } from "../test/vitest/vitest.tooling-isolated-paths.mjs"; import { isUiTestTarget } from "../test/vitest/vitest.ui-paths.mjs"; import { boundaryTestFiles } from "../test/vitest/vitest.unit-paths.mjs"; @@ -39,22 +40,6 @@ const GATEWAY_SERVER_VITEST_CONFIG = "test/vitest/vitest.gateway-server.config.t const GATEWAY_VITEST_CONFIG = "test/vitest/vitest.gateway.config.ts"; export const VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS = new Map([ ["test/vitest/vitest.e2e.config.ts", DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS], - [ - "test/vitest/vitest.agents-embedded-agent.config.ts", - DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS, - ], - [ - "test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts", - DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS, - ], - [ - "test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts", - DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS, - ], - [ - "test/vitest/vitest.agents-embedded-agent-run.config.ts", - DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS, - ], [GATEWAY_VITEST_CONFIG, DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS], ["test/vitest/vitest.ui-e2e.config.ts", DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS], ["test/vitest/vitest.full-agentic.config.ts", DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS], @@ -70,6 +55,12 @@ export const VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS = new Map([ [GATEWAY_CORE_VITEST_CONFIG, DEFAULT_EXTRA_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS], [GATEWAY_SERVER_VITEST_CONFIG, DEFAULT_EXTRA_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS], ]); +for (const owner of embeddedAgentVitestProjectOwners) { + VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS.set( + owner.config, + DEFAULT_LONG_RUNNING_VITEST_NO_OUTPUT_TIMEOUT_MS, + ); +} export const TOOLING_EXCLUDED_TESTS = new Set([ ...boundaryTestFiles, "test/scripts/docker-build-helper.test.ts", diff --git a/scripts/test-projects.test-support.mjs b/scripts/test-projects.test-support.mjs index 3749d6efde62..1cf2d5188827 100644 --- a/scripts/test-projects.test-support.mjs +++ b/scripts/test-projects.test-support.mjs @@ -7,9 +7,8 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { - agentsCoreIsolatedTestFiles, - agentsEmbeddedIncompleteTurnTestFiles, - agentsEmbeddedOverflowCompactionTestFiles, + agentVitestProjectOwners, + embeddedAgentVitestProjectOwners, isAgentsCoreIsolatedTestFile, } from "../test/vitest/vitest.agents-paths.mjs"; import { isChannelSurfaceTestFile } from "../test/vitest/vitest.channel-paths.mjs"; @@ -90,19 +89,18 @@ import { } from "./run-vitest.mjs"; const DEFAULT_VITEST_CONFIG = "test/vitest/vitest.unit.config.ts"; -const AGENTS_EMBEDDED_AGENT_TEST_ROOT = "src/agents/embedded-agent-runner"; -const AGENTS_CORE_ISOLATED_VITEST_CONFIG = "test/vitest/vitest.agents-core-isolated.config.ts"; -const AGENTS_CORE_VITEST_CONFIG = "test/vitest/vitest.agents-core.config.ts"; -const AGENTS_EMBEDDED_AGENT_VITEST_CONFIG = "test/vitest/vitest.agents-embedded-agent.config.ts"; +const AGENTS_EMBEDDED_AGENT_TEST_ROOT = agentVitestProjectOwners.embedded.root; +const AGENTS_CORE_ISOLATED_VITEST_CONFIG = agentVitestProjectOwners.coreIsolated.config; +const AGENTS_CORE_VITEST_CONFIG = agentVitestProjectOwners.core.config; +const AGENTS_EMBEDDED_AGENT_VITEST_CONFIG = agentVitestProjectOwners.embedded.config; const AGENTS_EMBEDDED_AGENT_INCOMPLETE_TURN_VITEST_CONFIG = - "test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts"; + agentVitestProjectOwners.embeddedIncompleteTurn.config; const AGENTS_EMBEDDED_AGENT_OVERFLOW_COMPACTION_VITEST_CONFIG = - "test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts"; -const AGENTS_EMBEDDED_AGENT_RUN_VITEST_CONFIG = - "test/vitest/vitest.agents-embedded-agent-run.config.ts"; -const AGENTS_SUPPORT_VITEST_CONFIG = "test/vitest/vitest.agents-support.config.ts"; -const AGENTS_TOOLS_VITEST_CONFIG = "test/vitest/vitest.agents-tools.config.ts"; -const AGENTS_VITEST_CONFIG = "test/vitest/vitest.agents.config.ts"; + agentVitestProjectOwners.embeddedOverflowCompaction.config; +const AGENTS_EMBEDDED_AGENT_RUN_VITEST_CONFIG = agentVitestProjectOwners.embeddedRun.config; +const AGENTS_SUPPORT_VITEST_CONFIG = agentVitestProjectOwners.support.config; +const AGENTS_TOOLS_VITEST_CONFIG = agentVitestProjectOwners.tools.config; +const AGENTS_VITEST_CONFIG = agentVitestProjectOwners.all.config; const ACP_VITEST_CONFIG = "test/vitest/vitest.acp.config.ts"; const AUTO_REPLY_CORE_VITEST_CONFIG = "test/vitest/vitest.auto-reply-core.config.ts"; const AUTO_REPLY_VITEST_CONFIG = "test/vitest/vitest.auto-reply.config.ts"; @@ -2802,7 +2800,7 @@ function listUnitFastFullSuiteTestTargets() { } function listAgentsCoreFullSuiteTestTargets(cwd) { - const isolatedTests = new Set(agentsCoreIsolatedTestFiles); + const isolatedTests = new Set(agentVitestProjectOwners.coreIsolated.include); const agentsDir = path.join(cwd, "src/agents"); if (!fs.existsSync(agentsDir)) { return []; @@ -4041,7 +4039,7 @@ function classifyTarget(arg, cwd) { return configTargetKind; } if (isAgentsCoreIsolatedTestFile(relative)) { - return "agentsCoreIsolated"; + return agentVitestProjectOwners.coreIsolated.kind; } if (isControlUiE2eTarget(relative)) { return "uiE2e"; @@ -4249,33 +4247,41 @@ function classifyTarget(arg, cwd) { if (isPathAtOrUnder(relative, "src/auto-reply")) { return "autoReply"; } - if (isPathAtOrUnder(relative, "src/agents")) { + if (isPathAtOrUnder(relative, agentVitestProjectOwners.all.root)) { // Focused runs must preserve the full suite's isolated harness and hook-timeout contracts. - if (relative === "src/agents" || relative === AGENTS_EMBEDDED_AGENT_TEST_ROOT) { - return "agent"; + if ( + relative === agentVitestProjectOwners.all.root || + relative === AGENTS_EMBEDDED_AGENT_TEST_ROOT + ) { + return agentVitestProjectOwners.all.kind; } - if (agentsEmbeddedIncompleteTurnTestFiles.includes(relative)) { - return "agentEmbeddedIncompleteTurn"; + if (agentVitestProjectOwners.embeddedIncompleteTurn.include.includes(relative)) { + return agentVitestProjectOwners.embeddedIncompleteTurn.kind; } - if (agentsEmbeddedOverflowCompactionTestFiles.includes(relative)) { - return "agentEmbeddedOverflowCompaction"; + if (agentVitestProjectOwners.embeddedOverflowCompaction.include.includes(relative)) { + return agentVitestProjectOwners.embeddedOverflowCompaction.kind; } - if (isPathAtOrUnder(relative, `${AGENTS_EMBEDDED_AGENT_TEST_ROOT}/run`)) { - return "agentEmbeddedRun"; + if (isPathAtOrUnder(relative, agentVitestProjectOwners.embeddedRun.root)) { + return agentVitestProjectOwners.embeddedRun.kind; } if (isPathAtOrUnder(relative, AGENTS_EMBEDDED_AGENT_TEST_ROOT)) { - return isGlobTarget(relative) ? "agent" : "agentEmbedded"; + return isGlobTarget(relative) + ? agentVitestProjectOwners.all.kind + : agentVitestProjectOwners.embedded.kind; } - if (isPathAtOrUnder(relative, "src/agents/tools")) { - return "agentTools"; + if (isPathAtOrUnder(relative, agentVitestProjectOwners.tools.root)) { + return agentVitestProjectOwners.tools.kind; } if (isGlobTarget(relative)) { - const owner = relative.slice("src/agents/".length).split("/", 1)[0]; - return isGlobTarget(owner) ? "agent" : "agentSupport"; + const owner = relative.slice(agentVitestProjectOwners.all.root.length + 1).split("/", 1)[0]; + return isGlobTarget(owner) + ? agentVitestProjectOwners.all.kind + : agentVitestProjectOwners.support.kind; } - return isFileLikeTarget(relative) && path.posix.dirname(relative) === "src/agents" - ? "agentCore" - : "agentSupport"; + return isFileLikeTarget(relative) && + path.posix.dirname(relative) === agentVitestProjectOwners.core.root + ? agentVitestProjectOwners.core.kind + : agentVitestProjectOwners.support.kind; } if (isPathAtOrUnder(relative, "src/plugins")) { return "plugin"; @@ -4439,14 +4445,7 @@ export function buildVitestRunPlans( for (const targetArg of activeTargetArgs) { if (!watchMode && toRepoRelativeTarget(targetArg, cwd) === AGENTS_EMBEDDED_AGENT_TEST_ROOT) { // The recursive parent spans four harness owners; keep every isolated project intact. - const embeddedTargetsByKind = [ - ["agentEmbedded", [`${AGENTS_EMBEDDED_AGENT_TEST_ROOT}/*.test.ts`]], - ["agentEmbeddedIncompleteTurn", agentsEmbeddedIncompleteTurnTestFiles], - ["agentEmbeddedOverflowCompaction", agentsEmbeddedOverflowCompactionTestFiles], - ["agentEmbeddedRun", [`${AGENTS_EMBEDDED_AGENT_TEST_ROOT}/run`]], - ]; - - for (const [kind, targets] of embeddedTargetsByKind) { + for (const { kind, include: targets } of embeddedAgentVitestProjectOwners) { const current = groupedTargets.get(kind) ?? []; for (const target of targets) { if (!current.includes(target)) { diff --git a/test/scripts/ci-node-test-plan.test.ts b/test/scripts/ci-node-test-plan.test.ts index cb4922fef504..2777df28b735 100644 --- a/test/scripts/ci-node-test-plan.test.ts +++ b/test/scripts/ci-node-test-plan.test.ts @@ -12,10 +12,8 @@ import { import { expectNoNodeFsScans } from "../../src/test-utils/fs-scan-assertions.js"; import { listGitTrackedFiles, sortRepoPaths, toRepoPath } from "../../src/test-utils/repo-files.js"; import { - agentsEmbeddedIncompleteTurnTestFiles, - agentsEmbeddedOverflowCompactionTestFiles, - agentsEmbeddedRunTestPatterns, - agentsEmbeddedTestPatterns, + agentVitestProjectOwners, + embeddedAgentVitestProjectOwners, } from "../vitest/vitest.agents-paths.mjs"; import { commandsLightTestFiles } from "../vitest/vitest.commands-light-paths.mjs"; import { createPluginsVitestConfig } from "../vitest/vitest.plugins.config.ts"; @@ -1111,26 +1109,23 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => { const shard = createNodeTestShards().find( (candidate) => candidate.shardName === "agentic-agents-embedded", ); - const incompleteTurnFiles = new Set(agentsEmbeddedIncompleteTurnTestFiles); - const overflowCompactionFiles = new Set(agentsEmbeddedOverflowCompactionTestFiles); + const incompleteTurnFiles = new Set(agentVitestProjectOwners.embeddedIncompleteTurn.include); + const overflowCompactionFiles = new Set( + agentVitestProjectOwners.embeddedOverflowCompaction.include, + ); const actual = [ ...fg - .sync(agentsEmbeddedTestPatterns) + .sync(agentVitestProjectOwners.embedded.include) .filter((file) => !incompleteTurnFiles.has(file) && !overflowCompactionFiles.has(file)), - ...agentsEmbeddedIncompleteTurnTestFiles, - ...agentsEmbeddedOverflowCompactionTestFiles, - ...fg.sync(agentsEmbeddedRunTestPatterns), + ...agentVitestProjectOwners.embeddedIncompleteTurn.include, + ...agentVitestProjectOwners.embeddedOverflowCompaction.include, + ...fg.sync(agentVitestProjectOwners.embeddedRun.include), ].toSorted((left, right) => left.localeCompare(right)); const expected = listTestFiles("src/agents/embedded-agent-runner").toSorted((left, right) => left.localeCompare(right), ); - expect(shard?.configs).toEqual([ - "test/vitest/vitest.agents-embedded-agent.config.ts", - "test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts", - "test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts", - "test/vitest/vitest.agents-embedded-agent-run.config.ts", - ]); + expect(shard?.configs).toEqual(embeddedAgentVitestProjectOwners.map((owner) => owner.config)); expect(actual).toEqual(expected); expect(new Set(actual).size).toBe(actual.length); }); diff --git a/test/scripts/test-projects.test.ts b/test/scripts/test-projects.test.ts index c2cea5f2f37f..7da7ac0873d1 100644 --- a/test/scripts/test-projects.test.ts +++ b/test/scripts/test-projects.test.ts @@ -33,7 +33,7 @@ import { } from "../../scripts/test-projects.test-support.mjs"; import { captureReaddirSyncCallsDuring } from "../../src/test-utils/fs-scan-assertions.js"; import { toRepoPath } from "../../src/test-utils/repo-files.js"; -import { agentsCoreIsolatedTestFiles } from "../vitest/vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "../vitest/vitest.agents-paths.mjs"; import { channelConfigContractPatterns, channelRegistryContractPatterns, @@ -2617,7 +2617,7 @@ describe("scripts/test-projects changed-target routing", () => { ]); }); - it.each(agentsCoreIsolatedTestFiles)( + it.each(agentVitestProjectOwners.coreIsolated.include)( "routes isolated agent test %s to the isolated agents-core shard", (testFile) => { expect(buildVitestRunPlans([testFile])).toEqual([ diff --git a/test/vitest-projects-config.test.ts b/test/vitest-projects-config.test.ts index c83ff7e1970d..d4e0f7619e69 100644 --- a/test/vitest-projects-config.test.ts +++ b/test/vitest-projects-config.test.ts @@ -7,6 +7,11 @@ import { createAgentsEmbeddedIncompleteTurnVitestConfig } from "./vitest/vitest. import { createAgentsEmbeddedOverflowCompactionVitestConfig } from "./vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts"; import { createAgentsEmbeddedRunVitestConfig } from "./vitest/vitest.agents-embedded-agent-run.config.ts"; import { createAgentsEmbeddedVitestConfig } from "./vitest/vitest.agents-embedded-agent.config.ts"; +import { + agentVitestProjectConfigs, + agentVitestProjectOwners, + embeddedAgentVitestProjectOwners, +} from "./vitest/vitest.agents-paths.mjs"; import { createAgentsSupportVitestConfig } from "./vitest/vitest.agents-support.config.ts"; import { createAgentsToolsVitestConfig } from "./vitest/vitest.agents-tools.config.ts"; import { createAgentsVitestConfig } from "./vitest/vitest.agents.config.ts"; @@ -63,6 +68,28 @@ describe("projects vitest config", () => { expect(requireTestConfig(baseConfig).projects).toEqual([...rootVitestProjects]); }); + it("keeps root and full-suite agent projects aligned with canonical owners", () => { + const agenticShard = fullSuiteVitestShards.find((shard) => shard.name === "agentic"); + const agentConfigs = new Set(agentVitestProjectConfigs); + + expect(rootVitestProjects.filter((config) => agentConfigs.has(config))).toEqual( + agentVitestProjectConfigs, + ); + expect(agenticShard?.projects.filter((config) => agentConfigs.has(config))).toEqual( + agentVitestProjectConfigs, + ); + expect(agentConfigs.size).toBe(agentVitestProjectConfigs.length); + }); + + it("keeps all embedded harnesses under their canonical embedded owner", () => { + expect(embeddedAgentVitestProjectOwners).toEqual([ + agentVitestProjectOwners.embedded, + agentVitestProjectOwners.embeddedIncompleteTurn, + agentVitestProjectOwners.embeddedOverflowCompaction, + agentVitestProjectOwners.embeddedRun, + ]); + }); + it("keeps root watch projects aligned with dedicated extension shard lanes", () => { const extensionShard = fullSuiteVitestShards.find( (shard) => shard.config === "test/vitest/vitest.full-extensions.config.ts", diff --git a/test/vitest-scoped-config.test.ts b/test/vitest-scoped-config.test.ts index 0b4806bfc307..36e7ec515849 100644 --- a/test/vitest-scoped-config.test.ts +++ b/test/vitest-scoped-config.test.ts @@ -9,7 +9,7 @@ import { normalizeConfigPath, normalizeConfigPaths } from "./helpers/vitest-conf import { createAcpVitestConfig } from "./vitest/vitest.acp.config.ts"; import { createAgentsCoreIsolatedVitestConfig } from "./vitest/vitest.agents-core-isolated.config.ts"; import { createAgentsCoreVitestConfig } from "./vitest/vitest.agents-core.config.ts"; -import { agentsCoreIsolatedTestFiles } from "./vitest/vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest/vitest.agents-paths.mjs"; import { createAgentsVitestConfig } from "./vitest/vitest.agents.config.ts"; import { createAutoReplyCoreVitestConfig } from "./vitest/vitest.auto-reply-core.config.ts"; import { createAutoReplyReplyVitestConfig } from "./vitest/vitest.auto-reply-reply.config.ts"; @@ -663,7 +663,7 @@ describe("scoped vitest configs", () => { const sharedConfig = requireTestConfig(defaultAgentsCoreConfig); const isolatedConfig = requireTestConfig(defaultAgentsCoreIsolatedConfig); - const scopedIsolatedFiles = agentsCoreIsolatedTestFiles.map((file) => + const scopedIsolatedFiles = agentVitestProjectOwners.coreIsolated.include.map((file) => file.replace("src/agents/", ""), ); expect(sharedConfig.exclude).toEqual(expect.arrayContaining(scopedIsolatedFiles)); diff --git a/test/vitest/vitest.agents-core-isolated.config.ts b/test/vitest/vitest.agents-core-isolated.config.ts index bd4a82f6d114..4a89cb6e4aae 100644 --- a/test/vitest/vitest.agents-core-isolated.config.ts +++ b/test/vitest/vitest.agents-core-isolated.config.ts @@ -1,13 +1,14 @@ // Vitest agents core isolated config separates suites with conflicting module mocks. -import { agentsCoreIsolatedTestFiles } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsCoreIsolatedVitestConfig(env?: Record) { - return createScopedVitestConfig(agentsCoreIsolatedTestFiles, { - dir: "src/agents", + const owner = agentVitestProjectOwners.coreIsolated; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, isolate: true, - name: "agents-core-isolated", + name: owner.name, passWithNoTests: true, useNonIsolatedRunner: false, }); diff --git a/test/vitest/vitest.agents-core.config.ts b/test/vitest/vitest.agents-core.config.ts index 64cc69afb780..e3b7a83cce9d 100644 --- a/test/vitest/vitest.agents-core.config.ts +++ b/test/vitest/vitest.agents-core.config.ts @@ -1,14 +1,15 @@ // Vitest agents core config wires the agents core test shard. -import { agentsCoreIsolatedTestFiles, agentsCoreTestPatterns } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsCoreVitestConfig(env?: Record) { - return createScopedVitestConfig(agentsCoreTestPatterns, { - dir: "src/agents", + const owner = agentVitestProjectOwners.core; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, - exclude: agentsCoreIsolatedTestFiles, + exclude: owner.exclude, fileParallelism: false, - name: "agents-core", + name: owner.name, }); } diff --git a/test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts b/test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts index 8afa05160f73..ef08f6bb6144 100644 --- a/test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts +++ b/test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts @@ -1,15 +1,16 @@ // Vitest embedded agent incomplete-turn config isolates the expensive harness warmup. -import { agentsEmbeddedIncompleteTurnTestFiles } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsEmbeddedIncompleteTurnVitestConfig( env?: Record, ) { - return createScopedVitestConfig(agentsEmbeddedIncompleteTurnTestFiles, { - dir: "src/agents/embedded-agent-runner", + const owner = agentVitestProjectOwners.embeddedIncompleteTurn; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, fileParallelism: false, - name: "agents-embedded-agent-incomplete-turn", + name: owner.name, }); } diff --git a/test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts b/test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts index 5435e50f626d..39f4d7a60b5e 100644 --- a/test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts +++ b/test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts @@ -1,15 +1,16 @@ // Vitest embedded agent overflow config isolates the expensive harness warmup. -import { agentsEmbeddedOverflowCompactionTestFiles } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsEmbeddedOverflowCompactionVitestConfig( env?: Record, ) { - return createScopedVitestConfig(agentsEmbeddedOverflowCompactionTestFiles, { - dir: "src/agents/embedded-agent-runner", + const owner = agentVitestProjectOwners.embeddedOverflowCompaction; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, fileParallelism: false, - name: "agents-embedded-agent-overflow-compaction", + name: owner.name, }); } diff --git a/test/vitest/vitest.agents-embedded-agent-run.config.ts b/test/vitest/vitest.agents-embedded-agent-run.config.ts index 90b3d4af7087..929be49928dd 100644 --- a/test/vitest/vitest.agents-embedded-agent-run.config.ts +++ b/test/vitest/vitest.agents-embedded-agent-run.config.ts @@ -1,13 +1,14 @@ // Vitest embedded agent run config keeps the run subtree in a bounded serial shard. -import { agentsEmbeddedRunTestPatterns } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsEmbeddedRunVitestConfig(env?: Record) { - return createScopedVitestConfig(agentsEmbeddedRunTestPatterns, { - dir: "src/agents/embedded-agent-runner/run", + const owner = agentVitestProjectOwners.embeddedRun; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, fileParallelism: false, - name: "agents-embedded-agent-run", + name: owner.name, }); } diff --git a/test/vitest/vitest.agents-embedded-agent.config.ts b/test/vitest/vitest.agents-embedded-agent.config.ts index 947f2da42c47..a6881cd49d23 100644 --- a/test/vitest/vitest.agents-embedded-agent.config.ts +++ b/test/vitest/vitest.agents-embedded-agent.config.ts @@ -1,23 +1,17 @@ // Vitest agents embedded agent config wires the agents embedded agent test shard. -import { - agentsEmbeddedIncompleteTurnTestFiles, - agentsEmbeddedOverflowCompactionTestFiles, - agentsEmbeddedTestPatterns, -} from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsEmbeddedVitestConfig(env?: Record) { - return createScopedVitestConfig(agentsEmbeddedTestPatterns, { - dir: "src/agents", + const owner = agentVitestProjectOwners.embedded; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, - exclude: [ - ...agentsEmbeddedIncompleteTurnTestFiles, - ...agentsEmbeddedOverflowCompactionTestFiles, - ], + exclude: owner.exclude, fileParallelism: false, // Cold shared harness imports exceed the generic limit on 2-vCPU hosted release runners. hookTimeout: 600_000, - name: "agents-embedded-agent", + name: owner.name, }); } diff --git a/test/vitest/vitest.agents-paths.d.mts b/test/vitest/vitest.agents-paths.d.mts index 7424bf86b8a8..a4b933e809bb 100644 --- a/test/vitest/vitest.agents-paths.d.mts +++ b/test/vitest/vitest.agents-paths.d.mts @@ -1,11 +1,25 @@ -export const agentsAllTestPatterns: string[]; -export const agentsCoreIsolatedTestFiles: string[]; +export type AgentVitestProjectOwner = { + kind: string; + name: string; + config: string; + root: string; + dir: string; + include: string[]; + exclude: string[]; +}; + +export const agentVitestProjectOwners: { + all: AgentVitestProjectOwner; + coreIsolated: AgentVitestProjectOwner; + core: AgentVitestProjectOwner; + embedded: AgentVitestProjectOwner; + embeddedIncompleteTurn: AgentVitestProjectOwner; + embeddedOverflowCompaction: AgentVitestProjectOwner; + embeddedRun: AgentVitestProjectOwner; + support: AgentVitestProjectOwner; + tools: AgentVitestProjectOwner; +}; + +export const agentVitestProjectConfigs: string[]; +export const embeddedAgentVitestProjectOwners: AgentVitestProjectOwner[]; export function isAgentsCoreIsolatedTestFile(file: string): boolean; -export const agentsCoreTestPatterns: string[]; -export const agentsEmbeddedTestPatterns: string[]; -export const agentsEmbeddedIncompleteTurnTestFiles: string[]; -export const agentsEmbeddedOverflowCompactionTestFiles: string[]; -export const agentsEmbeddedRunTestPatterns: string[]; -export const agentsToolsTestPatterns: string[]; -export const agentsSupportTestPatterns: string[]; -export const agentsSupportExcludePatterns: string[]; diff --git a/test/vitest/vitest.agents-paths.mjs b/test/vitest/vitest.agents-paths.mjs index 625ee1906a5f..7d56f224b78f 100644 --- a/test/vitest/vitest.agents-paths.mjs +++ b/test/vitest/vitest.agents-paths.mjs @@ -1,9 +1,10 @@ -// Test routing globs for agent core, embedded-agent, tool, and support suites. -export const agentsAllTestPatterns = ["src/agents/**/*.test.ts"]; +// Canonical agent project ownership for focused runs, full suites, and CI. +const agentsRoot = "src/agents"; +const embeddedRoot = `${agentsRoot}/embedded-agent-runner`; -// These suites install mocks for shared runtime, network, or plugin modules. -// Keep their module graphs separate from the shared agents-core worker. -export const agentsCoreIsolatedTestFiles = [ +// These suites mock shared runtime, network, or plugin modules and cannot +// share the non-isolated core worker without leaking module state. +const coreIsolatedFiles = [ "src/agents/image-generation-task-status.test.ts", "src/agents/media-generation-task-status-shared.test.ts", "src/agents/mcp-http-fetch.test.ts", @@ -16,32 +17,113 @@ export const agentsCoreIsolatedTestFiles = [ "src/agents/subagent-orphan-recovery.test.ts", "src/agents/video-generation-task-status.test.ts", ]; +const incompleteTurnFiles = [`${embeddedRoot}/run.incomplete-turn.test.ts`]; +const overflowCompactionFiles = [`${embeddedRoot}/run.overflow-compaction.test.ts`]; -const agentsCoreIsolatedTestFileSet = new Set(agentsCoreIsolatedTestFiles); +export const agentVitestProjectOwners = { + all: { + kind: "agent", + name: "agents", + config: "test/vitest/vitest.agents.config.ts", + root: agentsRoot, + dir: agentsRoot, + include: [`${agentsRoot}/**/*.test.ts`], + exclude: [], + }, + coreIsolated: { + kind: "agentsCoreIsolated", + name: "agents-core-isolated", + config: "test/vitest/vitest.agents-core-isolated.config.ts", + root: agentsRoot, + dir: agentsRoot, + include: coreIsolatedFiles, + exclude: [], + }, + core: { + kind: "agentCore", + name: "agents-core", + config: "test/vitest/vitest.agents-core.config.ts", + root: agentsRoot, + dir: agentsRoot, + include: [`${agentsRoot}/*.test.ts`], + exclude: coreIsolatedFiles, + }, + embedded: { + kind: "agentEmbedded", + name: "agents-embedded-agent", + config: "test/vitest/vitest.agents-embedded-agent.config.ts", + root: embeddedRoot, + dir: agentsRoot, + include: [`${embeddedRoot}/*.test.ts`], + exclude: [...incompleteTurnFiles, ...overflowCompactionFiles], + }, + embeddedIncompleteTurn: { + kind: "agentEmbeddedIncompleteTurn", + name: "agents-embedded-agent-incomplete-turn", + config: "test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts", + root: embeddedRoot, + dir: embeddedRoot, + include: incompleteTurnFiles, + exclude: [], + }, + embeddedOverflowCompaction: { + kind: "agentEmbeddedOverflowCompaction", + name: "agents-embedded-agent-overflow-compaction", + config: "test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts", + root: embeddedRoot, + dir: embeddedRoot, + include: overflowCompactionFiles, + exclude: [], + }, + embeddedRun: { + kind: "agentEmbeddedRun", + name: "agents-embedded-agent-run", + config: "test/vitest/vitest.agents-embedded-agent-run.config.ts", + root: `${embeddedRoot}/run`, + dir: `${embeddedRoot}/run`, + include: [`${embeddedRoot}/run/**/*.test.ts`], + exclude: [], + }, + support: { + kind: "agentSupport", + name: "agents-support", + config: "test/vitest/vitest.agents-support.config.ts", + root: agentsRoot, + dir: agentsRoot, + include: [`${agentsRoot}/*/**/*.test.ts`], + exclude: [`${embeddedRoot}/**`, `${agentsRoot}/tools/**`], + }, + tools: { + kind: "agentTools", + name: "agents-tools", + config: "test/vitest/vitest.agents-tools.config.ts", + root: `${agentsRoot}/tools`, + dir: agentsRoot, + include: [`${agentsRoot}/tools/**/*.test.ts`], + exclude: [], + }, +}; + +export const agentVitestProjectConfigs = [ + agentVitestProjectOwners.coreIsolated.config, + agentVitestProjectOwners.core.config, + agentVitestProjectOwners.embedded.config, + agentVitestProjectOwners.embeddedIncompleteTurn.config, + agentVitestProjectOwners.embeddedOverflowCompaction.config, + agentVitestProjectOwners.embeddedRun.config, + agentVitestProjectOwners.support.config, + agentVitestProjectOwners.tools.config, +]; + +export const embeddedAgentVitestProjectOwners = [ + agentVitestProjectOwners.embedded, + agentVitestProjectOwners.embeddedIncompleteTurn, + agentVitestProjectOwners.embeddedOverflowCompaction, + agentVitestProjectOwners.embeddedRun, +]; + +const coreIsolatedFileSet = new Set(coreIsolatedFiles); export function isAgentsCoreIsolatedTestFile(value) { - return agentsCoreIsolatedTestFileSet.has(value.replaceAll("\\", "/")); + return coreIsolatedFileSet.has(value.replaceAll("\\", "/")); } - -export const agentsCoreTestPatterns = ["src/agents/*.test.ts"]; - -export const agentsEmbeddedTestPatterns = ["src/agents/embedded-agent-runner/*.test.ts"]; - -export const agentsEmbeddedIncompleteTurnTestFiles = [ - "src/agents/embedded-agent-runner/run.incomplete-turn.test.ts", -]; - -export const agentsEmbeddedOverflowCompactionTestFiles = [ - "src/agents/embedded-agent-runner/run.overflow-compaction.test.ts", -]; - -export const agentsEmbeddedRunTestPatterns = ["src/agents/embedded-agent-runner/run/**/*.test.ts"]; - -export const agentsToolsTestPatterns = ["src/agents/tools/**/*.test.ts"]; - -export const agentsSupportTestPatterns = ["src/agents/*/**/*.test.ts"]; - -export const agentsSupportExcludePatterns = [ - "src/agents/embedded-agent-runner/**", - "src/agents/tools/**", -]; diff --git a/test/vitest/vitest.agents-support.config.ts b/test/vitest/vitest.agents-support.config.ts index 2cd3b2f128ec..a79e95003e7b 100644 --- a/test/vitest/vitest.agents-support.config.ts +++ b/test/vitest/vitest.agents-support.config.ts @@ -1,13 +1,14 @@ // Vitest agents support config wires the agents support test shard. -import { agentsSupportExcludePatterns, agentsSupportTestPatterns } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsSupportVitestConfig(env?: Record) { - return createScopedVitestConfig(agentsSupportTestPatterns, { - dir: "src/agents", + const owner = agentVitestProjectOwners.support; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, - exclude: agentsSupportExcludePatterns, - name: "agents-support", + exclude: owner.exclude, + name: owner.name, }); } diff --git a/test/vitest/vitest.agents-tools.config.ts b/test/vitest/vitest.agents-tools.config.ts index fad9737a8067..f05aa793f551 100644 --- a/test/vitest/vitest.agents-tools.config.ts +++ b/test/vitest/vitest.agents-tools.config.ts @@ -1,13 +1,14 @@ // Vitest agents tools config wires the agents tools test shard. -import { agentsToolsTestPatterns } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsToolsVitestConfig(env?: Record) { - return createScopedVitestConfig(agentsToolsTestPatterns, { - dir: "src/agents", + const owner = agentVitestProjectOwners.tools; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, fileParallelism: false, - name: "agents-tools", + name: owner.name, }); } diff --git a/test/vitest/vitest.agents.config.ts b/test/vitest/vitest.agents.config.ts index b0a87542bfdb..77b4763d6614 100644 --- a/test/vitest/vitest.agents.config.ts +++ b/test/vitest/vitest.agents.config.ts @@ -1,12 +1,13 @@ // Vitest agents config wires the agents test shard. -import { agentsAllTestPatterns } from "./vitest.agents-paths.mjs"; +import { agentVitestProjectOwners } from "./vitest.agents-paths.mjs"; import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; export function createAgentsVitestConfig(env?: Record) { - return createScopedVitestConfig(agentsAllTestPatterns, { - dir: "src/agents", + const owner = agentVitestProjectOwners.all; + return createScopedVitestConfig(owner.include, { + dir: owner.dir, env, - name: "agents", + name: owner.name, }); } diff --git a/test/vitest/vitest.config.ts b/test/vitest/vitest.config.ts index c7297ebb0392..5de738b11913 100644 --- a/test/vitest/vitest.config.ts +++ b/test/vitest/vitest.config.ts @@ -1,5 +1,6 @@ // Vitest config config wires the config test shard. import { defineConfig } from "vitest/config"; +import { agentVitestProjectConfigs } from "./vitest.agents-paths.mjs"; import { resolveDefaultVitestPool, resolveLocalVitestMaxWorkers, @@ -33,14 +34,7 @@ export const rootVitestProjects = [ "test/vitest/vitest.commands-light.config.ts", "test/vitest/vitest.commands.config.ts", "test/vitest/vitest.auto-reply.config.ts", - "test/vitest/vitest.agents-core-isolated.config.ts", - "test/vitest/vitest.agents-core.config.ts", - "test/vitest/vitest.agents-embedded-agent.config.ts", - "test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts", - "test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts", - "test/vitest/vitest.agents-embedded-agent-run.config.ts", - "test/vitest/vitest.agents-support.config.ts", - "test/vitest/vitest.agents-tools.config.ts", + ...agentVitestProjectConfigs, "test/vitest/vitest.daemon.config.ts", "test/vitest/vitest.media.config.ts", "test/vitest/vitest.unit-fast.config.ts", diff --git a/test/vitest/vitest.test-shards.mjs b/test/vitest/vitest.test-shards.mjs index 599a30876455..7b0154d3cb15 100644 --- a/test/vitest/vitest.test-shards.mjs +++ b/test/vitest/vitest.test-shards.mjs @@ -1,4 +1,6 @@ // Full-suite Vitest shard definitions used by test-projects and CI planning. +import { agentVitestProjectConfigs } from "./vitest.agents-paths.mjs"; + export const autoReplyCoreTestInclude = [ "src/auto-reply/*.test.ts", "src/auto-reply/usage-bar/*.test.ts", @@ -101,14 +103,7 @@ export const fullSuiteVitestShards = [ "test/vitest/vitest.cli.config.ts", "test/vitest/vitest.commands-light.config.ts", "test/vitest/vitest.commands.config.ts", - "test/vitest/vitest.agents-core-isolated.config.ts", - "test/vitest/vitest.agents-core.config.ts", - "test/vitest/vitest.agents-embedded-agent.config.ts", - "test/vitest/vitest.agents-embedded-agent-incomplete-turn.config.ts", - "test/vitest/vitest.agents-embedded-agent-overflow-compaction.config.ts", - "test/vitest/vitest.agents-embedded-agent-run.config.ts", - "test/vitest/vitest.agents-support.config.ts", - "test/vitest/vitest.agents-tools.config.ts", + ...agentVitestProjectConfigs, "test/vitest/vitest.daemon.config.ts", "test/vitest/vitest.plugin-sdk-light.config.ts", "test/vitest/vitest.plugin-sdk.config.ts",