From 6d613f67dd24189a8bb7fb1a2f5e535957f46a58 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Mon, 11 May 2026 22:20:34 -0400 Subject: [PATCH] fix: harden opencode project file probes --- .opencode/plugins/ecc-hooks.ts | 2 +- tests/opencode-plugin-hooks.test.js | 46 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/.opencode/plugins/ecc-hooks.ts b/.opencode/plugins/ecc-hooks.ts index ff8628b5..31cfa8ac 100644 --- a/.opencode/plugins/ecc-hooks.ts +++ b/.opencode/plugins/ecc-hooks.ts @@ -45,7 +45,7 @@ export const ECCHooksPlugin: ECCHooksPluginFn = async ({ function hasProjectFile(relativePath: string): boolean { try { - return fs.existsSync(resolvePath(relativePath)) + return fs.statSync(resolvePath(relativePath)).isFile() } catch { return false } diff --git a/tests/opencode-plugin-hooks.test.js b/tests/opencode-plugin-hooks.test.js index 8b23cee8..474e3be7 100644 --- a/tests/opencode-plugin-hooks.test.js +++ b/tests/opencode-plugin-hooks.test.js @@ -119,6 +119,52 @@ async function main() { ) }), ], + [ + "session.created ignores directories named CLAUDE.md", + async () => { + const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), "ecc-opencode-plugin-")) + try { + fs.mkdirSync(path.join(projectDir, "CLAUDE.md")) + + const client = createClient() + const $ = createFailingShell() + const hooks = await ECCHooksPlugin({ client, $, directory: projectDir }) + + await hooks["session.created"]() + + assert.deepStrictEqual($.calls, [], `Unexpected shell probes: ${$.calls.join(", ")}`) + assert.ok( + !client.logs.some((entry) => entry.message === "[ECC] Found CLAUDE.md - loading project context"), + "Directory named CLAUDE.md should not be treated as project context" + ) + } finally { + fs.rmSync(projectDir, { recursive: true, force: true }) + } + }, + ], + [ + "shell.env ignores directories named like lockfiles and language markers", + async () => { + const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), "ecc-opencode-plugin-")) + try { + fs.mkdirSync(path.join(projectDir, "pnpm-lock.yaml")) + fs.mkdirSync(path.join(projectDir, "tsconfig.json")) + + const client = createClient() + const $ = createFailingShell() + const hooks = await ECCHooksPlugin({ client, $, directory: projectDir }) + + const env = await hooks["shell.env"]() + + assert.deepStrictEqual($.calls, [], `Unexpected shell probes: ${$.calls.join(", ")}`) + assert.ok(!("PACKAGE_MANAGER" in env), "Lockfile directory should not set PACKAGE_MANAGER") + assert.ok(!("DETECTED_LANGUAGES" in env), "Marker directory should not set DETECTED_LANGUAGES") + assert.ok(!("PRIMARY_LANGUAGE" in env), "Marker directory should not set PRIMARY_LANGUAGE") + } finally { + fs.rmSync(projectDir, { recursive: true, force: true }) + } + }, + ], ] let passed = 0