1427 lines
50 KiB
Markdown
1427 lines
50 KiB
Markdown
# Universal File Type Support — Implementation Plan
|
||
|
||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||
|
||
**Goal:** Extend Understand Anything to analyze 26+ non-code file types (Markdown, Dockerfile, YAML, SQL, Terraform, etc.) with new graph node/edge types, custom parsers, updated agent prompts, and dashboard visualization.
|
||
|
||
**Architecture:** Extend the existing LanguageConfig + AnalyzerPlugin pipeline. Add 8 new node types and 8 new edge types to the schema. Build 12 lightweight regex/parser-based analyzers for structured formats, LLM-only for unstructured. Update all 5 agent prompts to handle non-code files. Add new node colors and sidebar rendering to the dashboard.
|
||
|
||
**Tech Stack:** TypeScript, Zod, Vitest, React, React Flow, Zustand, TailwindCSS v4, `yaml` npm package, `@iarna/toml`, `jsonc-parser`
|
||
|
||
**Design doc:** `docs/plans/2026-03-28-understand-anything-extension-design.md`
|
||
|
||
---
|
||
|
||
## Task 1: Extend Core Types — Node & Edge Types
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/core/src/types.ts:1-116`
|
||
- Test: `understand-anything-plugin/packages/core/src/types.test.ts`
|
||
|
||
**Step 1: Write the failing test**
|
||
|
||
In `types.test.ts`, add a test that imports and verifies the new node types exist on GraphNode and edge types exist on EdgeType:
|
||
|
||
```typescript
|
||
import { describe, it, expect } from "vitest";
|
||
import type { GraphNode, GraphEdge, EdgeType, StructuralAnalysis } from "../types.js";
|
||
|
||
describe("Extended types", () => {
|
||
it("accepts all 13 node types", () => {
|
||
const nodeTypes: GraphNode["type"][] = [
|
||
"file", "function", "class", "module", "concept",
|
||
"config", "document", "service", "table", "endpoint",
|
||
"pipeline", "schema", "resource",
|
||
];
|
||
expect(nodeTypes).toHaveLength(13);
|
||
});
|
||
|
||
it("accepts all 26 edge types", () => {
|
||
const edgeTypes: EdgeType[] = [
|
||
"imports", "exports", "contains", "inherits", "implements",
|
||
"calls", "subscribes", "publishes", "middleware",
|
||
"reads_from", "writes_to", "transforms", "validates",
|
||
"depends_on", "tested_by", "configures",
|
||
"related", "similar_to",
|
||
"deploys", "serves", "migrates", "documents",
|
||
"provisions", "routes", "defines_schema", "triggers",
|
||
];
|
||
expect(edgeTypes).toHaveLength(26);
|
||
});
|
||
|
||
it("StructuralAnalysis has optional non-code fields", () => {
|
||
const analysis: StructuralAnalysis = {
|
||
functions: [], classes: [], imports: [], exports: [],
|
||
sections: [{ name: "Introduction", level: 1, lineRange: [1, 10] }],
|
||
definitions: [{ name: "users", kind: "table", lineRange: [1, 20], fields: ["id", "name"] }],
|
||
services: [{ name: "web", image: "node:22", ports: [3000] }],
|
||
endpoints: [{ method: "GET", path: "/api/users", lineRange: [5, 15] }],
|
||
steps: [{ name: "build", lineRange: [1, 5] }],
|
||
resources: [{ name: "aws_s3_bucket.main", kind: "aws_s3_bucket", lineRange: [1, 10] }],
|
||
};
|
||
expect(analysis.sections).toHaveLength(1);
|
||
expect(analysis.definitions).toHaveLength(1);
|
||
expect(analysis.services).toHaveLength(1);
|
||
expect(analysis.endpoints).toHaveLength(1);
|
||
expect(analysis.steps).toHaveLength(1);
|
||
expect(analysis.resources).toHaveLength(1);
|
||
});
|
||
});
|
||
```
|
||
|
||
**Step 2: Run test to verify it fails**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run types.test`
|
||
Expected: FAIL — TypeScript compilation errors for new types that don't exist yet
|
||
|
||
**Step 3: Implement the type extensions**
|
||
|
||
In `types.ts`, update the `GraphNode.type` union (line 12):
|
||
|
||
```typescript
|
||
type: "file" | "function" | "class" | "module" | "concept"
|
||
| "config" | "document" | "service" | "table" | "endpoint"
|
||
| "pipeline" | "schema" | "resource";
|
||
```
|
||
|
||
Update the `EdgeType` type (lines 1-7) to add 8 new edge types:
|
||
|
||
```typescript
|
||
export type EdgeType =
|
||
| "imports" | "exports" | "contains" | "inherits" | "implements" // Structural
|
||
| "calls" | "subscribes" | "publishes" | "middleware" // Behavioral
|
||
| "reads_from" | "writes_to" | "transforms" | "validates" // Data flow
|
||
| "depends_on" | "tested_by" | "configures" // Dependencies
|
||
| "related" | "similar_to" // Semantic
|
||
| "deploys" | "serves" | "migrates" | "documents" // Infrastructure
|
||
| "provisions" | "routes" | "defines_schema" | "triggers"; // Infrastructure
|
||
```
|
||
|
||
Extend `StructuralAnalysis` (after line 95) with new optional fields:
|
||
|
||
```typescript
|
||
export interface SectionInfo {
|
||
name: string;
|
||
level: number;
|
||
lineRange: [number, number];
|
||
}
|
||
|
||
export interface DefinitionInfo {
|
||
name: string;
|
||
kind: string; // "table", "message", "type", "schema"
|
||
lineRange: [number, number];
|
||
fields: string[];
|
||
}
|
||
|
||
export interface ServiceInfo {
|
||
name: string;
|
||
image?: string;
|
||
ports: number[];
|
||
}
|
||
|
||
export interface EndpointInfo {
|
||
method?: string;
|
||
path: string;
|
||
lineRange: [number, number];
|
||
}
|
||
|
||
export interface StepInfo {
|
||
name: string;
|
||
lineRange: [number, number];
|
||
}
|
||
|
||
export interface ResourceInfo {
|
||
name: string;
|
||
kind: string;
|
||
lineRange: [number, number];
|
||
}
|
||
|
||
export interface ReferenceResolution {
|
||
source: string;
|
||
target: string;
|
||
referenceType: string; // "file", "image", "schema", "service"
|
||
line?: number;
|
||
}
|
||
|
||
export interface StructuralAnalysis {
|
||
functions: Array<{ name: string; lineRange: [number, number]; params: string[]; returnType?: string }>;
|
||
classes: Array<{ name: string; lineRange: [number, number]; methods: string[]; properties: string[] }>;
|
||
imports: Array<{ source: string; specifiers: string[]; lineNumber: number }>;
|
||
exports: Array<{ name: string; lineNumber: number }>;
|
||
// Non-code structural data (all optional for backward compat)
|
||
sections?: SectionInfo[];
|
||
definitions?: DefinitionInfo[];
|
||
services?: ServiceInfo[];
|
||
endpoints?: EndpointInfo[];
|
||
steps?: StepInfo[];
|
||
resources?: ResourceInfo[];
|
||
}
|
||
```
|
||
|
||
Update `AnalyzerPlugin` interface (lines 109-115) — make `resolveImports` optional, add `extractReferences`:
|
||
|
||
```typescript
|
||
export interface AnalyzerPlugin {
|
||
name: string;
|
||
languages: string[];
|
||
analyzeFile(filePath: string, content: string): StructuralAnalysis;
|
||
resolveImports?(filePath: string, content: string): ImportResolution[];
|
||
extractCallGraph?(filePath: string, content: string): CallGraphEntry[];
|
||
extractReferences?(filePath: string, content: string): ReferenceResolution[];
|
||
}
|
||
```
|
||
|
||
**Step 4: Run test to verify it passes**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run types.test`
|
||
Expected: PASS
|
||
|
||
**Step 5: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/core/src/types.ts understand-anything-plugin/packages/core/src/types.test.ts
|
||
git commit -m "feat(core): extend GraphNode/EdgeType/StructuralAnalysis for non-code file types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 2: Extend Schema Validation — Zod Schemas & Aliases
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/core/src/schema.ts:1-554`
|
||
- Test: `understand-anything-plugin/packages/core/src/__tests__/schema.test.ts`
|
||
|
||
**Step 1: Write the failing tests**
|
||
|
||
Add to `schema.test.ts`:
|
||
|
||
```typescript
|
||
describe("Extended node/edge types", () => {
|
||
it("validates nodes with new types: config, document, service, table, endpoint, pipeline, schema, resource", () => {
|
||
const newTypes = ["config", "document", "service", "table", "endpoint", "pipeline", "schema", "resource"];
|
||
for (const type of newTypes) {
|
||
const graph = structuredClone(validGraph);
|
||
graph.nodes[0].type = type;
|
||
const result = validateGraph(graph);
|
||
expect(result.success).toBe(true);
|
||
expect(result.data!.nodes[0].type).toBe(type);
|
||
}
|
||
});
|
||
|
||
it("validates edges with new types: deploys, serves, migrates, documents, provisions, routes, defines_schema, triggers", () => {
|
||
const newTypes = ["deploys", "serves", "migrates", "documents", "provisions", "routes", "defines_schema", "triggers"];
|
||
for (const type of newTypes) {
|
||
const graph = structuredClone(validGraph);
|
||
graph.edges[0].type = type;
|
||
const result = validateGraph(graph);
|
||
expect(result.success).toBe(true);
|
||
expect(result.data!.edges[0].type).toBe(type);
|
||
}
|
||
});
|
||
|
||
it("auto-fixes new node type aliases: container→service, doc→document, workflow→pipeline, etc.", () => {
|
||
const aliases = { container: "service", doc: "document", workflow: "pipeline", route: "endpoint", setting: "config", infra: "resource", migration: "table" };
|
||
for (const [alias, canonical] of Object.entries(aliases)) {
|
||
const graph = structuredClone(validGraph);
|
||
(graph.nodes[0] as any).type = alias;
|
||
const result = validateGraph(graph);
|
||
expect(result.success).toBe(true);
|
||
expect(result.data!.nodes[0].type).toBe(canonical);
|
||
}
|
||
});
|
||
|
||
it("auto-fixes new edge type aliases: describes→documents, creates→provisions, exposes→serves", () => {
|
||
const aliases = { describes: "documents", creates: "provisions", exposes: "serves" };
|
||
for (const [alias, canonical] of Object.entries(aliases)) {
|
||
const graph = structuredClone(validGraph);
|
||
(graph.edges[0] as any).type = alias;
|
||
const result = validateGraph(graph);
|
||
expect(result.success).toBe(true);
|
||
expect(result.data!.edges[0].type).toBe(canonical);
|
||
}
|
||
});
|
||
});
|
||
```
|
||
|
||
**Step 2: Run test to verify it fails**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run schema.test`
|
||
Expected: FAIL — Zod enum rejects new types
|
||
|
||
**Step 3: Implement schema extensions**
|
||
|
||
In `schema.ts`:
|
||
|
||
1. Update `EdgeTypeSchema` (line 4-10) — add 8 new edge types:
|
||
```typescript
|
||
export const EdgeTypeSchema = z.enum([
|
||
"imports", "exports", "contains", "inherits", "implements",
|
||
"calls", "subscribes", "publishes", "middleware",
|
||
"reads_from", "writes_to", "transforms", "validates",
|
||
"depends_on", "tested_by", "configures",
|
||
"related", "similar_to",
|
||
"deploys", "serves", "migrates", "documents",
|
||
"provisions", "routes", "defines_schema", "triggers",
|
||
]);
|
||
```
|
||
|
||
2. Update `NODE_TYPE_ALIASES` (line 13-22) — add new aliases:
|
||
```typescript
|
||
export const NODE_TYPE_ALIASES: Record<string, string> = {
|
||
func: "function", fn: "function", method: "function",
|
||
interface: "class", struct: "class",
|
||
mod: "module", pkg: "module", package: "module",
|
||
// New non-code aliases
|
||
container: "service", deployment: "service", pod: "service",
|
||
doc: "document", readme: "document", docs: "document",
|
||
workflow: "pipeline", job: "pipeline", ci: "pipeline", action: "pipeline",
|
||
route: "endpoint", api: "endpoint", query: "endpoint", mutation: "endpoint",
|
||
setting: "config", env: "config", configuration: "config",
|
||
infra: "resource", infrastructure: "resource", terraform: "resource",
|
||
migration: "table", database: "table", db: "table", view: "table",
|
||
proto: "schema", protobuf: "schema", definition: "schema", typedef: "schema",
|
||
};
|
||
```
|
||
|
||
3. Update `EDGE_TYPE_ALIASES` (line 25-39) — add new aliases:
|
||
```typescript
|
||
// Add these entries:
|
||
describes: "documents",
|
||
documented_by: "documents",
|
||
creates: "provisions",
|
||
exposes: "serves",
|
||
listens: "serves",
|
||
deploys_to: "deploys",
|
||
migrates_to: "migrates",
|
||
routes_to: "routes",
|
||
triggers_on: "triggers",
|
||
fires: "triggers",
|
||
defines: "defines_schema",
|
||
```
|
||
|
||
4. Update `GraphNodeSchema` (line 267-277) — extend type enum:
|
||
```typescript
|
||
export const GraphNodeSchema = z.object({
|
||
id: z.string(),
|
||
type: z.enum([
|
||
"file", "function", "class", "module", "concept",
|
||
"config", "document", "service", "table", "endpoint",
|
||
"pipeline", "schema", "resource",
|
||
]),
|
||
name: z.string(),
|
||
filePath: z.string().optional(),
|
||
lineRange: z.tuple([z.number(), z.number()]).optional(),
|
||
summary: z.string(),
|
||
tags: z.array(z.string()),
|
||
complexity: z.enum(["simple", "moderate", "complex"]),
|
||
languageNotes: z.string().optional(),
|
||
});
|
||
```
|
||
|
||
**Step 4: Run test to verify it passes**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run schema.test`
|
||
Expected: PASS
|
||
|
||
**Step 5: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/core/src/schema.ts understand-anything-plugin/packages/core/src/__tests__/schema.test.ts
|
||
git commit -m "feat(core): extend Zod schemas and aliases for 8 new node/edge types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 3: Update PluginRegistry — Optional resolveImports
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/core/src/plugins/registry.ts:1-76`
|
||
- Test: `understand-anything-plugin/packages/core/src/__tests__/plugin-registry.test.ts`
|
||
|
||
**Step 1: Write the failing test**
|
||
|
||
Add to `plugin-registry.test.ts`:
|
||
|
||
```typescript
|
||
it("handles plugins with optional resolveImports (non-code plugins)", () => {
|
||
const markdownPlugin: AnalyzerPlugin = {
|
||
name: "markdown",
|
||
languages: ["markdown"],
|
||
analyzeFile: () => ({ functions: [], classes: [], imports: [], exports: [] }),
|
||
// No resolveImports — optional
|
||
};
|
||
registry.register(markdownPlugin);
|
||
const result = registry.resolveImports("README.md", "# Hello");
|
||
expect(result).toBeNull(); // Returns null for plugins without resolveImports
|
||
});
|
||
```
|
||
|
||
**Step 2: Run test to verify it fails**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run plugin-registry.test`
|
||
Expected: FAIL — current registry calls `plugin.resolveImports(...)` unconditionally
|
||
|
||
**Step 3: Update PluginRegistry**
|
||
|
||
In `registry.ts`, update `resolveImports` (line 62-66):
|
||
|
||
```typescript
|
||
resolveImports(filePath: string, content: string): ImportResolution[] | null {
|
||
const plugin = this.getPluginForFile(filePath);
|
||
if (!plugin || !plugin.resolveImports) return null;
|
||
return plugin.resolveImports(filePath, content);
|
||
}
|
||
```
|
||
|
||
**Step 4: Run test to verify it passes**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run plugin-registry.test`
|
||
Expected: PASS
|
||
|
||
**Step 5: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/core/src/plugins/registry.ts understand-anything-plugin/packages/core/src/__tests__/plugin-registry.test.ts
|
||
git commit -m "feat(core): make resolveImports optional on AnalyzerPlugin"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 4: Add Non-Code Language Configs (26 configs)
|
||
|
||
**Files:**
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/markdown.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/yaml.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/json-config.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/toml.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/env.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/xml.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/dockerfile.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/sql.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/graphql.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/protobuf.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/terraform.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/github-actions.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/makefile.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/shell.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/html.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/css.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/openapi.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/kubernetes.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/docker-compose.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/json-schema.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/csv.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/restructuredtext.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/powershell.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/batch.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/jenkinsfile.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/languages/configs/plaintext.ts`
|
||
- Modify: `understand-anything-plugin/packages/core/src/languages/configs/index.ts`
|
||
- Test: `understand-anything-plugin/packages/core/src/__tests__/language-registry.test.ts`
|
||
|
||
**Step 1: Write the failing test**
|
||
|
||
Add to `language-registry.test.ts`:
|
||
|
||
```typescript
|
||
describe("Non-code language configs", () => {
|
||
it("detects all non-code file types via extension", () => {
|
||
const registry = LanguageRegistry.createDefault();
|
||
const expectations: [string, string][] = [
|
||
["README.md", "markdown"],
|
||
["config.yaml", "yaml"],
|
||
["package.json", "json"],
|
||
["config.toml", "toml"],
|
||
[".env", "env"],
|
||
["pom.xml", "xml"],
|
||
["Dockerfile", "dockerfile"],
|
||
["schema.sql", "sql"],
|
||
["schema.graphql", "graphql"],
|
||
["types.proto", "protobuf"],
|
||
["main.tf", "terraform"],
|
||
["Makefile", "makefile"],
|
||
["deploy.sh", "shell"],
|
||
["index.html", "html"],
|
||
["styles.css", "css"],
|
||
["data.csv", "csv"],
|
||
["deploy.ps1", "powershell"],
|
||
];
|
||
for (const [file, expectedId] of expectations) {
|
||
const config = registry.getForFile(file);
|
||
expect(config?.id, `${file} should be detected as ${expectedId}`).toBe(expectedId);
|
||
}
|
||
});
|
||
});
|
||
```
|
||
|
||
**Step 2: Run test to verify it fails**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run language-registry.test`
|
||
Expected: FAIL — no configs registered for non-code extensions
|
||
|
||
**Step 3: Create all config files**
|
||
|
||
Each config follows the same pattern as `typescript.ts`. Example for markdown:
|
||
|
||
```typescript
|
||
// markdown.ts
|
||
import type { LanguageConfig } from "../types.js";
|
||
|
||
export const markdownConfig = {
|
||
id: "markdown",
|
||
displayName: "Markdown",
|
||
extensions: [".md", ".mdx"],
|
||
concepts: ["headings", "links", "code blocks", "front matter", "lists", "tables", "images"],
|
||
filePatterns: {
|
||
entryPoints: ["README.md"],
|
||
barrels: [],
|
||
tests: [],
|
||
config: [],
|
||
},
|
||
} satisfies LanguageConfig;
|
||
```
|
||
|
||
Create similar configs for all 26 types. Key extension mappings:
|
||
- yaml: `.yaml`, `.yml`
|
||
- json: `.json`, `.jsonc`
|
||
- toml: `.toml`
|
||
- env: `.env` (Note: LanguageRegistry needs filename match, not just extension)
|
||
- xml: `.xml`
|
||
- dockerfile: `Dockerfile` (filename-based detection — needs special handling)
|
||
- sql: `.sql`
|
||
- graphql: `.graphql`, `.gql`
|
||
- protobuf: `.proto`
|
||
- terraform: `.tf`, `.tfvars`
|
||
- github-actions: (detected by path `.github/workflows/*.yml` — defer to scanner)
|
||
- makefile: `Makefile` (filename-based — needs special handling)
|
||
- shell: `.sh`, `.bash`, `.zsh`
|
||
- html: `.html`, `.htm`
|
||
- css: `.css`, `.scss`, `.less`
|
||
- csv: `.csv`, `.tsv`
|
||
- powershell: `.ps1`, `.psm1`
|
||
- batch: `.bat`, `.cmd`
|
||
- plaintext: `.txt`
|
||
- restructuredtext: `.rst`
|
||
- jenkinsfile: (filename-based — `Jenkinsfile`)
|
||
|
||
**Important:** For filename-based detection (Dockerfile, Makefile, Jenkinsfile), extend LanguageRegistry to support `filenames` array in addition to `extensions`. Add a `filenames?: string[]` field to `LanguageConfig` and update `getForFile()` to check basename against filenames when extension lookup fails.
|
||
|
||
Update `configs/index.ts` to import and register all new configs in `builtinLanguageConfigs`.
|
||
|
||
**Step 4: Run test to verify it passes**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run language-registry.test`
|
||
Expected: PASS
|
||
|
||
**Step 5: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/core/src/languages/
|
||
git commit -m "feat(core): add 26 non-code language configs with filename-based detection"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 5: Build Custom Parsers (12 parsers)
|
||
|
||
**Files:**
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/markdown-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/yaml-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/json-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/toml-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/env-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/dockerfile-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/sql-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/graphql-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/protobuf-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/terraform-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/makefile-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/shell-parser.ts`
|
||
- Create: `understand-anything-plugin/packages/core/src/plugins/parsers/index.ts`
|
||
- Test: `understand-anything-plugin/packages/core/src/__tests__/parsers.test.ts`
|
||
|
||
Each parser implements `AnalyzerPlugin`. Build them TDD-style, one at a time.
|
||
|
||
**Step 1: Write failing tests for all 12 parsers**
|
||
|
||
Create `parsers.test.ts` with test suites for each parser. Example for MarkdownParser:
|
||
|
||
```typescript
|
||
import { describe, it, expect } from "vitest";
|
||
import { MarkdownParser } from "../plugins/parsers/markdown-parser.js";
|
||
|
||
describe("MarkdownParser", () => {
|
||
const parser = new MarkdownParser();
|
||
|
||
it("extracts heading sections", () => {
|
||
const content = "# Title\n\nIntro\n\n## Section A\n\nContent A\n\n### Subsection\n\nContent B";
|
||
const result = parser.analyzeFile("README.md", content);
|
||
expect(result.sections).toHaveLength(3);
|
||
expect(result.sections![0]).toMatchObject({ name: "Title", level: 1 });
|
||
expect(result.sections![1]).toMatchObject({ name: "Section A", level: 2 });
|
||
expect(result.sections![2]).toMatchObject({ name: "Subsection", level: 3 });
|
||
});
|
||
|
||
it("extracts YAML front matter as imports", () => {
|
||
const content = "---\ntitle: Test\ntags: [a, b]\n---\n# Content";
|
||
const result = parser.analyzeFile("post.md", content);
|
||
expect(result.imports).toHaveLength(0); // Front matter is metadata, not imports
|
||
});
|
||
|
||
it("extracts file references", () => {
|
||
const parser2 = new MarkdownParser();
|
||
const content = "See [guide](./docs/guide.md) and ";
|
||
const refs = parser2.extractReferences!("README.md", content);
|
||
expect(refs).toHaveLength(2);
|
||
expect(refs[0]).toMatchObject({ target: "./docs/guide.md", referenceType: "file" });
|
||
expect(refs[1]).toMatchObject({ target: "./assets/logo.png", referenceType: "image" });
|
||
});
|
||
});
|
||
```
|
||
|
||
Similar test suites for:
|
||
- **DockerfileParser**: Extract FROM stages, EXPOSE ports, COPY sources
|
||
- **SQLParser**: Extract CREATE TABLE, columns, foreign keys
|
||
- **YAMLParser**: Extract top-level key hierarchy
|
||
- **JSONParser**: Extract key structure, `$ref`/`$defs`
|
||
- **TerraformParser**: Extract resource/module/variable blocks
|
||
- **GraphQLParser**: Extract type/query/mutation/subscription definitions
|
||
- **ProtobufParser**: Extract message/service/enum definitions
|
||
- **MakefileParser**: Extract targets and dependencies
|
||
- **ShellParser**: Extract function definitions and source commands
|
||
- **TOMLParser**: Extract section structure
|
||
- **EnvParser**: Extract variable names
|
||
|
||
**Step 2: Run tests to verify they fail**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run parsers.test`
|
||
Expected: FAIL — parser modules don't exist
|
||
|
||
**Step 3: Implement all 12 parsers**
|
||
|
||
Each parser follows this pattern:
|
||
|
||
```typescript
|
||
import type { AnalyzerPlugin, StructuralAnalysis, ReferenceResolution } from "../../types.js";
|
||
|
||
export class MarkdownParser implements AnalyzerPlugin {
|
||
name = "markdown-parser";
|
||
languages = ["markdown"];
|
||
|
||
analyzeFile(filePath: string, content: string): StructuralAnalysis {
|
||
const sections = this.extractSections(content);
|
||
return {
|
||
functions: [], classes: [], imports: [], exports: [],
|
||
sections,
|
||
};
|
||
}
|
||
|
||
extractReferences(filePath: string, content: string): ReferenceResolution[] {
|
||
const refs: ReferenceResolution[] = [];
|
||
// Match [text](path) and 
|
||
const linkRegex = /!?\[([^\]]*)\]\(([^)]+)\)/g;
|
||
let match;
|
||
while ((match = linkRegex.exec(content)) !== null) {
|
||
const target = match[2];
|
||
if (target.startsWith("http")) continue; // Skip external URLs
|
||
const line = content.slice(0, match.index).split("\n").length;
|
||
refs.push({
|
||
source: filePath,
|
||
target,
|
||
referenceType: match[0].startsWith("!") ? "image" : "file",
|
||
line,
|
||
});
|
||
}
|
||
return refs;
|
||
}
|
||
|
||
private extractSections(content: string): SectionInfo[] {
|
||
const sections: SectionInfo[] = [];
|
||
const lines = content.split("\n");
|
||
for (let i = 0; i < lines.length; i++) {
|
||
const match = lines[i].match(/^(#{1,6})\s+(.+)/);
|
||
if (match) {
|
||
sections.push({
|
||
name: match[2].trim(),
|
||
level: match[1].length,
|
||
lineRange: [i + 1, i + 1],
|
||
});
|
||
}
|
||
}
|
||
// Fix lineRange end for each section (extends to next heading or EOF)
|
||
for (let i = 0; i < sections.length; i++) {
|
||
const next = sections[i + 1];
|
||
sections[i].lineRange[1] = next ? next.lineRange[0] - 1 : lines.length;
|
||
}
|
||
return sections;
|
||
}
|
||
}
|
||
```
|
||
|
||
Create `parsers/index.ts` that exports all parsers and a `registerAllParsers(registry: PluginRegistry)` helper.
|
||
|
||
**Install new dependencies:**
|
||
```bash
|
||
cd understand-anything-plugin/packages/core
|
||
pnpm add yaml @iarna/toml jsonc-parser
|
||
```
|
||
|
||
**Step 4: Run tests to verify they pass**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run parsers.test`
|
||
Expected: PASS
|
||
|
||
**Step 5: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/core/src/plugins/parsers/ understand-anything-plugin/packages/core/src/__tests__/parsers.test.ts understand-anything-plugin/packages/core/package.json understand-anything-plugin/packages/core/pnpm-lock.yaml
|
||
git commit -m "feat(core): add 12 custom parsers for non-code file types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 6: Update GraphBuilder — Support New Node Types
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/core/src/analyzer/graph-builder.ts:1-207`
|
||
- Test: `understand-anything-plugin/packages/core/src/analyzer/graph-builder.test.ts`
|
||
|
||
**Step 1: Write the failing test**
|
||
|
||
Add to `graph-builder.test.ts`:
|
||
|
||
```typescript
|
||
describe("Non-code file support", () => {
|
||
it("adds non-code file nodes with correct types", () => {
|
||
const builder = new GraphBuilder("test", "abc123");
|
||
builder.addNonCodeFile("README.md", {
|
||
nodeType: "document",
|
||
summary: "Project documentation",
|
||
tags: ["documentation"],
|
||
complexity: "simple",
|
||
});
|
||
const graph = builder.build();
|
||
expect(graph.nodes).toHaveLength(1);
|
||
expect(graph.nodes[0].type).toBe("document");
|
||
expect(graph.nodes[0].id).toBe("file:README.md");
|
||
});
|
||
|
||
it("adds non-code child nodes (sections, definitions, services)", () => {
|
||
const builder = new GraphBuilder("test", "abc123");
|
||
builder.addNonCodeFileWithAnalysis("schema.sql", {
|
||
nodeType: "file",
|
||
summary: "Database schema",
|
||
tags: ["database"],
|
||
complexity: "moderate",
|
||
definitions: [{ name: "users", kind: "table", lineRange: [1, 20] as [number, number], fields: ["id", "name", "email"] }],
|
||
});
|
||
const graph = builder.build();
|
||
// File node + table child node
|
||
expect(graph.nodes).toHaveLength(2);
|
||
expect(graph.nodes[1].type).toBe("table");
|
||
expect(graph.nodes[1].name).toBe("users");
|
||
// Contains edge
|
||
expect(graph.edges.some(e => e.type === "contains" && e.target.includes("users"))).toBe(true);
|
||
});
|
||
|
||
it("detects non-code languages from EXTENSION_LANGUAGE map", () => {
|
||
const builder = new GraphBuilder("test", "abc123");
|
||
builder.addFile("config.yaml", { summary: "Config", tags: [], complexity: "simple" });
|
||
const graph = builder.build();
|
||
expect(graph.project.languages).toContain("yaml");
|
||
});
|
||
});
|
||
```
|
||
|
||
**Step 2: Run test to verify it fails**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run graph-builder.test`
|
||
Expected: FAIL — `addNonCodeFile` and `addNonCodeFileWithAnalysis` methods don't exist
|
||
|
||
**Step 3: Implement GraphBuilder extensions**
|
||
|
||
Add new methods to GraphBuilder:
|
||
|
||
```typescript
|
||
interface NonCodeFileMeta extends FileMeta {
|
||
nodeType: GraphNode["type"];
|
||
}
|
||
|
||
interface NonCodeFileAnalysisMeta extends NonCodeFileMeta {
|
||
definitions?: DefinitionInfo[];
|
||
services?: ServiceInfo[];
|
||
endpoints?: EndpointInfo[];
|
||
steps?: StepInfo[];
|
||
resources?: ResourceInfo[];
|
||
sections?: SectionInfo[];
|
||
}
|
||
|
||
addNonCodeFile(filePath: string, meta: NonCodeFileMeta): void {
|
||
const lang = detectLanguage(filePath);
|
||
if (lang !== "unknown") this.languages.add(lang);
|
||
const name = filePath.split("/").pop() ?? filePath;
|
||
this.nodes.push({
|
||
id: `file:${filePath}`,
|
||
type: meta.nodeType,
|
||
name,
|
||
filePath,
|
||
summary: meta.summary,
|
||
tags: meta.tags,
|
||
complexity: meta.complexity,
|
||
});
|
||
}
|
||
|
||
addNonCodeFileWithAnalysis(filePath: string, meta: NonCodeFileAnalysisMeta): void {
|
||
this.addNonCodeFile(filePath, meta);
|
||
const fileId = `file:${filePath}`;
|
||
|
||
// Create child nodes for definitions (tables, schemas, etc.)
|
||
for (const def of meta.definitions ?? []) {
|
||
const childId = `${def.kind}:${filePath}:${def.name}`;
|
||
this.nodes.push({
|
||
id: childId,
|
||
type: this.mapKindToNodeType(def.kind),
|
||
name: def.name,
|
||
filePath,
|
||
lineRange: def.lineRange,
|
||
summary: `${def.kind}: ${def.name} (${def.fields.length} fields)`,
|
||
tags: [],
|
||
complexity: meta.complexity,
|
||
});
|
||
this.edges.push({ source: fileId, target: childId, type: "contains", direction: "forward", weight: 1 });
|
||
}
|
||
|
||
// Create child nodes for services
|
||
for (const svc of meta.services ?? []) {
|
||
const childId = `service:${filePath}:${svc.name}`;
|
||
this.nodes.push({
|
||
id: childId, type: "service", name: svc.name, filePath,
|
||
summary: `Service ${svc.name}${svc.image ? ` (image: ${svc.image})` : ""}`,
|
||
tags: [], complexity: meta.complexity,
|
||
});
|
||
this.edges.push({ source: fileId, target: childId, type: "contains", direction: "forward", weight: 1 });
|
||
}
|
||
|
||
// Similar for endpoints, steps, resources
|
||
}
|
||
|
||
private mapKindToNodeType(kind: string): GraphNode["type"] {
|
||
const mapping: Record<string, GraphNode["type"]> = {
|
||
table: "table", view: "table", index: "table",
|
||
message: "schema", type: "schema", enum: "schema",
|
||
resource: "resource", module: "resource",
|
||
service: "service", deployment: "service",
|
||
job: "pipeline", stage: "pipeline", target: "pipeline",
|
||
route: "endpoint", query: "endpoint", mutation: "endpoint",
|
||
};
|
||
return mapping[kind] ?? "concept";
|
||
}
|
||
```
|
||
|
||
**Step 4: Run test to verify it passes**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test -- --run graph-builder.test`
|
||
Expected: PASS
|
||
|
||
**Step 5: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/core/src/analyzer/graph-builder.ts understand-anything-plugin/packages/core/src/analyzer/graph-builder.test.ts
|
||
git commit -m "feat(core): add non-code file support to GraphBuilder"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 7: Update Core Exports
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/core/src/index.ts`
|
||
|
||
**Step 1: Update exports to include new types and parsers**
|
||
|
||
Add to `index.ts`:
|
||
|
||
```typescript
|
||
// New structural analysis types
|
||
export type {
|
||
SectionInfo,
|
||
DefinitionInfo,
|
||
ServiceInfo,
|
||
EndpointInfo,
|
||
StepInfo,
|
||
ResourceInfo,
|
||
ReferenceResolution,
|
||
} from "./types.js";
|
||
|
||
// Non-code parsers
|
||
export {
|
||
MarkdownParser,
|
||
DockerfileParser,
|
||
SQLParser,
|
||
YAMLConfigParser,
|
||
JSONConfigParser,
|
||
TOMLParser,
|
||
EnvParser,
|
||
GraphQLParser,
|
||
ProtobufParser,
|
||
TerraformParser,
|
||
MakefileParser,
|
||
ShellParser,
|
||
registerAllParsers,
|
||
} from "./plugins/parsers/index.js";
|
||
```
|
||
|
||
**Step 2: Build to verify exports work**
|
||
|
||
Run: `pnpm --filter @understand-anything/core build`
|
||
Expected: Success, no errors
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/core/src/index.ts
|
||
git commit -m "feat(core): export new types and parsers from core"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 8: Update Agent Prompts — Project Scanner
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/skills/understand/project-scanner-prompt.md`
|
||
|
||
**Step 1: Update the scanner to discover ALL file types**
|
||
|
||
Key changes to the prompt:
|
||
1. Remove the code-only file filter — scan `.md`, `.yaml`, `.json`, `.sql`, `.tf`, `Dockerfile`, etc.
|
||
2. Add a `fileCategory` field to each discovered file: `"code" | "config" | "docs" | "infra" | "data" | "script" | "markup"`
|
||
3. Update the exclusion list — still exclude `node_modules/`, `.git/`, binaries, but include non-code files
|
||
4. Add category detection logic in the discovery script:
|
||
- `.md`, `.rst`, `.txt` → `"docs"`
|
||
- `.yaml`, `.yml`, `.json`, `.toml`, `.env`, `.xml` → `"config"`
|
||
- `Dockerfile`, `docker-compose.*`, `.tf`, `.github/workflows/*`, `Makefile`, `Jenkinsfile` → `"infra"`
|
||
- `.sql`, `.graphql`, `.proto`, `.schema.json`, `.csv` → `"data"`
|
||
- `.sh`, `.bash`, `.ps1`, `.bat` → `"script"`
|
||
- `.html`, `.css`, `.scss` → `"markup"`
|
||
- Everything else → `"code"`
|
||
5. Update output schema to include `fileCategory` per file
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/skills/understand/project-scanner-prompt.md
|
||
git commit -m "feat(agents): update project-scanner to discover all file types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 9: Update Agent Prompts — File Analyzer
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/skills/understand/file-analyzer-prompt.md`
|
||
|
||
**Step 1: Add type-aware analysis prompts**
|
||
|
||
Key changes:
|
||
1. Add a section at the top explaining file categories and how to analyze each:
|
||
- **Code files** (current behavior): Extract functions, classes, imports, call graph
|
||
- **Config files**: Extract key settings, what they configure, which code they affect
|
||
- **Documentation files**: Extract sections/headings, key concepts, referenced code components
|
||
- **Infrastructure files**: Extract services, ports, volumes, deployments, which code they deploy
|
||
- **Data/Schema files**: Extract tables, columns, types, relationships, consuming code
|
||
- **Pipeline files**: Extract jobs, steps, triggers, deployed targets
|
||
|
||
2. Update the output JSON schema to include new fields:
|
||
- `sections` (for docs)
|
||
- `definitions` (for data/schema)
|
||
- `services` (for infra)
|
||
- `endpoints` (for API schemas)
|
||
- `steps` (for pipelines)
|
||
- `resources` (for IaC)
|
||
|
||
3. Add `nodeType` field to output: what GraphNode type each file should become (file, config, document, service, etc.)
|
||
|
||
4. Update edge generation guidance:
|
||
- Config files: generate `configures` edges to code files they affect
|
||
- Doc files: generate `documents` edges to described code
|
||
- Dockerfiles: generate `deploys` edges to code directories
|
||
- SQL migrations: generate `migrates` edges to tables
|
||
- CI configs: generate `triggers` edges to pipelines
|
||
- API schemas: generate `defines_schema` edges to endpoints
|
||
|
||
5. Update tagging guidance with new tags: `documentation`, `configuration`, `infrastructure`, `database`, `api-schema`, `ci-cd`, `deployment`, `migration`
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/skills/understand/file-analyzer-prompt.md
|
||
git commit -m "feat(agents): add type-aware analysis prompts for non-code files"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 10: Update Agent Prompts — Architecture Analyzer
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/skills/understand/architecture-analyzer-prompt.md`
|
||
|
||
**Step 1: Add non-code pattern detection**
|
||
|
||
Key changes:
|
||
1. Add new architectural patterns to detect:
|
||
- **Deployment topology**: Dockerfile → docker-compose → K8s manifests
|
||
- **Data pipeline**: Schema definition → migration → API endpoint → client code
|
||
- **Documentation coverage**: Which modules have corresponding docs
|
||
- **Configuration graph**: Which config files affect which code paths
|
||
2. Update layer hints to include non-code layers:
|
||
- `"infrastructure"` layer for Dockerfiles, K8s, Terraform
|
||
- `"documentation"` layer for docs
|
||
- `"data"` layer for SQL, schemas
|
||
- `"ci-cd"` layer for GitHub Actions, Jenkinsfiles
|
||
3. Update script to compute cross-category dependency analysis (code→infra, code→config, etc.)
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/skills/understand/architecture-analyzer-prompt.md
|
||
git commit -m "feat(agents): add non-code pattern detection to architecture analyzer"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 11: Update Agent Prompts — Tour Builder
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/skills/understand/tour-builder-prompt.md`
|
||
|
||
**Step 1: Add non-code tour stops**
|
||
|
||
Key changes:
|
||
1. Update tour step guidance to include non-code files:
|
||
- Step 1 could be README.md (project overview)
|
||
- Infrastructure stops: "How the app gets containerized"
|
||
- Data stops: "The database schema"
|
||
- CI/CD stops: "How code gets deployed"
|
||
2. Update `languageLesson` to also cover non-code concepts:
|
||
- Dockerfile: multi-stage builds, layer caching
|
||
- SQL: normalization, foreign keys
|
||
- YAML: anchors, merge keys
|
||
- Terraform: state management, modules
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/skills/understand/tour-builder-prompt.md
|
||
git commit -m "feat(agents): extend tour builder for non-code file stops"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 12: Update Agent Prompts — Graph Reviewer
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/skills/understand/graph-reviewer-prompt.md`
|
||
|
||
**Step 1: Update validation for new node/edge types**
|
||
|
||
Key changes:
|
||
1. Add new node types to the valid type list in the validation script
|
||
2. Add new edge types to the valid type list
|
||
3. Add quality checks for non-code nodes:
|
||
- Config nodes should have `configures` edges
|
||
- Document nodes should have `documents` edges
|
||
- Service nodes should have `deploys` edges
|
||
- Table nodes should reference columns
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/skills/understand/graph-reviewer-prompt.md
|
||
git commit -m "feat(agents): update graph reviewer for new node/edge types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 13: Add Language Context Snippets
|
||
|
||
**Files:**
|
||
- Create: `understand-anything-plugin/skills/understand/languages/markdown.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/yaml.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/json.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/sql.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/dockerfile.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/terraform.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/graphql.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/protobuf.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/shell.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/html.md`
|
||
- Create: `understand-anything-plugin/skills/understand/languages/css.md`
|
||
|
||
Each snippet follows the pattern of existing `typescript.md` / `python.md`:
|
||
|
||
```markdown
|
||
# Markdown
|
||
|
||
## Key Concepts
|
||
- Heading hierarchy (# through ######)
|
||
- Front matter (YAML metadata between --- delimiters)
|
||
- Code blocks (fenced with ``` or indented)
|
||
- Reference-style links
|
||
- Tables (pipe-delimited)
|
||
|
||
## Notable File Patterns
|
||
- `README.md` — Project overview (high-value entry point)
|
||
- `CONTRIBUTING.md` — Contribution guidelines
|
||
- `CHANGELOG.md` — Version history
|
||
- `docs/**/*.md` — Documentation directory
|
||
|
||
## Edge Patterns
|
||
- Markdown files `documents` the code components they describe
|
||
- Links to other .md files create `related` edges
|
||
- Code block references may imply `depends_on` edges
|
||
|
||
## Summary Style
|
||
> "Comprehensive guide document with N sections covering [topics]"
|
||
```
|
||
|
||
**Step 1: Create all 11 language snippets**
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/skills/understand/languages/
|
||
git commit -m "feat(agents): add language context snippets for 11 non-code file types"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 14: Update SKILL.md — Main Pipeline
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/skills/understand/SKILL.md`
|
||
|
||
**Step 1: Update the pipeline to handle non-code files**
|
||
|
||
Key changes:
|
||
1. **Phase 1 (SCAN)**: Update file batching to include non-code files. Add `fileCategory` to batch metadata.
|
||
2. **Phase 2 (ANALYZE)**: Update batch construction to group related non-code files together (e.g., Dockerfile + docker-compose.yml). Pass `fileCategory` to file-analyzer prompt.
|
||
3. **Phase 4 (ARCHITECTURE)**: Inject non-code language snippets for detected non-code languages.
|
||
4. **Phase 5 (TOUR)**: Include non-code nodes in tour candidate pool.
|
||
5. **Phase 7 (SAVE)**: No changes needed (schema handles new types).
|
||
6. **Node/Edge reference table**: Add the 8 new node types and 8 new edge types.
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/skills/understand/SKILL.md
|
||
git commit -m "feat(pipeline): update main skill pipeline for non-code file analysis"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 15: Dashboard — Add Node Type Colors to Theme Presets
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/dashboard/src/themes/presets.ts:1-143`
|
||
|
||
**Step 1: Add 8 new node type colors to all 5 presets**
|
||
|
||
Add these color entries to each preset's `colors` object:
|
||
|
||
For dark presets:
|
||
```typescript
|
||
"node-config": "#5eead4", // Teal
|
||
"node-document": "#7dd3fc", // Sky blue
|
||
"node-service": "#a78bfa", // Violet
|
||
"node-table": "#6ee7b7", // Emerald
|
||
"node-endpoint": "#fdba74", // Orange
|
||
"node-pipeline": "#fda4af", // Rose
|
||
"node-schema": "#fcd34d", // Amber
|
||
"node-resource": "#a5b4fc", // Indigo
|
||
```
|
||
|
||
For light preset, use slightly darker versions:
|
||
```typescript
|
||
"node-config": "#14b8a6",
|
||
"node-document": "#38bdf8",
|
||
"node-service": "#8b5cf6",
|
||
"node-table": "#34d399",
|
||
"node-endpoint": "#fb923c",
|
||
"node-pipeline": "#fb7185",
|
||
"node-schema": "#facc15",
|
||
"node-resource": "#818cf8",
|
||
```
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/dashboard/src/themes/presets.ts
|
||
git commit -m "feat(dashboard): add 8 new node type colors to all theme presets"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 16: Dashboard — Update CustomNode Component
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/dashboard/src/components/CustomNode.tsx:1-137`
|
||
|
||
**Step 1: Add new entries to typeColors and typeTextColors maps**
|
||
|
||
```typescript
|
||
const typeColors: Record<string, string> = {
|
||
file: "var(--color-node-file)",
|
||
function: "var(--color-node-function)",
|
||
class: "var(--color-node-class)",
|
||
module: "var(--color-node-module)",
|
||
concept: "var(--color-node-concept)",
|
||
config: "var(--color-node-config)",
|
||
document: "var(--color-node-document)",
|
||
service: "var(--color-node-service)",
|
||
table: "var(--color-node-table)",
|
||
endpoint: "var(--color-node-endpoint)",
|
||
pipeline: "var(--color-node-pipeline)",
|
||
schema: "var(--color-node-schema)",
|
||
resource: "var(--color-node-resource)",
|
||
};
|
||
|
||
const typeTextColors: Record<string, string> = {
|
||
file: "text-node-file",
|
||
function: "text-node-function",
|
||
class: "text-node-class",
|
||
module: "text-node-module",
|
||
concept: "text-node-concept",
|
||
config: "text-node-config",
|
||
document: "text-node-document",
|
||
service: "text-node-service",
|
||
table: "text-node-table",
|
||
endpoint: "text-node-endpoint",
|
||
pipeline: "text-node-pipeline",
|
||
schema: "text-node-schema",
|
||
resource: "text-node-resource",
|
||
};
|
||
```
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/dashboard/src/components/CustomNode.tsx
|
||
git commit -m "feat(dashboard): add new node type colors to CustomNode"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 17: Dashboard — Update NodeInfo Sidebar
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/dashboard/src/components/NodeInfo.tsx:1-312`
|
||
|
||
**Step 1: Add badge colors for new node types**
|
||
|
||
Add to `typeBadgeColors`:
|
||
```typescript
|
||
config: "text-node-config border border-node-config/30 bg-node-config/10",
|
||
document: "text-node-document border border-node-document/30 bg-node-document/10",
|
||
service: "text-node-service border border-node-service/30 bg-node-service/10",
|
||
table: "text-node-table border border-node-table/30 bg-node-table/10",
|
||
endpoint: "text-node-endpoint border border-node-endpoint/30 bg-node-endpoint/10",
|
||
pipeline: "text-node-pipeline border border-node-pipeline/30 bg-node-pipeline/10",
|
||
schema: "text-node-schema border border-node-schema/30 bg-node-schema/10",
|
||
resource: "text-node-resource border border-node-resource/30 bg-node-resource/10",
|
||
```
|
||
|
||
**Step 2: Add directional labels for new edge types**
|
||
|
||
Add to `getDirectionalLabel()`:
|
||
```typescript
|
||
case "deploys":
|
||
return isSource ? "deploys" : "deployed by";
|
||
case "serves":
|
||
return isSource ? "serves" : "served by";
|
||
case "migrates":
|
||
return isSource ? "migrates" : "migrated by";
|
||
case "documents":
|
||
return isSource ? "documents" : "documented by";
|
||
case "provisions":
|
||
return isSource ? "provisions" : "provisioned by";
|
||
case "routes":
|
||
return isSource ? "routes to" : "routed from";
|
||
case "defines_schema":
|
||
return isSource ? "defines schema for" : "schema defined by";
|
||
case "triggers":
|
||
return isSource ? "triggers" : "triggered by";
|
||
```
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/dashboard/src/components/NodeInfo.tsx
|
||
git commit -m "feat(dashboard): add new node/edge type support to NodeInfo sidebar"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 18: Dashboard — Update ProjectOverview with File Type Breakdown
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/dashboard/src/components/ProjectOverview.tsx`
|
||
|
||
**Step 1: Add file type distribution**
|
||
|
||
Add a "File Types" section after the stats grid that shows count per node type category:
|
||
- Code: file + function + class
|
||
- Config: config
|
||
- Docs: document
|
||
- Infra: service + resource + pipeline
|
||
- Data: table + endpoint + schema
|
||
|
||
Use colored dots matching the node type colors.
|
||
|
||
**Step 2: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/dashboard/src/components/ProjectOverview.tsx
|
||
git commit -m "feat(dashboard): add file type breakdown to ProjectOverview"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 19: Dashboard — Add Filter Controls
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/packages/dashboard/src/store.ts`
|
||
- Modify: `understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx`
|
||
- Modify: `understand-anything-plugin/packages/dashboard/src/App.tsx`
|
||
|
||
**Step 1: Add filter state to store**
|
||
|
||
Add to the Zustand store:
|
||
```typescript
|
||
nodeTypeFilters: Record<string, boolean>; // { code: true, config: true, docs: true, infra: true, data: true }
|
||
toggleNodeTypeFilter: (category: string) => void;
|
||
```
|
||
|
||
Default all categories to `true` (visible).
|
||
|
||
**Step 2: Apply filters in GraphView topology computation**
|
||
|
||
In `useLayerDetailTopology`, filter nodes based on `nodeTypeFilters` before layout.
|
||
|
||
**Step 3: Add filter checkboxes to App.tsx header**
|
||
|
||
Add small checkbox toggles next to the layer legend for each category.
|
||
|
||
**Step 4: Commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/packages/dashboard/src/store.ts understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx understand-anything-plugin/packages/dashboard/src/App.tsx
|
||
git commit -m "feat(dashboard): add node type category filter controls"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 20: Dashboard Build Verification
|
||
|
||
**Step 1: Build the dashboard**
|
||
|
||
Run: `pnpm --filter @understand-anything/dashboard build`
|
||
Expected: Success, no TypeScript errors
|
||
|
||
**Step 2: Build the core package**
|
||
|
||
Run: `pnpm --filter @understand-anything/core build`
|
||
Expected: Success
|
||
|
||
**Step 3: Run all core tests**
|
||
|
||
Run: `pnpm --filter @understand-anything/core test`
|
||
Expected: All tests pass
|
||
|
||
**Step 4: Run lint**
|
||
|
||
Run: `pnpm lint`
|
||
Expected: No errors
|
||
|
||
**Step 5: Commit any lint fixes**
|
||
|
||
```bash
|
||
git add -A
|
||
git commit -m "fix: lint and build fixes for universal file type support"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 21: Integration Test — End-to-End Verification
|
||
|
||
**Step 1: Dev server smoke test**
|
||
|
||
Run: `pnpm dev:dashboard`
|
||
- Load a knowledge graph that includes non-code nodes
|
||
- Verify new node types render with correct colors
|
||
- Verify NodeInfo sidebar shows new edge labels
|
||
- Verify filter controls work
|
||
|
||
**Step 2: Generate test graph with non-code nodes**
|
||
|
||
Update `scripts/generate-large-graph.mjs` to include non-code node types in the random generation, then generate a test graph and load it in the dashboard.
|
||
|
||
**Step 3: Commit**
|
||
|
||
```bash
|
||
git add scripts/generate-large-graph.mjs
|
||
git commit -m "feat(scripts): include non-code node types in test graph generator"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 22: Version Bump & Final Commit
|
||
|
||
**Files:**
|
||
- Modify: `understand-anything-plugin/package.json` → bump version
|
||
- Modify: `.claude-plugin/marketplace.json` → bump version
|
||
- Modify: `.claude-plugin/plugin.json` → bump version
|
||
- Modify: `.cursor-plugin/plugin.json` → bump version
|
||
|
||
**Step 1: Bump version in all 4 files** (e.g., 1.3.0 → 1.4.0)
|
||
|
||
**Step 2: Final commit**
|
||
|
||
```bash
|
||
git add understand-anything-plugin/package.json .claude-plugin/marketplace.json .claude-plugin/plugin.json .cursor-plugin/plugin.json
|
||
git commit -m "chore: bump version to 1.4.0 for universal file type support"
|
||
```
|
||
|
||
---
|
||
|
||
## Summary of All Tasks
|
||
|
||
| # | Task | Files | Depends On |
|
||
|---|------|-------|------------|
|
||
| 1 | Extend core types | types.ts | — |
|
||
| 2 | Extend schema validation | schema.ts | 1 |
|
||
| 3 | Update PluginRegistry | registry.ts | 1 |
|
||
| 4 | Add 26 language configs | languages/configs/ | 1 |
|
||
| 5 | Build 12 custom parsers | plugins/parsers/ | 1, 3 |
|
||
| 6 | Update GraphBuilder | graph-builder.ts | 1 |
|
||
| 7 | Update core exports | index.ts | 1-6 |
|
||
| 8 | Update project-scanner prompt | project-scanner-prompt.md | — |
|
||
| 9 | Update file-analyzer prompt | file-analyzer-prompt.md | — |
|
||
| 10 | Update architecture-analyzer prompt | architecture-analyzer-prompt.md | — |
|
||
| 11 | Update tour-builder prompt | tour-builder-prompt.md | — |
|
||
| 12 | Update graph-reviewer prompt | graph-reviewer-prompt.md | — |
|
||
| 13 | Add language context snippets | languages/*.md | — |
|
||
| 14 | Update SKILL.md pipeline | SKILL.md | 8-13 |
|
||
| 15 | Dashboard theme colors | presets.ts | — |
|
||
| 16 | Dashboard CustomNode | CustomNode.tsx | 15 |
|
||
| 17 | Dashboard NodeInfo | NodeInfo.tsx | 15 |
|
||
| 18 | Dashboard ProjectOverview | ProjectOverview.tsx | 15 |
|
||
| 19 | Dashboard filter controls | store.ts, GraphView.tsx, App.tsx | 15-18 |
|
||
| 20 | Build verification | — | 1-19 |
|
||
| 21 | Integration test | — | 20 |
|
||
| 22 | Version bump | package.json × 4 | 21 |
|
||
|
||
**Parallelizable groups:**
|
||
- Tasks 1-7 (core) are sequential
|
||
- Tasks 8-14 (agent prompts) can run in parallel with each other, and in parallel with Tasks 15-19 (dashboard)
|
||
- Tasks 20-22 are sequential and depend on all prior tasks
|