diff --git a/cli/__tests__/adapters.claude.environment.test.mjs b/cli/__tests__/adapters.claude.environment.test.mjs index 0b0cdce65b..0081dc97db 100644 --- a/cli/__tests__/adapters.claude.environment.test.mjs +++ b/cli/__tests__/adapters.claude.environment.test.mjs @@ -130,7 +130,7 @@ describe('claude adapter — ctx.environment', () => { test('TASK-174: a warmed MCP home makes claude execute the home build, not npx @latest', async () => { // The control for this arm is the rest of this file: every other test here // declares the shipped `npx -y @commonlyai/mcp@latest`, and the jest setup - // points COMMONLY_MCP_HOME at an EMPTY dir, so they all see it unchanged. + // points COMMONLY_MCP_HOME at a home with no installed build, so they all see it unchanged. // This arm is the same call with a populated home. const home = fs.mkdtempSync(path.join(os.tmpdir(), 'cli-mcp-home-')); const pkgDir = path.join(home, '0.3.13', 'node_modules', '@commonlyai', 'mcp'); @@ -140,6 +140,7 @@ describe('claude adapter — ctx.environment', () => { })); fs.writeFileSync(path.join(pkgDir, 'src', 'index.js'), ''); fs.writeFileSync(path.join(home, 'current'), '0.3.13\n'); + fs.writeFileSync(path.join(home, '.warm.lock'), 'warming\n'); const previous = process.env.COMMONLY_MCP_HOME; process.env.COMMONLY_MCP_HOME = home; try { @@ -181,7 +182,7 @@ describe('claude adapter — ctx.environment', () => { }); test('TASK-174: the cold path materialises an EXACT spec — the spawn never names @latest', async () => { - // The home holds nothing but the warm's registry cache: an empty home is the + // The home has no installed build, only the registry cache and warm lock: this is the // one state where the declaration still runs through npx, and `@latest` is // the one spec whose npx dir every seat shares and a publish rewrites in // place. So the config this adapter writes names the version the host @@ -192,6 +193,7 @@ describe('claude adapter — ctx.environment', () => { fs.writeFileSync(path.join(home, '.registry.json'), JSON.stringify({ version: '0.3.13', checkedAt: Date.now(), })); + fs.writeFileSync(path.join(home, '.warm.lock'), 'warming\n'); const previous = process.env.COMMONLY_MCP_HOME; process.env.COMMONLY_MCP_HOME = home; try { @@ -249,6 +251,7 @@ describe('claude adapter — ctx.environment', () => { })); fs.writeFileSync(path.join(pkgDir, 'src', 'index.js'), ''); fs.writeFileSync(path.join(home, 'current'), '0.3.7\n'); + fs.writeFileSync(path.join(home, '.warm.lock'), 'warming\n'); const previous = process.env.COMMONLY_MCP_HOME; process.env.COMMONLY_MCP_HOME = home; try { diff --git a/cli/__tests__/adapters.codex.test.mjs b/cli/__tests__/adapters.codex.test.mjs index 2beca25ccf..f5ebea80e7 100644 --- a/cli/__tests__/adapters.codex.test.mjs +++ b/cli/__tests__/adapters.codex.test.mjs @@ -196,6 +196,7 @@ describe('codex adapter — spawn()', () => { })); await writeFile(join(pkgDir, 'src', 'index.js'), ''); await writeFile(join(home, 'current'), '0.3.13\n'); + await writeFile(join(home, '.warm.lock'), 'warming\n'); const previous = process.env.COMMONLY_MCP_HOME; process.env.COMMONLY_MCP_HOME = home; try { diff --git a/cli/__tests__/adapters.pi.test.mjs b/cli/__tests__/adapters.pi.test.mjs index dfa5668557..b6b640f343 100644 --- a/cli/__tests__/adapters.pi.test.mjs +++ b/cli/__tests__/adapters.pi.test.mjs @@ -354,7 +354,7 @@ describe('helpers', () => { }); test('TASK-174: a warmed MCP home makes pi exec the home build, not npx @latest', async () => { // Control: the helper tests in this file call resolveMcpServers with the - // empty home the jest setup installs, and see `npx -y @commonlyai/mcp@latest` + // home without an installed build from jest setup, and see `npx -y @commonlyai/mcp@latest` // carried through unchanged. This arm is the same call with a real home. const home = await mkdtemp(join(tmpdir(), 'cli-mcp-home-')); const pkgDir = join(home, '0.3.13', 'node_modules', '@commonlyai', 'mcp'); @@ -364,6 +364,7 @@ describe('helpers', () => { })); await writeFile(join(pkgDir, 'src', 'index.js'), ''); await writeFile(join(home, 'current'), '0.3.13\n'); + await writeFile(join(home, '.warm.lock'), 'warming\n'); const previous = process.env.COMMONLY_MCP_HOME; process.env.COMMONLY_MCP_HOME = home; try { diff --git a/cli/jest.setup.cjs b/cli/jest.setup.cjs index 591c1ef6ff..62e7dc707f 100644 --- a/cli/jest.setup.cjs +++ b/cli/jest.setup.cjs @@ -9,12 +9,15 @@ * adapter tests that pin the npx form would fail for a reason that has nothing * to do with the change. * - * Pointing the home at a fresh empty dir per run restores that: the default - * `COMMONLY_MCP_HOME` is the real `~/.commonly/mcp`, and tests that want a - * warmed home set up their own temp dir and pass it in. + * Pointing the home at a fresh dir with no installed build per run restores + * that: the default `COMMONLY_MCP_HOME` is the real `~/.commonly/mcp`, and + * tests that want a warmed home set up their own temp dir and pass it in. + * The lock suppresses an unrelated detached warm child that could still write + * to this fixture after Jest has moved on to the next test file. */ -const { mkdtempSync } = require('node:fs'); +const { mkdtempSync, writeFileSync } = require('node:fs'); const { tmpdir } = require('node:os'); const { join } = require('node:path'); process.env.COMMONLY_MCP_HOME = mkdtempSync(join(tmpdir(), 'commonly-mcp-home-jest-')); +writeFileSync(join(process.env.COMMONLY_MCP_HOME, '.warm.lock'), 'warming\n');