mirror of
https://github.com/morluto/rea.git
synced 2026-10-11 21:39:55 +00:00
perf(test): reuse CLI boundary worker module graphs
Share CLI boundary module evaluation in bounded forks while preserving fresh command instances and child processes. Keep module-mocked cleanup tests and source/compiled product catalog verification isolated, and update focused artifact selection. Flameox full cohort with V8 coverage: 102.8s to 96.6s; 290 passed and two existing skips. Statement, function and branch coverage maps and hit sets match across all 1,153 source files. After syncing main, 75 focused tests, typecheck, lint, docs checks and formatting pass; all 834 test files are discovered exactly once.
This commit is contained in:
+13
-6
@@ -927,7 +927,7 @@ behavior, and complete CI evidence before merging.
|
||||
| `npm run test:focused -- PATH...` | Exact existing test files; compiled boundaries build first, and unmatched paths fail |
|
||||
| `npm run test:changed` | Source tests affected since the merge base with `origin/main`, including committed and dirty changes |
|
||||
| `npm run test:fast` | All domain, service, adapter, composition, conformance, and evaluation tests without build |
|
||||
| `npm run test:boundary` | Boundary, MCP boundary, process boundary, and process-global projects |
|
||||
| `npm run test:boundary` | Boundary, CLI boundary, MCP boundary, process boundary, and process-global projects |
|
||||
| `npm run test:mcp` | MCP boundary project |
|
||||
| `npm run test:acceptance` | Complete compiled CLI and MCP acceptance workflows |
|
||||
| `npm run test:watch` | Dirty source tests in watch mode, without build |
|
||||
@@ -989,11 +989,18 @@ Vitest projects use up to two workers, bounded by host parallelism.
|
||||
`process-boundary` runs later with serial files because process-tree sampling
|
||||
shares host resources. Acceptance and process-global cases use isolated forks
|
||||
without serial scheduling. Pure domain/service, composition, conformance,
|
||||
evaluation, and MCP boundary projects share module graphs; their tests avoid
|
||||
process-global state and keep resource cleanup test-scoped. Each MCP session
|
||||
still owns its resources. Adapter, non-MCP boundary, acceptance, and
|
||||
process-global projects retain per-file isolation. See `vitest.config.ts` for
|
||||
current settings.
|
||||
evaluation, CLI boundary, and MCP boundary projects share module graphs. Their
|
||||
tests avoid process-global state and keep resource cleanup test-scoped. Each
|
||||
MCP session still owns its resources, and CLI cases retain fresh command
|
||||
instances or subprocesses. CLI module mocks belong in `tests/process-global/`
|
||||
so they keep per-file isolation. Product catalog verification stays with the
|
||||
isolated filesystem boundary tests because it loads both source and compiled
|
||||
module graphs. Adapter, other boundary, acceptance, and process-global projects
|
||||
retain per-file isolation. See `vitest.config.ts` for current settings.
|
||||
|
||||
The reused CLI boundary workers cap V8 old space at 384 MiB, based on their
|
||||
profiled allocation and cleanup behavior. This encourages collection between
|
||||
files; spawned REA processes retain their own heap settings.
|
||||
|
||||
Vitest worker limits do not bound subprocesses launched within a test. Bound
|
||||
those batches separately so repeated CLI validation cannot oversubscribe the
|
||||
|
||||
+2
-2
@@ -124,14 +124,14 @@
|
||||
"test:local": "node scripts/run-development-tests.mjs local",
|
||||
"test:fast": "vitest run --project domain --project services --project adapters --project composition --project conformance --project evaluation",
|
||||
"pretest:boundary": "npm run test:prepare",
|
||||
"test:boundary": "vitest run --project boundary --project process-boundary --project mcp-boundary --project process-global",
|
||||
"test:boundary": "vitest run --project boundary --project cli-boundary --project process-boundary --project mcp-boundary --project process-global",
|
||||
"pretest:mcp": "node scripts/check-dependency-install.mjs && node scripts/run-exclusive.mjs artifacts turbo run artifacts:skills artifacts:mcp-catalog",
|
||||
"test:mcp": "vitest run --project mcp-boundary",
|
||||
"pretest:acceptance": "npm run build:cached",
|
||||
"test:acceptance": "vitest run --project acceptance",
|
||||
"test:changed": "node scripts/run-development-tests.mjs changed",
|
||||
"pretest:integration": "npm run test:prepare",
|
||||
"test:integration": "vitest run --project boundary --project process-boundary --project mcp-boundary --project process-global --project acceptance",
|
||||
"test:integration": "vitest run --project boundary --project cli-boundary --project process-boundary --project mcp-boundary --project process-global --project acceptance",
|
||||
"pretest:coverage": "npm run test:prepare",
|
||||
"test:coverage": "vitest run --coverage.enabled --coverage.provider=v8",
|
||||
"test:ci": "npm run test:coverage -- --reporter=default --reporter=junit --outputFile.junit=test-results.xml",
|
||||
|
||||
@@ -56,7 +56,9 @@ const artifactConsumers = {
|
||||
"tests/boundary/mcp/contractPresentation.test.ts",
|
||||
"tests/boundary/mcp/toolSchemaValidity.test.ts",
|
||||
],
|
||||
"artifacts:product-catalog": ["tests/boundary/cli/productCatalog.test.ts"],
|
||||
"artifacts:product-catalog": [
|
||||
"tests/boundary/filesystem/productCatalog.test.ts",
|
||||
],
|
||||
"artifacts:managed-evidence": [
|
||||
"tests/boundary/filesystem/setupSkill.test.ts",
|
||||
],
|
||||
|
||||
+17
-17
@@ -1,33 +1,33 @@
|
||||
import { Cli } from "incur";
|
||||
import { expect, it, vi } from "vitest";
|
||||
|
||||
import type { BrowserScenarioCapturePort } from "../../../src/application/BrowserScenarioCapturePort.js";
|
||||
import { createBrowserScenarioEvidence } from "../../../src/application/BrowserScenarioEvidence.js";
|
||||
import type { BrowserScenarioSessionPort } from "../../../src/browser/BrowserScenarioSessionPort.js";
|
||||
import { PlaywrightBrowserScenarioProvider } from "../../../src/browser/PlaywrightBrowserScenarioProvider.js";
|
||||
import { PlaywrightScenarioBrowserCleanupOwner } from "../../../src/browser/PlaywrightScenarioBrowser.js";
|
||||
import { registerBrowserScenarioCommands } from "../../../src/cliBrowserScenarioCommands.js";
|
||||
import { sanitizeBrowserUrl } from "../../../src/domain/browserObservation.js";
|
||||
import type { BrowserScenarioCapturePort } from "../../src/application/BrowserScenarioCapturePort.js";
|
||||
import { createBrowserScenarioEvidence } from "../../src/application/BrowserScenarioEvidence.js";
|
||||
import type { BrowserScenarioSessionPort } from "../../src/browser/BrowserScenarioSessionPort.js";
|
||||
import { PlaywrightBrowserScenarioProvider } from "../../src/browser/PlaywrightBrowserScenarioProvider.js";
|
||||
import { PlaywrightScenarioBrowserCleanupOwner } from "../../src/browser/PlaywrightScenarioBrowser.js";
|
||||
import { registerBrowserScenarioCommands } from "../../src/cliBrowserScenarioCommands.js";
|
||||
import { sanitizeBrowserUrl } from "../../src/domain/browserObservation.js";
|
||||
import {
|
||||
browserScenarioSchema,
|
||||
type BrowserScenario,
|
||||
} from "../../../src/domain/browserScenario.js";
|
||||
import type { BrowserScenarioAction } from "../../../src/domain/browserScenarioValues.js";
|
||||
import { browserStepArtifactsSchema } from "../../../src/domain/browserScenarioCaptureValues.js";
|
||||
import { silentLogger } from "../../../src/logger.js";
|
||||
} from "../../src/domain/browserScenario.js";
|
||||
import type { BrowserScenarioAction } from "../../src/domain/browserScenarioValues.js";
|
||||
import { browserStepArtifactsSchema } from "../../src/domain/browserScenarioCaptureValues.js";
|
||||
import { silentLogger } from "../../src/logger.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisTimeoutError,
|
||||
} from "../../../src/domain/analysisErrorCore.js";
|
||||
import { BrowserObservationError } from "../../../src/domain/browserObservationError.js";
|
||||
import { parseEvidence } from "../../../src/domain/evidence.js";
|
||||
import { jsonObjectSchema } from "../../../src/domain/jsonValue.js";
|
||||
import { ok } from "../../../src/domain/result.js";
|
||||
} from "../../src/domain/analysisErrorCore.js";
|
||||
import { BrowserObservationError } from "../../src/domain/browserObservationError.js";
|
||||
import { parseEvidence } from "../../src/domain/evidence.js";
|
||||
import { jsonObjectSchema } from "../../src/domain/jsonValue.js";
|
||||
import { ok } from "../../src/domain/result.js";
|
||||
|
||||
const state = vi.hoisted(() => ({
|
||||
provider: undefined as BrowserScenarioCapturePort | undefined,
|
||||
}));
|
||||
vi.mock("../../../src/composition/browserScenario.js", () => ({
|
||||
vi.mock("../../src/composition/browserScenario.js", () => ({
|
||||
createBrowserScenarioProvider: () => state.provider,
|
||||
}));
|
||||
|
||||
@@ -69,12 +69,25 @@ const TEST_PROJECTS = [
|
||||
name: "boundary",
|
||||
include: ["tests/boundary/**/*.test.ts"],
|
||||
exclude: [
|
||||
"tests/boundary/cli/**/*.test.ts",
|
||||
"tests/boundary/mcp/**/*.test.ts",
|
||||
"tests/boundary/process/**/*.test.ts",
|
||||
],
|
||||
pool: "forks" as const,
|
||||
maxWorkers: MAX_TEST_WORKERS,
|
||||
},
|
||||
{
|
||||
name: "cli-boundary",
|
||||
include: ["tests/boundary/cli/**/*.test.ts"],
|
||||
pool: "forks" as const,
|
||||
maxWorkers: MAX_TEST_WORKERS,
|
||||
// CLI tests create fresh command instances or subprocesses and own their
|
||||
// cleanup. Reuse the immutable graph; module mocks belong in process-global.
|
||||
isolate: false,
|
||||
// Long-lived workers should collect temporary command/schema allocations
|
||||
// before their two heaps compete with the real CLI child processes.
|
||||
execArgv: ["--max-old-space-size=384"],
|
||||
},
|
||||
{
|
||||
// Process-tree observations share host sampling resources; keep this small
|
||||
// lane serial while the independent projects run together.
|
||||
|
||||
Reference in New Issue
Block a user