diff --git a/understand-anything-plugin/hooks/auto-update-prompt.md b/understand-anything-plugin/hooks/auto-update-prompt.md index 13d5584..5fe88cc 100644 --- a/understand-anything-plugin/hooks/auto-update-prompt.md +++ b/understand-anything-plugin/hooks/auto-update-prompt.md @@ -37,6 +37,58 @@ Incrementally update the knowledge graph using deterministic structural fingerpr mkdir -p $PROJECT_ROOT/.understand-anything/intermediate ``` +9. **Apply `.understandignore` exclusions** (same semantics as `/understand` Step 2.5 in `agents/project-scanner.md`). + + Without this step, files in user-excluded paths (migrations, vendored code, tests) are counted as structural changes and can spuriously escalate the action to `FULL_UPDATE` even when the real change set is tiny. + + 1. If neither `$PROJECT_ROOT/.understand-anything/.understandignore` nor `$PROJECT_ROOT/.understandignore` exists, the step 7 extension filter is sufficient — skip to Phase 1. + + 2. Write the step 7 file list to `$PROJECT_ROOT/.understand-anything/intermediate/changed-files-pre.json` as a JSON array of relative paths. + + 3. Resolve `$PLUGIN_ROOT`: + - Use `$CLAUDE_PLUGIN_ROOT` if set (Claude Code's hook context sets this). + - Otherwise try `$HOME/.understand-anything-plugin`. + - Validate the chosen candidate by checking `$candidate/packages/core/dist/ignore-filter.js` exists. + - If neither resolves: report "Cannot locate plugin install at `$CLAUDE_PLUGIN_ROOT` or `$HOME/.understand-anything-plugin`; auto-update aborted. Run `/understand` to re-baseline." and **STOP**. Do **not** silently skip — silent skip reproduces issue #153. + + 4. Write `$PROJECT_ROOT/.understand-anything/intermediate/ignore-filter.mjs`: + ```javascript + import { readFileSync, writeFileSync } from 'node:fs'; + import { pathToFileURL } from 'node:url'; + import path from 'node:path'; + + const PROJECT_ROOT = process.cwd(); + const PLUGIN_ROOT = process.argv[2]; + const inputPath = process.argv[3]; + + const modUrl = pathToFileURL( + path.join(PLUGIN_ROOT, 'packages/core/dist/ignore-filter.js'), + ).href; + const { createIgnoreFilter } = await import(modUrl); + const filter = createIgnoreFilter(PROJECT_ROOT); + + const input = JSON.parse(readFileSync(inputPath, 'utf-8')); + const kept = input.filter((p) => !filter.isIgnored(p)); + const removed = input.length - kept.length; + + writeFileSync( + path.join(PROJECT_ROOT, '.understand-anything/intermediate/changed-files.json'), + JSON.stringify({ kept, removed, total: input.length }, null, 2), + ); + console.log(`.understandignore: kept ${kept.length}/${input.length} (removed ${removed})`); + ``` + + 5. Run it: + ```bash + node $PROJECT_ROOT/.understand-anything/intermediate/ignore-filter.mjs \ + "$PLUGIN_ROOT" \ + $PROJECT_ROOT/.understand-anything/intermediate/changed-files-pre.json + ``` + + 6. Read `$PROJECT_ROOT/.understand-anything/intermediate/changed-files.json`. Pass the `kept` array as the input file list for Phase 1's fingerprint-check script. + + 7. If `kept.length === 0`: update `meta.json` with the new commit hash, report "All changed source files are in ignored paths. Metadata updated." and **STOP**. + --- ## Phase 1 — Structural Fingerprint Check (Zero LLM Tokens)