fix: address remaining Copilot review findings

- SKILL.md Phase 7: use core buildFingerprintStore instead of ad-hoc regex script
- change-classifier: accurate FULL_UPDATE reason message (count vs percentage)
- persistence: add saveConfig/loadConfig tests (round-trip, missing, corrupted)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lum1104
2026-03-28 12:13:22 +08:00
Unverified
parent 5df763fd75
commit 39ee76f492
3 changed files with 44 additions and 31 deletions
@@ -43,13 +43,21 @@ export function classifyUpdate(
}
// Too many structural changes — suggest full rebuild
if (structuralCount > 30 || (totalFilesInGraph > 0 && structuralCount / totalFilesInGraph > 0.5)) {
const triggeredByCount = structuralCount > 30;
const triggeredByPercentage = totalFilesInGraph > 0 && structuralCount / totalFilesInGraph > 0.5;
if (triggeredByCount || triggeredByPercentage) {
const thresholdReason =
triggeredByCount && triggeredByPercentage
? ">30 files and >50% of project"
: triggeredByCount
? ">30 files"
: ">50% of project";
return {
action: "FULL_UPDATE",
filesToReanalyze: [...structurallyChangedFiles, ...newFiles],
rerunArchitecture: true,
rerunTour: true,
reason: `${structuralCount} files have structural changes (>${totalFilesInGraph > 0 ? "50% of project" : "30 files"}) — full rebuild recommended`,
reason: `${structuralCount} files have structural changes (${thresholdReason}) — full rebuild recommended`,
};
}
@@ -3,7 +3,7 @@ import { mkdtempSync, rmSync, existsSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { writeFileSync } from "node:fs";
import { saveGraph, loadGraph, saveMeta, loadMeta, saveFingerprints, loadFingerprints } from "./index.js";
import { saveGraph, loadGraph, saveMeta, loadMeta, saveFingerprints, loadFingerprints, saveConfig, loadConfig } from "./index.js";
import type { KnowledgeGraph, AnalysisMeta } from "../types.js";
import type { FingerprintStore } from "../fingerprint.js";
@@ -159,4 +159,28 @@ describe("persistence", () => {
expect(loaded).toBeNull();
});
});
describe("saveConfig / loadConfig", () => {
it("should round-trip config correctly", () => {
saveConfig(tempDir, { autoUpdate: true });
const loaded = loadConfig(tempDir);
expect(loaded).toEqual({ autoUpdate: true });
});
it("should return default config when no file exists", () => {
const loaded = loadConfig(tempDir);
expect(loaded).toEqual({ autoUpdate: false });
});
it("should return default config when config.json is corrupted", () => {
saveConfig(tempDir, { autoUpdate: true });
const dir = join(tempDir, ".understand-anything");
writeFileSync(join(dir, "config.json"), "not json!!", "utf-8");
const loaded = loadConfig(tempDir);
expect(loaded).toEqual({ autoUpdate: false });
});
});
});
@@ -482,34 +482,15 @@ Pass these parameters in the dispatch prompt:
2.5. **Generate structural fingerprints** for all analyzed files and save to `$PROJECT_ROOT/.understand-anything/fingerprints.json`. This creates the baseline for future automatic incremental updates.
Write and execute a Node.js script that:
1. Reads each source file path from the scan results (Phase 1)
2. For each file: computes a SHA-256 content hash, then extracts function/class/import/export declarations via regex matching:
- Functions: `function NAME(`, `const NAME = (`, `export function NAME(`, arrow functions assigned to const/let
- Classes: `class NAME`, `export class NAME`
- Imports: `import ... from '...'`, `import '...'`
- Exports: `export { ... }`, `export default`, `export function`, `export class`, `export const`
3. For each function: record name, parameter names, whether exported, and line count
4. For each class: record name, method names, property names, whether exported
5. Writes the fingerprint store JSON to `$PROJECT_ROOT/.understand-anything/fingerprints.json`:
```json
{
"version": "1.0.0",
"gitCommitHash": "<commit hash>",
"generatedAt": "<ISO timestamp>",
"files": {
"<filePath>": {
"filePath": "<filePath>",
"contentHash": "<sha256>",
"functions": [{ "name": "...", "params": ["..."], "exported": true, "lineCount": 35 }],
"classes": [{ "name": "...", "methods": ["..."], "properties": ["..."], "exported": true, "lineCount": 50 }],
"imports": [{ "source": "...", "specifiers": ["..."] }],
"exports": ["name1", "name2"],
"totalLines": 120
}
}
}
```
Write and execute a Node.js script that uses the core fingerprint module (tree-sitter-based, not regex):
```javascript
import { buildFingerprintStore } from '@understand-anything/core';
import { saveFingerprints } from '@understand-anything/core';
const store = await buildFingerprintStore('<PROJECT_ROOT>', sourceFilePaths);
saveFingerprints('<PROJECT_ROOT>', store);
```
Where `sourceFilePaths` is the list of all analyzed source file paths from Phase 1. This uses the same tree-sitter analysis pipeline as the main fingerprint engine, ensuring the baseline matches the comparison logic used during auto-updates.
3. Clean up intermediate files:
```bash