diff --git a/packages/agent-bundle/tests/mcp-probe-service.test.ts b/packages/agent-bundle/tests/mcp-probe-service.test.ts index decc49386..2f97df4dd 100644 --- a/packages/agent-bundle/tests/mcp-probe-service.test.ts +++ b/packages/agent-bundle/tests/mcp-probe-service.test.ts @@ -1047,6 +1047,7 @@ it('removes the fresh plugin data directory after every probe', async () => { }); await service.probe({ host: 'claude', serverName: 'timeline' }); + await service.settle(); await expect(readFile(join(pluginData!, 'proof.txt'), 'utf8')).rejects.toMatchObject({ code: 'ENOENT' }); } finally { diff --git a/packages/agent-bundle/tests/native-claude-contract.test.ts b/packages/agent-bundle/tests/native-claude-contract.test.ts index 60ee33c61..7e3a5fcde 100644 --- a/packages/agent-bundle/tests/native-claude-contract.test.ts +++ b/packages/agent-bundle/tests/native-claude-contract.test.ts @@ -492,12 +492,14 @@ it('enforces a process timeout and output cap even when the child ignores termin const harness = await loadNativeClaudeContract(); expect(harness).toBeDefined(); + // The timeout must outlast child Node startup, or SIGTERM lands before the + // child installs its handler and the default action kills it. const timedOut = await harness!.runNativeClaudeProcess({ args: ['-e', 'process.on("SIGTERM", () => undefined); setInterval(() => undefined, 1000);'], cwd: process.cwd(), environment: process.env, executable: process.execPath, - }, { gracePeriodMs: 100, maxOutputBytes: 64, timeoutMs: 300 }); + }, { gracePeriodMs: 100, maxOutputBytes: 64, timeoutMs: 2_000 }); expect(timedOut).toMatchObject({ exitCode: null, signal: 'SIGKILL', termination: 'timed-out' }); const oversized = await harness!.runNativeClaudeProcess({ diff --git a/packages/agent-bundle/tests/support/eval-project.ts b/packages/agent-bundle/tests/support/eval-project.ts index 79365483e..e24c5e73a 100644 --- a/packages/agent-bundle/tests/support/eval-project.ts +++ b/packages/agent-bundle/tests/support/eval-project.ts @@ -20,7 +20,11 @@ export interface SeedEvalProjectOptions { readonly targets?: readonly string[]; } -const evalEntryPoint = resolve(process.cwd(), 'packages/agent-bundle/src/eval/index.ts'); +// The defining modules, not src/eval/index.ts: suite discovery loads through +// Jiti with the module cache off, and the barrel's graph took ~30s per +// discovery on a loaded host, past eval admission deadlines. +const evalSuiteModule = resolve(process.cwd(), 'packages/agent-bundle/src/eval/suite.ts'); +const evalAssertionsModule = resolve(process.cwd(), 'packages/agent-bundle/src/eval/assertions.ts'); // defineConfig's defining module, not the package entry: seeded configs load // through Jiti with the module cache off, so re-exporting src/index.ts made // every config load re-transpile the whole package graph (~5s per project). @@ -101,7 +105,11 @@ export const seedEvalProject = async ( type: 'module', }), ), - writeFile(join(root, 'node_modules/agent-bundle/eval.ts'), `export * from ${JSON.stringify(evalEntryPoint)};\n`), + writeFile(join(root, 'node_modules/agent-bundle/eval.ts'), [ + `export { defineEvalSuite } from ${JSON.stringify(evalSuiteModule)};`, + `export { expectOutcome, expectSkillActivation } from ${JSON.stringify(evalAssertionsModule)};`, + '', + ].join('\n')), writeFile( join(root, 'node_modules/agent-bundle/index.ts'), `export { defineConfig } from ${JSON.stringify(sourceEntryPoint)};\n`,