diff --git a/docs/superpowers/plans/2026-04-09-understand-knowledge.md b/docs/superpowers/plans/2026-04-09-understand-knowledge.md new file mode 100644 index 0000000..4c0635f --- /dev/null +++ b/docs/superpowers/plans/2026-04-09-understand-knowledge.md @@ -0,0 +1,1740 @@ +# /understand-knowledge Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add a `/understand-knowledge` skill that takes any folder of markdown notes (Obsidian, Logseq, Dendron, Foam, Karpathy-style, Zettelkasten, or plain) and produces an interactive knowledge graph with typed nodes, edges, and dashboard visualization. + +**Architecture:** Extends the existing schema with 5 knowledge node types and 6 knowledge edge types. A new 5-agent pipeline (knowledge-scanner → format-detector → article-analyzer → relationship-builder → graph-reviewer) processes markdown files. The dashboard renders knowledge graphs with vertical layout, a knowledge-specific sidebar, and a reading mode panel — all driven by a new `kind` field on the root graph object. + +**Tech Stack:** TypeScript, Zod (schema validation), React + ReactFlow (dashboard), dagre (layout), TailwindCSS v4, Vitest (testing) + +**Spec:** `docs/superpowers/specs/2026-04-09-understand-knowledge-design.md` + +--- + +## File Structure + +### Core package changes +- Modify: `understand-anything-plugin/packages/core/src/types.ts` — add 5 node types, 6 edge types, `KnowledgeMeta` interface, `kind` field +- Modify: `understand-anything-plugin/packages/core/src/schema.ts` — add new types to Zod schemas, add aliases +- Modify: `understand-anything-plugin/packages/core/src/types.test.ts` — add tests for new types +- Test: `understand-anything-plugin/packages/core/src/__tests__/knowledge-schema.test.ts` — validation tests for knowledge-specific schema + +### Dashboard changes +- Modify: `understand-anything-plugin/packages/dashboard/src/store.ts` — add knowledge node types, edge categories, `ViewMode`, node categories +- Modify: `understand-anything-plugin/packages/dashboard/src/components/CustomNode.tsx` — add colors for 5 new node types +- Modify: `understand-anything-plugin/packages/dashboard/src/components/NodeInfo.tsx` — add badge colors and edge labels for new types, add knowledge sidebar sections +- Modify: `understand-anything-plugin/packages/dashboard/src/components/ProjectOverview.tsx` — add knowledge-specific stats +- Modify: `understand-anything-plugin/packages/dashboard/src/index.css` — add CSS variables for 5 new node colors +- Modify: `understand-anything-plugin/packages/dashboard/src/App.tsx` — detect `kind` field, set view mode +- Create: `understand-anything-plugin/packages/dashboard/src/components/KnowledgeInfo.tsx` — knowledge-specific sidebar +- Create: `understand-anything-plugin/packages/dashboard/src/components/ReadingPanel.tsx` — full article reading overlay + +### Skill & agent definitions +- Create: `understand-anything-plugin/skills/understand-knowledge/SKILL.md` — skill entry point +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/obsidian.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/logseq.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/dendron.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/foam.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/karpathy.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/zettelkasten.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/plain.md` +- Create: `understand-anything-plugin/agents/knowledge-scanner.md` +- Create: `understand-anything-plugin/agents/format-detector.md` +- Create: `understand-anything-plugin/agents/article-analyzer.md` +- Create: `understand-anything-plugin/agents/relationship-builder.md` + +Existing `graph-reviewer.md` agent is reused for the final validation step. + +--- + +## Task 1: Extend Core Types + +**Files:** +- Modify: `understand-anything-plugin/packages/core/src/types.ts` + +- [ ] **Step 1: Add knowledge node types to NodeType union** + +In `understand-anything-plugin/packages/core/src/types.ts`, add the 5 knowledge types after the domain types: + +```typescript +// Node types (21 total: 5 code + 8 non-code + 3 domain + 5 knowledge) +export type NodeType = + | "file" | "function" | "class" | "module" | "concept" + | "config" | "document" | "service" | "table" | "endpoint" + | "pipeline" | "schema" | "resource" + | "domain" | "flow" | "step" + | "article" | "entity" | "topic" | "claim" | "source"; +``` + +- [ ] **Step 2: Add knowledge edge types to EdgeType union** + +```typescript +// Edge types (35 total in 8 categories) +export type 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" | "provisions" | "triggers" + | "migrates" | "documents" | "routes" | "defines_schema" + | "contains_flow" | "flow_step" | "cross_domain" + | "cites" | "contradicts" | "builds_on" | "exemplifies" | "categorized_under" | "authored_by"; +``` + +- [ ] **Step 3: Add KnowledgeMeta interface** + +Add after the `DomainMeta` interface: + +```typescript +// Optional knowledge metadata for article/entity/topic/claim/source nodes +export interface KnowledgeMeta { + format?: "obsidian" | "logseq" | "dendron" | "foam" | "karpathy" | "zettelkasten" | "plain"; + wikilinks?: string[]; + backlinks?: string[]; + frontmatter?: Record; + sourceUrl?: string; + confidence?: number; // 0-1, for LLM-inferred relationships +} +``` + +- [ ] **Step 4: Add knowledgeMeta to GraphNode** + +```typescript +export interface GraphNode { + id: string; + type: NodeType; + name: string; + filePath?: string; + lineRange?: [number, number]; + summary: string; + tags: string[]; + complexity: "simple" | "moderate" | "complex"; + languageNotes?: string; + domainMeta?: DomainMeta; + knowledgeMeta?: KnowledgeMeta; +} +``` + +- [ ] **Step 5: Add kind field to KnowledgeGraph** + +```typescript +export interface KnowledgeGraph { + version: string; + kind?: "codebase" | "knowledge"; // undefined defaults to "codebase" for backward compat + project: ProjectMeta; + nodes: GraphNode[]; + edges: GraphEdge[]; + layers: Layer[]; + tour: TourStep[]; +} +``` + +- [ ] **Step 6: Build core and verify no type errors** + +Run: `pnpm --filter @understand-anything/core build` +Expected: Clean build, no errors + +- [ ] **Step 7: Commit** + +```bash +git add understand-anything-plugin/packages/core/src/types.ts +git commit -m "feat(core): add knowledge node types, edge types, KnowledgeMeta, and graph kind field" +``` + +--- + +## Task 2: Extend Schema Validation + +**Files:** +- Modify: `understand-anything-plugin/packages/core/src/schema.ts` +- Create: `understand-anything-plugin/packages/core/src/__tests__/knowledge-schema.test.ts` + +- [ ] **Step 1: Add knowledge edge types to EdgeTypeSchema** + +In `understand-anything-plugin/packages/core/src/schema.ts`, update the `EdgeTypeSchema` z.enum to include the 6 new 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", "provisions", "triggers", + "migrates", "documents", "routes", "defines_schema", + "contains_flow", "flow_step", "cross_domain", + // Knowledge + "cites", "contradicts", "builds_on", "exemplifies", "categorized_under", "authored_by", +]); +``` + +- [ ] **Step 2: Add knowledge node type aliases** + +Add to `NODE_TYPE_ALIASES`: + +```typescript + // Knowledge aliases + note: "article", + page: "article", + wiki_page: "article", + person: "entity", + tool: "entity", + paper: "entity", + organization: "entity", + org: "entity", + category: "topic", + theme: "topic", + tag_topic: "topic", + assertion: "claim", + insight: "claim", + takeaway: "claim", + reference: "source", + raw: "source", + citation: "source", +``` + +- [ ] **Step 3: Add knowledge edge type aliases** + +Add to `EDGE_TYPE_ALIASES`: + +```typescript + // Knowledge aliases + references: "cites", + cited_by: "cites", + sourced_from: "cites", + conflicts_with: "contradicts", + disagrees_with: "contradicts", + extends: "builds_on", // Note: "extends" was already mapped to "inherits" — knowledge context will use builds_on via the relationship-builder agent prompt, so keep "extends" → "inherits" for code + refines: "builds_on", + deepens: "builds_on", + example_of: "exemplifies", + instance_of: "exemplifies", + belongs_to: "categorized_under", + tagged_with: "categorized_under", + part_of: "categorized_under", + written_by: "authored_by", + created_by: "authored_by", +``` + +- [ ] **Step 4: Write the failing test for knowledge graph validation** + +Create `understand-anything-plugin/packages/core/src/__tests__/knowledge-schema.test.ts`: + +```typescript +import { describe, it, expect } from "vitest"; +import { validateGraph } from "../schema"; +import type { KnowledgeGraph } from "../types"; + +describe("knowledge graph schema validation", () => { + const minimalKnowledgeGraph: KnowledgeGraph = { + version: "1.0", + kind: "knowledge", + project: { + name: "Test KB", + languages: [], + frameworks: [], + description: "A test knowledge base", + analyzedAt: new Date().toISOString(), + gitCommitHash: "abc123", + }, + nodes: [ + { + id: "article:test-note", + type: "article", + name: "Test Note", + summary: "A test article node", + tags: ["test"], + complexity: "simple", + }, + { + id: "entity:karpathy", + type: "entity", + name: "Andrej Karpathy", + summary: "AI researcher", + tags: ["person", "ai"], + complexity: "simple", + }, + { + id: "topic:pkm", + type: "topic", + name: "Personal Knowledge Management", + summary: "Tools and methods for managing personal knowledge", + tags: ["knowledge", "productivity"], + complexity: "moderate", + }, + ], + edges: [ + { + source: "article:test-note", + target: "entity:karpathy", + type: "authored_by", + direction: "forward", + weight: 0.8, + }, + { + source: "article:test-note", + target: "topic:pkm", + type: "categorized_under", + direction: "forward", + weight: 0.7, + }, + ], + layers: [ + { + id: "layer:pkm", + name: "PKM", + description: "Personal Knowledge Management topic cluster", + nodeIds: ["article:test-note", "topic:pkm"], + }, + ], + tour: [], + }; + + it("validates a minimal knowledge graph", () => { + const result = validateGraph(minimalKnowledgeGraph); + const fatals = result.issues.filter((i) => i.level === "fatal"); + expect(fatals).toHaveLength(0); + }); + + it("accepts all knowledge node types", () => { + const graph = { + ...minimalKnowledgeGraph, + nodes: [ + ...minimalKnowledgeGraph.nodes, + { id: "claim:rag-bad", type: "claim", name: "RAG loses context", summary: "An assertion", tags: ["claim"], complexity: "simple" }, + { id: "source:paper1", type: "source", name: "Attention paper", summary: "A source", tags: ["paper"], complexity: "simple" }, + ], + }; + const result = validateGraph(graph); + const fatals = result.issues.filter((i) => i.level === "fatal"); + expect(fatals).toHaveLength(0); + }); + + it("accepts all knowledge edge types", () => { + const graph = { + ...minimalKnowledgeGraph, + nodes: [ + ...minimalKnowledgeGraph.nodes, + { id: "claim:c1", type: "claim", name: "Claim 1", summary: "c1", tags: [], complexity: "simple" }, + { id: "claim:c2", type: "claim", name: "Claim 2", summary: "c2", tags: [], complexity: "simple" }, + { id: "source:s1", type: "source", name: "Source 1", summary: "s1", tags: [], complexity: "simple" }, + { id: "article:a2", type: "article", name: "Article 2", summary: "a2", tags: [], complexity: "simple" }, + ], + edges: [ + ...minimalKnowledgeGraph.edges, + { source: "article:test-note", target: "source:s1", type: "cites", direction: "forward", weight: 0.7 }, + { source: "claim:c1", target: "claim:c2", type: "contradicts", direction: "forward", weight: 0.6 }, + { source: "article:a2", target: "article:test-note", type: "builds_on", direction: "forward", weight: 0.7 }, + { source: "entity:karpathy", target: "topic:pkm", type: "exemplifies", direction: "forward", weight: 0.5 }, + ], + }; + const result = validateGraph(graph); + const fatals = result.issues.filter((i) => i.level === "fatal"); + expect(fatals).toHaveLength(0); + }); + + it("resolves knowledge node type aliases", () => { + const graph = { + ...minimalKnowledgeGraph, + nodes: [ + { id: "note:n1", type: "note", name: "A Note", summary: "note alias", tags: [], complexity: "simple" }, + { id: "person:p1", type: "person", name: "A Person", summary: "person alias", tags: [], complexity: "simple" }, + ], + edges: [], + layers: [], + }; + const result = validateGraph(graph); + const noteNode = result.graph.nodes.find((n) => n.id === "note:n1"); + const personNode = result.graph.nodes.find((n) => n.id === "person:p1"); + expect(noteNode?.type).toBe("article"); + expect(personNode?.type).toBe("entity"); + }); + + it("resolves knowledge edge type aliases", () => { + const graph = { + ...minimalKnowledgeGraph, + edges: [ + { source: "article:test-note", target: "entity:karpathy", type: "written_by", direction: "forward", weight: 0.8 }, + ], + }; + const result = validateGraph(graph); + const edge = result.graph.edges.find((e) => e.source === "article:test-note" && e.target === "entity:karpathy"); + expect(edge?.type).toBe("authored_by"); + }); +}); +``` + +- [ ] **Step 5: Run tests to verify they fail** + +Run: `pnpm --filter @understand-anything/core test -- --run src/__tests__/knowledge-schema.test.ts` +Expected: Tests fail because EdgeTypeSchema doesn't include knowledge types yet (if schema.ts wasn't updated), or pass if Steps 1-3 were done correctly. + +- [ ] **Step 6: Run all core tests to verify nothing is broken** + +Run: `pnpm --filter @understand-anything/core test -- --run` +Expected: All existing tests pass, new knowledge tests pass + +- [ ] **Step 7: Commit** + +```bash +git add understand-anything-plugin/packages/core/src/schema.ts understand-anything-plugin/packages/core/src/__tests__/knowledge-schema.test.ts +git commit -m "feat(core): add knowledge types to schema validation with aliases and tests" +``` + +--- + +## Task 3: Dashboard — CSS Variables & Node Colors + +**Files:** +- Modify: `understand-anything-plugin/packages/dashboard/src/index.css` + +- [ ] **Step 1: Add CSS variables for 5 knowledge node types** + +In `understand-anything-plugin/packages/dashboard/src/index.css`, add after the existing `--color-node-resource` line: + +```css + /* Knowledge node colors */ + --color-node-article: #d4a574; /* warm amber */ + --color-node-entity: #7ba4c9; /* soft blue */ + --color-node-topic: #c9b06c; /* muted gold */ + --color-node-claim: #6fb07a; /* soft green */ + --color-node-source: #8a8a8a; /* gray */ +``` + +- [ ] **Step 2: Add Tailwind text-color utilities for knowledge nodes** + +Verify TailwindCSS v4 picks up the CSS variables automatically. If the existing pattern uses `text-node-*` classes defined elsewhere, add matching entries. Check if there's a Tailwind config or if the CSS variables are consumed directly. + +Look at how existing `text-node-file` etc. are defined — if they're in the CSS file as utility classes, add: + +```css + .text-node-article { color: var(--color-node-article); } + .text-node-entity { color: var(--color-node-entity); } + .text-node-topic { color: var(--color-node-topic); } + .text-node-claim { color: var(--color-node-claim); } + .text-node-source { color: var(--color-node-source); } +``` + +And corresponding `border-node-*` and `bg-node-*` variants if the pattern requires them. + +- [ ] **Step 3: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/index.css +git commit -m "feat(dashboard): add CSS variables and utility classes for knowledge node types" +``` + +--- + +## Task 4: Dashboard — Store & Type Maps + +**Files:** +- Modify: `understand-anything-plugin/packages/dashboard/src/store.ts` + +- [ ] **Step 1: Add knowledge types to NodeType union** + +Update the local `NodeType` in store.ts: + +```typescript +export type NodeType = "file" | "function" | "class" | "module" | "concept" | "config" | "document" | "service" | "table" | "endpoint" | "pipeline" | "schema" | "resource" | "domain" | "flow" | "step" | "article" | "entity" | "topic" | "claim" | "source"; +``` + +- [ ] **Step 2: Add knowledge edge category** + +Update `EdgeCategory` and `EDGE_CATEGORY_MAP`: + +```typescript +export type EdgeCategory = "structural" | "behavioral" | "data-flow" | "dependencies" | "semantic" | "infrastructure" | "domain" | "knowledge"; + +export const EDGE_CATEGORY_MAP: Record = { + structural: ["imports", "exports", "contains", "inherits", "implements"], + behavioral: ["calls", "subscribes", "publishes", "middleware"], + "data-flow": ["reads_from", "writes_to", "transforms", "validates"], + dependencies: ["depends_on", "tested_by", "configures"], + semantic: ["related", "similar_to"], + infrastructure: ["deploys", "serves", "provisions", "triggers"], + domain: ["contains_flow", "flow_step", "cross_domain"], + knowledge: ["cites", "contradicts", "builds_on", "exemplifies", "categorized_under", "authored_by"], +}; +``` + +- [ ] **Step 3: Add knowledge to ALL_NODE_TYPES and ALL_EDGE_CATEGORIES** + +```typescript +export const ALL_NODE_TYPES: NodeType[] = ["file", "function", "class", "module", "concept", "config", "document", "service", "table", "endpoint", "pipeline", "schema", "resource", "domain", "flow", "step", "article", "entity", "topic", "claim", "source"]; + +export const ALL_EDGE_CATEGORIES: EdgeCategory[] = ["structural", "behavioral", "data-flow", "dependencies", "semantic", "infrastructure", "domain", "knowledge"]; +``` + +- [ ] **Step 4: Add "knowledge" to ViewMode and NodeCategory** + +```typescript +export type ViewMode = "structural" | "domain" | "knowledge"; + +export type NodeCategory = "code" | "config" | "docs" | "infra" | "data" | "domain" | "knowledge"; +``` + +Update the `NODE_CATEGORY_MAP` (find where it maps node types to categories) to include: + +```typescript + article: "knowledge", + entity: "knowledge", + topic: "knowledge", + claim: "knowledge", + source: "knowledge", +``` + +- [ ] **Step 5: Add knowledge node type filter default** + +In the store's initial state `nodeTypeFilters`, add: + +```typescript +nodeTypeFilters: { code: true, config: true, docs: true, infra: true, data: true, domain: true, knowledge: true }, +``` + +- [ ] **Step 6: Build dashboard and verify no errors** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build + +- [ ] **Step 7: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/store.ts +git commit -m "feat(dashboard): add knowledge types to store, edge categories, and view mode" +``` + +--- + +## Task 5: Dashboard — CustomNode & NodeInfo Type Maps + +**Files:** +- Modify: `understand-anything-plugin/packages/dashboard/src/components/CustomNode.tsx` +- Modify: `understand-anything-plugin/packages/dashboard/src/components/NodeInfo.tsx` + +- [ ] **Step 1: Add knowledge node colors to CustomNode.tsx** + +In `typeColors` map, add after the `step` entry: + +```typescript + // Knowledge + article: "var(--color-node-article)", + entity: "var(--color-node-entity)", + topic: "var(--color-node-topic)", + claim: "var(--color-node-claim)", + source: "var(--color-node-source)", +``` + +In `typeTextColors` map, add: + +```typescript + // Knowledge + article: "text-node-article", + entity: "text-node-entity", + topic: "text-node-topic", + claim: "text-node-claim", + source: "text-node-source", +``` + +- [ ] **Step 2: Add knowledge node badge colors to NodeInfo.tsx** + +In `typeBadgeColors` map, add: + +```typescript + // Knowledge + article: "text-node-article border border-node-article/30 bg-node-article/10", + entity: "text-node-entity border border-node-entity/30 bg-node-entity/10", + topic: "text-node-topic border border-node-topic/30 bg-node-topic/10", + claim: "text-node-claim border border-node-claim/30 bg-node-claim/10", + source: "text-node-source border border-node-source/30 bg-node-source/10", +``` + +- [ ] **Step 3: Add knowledge edge labels to NodeInfo.tsx** + +In `EDGE_LABELS` map, add: + +```typescript + // Knowledge + cites: { forward: "cites", backward: "cited by" }, + contradicts: { forward: "contradicts", backward: "contradicted by" }, + builds_on: { forward: "builds on", backward: "built upon by" }, + exemplifies: { forward: "exemplifies", backward: "exemplified by" }, + categorized_under: { forward: "categorized under", backward: "categorizes" }, + authored_by: { forward: "authored by", backward: "authored" }, +``` + +- [ ] **Step 4: Build dashboard and verify** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build, no type errors + +- [ ] **Step 5: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/components/CustomNode.tsx understand-anything-plugin/packages/dashboard/src/components/NodeInfo.tsx +git commit -m "feat(dashboard): add knowledge node colors, badge colors, and edge labels" +``` + +--- + +## Task 6: Dashboard — Knowledge Sidebar Component + +**Files:** +- Create: `understand-anything-plugin/packages/dashboard/src/components/KnowledgeInfo.tsx` +- Modify: `understand-anything-plugin/packages/dashboard/src/App.tsx` + +- [ ] **Step 1: Create KnowledgeInfo.tsx** + +Create `understand-anything-plugin/packages/dashboard/src/components/KnowledgeInfo.tsx`: + +```tsx +import { useDashboardStore } from "../store"; +import type { GraphNode, GraphEdge, KnowledgeGraph } from "@understand-anything/core/types"; + +const KNOWLEDGE_NODE_TYPES = new Set(["article", "entity", "topic", "claim", "source"]); + +function getBacklinks(nodeId: string, edges: GraphEdge[]): string[] { + return edges + .filter((e) => e.target === nodeId) + .map((e) => e.source); +} + +function getOutgoingLinks(nodeId: string, edges: GraphEdge[]): string[] { + return edges + .filter((e) => e.source === nodeId) + .map((e) => e.target); +} + +function NodeLink({ nodeId, nodes, onNavigate }: { nodeId: string; nodes: GraphNode[]; onNavigate: (id: string) => void }) { + const node = nodes.find((n) => n.id === nodeId); + if (!node) return {nodeId}; + return ( + + ); +} + +export default function KnowledgeInfo() { + const graph = useDashboardStore((s) => s.graph); + const selectedNode = useDashboardStore((s) => s.selectedNode); + const setSelectedNode = useDashboardStore((s) => s.setSelectedNode); + + if (!graph || !selectedNode) return null; + + const node = graph.nodes.find((n) => n.id === selectedNode); + if (!node) return null; + + const backlinks = getBacklinks(node.id, graph.edges); + const outgoing = getOutgoingLinks(node.id, graph.edges); + const meta = node.knowledgeMeta; + + return ( +
+ {/* Header */} +
+
{node.type}
+

{node.name}

+
+ + {/* Summary */} +

{node.summary}

+ + {/* Tags */} + {node.tags.length > 0 && ( +
+ {node.tags.map((tag) => ( + + {tag} + + ))} +
+ )} + + {/* Knowledge-specific metadata */} + {meta?.sourceUrl && ( +
+
Source
+ {meta.sourceUrl} +
+ )} + + {meta?.confidence !== undefined && ( +
+
Confidence
+
+
+
+
+ {Math.round(meta.confidence * 100)}% +
+
+ )} + + {/* Frontmatter */} + {meta?.frontmatter && Object.keys(meta.frontmatter).length > 0 && ( +
+
Frontmatter
+
+ {Object.entries(meta.frontmatter).map(([key, value]) => ( +
+ {key}:{" "} + {String(value)} +
+ ))} +
+
+ )} + + {/* Backlinks */} + {backlinks.length > 0 && ( +
+
+ Backlinks ({backlinks.length}) +
+
+ {backlinks.map((id) => ( + + ))} +
+
+ )} + + {/* Outgoing */} + {outgoing.length > 0 && ( +
+
+ Outgoing Links ({outgoing.length}) +
+
+ {outgoing.map((id) => ( + + ))} +
+
+ )} +
+ ); +} +``` + +- [ ] **Step 2: Integrate KnowledgeInfo into App.tsx sidebar rendering** + +In `understand-anything-plugin/packages/dashboard/src/App.tsx`, find where the sidebar renders `NodeInfo` and add a condition: if `graph.kind === "knowledge"` and a node is selected, render `KnowledgeInfo` instead of `NodeInfo`. + +Import at top: +```typescript +import KnowledgeInfo from "./components/KnowledgeInfo"; +``` + +In the sidebar section, wrap the existing NodeInfo render: +```tsx +{graph?.kind === "knowledge" ? : } +``` + +- [ ] **Step 3: Build dashboard and verify** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build + +- [ ] **Step 4: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/components/KnowledgeInfo.tsx understand-anything-plugin/packages/dashboard/src/App.tsx +git commit -m "feat(dashboard): add KnowledgeInfo sidebar component for knowledge graphs" +``` + +--- + +## Task 7: Dashboard — Reading Panel + +**Files:** +- Create: `understand-anything-plugin/packages/dashboard/src/components/ReadingPanel.tsx` +- Modify: `understand-anything-plugin/packages/dashboard/src/App.tsx` + +- [ ] **Step 1: Create ReadingPanel.tsx** + +Create `understand-anything-plugin/packages/dashboard/src/components/ReadingPanel.tsx`: + +```tsx +import { useState } from "react"; +import { useDashboardStore } from "../store"; + +export default function ReadingPanel() { + const graph = useDashboardStore((s) => s.graph); + const selectedNode = useDashboardStore((s) => s.selectedNode); + const setSelectedNode = useDashboardStore((s) => s.setSelectedNode); + const [isExpanded, setIsExpanded] = useState(false); + + if (!graph || graph.kind !== "knowledge" || !selectedNode) return null; + + const node = graph.nodes.find((n) => n.id === selectedNode); + if (!node || node.type !== "article") return null; + + // Get backlinks for this article + const backlinks = graph.edges + .filter((e) => e.target === node.id) + .map((e) => { + const sourceNode = graph.nodes.find((n) => n.id === e.source); + return sourceNode ? { id: sourceNode.id, name: sourceNode.name, type: sourceNode.type } : null; + }) + .filter(Boolean) as { id: string; name: string; type: string }[]; + + return ( +
+ {/* Header bar */} +
+
+ Reading + {node.name} +
+
+ + +
+
+ +
+ {/* Main content */} +
+
+

{node.name}

+ + {/* Tags */} + {node.tags.length > 0 && ( +
+ {node.tags.map((tag) => ( + + {tag} + + ))} +
+ )} + + {/* Article content (summary for now — full markdown rendering is a future enhancement) */} +
+

{node.summary}

+
+ + {/* Frontmatter metadata */} + {node.knowledgeMeta?.frontmatter && Object.keys(node.knowledgeMeta.frontmatter).length > 0 && ( +
+
Metadata
+ {Object.entries(node.knowledgeMeta.frontmatter).map(([key, value]) => ( +
+ {key}:{" "} + {String(value)} +
+ ))} +
+ )} +
+
+ + {/* Backlinks sidebar */} + {backlinks.length > 0 && ( +
+
+ Backlinks ({backlinks.length}) +
+
+ {backlinks.map((link) => ( + + ))} +
+
+ )} +
+
+ ); +} +``` + +- [ ] **Step 2: Add ReadingPanel to App.tsx** + +Import and render `ReadingPanel` in the main dashboard layout, positioned at the bottom: + +```typescript +import ReadingPanel from "./components/ReadingPanel"; +``` + +Add `` inside the dashboard container, after the graph view area. + +- [ ] **Step 3: Build and verify** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build + +- [ ] **Step 4: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/components/ReadingPanel.tsx understand-anything-plugin/packages/dashboard/src/App.tsx +git commit -m "feat(dashboard): add ReadingPanel for article reading mode in knowledge graphs" +``` + +--- + +## Task 8: Dashboard — Vertical Layout for Knowledge Graphs + +**Files:** +- Modify: `understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx` +- Modify: `understand-anything-plugin/packages/dashboard/src/utils/layout.ts` (if direction isn't already configurable) + +- [ ] **Step 1: Check how layout direction is passed to dagre** + +Read `GraphView.tsx` to find where `applyDagreLayout` is called. The layout.ts `applyDagreLayout` already accepts a `direction: "TB" | "LR"` parameter (default `"TB"`). + +Find where GraphView calls this function and check what direction it passes. + +- [ ] **Step 2: Pass graph kind to layout decision** + +In `GraphView.tsx`, where the layout is applied, check the graph's `kind` field. If `kind === "knowledge"`, use `"TB"` (top-to-bottom). If `kind === "codebase"` or undefined, keep the existing default. + +The graph object is available via the store. Add: + +```typescript +const graphKind = useDashboardStore((s) => s.graph?.kind); +const layoutDirection = graphKind === "knowledge" ? "TB" : "LR"; +``` + +Pass `layoutDirection` to the layout call. + +- [ ] **Step 3: Build and verify** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build + +- [ ] **Step 4: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx +git commit -m "feat(dashboard): use vertical top-down layout for knowledge graphs" +``` + +--- + +## Task 9: Dashboard — Knowledge Edge Styling + +**Files:** +- Modify: `understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx` + +- [ ] **Step 1: Add knowledge edge style map** + +In `GraphView.tsx`, add a style map for knowledge edge types. Follow the existing pattern from `DomainGraphView.tsx` which uses ReactFlow's `style` prop: + +```typescript +const KNOWLEDGE_EDGE_STYLES: Record = { + cites: { strokeDasharray: "6 3", strokeWidth: 1.5 }, + contradicts: { stroke: "#c97070", strokeWidth: 2 }, + builds_on: { stroke: "var(--color-accent)", strokeWidth: 2 }, + categorized_under: { stroke: "rgba(150,150,150,0.5)", strokeWidth: 1 }, + authored_by: { strokeDasharray: "3 3", stroke: "var(--color-node-entity)", strokeWidth: 1.5 }, + exemplifies: { strokeDasharray: "3 3", stroke: "var(--color-node-claim)", strokeWidth: 1.5 }, +}; +``` + +- [ ] **Step 2: Apply styles when building ReactFlow edges** + +Where edges are converted to ReactFlow format, check if the graph is `kind === "knowledge"` and the edge type has a knowledge style. Merge the style: + +```typescript +const knowledgeStyle = graph?.kind === "knowledge" ? KNOWLEDGE_EDGE_STYLES[edge.type] : undefined; +// Merge with existing edge style +const style = { ...baseEdgeStyle, ...knowledgeStyle }; +``` + +- [ ] **Step 3: Build and verify** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build + +- [ ] **Step 4: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/components/GraphView.tsx +git commit -m "feat(dashboard): add distinct edge styles for knowledge relationship types" +``` + +--- + +## Task 10: Dashboard — Knowledge-Aware ProjectOverview + +**Files:** +- Modify: `understand-anything-plugin/packages/dashboard/src/components/ProjectOverview.tsx` + +- [ ] **Step 1: Add knowledge-specific stats** + +In `ProjectOverview.tsx`, detect `graph.kind === "knowledge"` and show knowledge-specific stats: + +- Total articles, entities, topics, claims, sources (instead of "code, config, docs, infra, data") +- Detected format (from the first node's `knowledgeMeta.format`) +- Remove "Languages" and "Frameworks" sections for knowledge graphs (they'll be empty) + +Add after the existing stats grid: + +```tsx +{graph.kind === "knowledge" && ( +
+
Knowledge Stats
+
+ n.type === "article").length} /> + n.type === "entity").length} /> + n.type === "topic").length} /> + n.type === "claim").length} /> + n.type === "source").length} /> +
+
+)} +``` + +Reuse or create a `StatBox` component matching the existing style. + +- [ ] **Step 2: Conditionally hide code-specific sections** + +Wrap the "Languages", "Frameworks", and code-specific file type breakdown sections in a condition: + +```tsx +{graph.kind !== "knowledge" && ( + <> + {/* existing languages/frameworks/file-types sections */} + +)} +``` + +- [ ] **Step 3: Build and verify** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build + +- [ ] **Step 4: Commit** + +```bash +git add understand-anything-plugin/packages/dashboard/src/components/ProjectOverview.tsx +git commit -m "feat(dashboard): add knowledge-specific stats to ProjectOverview" +``` + +--- + +## Task 11: Create Agent Definitions + +**Files:** +- Create: `understand-anything-plugin/agents/knowledge-scanner.md` +- Create: `understand-anything-plugin/agents/format-detector.md` +- Create: `understand-anything-plugin/agents/article-analyzer.md` +- Create: `understand-anything-plugin/agents/relationship-builder.md` + +- [ ] **Step 1: Create knowledge-scanner agent** + +Create `understand-anything-plugin/agents/knowledge-scanner.md`: + +```markdown +--- +name: knowledge-scanner +description: Scans a directory for markdown files and produces a file manifest for knowledge base analysis +model: inherit +--- + +# Knowledge Scanner Agent + +You scan a target directory to discover all markdown files for knowledge base analysis. + +## Input + +You receive a JSON block with: +- `targetDir` — absolute path to the knowledge base directory + +## Task + +1. Use Glob/Bash to find all `.md` files in the target directory (recursive) +2. Exclude common non-content directories: `.obsidian/`, `logseq/`, `.foam/`, `_meta/`, `node_modules/`, `.git/` +3. For each file, capture: + - `path` — relative path from targetDir + - `sizeLines` — number of lines + - `preview` — first 20 lines of content +4. Detect directory structure signatures: + - Check for `.obsidian/` directory + - Check for `logseq/` + `pages/` directories + - Check for `.dendron.yml` or `*.schema.yml` + - Check for `.foam/` or `.vscode/foam.json` + - Check for `raw/` + `wiki/` + `index.md` + - Scan a sample of files for `[[wikilinks]]` and unique ID prefixes +5. Write results to `$PROJECT_ROOT/.understand-anything/intermediate/knowledge-manifest.json` + +## Output Schema + +```json +{ + "targetDir": "/absolute/path", + "totalFiles": 342, + "directorySignatures": { + "hasObsidianDir": true, + "hasLogseqDir": false, + "hasDendronConfig": false, + "hasFoamConfig": false, + "hasKarpathyStructure": false, + "hasWikilinks": true, + "hasUniqueIdPrefixes": false + }, + "files": [ + { + "path": "notes/topic.md", + "sizeLines": 45, + "preview": "---\ntags: [ai, ml]\n---\n# Topic Name\n..." + } + ] +} +``` + +## Rules + +- Do NOT read file contents beyond the 20-line preview +- Sort files by path alphabetically +- Report total count prominently +- Write output to `.understand-anything/intermediate/knowledge-manifest.json` +``` + +- [ ] **Step 2: Create format-detector agent** + +Create `understand-anything-plugin/agents/format-detector.md`: + +```markdown +--- +name: format-detector +description: Detects the knowledge base format from directory signatures and file samples +model: inherit +--- + +# Format Detector Agent + +You analyze the knowledge-manifest.json to determine which knowledge base format is being used. + +## Input + +Read `.understand-anything/intermediate/knowledge-manifest.json` produced by the knowledge-scanner. + +## Detection Priority + +Apply these rules in order (first match wins): + +| Priority | Signal | Format | +|----------|--------|--------| +| 1 | `hasObsidianDir === true` | `obsidian` | +| 2 | `hasLogseqDir === true` | `logseq` | +| 3 | `hasDendronConfig === true` | `dendron` | +| 4 | `hasFoamConfig === true` | `foam` | +| 5 | `hasKarpathyStructure === true` | `karpathy` | +| 6 | `hasWikilinks === true` AND `hasUniqueIdPrefixes === true` | `zettelkasten` | +| 7 | fallback | `plain` | + +## Output + +Write to `.understand-anything/intermediate/format-detection.json`: + +```json +{ + "format": "obsidian", + "confidence": 0.95, + "parsingHints": { + "linkStyle": "wikilink", + "metadataLocation": "yaml-frontmatter", + "folderSemantics": "none", + "specialFiles": [".obsidian/app.json"], + "tagSyntax": "hashtag-inline" + } +} +``` + +## Rules + +- Always produce exactly one format +- Set confidence based on how many signals matched +- Include parsing hints that will help the article-analyzer +``` + +- [ ] **Step 3: Create article-analyzer agent** + +Create `understand-anything-plugin/agents/article-analyzer.md`: + +```markdown +--- +name: article-analyzer +description: Analyzes individual markdown files to extract knowledge nodes and explicit edges +model: inherit +--- + +# Article Analyzer Agent + +You analyze batches of markdown files from a knowledge base to extract structured knowledge graph data. + +## Input + +You receive a JSON block with: +- `projectRoot` — absolute path to the knowledge base +- `batchFiles` — array of file objects from the manifest (path, sizeLines, preview) +- `format` — detected format from format-detection.json +- `parsingHints` — format-specific parsing guidance + +You also receive a **format guide** (injected by the skill) that describes how to parse this specific format. + +## Task + +For each file in the batch: + +### 1. Read the full file content + +### 2. Extract the article node + +- **id**: `article:` (e.g., `article:notes/topic`) +- **type**: `article` +- **name**: First heading, or frontmatter title, or filename +- **filePath**: relative path +- **summary**: 2-3 sentence summary of the article content +- **tags**: from frontmatter tags, inline #tags, or inferred from content (3-5 tags) +- **complexity**: `simple` (<50 lines), `moderate` (50-200 lines), `complex` (>200 lines) +- **knowledgeMeta**: `{ format, wikilinks, frontmatter }` + +### 3. Extract entity nodes + +Identify named entities mentioned in the article: +- People, organizations, tools, papers, projects, datasets +- **id**: `entity:` (e.g., `entity:andrej-karpathy`) +- **type**: `entity` +- **summary**: one-sentence description based on context in the article +- **tags**: entity category tags like `person`, `tool`, `paper`, `organization` + +### 4. Extract claim nodes (for articles with strong assertions) + +- Only extract claims that are significant takeaways or insights +- **id**: `claim::` (e.g., `claim:notes/topic:rag-loses-context`) +- **type**: `claim` +- **summary**: the assertion itself + +### 5. Extract source nodes (for cited references) + +- External URLs, paper references, book citations +- **id**: `source:` +- **type**: `source` +- **knowledgeMeta**: `{ sourceUrl }` + +### 6. Extract explicit edges + +- `[[wikilinks]]` → find target article, create `related` edge +- Frontmatter references → `categorized_under` or `related` edges +- Inline citations/URLs → `cites` edges to source nodes +- Author mentions → `authored_by` edges + +## Node ID Conventions + +``` +article: +entity: +topic: +claim:: +source: +``` + +Normalize: lowercase, replace spaces with hyphens, remove special characters. + +**Deduplicate entities**: If the same entity appears across multiple files in the batch, emit it only once. Use the most informative summary. + +## Edge Weight Conventions + +``` +contains: 1.0 +authored_by: 0.9 +cites: 0.8 +categorized_under: 0.7 +builds_on: 0.7 +related: 0.5 +exemplifies: 0.5 +contradicts: 0.6 +``` + +## Output + +Write per-batch results to `.understand-anything/intermediate/article-batch-.json`: + +```json +{ + "nodes": [...], + "edges": [...] +} +``` + +## Rules + +- One article node per file (always) +- Entity nodes only for clearly named entities (not generic concepts) +- Claim nodes only for significant assertions (not every sentence) +- Source nodes only for explicit external references +- Deduplicate entities within the batch +- Respect the format guide for parsing links and metadata +``` + +- [ ] **Step 4: Create relationship-builder agent** + +Create `understand-anything-plugin/agents/relationship-builder.md`: + +```markdown +--- +name: relationship-builder +description: Discovers implicit cross-file relationships and builds topic clusters from analyzed knowledge nodes +model: inherit +--- + +# Relationship Builder Agent + +You analyze all extracted nodes and edges to discover implicit relationships that explicit links missed. + +## Input + +Read all `article-batch-*.json` files from `.understand-anything/intermediate/`. Merge all nodes and edges. + +## Task + +### 1. Deduplicate entities globally + +Multiple batches may have emitted the same entity. Merge them: +- Keep the most detailed summary +- Union all tags +- Collapse duplicate IDs + +### 2. Discover implicit relationships + +For each pair of articles/entities, determine if there's an implicit relationship: + +- **builds_on**: Article A extends or deepens ideas from Article B (similar topics, references same entities, but goes further) +- **contradicts**: Article A makes claims that conflict with Article B +- **categorized_under**: Group articles into topic clusters +- **exemplifies**: An entity is a concrete example of a concept/topic +- **related**: Articles share significant thematic overlap but aren't explicitly linked + +Set `confidence` in knowledgeMeta for LLM-inferred edges (0.0-1.0). + +### 3. Build topic nodes + +Identify thematic clusters across all articles: +- **id**: `topic:` +- **type**: `topic` +- **summary**: description of what this topic covers +- Create `categorized_under` edges from articles/entities to their topics + +### 4. Build layers + +Group nodes into layers by topic: +- Each topic becomes a layer +- Articles, entities, claims, and sources are assigned to their primary topic's layer +- Nodes not clearly belonging to any topic go into an "Uncategorized" layer + +### 5. Build tour + +Create a guided tour through the knowledge base: +- Start with the broadest topic overview +- Walk through key articles in a logical learning order +- Each step covers 1-3 related nodes +- 5-10 tour steps total + +## Output + +Write to `.understand-anything/intermediate/relationships.json`: + +```json +{ + "nodes": [...], + "edges": [...], + "layers": [...], + "tour": [...] +} +``` + +## Rules + +- Only add edges with confidence > 0.4 +- Don't duplicate edges that already exist from article-analyzer +- Topics should be meaningful clusters (3+ articles), not one-off categories +- Tour should be navigable by someone new to the knowledge base +- Keep layers balanced — no layer with 50%+ of all nodes +``` + +- [ ] **Step 5: Commit** + +```bash +git add understand-anything-plugin/agents/knowledge-scanner.md understand-anything-plugin/agents/format-detector.md understand-anything-plugin/agents/article-analyzer.md understand-anything-plugin/agents/relationship-builder.md +git commit -m "feat(agents): add knowledge-scanner, format-detector, article-analyzer, and relationship-builder agents" +``` + +--- + +## Task 12: Create Format Guides + +**Files:** +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/obsidian.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/logseq.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/dendron.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/foam.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/karpathy.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/zettelkasten.md` +- Create: `understand-anything-plugin/skills/understand-knowledge/formats/plain.md` + +**IMPORTANT**: Each format guide must be **research-backed**. The implementing agent MUST: +1. Use WebSearch and WebFetch to read the **official documentation** for each format +2. Study the actual parsing rules, not assumptions +3. Include specific syntax examples from real documentation + +- [ ] **Step 1: Create obsidian.md format guide** + +Research Obsidian's official docs (https://help.obsidian.md/) and create `understand-anything-plugin/skills/understand-knowledge/formats/obsidian.md`: + +The guide must cover: +- Detection: `.obsidian/` directory exists +- Link syntax: `[[wikilink]]`, `[[note|alias]]`, `[[note#heading]]`, `![[embed]]` +- Metadata: YAML frontmatter between `---` delimiters +- Tags: `#tag` inline, `tags:` in frontmatter (both array and space-separated) +- Properties: Obsidian Properties (frontmatter fields rendered in UI) +- Folder semantics: Obsidian doesn't assign folder meaning by default +- Special files: `.obsidian/app.json`, `.obsidian/workspace.json` (ignore these) +- Canvas: `.canvas` files (JSON format, describe spatial layouts — extract card references) +- Dataview: inline fields `key:: value`, `[key:: value]` + +- [ ] **Step 2: Create logseq.md format guide** + +Research Logseq docs (https://docs.logseq.com/) and create `understand-anything-plugin/skills/understand-knowledge/formats/logseq.md`: + +Cover: +- Detection: `logseq/` + `pages/` directories +- Structure: `journals/YYYY_MM_DD.md` (daily notes), `pages/*.md` (named pages) +- Link syntax: `[[wikilinks]]`, `((block-references))` by UUID +- Block-based: Content is organized as bullet-point outlines +- Properties: `key:: value` syntax on blocks +- Tags: `#tag` inline, page tags via properties +- Special: `logseq/config.edn` for configuration + +- [ ] **Step 3: Create dendron.md format guide** + +Research Dendron wiki (https://wiki.dendron.so/) and create `understand-anything-plugin/skills/understand-knowledge/formats/dendron.md`: + +Cover: +- Detection: `.dendron.yml` or `*.schema.yml` files +- Hierarchy: dot-delimited filenames (`a.b.c.md`) +- Link syntax: `[[wikilinks]]` with hierarchy awareness +- Schemas: `.schema.yml` files define expected hierarchy structure +- Frontmatter: YAML with required `id` and `title` fields +- Stubs: auto-created intermediate hierarchy files + +- [ ] **Step 4: Create foam.md format guide** + +Research Foam docs (https://foambubble.github.io/foam/) and create `understand-anything-plugin/skills/understand-knowledge/formats/foam.md`: + +Cover: +- Detection: `.foam/` directory or `.vscode/foam.json` +- Link syntax: `[[wikilinks]]` plus link reference definitions at file bottom +- Placeholder links: links to non-existent files +- Frontmatter: standard YAML +- Auto-linking: Foam auto-updates links on file rename/move + +- [ ] **Step 5: Create karpathy.md format guide** + +Research Karpathy's gist (https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) and create `understand-anything-plugin/skills/understand-knowledge/formats/karpathy.md`: + +Cover: +- Detection: `raw/` + `wiki/` directories + `index.md` +- Structure: `raw/` (immutable sources), `wiki/` (compiled articles), `_meta/` (state) +- Special files: `index.md` (master page list), `log.md` (append-only operations log) +- Link style: standard markdown links (not wikilinks) +- Log parsing: `## [YYYY-MM-DD] operation | Title` entries +- Wiki articles: LLM-compiled, may have cross-references and backlinks + +- [ ] **Step 6: Create zettelkasten.md format guide** + +Research zettelkasten.de and create `understand-anything-plugin/skills/understand-knowledge/formats/zettelkasten.md`: + +Cover: +- Detection: `[[wikilinks]]` + unique ID prefixes in filenames (timestamps like `202604091234`) +- Atomic notes: one idea per note +- Unique IDs: timestamp or alphanumeric prefix in filename +- Links: `[[wikilinks]]` with optional typed links +- Frontmatter: YAML with tags, creation date +- No folder hierarchy: flat structure, connections via links only + +- [ ] **Step 7: Create plain.md format guide** + +Create `understand-anything-plugin/skills/understand-knowledge/formats/plain.md`: + +Cover: +- Detection: fallback when no other format detected +- Links: standard markdown `[text](relative/path.md)` links +- Structure: folder hierarchy provides categorization +- Headings: `#` hierarchy provides structure within files +- No special metadata expectations +- Tags: none expected (LLM infers topics) + +- [ ] **Step 8: Commit** + +```bash +git add understand-anything-plugin/skills/understand-knowledge/formats/ +git commit -m "feat(skill): add 7 research-backed format guides for knowledge base parsing" +``` + +--- + +## Task 13: Create SKILL.md + +**Files:** +- Create: `understand-anything-plugin/skills/understand-knowledge/SKILL.md` + +- [ ] **Step 1: Create the skill definition** + +Create `understand-anything-plugin/skills/understand-knowledge/SKILL.md`: + +```markdown +--- +name: understand-knowledge +description: Analyze a markdown knowledge base (Obsidian, Logseq, Dendron, Foam, Karpathy-style, Zettelkasten, or plain) to produce an interactive knowledge graph with typed relationships +argument-hint: [path/to/notes] [--ingest ] +--- + +# /understand-knowledge + +Analyze a personal knowledge base of markdown files and produce an interactive knowledge graph. + +## Arguments + +- `path/to/notes` — (optional) directory containing markdown files. Defaults to current working directory. +- `--ingest ` — (optional) incrementally add new file(s) to an existing knowledge graph. + +## Phase 0: Pre-flight + +1. Determine the target directory: + - If a path argument is provided, use it + - Otherwise use the current working directory +2. Create `.understand-anything/` and `.understand-anything/intermediate/` directories if they don't exist +3. If `--ingest` flag is present: + - Verify `.understand-anything/knowledge-graph.json` exists (error if not — must run full scan first) + - Read the existing graph + - Skip to Phase 2 with only the new/changed files +4. Get the current git commit hash (if in a git repo, otherwise use "no-git") + +## Phase 1: SCAN + +Dispatch the **knowledge-scanner** agent: + +```json +{ + "targetDir": "" +} +``` + +Wait for the agent to write `.understand-anything/intermediate/knowledge-manifest.json`. + +Report: "Scanned {totalFiles} markdown files." + +## Phase 2: FORMAT DETECTION + +Dispatch the **format-detector** agent. + +Wait for `.understand-anything/intermediate/format-detection.json`. + +Report: "Detected format: {format} (confidence: {confidence})" + +## Phase 3: ANALYZE + +Read the format detection result. Load the corresponding format guide: + +- `obsidian` → inject `skills/understand-knowledge/formats/obsidian.md` +- `logseq` → inject `skills/understand-knowledge/formats/logseq.md` +- `dendron` → inject `skills/understand-knowledge/formats/dendron.md` +- `foam` → inject `skills/understand-knowledge/formats/foam.md` +- `karpathy` → inject `skills/understand-knowledge/formats/karpathy.md` +- `zettelkasten` → inject `skills/understand-knowledge/formats/zettelkasten.md` +- `plain` → inject `skills/understand-knowledge/formats/plain.md` + +Batch the files from the manifest into groups of 15-25 files each. + +For each batch, dispatch an **article-analyzer** agent with: + +```json +{ + "projectRoot": "", + "batchFiles": [...], + "format": "", + "parsingHints": {...} +} +``` + +Inject the format guide content into each agent's context. + +Run up to 5 batches concurrently. + +Wait for all `article-batch-*.json` files. + +Report: "Analyzed {totalFiles} files across {batchCount} batches." + +## Phase 4: RELATIONSHIPS + +Dispatch the **relationship-builder** agent. + +Wait for `.understand-anything/intermediate/relationships.json`. + +Report: "Discovered {topicCount} topics, {implicitEdgeCount} implicit relationships." + +## Phase 5: ASSEMBLE + +Merge all intermediate results into a single knowledge graph: + +1. Read all `article-batch-*.json` files — collect all nodes and edges +2. Read `relationships.json` — merge in topic nodes, implicit edges, layers, and tour +3. Deduplicate nodes by ID (keep the most complete version) +4. Deduplicate edges by source+target+type +5. Assemble into `KnowledgeGraph` format: + +```json +{ + "version": "1.0", + "kind": "knowledge", + "project": { + "name": "", + "languages": [], + "frameworks": [], + "description": "Knowledge base analyzed from format", + "analyzedAt": "", + "gitCommitHash": "" + }, + "nodes": [...], + "edges": [...], + "layers": [...], + "tour": [...] +} +``` + +## Phase 6: REVIEW + +Dispatch the existing **graph-reviewer** agent to validate: +- All edge source/target IDs reference existing nodes +- No orphan nodes (nodes with zero edges) +- No duplicate node IDs +- All layers reference existing nodes +- Tour steps reference existing nodes + +Apply fixes from the reviewer. + +## Phase 7: SAVE + +1. Write `.understand-anything/knowledge-graph.json` +2. Write `.understand-anything/meta.json`: + ```json + { + "lastAnalyzedAt": "", + "gitCommitHash": "", + "version": "1.0", + "analyzedFiles": , + "knowledgeFormat": "" + } + ``` +3. Clean up `.understand-anything/intermediate/` directory +4. Report: "Knowledge graph saved with {nodeCount} nodes and {edgeCount} edges." + +## Phase 8: DASHBOARD + +Auto-trigger `/understand-dashboard` to launch the visualization. + +## Incremental Mode (--ingest) + +When `--ingest ` is specified: + +1. Read the existing `knowledge-graph.json` +2. Scan only the specified file(s) or folder +3. Skip format detection (reuse format from existing graph's metadata) +4. Run article-analyzer on only the new/changed files +5. Run relationship-builder on new nodes against the full existing graph +6. Merge new nodes/edges into the existing graph +7. Re-run graph-reviewer +8. Save updated graph +``` + +- [ ] **Step 2: Commit** + +```bash +git add understand-anything-plugin/skills/understand-knowledge/SKILL.md +git commit -m "feat(skill): add /understand-knowledge skill definition with 8-phase pipeline" +``` + +--- + +## Task 14: Build, Test & Verify End-to-End + +**Files:** +- All modified files + +- [ ] **Step 1: Build core package** + +Run: `pnpm --filter @understand-anything/core build` +Expected: Clean build, no errors + +- [ ] **Step 2: Run core tests** + +Run: `pnpm --filter @understand-anything/core test -- --run` +Expected: All tests pass, including new knowledge-schema tests + +- [ ] **Step 3: Build dashboard** + +Run: `pnpm --filter @understand-anything/dashboard build` +Expected: Clean build, no errors + +- [ ] **Step 4: Run lint** + +Run: `pnpm lint` +Expected: No lint errors + +- [ ] **Step 5: Verify skill is discoverable** + +Check that the skill file exists and has valid frontmatter: + +Run: `head -5 understand-anything-plugin/skills/understand-knowledge/SKILL.md` +Expected: Valid `---` delimited YAML with name, description, argument-hint + +- [ ] **Step 6: Verify all agents are present** + +Run: `ls understand-anything-plugin/agents/ | grep knowledge\|format\|article\|relationship` +Expected: `knowledge-scanner.md`, `format-detector.md`, `article-analyzer.md`, `relationship-builder.md` + +- [ ] **Step 7: Verify all format guides are present** + +Run: `ls understand-anything-plugin/skills/understand-knowledge/formats/` +Expected: `obsidian.md`, `logseq.md`, `dendron.md`, `foam.md`, `karpathy.md`, `zettelkasten.md`, `plain.md` + +- [ ] **Step 8: Final commit** + +```bash +git add -A +git commit -m "feat: complete /understand-knowledge implementation — knowledge base analysis skill" +```