@vpxa/aikit 0.1.179 → 0.1.180

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.179",
3
+ "version": "0.1.180",
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",
@@ -317,6 +317,15 @@ Load the \`docs\` skill and generate comprehensive documentation:
317
317
 
318
318
  6. **Persist Knowledge** — \`produce_knowledge({ path: "." })\` + \`knowledge({ action: "remember", ... })\` for key findings
319
319
 
320
+ 7. **AGENTS.md** — Generate an agent-friendly project context file at the repo root:
321
+ - Project overview, architecture style, key modules
322
+ - Build/test/run commands
323
+ - Coding conventions and patterns in use
324
+ - Key entry points and data flows
325
+ - Known concerns and tech debt
326
+
327
+ > **Interactive HTML viewers** (C4 diagrams, code tour walkthroughs) are generated by the \`/aikit-docs-site\` command. Use it after this command to produce interactive explorable documentation.
328
+
320
329
  ### Phase 5: Interactive Presentation
321
330
 
322
331
  Present the understanding as a rich interactive dashboard using \`present\`:
@@ -347,91 +356,209 @@ After all phases complete, present a final summary to the user:
347
356
  - **Mark unknowns** with \`[TODO]\` and intent-dependent decisions with \`[ASK USER]\`
348
357
  - **Delegate to specialists**: architecture diagrams → \`c4-architecture\` skill, ADRs → \`adr-skill\`
349
358
  - **Compress between phases** — use \`digest\` and \`stash\` to manage context
350
- - **🛑 STOP after Phase 5** — present results and ask user for feedback before any follow-up work`},"docs-site":{description:`Generate an interactive HTML documentation site with architecture diagrams, process flows, and component docs`,agent:`Orchestrator`,tools:[`onboard`,`analyze`,`produce_knowledge`,`graph`,`search`,`symbol`,`trace`,`file_summary`,`compact`,`digest`,`knowledge`,`browser`,`present`,`check`,`git_context`,`measure`],content:`## Generate Documentation Site
359
+ - **🛑 STOP after Phase 5** — present results and ask user for feedback before any follow-up work`},"docs-site":{description:`Generate interactive HTML documentation C4 architecture viewers and code tour walkthroughs with browser verification`,agent:`Orchestrator`,tools:[`onboard`,`analyze`,`produce_knowledge`,`graph`,`search`,`symbol`,`trace`,`file_summary`,`compact`,`digest`,`knowledge`,`browser`,`present`,`check`,`git_context`,`measure`],content:`## Generate Interactive Documentation Viewers
360
+
361
+ Create interactive HTML documentation using C4 architecture viewers and code tour walkthroughs.
351
362
 
352
- Create a multi-page HTML documentation site using the DocPage manifest system.
363
+ > **Prerequisite:** Run \`/aikit-docs\` first to generate the base markdown documentation and AGENTS.md.
353
364
 
354
- ### Step 1: Analyze Project
365
+ ### Phase 1: Analyze Project
355
366
 
356
367
  \`\`\`
357
- onboard({ path: "." }) # If not done
358
- analyze({ aspect: "structure", path: "." }) # Directory layout
359
- analyze({ aspect: "dependencies", path: "." }) # Module graph
360
- analyze({ aspect: "entry_points", path: "." }) # API surface
361
- analyze({ aspect: "diagram", path: "." }) # Architecture diagram data
368
+ onboard({ path: "." }) # If not done (check status() first)
369
+ analyze({ aspect: "structure", path: "." }) # Directory layout
370
+ analyze({ aspect: "dependencies", path: "." }) # Module graph
371
+ analyze({ aspect: "entry_points", path: "." }) # API surface
372
+ analyze({ aspect: "diagram", path: "." }) # Architecture diagram data
373
+ graph({ action: "find_nodes" }) # Module graph for C4 mapping
374
+ graph({ action: "detect_communities" }) # Natural module clusters
362
375
  \`\`\`
363
376
 
364
- ### Step 2: Determine Pages
377
+ Stash results for use in subsequent phases.
365
378
 
366
- Based on analysis, determine which pages the site needs:
379
+ ### Phase 2: Generate C4 Architecture Data
367
380
 
368
- | Kind | When to include |
369
- |------|-----------------|
370
- | architecture | Always — C4 context + container diagrams |
371
- | process-flow | When the project has workflows, pipelines, or multi-step processes |
372
- | tour | When the project has >5 modules — guided onboarding walkthrough |
373
- | docs-hub | Always — landing page linking all other pages |
374
- | component-detail | For each major module/service (>3 exports) |
375
- | lifecycle-flow | For request lifecycles, event pipelines, build processes |
376
- | data-table-schema | For database schemas, API contracts, config structures |
377
- | report | For metrics dashboards, health reports |
381
+ Create C4 JSON data files for each architectural level. Save to \`docs/architecture/interactive/\`.
378
382
 
379
- ### Step 3: Build Manifest
380
-
381
- Create a DocPage manifest JSON:
383
+ **Required schema MUST match exactly:**
382
384
 
383
385
  \`\`\`json
384
386
  {
385
- "schemaVersion": 1,
386
- "metadata": {
387
- "title": "<Project Name> Documentation",
388
- "description": "Auto-generated documentation site",
389
- "version": "1.0.0",
390
- "generatedAt": "<ISO timestamp>"
391
- },
392
- "pages": [
387
+ "title": "Project Name - C4 Level",
388
+ "description": "What this diagram shows",
389
+ "layout": { "direction": "DOWN", "spacing": 80, "layerSpacing": 120 },
390
+ "nodes": [
393
391
  {
394
- "kind": "docs-hub",
395
- "renderer": "report-template",
396
- "filename": "index.html",
397
- "title": "Documentation Hub",
398
- "payload": { /* docs-hub block data */ }
399
- },
392
+ "id": "unique-string-id",
393
+ "type": "person|system|container|component|database|queue|external",
394
+ "label": "Display Name",
395
+ "description": "What this element does",
396
+ "technology": "Language/framework",
397
+ "parentId": "optional-boundary-id"
398
+ }
399
+ ],
400
+ "edges": [
401
+ {
402
+ "id": "unique-edge-id",
403
+ "source": "source-node-id",
404
+ "target": "target-node-id",
405
+ "label": "Relationship description",
406
+ "technology": "Protocol/transport"
407
+ }
408
+ ]
409
+ }
410
+ \`\`\`
411
+
412
+ **C4 levels to generate:**
413
+ 1. \`system-context.json\` — External actors + the system as a black box
414
+ 2. \`containers.json\` — Major deployable units (services, databases, frontends)
415
+ 3. \`{component-name}-components.json\` — Internal structure of key containers
416
+
417
+ **Critical rules:**
418
+ - Top-level keys are \`nodes\` and \`edges\` (NOT \`elements\`/\`relationships\`)
419
+ - Every edge MUST have a unique \`id\` field (ELK crashes without it)
420
+ - Node \`type\` MUST be one of: person, system, container, component, database, queue, external
421
+ - \`layout.direction\` MUST be: DOWN, UP, LEFT, or RIGHT
422
+ - \`parentId\` references must point to existing node IDs (or omit entirely)
423
+
424
+ ### Phase 3: Generate Tour Data
425
+
426
+ Create code tour JSON files. Save to \`docs/tours/interactive/\`.
427
+
428
+ **Required schema — MUST match exactly:**
429
+
430
+ \`\`\`json
431
+ {
432
+ "title": "Tour Title",
433
+ "description": "What this tour teaches",
434
+ "estimatedTime": "15 min",
435
+ "steps": [
400
436
  {
401
- "kind": "architecture",
402
- "renderer": "canvas",
403
- "filename": "architecture.html",
404
- "title": "System Architecture",
405
- "payload": { /* C4 nodes + edges */ }
437
+ "stepNumber": 1,
438
+ "id": "kebab-case-step-id",
439
+ "title": "Step Title",
440
+ "file": "relative/path/to/file.ts",
441
+ "line": 42,
442
+ "explanation": "What this code does and why it matters",
443
+ "learnsConcept": "Concept name",
444
+ "duration": "2 min",
445
+ "notes": "Optional additional context"
406
446
  }
407
- // ... more pages based on Step 2
408
447
  ],
409
- "navigation": [
410
- { "label": "Home", "href": "index.html", "icon": "🏠" },
411
- { "label": "Architecture", "href": "architecture.html", "icon": "🏗️", "category": "Technical" }
412
- // ... matching pages
448
+ "dependencies": [
449
+ { "source": "step-id-1", "target": "step-id-2" }
413
450
  ]
414
451
  }
415
452
  \`\`\`
416
453
 
417
- ### Step 4: Generate Site
454
+ **Tours to generate:**
455
+ 1. \`architecture-overview.json\` — High-level system walkthrough (entry points → core logic → outputs)
456
+ 2. \`onboarding.json\` — New developer guided tour (most important files in dependency order)
457
+ 3. Additional tours for complex subsystems with >5 modules
458
+
459
+ **Critical rules:**
460
+ - Step content field is \`explanation\` (NOT \`description\`)
461
+ - Every step needs \`id\` (kebab-case) and \`stepNumber\` (integer, 1-based)
462
+ - \`learnsConcept\` is the concept tag (NOT \`highlights\`)
463
+ - \`dependencies\` array uses step \`id\` values in \`{source, target}\` objects
464
+ - Root MUST have \`title\`, \`description\`, \`estimatedTime\`
465
+
466
+ ### Phase 4: Inject Data into HTML Templates
418
467
 
419
- Write the manifest to a temp file, then invoke:
468
+ Use PowerShell to inject JSON data into the viewer template HTML files.
420
469
 
470
+ **Template locations:**
471
+ - C4 viewer: \`C:\\Users\\AnVPX\\.copilot\\skills\\c4-architecture\\assets\\c4-viewer.html\` (tag: \`id="diagram-data"\`)
472
+ - Tour viewer: \`C:\\Users\\AnVPX\\.copilot\\skills\\docs\\assets\\tour-viewer.html\` (tag: \`id="tour-data"\`)
473
+
474
+ **Injection procedure (for EACH JSON file):**
475
+
476
+ \`\`\`powershell
477
+ $template = [System.IO.File]::ReadAllText("TEMPLATE_PATH")
478
+ $startTag = '<script type="application/json" id="TARGET_ID">'
479
+ $startIdx = $template.IndexOf($startTag)
480
+ if ($startIdx -lt 0) { throw "Tag not found" }
481
+ $contentStart = $startIdx + $startTag.Length
482
+ $endIdx = $template.IndexOf('<\/script>', $contentStart)
483
+
484
+ $before = $template.Substring(0, $contentStart)
485
+ $after = $template.Substring($endIdx)
486
+ $data = Get-Content "JSON_PATH" -Raw
487
+
488
+ $output = $before + [char]10 + $data + [char]10 + $after
489
+ [System.IO.File]::WriteAllText("OUTPUT_PATH", $output, [System.Text.Encoding]::UTF8)
490
+ \`\`\`
491
+
492
+ **Output file layout:**
421
493
  \`\`\`
422
- run_in_terminal("node packages/viewers/inject-viewer.mjs --manifest manifest.json --out docs/site/")
494
+ docs/
495
+ architecture/interactive/
496
+ system-context.json # Data
497
+ system-context.html # Injected viewer (from c4-viewer.html)
498
+ containers.json
499
+ containers.html
500
+ tours/interactive/
501
+ architecture-overview.json # Data
502
+ architecture-overview.html # Injected viewer (from tour-viewer.html)
503
+ onboarding.json
504
+ onboarding.html
423
505
  \`\`\`
424
506
 
425
- ### Step 5: Verify & Present
507
+ **Rules:**
508
+ - JSON + HTML MUST be siblings in the same \`interactive/\` directory
509
+ - NEVER use \`inject-viewer.mjs\` — use the PowerShell procedure above
510
+ - Verify \`$startIdx -ge 0\` before proceeding
426
511
 
427
- - Check all output files exist in \`docs/site/\`
428
- - Open the hub page: \`browser({ action: 'open', url: 'file:///path/to/docs/site/index.html' })\`
429
- - Present a summary of generated pages
512
+ ### Phase 5: Browser Verification (MANDATORY)
430
513
 
431
- ### Rules
514
+ **Every generated HTML file MUST be tested before presenting to user.**
515
+
516
+ \`\`\`
517
+ # 1. Serve the docs folder
518
+ run_in_terminal("npx -y serve docs -l 4000 --no-clipboard", mode: "async")
519
+
520
+ # 2. Open each viewer
521
+ browser({ action: 'open', url: 'http://localhost:4000/architecture/interactive/system-context.html', mode: 'ui', waitUntil: 'networkidle' })
522
+
523
+ # 3. Read accessibility snapshot
524
+ browser({ action: 'read', pageId: '<id>', readMode: 'snapshot' })
525
+
526
+ # 4. Verify content renders:
527
+ # C4: nodes with labels, edges, Zoom In/Out/Fit buttons, Mini Map
528
+ # Tour: step numbers + titles, Prev/Next buttons, explanation text, file paths
529
+
530
+ # 5. If blank or errors → fix JSON schema → re-inject → re-test
531
+
532
+ # 6. Clean up
533
+ browser({ action: 'session', sessionAction: 'close', pageId: '<id>' })
534
+ kill_terminal(<serve-terminal-id>)
535
+ \`\`\`
536
+
537
+ **Verification checklist:**
538
+
539
+ | Viewer | Must see in snapshot | Failure indicator |
540
+ |--------|---------------------|-------------------|
541
+ | C4 | Node labels, edge groups, Zoom/Fit buttons, Mini Map | Empty page, "Error", no nodes |
542
+ | Tour | Step numbers + titles, Prev/Next, explanation text | Blank panel, "undefined", no steps |
543
+
544
+ ### Phase 6: Present Results
545
+
546
+ After ALL viewers pass verification:
547
+
548
+ 1. List all generated files (JSON + HTML) with descriptions
549
+ 2. Provide the serve command: \`npx -y serve docs -l 4000 --no-clipboard\`
550
+ 3. List all viewer URLs (e.g., \`http://localhost:4000/architecture/interactive/system-context.html\`)
551
+ 4. Note any issues found during verification
552
+
553
+ ### Critical Rules
432
554
 
433
- - All page data must come from AI Kit analysis tools never fabricate
434
- - Architecture diagrams must follow C4 model conventions
435
- - Process flows must use the correct node types (start-end, manual, automated, integration, decision, prerequisite)
436
- - Every page in the manifest must have a corresponding navigation entry
437
- - Use \`knowledge({ action: "remember" })\` to persist the manifest for incremental updates`}};export{e as PROMPTS};
555
+ 1. **NEVER skip browser verification** a valid JSON can still produce a broken viewer
556
+ 2. **NEVER use \`file:///\` URLs** CORS blocks ES modules; always serve via HTTP
557
+ 3. **NEVER use \`inject-viewer.mjs\`** use the PowerShell injection procedure
558
+ 4. **NEVER use \`elements\`/\`relationships\`** the ReactFlow viewer uses \`nodes\`/\`edges\`
559
+ 5. **NEVER omit \`id\` on edges** ELK layout throws null errors
560
+ 6. **NEVER use \`description\` in tour steps** — template reads \`explanation\`
561
+ 7. **ALWAYS use \`npx -y\`** — without \`-y\` the command hangs on install prompt
562
+ 8. **ALWAYS include \`layout\` object in C4 JSON** — ELK crashes without direction/spacing
563
+ 9. **ALWAYS verify \`$startIdx -ge 0\`** before injection — missing tag = wrong template
564
+ 10. **All data must come from AI Kit analysis tools** — never fabricate architecture`}};export{e as PROMPTS};
@@ -45,7 +45,7 @@ function parseArgs(argv) {
45
45
  }
46
46
 
47
47
  function escapeRegExp(value) {
48
- return value.replace(/[|\\{}()[]^$+*?.]/g, '\\$&');
48
+ return value.replace(/[|\\\\{}()\\[\\]^$+*?.]/g, '\\\\$&');
49
49
  }
50
50
 
51
51
  function buildScriptPattern(id) {
@@ -1497,7 +1497,7 @@ Before finalizing any C4 diagram, verify:
1497
1497
  - [ ] Message topics shown individually (not as single broker)
1498
1498
  - [ ] No infrastructure details in container diagrams
1499
1499
  - [ ] Consistent with other diagrams in the set
1500
- `},{file:`references/html-design-system.md`,content:'# HTML/SVG Architecture Diagram Design System\n\nThis file is the centralized design system for HTML and SVG architecture diagrams.\n\nIt is the single source of truth for visual tokens, component categories, layout rules, and `present` tool composition guidance used by the `c4-architecture` skill and the `present` skill. Update component types, colors, layout rules, and icon slots here only.\n\n## Purpose\n\n- Define a reusable visual language for C4-style architecture diagrams rendered as HTML and inline SVG.\n- Keep category styling extensible through a registry instead of hardcoded component types.\n- Standardize diagram composition for both skill-authored documentation and `present` output.\n\n## Core Design Tokens\n\n### Typography\n\n- Font family: `"JetBrains Mono", monospace`\n- Font source: Google Fonts (`https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap`)\n- Component names: `12px`\n- Sublabels: `9px`\n- Annotations: `8px`\n- Tiny labels: `7px`\n- Legend: `10px`\n- Icon area labels: `11px`\n\n### Background\n\n- Page background: `#020617` (`slate-950`)\n- Background pattern: inline SVG grid pattern over the page background\n- Recommended grid line colors:\n - Major grid: `rgba(148, 163, 184, 0.08)`\n - Minor grid: `rgba(148, 163, 184, 0.04)`\n\n### Component Box Defaults\n\n- Shape: rounded rectangle\n- Border radius: `rx="6"`\n- Stroke width: `1.5px`\n- Fill: category-specific semi-transparent RGBA fill\n- Stroke: category-specific hex stroke\n- Label stack:\n - Line 1: C4 label such as `<<Container>>`\n - Line 2: component name\n - Line 3: subtype or technology summary\n\n## Category Registry\n\nThe registry is hierarchical: categories define shared tokens and C4 intent, while sub-types inherit the category styling and reserve an icon slot for future SVG glyphs.\n\n| Category | Stroke Color | Fill Color | C4 Mapping | Sub-types |\n|---|---|---|---|---|\n| Frontend | `#22d3ee` | `rgba(8, 51, 68, 0.4)` | Container (SPA, web) | SPA, Mobile App, Static Site, Micro-frontend, PWA, Desktop App |\n| Backend | `#34d399` | `rgba(6, 78, 59, 0.4)` | Container (service) | API Service, Worker/Job, BFF, Microservice, Serverless Function, gRPC Service |\n| Data | `#a78bfa` | `rgba(76, 29, 149, 0.4)` | ContainerDb | Relational DB, Document DB, Key-Value Store, Cache, Search Engine, Data Warehouse, Graph DB, Time-Series DB |\n| Infrastructure | `#fbbf24` | `rgba(120, 53, 15, 0.3)` | Deployment_Node | CDN, Load Balancer, DNS, Object Storage, Container Registry, Reverse Proxy, Service Mesh |\n| Messaging | `#fb923c` | `rgba(251, 146, 60, 0.3)` | ContainerQueue | Message Queue, Event Bus, Stream, Pub/Sub, Webhook |\n| Security | `#fb7185` | `rgba(136, 19, 55, 0.4)` | System_Ext / boundary | Auth Provider, API Gateway, WAF, Secret Manager, Certificate Manager, Identity Provider |\n| External | `#94a3b8` | `rgba(30, 41, 59, 0.5)` | System_Ext | Third-party API, SaaS, Legacy System, Partner Service, Payment Provider |\n| Monitoring | `#38bdf8` | `rgba(12, 74, 110, 0.4)` | Container | Logging, Metrics, Tracing, Alerting, APM |\n\n## Sub-type Registry\n\nEach sub-type inherits its category tokens and keeps a placeholder slot for an inline SVG icon.\n\n| Category | Sub-type | C4 Label | Icon Slot |\n|---|---|---|---|\n| Frontend | SPA | `<<Container>>` | `icon-spa` |\n| Frontend | Mobile App | `<<Container>>` | `icon-mobile-app` |\n| Frontend | Static Site | `<<Container>>` | `icon-static-site` |\n| Frontend | Micro-frontend | `<<Container>>` | `icon-micro-frontend` |\n| Frontend | PWA | `<<Container>>` | `icon-pwa` |\n| Frontend | Desktop App | `<<Container>>` | `icon-desktop-app` |\n| Backend | API Service | `<<Container>>` | `icon-api-service` |\n| Backend | Worker/Job | `<<Container>>` | `icon-worker-job` |\n| Backend | BFF | `<<Container>>` | `icon-bff` |\n| Backend | Microservice | `<<Container>>` | `icon-microservice` |\n| Backend | Serverless Function | `<<Container>>` | `icon-serverless-function` |\n| Backend | gRPC Service | `<<Container>>` | `icon-grpc-service` |\n| Data | Relational DB | `<<ContainerDb>>` | `icon-relational-db` |\n| Data | Document DB | `<<ContainerDb>>` | `icon-document-db` |\n| Data | Key-Value Store | `<<ContainerDb>>` | `icon-key-value-store` |\n| Data | Cache | `<<ContainerDb>>` | `icon-cache` |\n| Data | Search Engine | `<<ContainerDb>>` | `icon-search-engine` |\n| Data | Data Warehouse | `<<ContainerDb>>` | `icon-data-warehouse` |\n| Data | Graph DB | `<<ContainerDb>>` | `icon-graph-db` |\n| Data | Time-Series DB | `<<ContainerDb>>` | `icon-time-series-db` |\n| Infrastructure | CDN | `<<Deployment_Node>>` | `icon-cdn` |\n| Infrastructure | Load Balancer | `<<Deployment_Node>>` | `icon-load-balancer` |\n| Infrastructure | DNS | `<<Deployment_Node>>` | `icon-dns` |\n| Infrastructure | Object Storage | `<<Deployment_Node>>` | `icon-object-storage` |\n| Infrastructure | Container Registry | `<<Deployment_Node>>` | `icon-container-registry` |\n| Infrastructure | Reverse Proxy | `<<Deployment_Node>>` | `icon-reverse-proxy` |\n| Infrastructure | Service Mesh | `<<Deployment_Node>>` | `icon-service-mesh` |\n| Messaging | Message Queue | `<<ContainerQueue>>` | `icon-message-queue` |\n| Messaging | Event Bus | `<<ContainerQueue>>` | `icon-event-bus` |\n| Messaging | Stream | `<<ContainerQueue>>` | `icon-stream` |\n| Messaging | Pub/Sub | `<<ContainerQueue>>` | `icon-pub-sub` |\n| Messaging | Webhook | `<<ContainerQueue>>` | `icon-webhook` |\n| Security | Auth Provider | `<<System_Ext>>` | `icon-auth-provider` |\n| Security | API Gateway | `<<System_Ext>>` | `icon-api-gateway` |\n| Security | WAF | `<<System_Ext>>` | `icon-waf` |\n| Security | Secret Manager | `<<System_Ext>>` | `icon-secret-manager` |\n| Security | Certificate Manager | `<<System_Ext>>` | `icon-certificate-manager` |\n| Security | Identity Provider | `<<System_Ext>>` | `icon-identity-provider` |\n| External | Third-party API | `<<System_Ext>>` | `icon-third-party-api` |\n| External | SaaS | `<<System_Ext>>` | `icon-saas` |\n| External | Legacy System | `<<System_Ext>>` | `icon-legacy-system` |\n| External | Partner Service | `<<System_Ext>>` | `icon-partner-service` |\n| External | Payment Provider | `<<System_Ext>>` | `icon-payment-provider` |\n| Monitoring | Logging | `<<Container>>` | `icon-logging` |\n| Monitoring | Metrics | `<<Container>>` | `icon-metrics` |\n| Monitoring | Tracing | `<<Container>>` | `icon-tracing` |\n| Monitoring | Alerting | `<<Container>>` | `icon-alerting` |\n| Monitoring | APM | `<<Container>>` | `icon-apm` |\n\n## Icon Registry\n\nIcons are inline SVG `<symbol>` elements with a 16x16 viewBox, rendered via `<use>` at `(x+W-22, y+4)` inside the component box. They use `currentColor` to inherit the category stroke color.\n\n### Category-Level Icons (active)\n\nEach category has a shared icon defined in `html-template.html` `<defs>`. All sub-types within a category use their category icon by default. Sub-type-specific icons can override these in the future.\n\n| Category | Symbol ID | Shape | Status |\n|---|---|---|---|\n| Frontend | `icon-frontend` | Monitor with stand | **active** |\n| Backend | `icon-backend` | Server rack (3 units) | **active** |\n| Data | `icon-data` | Database cylinder | **active** |\n| Infrastructure | `icon-infrastructure` | Cloud | **active** |\n| Messaging | `icon-messaging` | Envelope | **active** |\n| Security | `icon-security` | Shield with checkmark | **active** |\n| External | `icon-external` | Globe with meridians | **active** |\n| Monitoring | `icon-monitoring` | Line chart with axes | **active** |\n\nUsage pattern:\n```svg\n<use href="#icon-frontend" class="icon-use" x="448" y="154" width="16" height="16"/>\n```\n\n### Sub-type Icons (planned)\n\nWhen a sub-type icon is added, it overrides the category icon for that specific component. Until implemented, all sub-types use their category icon.\n\n| Sub-type | Icon | Status |\n|---|---|---|\n| SPA | `icon-spa` | planned |\n| Mobile App | `icon-mobile-app` | planned |\n| Static Site | `icon-static-site` | planned |\n| Micro-frontend | `icon-micro-frontend` | planned |\n| PWA | `icon-pwa` | planned |\n| Desktop App | `icon-desktop-app` | planned |\n| API Service | `icon-api-service` | planned |\n| Worker/Job | `icon-worker-job` | planned |\n| BFF | `icon-bff` | planned |\n| Microservice | `icon-microservice` | planned |\n| Serverless Function | `icon-serverless-function` | planned |\n| gRPC Service | `icon-grpc-service` | planned |\n| Relational DB | `icon-relational-db` | planned |\n| Document DB | `icon-document-db` | planned |\n| Key-Value Store | `icon-key-value-store` | planned |\n| Cache | `icon-cache` | planned |\n| Search Engine | `icon-search-engine` | planned |\n| Data Warehouse | `icon-data-warehouse` | planned |\n| Graph DB | `icon-graph-db` | planned |\n| Time-Series DB | `icon-time-series-db` | planned |\n| CDN | `icon-cdn` | planned |\n| Load Balancer | `icon-load-balancer` | planned |\n| DNS | `icon-dns` | planned |\n| Object Storage | `icon-object-storage` | planned |\n| Container Registry | `icon-container-registry` | planned |\n| Reverse Proxy | `icon-reverse-proxy` | planned |\n| Service Mesh | `icon-service-mesh` | planned |\n| Message Queue | `icon-message-queue` | planned |\n| Event Bus | `icon-event-bus` | planned |\n| Stream | `icon-stream` | planned |\n| Pub/Sub | `icon-pub-sub` | planned |\n| Webhook | `icon-webhook` | planned |\n| Auth Provider | `icon-auth-provider` | planned |\n| API Gateway | `icon-api-gateway` | planned |\n| WAF | `icon-waf` | planned |\n| Secret Manager | `icon-secret-manager` | planned |\n| Certificate Manager | `icon-certificate-manager` | planned |\n| Identity Provider | `icon-identity-provider` | planned |\n| Third-party API | `icon-third-party-api` | planned |\n| SaaS | `icon-saas` | planned |\n| Legacy System | `icon-legacy-system` | planned |\n| Partner Service | `icon-partner-service` | planned |\n| Payment Provider | `icon-payment-provider` | planned |\n| Logging | `icon-logging` | planned |\n| Metrics | `icon-metrics` | planned |\n| Tracing | `icon-tracing` | planned |\n| Alerting | `icon-alerting` | planned |\n| APM | `icon-apm` | planned |\n\n## Technology Icon Registry\n\nThe HTML C4 viewer also supports technology-specific SVG icons. It resolves them from each node\'s `technology` field after normalization. Set `icon` on node data when you need an explicit override; `icon` takes precedence over auto-detection from `technology`. If neither `icon` nor a normalized `technology` value matches a registry key, the viewer falls back to the generic C4 type icon for that node, such as person, database, queue, or container.\n\n### Available Keys\n\n- **Cloud:** `aws`, `azure`, `googlecloud`, `cloudflare`, `vercel`, `netlify`\n- **Languages:** `typescript`, `javascript`, `python`, `java`, `go`, `rust`, `csharp`, `php`, `ruby`, `swift`, `kotlin`\n- **Frontend:** `react`, `vuedotjs`, `angular`, `svelte`, `nextdotjs`, `html5`, `css3`\n- **Backend:** `nodedotjs`, `express`, `nestjs`, `django`, `spring`, `dotnet`\n- **Data:** `postgresql`, `mysql`, `mongodb`, `redis`, `elasticsearch`, `amazondynamodb`, `sqlite`\n- **Infrastructure:** `docker`, `kubernetes`, `nginx`, `linux`, `terraform`, `github`\n- **Messaging/API:** `apachekafka`, `rabbitmq`, `graphql`, `grpc`\n\n### Common Aliases\n\nCommon aliases are normalized before lookup. For example: `node` -> `nodedotjs`, `postgres` -> `postgresql`, `k8s` -> `kubernetes`, `vue` -> `vuedotjs`, `next.js` -> `nextdotjs`, `mongo` -> `mongodb`, `kafka` -> `apachekafka`, `gcp` -> `googlecloud`, `c#` -> `csharp`, and `.net` -> `dotnet`.\n\n## Visual Elements\n\n### Component Box Pattern\n\nUse a rounded component box with semi-transparent fill and category stroke.\n\n```svg\n<g class="node backend">\n <rect x="280" y="210" width="190" height="60" rx="6" />\n <text class="c4-tag" x="294" y="226">&lt;&lt;Container&gt;&gt;</text>\n <text class="node-title" x="294" y="243">API Service</text>\n <text class="node-subtitle" x="294" y="257">Backend / HTTPS JSON</text>\n</g>\n```\n\n### Arrow Masking Technique\n\nUse an opaque background rectangle below the box content to visually hide arrows beneath components without breaking the component fill style.\n\n```svg\n<g class="node-mask-layer">\n <rect x="280" y="210" width="190" height="60" rx="6" fill="#020617" />\n <rect x="280" y="210" width="190" height="60" rx="6"\n fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" />\n</g>\n```\n\n### Security Group Boundary\n\n- Purpose: show auth, gateway, WAF, or identity zones\n- Stroke color: rose (`#fb7185`)\n- Pattern: `stroke-dasharray="4,4"`\n- Suggested label: `Security Boundary`\n\n```svg\n<rect x="700" y="140" width="220" height="180" rx="12"\n fill="transparent" stroke="#fb7185" stroke-width="1.5"\n stroke-dasharray="4,4" />\n```\n\n### Region Boundary\n\n- Purpose: group a deployment region, platform segment, or domain slice\n- Stroke color: amber (`#fbbf24`)\n- Pattern: `stroke-dasharray="8,4"`\n- Radius: `rx="12"`\n\n```svg\n<rect x="70" y="120" width="600" height="430" rx="12"\n fill="transparent" stroke="#fbbf24" stroke-width="1.5"\n stroke-dasharray="8,4" />\n```\n\n### Arrow Marker SVG Definition\n\n```svg\n<defs>\n <marker id="arrowhead" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">\n <path d="M0,0 L8,4 L0,8 Z" fill="#cbd5e1" />\n </marker>\n</defs>\n```\n\n### Arrow Z-order Rule\n\nDraw arrows early in the SVG so component boxes and masking layers paint over them. This keeps connectors readable in dense diagrams and avoids arrow overlap across component interiors.\n\n## Spacing Rules\n\n- Standard component height: `60px`\n- Minimum vertical gap between stacked components: `40px`\n- Inline connectors should route through gaps rather than through component interiors\n- Keep labels inside the top `28px` of the box and the subtype line inside the lower third\n- Place legends outside boundaries to prevent classification noise inside the diagram area\n\n## Layout Structure\n\nThe canonical page composition is:\n\n1. Header: title, pulse dot, subtitle\n2. Main SVG diagram: embedded inside a rounded border card\n3. Summary cards: grid of 3 cards beneath the diagram\n4. Footer metadata: generator, scope, rendering notes, last-updated stamp\n\n## Present Tool Integration\n\nCompose architecture diagrams with the `present` tool by embedding the full HTML/SVG diagram in a markdown block and pairing it with metrics or cards blocks as needed.\n\n### `format: "html"`\n\nUse a `markdown` block with embedded `<div>`, inline SVG, and a `<style>` tag containing the full CSS. The `present` html format renders raw HTML in markdown blocks.\n\n### `format: "browser"`\n\nUse the same composition: a `markdown` block containing the full HTML structure. Summary content can also be added with `cards` and `metrics` blocks alongside the SVG diagram block.\n\n### Example `present` Call Structure\n\n```js\npresent({\n format: "html", // or "browser"\n title: "System Architecture",\n content: [\n {\n type: "metrics",\n title: "Overview",\n value: [\n { label: "Services", value: "6" },\n { label: "Data Stores", value: "2" },\n { label: "External Systems", value: "3" }\n ]\n },\n {\n type: "markdown",\n title: "Architecture Diagram",\n value: "<div class=\'arch-diagram\'>...(inline SVG)...</div><style>...(design system CSS)...</style>"\n },\n {\n type: "cards",\n title: "Summary",\n value: [\n { title: "Frontend", body: "React SPA..." },\n { title: "Backend", body: "API + async workers..." },\n { title: "Security", body: "Gateway + IdP..." }\n ]\n }\n ]\n})\n```\n\nThis design system is the single source of truth. The `c4-architecture` skill and `present` skill both reference this file. Update component types, colors, or layout rules here only.\n\n## Adding New Categories\n\n1. Add a new row to the Category Registry with the category name, colors, C4 mapping, and initial subtype set.\n2. Add the new sub-types to the Sub-type Registry with a C4 label and icon slot name.\n3. Add icon placeholders to the Icon Registry.\n4. Update [html-template.html](html-template.html) legend content so the new category appears in the rendered template.\n5. Update summary card accent colors in [html-template.html](html-template.html) if the new category needs a dedicated card treatment.\n\n## Template Pairing\n\nSee [html-template.html](html-template.html) for the complete self-contained reference implementation of this design system.\n'},{file:`references/c4.schema.json`,content:JSON.stringify({$schema:`http://json-schema.org/draft-07/schema#`,title:`AIKIT Architecture Diagram`,description:`Schema for AI Kit C4 interactive architecture diagrams. The agent generates JSON matching this schema, which is injected into c4-viewer.html.`,version:`1.0.0`,type:`object`,required:[`title`,`type`,`nodes`,`edges`],properties:{title:{type:`string`,description:`Diagram title displayed in the viewer header`},description:{type:`string`,description:`Brief diagram description`},type:{type:`string`,enum:[`context`,`container`,`component`,`deployment`],description:`C4 diagram level`},layout:{type:`object`,properties:{direction:{type:`string`,enum:[`TB`,`LR`,`BT`,`RL`],default:`TB`},spacing:{type:`number`,default:80},layerSpacing:{type:`number`,default:120}}},nodes:{type:`array`,items:{type:`object`,required:[`id`,`type`,`label`],properties:{id:{type:`string`,description:`Unique node identifier`},type:{type:`string`,enum:[`person`,`system`,`container`,`component`,`database`,`queue`,`external`,`boundary`,`deploymentNode`],description:`C4 element type - determines visual styling`},label:{type:`string`,description:`Display label`},technology:{type:`string`,description:`Technology tag used for display and icon auto-resolution (e.g., 'React', 'PostgreSQL')`},icon:{type:`string`,description:`Optional icon override key. Takes precedence over auto-detection from the technology field. Use Technology Icon Registry keys such as 'react', 'postgresql', or 'docker'.`},description:{type:`string`,description:`Element description shown on hover/expand`},children:{type:`array`,items:{type:`string`},description:`Child node IDs (for boundary/group nodes only)`},x:{type:`number`,description:`Optional fixed x position`},y:{type:`number`,description:`Optional fixed y position`}}}},edges:{type:`array`,items:{type:`object`,required:[`source`,`target`],properties:{id:{type:`string`,description:`Optional edge identifier`},source:{type:`string`,description:`Source node ID`},target:{type:`string`,description:`Target node ID`},label:{type:`string`,description:`Relationship label`},technology:{type:`string`,description:`Protocol/technology (e.g., 'REST/HTTPS')`},style:{type:`string`,enum:[`solid`,`dashed`,`dotted`],default:`solid`},animated:{type:`boolean`,default:!1,description:`Animate the edge (for async/event flows)`}}}}}},null,2)},{file:`SKILL.md`,content:`---
1500
+ `},{file:`references/html-design-system.md`,content:'# HTML/SVG Architecture Diagram Design System\n\nThis file is the centralized design system for HTML and SVG architecture diagrams.\n\nIt is the single source of truth for visual tokens, component categories, layout rules, and `present` tool composition guidance used by the `c4-architecture` skill and the `present` skill. Update component types, colors, layout rules, and icon slots here only.\n\n## Purpose\n\n- Define a reusable visual language for C4-style architecture diagrams rendered as HTML and inline SVG.\n- Keep category styling extensible through a registry instead of hardcoded component types.\n- Standardize diagram composition for both skill-authored documentation and `present` output.\n\n## Core Design Tokens\n\n### Typography\n\n- Font family: `"JetBrains Mono", monospace`\n- Font source: Google Fonts (`https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap`)\n- Component names: `12px`\n- Sublabels: `9px`\n- Annotations: `8px`\n- Tiny labels: `7px`\n- Legend: `10px`\n- Icon area labels: `11px`\n\n### Background\n\n- Page background: `#020617` (`slate-950`)\n- Background pattern: inline SVG grid pattern over the page background\n- Recommended grid line colors:\n - Major grid: `rgba(148, 163, 184, 0.08)`\n - Minor grid: `rgba(148, 163, 184, 0.04)`\n\n### Component Box Defaults\n\n- Shape: rounded rectangle\n- Border radius: `rx="6"`\n- Stroke width: `1.5px`\n- Fill: category-specific semi-transparent RGBA fill\n- Stroke: category-specific hex stroke\n- Label stack:\n - Line 1: C4 label such as `<<Container>>`\n - Line 2: component name\n - Line 3: subtype or technology summary\n\n## Category Registry\n\nThe registry is hierarchical: categories define shared tokens and C4 intent, while sub-types inherit the category styling and reserve an icon slot for future SVG glyphs.\n\n| Category | Stroke Color | Fill Color | C4 Mapping | Sub-types |\n|---|---|---|---|---|\n| Frontend | `#22d3ee` | `rgba(8, 51, 68, 0.4)` | Container (SPA, web) | SPA, Mobile App, Static Site, Micro-frontend, PWA, Desktop App |\n| Backend | `#34d399` | `rgba(6, 78, 59, 0.4)` | Container (service) | API Service, Worker/Job, BFF, Microservice, Serverless Function, gRPC Service |\n| Data | `#a78bfa` | `rgba(76, 29, 149, 0.4)` | ContainerDb | Relational DB, Document DB, Key-Value Store, Cache, Search Engine, Data Warehouse, Graph DB, Time-Series DB |\n| Infrastructure | `#fbbf24` | `rgba(120, 53, 15, 0.3)` | Deployment_Node | CDN, Load Balancer, DNS, Object Storage, Container Registry, Reverse Proxy, Service Mesh |\n| Messaging | `#fb923c` | `rgba(251, 146, 60, 0.3)` | ContainerQueue | Message Queue, Event Bus, Stream, Pub/Sub, Webhook |\n| Security | `#fb7185` | `rgba(136, 19, 55, 0.4)` | System_Ext / boundary | Auth Provider, API Gateway, WAF, Secret Manager, Certificate Manager, Identity Provider |\n| External | `#94a3b8` | `rgba(30, 41, 59, 0.5)` | System_Ext | Third-party API, SaaS, Legacy System, Partner Service, Payment Provider |\n| Monitoring | `#38bdf8` | `rgba(12, 74, 110, 0.4)` | Container | Logging, Metrics, Tracing, Alerting, APM |\n\n## Sub-type Registry\n\nEach sub-type inherits its category tokens and keeps a placeholder slot for an inline SVG icon.\n\n| Category | Sub-type | C4 Label | Icon Slot |\n|---|---|---|---|\n| Frontend | SPA | `<<Container>>` | `icon-spa` |\n| Frontend | Mobile App | `<<Container>>` | `icon-mobile-app` |\n| Frontend | Static Site | `<<Container>>` | `icon-static-site` |\n| Frontend | Micro-frontend | `<<Container>>` | `icon-micro-frontend` |\n| Frontend | PWA | `<<Container>>` | `icon-pwa` |\n| Frontend | Desktop App | `<<Container>>` | `icon-desktop-app` |\n| Backend | API Service | `<<Container>>` | `icon-api-service` |\n| Backend | Worker/Job | `<<Container>>` | `icon-worker-job` |\n| Backend | BFF | `<<Container>>` | `icon-bff` |\n| Backend | Microservice | `<<Container>>` | `icon-microservice` |\n| Backend | Serverless Function | `<<Container>>` | `icon-serverless-function` |\n| Backend | gRPC Service | `<<Container>>` | `icon-grpc-service` |\n| Data | Relational DB | `<<ContainerDb>>` | `icon-relational-db` |\n| Data | Document DB | `<<ContainerDb>>` | `icon-document-db` |\n| Data | Key-Value Store | `<<ContainerDb>>` | `icon-key-value-store` |\n| Data | Cache | `<<ContainerDb>>` | `icon-cache` |\n| Data | Search Engine | `<<ContainerDb>>` | `icon-search-engine` |\n| Data | Data Warehouse | `<<ContainerDb>>` | `icon-data-warehouse` |\n| Data | Graph DB | `<<ContainerDb>>` | `icon-graph-db` |\n| Data | Time-Series DB | `<<ContainerDb>>` | `icon-time-series-db` |\n| Infrastructure | CDN | `<<Deployment_Node>>` | `icon-cdn` |\n| Infrastructure | Load Balancer | `<<Deployment_Node>>` | `icon-load-balancer` |\n| Infrastructure | DNS | `<<Deployment_Node>>` | `icon-dns` |\n| Infrastructure | Object Storage | `<<Deployment_Node>>` | `icon-object-storage` |\n| Infrastructure | Container Registry | `<<Deployment_Node>>` | `icon-container-registry` |\n| Infrastructure | Reverse Proxy | `<<Deployment_Node>>` | `icon-reverse-proxy` |\n| Infrastructure | Service Mesh | `<<Deployment_Node>>` | `icon-service-mesh` |\n| Messaging | Message Queue | `<<ContainerQueue>>` | `icon-message-queue` |\n| Messaging | Event Bus | `<<ContainerQueue>>` | `icon-event-bus` |\n| Messaging | Stream | `<<ContainerQueue>>` | `icon-stream` |\n| Messaging | Pub/Sub | `<<ContainerQueue>>` | `icon-pub-sub` |\n| Messaging | Webhook | `<<ContainerQueue>>` | `icon-webhook` |\n| Security | Auth Provider | `<<System_Ext>>` | `icon-auth-provider` |\n| Security | API Gateway | `<<System_Ext>>` | `icon-api-gateway` |\n| Security | WAF | `<<System_Ext>>` | `icon-waf` |\n| Security | Secret Manager | `<<System_Ext>>` | `icon-secret-manager` |\n| Security | Certificate Manager | `<<System_Ext>>` | `icon-certificate-manager` |\n| Security | Identity Provider | `<<System_Ext>>` | `icon-identity-provider` |\n| External | Third-party API | `<<System_Ext>>` | `icon-third-party-api` |\n| External | SaaS | `<<System_Ext>>` | `icon-saas` |\n| External | Legacy System | `<<System_Ext>>` | `icon-legacy-system` |\n| External | Partner Service | `<<System_Ext>>` | `icon-partner-service` |\n| External | Payment Provider | `<<System_Ext>>` | `icon-payment-provider` |\n| Monitoring | Logging | `<<Container>>` | `icon-logging` |\n| Monitoring | Metrics | `<<Container>>` | `icon-metrics` |\n| Monitoring | Tracing | `<<Container>>` | `icon-tracing` |\n| Monitoring | Alerting | `<<Container>>` | `icon-alerting` |\n| Monitoring | APM | `<<Container>>` | `icon-apm` |\n\n## Icon Registry\n\nIcons are inline SVG `<symbol>` elements with a 16x16 viewBox, rendered via `<use>` at `(x+W-22, y+4)` inside the component box. They use `currentColor` to inherit the category stroke color.\n\n### Category-Level Icons (active)\n\nEach category has a shared icon defined in `html-template.html` `<defs>`. All sub-types within a category use their category icon by default. Sub-type-specific icons can override these in the future.\n\n| Category | Symbol ID | Shape | Status |\n|---|---|---|---|\n| Frontend | `icon-frontend` | Monitor with stand | **active** |\n| Backend | `icon-backend` | Server rack (3 units) | **active** |\n| Data | `icon-data` | Database cylinder | **active** |\n| Infrastructure | `icon-infrastructure` | Cloud | **active** |\n| Messaging | `icon-messaging` | Envelope | **active** |\n| Security | `icon-security` | Shield with checkmark | **active** |\n| External | `icon-external` | Globe with meridians | **active** |\n| Monitoring | `icon-monitoring` | Line chart with axes | **active** |\n\nUsage pattern:\n```svg\n<use href="#icon-frontend" class="icon-use" x="448" y="154" width="16" height="16"/>\n```\n\n### Sub-type Icons (planned)\n\nWhen a sub-type icon is added, it overrides the category icon for that specific component. Until implemented, all sub-types use their category icon.\n\n| Sub-type | Icon | Status |\n|---|---|---|\n| SPA | `icon-spa` | planned |\n| Mobile App | `icon-mobile-app` | planned |\n| Static Site | `icon-static-site` | planned |\n| Micro-frontend | `icon-micro-frontend` | planned |\n| PWA | `icon-pwa` | planned |\n| Desktop App | `icon-desktop-app` | planned |\n| API Service | `icon-api-service` | planned |\n| Worker/Job | `icon-worker-job` | planned |\n| BFF | `icon-bff` | planned |\n| Microservice | `icon-microservice` | planned |\n| Serverless Function | `icon-serverless-function` | planned |\n| gRPC Service | `icon-grpc-service` | planned |\n| Relational DB | `icon-relational-db` | planned |\n| Document DB | `icon-document-db` | planned |\n| Key-Value Store | `icon-key-value-store` | planned |\n| Cache | `icon-cache` | planned |\n| Search Engine | `icon-search-engine` | planned |\n| Data Warehouse | `icon-data-warehouse` | planned |\n| Graph DB | `icon-graph-db` | planned |\n| Time-Series DB | `icon-time-series-db` | planned |\n| CDN | `icon-cdn` | planned |\n| Load Balancer | `icon-load-balancer` | planned |\n| DNS | `icon-dns` | planned |\n| Object Storage | `icon-object-storage` | planned |\n| Container Registry | `icon-container-registry` | planned |\n| Reverse Proxy | `icon-reverse-proxy` | planned |\n| Service Mesh | `icon-service-mesh` | planned |\n| Message Queue | `icon-message-queue` | planned |\n| Event Bus | `icon-event-bus` | planned |\n| Stream | `icon-stream` | planned |\n| Pub/Sub | `icon-pub-sub` | planned |\n| Webhook | `icon-webhook` | planned |\n| Auth Provider | `icon-auth-provider` | planned |\n| API Gateway | `icon-api-gateway` | planned |\n| WAF | `icon-waf` | planned |\n| Secret Manager | `icon-secret-manager` | planned |\n| Certificate Manager | `icon-certificate-manager` | planned |\n| Identity Provider | `icon-identity-provider` | planned |\n| Third-party API | `icon-third-party-api` | planned |\n| SaaS | `icon-saas` | planned |\n| Legacy System | `icon-legacy-system` | planned |\n| Partner Service | `icon-partner-service` | planned |\n| Payment Provider | `icon-payment-provider` | planned |\n| Logging | `icon-logging` | planned |\n| Metrics | `icon-metrics` | planned |\n| Tracing | `icon-tracing` | planned |\n| Alerting | `icon-alerting` | planned |\n| APM | `icon-apm` | planned |\n\n## Technology Icon Registry\n\nThe HTML C4 viewer also supports technology-specific SVG icons. It resolves them from each node\'s `technology` field after normalization. Set `icon` on node data when you need an explicit override; `icon` takes precedence over auto-detection from `technology`. If neither `icon` nor a normalized `technology` value matches a registry key, the viewer falls back to the generic C4 type icon for that node, such as person, database, queue, or container.\n\n### Available Keys\n\n- **Cloud:** `aws`, `azure`, `googlecloud`, `cloudflare`, `vercel`, `netlify`\n- **Languages:** `typescript`, `javascript`, `python`, `java`, `go`, `rust`, `csharp`, `php`, `ruby`, `swift`, `kotlin`\n- **Frontend:** `react`, `vuedotjs`, `angular`, `svelte`, `nextdotjs`, `html5`, `css3`\n- **Backend:** `nodedotjs`, `express`, `nestjs`, `django`, `spring`, `dotnet`\n- **Data:** `postgresql`, `mysql`, `mongodb`, `redis`, `elasticsearch`, `amazondynamodb`, `sqlite`\n- **Infrastructure:** `docker`, `kubernetes`, `nginx`, `linux`, `terraform`, `github`\n- **Messaging/API:** `apachekafka`, `rabbitmq`, `graphql`, `grpc`\n\n### Common Aliases\n\nCommon aliases are normalized before lookup. For example: `node` -> `nodedotjs`, `postgres` -> `postgresql`, `k8s` -> `kubernetes`, `vue` -> `vuedotjs`, `next.js` -> `nextdotjs`, `mongo` -> `mongodb`, `kafka` -> `apachekafka`, `gcp` -> `googlecloud`, `c#` -> `csharp`, and `.net` -> `dotnet`.\n\n## Visual Elements\n\n### Component Box Pattern\n\nUse a rounded component box with semi-transparent fill and category stroke.\n\n```svg\n<g class="node backend">\n <rect x="280" y="210" width="190" height="60" rx="6" />\n <text class="c4-tag" x="294" y="226">&lt;&lt;Container&gt;&gt;</text>\n <text class="node-title" x="294" y="243">API Service</text>\n <text class="node-subtitle" x="294" y="257">Backend / HTTPS JSON</text>\n</g>\n```\n\n### Arrow Masking Technique\n\nUse an opaque background rectangle below the box content to visually hide arrows beneath components without breaking the component fill style.\n\n```svg\n<g class="node-mask-layer">\n <rect x="280" y="210" width="190" height="60" rx="6" fill="#020617" />\n <rect x="280" y="210" width="190" height="60" rx="6"\n fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" />\n</g>\n```\n\n### Security Group Boundary\n\n- Purpose: show auth, gateway, WAF, or identity zones\n- Stroke color: rose (`#fb7185`)\n- Pattern: `stroke-dasharray="4,4"`\n- Suggested label: `Security Boundary`\n\n```svg\n<rect x="700" y="140" width="220" height="180" rx="12"\n fill="transparent" stroke="#fb7185" stroke-width="1.5"\n stroke-dasharray="4,4" />\n```\n\n### Region Boundary\n\n- Purpose: group a deployment region, platform segment, or domain slice\n- Stroke color: amber (`#fbbf24`)\n- Pattern: `stroke-dasharray="8,4"`\n- Radius: `rx="12"`\n\n```svg\n<rect x="70" y="120" width="600" height="430" rx="12"\n fill="transparent" stroke="#fbbf24" stroke-width="1.5"\n stroke-dasharray="8,4" />\n```\n\n### Arrow Marker SVG Definition\n\n```svg\n<defs>\n <marker id="arrowhead" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">\n <path d="M0,0 L8,4 L0,8 Z" fill="#cbd5e1" />\n </marker>\n</defs>\n```\n\n### Arrow Z-order Rule\n\nDraw arrows early in the SVG so component boxes and masking layers paint over them. This keeps connectors readable in dense diagrams and avoids arrow overlap across component interiors.\n\n## Spacing Rules\n\n- Standard component height: `60px`\n- Minimum vertical gap between stacked components: `40px`\n- Inline connectors should route through gaps rather than through component interiors\n- Keep labels inside the top `28px` of the box and the subtype line inside the lower third\n- Place legends outside boundaries to prevent classification noise inside the diagram area\n\n## Layout Structure\n\nThe canonical page composition is:\n\n1. Header: title, pulse dot, subtitle\n2. Main SVG diagram: embedded inside a rounded border card\n3. Summary cards: grid of 3 cards beneath the diagram\n4. Footer metadata: generator, scope, rendering notes, last-updated stamp\n\n## Present Tool Integration\n\nCompose architecture diagrams with the `present` tool by embedding the full HTML/SVG diagram in a markdown block and pairing it with metrics or cards blocks as needed.\n\n### `format: "html"`\n\nUse a `markdown` block with embedded `<div>`, inline SVG, and a `<style>` tag containing the full CSS. The `present` html format renders raw HTML in markdown blocks.\n\n### `format: "browser"`\n\nUse the same composition: a `markdown` block containing the full HTML structure. Summary content can also be added with `cards` and `metrics` blocks alongside the SVG diagram block.\n\n### Example `present` Call Structure\n\n```js\npresent({\n format: "html", // or "browser"\n title: "System Architecture",\n content: [\n {\n type: "metrics",\n title: "Overview",\n value: [\n { label: "Services", value: "6" },\n { label: "Data Stores", value: "2" },\n { label: "External Systems", value: "3" }\n ]\n },\n {\n type: "markdown",\n title: "Architecture Diagram",\n value: "<div class=\'arch-diagram\'>...(inline SVG)...</div><style>...(design system CSS)...</style>"\n },\n {\n type: "cards",\n title: "Summary",\n value: [\n { title: "Frontend", body: "React SPA..." },\n { title: "Backend", body: "API + async workers..." },\n { title: "Security", body: "Gateway + IdP..." }\n ]\n }\n ]\n})\n```\n\nThis design system is the single source of truth. The `c4-architecture` skill and `present` skill both reference this file. Update component types, colors, or layout rules here only.\n\n## Adding New Categories\n\n1. Add a new row to the Category Registry with the category name, colors, C4 mapping, and initial subtype set.\n2. Add the new sub-types to the Sub-type Registry with a C4 label and icon slot name.\n3. Add icon placeholders to the Icon Registry.\n4. Update [html-template.html](html-template.html) legend content so the new category appears in the rendered template.\n5. Update summary card accent colors in [html-template.html](html-template.html) if the new category needs a dedicated card treatment.\n\n## Template Pairing\n\nSee [html-template.html](html-template.html) for the complete self-contained reference implementation of this design system.\n'},{file:`references/c4.schema.json`,content:JSON.stringify({$schema:`http://json-schema.org/draft-07/schema#`,title:`AIKIT Architecture Diagram`,description:`Schema for AI Kit C4 interactive architecture diagrams. The agent generates JSON matching this schema, which is injected into c4-viewer.html.`,version:`1.0.0`,type:`object`,required:[`title`,`type`,`nodes`,`edges`],properties:{title:{type:`string`,description:`Diagram title displayed in the viewer header`},description:{type:`string`,description:`Brief diagram description`},type:{type:`string`,enum:[`context`,`container`,`component`,`deployment`],description:`C4 diagram level`},layout:{type:`object`,properties:{direction:{type:`string`,enum:[`DOWN`,`UP`,`LEFT`,`RIGHT`],default:`DOWN`},spacing:{type:`number`,default:80},layerSpacing:{type:`number`,default:120}}},nodes:{type:`array`,items:{type:`object`,required:[`id`,`type`,`label`],properties:{id:{type:`string`,description:`Unique node identifier`},type:{type:`string`,enum:[`person`,`system`,`container`,`component`,`database`,`queue`,`external`,`boundary`,`deploymentNode`],description:`C4 element type - determines visual styling`},label:{type:`string`,description:`Display label`},technology:{type:`string`,description:`Technology tag used for display and icon auto-resolution (e.g., 'React', 'PostgreSQL')`},icon:{type:`string`,description:`Optional icon override key. Takes precedence over auto-detection from the technology field. Use Technology Icon Registry keys such as 'react', 'postgresql', or 'docker'.`},description:{type:`string`,description:`Element description shown on hover/expand`},children:{type:`array`,items:{type:`string`},description:`Child node IDs (for boundary/group nodes only)`},x:{type:`number`,description:`Optional fixed x position`},y:{type:`number`,description:`Optional fixed y position`}}}},edges:{type:`array`,items:{type:`object`,required:[`id`,`source`,`target`],properties:{id:{type:`string`,description:`Unique edge identifier (required for ELK layout)`},source:{type:`string`,description:`Source node ID`},target:{type:`string`,description:`Target node ID`},label:{type:`string`,description:`Relationship label`},technology:{type:`string`,description:`Protocol/technology (e.g., 'REST/HTTPS')`},style:{type:`string`,enum:[`solid`,`dashed`,`dotted`],default:`solid`},animated:{type:`boolean`,default:!1,description:`Animate the edge (for async/event flows)`}}}}}},null,2)},{file:`SKILL.md`,content:`---
1501
1501
  name: c4-architecture
1502
1502
  description: "Generate architecture documentation using C4 model diagrams. Supports two output formats: Mermaid (md) for documentation and HTML/SVG for presentations. Use when asked to create architecture diagrams, document system architecture, visualize software structure, create C4 diagrams, or generate context/container/component/deployment diagrams."
1503
1503
  metadata:
@@ -1521,12 +1521,15 @@ metadata:
1521
1521
  \`\`\`json
1522
1522
  {
1523
1523
  "title": "System Name",
1524
- "elements": [
1525
- { "id": "unique-id", "label": "Display Name", "type": "system|container|component|person|database|queue|external",
1526
- "technology": "optional", "description": "optional", "tags": ["optional"], "parentId": "optional-parent-id" }
1524
+ "description": "What this diagram shows",
1525
+ "layout": { "direction": "DOWN", "spacing": 80, "layerSpacing": 120 },
1526
+ "nodes": [
1527
+ { "id": "unique-id", "type": "person|system|container|component|database|queue|external",
1528
+ "label": "Display Name", "technology": "optional", "description": "optional", "parentId": "optional-parent-id" }
1527
1529
  ],
1528
- "relationships": [
1529
- { "sourceId": "from-id", "targetId": "to-id", "label": "optional", "technology": "optional" }
1530
+ "edges": [
1531
+ { "id": "unique-edge-id", "source": "source-node-id", "target": "target-node-id",
1532
+ "label": "optional", "technology": "optional" }
1530
1533
  ]
1531
1534
  }
1532
1535
  \`\`\`
@@ -837,7 +837,10 @@ docs/
837
837
  ├── index.md # Tour listing with descriptions
838
838
  ├── architecture.md # System structure tour
839
839
  ├── data-flow.md # Data pipeline tour
840
- └── feature-{name}.md # Feature-specific tours
840
+ ├── feature-{name}.md # Feature-specific tours
841
+ └── interactive/
842
+ ├── {name}.json # Tour data injected into viewer
843
+ └── {name}.html # Interactive viewer output
841
844
  \`\`\`
842
845
 
843
846
  ## Interactive JSON Tour (Recommended)
@@ -851,16 +854,16 @@ Tour data must conform to [references/tour.schema.json](references/tour.schema.j
851
854
  ### Usage (MANDATORY — every tour MUST produce interactive HTML)
852
855
 
853
856
  Every tour MUST produce both:
854
- - \`docs/tours/{name}.tour.json\` — machine-readable data
857
+ - \`docs/tours/interactive/{name}.json\` — machine-readable data
855
858
  - \`docs/tours/interactive/{name}.html\` — interactive viewer for humans
856
859
 
857
860
  Steps:
858
861
  1. Generate JSON that conforms to [references/tour.schema.json](references/tour.schema.json)
859
- 2. Save JSON to \`docs/tours/{name}.tour.json\`
862
+ 2. Save JSON to \`docs/tours/interactive/{name}.json\`
860
863
  3. Create interactive HTML by running the injection script:
861
864
 
862
865
  \`\`\`bash
863
- node scripts/inject-viewer.mjs --template assets/tour-viewer.html --data docs/tours/{name}.tour.json --out docs/tours/interactive/{name}.html
866
+ node scripts/inject-viewer.mjs --template assets/tour-viewer.html --data docs/tours/interactive/{name}.json --out docs/tours/interactive/{name}.html
864
867
  \`\`\`
865
868
 
866
869
  The script reads the viewer template, injects tour JSON data, and writes the output HTML. Cross-platform, no dependencies.
@@ -871,6 +874,7 @@ The script reads the viewer template, injects tour JSON data, and writes the out
871
874
  {
872
875
  "title": "Authentication Tour",
873
876
  "description": "Walk through the login path from entry point to token issuance.",
877
+ "estimatedTime": "12 min",
874
878
  "version": "1.0.0",
875
879
  "metadata": {
876
880
  "author": "AI Kit",
@@ -880,33 +884,27 @@ The script reads the viewer template, injects tour JSON data, and writes the out
880
884
  },
881
885
  "steps": [
882
886
  {
887
+ "stepNumber": 1,
883
888
  "id": "entry-point",
884
889
  "title": "Request Entry",
885
- "description": "This handler receives the login request, validates the outer shape, and forwards work to the auth service.",
890
+ "explanation": "This handler receives the login request, validates the outer shape, and forwards work to the auth service. It exists to keep malformed input from reaching credential and token logic deeper in the stack. The route uses boundary validation first, then hands the normalized request to the auth service so downstream code can assume a known shape. This step connects the public HTTP surface to the internal authentication pipeline.",
886
891
  "file": "src/http/routes/login.ts",
887
892
  "line": 1,
888
893
  "endLine": 28,
894
+ "learnsConcept": "Request boundary validation",
895
+ "duration": "2 min",
889
896
  "language": "ts",
890
897
  "codeSnippet": "export async function loginRoute(req, res) { /* ... */ }",
891
- "highlights": [
892
- {
893
- "line": 8,
894
- "label": "Request validation starts here",
895
- "style": "info"
896
- }
897
- ],
898
- "notes": [
899
- "Introduces the request boundary.",
900
- "The main concept here is input validation before auth logic."
901
- ]
898
+ "notes": "Introduces the request boundary and shows why validation happens before auth logic."
902
899
  }
903
- ]
900
+ ],
901
+ "dependencies": []
904
902
  }
905
903
  \`\`\`
906
904
 
907
905
  ### Step Content Quality Requirements
908
906
 
909
- Each tour step description MUST include ALL of these elements:
907
+ Each tour step explanation MUST include ALL of these elements:
910
908
 
911
909
  1. **What** — What this code does (1 sentence)
912
910
  2. **Why** — Why it exists, what problem it solves, what would break without it (1-2 sentences)
@@ -916,30 +914,32 @@ Each tour step description MUST include ALL of these elements:
916
914
  **Bad example (too shallow):**
917
915
  \`\`\`json
918
916
  {
917
+ "stepNumber": 3,
918
+ "id": "preview-generator",
919
919
  "title": "The preview generator",
920
- "description": "This file registers the skills adapter for generating preview files.",
921
- "notes": ["Entry point for the build pipeline."]
920
+ "explanation": "This file registers the skills adapter for generating preview files."
922
921
  }
923
922
  \`\`\`
924
923
 
925
924
  **Good example (deep, educational):**
926
925
  \`\`\`json
927
926
  {
927
+ "stepNumber": 3,
928
+ "id": "skills-adapter-registration",
928
929
  "title": "Skills Adapter Registration",
929
- "description": "generate.mjs registers the skills adapter — a function that reads .mjs skill definitions and transforms them into deployable SKILL.md + reference files. Without this adapter, the build pipeline has no way to discover or process skill sources. It uses a plugin pattern where each adapter (skills, prompts, agents) is registered independently, allowing the pipeline to process different artifact types through a unified interface.",
930
- "notes": ["This is the entry point that connects raw .mjs definitions to the full build output. The adapter pattern means adding a new artifact type (e.g., workflows) requires only registering a new adapter — no changes to the core pipeline. Watch for the 'definitions' directory scan that feeds into this adapter."],
931
- "highlights": [
932
- { "line": 30, "endLine": 45, "label": "Adapter registration block each registerAdapter() call wires a definition type to its generator" }
933
- ]
930
+ "explanation": "generate.mjs registers the skills adapter — a function that reads .mjs skill definitions and transforms them into deployable SKILL.md + reference files. Without this adapter, the build pipeline has no way to discover or process skill sources. It uses a plugin pattern where each adapter (skills, prompts, agents) is registered independently, allowing the pipeline to process different artifact types through a unified interface. This step matters because it is the bridge between raw authoring inputs and every generated documentation artifact downstream.",
931
+ "learnsConcept": "Adapter-based generation pipelines",
932
+ "duration": "3 min",
933
+ "notes": "This is the entry point that connects raw .mjs definitions to the full build output. Watch for the definitions directory scan that feeds into the adapter."
934
934
  }
935
935
  \`\`\`
936
936
 
937
937
  **Quality bar:** If a developer reads only the tour (without opening any files), they should understand the system's architecture, design decisions, and data flow.
938
938
 
939
939
  **Minimum requirements per step:**
940
- - Description: 3-5 sentences minimum (not 1-2)
941
- - Notes: 2-3 sentences explaining architectural significance
942
- - Highlights: At least 1 per step with meaningful labels (not just line numbers)
940
+ - Explanation: 3-5 sentences minimum (not 1-2)
941
+ - Notes: Optional, but when present use 1-2 sentences explaining architectural significance
942
+ - Include \`stepNumber\`, \`id\`, \`duration\`, and \`learnsConcept\` for every step
943
943
  - codeSnippet: Include for steps where the key logic fits in <15 lines
944
944
 
945
945
  ### Line Number Validation (MANDATORY)
@@ -956,7 +956,7 @@ After generating tour JSON, validate EVERY step's line numbers against the actua
956
956
  For each step:
957
957
  compact({ path: step.file, query: step.title }) → find actual location
958
958
  read_file(step.file, step.line, step.line + 10) → verify code matches description
959
- If mismatch → search({ query: step.description }) → find correct file:line
959
+ If mismatch → search({ query: step.explanation }) → find correct file:line
960
960
  \`\`\`
961
961
 
962
962
  Tour JSON with stale line numbers is a **quality gate failure**. Fix before saving.
@@ -965,15 +965,17 @@ Tour JSON with stale line numbers is a **quality gate failure**. Fix before savi
965
965
 
966
966
  1. **title**: Use a reader-facing tour name.
967
967
  2. **description**: State the tour goal and scope in one or two sentences.
968
- 3. **version**: Set the schema version you are targeting.
969
- 4. **metadata**: Use optional metadata for authoring info, tags, timestamps, and difficulty.
970
- 5. **steps**: Order is defined by array position. Do not add a separate ordinal field.
971
- 6. **id**: Optional but recommended for stable references and analytics; use descriptive kebab-case when present.
972
- 7. **description** on each step: Explain what matters in this step and why it belongs in the tour.
973
- 8. **file**, **line**, and **endLine**: Point to the exact source span when possible.
974
- 9. **codeSnippet** and **language**: Provide a fallback snippet when the viewer cannot load the file directly.
975
- 10. **highlights**: Use line annotations for the few lines the reader should notice first.
976
- 11. **notes**: Capture concepts, tips, cautions, or prerequisite reminders that do not belong in the main description.
968
+ 3. **estimatedTime**: Include a reader-facing duration for the full tour, such as \`15 min\`.
969
+ 4. **version**: Set the schema version you are targeting.
970
+ 5. **metadata**: Use optional metadata for authoring info, tags, timestamps, and difficulty.
971
+ 6. **steps**: Keep array order aligned with the explicit \`stepNumber\` field.
972
+ 7. **id**: Required for stable references and dependency edges; use descriptive kebab-case.
973
+ 8. **explanation** on each step: Explain what matters in this step and why it belongs in the tour.
974
+ 9. **file**, **line**, and **endLine**: Point to the exact source span when possible.
975
+ 10. **learnsConcept** and **duration**: Use them to make the learning goal and reading effort explicit.
976
+ 11. **codeSnippet** and **language**: Provide a fallback snippet when the viewer cannot load the file directly.
977
+ 12. **notes**: Capture concepts, tips, cautions, or prerequisite reminders that do not belong in the main explanation.
978
+ 13. **dependencies**: Use step ids to describe prerequisite or flow relationships when the graph should show them.
977
979
 
978
980
  Mapping from the old contract to the current schema:
979
981
 
@@ -1185,7 +1187,7 @@ docs/
1185
1187
  "description": "Schema for AI Kit interactive code tour data. The agent generates JSON matching this schema, which is injected into tour-viewer.html.",
1186
1188
  "version": "1.0.0",
1187
1189
  "type": "object",
1188
- "required": ["title", "steps"],
1190
+ "required": ["title", "description", "estimatedTime", "steps"],
1189
1191
  "properties": {
1190
1192
  "title": {
1191
1193
  "type": "string",
@@ -1195,6 +1197,10 @@ docs/
1195
1197
  "type": "string",
1196
1198
  "description": "Brief tour description shown below the title"
1197
1199
  },
1200
+ "estimatedTime": {
1201
+ "type": "string",
1202
+ "description": "Estimated reading time (e.g., '15 min')"
1203
+ },
1198
1204
  "version": {
1199
1205
  "type": "string",
1200
1206
  "description": "Schema version for forward compatibility",
@@ -1214,15 +1220,25 @@ docs/
1214
1220
  "minItems": 1,
1215
1221
  "items": {
1216
1222
  "type": "object",
1217
- "required": ["title", "description"],
1223
+ "required": ["title", "explanation", "id", "stepNumber"],
1218
1224
  "properties": {
1225
+ "stepNumber": {
1226
+ "type": "integer",
1227
+ "minimum": 1,
1228
+ "description": "1-based step order number"
1229
+ },
1230
+ "id": {
1231
+ "type": "string",
1232
+ "pattern": "^[a-z0-9-]+$",
1233
+ "description": "Kebab-case unique step identifier (used in dependency graph)"
1234
+ },
1219
1235
  "title": {
1220
1236
  "type": "string",
1221
1237
  "description": "Step title shown in navigation"
1222
1238
  },
1223
- "description": {
1239
+ "explanation": {
1224
1240
  "type": "string",
1225
- "description": "Markdown content explaining this step"
1241
+ "description": "Detailed explanation of what this code does and why it matters (3-5 sentences minimum)"
1226
1242
  },
1227
1243
  "file": {
1228
1244
  "type": "string",
@@ -1236,6 +1252,14 @@ docs/
1236
1252
  "type": "integer",
1237
1253
  "description": "Ending line number (for range highlights)"
1238
1254
  },
1255
+ "learnsConcept": {
1256
+ "type": "string",
1257
+ "description": "Key concept this step teaches (displayed as concept tag)"
1258
+ },
1259
+ "duration": {
1260
+ "type": "string",
1261
+ "description": "Estimated reading time for this step (e.g., '2 min')"
1262
+ },
1239
1263
  "codeSnippet": {
1240
1264
  "type": "string",
1241
1265
  "description": "Code snippet to display if file is not available"
@@ -1244,26 +1268,24 @@ docs/
1244
1268
  "type": "string",
1245
1269
  "description": "Language for syntax highlighting of codeSnippet"
1246
1270
  },
1247
- "highlights": {
1248
- "type": "array",
1249
- "items": {
1250
- "type": "object",
1251
- "properties": {
1252
- "line": { "type": "integer" },
1253
- "label": { "type": "string" },
1254
- "style": { "type": "string", "enum": ["info", "warning", "error", "success"] }
1255
- },
1256
- "required": ["line"]
1257
- },
1258
- "description": "Line-level highlights within the code"
1259
- },
1260
1271
  "notes": {
1261
- "type": "array",
1262
- "items": { "type": "string" },
1263
- "description": "Additional callouts or tips for this step"
1272
+ "type": "string",
1273
+ "description": "Additional notes for this step"
1264
1274
  }
1265
1275
  }
1266
1276
  }
1277
+ },
1278
+ "dependencies": {
1279
+ "type": "array",
1280
+ "items": {
1281
+ "type": "object",
1282
+ "required": ["source", "target"],
1283
+ "properties": {
1284
+ "source": { "type": "string", "description": "Source step id" },
1285
+ "target": { "type": "string", "description": "Target step id" }
1286
+ }
1287
+ },
1288
+ "description": "Step dependency edges for the graph visualization"
1267
1289
  }
1268
1290
  }
1269
1291
  }`},{file:`references/generation-pipeline.md`,content:`# Generation Pipeline Reference
@@ -2595,11 +2617,11 @@ PRDs go in \`docs/prd/PRD-NNN-descriptive-name.md\`. The index lives at \`docs/p
2595
2617
  Detailed instructions in [references/tour-generation.md](references/tour-generation.md).
2596
2618
 
2597
2619
  **MANDATORY outputs** for every tour:
2598
- 1. \`docs/tours/{name}.tour.json\` — data (must conform to [tour.schema.json](references/tour.schema.json))
2620
+ 1. \`docs/tours/interactive/{name}.json\` — data (must conform to [tour.schema.json](references/tour.schema.json))
2599
2621
  2. \`docs/tours/interactive/{name}.html\` — interactive viewer (inject JSON into shipped \`assets/tour-viewer.html\`)
2600
2622
 
2601
2623
  **Content quality bar:**
2602
- - Each step: 3-5 sentence description (what/why/how/connection), 2-3 sentence notes, ≥1 highlight
2624
+ - Each step: 3-5 sentence explanation (what/why/how/connection), include \`stepNumber\`, \`id\`, \`duration\`, and \`learnsConcept\`
2603
2625
  - Line numbers MUST be validated against actual source files before saving
2604
2626
  - A developer reading only the tour should understand the system without opening files
2605
2627