@vpxa/aikit 0.1.121 → 0.1.122

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/aikit",
3
- "version": "0.1.121",
3
+ "version": "0.1.122",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -4082,6 +4082,93 @@ C4Deployment
4082
4082
  Rel(api, db, "Reads/writes", "JDBC")
4083
4083
  \`\`\`
4084
4084
 
4085
+ ## Layer Architecture Diagrams
4086
+
4087
+ Layer diagrams show how modules group into architectural layers and expose cross-layer dependencies - especially violations (upward or skip-layer calls).
4088
+
4089
+ ### Layer Map Diagram
4090
+
4091
+ Use Mermaid \`graph TD\` with subgraphs. Each layer is a subgraph, color-coded:
4092
+
4093
+ | Layer | Color | Stroke |
4094
+ |-------|-------|--------|
4095
+ | Presentation | \`#0e1a27\` fill | \`#22d3ee\` |
4096
+ | Business / Domain | \`#0e1a27\` fill | \`#34d399\` |
4097
+ | Data / Persistence | \`#0e1a27\` fill | \`#a78bfa\` |
4098
+ | Infrastructure | \`#0e1a27\` fill | \`#fbbf24\` |
4099
+ | Cross-cutting | \`#0e1a27\` fill | \`#fb923c\` |
4100
+
4101
+ **Example:**
4102
+
4103
+ \`\`\`mermaid
4104
+ graph TD
4105
+ subgraph Presentation["Presentation Layer"]
4106
+ style Presentation fill:#0e1a27,stroke:#22d3ee
4107
+ Pages["pages/"]
4108
+ Components["components/"]
4109
+ end
4110
+ subgraph Business["Business Layer"]
4111
+ style Business fill:#0e1a27,stroke:#34d399
4112
+ Services["services/"]
4113
+ UseCases["use-cases/"]
4114
+ end
4115
+ subgraph Data["Data Layer"]
4116
+ style Data fill:#0e1a27,stroke:#a78bfa
4117
+ Repos["repositories/"]
4118
+ Models["models/"]
4119
+ end
4120
+
4121
+ Pages --> Services
4122
+ Services --> Repos
4123
+ Components -.->|violation| Models
4124
+ \`\`\`
4125
+
4126
+ **Violation highlighting**: Use dotted lines with \`|violation|\` labels for cross-layer violations (e.g., Presentation accessing Data directly). Optionally use \`linkStyle\` with \`stroke:red,stroke-dasharray:5\` for emphasis.
4127
+
4128
+ ### Layer Detection Workflow
4129
+
4130
+ 1. \`analyze({ aspect: "structure", path: "." })\` - get directory tree
4131
+ 2. Detect framework (see Framework Layer Heuristics below)
4132
+ 3. Apply directory-to-layer mapping based on framework heuristics
4133
+ 4. \`analyze({ aspect: "dependencies", path: "." })\` - get import graph
4134
+ 5. Identify cross-layer dependencies - flag violations
4135
+ 6. Generate Mermaid diagram with subgraphs
4136
+
4137
+ ### Generic Layer Patterns
4138
+
4139
+ When no framework is detected, use these directory heuristics:
4140
+
4141
+ | Directory Pattern | Layer |
4142
+ |-------------------|-------|
4143
+ | \`pages/\`, \`views/\`, \`screens/\`, \`ui/\`, \`components/\` | Presentation |
4144
+ | \`services/\`, \`use-cases/\`, \`domain/\`, \`logic/\`, \`core/\` | Business |
4145
+ | \`models/\`, \`entities/\`, \`repositories/\`, \`db/\`, \`data/\` | Data |
4146
+ | \`infra/\`, \`config/\`, \`deploy/\`, \`docker/\`, \`k8s/\` | Infrastructure |
4147
+ | \`middleware/\`, \`utils/\`, \`shared/\`, \`common/\`, \`lib/\` | Cross-cutting |
4148
+
4149
+ ### Framework Layer Heuristics
4150
+
4151
+ Detect the framework from \`package.json\`, \`go.mod\`, \`requirements.txt\`, etc., then apply framework-specific layer assignments:
4152
+
4153
+ | Framework | Detection | Layer Assignments |
4154
+ |-----------|-----------|-------------------|
4155
+ | React / Next.js | \`react-dom\` or \`next\` in deps | \`pages/\` -> Presentation, \`components/\` -> Presentation, \`hooks/\` -> Business, \`api/\` -> Backend, \`lib/\` -> Shared |
4156
+ | Vue | \`vue\` in deps | \`views/\` -> Presentation, \`components/\` -> Presentation, \`composables/\` -> Business, \`stores/\` -> State |
4157
+ | Express | \`express\` in deps | \`routes/\` -> API, \`controllers/\` -> Business, \`middleware/\` -> Cross-cutting, \`models/\` -> Data, \`services/\` -> Business |
4158
+ | Go / Gin | \`gin-gonic\` in go.mod | \`cmd/\` -> Entry, \`internal/\` -> Business, \`pkg/\` -> Shared, \`handlers/\` -> API, \`middleware/\` -> Cross-cutting |
4159
+ | Django | \`django\` in requirements | \`views.py\` -> API, \`models.py\` -> Data, \`serializers.py\` -> Transform, \`urls.py\` -> Routing, \`services/\` -> Business |
4160
+ | Flask | \`flask\` in requirements | \`routes/\` -> API, \`models/\` -> Data, \`services/\` -> Business, \`blueprints/\` -> Modular |
4161
+ | Spring Boot | \`spring-boot\` in pom/gradle | \`controllers/\` -> API, \`services/\` -> Business, \`repositories/\` -> Data, \`entities/\` -> Domain |
4162
+ | Rails | \`rails\` in Gemfile | \`controllers/\` -> API, \`models/\` -> Data, \`services/\` -> Business, \`views/\` -> Presentation |
4163
+
4164
+ **Workflow for framework-aware layer diagrams:**
4165
+
4166
+ 1. Detect framework from manifest files (\`package.json\`, \`go.mod\`, etc.)
4167
+ 2. Look up the framework's layer assignment table above
4168
+ 3. Map each source directory to its assigned layer
4169
+ 4. Generate the Layer Map Diagram using the mapped subgraphs
4170
+ 5. Flag any imports that cross more than one layer boundary as violations
4171
+
4085
4172
  ## HTML/SVG Format
4086
4173
 
4087
4174
  For HTML/SVG output, use the design system and template from the references.
@@ -4283,6 +4370,313 @@ Write architecture documentation to \`docs/architecture/\` with naming conventio
4283
4370
  | Developers | All levels as needed |
4284
4371
  | DevOps | Container + Deployment |
4285
4372
 
4373
+ ## Interactive Architecture Diagrams (React Flow)
4374
+
4375
+ When HTML output is requested and the architecture is complex (>10 nodes, multiple layers, or interactive exploration needed), generate a standalone HTML file using React Flow via CDN. This produces zoomable, pannable, collapsible diagrams superior to static SVG.
4376
+
4377
+ ### Standalone HTML Template
4378
+
4379
+ \`\`\`html
4380
+ <!DOCTYPE html>
4381
+ <html lang="en">
4382
+ <head>
4383
+ <meta charset="UTF-8"/>
4384
+ <title>{{DIAGRAM_TITLE}} — C4 Architecture</title>
4385
+ <script src="https://unpkg.com/react@18/umd/react.production.min.js"><\/script>
4386
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"><\/script>
4387
+ <script src="https://unpkg.com/@xyflow/react@12/dist/umd/index.js"><\/script>
4388
+ <script src="https://unpkg.com/elkjs@0.9/lib/elk.bundled.js"><\/script>
4389
+ <link rel="stylesheet" href="https://unpkg.com/@xyflow/react@12/dist/style.css"/>
4390
+ <style>
4391
+ body { margin: 0; font-family: system-ui, sans-serif; }
4392
+ .react-flow { width: 100vw; height: 100vh; }
4393
+ .c4-node { padding: 12px 16px; border-radius: 8px; border: 2px solid; min-width: 160px; }
4394
+ .c4-node-label { font-weight: 600; font-size: 14px; }
4395
+ .c4-node-tech { font-size: 11px; opacity: 0.7; margin-top: 4px; }
4396
+ .c4-node-desc { font-size: 12px; margin-top: 6px; max-width: 200px; }
4397
+ .c4-boundary { border: 2px dashed #64748b; border-radius: 12px; padding: 24px; background: rgba(100,116,139,0.05); }
4398
+ </style>
4399
+ </head>
4400
+ <body>
4401
+ <div id="root"></div>
4402
+ <script>
4403
+ // Node data — replace with generated architecture
4404
+ const nodes = {{NODES_JSON}};
4405
+ const edges = {{EDGES_JSON}};
4406
+ // ELK layout then render — see layout section below
4407
+ <\/script>
4408
+ </body>
4409
+ </html>
4410
+ \`\`\`
4411
+
4412
+ ### Custom Node Types by C4 Category
4413
+
4414
+ \`\`\`javascript
4415
+ const nodeTypes = {
4416
+ person: { shape: 'circle', color: '#60a5fa', icon: '👤' },
4417
+ system: { shape: 'rect-lg', color: '#a78bfa', border: 'solid' },
4418
+ container: { shape: 'rect-md', color: '#34d399', border: 'solid' },
4419
+ component: { shape: 'rect-sm', color: '#22d3ee', border: 'solid' },
4420
+ boundary: { shape: 'group', color: '#64748b', border: 'dashed' },
4421
+ database: { shape: 'cylinder', color: '#a78bfa', icon: '🗄️' },
4422
+ queue: { shape: 'rect-md', color: '#fb923c', icon: '📨' },
4423
+ external: { shape: 'rect-md', color: '#94a3b8', border: 'dotted' },
4424
+ };
4425
+ // Category colors match HTML/SVG design system above
4426
+ \`\`\`
4427
+
4428
+ ### ELK.js Hierarchical Layout
4429
+
4430
+ \`\`\`javascript
4431
+ const elkOptions = {
4432
+ 'elk.algorithm': 'layered',
4433
+ 'elk.direction': 'DOWN', // TOP → BOTTOM for C4
4434
+ 'elk.spacing.nodeNode': '50',
4435
+ 'elk.layered.spacing.nodeNodeBetweenLayers': '80',
4436
+ 'elk.edgeRouting': 'ORTHOGONAL',
4437
+ 'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',
4438
+ 'elk.hierarchyHandling': 'INCLUDE_CHILDREN', // for boundaries/groups
4439
+ };
4440
+
4441
+ async function layoutWithElk(nodes, edges) {
4442
+ const elk = new ELK();
4443
+ const graph = {
4444
+ id: 'root',
4445
+ children: nodes.map(n => ({
4446
+ id: n.id, width: n.width || 200, height: n.height || 80,
4447
+ ...(n.parentNode && { parentId: n.parentNode }),
4448
+ })),
4449
+ edges: edges.map(e => ({ id: e.id, sources: [e.source], targets: [e.target] })),
4450
+ };
4451
+ const layout = await elk.layout(graph, { layoutOptions: elkOptions });
4452
+ return layout.children.map(child => ({
4453
+ ...nodes.find(n => n.id === child.id),
4454
+ position: { x: child.x, y: child.y },
4455
+ }));
4456
+ }
4457
+ \`\`\`
4458
+
4459
+ ### SVG Export from React Flow
4460
+
4461
+ When static SVG is needed from an interactive diagram (for embedding in markdown docs or printing):
4462
+
4463
+ \`\`\`javascript
4464
+ function exportToSVG(nodes, edges, options = {}) {
4465
+ const { padding = 20, fontSize = 12 } = options;
4466
+ const bounds = computeBoundingBox(nodes, padding);
4467
+ const svgParts = [
4468
+ \\\`<svg xmlns="http://www.w3.org/2000/svg" viewBox="\${bounds.viewBox}">\\\`,
4469
+ '<defs><marker id="arrow" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" fill="#64748b"/></marker></defs>',
4470
+ ];
4471
+ // Render boundary groups first (back layer)
4472
+ nodes.filter(n => n.type === 'boundary').forEach(n => {
4473
+ svgParts.push(\\\`<rect x="\${n.position.x}" y="\${n.position.y}" width="\${n.width}" height="\${n.height}" rx="12" fill="none" stroke="#64748b" stroke-dasharray="8 4" stroke-width="2"/>\\\`);
4474
+ svgParts.push(\\\`<text x="\${n.position.x + 12}" y="\${n.position.y + 20}" font-size="13" fill="#64748b">\${n.data.label}</text>\\\`);
4475
+ });
4476
+ // Render edges
4477
+ edges.forEach(e => {
4478
+ const source = nodes.find(n => n.id === e.source);
4479
+ const target = nodes.find(n => n.id === e.target);
4480
+ svgParts.push(\\\`<line x1="\${source.position.x + source.width/2}" y1="\${source.position.y + source.height}" x2="\${target.position.x + target.width/2}" y2="\${target.position.y}" stroke="#64748b" stroke-width="1.5" marker-end="url(#arrow)"/>\\\`);
4481
+ if (e.label) svgParts.push(\\\`<text x="\${(source.position.x + target.position.x)/2 + 60}" y="\${(source.position.y + target.position.y)/2 + 40}" font-size="11" fill="#94a3b8">\${e.label}</text>\\\`);
4482
+ });
4483
+ // Render nodes
4484
+ nodes.filter(n => n.type !== 'boundary').forEach(n => {
4485
+ const color = nodeTypes[n.type]?.color || '#64748b';
4486
+ svgParts.push(\\\`<rect x="\${n.position.x}" y="\${n.position.y}" width="\${n.width || 200}" height="\${n.height || 80}" rx="8" fill="\${color}22" stroke="\${color}" stroke-width="2"/>\\\`);
4487
+ svgParts.push(\\\`<text x="\${n.position.x + 12}" y="\${n.position.y + 24}" font-size="\${fontSize}" font-weight="600" fill="#e2e8f0">\${n.data.label}</text>\\\`);
4488
+ if (n.data.technology) svgParts.push(\\\`<text x="\${n.position.x + 12}" y="\${n.position.y + 42}" font-size="11" fill="#94a3b8">[\${n.data.technology}]</text>\\\`);
4489
+ if (n.data.description) svgParts.push(\\\`<text x="\${n.position.x + 12}" y="\${n.position.y + 60}" font-size="11" fill="#cbd5e1">\${n.data.description}</text>\\\`);
4490
+ });
4491
+ svgParts.push('</svg>');
4492
+ return svgParts.join('\\n');
4493
+ }
4494
+ \`\`\`
4495
+
4496
+ ### When to Use React Flow vs Static SVG
4497
+
4498
+ | Scenario | Output | Rationale |
4499
+ |----------|--------|-----------|
4500
+ | >10 components | React Flow HTML | Needs zoom/pan for readability |
4501
+ | Multi-layer (≥3 layers) | React Flow HTML | ELK layout handles crossing minimization |
4502
+ | Exploration/onboarding | React Flow HTML | Interactive collapse/expand aids learning |
4503
+ | Markdown embedding | Static SVG export | Inline in \`.md\` files |
4504
+ | Print/PDF | Static SVG export | Fixed layout, no JS needed |
4505
+ | Simple (≤5 components) | Static SVG directly | Overhead of React Flow unnecessary |
4506
+ | CI/automated docs | Static SVG export | Deterministic, no browser needed |
4507
+
4508
+ ## Architecture Generation Prompts
4509
+
4510
+ Structured LLM prompt templates for generating high-quality architecture documentation. Each prompt produces strict JSON output that feeds into diagram generation.
4511
+
4512
+ ### Layer Detection Prompt
4513
+
4514
+ \`\`\`
4515
+ You are a software architecture analyst. Given the following list of file paths from a codebase, identify the architectural layers present.
4516
+
4517
+ **File paths:**
4518
+ {{FILE_PATHS}}
4519
+
4520
+ **Framework context (if detected):**
4521
+ {{FRAMEWORK_CONTEXT}}
4522
+
4523
+ **Instructions:**
4524
+ - Identify 3-7 distinct architectural layers
4525
+ - Each layer must have a clear single responsibility
4526
+ - Assign file path glob patterns to each layer
4527
+ - If a file doesn't fit any layer, assign it to "Core" or "Shared"
4528
+
4529
+ **Respond ONLY with a JSON object in this exact format, no additional text:**
4530
+ {
4531
+ "layers": [
4532
+ {
4533
+ "id": "layer-id-slug",
4534
+ "name": "Human Readable Name",
4535
+ "description": "Single sentence describing layer responsibility",
4536
+ "filePatterns": ["src/api/**", "src/routes/**"],
4537
+ "color": "#hex-color"
4538
+ }
4539
+ ],
4540
+ "unmatched": ["paths/that/dont/fit/**"]
4541
+ }
4542
+ \`\`\`
4543
+
4544
+ ### Component Analysis Prompt
4545
+
4546
+ \`\`\`
4547
+ You are a software architecture analyst. Analyze this source file and extract its architectural role.
4548
+
4549
+ **File:** {{FILE_PATH}}
4550
+ **Content:**
4551
+ {{FILE_CONTENT}}
4552
+
4553
+ **Project context:**
4554
+ {{PROJECT_SUMMARY}}
4555
+
4556
+ **Respond ONLY with a JSON object:**
4557
+ {
4558
+ "summary": "One sentence: what this file does",
4559
+ "technology": "Primary technology/framework used",
4560
+ "category": "frontend|backend|data|infrastructure|messaging|security|external|monitoring",
4561
+ "layer": "Which architectural layer this belongs to",
4562
+ "dependencies": ["module-ids this file imports from"],
4563
+ "exposes": ["exported functions/classes/types"],
4564
+ "complexity": "low|medium|high",
4565
+ "c4Type": "container|component"
4566
+ }
4567
+ \`\`\`
4568
+
4569
+ ### Architecture Synthesis Prompt
4570
+
4571
+ \`\`\`
4572
+ You are a C4 architecture diagram generator. Given analyzed components, their relationships, and layer assignments, produce a complete C4 diagram specification.
4573
+
4574
+ **Components:**
4575
+ {{COMPONENTS_JSON}}
4576
+
4577
+ **Relationships (import edges):**
4578
+ {{EDGES_JSON}}
4579
+
4580
+ **Layers:**
4581
+ {{LAYERS_JSON}}
4582
+
4583
+ **Diagram level:** {{LEVEL}} (context|container|component)
4584
+
4585
+ **Instructions:**
4586
+ - Group components into their layers as boundaries
4587
+ - Identify the most important relationships (max 3 per component)
4588
+ - Label relationships with the interaction type (calls, subscribes, reads, writes)
4589
+ - External systems go outside all boundaries
4590
+ - Users/actors are Person type
4591
+
4592
+ **Respond ONLY with a JSON object:**
4593
+ {
4594
+ "title": "Diagram title",
4595
+ "nodes": [
4596
+ { "id": "unique-id", "type": "person|system|container|component|boundary|database|queue|external", "label": "Display Name", "technology": "Tech stack", "description": "Brief desc", "parent": "boundary-id-or-null", "layer": "layer-id" }
4597
+ ],
4598
+ "edges": [
4599
+ { "id": "edge-id", "source": "node-id", "target": "node-id", "label": "Relationship description", "style": "solid|dashed|dotted" }
4600
+ ],
4601
+ "layoutHints": { "direction": "DOWN|RIGHT", "groupByLayer": true }
4602
+ }
4603
+ \`\`\`
4604
+
4605
+ ### Framework Context Addendum Pattern
4606
+
4607
+ When a framework is detected, inject its addendum into the Layer Detection and Component Analysis prompts:
4608
+
4609
+ \`\`\`markdown
4610
+ ## {{FRAMEWORK}} Framework Addendum
4611
+ (Injected into architecture prompts when {{FRAMEWORK}} is detected)
4612
+
4613
+ ### Canonical File Roles
4614
+
4615
+ | Path Pattern | Role | C4 Type |
4616
+ |---|---|---|
4617
+ | {{pattern}} | {{role}} | {{type}} |
4618
+
4619
+ ### Architectural Layers
4620
+
4621
+ | Layer ID | Layer Name | What Goes Here |
4622
+ |---|---|---|
4623
+ | {{layer_id}} | {{name}} | {{description}} |
4624
+
4625
+ ### Edge Patterns
4626
+ - {{pattern 1: e.g., "pages/ → api/ via fetch/tRPC"}}
4627
+ - {{pattern 2: e.g., "services/ → repositories/ for data access"}}
4628
+ \`\`\`
4629
+
4630
+ **Addendum examples to create per framework:**
4631
+ - \`next.js\`: pages/app router → API routes → services → DB
4632
+ - \`express\`: routes → controllers → services → models
4633
+ - \`react-spa\`: pages → components → hooks → api-client → store
4634
+ - \`nestjs\`: modules → controllers → providers → entities
4635
+ - \`django\`: urls → views → serializers → models → managers
4636
+
4637
+ ## Architecture Documentation Pipeline
4638
+
4639
+ When generating comprehensive architecture documentation, orchestrate this phased approach:
4640
+
4641
+ ### Phase 1 — Scan (deterministic, no LLM)
4642
+ \`\`\`
4643
+ analyze({ aspect: "structure", path: "." }) # Directory tree
4644
+ analyze({ aspect: "dependencies", path: "." }) # Import graph
4645
+ analyze({ aspect: "entry_points", path: "." }) # Entry points (0 in-degree)
4646
+ graph({ action: "stats" }) # Graph size for complexity estimate
4647
+ \`\`\`
4648
+
4649
+ ### Phase 2 — Classify (LLM-assisted)
4650
+ 1. Apply **Layer Detection Prompt** with file paths from Phase 1
4651
+ 2. Detect framework from package.json/config files
4652
+ 3. Inject **Framework Addendum** for detected framework
4653
+ 4. Apply **Component Analysis Prompt** to key files (entry points + high fan-in nodes)
4654
+ 5. Output: \`layers.json\`, \`components.json\`
4655
+
4656
+ ### Phase 3 — Synthesize (LLM-assisted)
4657
+ 1. Apply **Architecture Synthesis Prompt** per C4 level:
4658
+ - System Context: external actors + top-level system boundary
4659
+ - Containers: runtime units (services, DBs, queues, frontends)
4660
+ - Components: internal modules within each container
4661
+ 2. Generate BOTH output formats:
4662
+ - **Mermaid** for \`docs/architecture/*.md\` files
4663
+ - **React Flow HTML** for interactive exploration
4664
+ 3. Output: diagram specs per level
4665
+
4666
+ ### Phase 4 — Layout & Render
4667
+ 1. Apply ELK.js layout to React Flow nodes
4668
+ 2. Generate static SVG exports for markdown embedding
4669
+ 3. Write files:
4670
+ - \`docs/architecture/c4-context.md\` (Mermaid)
4671
+ - \`docs/architecture/c4-containers.md\` (Mermaid)
4672
+ - \`docs/architecture/interactive/\` (HTML files)
4673
+
4674
+ ### Phase 5 — Validate
4675
+ \`\`\`
4676
+ check({}) # Typecheck (if TS)
4677
+ blast_radius({ files: ["docs/architecture/**"] }) # Verify scope
4678
+ \`\`\`
4679
+
4286
4680
  ## References
4287
4681
 
4288
4682
  - [references/c4-syntax.md](references/c4-syntax.md) - Complete Mermaid C4 syntax
@@ -5692,6 +6086,503 @@ Document implementation patterns for:
5692
6086
  - **Tools**: \`analyze({ aspect: "entry_points", ... })\` + \`analyze({ aspect: "patterns", ... })\`
5693
6087
  - **Output**: \`docs/guides/contributing.md\` or \`docs/architecture/overview.md\` extension section
5694
6088
 
6089
+ ## Guided Tour Generation
6090
+
6091
+ Generate dependency-ordered codebase walkthroughs that teach the system through its natural reading order. Tours live in \`docs/tours/\`.
6092
+
6093
+ ### Algorithm
6094
+
6095
+ 1. \`analyze({ aspect: "entry_points", path: "." })\` — find tour start points (0 in-degree modules)
6096
+ 2. \`graph({ action: "find_nodes", name_pattern: "src" })\` — get all module nodes
6097
+ 3. \`graph({ action: "neighbors", node_id: "<entry>", direction: "outgoing" })\` — build dependency graph
6098
+ 4. Topological sort on import edges — determine reading order
6099
+ 5. Group by depth/layer — create logical tour steps
6100
+ 6. Batch ≤ 3 related files per step — keep each step focused
6101
+ 7. Append concept/cross-cutting nodes as final steps
6102
+
6103
+ ### Tour Step Format
6104
+
6105
+ Each step in a tour:
6106
+
6107
+ \`\`\`markdown
6108
+ ## Step {order}: {title}
6109
+
6110
+ {description — what the reader will understand after this step}
6111
+
6112
+ **Files:**
6113
+ - \`{file1}\` — {role}
6114
+ - \`{file2}\` — {role}
6115
+
6116
+ **Key concepts:** {comma-separated concepts introduced here}
6117
+ **Depends on:** Steps {list of prerequisite step numbers}
6118
+ \`\`\`
6119
+
6120
+ ### Tour Generation Workflow
6121
+
6122
+ 1. Run the algorithm above to produce ordered step list
6123
+ 2. For each step, use \`compact({ path, query: "purpose and public API" })\` to extract key info
6124
+ 3. Write tour as \`docs/tours/{topic}.md\`
6125
+ 4. Generate \`docs/tours/index.md\` linking all tours with descriptions
6126
+
6127
+ ### Tour Index Template (\`docs/tours/index.md\`)
6128
+
6129
+ \`\`\`markdown
6130
+ # Codebase Tours
6131
+
6132
+ Guided walkthroughs ordered by dependency — read them in sequence to understand the system.
6133
+
6134
+ | Tour | Description | Steps | Audience |
6135
+ |------|-------------|-------|----------|
6136
+ | [Architecture](./architecture.md) | System structure and layers | N | New team members |
6137
+ | [Data Flow](./data-flow.md) | How data moves through the system | N | Backend developers |
6138
+ | [Feature: {name}](./feature-{name}.md) | End-to-end feature trace | N | Feature developers |
6139
+ \`\`\`
6140
+
6141
+ ### Directory Convention
6142
+
6143
+ \`\`\`
6144
+ docs/
6145
+ └── tours/
6146
+ ├── index.md # Tour listing with descriptions
6147
+ ├── architecture.md # System structure tour
6148
+ ├── data-flow.md # Data pipeline tour
6149
+ └── feature-{name}.md # Feature-specific tours
6150
+ \`\`\`
6151
+
6152
+ ## Business Domain Documentation
6153
+
6154
+ Document the business domain as a three-level hierarchy: **Domain → Flow → Step**. This captures what the system does in business terms, separate from its technical architecture.
6155
+
6156
+ ### Hierarchy
6157
+
6158
+ - **Domain**: A bounded business context (e.g., "Authentication", "Billing", "Inventory")
6159
+ - **Flow**: A business process within a domain (e.g., "User Login", "Invoice Generation")
6160
+ - **Step**: An atomic action within a flow (e.g., "Validate Credentials", "Generate PDF")
6161
+
6162
+ ### Domain Discovery Workflow
6163
+
6164
+ 1. \`analyze({ aspect: "structure", path: "." })\` — identify top-level domain boundaries (directories, modules)
6165
+ 2. \`analyze({ aspect: "entry_points", path: "." })\` — detect flow entry types (HTTP, CLI, event, cron, manual)
6166
+ 3. \`trace({ start: "<entry-point>", direction: "forward" })\` — map each flow's step sequence
6167
+ 4. \`graph({ action: "neighbors", node_id: "<domain-module>", direction: "both" })\` — find cross-domain interactions
6168
+
6169
+ ### Domain Template (\`docs/architecture/domains/{domain-name}.md\`)
6170
+
6171
+ \`\`\`markdown
6172
+ # Domain: {Name}
6173
+
6174
+ ## Overview
6175
+ {What this domain handles in business terms}
6176
+
6177
+ ## Entry Points
6178
+
6179
+ | Entry | Type | Trigger |
6180
+ |-------|------|---------|
6181
+ | \`{endpoint/command}\` | {http/cli/event/cron/manual} | {what triggers it} |
6182
+
6183
+ ## Entities
6184
+ - **{Entity}**: {description + key attributes}
6185
+
6186
+ ## Business Rules
6187
+ - {rule 1 — e.g., "Passwords must be hashed before storage"}
6188
+ - {rule 2}
6189
+
6190
+ ## Flows
6191
+
6192
+ ### {Flow Name}
6193
+ {What this flow accomplishes}
6194
+
6195
+ **Steps:**
6196
+ 1. {Step 1} — \`{file:function}\` — {what happens}
6197
+ 2. {Step 2} — \`{file:function}\` — {what happens}
6198
+ 3. {Step 3} — \`{file:function}\` — {what happens}
6199
+
6200
+ ### {Flow Name 2}
6201
+ ...
6202
+
6203
+ ## Cross-Domain Interactions
6204
+
6205
+ | This Domain | Direction | Other Domain | Mechanism |
6206
+ |-------------|-----------|--------------|-----------|
6207
+ | {current} | → calls | {other} | {API/event/import} |
6208
+ | {other} | → notifies | {current} | {event/callback} |
6209
+ \`\`\`
6210
+
6211
+ ### Directory Convention
6212
+
6213
+ \`\`\`
6214
+ docs/
6215
+ └── architecture/
6216
+ └── domains/
6217
+ ├── authentication.md
6218
+ ├── billing.md
6219
+ └── inventory.md
6220
+ \`\`\`
6221
+
6222
+ ## Interactive Tour Visualization (React Flow)
6223
+
6224
+ When HTML output is requested for tours or onboarding guides, generate a standalone React Flow HTML file showing the codebase tour as an interactive graph. Nodes represent files/modules, edges show dependencies AND tour progression order.
6225
+
6226
+ ### Tour Graph HTML Template
6227
+
6228
+ \`\`\`html
6229
+ <!DOCTYPE html>
6230
+ <html lang="en">
6231
+ <head>
6232
+ <meta charset="UTF-8"/>
6233
+ <title>{{TOUR_TITLE}} — Codebase Tour</title>
6234
+ <script src="https://unpkg.com/react@18/umd/react.production.min.js"><\/script>
6235
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"><\/script>
6236
+ <script src="https://unpkg.com/@xyflow/react@12/dist/umd/index.js"><\/script>
6237
+ <script src="https://unpkg.com/elkjs@0.9/lib/elk.bundled.js"><\/script>
6238
+ <link rel="stylesheet" href="https://unpkg.com/@xyflow/react@12/dist/style.css"/>
6239
+ <style>
6240
+ body { margin: 0; font-family: system-ui, sans-serif; background: #0f172a; color: #e2e8f0; }
6241
+ .react-flow { width: 100vw; height: 100vh; }
6242
+ .tour-node { padding: 12px 16px; border-radius: 8px; border: 2px solid; min-width: 180px; cursor: pointer; transition: all 0.2s; }
6243
+ .tour-node:hover { transform: scale(1.05); box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
6244
+ .tour-node.active { border-color: #22d3ee; box-shadow: 0 0 20px rgba(34,211,238,0.3); }
6245
+ .tour-node.visited { opacity: 0.7; }
6246
+ .tour-node.upcoming { opacity: 0.5; }
6247
+ .step-number { position: absolute; top: -10px; left: -10px; width: 24px; height: 24px; border-radius: 50%; background: #22d3ee; color: #0f172a; font-size: 12px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
6248
+ .tour-panel { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: #1e293b; border: 1px solid #334155; border-radius: 12px; padding: 16px 24px; max-width: 600px; z-index: 10; }
6249
+ .tour-panel h3 { margin: 0 0 8px; color: #22d3ee; }
6250
+ .tour-panel p { margin: 0; font-size: 14px; line-height: 1.5; }
6251
+ .tour-nav { margin-top: 12px; display: flex; gap: 8px; }
6252
+ .tour-nav button { padding: 6px 16px; border-radius: 6px; border: 1px solid #475569; background: #334155; color: #e2e8f0; cursor: pointer; }
6253
+ .tour-nav button:hover { background: #475569; }
6254
+ .tour-nav button.primary { background: #22d3ee; color: #0f172a; border: none; }
6255
+ </style>
6256
+ </head>
6257
+ <body>
6258
+ <div id="root"></div>
6259
+ <script>
6260
+ const tourSteps = {{TOUR_STEPS_JSON}};
6261
+ const nodes = {{NODES_JSON}};
6262
+ const edges = {{EDGES_JSON}};
6263
+ // Tour logic: highlight active step, show explanation panel, navigate prev/next
6264
+ <\/script>
6265
+ </body>
6266
+ </html>
6267
+ \`\`\`
6268
+
6269
+ ### Tour Node Types
6270
+
6271
+ \`\`\`javascript
6272
+ const tourNodeTypes = {
6273
+ entryPoint: { color: '#22d3ee', icon: '🚀', label: 'Entry Point' },
6274
+ core: { color: '#34d399', icon: '⚙️', label: 'Core Module' },
6275
+ utility: { color: '#a78bfa', icon: '🔧', label: 'Utility' },
6276
+ config: { color: '#fbbf24', icon: '⚙️', label: 'Configuration' },
6277
+ test: { color: '#fb923c', icon: '🧪', label: 'Test' },
6278
+ external: { color: '#94a3b8', icon: '📦', label: 'External Dep' },
6279
+ };
6280
+ \`\`\`
6281
+
6282
+ ### Tour Edge Types
6283
+
6284
+ \`\`\`javascript
6285
+ const tourEdgeTypes = {
6286
+ dependency: { style: 'solid', color: '#475569', animated: false }, // import relationship
6287
+ tourPath: { style: 'solid', color: '#22d3ee', animated: true }, // tour progression
6288
+ dataFlow: { style: 'dashed', color: '#34d399', animated: false }, // data movement
6289
+ };
6290
+ \`\`\`
6291
+
6292
+ ### Tour Step Metadata
6293
+
6294
+ Each tour step node carries:
6295
+ \`\`\`json
6296
+ {
6297
+ "id": "step-1",
6298
+ "file": "src/index.ts",
6299
+ "title": "Application Entry Point",
6300
+ "explanation": "This is where the app bootstraps...",
6301
+ "learnsConcept": "Dependency injection setup",
6302
+ "stepNumber": 1,
6303
+ "layer": "entry",
6304
+ "linesOfInterest": [12, 45, 78],
6305
+ "duration": "2 min"
6306
+ }
6307
+ \`\`\`
6308
+
6309
+ ### SVG Export for Markdown Embedding
6310
+
6311
+ Same pattern as c4-architecture SVG export — iterate tour nodes and edges, generate static SVG showing tour path with numbered steps. Embed in \`docs/tours/*.md\` files.
6312
+
6313
+ ## Documentation Generation Prompts
6314
+
6315
+ Structured LLM prompt templates for generating high-quality documentation. Each produces strict JSON for consistent, parseable output.
6316
+
6317
+ ### Tour Generation Prompt (2-Phase)
6318
+
6319
+ **Phase 1** is deterministic (no LLM needed):
6320
+ \`\`\`
6321
+ # Deterministic Tour Ranking (run BEFORE LLM)
6322
+ 1. graph({ action: "find_nodes" }) → get all module nodes
6323
+ 2. Compute for each node:
6324
+ - in_degree (how many import it) → "importance"
6325
+ - out_degree (how many it imports) → "complexity"
6326
+ - centrality = in_degree / (in_degree + out_degree)
6327
+ 3. Rank by: entry_points FIRST, then by centrality DESC
6328
+ 4. Group by layer (from layer detection)
6329
+ 5. Topological sort within each layer
6330
+ 6. Output: ordered node list with rankings
6331
+ \`\`\`
6332
+
6333
+ **Phase 2** uses LLM with Phase 1 results as context:
6334
+ \`\`\`
6335
+ You are a developer onboarding guide. Given a ranked list of codebase modules with their relationships, generate a guided tour that teaches the system through progressive understanding.
6336
+
6337
+ **Module rankings (from static analysis):**
6338
+ {{RANKED_MODULES_JSON}}
6339
+
6340
+ **Dependency graph (edges):**
6341
+ {{EDGES_JSON}}
6342
+
6343
+ **Detected layers:**
6344
+ {{LAYERS_JSON}}
6345
+
6346
+ **Instructions:**
6347
+ - Create 8-15 tour steps (adjust to codebase size)
6348
+ - Start with entry points and high-level orchestration
6349
+ - Progress to increasingly detailed/specialized modules
6350
+ - Each step should teach ONE concept
6351
+ - Group related files into single steps (max 3 files per step)
6352
+ - End with cross-cutting concerns and extension points
6353
+ - Include estimated reading time per step
6354
+
6355
+ **Respond ONLY with a JSON object:**
6356
+ {
6357
+ "title": "Tour title",
6358
+ "description": "One sentence overview",
6359
+ "estimatedTime": "30 min",
6360
+ "steps": [
6361
+ {
6362
+ "stepNumber": 1,
6363
+ "title": "Step title — concept learned",
6364
+ "files": ["src/index.ts"],
6365
+ "explanation": "2-3 sentences explaining what this teaches",
6366
+ "learnsConcept": "Single concept name",
6367
+ "prerequisites": [],
6368
+ "linesOfInterest": { "src/index.ts": [12, 45] },
6369
+ "duration": "2 min"
6370
+ }
6371
+ ]
6372
+ }
6373
+ \`\`\`
6374
+
6375
+ ### File Documentation Prompt
6376
+
6377
+ \`\`\`
6378
+ You are a technical writer. Document this source file for developer reference.
6379
+
6380
+ **File:** {{FILE_PATH}}
6381
+ **Content:**
6382
+ {{FILE_CONTENT}}
6383
+
6384
+ **Module's role in architecture:** {{MODULE_ROLE}}
6385
+ **Layer:** {{LAYER}}
6386
+
6387
+ **Respond ONLY with a JSON object:**
6388
+ {
6389
+ "title": "Module name — one-line purpose",
6390
+ "overview": "2-3 sentence description of what this module does and why it exists",
6391
+ "publicAPI": [
6392
+ { "name": "functionName", "signature": "typed signature", "description": "what it does", "example": "brief usage" }
6393
+ ],
6394
+ "dependencies": [
6395
+ { "module": "import path", "purpose": "why this dependency" }
6396
+ ],
6397
+ "patterns": ["Pattern names used (e.g., Factory, Observer, Middleware)"],
6398
+ "gotchas": ["Non-obvious behaviors or edge cases"],
6399
+ "relatedModules": ["paths to related files for cross-reference"]
6400
+ }
6401
+ \`\`\`
6402
+
6403
+ ### Domain Documentation Prompt
6404
+
6405
+ \`\`\`
6406
+ You are a domain-driven design analyst. Given files belonging to a business domain, document the domain model.
6407
+
6408
+ **Domain:** {{DOMAIN_NAME}}
6409
+ **Files in this domain:**
6410
+ {{FILE_LIST}}
6411
+
6412
+ **Key file contents (summarized):**
6413
+ {{FILE_SUMMARIES}}
6414
+
6415
+ **Cross-domain relationships:**
6416
+ {{CROSS_DOMAIN_EDGES}}
6417
+
6418
+ **Respond ONLY with a JSON object:**
6419
+ {
6420
+ "domain": "Domain name",
6421
+ "description": "What business capability this domain handles",
6422
+ "ubiquitousLanguage": [
6423
+ { "term": "Term", "definition": "What it means in this context" }
6424
+ ],
6425
+ "entities": [
6426
+ { "name": "Entity", "description": "Role", "keyAttributes": ["attr1", "attr2"] }
6427
+ ],
6428
+ "businessRules": [
6429
+ "Rule 1 description",
6430
+ "Rule 2 description"
6431
+ ],
6432
+ "flows": [
6433
+ { "name": "Flow name", "steps": ["Step 1 → file:fn", "Step 2 → file:fn"], "trigger": "What initiates this" }
6434
+ ],
6435
+ "crossDomainInteractions": [
6436
+ { "direction": "outgoing|incoming", "otherDomain": "Name", "mechanism": "API/event/import", "purpose": "Why" }
6437
+ ]
6438
+ }
6439
+ \`\`\`
6440
+
6441
+ ## Documentation Generation Pipeline
6442
+
6443
+ Orchestrate comprehensive documentation generation using a phased approach (inspired by multi-agent pipeline patterns).
6444
+
6445
+ ### Phase 1 — Inventory (deterministic)
6446
+ \`\`\`
6447
+ # Scan existing docs and detect staleness
6448
+ find({ glob: "docs/**/*.md" }) # Current doc inventory
6449
+ git_context({ include_diff: true }) # Recent changes
6450
+ blast_radius({ files: changedFiles }) # What docs might be stale
6451
+ \`\`\`
6452
+
6453
+ ### Phase 2 — Analyze (deterministic + LLM)
6454
+ \`\`\`
6455
+ # Identify documentation gaps
6456
+ analyze({ aspect: "structure" }) # All modules
6457
+ analyze({ aspect: "entry_points" }) # Tour starting points
6458
+ graph({ action: "find_nodes" }) # Full module graph
6459
+ # For each undocumented module: apply File Documentation Prompt
6460
+ # For each domain cluster: apply Domain Documentation Prompt
6461
+ \`\`\`
6462
+
6463
+ ### Phase 3 — Detect Layers (LLM-assisted)
6464
+ \`\`\`
6465
+ # Classify architecture for tour and domain docs
6466
+ 1. Collect all file paths from structure analysis
6467
+ 2. Apply Layer Detection Prompt (from c4-architecture skill)
6468
+ 3. Inject Framework Addendum for detected framework
6469
+ 4. Output: layers.json used by tour generation
6470
+ \`\`\`
6471
+
6472
+ ### Phase 4 — Generate Tours (2-phase)
6473
+ \`\`\`
6474
+ # Phase 4a: Deterministic ranking
6475
+ 1. Compute node rankings (in-degree, centrality, layer)
6476
+ 2. Topological sort within layers
6477
+ 3. Identify tour start points (entry_points with 0 in-degree)
6478
+
6479
+ # Phase 4b: LLM narrative
6480
+ 1. Apply Tour Generation Prompt with rankings from 4a
6481
+ 2. Generate both Mermaid tour diagram AND React Flow HTML
6482
+ 3. Output: docs/tours/getting-started.md + docs/tours/interactive/
6483
+ \`\`\`
6484
+
6485
+ ### Phase 5 — Generate Domain Docs (LLM-assisted)
6486
+ \`\`\`
6487
+ # For each detected domain/bounded context:
6488
+ 1. Identify files belonging to domain (from layer/cluster analysis)
6489
+ 2. compact() key files for context
6490
+ 3. Apply Domain Documentation Prompt
6491
+ 4. Output: docs/architecture/domains/{domain}.md
6492
+ \`\`\`
6493
+
6494
+ ### Phase 6 — Validate & Cross-Reference
6495
+ \`\`\`
6496
+ # Ensure consistency
6497
+ 1. Check all internal doc links resolve
6498
+ 2. Verify code references still exist (file:line citations)
6499
+ 3. Cross-reference tour steps with actual files
6500
+ 4. check({}) to ensure no build breaks
6501
+ \`\`\`
6502
+
6503
+ ### Output Structure
6504
+ \`\`\`
6505
+ docs/
6506
+ ├── tours/
6507
+ │ ├── getting-started.md # Primary tour (Mermaid diagrams)
6508
+ │ ├── advanced-internals.md # Deep-dive tour
6509
+ │ └── interactive/
6510
+ │ ├── getting-started.html # React Flow interactive tour
6511
+ │ └── advanced-internals.html
6512
+ ├── architecture/
6513
+ │ ├── c4-context.md
6514
+ │ ├── c4-containers.md
6515
+ │ ├── interactive/
6516
+ │ │ ├── overview.html # React Flow architecture
6517
+ │ │ └── per-service.html
6518
+ │ └── domains/
6519
+ │ ├── authentication.md
6520
+ │ └── billing.md
6521
+ ├── reference/
6522
+ │ └── modules/ # Per-module API docs
6523
+ └── guides/
6524
+ └── contributing.md
6525
+ \`\`\`
6526
+
6527
+ ## Framework Context Injection
6528
+
6529
+ When generating documentation for a specific framework, inject framework-specific conventions into LLM prompts to improve generation quality:
6530
+
6531
+ ### Detection
6532
+ \`\`\`
6533
+ # Auto-detect framework from project files:
6534
+ - package.json → "next", "react", "express", "nestjs", "@angular/core"
6535
+ - requirements.txt → "django", "flask", "fastapi"
6536
+ - go.mod → "gin", "fiber", "echo"
6537
+ - Cargo.toml → "actix-web", "axum", "rocket"
6538
+ \`\`\`
6539
+
6540
+ ### Addendum Format
6541
+ \`\`\`markdown
6542
+ ## {{FRAMEWORK}} Documentation Addendum
6543
+ (Injected into documentation prompts when {{FRAMEWORK}} is detected)
6544
+
6545
+ ### Canonical Documentation Structure
6546
+
6547
+ | Path Pattern | Doc Type | Template |
6548
+ |---|---|---|
6549
+ | {{src_pattern}} | {{doc_type}} | {{which template to use}} |
6550
+
6551
+ ### Tour Conventions
6552
+
6553
+ - Tour starts at: {{entry_point_pattern}}
6554
+ - Key learning progression: {{progression}}
6555
+ - Framework-specific concepts to teach: {{concepts}}
6556
+
6557
+ ### Domain Conventions
6558
+
6559
+ - Where domains live: {{domain_path_pattern}}
6560
+ - How domains are bounded: {{boundary_mechanism}}
6561
+ \`\`\`
6562
+
6563
+ ### Example: Next.js Addendum
6564
+ \`\`\`
6565
+ ## Next.js Documentation Addendum
6566
+
6567
+ ### Canonical Documentation Structure
6568
+ | Path Pattern | Doc Type | Template |
6569
+ |---|---|---|
6570
+ | app/layout.tsx | Architecture | Root layout, providers, theme |
6571
+ | app/**/page.tsx | Feature docs | Page-level feature documentation |
6572
+ | app/api/** | API Reference | Endpoint documentation |
6573
+ | lib/** | Reference | Utility/service documentation |
6574
+ | components/** | Component docs | Props, usage examples, variants |
6575
+
6576
+ ### Tour Conventions
6577
+ - Tour starts at: app/layout.tsx (root) → app/page.tsx (home)
6578
+ - Key progression: Layout → Pages → API Routes → Lib → Components
6579
+ - Framework concepts: App Router, Server Components, Server Actions, Middleware
6580
+
6581
+ ### Domain Conventions
6582
+ - Domains live in: app/(domain)/ or features/(domain)/
6583
+ - Bounded by: Route groups or feature folders
6584
+ \`\`\`
6585
+
5695
6586
  ## Rules for the \`_docs-sync\` Epilogue Step
5696
6587
 
5697
6588
  When this skill is loaded during the \`_docs-sync\` epilogue: