feat(skill): add /understand-onboard command for team onboarding guides

Generates a structured markdown onboarding guide from the knowledge graph,
including project overview, architecture layers, key concepts, guided tour,
file map, and complexity hotspots.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lum1104
2026-03-14 22:49:37 +08:00
co-authored by Claude Opus 4.6
parent eb0d2eaac0
commit 09fc78f321
4 changed files with 235 additions and 0 deletions
@@ -0,0 +1,23 @@
---
name: understand-onboard
description: Generate a structured onboarding guide for new team members using the knowledge graph
---
# /understand-onboard
Generate a comprehensive onboarding guide from the project's knowledge graph.
## Instructions
1. Read the knowledge graph at `.understand-anything/knowledge-graph.json`
2. If it doesn't exist, tell the user to run `/understand` first
3. Generate a structured onboarding guide that includes:
- Project overview (name, languages, frameworks, description)
- Architecture layers and their responsibilities
- Key concepts to understand
- Guided tour (step-by-step walkthrough)
- File map (what each key file does)
- Complexity hotspots (what to be careful with)
4. Format as clean markdown
5. Offer to save the guide to `docs/ONBOARDING.md` in the project
6. Suggest the user commit it to the repo for the team
@@ -0,0 +1,87 @@
import { describe, it, expect } from "vitest";
import { buildOnboardingGuide } from "../onboard-builder.js";
import type { KnowledgeGraph } from "@understand-anything/core";
const sampleGraph: KnowledgeGraph = {
version: "1.0.0",
project: {
name: "test-project",
languages: ["typescript", "python"],
frameworks: ["express", "prisma"],
description: "A test REST API",
analyzedAt: "2026-03-14T00:00:00Z",
gitCommitHash: "abc123",
},
nodes: [
{ id: "file:src/index.ts", type: "file", name: "index.ts", filePath: "src/index.ts", summary: "Entry point", tags: ["entry"], complexity: "simple" },
{ id: "file:src/service.ts", type: "file", name: "service.ts", filePath: "src/service.ts", summary: "Core service", tags: ["service"], complexity: "complex" },
{ id: "concept:auth", type: "concept", name: "Auth Flow", summary: "JWT-based authentication", tags: ["concept", "auth"], complexity: "complex" },
],
edges: [
{ source: "file:src/index.ts", target: "file:src/service.ts", type: "imports", direction: "forward", weight: 0.8 },
],
layers: [
{ id: "layer:api", name: "API Layer", description: "Routes and handlers", nodeIds: ["file:src/index.ts"] },
{ id: "layer:service", name: "Service Layer", description: "Business logic", nodeIds: ["file:src/service.ts"] },
],
tour: [
{ order: 1, title: "Start Here", description: "Begin with index.ts", nodeIds: ["file:src/index.ts"] },
{ order: 2, title: "Core Logic", description: "Service layer", nodeIds: ["file:src/service.ts"] },
],
};
describe("onboard-builder", () => {
it("includes project overview section", () => {
const guide = buildOnboardingGuide(sampleGraph);
expect(guide).toContain("# test-project");
expect(guide).toContain("A test REST API");
});
it("lists languages and frameworks", () => {
const guide = buildOnboardingGuide(sampleGraph);
expect(guide).toContain("typescript");
expect(guide).toContain("express");
});
it("includes architecture layers section", () => {
const guide = buildOnboardingGuide(sampleGraph);
expect(guide).toContain("## Architecture");
expect(guide).toContain("API Layer");
expect(guide).toContain("Service Layer");
});
it("includes key concepts section", () => {
const guide = buildOnboardingGuide(sampleGraph);
expect(guide).toContain("## Key Concepts");
expect(guide).toContain("Auth Flow");
});
it("includes getting started / tour section", () => {
const guide = buildOnboardingGuide(sampleGraph);
expect(guide).toContain("## Getting Started");
expect(guide).toContain("Start Here");
});
it("includes complexity hotspots", () => {
const guide = buildOnboardingGuide(sampleGraph);
expect(guide).toContain("## Complexity Hotspots");
expect(guide).toContain("service.ts");
});
it("includes file map section", () => {
const guide = buildOnboardingGuide(sampleGraph);
expect(guide).toContain("## File Map");
});
it("handles graph with no layers gracefully", () => {
const noLayers = { ...sampleGraph, layers: [] };
const guide = buildOnboardingGuide(noLayers);
expect(guide).toContain("# test-project");
});
it("handles graph with no tour gracefully", () => {
const noTour = { ...sampleGraph, tour: [] };
const guide = buildOnboardingGuide(noTour);
expect(guide).toContain("# test-project");
});
});
+1
View File
@@ -14,3 +14,4 @@ export {
formatExplainPrompt,
type ExplainContext,
} from "./explain-builder.js";
export { buildOnboardingGuide } from "./onboard-builder.js";
+124
View File
@@ -0,0 +1,124 @@
import type { KnowledgeGraph } from "@understand-anything/core";
/**
* Generate a structured onboarding guide from the knowledge graph.
* Output is standalone markdown suitable for a README, wiki, or docs.
*/
export function buildOnboardingGuide(graph: KnowledgeGraph): string {
const { project, nodes, edges, layers, tour } = graph;
const lines: string[] = [];
// --- Project Overview ---
lines.push(`# ${project.name}`);
lines.push("");
lines.push(`> ${project.description}`);
lines.push("");
lines.push(`| | |`);
lines.push(`|---|---|`);
lines.push(`| **Languages** | ${project.languages.join(", ")} |`);
lines.push(`| **Frameworks** | ${project.frameworks.join(", ")} |`);
lines.push(`| **Components** | ${nodes.length} nodes, ${edges.length} relationships |`);
lines.push(`| **Last Analyzed** | ${project.analyzedAt} |`);
lines.push("");
// --- Architecture ---
if (layers.length > 0) {
lines.push("## Architecture");
lines.push("");
lines.push("The project is organized into the following layers:");
lines.push("");
for (const layer of layers) {
const memberNames = layer.nodeIds
.map((id) => nodes.find((n) => n.id === id)?.name)
.filter(Boolean);
lines.push(`### ${layer.name}`);
lines.push("");
lines.push(layer.description);
lines.push("");
if (memberNames.length > 0) {
lines.push(`Key components: ${memberNames.join(", ")}`);
lines.push("");
}
}
}
// --- Key Concepts ---
const conceptNodes = nodes.filter((n) => n.type === "concept");
if (conceptNodes.length > 0) {
lines.push("## Key Concepts");
lines.push("");
lines.push("Important architectural and domain concepts to understand:");
lines.push("");
for (const concept of conceptNodes) {
lines.push(`### ${concept.name}`);
lines.push("");
lines.push(concept.summary);
lines.push("");
}
}
// --- Getting Started (Tour) ---
if (tour.length > 0) {
lines.push("## Getting Started");
lines.push("");
lines.push("Follow this guided tour to understand the codebase:");
lines.push("");
for (const step of tour) {
const stepNodes = step.nodeIds
.map((id) => nodes.find((n) => n.id === id))
.filter(Boolean);
lines.push(`### ${step.order}. ${step.title}`);
lines.push("");
lines.push(step.description);
lines.push("");
if (stepNodes.length > 0) {
lines.push("**Files to look at:**");
for (const node of stepNodes) {
if (node!.filePath) {
lines.push(`- \`${node!.filePath}\`${node!.summary}`);
}
}
lines.push("");
}
if (step.languageLesson) {
lines.push(`> **Language Tip:** ${step.languageLesson}`);
lines.push("");
}
}
}
// --- File Map ---
const fileNodes = nodes.filter((n) => n.type === "file" && n.filePath);
if (fileNodes.length > 0) {
lines.push("## File Map");
lines.push("");
lines.push("| File | Purpose | Complexity |");
lines.push("|------|---------|------------|");
for (const node of fileNodes) {
lines.push(`| \`${node.filePath}\` | ${node.summary} | ${node.complexity} |`);
}
lines.push("");
}
// --- Complexity Hotspots ---
const complexNodes = nodes.filter((n) => n.complexity === "complex");
if (complexNodes.length > 0) {
lines.push("## Complexity Hotspots");
lines.push("");
lines.push("These components are the most complex and deserve extra attention:");
lines.push("");
for (const node of complexNodes) {
lines.push(`- **${node.name}** (${node.type}): ${node.summary}`);
}
lines.push("");
}
// --- Footer ---
lines.push("---");
lines.push("");
lines.push(`*Generated by [Understand Anything](https://github.com/anthropics/understand-anything) from knowledge graph v${graph.version}*`);
lines.push("");
return lines.join("\n");
}