From 2c1e4b695ed930e6d13dfa4bec033c889fbc807d Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 8 Apr 2026 13:08:12 -0500 Subject: [PATCH] test(scanning): add regression tests for dot-folder exclusions - codebase-generator: verify .claude/, .plans/, .cursor/, .vscode/ excluded - detection: verify scanProjectFiles skips .claude, .gsd, .planning, .plans, .cursor, .vscode --- .../gsd/tests/codebase-generator.test.ts | 22 +++++++++++ .../extensions/gsd/tests/detection.test.ts | 37 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/resources/extensions/gsd/tests/codebase-generator.test.ts b/src/resources/extensions/gsd/tests/codebase-generator.test.ts index 91ef3314a..fb3a0fc15 100644 --- a/src/resources/extensions/gsd/tests/codebase-generator.test.ts +++ b/src/resources/extensions/gsd/tests/codebase-generator.test.ts @@ -138,6 +138,28 @@ test("generateCodebaseMap: excludes .gsd/ files", () => { } }); +test("generateCodebaseMap: excludes .claude/ and other tool directories", () => { + const base = makeTmpRepo(); + try { + addFile(base, "src/main.ts"); + addFile(base, ".claude/CLAUDE.md"); + addFile(base, ".claude/memory/user.md"); + addFile(base, ".plans/plan.md"); + addFile(base, ".cursor/settings.json"); + addFile(base, ".vscode/settings.json"); + + const result = generateCodebaseMap(base); + assert.ok(result.content.includes("`src/main.ts`"), "should include src/main.ts"); + assert.ok(!result.content.includes("CLAUDE.md"), "should exclude .claude/ files"); + assert.ok(!result.content.includes("user.md"), "should exclude .claude/memory/ files"); + assert.ok(!result.content.includes(".plans"), "should exclude .plans/ files"); + assert.ok(!result.content.includes(".cursor"), "should exclude .cursor/ files"); + assert.ok(!result.content.includes(".vscode"), "should exclude .vscode/ files"); + } finally { + cleanup(base); + } +}); + test("generateCodebaseMap: excludes binary and lock files", () => { const base = makeTmpRepo(); try { diff --git a/src/resources/extensions/gsd/tests/detection.test.ts b/src/resources/extensions/gsd/tests/detection.test.ts index c1efd9d0f..25843ca7a 100644 --- a/src/resources/extensions/gsd/tests/detection.test.ts +++ b/src/resources/extensions/gsd/tests/detection.test.ts @@ -17,6 +17,7 @@ import { detectProjectState, detectV1Planning, detectProjectSignals, + scanProjectFiles, } from "../detection.ts"; function makeTempDir(prefix: string): string { @@ -1188,3 +1189,39 @@ test("detectProjectSignals: Spring Boot settings-defined catalog accessor emits cleanup(dir); } }); + +// ─── scanProjectFiles: RECURSIVE_SCAN_IGNORED_DIRS ────────────────────── + +test("scanProjectFiles: excludes .claude, .gsd, .planning, .plans, .cursor, .vscode directories", () => { + const dir = makeTempDir("scan-ignore-dotdirs"); + try { + // Create project files that should be included + mkdirSync(join(dir, "src"), { recursive: true }); + writeFileSync(join(dir, "src", "main.ts"), "// main\n", "utf-8"); + writeFileSync(join(dir, "README.md"), "# Project\n", "utf-8"); + + // Create tool directories that should be excluded + const excludedDirs = [".claude", ".gsd", ".planning", ".plans", ".cursor", ".vscode"]; + for (const d of excludedDirs) { + mkdirSync(join(dir, d), { recursive: true }); + writeFileSync(join(dir, d, "config.json"), "{}\n", "utf-8"); + } + // Nested .claude directory + mkdirSync(join(dir, ".claude", "memory"), { recursive: true }); + writeFileSync(join(dir, ".claude", "memory", "user.md"), "# Memory\n", "utf-8"); + + const files = scanProjectFiles(dir); + + // Should include project files + assert.ok(files.includes("src/main.ts"), "should include src/main.ts"); + assert.ok(files.includes("README.md"), "should include README.md"); + + // Should exclude all tool directories + for (const d of excludedDirs) { + const hasExcluded = files.some((f) => f.startsWith(`${d}/`)); + assert.ok(!hasExcluded, `should exclude ${d}/ directory but found: ${files.filter((f) => f.startsWith(`${d}/`)).join(", ")}`); + } + } finally { + cleanup(dir); + } +});