mirror of
https://github.com/Egonex-AI/Understand-Anything.git
synced 2026-06-22 10:58:03 +08:00
fix: address PR review feedback (C1-C4, I1-I5)
Critical fixes: - C1: Remove unused treeSitter.nodeTypes from configs and schema — extraction logic is TS/JS-specific, nodeTypes gave false impression of generality - C2+C3: Remove blocking temp dir prompt, default to .understand-anything/tmp/, update all 5 prompt templates to use project-local paths instead of /tmp/ - C4: Fix false-positive framework detection — use "next": (with quotes) for Next.js, remove cors/body-parser from Express keywords Important fixes: - I1: Change FrameworkConfig.language to languages[] array — React/Express/Vue now correctly listed under both typescript and javascript - I2: Fix getByExtension case sensitivity — .TS now resolves same as .ts - I3: languageKeyFromPath returns null instead of throwing for unknown extensions - I4: Duplicate framework registration is now a no-op instead of corrupting array - I5: SKILL.md now says "skip silently" when language/framework snippet not found Also: getForLanguage returns a defensive copy, 3 new tests added (157 total).
This commit is contained in:
@@ -81,6 +81,30 @@ describe("FrameworkRegistry", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("returns frameworks for all listed languages (cross-language)", () => {
|
||||
const registry = FrameworkRegistry.createDefault();
|
||||
// React lists both typescript and javascript
|
||||
const tsFrameworks = registry.getForLanguage("typescript");
|
||||
const jsFrameworks = registry.getForLanguage("javascript");
|
||||
expect(tsFrameworks.some((f) => f.id === "react")).toBe(true);
|
||||
expect(jsFrameworks.some((f) => f.id === "react")).toBe(true);
|
||||
});
|
||||
|
||||
it("does not duplicate on re-registration", () => {
|
||||
const registry = new FrameworkRegistry();
|
||||
registry.register(djangoConfig);
|
||||
registry.register(djangoConfig);
|
||||
expect(registry.getForLanguage("python")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("getForLanguage returns a copy, not the internal array", () => {
|
||||
const registry = new FrameworkRegistry();
|
||||
registry.register(djangoConfig);
|
||||
const result = registry.getForLanguage("python");
|
||||
result.push(reactConfig);
|
||||
expect(registry.getForLanguage("python")).toHaveLength(1);
|
||||
});
|
||||
|
||||
describe("createDefault", () => {
|
||||
it("registers all 10 built-in framework configs", () => {
|
||||
const registry = FrameworkRegistry.createDefault();
|
||||
|
||||
@@ -7,20 +7,6 @@ export const javascriptConfig = {
|
||||
treeSitter: {
|
||||
wasmPackage: "tree-sitter-javascript",
|
||||
wasmFile: "tree-sitter-javascript.wasm",
|
||||
nodeTypes: {
|
||||
function: [
|
||||
"function_declaration",
|
||||
"arrow_function",
|
||||
"function_expression",
|
||||
"method_definition",
|
||||
],
|
||||
class: ["class_declaration"],
|
||||
import: ["import_statement"],
|
||||
export: ["export_statement"],
|
||||
call: ["call_expression"],
|
||||
string: ["string", "string_fragment"],
|
||||
parameter: ["formal_parameters"],
|
||||
},
|
||||
},
|
||||
concepts: [
|
||||
"closures",
|
||||
|
||||
@@ -7,24 +7,6 @@ export const typescriptConfig = {
|
||||
treeSitter: {
|
||||
wasmPackage: "tree-sitter-typescript",
|
||||
wasmFile: "tree-sitter-typescript.wasm",
|
||||
nodeTypes: {
|
||||
function: [
|
||||
"function_declaration",
|
||||
"arrow_function",
|
||||
"function_expression",
|
||||
"method_definition",
|
||||
],
|
||||
class: ["class_declaration"],
|
||||
import: ["import_statement"],
|
||||
export: ["export_statement"],
|
||||
call: ["call_expression"],
|
||||
string: ["string", "string_fragment"],
|
||||
parameter: [
|
||||
"formal_parameters",
|
||||
"required_parameter",
|
||||
"optional_parameter",
|
||||
],
|
||||
},
|
||||
},
|
||||
concepts: [
|
||||
"generics",
|
||||
|
||||
@@ -12,11 +12,17 @@ export class FrameworkRegistry {
|
||||
|
||||
register(config: FrameworkConfig): void {
|
||||
const parsed = FrameworkConfigSchema.parse(config);
|
||||
|
||||
// Prevent duplicate registration
|
||||
if (this.byId.has(parsed.id)) return;
|
||||
|
||||
this.byId.set(parsed.id, parsed);
|
||||
|
||||
const existing = this.byLanguage.get(parsed.language) ?? [];
|
||||
existing.push(parsed);
|
||||
this.byLanguage.set(parsed.language, existing);
|
||||
for (const lang of parsed.languages) {
|
||||
const existing = this.byLanguage.get(lang) ?? [];
|
||||
existing.push(parsed);
|
||||
this.byLanguage.set(lang, existing);
|
||||
}
|
||||
}
|
||||
|
||||
getById(id: string): FrameworkConfig | null {
|
||||
@@ -24,7 +30,7 @@ export class FrameworkRegistry {
|
||||
}
|
||||
|
||||
getForLanguage(langId: string): FrameworkConfig[] {
|
||||
return this.byLanguage.get(langId) ?? [];
|
||||
return [...(this.byLanguage.get(langId) ?? [])];
|
||||
}
|
||||
|
||||
getAllFrameworks(): FrameworkConfig[] {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const djangoConfig = {
|
||||
id: "django",
|
||||
displayName: "Django",
|
||||
language: "python",
|
||||
languages: ["python"],
|
||||
detectionKeywords: [
|
||||
"django",
|
||||
"djangorestframework",
|
||||
|
||||
@@ -3,8 +3,8 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const expressConfig = {
|
||||
id: "express",
|
||||
displayName: "Express",
|
||||
language: "javascript",
|
||||
detectionKeywords: ["express", "express-validator", "cors", "body-parser"],
|
||||
languages: ["javascript", "typescript"],
|
||||
detectionKeywords: ["\"express\":", "express-validator", "express-session"],
|
||||
manifestFiles: ["package.json"],
|
||||
promptSnippetPath: "./frameworks/express.md",
|
||||
entryPoints: [
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const fastapiConfig = {
|
||||
id: "fastapi",
|
||||
displayName: "FastAPI",
|
||||
language: "python",
|
||||
languages: ["python"],
|
||||
detectionKeywords: ["fastapi", "uvicorn", "starlette"],
|
||||
manifestFiles: [
|
||||
"requirements.txt",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const flaskConfig = {
|
||||
id: "flask",
|
||||
displayName: "Flask",
|
||||
language: "python",
|
||||
languages: ["python"],
|
||||
detectionKeywords: [
|
||||
"flask",
|
||||
"flask-restful",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const ginConfig = {
|
||||
id: "gin",
|
||||
displayName: "Gin",
|
||||
language: "go",
|
||||
languages: ["go"],
|
||||
detectionKeywords: ["github.com/gin-gonic/gin"],
|
||||
manifestFiles: ["go.mod"],
|
||||
promptSnippetPath: "./frameworks/gin.md",
|
||||
|
||||
@@ -3,8 +3,8 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const nextjsConfig = {
|
||||
id: "nextjs",
|
||||
displayName: "Next.js",
|
||||
language: "typescript",
|
||||
detectionKeywords: ["next", "@next/font", "@next/image"],
|
||||
languages: ["typescript", "javascript"],
|
||||
detectionKeywords: ["\"next\":", "@next/font", "@next/image"],
|
||||
manifestFiles: ["package.json"],
|
||||
promptSnippetPath: "./frameworks/nextjs.md",
|
||||
entryPoints: [
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const railsConfig = {
|
||||
id: "rails",
|
||||
displayName: "Ruby on Rails",
|
||||
language: "ruby",
|
||||
languages: ["ruby"],
|
||||
detectionKeywords: [
|
||||
"rails",
|
||||
"railties",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const reactConfig = {
|
||||
id: "react",
|
||||
displayName: "React",
|
||||
language: "typescript",
|
||||
languages: ["typescript", "javascript"],
|
||||
detectionKeywords: ["react", "react-dom", "@types/react"],
|
||||
manifestFiles: ["package.json"],
|
||||
promptSnippetPath: "./frameworks/react.md",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const springConfig = {
|
||||
id: "spring",
|
||||
displayName: "Spring Boot",
|
||||
language: "java",
|
||||
languages: ["java", "kotlin"],
|
||||
detectionKeywords: [
|
||||
"spring-boot",
|
||||
"spring-boot-starter",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FrameworkConfig } from "../types.js";
|
||||
export const vueConfig = {
|
||||
id: "vue",
|
||||
displayName: "Vue",
|
||||
language: "typescript",
|
||||
languages: ["typescript", "javascript"],
|
||||
detectionKeywords: ["vue", "@vue/cli-service", "nuxt", "vite-plugin-vue"],
|
||||
manifestFiles: ["package.json"],
|
||||
promptSnippetPath: "./frameworks/vue.md",
|
||||
|
||||
@@ -25,7 +25,7 @@ export class LanguageRegistry {
|
||||
}
|
||||
|
||||
getByExtension(ext: string): LanguageConfig | null {
|
||||
const key = ext.startsWith(".") ? ext : `.${ext}`;
|
||||
const key = (ext.startsWith(".") ? ext : `.${ext}`).toLowerCase();
|
||||
return this.byExtension.get(key) ?? null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { z } from "zod";
|
||||
|
||||
// Tree-sitter node type mappings for a language
|
||||
// Tree-sitter grammar configuration for a language.
|
||||
// Only wasmPackage and wasmFile are needed for grammar loading.
|
||||
// The extraction logic in tree-sitter-plugin.ts is currently TS/JS-specific;
|
||||
// when grammars for other languages are added, language-specific extractors
|
||||
// should be registered via the customAnalyzer escape hatch.
|
||||
export const TreeSitterConfigSchema = z.object({
|
||||
wasmPackage: z.string(),
|
||||
wasmFile: z.string(),
|
||||
nodeTypes: z.object({
|
||||
function: z.array(z.string()),
|
||||
class: z.array(z.string()),
|
||||
import: z.array(z.string()),
|
||||
export: z.array(z.string()),
|
||||
call: z.array(z.string()),
|
||||
string: z.array(z.string()),
|
||||
parameter: z.array(z.string()),
|
||||
}),
|
||||
});
|
||||
|
||||
export type TreeSitterConfig = z.infer<typeof TreeSitterConfigSchema>;
|
||||
@@ -43,7 +38,7 @@ export type LanguageConfig = z.infer<typeof LanguageConfigSchema>;
|
||||
export const FrameworkConfigSchema = z.object({
|
||||
id: z.string().min(1),
|
||||
displayName: z.string().min(1),
|
||||
language: z.string().min(1),
|
||||
languages: z.array(z.string().min(1)).min(1),
|
||||
detectionKeywords: z.array(z.string()).min(1),
|
||||
manifestFiles: z.array(z.string()).min(1),
|
||||
promptSnippetPath: z.string().min(1),
|
||||
|
||||
@@ -201,17 +201,13 @@ export class TreeSitterPlugin implements AnalyzerPlugin {
|
||||
this.languages = langs;
|
||||
}
|
||||
|
||||
private languageKeyFromPath(filePath: string): string {
|
||||
private languageKeyFromPath(filePath: string): string | null {
|
||||
const ext = extname(filePath).toLowerCase();
|
||||
|
||||
// Special case: .tsx needs its own grammar
|
||||
if (ext === ".tsx") return "tsx";
|
||||
|
||||
const lang = this._extensionToLang.get(ext);
|
||||
if (!lang) {
|
||||
throw new Error(`Unsupported file extension: ${ext}`);
|
||||
}
|
||||
return lang;
|
||||
return this._extensionToLang.get(ext) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,6 +300,7 @@ export class TreeSitterPlugin implements AnalyzerPlugin {
|
||||
);
|
||||
}
|
||||
const langKey = this.languageKeyFromPath(filePath);
|
||||
if (!langKey) return null;
|
||||
const lang = this._languages.get(langKey);
|
||||
if (!lang) {
|
||||
// Language grammar not loaded — graceful degradation
|
||||
|
||||
@@ -20,29 +20,19 @@ Analyze the current codebase and produce a `knowledge-graph.json` file in `.unde
|
||||
|
||||
Determine whether to run a full analysis or incremental update.
|
||||
|
||||
1. **STOP and ask the user where temporary scripts and intermediate files should be written.** You MUST wait for the user's response before proceeding to step 2 or any other step. Do NOT read prompt templates, launch subagents, or begin any analysis until this question is answered.
|
||||
|
||||
Ask the user:
|
||||
> Where should I write temporary scripts and intermediate files during analysis?
|
||||
> 1. **Project directory** (recommended): `.understand-anything/tmp/` — stays within the project
|
||||
> 2. **System temp**: `/tmp/` — may require permissions outside the project
|
||||
|
||||
After the user responds, store the chosen path as `$TMP_DIR`. Create it: `mkdir -p $TMP_DIR`.
|
||||
|
||||
All subagent prompts reference `$TMP_DIR` for script files and intermediate JSON. When dispatching subagents, replace any `/tmp/ua-` paths in the prompt templates with `$TMP_DIR/ua-` so scripts and results are written to the user's chosen location.
|
||||
|
||||
2. Set `PROJECT_ROOT` to the current working directory.
|
||||
3. Get the current git commit hash:
|
||||
1. Set `PROJECT_ROOT` to the current working directory.
|
||||
2. Get the current git commit hash:
|
||||
```bash
|
||||
git rev-parse HEAD
|
||||
```
|
||||
4. Create the intermediate output directory:
|
||||
3. Create the intermediate and temp output directories:
|
||||
```bash
|
||||
mkdir -p $PROJECT_ROOT/.understand-anything/intermediate
|
||||
mkdir -p $PROJECT_ROOT/.understand-anything/tmp
|
||||
```
|
||||
5. Check if `$PROJECT_ROOT/.understand-anything/knowledge-graph.json` exists. If it does, read it.
|
||||
6. Check if `$PROJECT_ROOT/.understand-anything/meta.json` exists. If it does, read it to get `gitCommitHash`.
|
||||
7. **Decision logic:**
|
||||
4. Check if `$PROJECT_ROOT/.understand-anything/knowledge-graph.json` exists. If it does, read it.
|
||||
5. Check if `$PROJECT_ROOT/.understand-anything/meta.json` exists. If it does, read it to get `gitCommitHash`.
|
||||
6. **Decision logic:**
|
||||
|
||||
| Condition | Action |
|
||||
|---|---|
|
||||
@@ -57,7 +47,7 @@ Determine whether to run a full analysis or incremental update.
|
||||
```
|
||||
If this returns no files, report "Graph is up to date" and STOP.
|
||||
|
||||
8. **Collect project context for subagent injection:**
|
||||
7. **Collect project context for subagent injection:**
|
||||
- Read `README.md` (or `README.rst`, `readme.md`) from `$PROJECT_ROOT` if it exists. Store as `$README_CONTENT` (first 3000 characters).
|
||||
- Read the primary package manifest (`package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `pom.xml`) if it exists. Store as `$MANIFEST_CONTENT`.
|
||||
- Capture the top-level directory tree:
|
||||
@@ -113,8 +103,8 @@ For each batch, dispatch a subagent using the prompt template at `./file-analyze
|
||||
|
||||
**Build the combined prompt template:**
|
||||
1. Read the base template at `./file-analyzer-prompt.md`.
|
||||
2. **Language context injection:** For each language detected in Phase 1 (e.g., `python`), read the file at `./languages/<language-id>.md` (e.g., `./languages/python.md`) and append its content after the base template under a `## Language Context` header. These files are in the `languages/` subdirectory next to this SKILL.md file. Use `ls ./languages/` to discover available language files if needed.
|
||||
3. **Framework addendum injection:** For each framework detected in Phase 1 (e.g., `Django`), read the file at `./frameworks/<framework-id-lowercase>.md` (e.g., `./frameworks/django.md`) and append its full content after the language context. These files are in the `frameworks/` subdirectory next to this SKILL.md file. Use `ls ./frameworks/` to discover available framework files if needed.
|
||||
2. **Language context injection:** For each language detected in Phase 1 (e.g., `python`), read the file at `./languages/<language-id>.md` (e.g., `./languages/python.md`) and append its content after the base template under a `## Language Context` header. If the file does not exist for a detected language, skip it silently and continue. These files are in the `languages/` subdirectory next to this SKILL.md file. Use `ls ./languages/` to discover available language files if needed.
|
||||
3. **Framework addendum injection:** For each framework detected in Phase 1 (e.g., `Django`), read the file at `./frameworks/<framework-id-lowercase>.md` (e.g., `./frameworks/django.md`) and append its full content after the language context. If the file does not exist for a detected framework, skip it silently and continue. These files are in the `frameworks/` subdirectory next to this SKILL.md file. Use `ls ./frameworks/` to discover available framework files if needed.
|
||||
|
||||
Then for each batch pass the combined template content as the subagent's prompt, appending the following additional context:
|
||||
|
||||
@@ -172,8 +162,8 @@ Merge all file-analyzer results into a single set of nodes and edges. Then perfo
|
||||
|
||||
**Build the combined prompt template:**
|
||||
1. Read the base template at `./architecture-analyzer-prompt.md`.
|
||||
2. **Language context injection:** For each language detected in Phase 1 (e.g., `python`), read the file at `./languages/<language-id>.md` (e.g., `./languages/python.md`) and append its content after the base template under a `## Language Context` header. These files are in the `languages/` subdirectory next to this SKILL.md file.
|
||||
3. **Framework addendum injection:** For each framework detected in Phase 1 (e.g., `Django`), read the file at `./frameworks/<framework-id-lowercase>.md` (e.g., `./frameworks/django.md`) and append its full content after the language context. These files are in the `frameworks/` subdirectory next to this SKILL.md file.
|
||||
2. **Language context injection:** For each language detected in Phase 1 (e.g., `python`), read the file at `./languages/<language-id>.md` (e.g., `./languages/python.md`) and append its content after the base template under a `## Language Context` header. If the file does not exist for a detected language, skip it silently and continue. These files are in the `languages/` subdirectory next to this SKILL.md file.
|
||||
3. **Framework addendum injection:** For each framework detected in Phase 1 (e.g., `Django`), read the file at `./frameworks/<framework-id-lowercase>.md` (e.g., `./frameworks/django.md`) and append its full content after the language context. If the file does not exist for a detected framework, skip it silently and continue. These files are in the `frameworks/` subdirectory next to this SKILL.md file.
|
||||
|
||||
Pass the combined content as the subagent's prompt, appending the following additional context:
|
||||
|
||||
@@ -416,7 +406,7 @@ Pass these parameters in the dispatch prompt:
|
||||
3. Clean up intermediate files:
|
||||
```bash
|
||||
rm -rf $PROJECT_ROOT/.understand-anything/intermediate
|
||||
rm -rf $TMP_DIR
|
||||
rm -rf $PROJECT_ROOT/.understand-anything/tmp
|
||||
```
|
||||
|
||||
4. Report a summary to the user containing:
|
||||
|
||||
@@ -164,7 +164,7 @@ For each pair of groups with imports between them, determine the dominant direct
|
||||
Before writing the script, create its input JSON file:
|
||||
|
||||
```bash
|
||||
cat > /tmp/ua-arch-input.json << 'ENDJSON'
|
||||
cat > $PROJECT_ROOT/.understand-anything/tmp/ua-arch-input.json << 'ENDJSON'
|
||||
{
|
||||
"fileNodes": [<file nodes from prompt>],
|
||||
"importEdges": [<import edges from prompt>]
|
||||
@@ -177,7 +177,7 @@ ENDJSON
|
||||
After writing the script, execute it:
|
||||
|
||||
```bash
|
||||
node /tmp/ua-arch-analyze.js /tmp/ua-arch-input.json /tmp/ua-arch-results.json
|
||||
node $PROJECT_ROOT/.understand-anything/tmp/ua-arch-analyze.js $PROJECT_ROOT/.understand-anything/tmp/ua-arch-input.json $PROJECT_ROOT/.understand-anything/tmp/ua-arch-results.json
|
||||
```
|
||||
|
||||
If the script exits with a non-zero code, read stderr, diagnose the issue, fix the script, and re-run. You have up to 2 retry attempts.
|
||||
@@ -186,7 +186,7 @@ If the script exits with a non-zero code, read stderr, diagnose the issue, fix t
|
||||
|
||||
## Phase 2 -- Semantic Layer Assignment
|
||||
|
||||
After the script completes, read `/tmp/ua-arch-results.json`. Use the structural analysis as the primary input for your layer decisions. Do NOT re-read source files or re-analyze imports -- trust the script's results entirely.
|
||||
After the script completes, read `$PROJECT_ROOT/.understand-anything/tmp/ua-arch-results.json`. Use the structural analysis as the primary input for your layer decisions. Do NOT re-read source files or re-analyze imports -- trust the script's results entirely.
|
||||
|
||||
### Step 1 -- Evaluate Directory Groups as Layer Candidates
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ The script must write this exact JSON structure to the output file:
|
||||
Before writing the script, create its input JSON file. **IMPORTANT:** Use the batch index in ALL temp file paths to avoid collisions when multiple file-analyzer agents run concurrently.
|
||||
|
||||
```bash
|
||||
cat > /tmp/ua-file-analyzer-input-<batchIndex>.json << 'ENDJSON'
|
||||
cat > $PROJECT_ROOT/.understand-anything/tmp/ua-file-analyzer-input-<batchIndex>.json << 'ENDJSON'
|
||||
{
|
||||
"projectRoot": "<project-root>",
|
||||
"allProjectFiles": [<full file list from scan>],
|
||||
@@ -126,9 +126,9 @@ After writing the script, execute it. **Use the batch index in every temp file p
|
||||
|
||||
```bash
|
||||
# For Node.js scripts:
|
||||
node /tmp/ua-file-extract-<batchIndex>.js /tmp/ua-file-analyzer-input-<batchIndex>.json /tmp/ua-file-extract-results-<batchIndex>.json
|
||||
node $PROJECT_ROOT/.understand-anything/tmp/ua-file-extract-<batchIndex>.js $PROJECT_ROOT/.understand-anything/tmp/ua-file-analyzer-input-<batchIndex>.json $PROJECT_ROOT/.understand-anything/tmp/ua-file-extract-results-<batchIndex>.json
|
||||
# For Python scripts:
|
||||
python3 /tmp/ua-file-extract-<batchIndex>.py /tmp/ua-file-analyzer-input-<batchIndex>.json /tmp/ua-file-extract-results-<batchIndex>.json
|
||||
python3 $PROJECT_ROOT/.understand-anything/tmp/ua-file-extract-<batchIndex>.py $PROJECT_ROOT/.understand-anything/tmp/ua-file-analyzer-input-<batchIndex>.json $PROJECT_ROOT/.understand-anything/tmp/ua-file-extract-results-<batchIndex>.json
|
||||
```
|
||||
|
||||
If the script exits with a non-zero code, read stderr, diagnose the issue, fix the script, and re-run. You have up to 2 retry attempts.
|
||||
@@ -137,7 +137,7 @@ If the script exits with a non-zero code, read stderr, diagnose the issue, fix t
|
||||
|
||||
## Phase 2 -- Semantic Analysis
|
||||
|
||||
After the script completes, read `/tmp/ua-file-extract-results-<batchIndex>.json`. Use these structured results as the foundation for your analysis. Do NOT re-read the source files unless the script skipped a file or you need to understand a specific code pattern that the script could not capture.
|
||||
After the script completes, read `$PROJECT_ROOT/.understand-anything/tmp/ua-file-extract-results-<batchIndex>.json`. Use these structured results as the foundation for your analysis. Do NOT re-read the source files unless the script skipped a file or you need to understand a specific code pattern that the script could not capture.
|
||||
|
||||
For each file in the script's `results` array, produce `GraphNode` and `GraphEdge` objects by combining the script's structural data with your expert judgment.
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ The script must write this exact JSON structure to the output file:
|
||||
After writing the script, execute it:
|
||||
|
||||
```bash
|
||||
node /tmp/ua-graph-validate.js "<graph-file-path>" "/tmp/ua-review-results.json"
|
||||
node $PROJECT_ROOT/.understand-anything/tmp/ua-graph-validate.js "<graph-file-path>" "$PROJECT_ROOT/.understand-anything/tmp/ua-review-results.json"
|
||||
```
|
||||
|
||||
If the script exits with a non-zero code, read stderr, diagnose the issue, fix the script, and re-run. You have up to 2 retry attempts.
|
||||
@@ -143,7 +143,7 @@ If the script exits with a non-zero code, read stderr, diagnose the issue, fix t
|
||||
|
||||
## Phase 2 -- Review and Decision
|
||||
|
||||
After the script completes, read `/tmp/ua-review-results.json`. Do NOT re-read the original graph file -- trust the script's results entirely.
|
||||
After the script completes, read `$PROJECT_ROOT/.understand-anything/tmp/ua-review-results.json`. Do NOT re-read the original graph file -- trust the script's results entirely.
|
||||
|
||||
Review the `issues` and `warnings` arrays and render your decision:
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ The script must write this exact JSON structure to the output file:
|
||||
After writing the script, execute it:
|
||||
|
||||
```bash
|
||||
node /tmp/ua-project-scan.js "<project-root>" "/tmp/ua-scan-results.json"
|
||||
node $PROJECT_ROOT/.understand-anything/tmp/ua-project-scan.js "<project-root>" "$PROJECT_ROOT/.understand-anything/tmp/ua-scan-results.json"
|
||||
```
|
||||
|
||||
(Or the equivalent for bash/Python, depending on which language you chose.)
|
||||
@@ -152,7 +152,7 @@ If the script exits with a non-zero code, read stderr, diagnose the issue, fix t
|
||||
|
||||
## Phase 2 -- Description and Final Assembly
|
||||
|
||||
After the script completes, read `/tmp/ua-scan-results.json`. Do NOT re-run file discovery commands or re-count lines -- trust the script's results entirely.
|
||||
After the script completes, read `$PROJECT_ROOT/.understand-anything/tmp/ua-scan-results.json`. Do NOT re-run file discovery commands or re-count lines -- trust the script's results entirely.
|
||||
|
||||
**IMPORTANT:** The final output must NOT contain the `scriptCompleted`, `rawDescription`, or `readmeHead` fields. These are intermediate script fields only. Strip them when assembling the final JSON.
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ Create a lookup of each node ID to its `summary`, `type`, `tags` (default to emp
|
||||
Before writing the script, create its input JSON file:
|
||||
|
||||
```bash
|
||||
cat > /tmp/ua-tour-input.json << 'ENDJSON'
|
||||
cat > $PROJECT_ROOT/.understand-anything/tmp/ua-tour-input.json << 'ENDJSON'
|
||||
{
|
||||
"nodes": [<nodes from prompt>],
|
||||
"edges": [<edges from prompt>],
|
||||
@@ -146,7 +146,7 @@ ENDJSON
|
||||
After writing the script, execute it:
|
||||
|
||||
```bash
|
||||
node /tmp/ua-tour-analyze.js /tmp/ua-tour-input.json /tmp/ua-tour-results.json
|
||||
node $PROJECT_ROOT/.understand-anything/tmp/ua-tour-analyze.js $PROJECT_ROOT/.understand-anything/tmp/ua-tour-input.json $PROJECT_ROOT/.understand-anything/tmp/ua-tour-results.json
|
||||
```
|
||||
|
||||
If the script exits with a non-zero code, read stderr, diagnose the issue, fix the script, and re-run. You have up to 2 retry attempts.
|
||||
@@ -155,7 +155,7 @@ If the script exits with a non-zero code, read stderr, diagnose the issue, fix t
|
||||
|
||||
## Phase 2 -- Pedagogical Tour Design
|
||||
|
||||
After the script completes, read `/tmp/ua-tour-results.json`. Use the structural analysis as your primary guide for designing the tour. Do NOT re-read source files or re-analyze the graph -- trust the script's results entirely.
|
||||
After the script completes, read `$PROJECT_ROOT/.understand-anything/tmp/ua-tour-results.json`. Use the structural analysis as your primary guide for designing the tour. Do NOT re-read source files or re-analyze the graph -- trust the script's results entirely.
|
||||
|
||||
### Step 1 -- Choose the Starting Point
|
||||
|
||||
|
||||
Reference in New Issue
Block a user