diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 67018c5..3f1b6b2 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "understand-anything", "description": "AI-powered codebase understanding — analyze, visualize, and explain any project", - "version": "2.7.3", + "version": "2.7.4", "author": { "name": "Lum1104" }, diff --git a/.copilot-plugin/plugin.json b/.copilot-plugin/plugin.json index 5c2fa9c..b5b668f 100644 --- a/.copilot-plugin/plugin.json +++ b/.copilot-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "understand-anything", "description": "AI-powered codebase understanding — analyze, visualize, and explain any project", - "version": "2.7.3", + "version": "2.7.4", "author": { "name": "Lum1104" }, diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index 8f9f665..0e5ba34 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "understand-anything", "displayName": "Understand Anything", "description": "AI-powered codebase understanding — analyze, visualize, and explain any project", - "version": "2.7.3", + "version": "2.7.4", "author": { "name": "Lum1104" }, diff --git a/understand-anything-plugin/.claude-plugin/plugin.json b/understand-anything-plugin/.claude-plugin/plugin.json index 67018c5..3f1b6b2 100644 --- a/understand-anything-plugin/.claude-plugin/plugin.json +++ b/understand-anything-plugin/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "understand-anything", "description": "AI-powered codebase understanding — analyze, visualize, and explain any project", - "version": "2.7.3", + "version": "2.7.4", "author": { "name": "Lum1104" }, diff --git a/understand-anything-plugin/agents/file-analyzer.md b/understand-anything-plugin/agents/file-analyzer.md index 6d0e506..6b2a183 100644 --- a/understand-anything-plugin/agents/file-analyzer.md +++ b/understand-anything-plugin/agents/file-analyzer.md @@ -64,6 +64,8 @@ node /extract-structure.mjs \ If the script exits non-zero, read stderr and report the error. Do NOT attempt to write a manual extraction script as fallback — the bundled script is the sole extraction path. +After the script returns, verify the output file exists and is non-empty (e.g. `test -s $PROJECT_ROOT/.understand-anything/tmp/ua-file-extract-results-.json`). Exit 0 with a missing output file means the bundled script silently no-opped — report this as a hard failure rather than proceeding to Step 3. + ### Step 3 — Read the extraction results Read `$PROJECT_ROOT/.understand-anything/tmp/ua-file-extract-results-.json`. The output format is: diff --git a/understand-anything-plugin/package.json b/understand-anything-plugin/package.json index def2ade..b789128 100644 --- a/understand-anything-plugin/package.json +++ b/understand-anything-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@understand-anything/skill", - "version": "2.7.3", + "version": "2.7.4", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/understand-anything-plugin/skills/understand/extract-structure.mjs b/understand-anything-plugin/skills/understand/extract-structure.mjs index 030bc0f..a8bbd28 100644 --- a/understand-anything-plugin/skills/understand/extract-structure.mjs +++ b/understand-anything-plugin/skills/understand/extract-structure.mjs @@ -19,7 +19,7 @@ import { createRequire } from 'node:module'; import { dirname, resolve, join } from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; -import { readFileSync, writeFileSync } from 'node:fs'; +import { existsSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'; const __dirname = dirname(fileURLToPath(import.meta.url)); // skills/understand/ -> plugin root is two dirs up @@ -133,6 +133,10 @@ async function main() { }; writeFileSync(outputPath, JSON.stringify(output, null, 2), 'utf-8'); + + if (!existsSync(outputPath)) { + throw new Error(`output file missing after write: ${outputPath}`); + } } // --------------------------------------------------------------------------- @@ -302,11 +306,25 @@ export function buildResult(file, totalLines, nonEmptyLines, analysis, callGraph // --------------------------------------------------------------------------- // Run only when executed directly as a CLI; importing the module (e.g. from // tests) must not trigger main(). +// +// Canonicalize both sides through realpathSync. Node ESM resolves +// import.meta.url through symlinks but pathToFileURL(process.argv[1]) preserves +// them, so a raw equality check silently no-ops when the script is invoked via +// a symlinked plugin install path (the default in Claude Code / Copilot CLI +// caches). See GitHub issue #162. // --------------------------------------------------------------------------- -const isCli = - process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href; +function isCliEntry() { + if (!process.argv[1]) return false; + try { + const modulePath = realpathSync(fileURLToPath(import.meta.url)); + const argvPath = realpathSync(process.argv[1]); + return modulePath === argvPath; + } catch { + return false; + } +} -if (isCli) { +if (isCliEntry()) { try { await main(); } catch (err) {