
Code Atlas
- 47 installs
- 70 repo stars
- Updated July 26, 2026
- rysweet/amplihack
Helps with ai & agent building tasks.
About
code-atlas is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- code-atlas
- AI & Agent Building
- AI-coding skill
Code Atlas by the numbers
- 47 all-time installs (skills.sh)
- +1 installs in the week ending Jul 26, 2026 (Skillselion tracking)
- Ranked #7,461 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/rysweet/amplihack --skill code-atlasAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 47 |
|---|---|
| repo stars | ★ 70 |
| Last updated | July 26, 2026 |
| Repository | rysweet/amplihack ↗ |
What it does
Helps with ai & agent building tasks.
Files
Code Atlas Skill
Purpose
Build exhaustive, regeneratable architecture atlases directly from code truth. A code-atlas is a living document set: diagrams, graphs, and inventory tables that form a navigable map of any codebase. Atlas-building is investigation: structured reasoning about code in graph form reveals structural bugs, API contract mismatches, and architectural drift that linear code review misses.
An atlas is complete when any engineer, given only the atlas and a bug report, can trace the full execution path without opening the source code.
Layer Overview
Layer definitions are the single source of truth in LAYERS.yaml. All references below use slugs from that file.
| Slug | Name | Description | Recommended Diagram Type |
|---|---|---|---|
repo-surface | Repository Surface | All source files, project structure, build systems | Mermaid flowchart TD |
ast-lsp-bindings | AST+LSP Symbol Bindings | Cross-file symbol references, dead code, interface mismatches | Mermaid flowchart LR or DOT digraph |
compile-deps | Compile-time Dependencies | Package imports, dependency trees, circular deps | DOT digraph (handles large trees better) |
runtime-topology | Runtime Topology | Services, containers, ports, inter-service connections | DOT digraph with subgraph clusters |
api-contracts | API Contracts | HTTP routes, gRPC, GraphQL, middleware chains | Mermaid flowchart TD |
data-flow | Data Flow | DTO-to-storage chains, transformation steps | Mermaid flowchart LR |
service-components | Service Component Architecture | Per-service internal module/package structure | Mermaid graph TD (one per service) |
user-journeys | User Journey Scenarios | End-to-end paths from entry to outcome | Mermaid sequenceDiagram |
Per-Layer Scope Guidance
| Slug | Scope Target |
|---|---|
repo-surface | Top-level directories and build entry points. Do not enumerate every file. |
ast-lsp-bindings | Exported symbols and their cross-file references. Focus on public API surface. |
compile-deps | Direct dependencies and one level of transitive. Include version constraints. |
runtime-topology | All deployed services, their ports, and inter-service protocols. |
api-contracts | Every HTTP/gRPC/GraphQL endpoint with auth, DTOs, and middleware. |
data-flow | Primary read/write paths per service. Skip internal caching flows unless relevant. |
service-components | Top-level packages/modules within each service. Show coupling edges. |
user-journeys | Derive from api-contracts routes + pages/CLI entries. Trace 3-8 key journeys. |
Skill Delegation Architecture
code-atlas (this skill)
Responsibilities:
- Atlas layer orchestration (all 8 layers)
- Language-agnostic code exploration
- Three-pass bug-hunting workflow
- Staleness detection triggers
- Density management (split, not prompt)
- Publication workflow (GitHub Pages, mkdocs, SVG)
Delegates to:
code-visualizer skill Python AST module analysis (compile-deps + service-components fallback)
mermaid-diagram-generator Mermaid syntax generation and formatting
lsp-setup skill Layer ast-lsp-bindings: LSP-assisted symbol queries (optional)
visualization-architect Complex DOT graph rendering and cross-layer layouts
analyzer agent Deep codebase investigation and dependency mapping
reviewer agent Contradiction hunting (Passes 1, 2, 3)When to Use This Skill
| Trigger | Use Case |
|---|---|
| Starting work on an unfamiliar codebase | Full atlas build before coding |
| Onboarding a new engineer | Share atlas as navigation guide |
| Before a major refactor | Map current state; plan changes against topology |
| Bug hunt stalled | Pass 1 + Pass 2 bug-hunting through graphs |
| Docs feel stale | Staleness check + targeted rebuild |
| Adding CI/CD quality gate | Register atlas freshness checks |
| Publishing documentation site | GitHub Pages / mkdocs publication workflow |
| Reviewing an unfamiliar PR | PR impact view using diff against current atlas |
Quick Start
# Build a full atlas
User: Build a complete code atlas for this repository
# Run bug hunting
User: Run code atlas bug hunting passes on this service
# Check freshness
User: Are our architecture diagrams still accurate?
# Publish
User: Publish our code atlas to GitHub PagesWhy Both Mermaid and Graphviz
The skill defaults to building atlas diagrams in both formats because they find different bugs. A controlled experiment across 7 repos showed only ~15% overlap in bugs found -- running both finds ~1.7x the bugs of either alone. The different syntax forces different reasoning paths through the same code. Evidence is documented in PR #3221.
The user can override to a single format:
User: Build a code atlas using only Mermaid
User: Build a code atlas in DOT format onlyDiagram Density Policy
There are no hard node/edge limits. Instead:
If a diagram would be unreadably dense, split into sub-diagrams by package or service boundary. In batch mode, auto-group without prompting the user. Each sub-diagram should target 15-40 nodes for readability.
For example, a runtime-topology diagram with 80 services should be split into sub-diagrams by domain (e.g., runtime-topology-payments.mmd, runtime-topology-auth.mmd) plus one high-level overview diagram showing inter-domain connections.
A table is only produced as a companion to a diagram, never as a replacement.
Recipe: 12-Phase Atlas Build
The atlas build follows these phases in order:
1. Validate Prerequisites -- Check tools (mmdc, dot, kuzu), detect LSP mode 2. Build Layers 1-4 (structural) -- repo-surface, ast-lsp-bindings, compile-deps, runtime-topology 3. Build Layers 5-8 (behavioral) -- api-contracts, data-flow, service-components, user-journeys 4. Verify All 8 Layers -- Hard gate: every slug must have .mmd + .dot + rendered .svg + README with embedded images 5. Bug Hunt (Mermaid arm) -- 3-pass hunt using only .mmd diagrams 6. Bug Hunt (Graphviz arm) -- 3-pass hunt using only .dot diagrams (parallel with step 5) 7. Merge Findings -- Deduplicate across both arms 8. Multi-Agent Validation -- 3 specialists vote independently; threshold >= 2/3 to confirm 9. File Issues -- Validated bugs filed as GitHub issues (never stored in atlas) 10. Kuzu Ingestion + OpenCypher -- Ingest to graph (REQUIRED) + generate standalone .cypher files 11. Publish Atlas -- Render SVGs, write index, update mkdocs nav 12. Final Checklist Review -- Independent reviewer verifies completeness of all deliverables
After each build phase, diagrams are written to docs/atlas/{slug}/ with .mmd source, .dot source, rendered *-mermaid.svg and *-dot.svg, and a README.md that embeds the SVGs inline using  syntax.
Bug-Hunting Workflow Overview
The atlas is an active investigation tool. Three passes transform it from a map into a high-confidence bug-detection engine. Each pass runs in a fresh context window to prevent anchoring bias.
- Pass 1 (Comprehensive Build + Hunt): Build all layers, then systematically hunt
contradictions between them. Route/DTO mismatches, orphaned env vars, dead runtime paths, stale doc references.
- Pass 2 (Fresh-Eyes Cross-Check): A new context window re-examines the atlas
independently. Confirms, overturns, or escalates Pass 1 findings.
- Pass 3 (Scenario Deep-Dive): Every user-journeys journey is traced end-to-end through
api-contracts, data-flow, runtime-topology, service-components, and ast-lsp-bindings. Each journey receives a verdict: PASS, FAIL, or NEEDS_ATTENTION.
Full checklists, templates, and output formats: bug-hunt-guide.md
Layer 8: ast-lsp-bindings Operating Modes
Layer ast-lsp-bindings operates in one of two modes, always labelled on line 1 of its README:
| Mode | Trigger | Mechanism |
|---|---|---|
lsp-assisted | lsp-setup reports active LSP server | Delegates symbol queries to LSP |
static-approximation | LSP unavailable | ripgrep + code-visualizer AST |
The mode label is never absent, never defaulted silently.
Output Structure
docs/atlas/
index.md
staleness-map.yaml
{slug}/
README.md (embeds SVG diagrams inline with )
*-mermaid.svg (rendered Mermaid diagrams)
*-dot.svg (rendered Graphviz diagrams)
*.mmd (Mermaid source)
*.dot (Graphviz source)
inventory.md (where applicable)
cypher/
schema.cypher (CREATE NODE/REL TABLE statements)
atlas-layers.cypher
atlas-services.cypher
atlas-bugs.cypher
atlas-relationships.cypher
queries.cypher (ready-to-run example queries)Three non-negotiable output rules:
1. Bug hunt results are never stored in the atlas. All findings are filed as GitHub issues with the code-atlas-bughunt label. 2. Kuzu ingestion is required, not optional. If Kuzu is unavailable, fail loudly and attempt to fix (install kuzu package). Never silently skip. 3. OpenCypher .cypher files are always generated alongside Kuzu ingestion for portability to any graph database.
Staleness Detection
Staleness triggers are defined per-layer in LAYERS.yaml as glob patterns. When git diff matches a trigger pattern, the corresponding layer is marked stale.
Full trigger table, rebuild commands, and incremental rebuild strategy: reference.md
CI Integration
Three GitHub Actions patterns are available:
1. Post-merge staleness gate with auto-commit 2. PR impact check with layer annotations 3. Scheduled weekly full rebuild with issue creation on failure
Full workflow YAML and configuration: publication-guide.md
Publication
Outputs GitHub Pages-ready docs/atlas/ structure. Compatible with mkdocs-material and plain GitHub Pages. SVGs are committed so no render step is needed at read time.
SVG generation commands, mkdocs integration, and deployment workflows: publication-guide.md
Diagram Examples
Per-layer Mermaid and DOT examples with recommended diagram types: examples.md
Security Controls
All security controls (SEC-01 through SEC-19) are defined in SECURITY.md. Key controls:
- Secret values never emitted (env files parsed for key names only)
- Path traversal prevented via realpath() boundary validation
- Mermaid/DOT/SVG labels sanitized (XSS prevention)
- Bug report code quotes redacted of credential patterns
- All file:line references use relative paths (SEC-16)
API Contracts
Typed contracts for all skill delegations and filesystem layout: API-CONTRACTS.md
Reference
Error codes, Kuzu ingestion schema, staleness trigger table: reference.md
Success Criteria
A complete atlas satisfies:
- All 8 layers produced with diagrams in
docs/atlas/{slug}/ - Both DOT and Mermaid source files present (unless user requested single format)
- SVG renders alongside source files
- Bug hunt findings filed as GitHub issues (never stored in atlas docs)
- Every filed bug includes: layer reference, file path, line number, code evidence
- No orphaned nodes in diagrams
- ast-lsp-bindings README states mode on line 1
Limitations
- Not a static analysis tool: Uses grep, AST, config parsing -- not a compiler
- Staleness is heuristic: Git diff pattern matching, not semantic analysis
- Python AST delegation: Python module graphs delegate to code-visualizer (Python-only)
- SVG rendering requires Graphviz/Mermaid CLI: CI environments need these installed
- Bug hunting is probabilistic: Human review required before filing
- Single-repository focus: Cross-repo deps require manual configuration
- No runtime instrumentation: Call frequencies and latency require APM tools
Remember
Diagramming is investigation, not just documentation.
The most valuable output of a code atlas is the bugs and contradictions discovered while reasoning about the system in graph form.
Five rules that are never negotiable:
1. No silent diagram-to-table substitution. If density is high, split into sub-diagrams. 2. Mode is always visible. ast-lsp-bindings README always states its mode on line 1. 3. Three-pass bug hunting. Pass 1 hunts. Pass 2 validates. Pass 3 verdicts per journey. 4. Bugs go to issues, never the atlas. The atlas is a living architecture doc, not a bug report. 5. Kuzu is required, not optional. Never silently skip graph ingestion. Fail loudly and fix.
Rebuild from code truth. Hunt contradictions. File evidence-backed bugs. Repeat.
Code Atlas — API Contracts
Version: 1.1.0 Role: API contract specification for all interfaces the code-atlas skill exposes and consumes.
v1.1.0 additions (backward compatible):
- Layer 7 (Service Component Architecture) and Layer 8 (AST+LSP Symbol Bindings) contracts
BugReport.passextended to1 | 2 | 3JourneyVerdictschema for Pass 3 per-journey outputs- Three new error codes:
DENSITY_THRESHOLD_EXCEEDED,LAYER7_SOURCE_NOT_FOUND,LAYER8_LSP_UNAVAILABLE - Density threshold contract (§1b) and
lsp-setupdelegation contract (§2f)
---
Design Philosophy
Every interface follows three rules:
1. Single purpose — each contract does one thing 2. Stable studs — callers and delegates can rely on these shapes across versions 3. Minimal surface — no parameter exists without a concrete use case
---
1. Skill Invocation Contract
Input Schema
The user invokes /code-atlas with a natural-language request. Claude normalises it into these parameters:
# Invocation parameters (all optional with defaults)
invocation:
codebase_path: string # Default: "." (current working directory)
layers: array<LayerID> # Default: [1,2,3,4,5,6] (all)
journeys: array<Journey> # Default: [] (auto-derived from Layer 3)
output_dir: string # Default: "docs/atlas"
diagram_formats: array<Fmt> # Default: ["mermaid", "dot"]
bug_hunt: boolean # Default: true
publish: boolean # Default: false (set true to trigger GitHub Pages push)
# Types
LayerID: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
Fmt: "mermaid" | "dot" | "both"
Journey:
name: string # e.g. "user-checkout"
entry: string # Route or CLI command: "POST /api/orders"
description: string # One sentence; used in sequence diagram titleOutput Contract
The skill returns a structured completion summary and populates the filesystem:
completion_summary:
layers_built: array<LayerID> # Which layers were completed
diagrams_created: array<FilePath> # Relative paths to .mmd/.dot/.svg files
inventory_tables: array<FilePath> # Relative paths to .md inventory tables
bug_reports: array<BugReport> # All findings (see §4)
staleness_triggers: array<Trigger> # CI/staleness table for this codebase
errors: array<SkillError> # Any non-fatal errors (see §5)Invocation Examples
# Minimal — full atlas on current directory
/code-atlas
# Targeted — routing and data layers only, no bug hunt
/code-atlas layers=3,4 bug_hunt=false
# Custom journey, publish to GitHub Pages
/code-atlas journeys="user-checkout: POST /api/orders" publish=true
# Single service subdirectory, DOT format only
/code-atlas codebase_path=services/billing diagram_formats=dot---
1b. Density Threshold Contract
The density guard prevents silent table-substitution for large diagrams (FORBIDDEN_PATTERNS.md §2 compliance). It applies to all layers (1–8) without exception.
DensityThresholdConfig Schema
interface DensityThresholdConfig {
nodes: number; // Default: 50 — trigger when node_count > 50
edges: number; // Default: 100 — trigger when edge_count > 100
// Trigger condition: (node_count > nodes) OR (edge_count > edges)
// Override: --density-threshold nodes=N,edges=M on any invocation
}Trigger Semantics
| Condition | Required Behaviour |
|---|---|
node_count > 50 OR edge_count > 100 | Pause execution; present DENSITY_PROMPT to user |
| User selects option (a) | Render full diagram; continue normally |
| User selects option (b) | Render simplified/clustered diagram; continue |
| User selects option (c) | Render table; emit SkillError with code DENSITY_THRESHOLD_EXCEEDED |
| No user interaction available (non-interactive) | Default to option (b); log SkillError |
NEVER: Fall back silently to a table without presenting this prompt. Any code path that bypasses the prompt is a contract violation.
Required Prompt Wording
The exact wording of the user prompt MUST be:
This diagram has {N} nodes and {M} edges, which may render poorly.
Please choose:
(a) Full diagram anyway
(b) Simplified/clustered diagram
(c) Table representationPer-Invocation Override
# Raise thresholds for a codebase with large service graphs
/code-atlas --density-threshold nodes=100,edges=200
# Lower thresholds for presentation-quality output
/code-atlas --density-threshold nodes=30,edges=60Override values are applied uniformly across all layers in that invocation.
---
2. Inter-Skill Delegation Contracts
Code-atlas delegates to three components. Each contract defines what is passed IN and what is expected BACK.
---
2a. code-visualizer Skill
When invoked: Layer 2 build, when .py files are detected in the codebase.
Input (what code-atlas passes):
delegation_input:
skill: "code-visualizer"
task: "analyze-dependencies"
payload:
module_paths: array<string> # Python module paths to analyse
output_format: "mermaid" # code-atlas always requests mermaid from this skill
check_staleness: boolean # true if atlas already exists (incremental rebuild)Expected output:
delegation_output:
mermaid_source: string # Valid flowchart TD mermaid syntax
modules_found: array<string> # Canonical module names discovered
import_edges: array<Edge> # [{from: "auth.models", to: "db.session"}]
stale_diagrams: array<string> # Paths of diagrams that are now stale (if staleness checked)
Edge:
from: string
to: string
type: "import" | "from-import" | "relative"Fallback: If code-visualizer cannot analyse (non-Python, import errors), code-atlas logs a SkillError with layer: 2 and uses the analyzer agent instead (§2d).
---
2b. mermaid-diagram-generator Skill
When invoked: All layers producing Mermaid output, when diagram complexity exceeds ~15 nodes or requires custom styling.
Input (what code-atlas passes):
delegation_input:
skill: "mermaid-diagram-generator"
task: "generate-diagram"
payload:
diagram_type: DiagramType
nodes: array<Node>
edges: array<Edge>
title: string
style_hints:
direction: "TD" | "LR" | "BT" | "RL"
theme: "default" | "dark" | "neutral"
DiagramType: "flowchart" | "sequence" | "class" | "er"
Node:
id: string # Unique identifier, no spaces
label: string # Human-readable display text
shape: "rect" | "rounded" | "diamond" | "cylinder" | "circle"
Edge:
from: string # Node ID
to: string # Node ID
label: string # Optional edge annotation
style: "solid" | "dashed" | "dotted"Expected output:
```yaml delegation_output: mermaid_syntax: string # Complete, valid mermaid block (without ` fences) diagram_type: DiagramType # Confirmed type used node_count: integer # Actual nodes in output ```
Contract guarantee: The returned mermaid_syntax must be renderable by mmdc without error. If the diagram generator cannot produce valid syntax, it MUST return an error rather than invalid syntax.
---
2c. visualization-architect Agent
When invoked:
- Layer 1 (runtime topology) — always, for service cluster layout
- Any layer where DOT format is requested and node count > 20
- Cross-layer overview diagrams
Input (what code-atlas passes):
delegation_input:
subagent_type: "amplihack:amplihack:core:architect"
prompt: |
Create a Graphviz DOT diagram for: {layer_description}
Services/nodes: {node_list}
Connections: {edge_list}
Requirements:
- Use subgraph clusters for service groups
- rankdir=LR for service topology; TB for dependency trees
- Output ONLY the DOT source (no markdown fences, no explanation)
- Node shapes: box for services, cylinder for databases, diamond for gatewaysExpected output:
Raw DOT source string beginning with `digraph` or `graph`.
No markdown. No explanation. Just the DOT.Validation: Code-atlas validates the DOT output by checking it starts with digraph or graph and contains at least one -> or -- edge. If invalid, logs SkillError and falls back to mermaid for that layer.
---
2d. analyzer Agent (conditional)
When invoked: First run on an unfamiliar codebase, or when Layer 2 delegation to code-visualizer fails for non-Python files.
Input:
delegation_input:
subagent_type: "amplihack:amplihack:specialized:analyzer"
prompt: |
Analyze the {language} codebase at {path}.
Extract: module names, import/dependency edges, external packages.
Return JSON matching the Layer2AnalysisResult schema.Expected output (Layer2AnalysisResult):
{
"language": "go",
"modules": ["cmd/server", "internal/auth", "pkg/db"],
"edges": [
{ "from": "cmd/server", "to": "internal/auth", "type": "import" },
{ "from": "internal/auth", "to": "pkg/db", "type": "import" }
],
"external_packages": [{ "name": "github.com/gin-gonic/gin", "version": "v1.9.1" }]
}---
2e. reviewer Agent
When invoked: Pass 1 (contradiction hunt) and Pass 2 (journey trace) of bug-hunting.
Input:
delegation_input:
subagent_type: "amplihack:amplihack:core:reviewer"
prompt: |
Cross-reference the following layer truth sets for contradictions.
Layer A ({layer_a_name}): {layer_a_data}
Layer B ({layer_b_name}): {layer_b_data}
For each contradiction found, produce a BugReport JSON object.
Return an array of BugReport objects (empty array if none found).Expected output: Array of BugReport objects (see §4).
---
2f. lsp-setup Skill (Layer 8 — LSP-assisted mode)
When invoked: Layer 8 build, when lsp-setup reports an active LSP server for the detected language.
Input (what code-atlas passes):
delegation_input:
skill: "lsp-setup"
task: "query-symbols"
payload:
codebase_path: string # Root path of the analysed codebase
language: string # e.g. "python", "typescript", "go"
query_type: LSPQueryType
target_files: array<string> # Subset of files to query (empty = entire codebase)
LSPQueryType: "symbol-references" | "dead-code" | "interface-mismatches"Expected output (LSPSymbolReport):
interface LSPSymbolReport {
mode: "lsp-assisted"; // Always "lsp-assisted" when this path is taken
language: string;
query_type: LSPQueryType;
symbols: SymbolEntry[];
unreferenced_symbols: string[]; // Dead code candidates (for query_type=dead-code)
interface_mismatches: Mismatch[]; // For query_type=interface-mismatches
}
interface SymbolEntry {
name: string; // Fully qualified symbol name
file: string; // Relative path from codebase root
line: number;
references: Reference[]; // All call sites
}
interface Reference {
file: string;
line: number;
context: string; // One line of surrounding code
}
interface Mismatch {
symbol: string;
defined_signature: string; // What the definition declares
call_signature: string; // What the call site provides
definition_file: string;
call_file: string;
call_line: number;
}Fallback when LSP unavailable:
If lsp-setup returns LAYER8_LSP_UNAVAILABLE, code-atlas switches to static fallback mode:
interface StaticSymbolReport {
mode: "static-approximation"; // MUST be "static-approximation" — never hidden
language: string;
query_type: LSPQueryType;
symbols: SymbolEntry[]; // Best-effort from ripgrep + code-visualizer AST
unreferenced_symbols: string[];
interface_mismatches: Mismatch[];
warning: string; // e.g. "Results are approximate. Install an LSP for verified analysis."
}Mode labelling contract: The mode field is written into the Layer 8 README output header on the first line. It is never absent, never overwritten, and never defaulted silently. Users always know which mode was used.
// LSP-assisted mode delegation (full contract)
interface LSPSetupDelegation {
skill: "lsp-setup";
query: LSPQueryType;
params: { codebase_path: string; language: string };
output: LSPSymbolReport | StaticSymbolReport;
fallback: "static-approximation"; // Declared, communicated to user — never silent
}---
3. Output Artifact Schema
The skill produces a deterministic filesystem structure. This is the filesystem API — consumers (CI, mkdocs, GitHub Pages) depend on this layout being stable.
docs/atlas/
├── README.md # Atlas index; links to all layers
├── staleness-map.yaml # Glob → layer mapping for CI (see §6)
│
├── repo-surface/
│ ├── README.md # Layer narrative
│ ├── topology.dot # Graphviz DOT source
│ ├── topology.mmd # Mermaid source
│ └── topology.svg # Pre-rendered SVG (committed)
│
├── compile-deps/
│ ├── README.md
│ ├── deps.mmd
│ ├── deps.svg
│ └── inventory.md # Package inventory table (REQUIRED)
│
├── api-contracts/
│ ├── README.md
│ ├── routes.mmd
│ ├── routes.svg
│ └── inventory.md # Route inventory table (REQUIRED)
│
├── data-flow/
│ ├── README.md
│ ├── dataflow.mmd
│ └── dataflow.svg
│
├── user-journeys/
│ ├── README.md
│ └── {journey-name}.mmd # One file per journey (minimum 3)
│
├── inventory/
│ ├── services.md # 6a: Service inventory (REQUIRED)
│ ├── env-vars.md # 6b: Env var inventory (REQUIRED)
│ ├── data-stores.md # 6c: Data store inventory (REQUIRED)
│ └── external-deps.md # 6d: External dependency inventory (REQUIRED)
│
├── service-components/ # NEW in v1.1.0
│ ├── README.md # States purpose, service list, and mode used
│ ├── {service-name}.mmd # One Mermaid graph TD per service (REQUIRED)
│ └── {service-name}.svg # Pre-rendered SVG (optional; depends on mmdc)
│
├── ast-lsp-bindings/ # NEW in v1.1.0
│ ├── README.md # MUST state operating mode on first line
│ ├── symbol-references.mmd # Cross-file symbol reference graph (REQUIRED)
│ ├── dead-code.md # Dead code report table (REQUIRED)
│ └── mismatched-interfaces.md # Interface mismatch report (REQUIRED)
│
├── bug-reports/
│ ├── {YYYY-MM-DD}-pass1-{slug}.md # Pass 1 findings
│ ├── {YYYY-MM-DD}-pass2-{slug}.md # Pass 2 findings
│ └── {YYYY-MM-DD}-pass3-{slug}.md # Pass 3 per-journey verdict (NEW in v1.1.0)
│
└── experiments/ # NEW in v1.1.0 — Appendix A artifacts
└── {YYYY-MM-DD}-mermaid-vs-graphviz-L{N}.mdInventory Table Schemas
Route Inventory (Layer 3 — `inventory.md`):
| Method | Path | Handler | Auth | Request DTO | Response DTO | Middleware |
| ------ | ----------- | ---------------------- | ---- | ------------------ | ------------- | -------------------- |
| POST | /api/orders | OrderController.create | JWT | CreateOrderRequest | OrderResponse | rate-limit, validate |Env Var Inventory (Layer 6b — `env-vars.md`):
| Variable | Required | Default | Used By | Declared In |
| ------------ | -------- | ----------------- | ---------------- | ------------ |
| DATABASE_URL | yes | — | db/connection.go | .env.example |
| REDIS_URL | no | redis://localhost | cache/client.go | .env.example |Service Inventory (Layer 6a — `services.md`):
| Service | Port | Protocol | Depends On | Health Check |
| ---------- | ---- | -------- | --------------- | ------------ |
| api-server | 8080 | HTTP | postgres, redis | GET /health |Layer 7 Filesystem Contract
interface Layer7Output {
directory: "docs/atlas/service-components/";
files: {
readme: "README.md"; // Required; lists services analysed
service_diagrams: "{service-name}.mmd"; // One per service; Mermaid graph TD
rendered_svgs?: "{service-name}.svg"; // Optional; produced when mmdc available
};
diagram_content: {
type: "graph TD"; // Always top-down flow for component maps
shows: "packages → files → key exported symbols";
density_guard_applies: true; // >50 nodes OR >100 edges → user prompt
};
}Error: LAYER7_SOURCE_NOT_FOUND — emitted when no intra-service structure (packages, modules, or components) can be discovered within the given codebase_path. Layer 7 is skipped; other layers continue.
Layer 8 Filesystem Contract
interface Layer8Output {
directory: "docs/atlas/ast-lsp-bindings/";
files: {
readme: "README.md"; // First line MUST state operating mode
symbol_refs: "symbol-references.mmd"; // Cross-file reference graph
dead_code: "dead-code.md"; // Table of unreferenced symbols
mismatched: "mismatched-interfaces.md"; // Table of call-site/definition mismatches
};
mode: "lsp-assisted" | "static-approximation"; // Set by lsp-setup delegation result
mode_label_contract: "Mode MUST appear verbatim in README.md line 1 as: '**Mode:** {mode}'";
density_guard_applies: true; // Applies to symbol-references.mmd
}Error: LAYER8_LSP_UNAVAILABLE — emitted when lsp-setup cannot locate or start a language server. Layer 8 falls back to static-approximation mode (communicated to user; never silent). If static analysis also fails, Layer 8 is skipped.
Layer 8 README header template:
# Layer 8: AST+LSP Symbol Bindings
**Mode:** lsp-assisted | static-approximation
**Language:** {language}
**Analysis date:** {YYYY-MM-DD}
{One sentence: "Results are LSP-verified." OR "Results are approximate — install an LSP for verified analysis."}---
4. Bug Report Schema
Every finding from Pass 1, Pass 2, or Pass 3 produces a BugReport object and a corresponding .md file.
BugReport Object
interface BugReport {
id: string; // Slug: "route-dto-mismatch-order-customerid"
title: string; // One sentence: "POST /api/orders handler reads undeclared field"
severity: "critical" | "major" | "minor" | "info";
pass: 1 | 2 | 3; // Which bug-hunt pass found this (v1.1.0: added 3)
layers_involved: (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8)[]; // v1.1.0: extended to include 7 and 8
evidence: Evidence[]; // Minimum 1 required
recommendation: string; // One actionable sentence
}
interface Evidence {
type: "code-quote" | "layer-reference" | "diagram-annotation";
file: string; // Relative path from codebase root
line?: number; // Specific line number (for code-quote only)
content: string; // The actual quoted code or layer data
}Pass semantics:
pass: 1— Comprehensive Build + Hunt (structural contradictions, orphaned env vars, stale docs)pass: 2— Fresh-Eyes Cross-Check (re-examination from scratch; validates or overturns Pass 1)pass: 3— Scenario Deep-Dive (per-journey trace; emitsJourneyVerdictobjects, see §4b)
Bug Report Markdown Template
File: docs/atlas/bug-reports/{YYYY-MM-DD}-pass{N}-{slug}.md
````markdown
Bug: {title}
Severity: {severity} Found in pass: {pass} ({contradiction-hunt | journey-trace}) Layers involved: {layers} Date: {YYYY-MM-DD}
Description
{One paragraph explaining the contradiction or gap.}
Evidence
Layer {N} truth: {layer_name}
```{language} {code_quote_or_data}
_Source: {file}:{line}_
Layer {M} truth: {layer_name}
```{language} {code_quote_or_data}
_Source: `{file}:{line}`_
## Contradiction
{Explicit statement of the mismatch: "Layer 3 declares X; Layer 4 does not define Y that X references."}
## Recommendation
{Actionable fix in one sentence.}
---
4b. Journey Verdict Schema (Pass 3)
Pass 3 of the bug hunt traces each Layer 5 journey end-to-end. For each journey, the reviewer agent produces a JourneyVerdict block appended to the Pass 3 bug report file.
JourneyVerdict Object
interface JourneyVerdict {
journey_name: string; // Must match a Layer 5 journey name
verdict: "PASS" | "FAIL" | "NEEDS_ATTENTION"; // Aggregate status
criteria: VerdictCriterion[]; // Per-criterion breakdown
rationale: string; // One paragraph; required
}
interface VerdictCriterion {
criterion: string; // Human-readable criterion description
status: "pass" | "fail" | "attention"; // Individual criterion result
evidence: string; // File:line reference or "no evidence found"
}Verdict Semantics
| Verdict | Condition |
|---|---|
PASS | All criteria have status: "pass" — no bugs found in this journey's path |
FAIL | At least one criterion has status: "fail" — critical or major bug on this path |
NEEDS_ATTENTION | At least one criterion has status: "attention", no "fail" — minor issues or ambiguities requiring human review |
Standard Pass 3 Criteria
Each journey is evaluated against these mandatory criteria (additional criteria may be added):
| Criterion | Checks |
|---|---|
| Layer 3 routes match journey steps | Every step in the journey sequence has a matching route in Layer 3 |
| Layer 4 data flows complete | DTOs and state transitions on this path have no gaps |
| Layer 7 service components reachable | All components invoked by this journey are present in Layer 7 output |
| No dead code on critical path | Layer 8 dead-code report has no entries on this journey's execution path |
Verdict Block Markdown Template
Appended to docs/atlas/bug-reports/{YYYY-MM-DD}-pass3-{journey-slug}.md:
## Journey: {journey_name}
### Verdict: PASS | FAIL | NEEDS_ATTENTION
| Criterion | Status | Evidence |
|-----------|--------|----------|
| Layer 3 routes match journey steps | ✅/❌/⚠️ | {file:line or "no evidence found"} |
| Layer 4 data flows complete | ✅/❌/⚠️ | {file:line} |
| Layer 7 service components reachable | ✅/❌/⚠️ | {file:line} |
| No dead code on critical path | ✅/❌/⚠️ | {file:line} |
**Verdict Rationale:** {One paragraph explaining the overall verdict with specific references.}Status symbol mapping: ✅ = pass, ❌ = fail, ⚠️ = needs_attention
---
5. Error Handling
SkillError Schema
Non-fatal errors are collected and returned in completion_summary.errors. The skill never halts on a single layer failure — it logs the error, skips the layer, and continues.
interface SkillError {
layer: LayerID | "delegation" | "publish" | "density";
code: ErrorCode;
message: string;
file?: string; // Triggering file, if known
fallback_taken?: string; // What the skill did instead
}
type ErrorCode =
// Existing codes (v1.0.0)
| "LAYER_SOURCE_NOT_FOUND" // No source files matched for this layer
| "DELEGATION_FAILED" // Sub-skill/agent returned invalid output
| "DOT_RENDER_FAILED" // graphviz not installed or DOT syntax invalid
| "SVG_TOO_LARGE" // mmdc produced SVG exceeding 5MB
| "PUBLISH_FAILED" // GitHub Pages push failed
| "JOURNEY_UNDER_MINIMUM" // Fewer than 3 journeys could be derived
| "INCOMPLETE_INVENTORY" // Required inventory columns are missing
// New codes (v1.1.0)
| "DENSITY_THRESHOLD_EXCEEDED" // User selected table via density prompt (option c)
| "LAYER7_SOURCE_NOT_FOUND" // No intra-service structure discoverable for Layer 7
| "LAYER8_LSP_UNAVAILABLE"; // LSP tooling not found; fell back to static-approximationError Response Examples
{
"layer": 1,
"code": "LAYER_SOURCE_NOT_FOUND",
"message": "No docker-compose.yml or k8s manifests found.",
"fallback_taken": "Layer 1 skipped. Re-run with explicit service definitions."
}{
"layer": 1,
"code": "DOT_RENDER_FAILED",
"message": "graphviz not installed (dot command not found).",
"file": "docs/atlas/repo-surface/topology.dot",
"fallback_taken": "Mermaid-only output produced. Install graphviz for SVG render."
}{
"layer": 2,
"code": "DELEGATION_FAILED",
"message": "code-visualizer returned non-mermaid output for Python analysis.",
"fallback_taken": "Delegated to analyzer agent instead."
}{
"layer": "density",
"code": "DENSITY_THRESHOLD_EXCEEDED",
"message": "Layer 7 service diagram has 73 nodes and 118 edges. User selected table representation.",
"file": "docs/atlas/service-components/payments.mmd",
"fallback_taken": "Table representation written to service-components/payments.md instead of diagram."
}{
"layer": 7,
"code": "LAYER7_SOURCE_NOT_FOUND",
"message": "No intra-service module structure found at services/notifications/.",
"fallback_taken": "Layer 7 skipped for notifications service. Re-run after adding package declarations."
}{
"layer": 8,
"code": "LAYER8_LSP_UNAVAILABLE",
"message": "lsp-setup reported no active language server for TypeScript at services/frontend/.",
"fallback_taken": "Layer 8 running in static-approximation mode. Results labeled accordingly."
}---
6. Staleness Trigger Contract
The staleness trigger map is produced as docs/atlas/staleness-map.yaml and consumed directly by CI paths: filters.
StalenessMap Schema
staleness_map:
- glob: "docker-compose*.yml"
layers_affected: [1, 6]
rebuild_command: "/code-atlas layers=1,6"
- glob: "k8s/**/*.yaml"
layers_affected: [1]
rebuild_command: "/code-atlas layers=1"
- glob: "**/*.go"
layers_affected: [2, 3, 4]
rebuild_command: "/code-atlas layers=2,3,4"
- glob: "**/*.ts"
layers_affected: [2, 3, 4]
rebuild_command: "/code-atlas layers=2,3,4"
- glob: "**/*.py"
layers_affected: [2]
rebuild_command: "/code-atlas layers=2"
- glob: "openapi*.{json,yaml}"
layers_affected: [3, 5]
rebuild_command: "/code-atlas layers=3,5"
- glob: ".env.example"
layers_affected: [6]
rebuild_command: "/code-atlas layers=6"
- glob: "**/*.csproj"
layers_affected: [2]
rebuild_command: "/code-atlas layers=2"
- glob: "go.mod"
layers_affected: [2]
rebuild_command: "/code-atlas layers=2"
- glob: "package.json"
layers_affected: [2]
rebuild_command: "/code-atlas layers=2"
- glob: "Cargo.toml"
layers_affected: [2]
rebuild_command: "/code-atlas layers=2"
# Layer 7 staleness triggers (service component structure)
- glob: "**/__init__.py"
layers_affected: [7]
rebuild_command: "/code-atlas layers=7"
- glob: "**/package.json"
layers_affected: [7]
rebuild_command: "/code-atlas layers=7"
- glob: "**/*.mod"
layers_affected: [7]
rebuild_command: "/code-atlas layers=7"
# Layer 8 staleness triggers (symbol bindings)
- glob: "**/*.py"
layers_affected: [2, 8]
rebuild_command: "/code-atlas layers=2,8"
- glob: "**/*.ts"
layers_affected: [2, 3, 4, 8]
rebuild_command: "/code-atlas layers=2,3,4,8"
- glob: "**/*.go"
layers_affected: [2, 3, 4, 8]
rebuild_command: "/code-atlas layers=2,3,4,8"---
7. Versioning Strategy
Stay at v1.x as long as all changes are additive.
| Change Type | Action | Example |
|---|---|---|
| Add optional invocation parameter | Backward compatible — minor bump | --density-threshold added in v1.1.0 |
| Add new layer ID (7, 8, …) | Backward compatible — minor bump | Layers 7/8 added in v1.1.0 |
Add new ErrorCode value | Backward compatible — minor bump | 3 codes added in v1.1.0 |
| Add new delegation contract (§2x) | Backward compatible — minor bump | §2f lsp-setup added in v1.1.0 |
| Add new BugReport field (optional) | Backward compatible — minor bump | — |
Rename existing docs/atlas/ subdirectory | Breaking — bump to v2.0.0 | — |
| Remove existing output artifact | Breaking — bump to v2.0.0 | — |
Change BugReport required field names | Breaking — bump to v2.0.0 | — |
| Remove delegation contract | Breaking — bump to v2.0.0 | — |
Change staleness-map.yaml key names | Breaking — bump to v2.0.0 | — |
v2 trigger condition: Any change to docs/atlas/ layout or BugReport schema that breaks existing CI integrations.
Version history:
v1.0.0— Initial release: Layers 1–6, 2-pass bug huntv1.1.0— Layers 7–8, 3-pass bug hunt, density guard, lsp-setup delegation
---
8. Contract Stability Guarantees
| Contract | Stability | Notes | | --------------------------------- | ------------ | ------------------------------------------------------- | ---- | ---------------------------------------------- | | Skill invocation parameters | Stable | Additive only in v1.x | | docs/atlas/ directory layout | Stable | Breaking = v2; new directories are additive | | staleness-map.yaml key names | Stable | glob, layers_affected, rebuild_command guaranteed | | BugReport.id format | Stable | {topic}-{field-slug} format guaranteed | | BugReport.pass values | Stable | 1 | 2 | 3guaranteed; adding4 is additive (no break) | | JourneyVerdict verdict values | Stable | PASS | FAIL | NEEDS_ATTENTION guaranteed | | Layer 7 service diagram filenames | Stable | service-components/{service-name}.mmd guaranteed | | Layer 8 README mode label | Stable | Line 1 format **Mode:** {mode} guaranteed | | Density prompt wording | Stable | Options (a)(b)(c) wording guaranteed; do not reorder | | DensityThresholdConfig defaults | Stable | nodes: 50, edges: 100 defaults guaranteed | | Inventory table column order | Unstable | Consumers MUST use column headers, not position | | Delegation input shapes (§2a–§2f) | Internal | May change between minor versions | | Individual SVG filenames | Stable | {layer-slug}/{diagram-name}.svg guaranteed |
Bug Hunt Guide
Consolidated three-pass bug hunt checklist for the code-atlas skill.
Pass 1: Comprehensive Build + Hunt
"Build the atlas from verified code paths, then systematically hunt contradictions between layers."
Checklist
- [ ] Route/DTO Mismatch (api-contracts x data-flow): For every route handler, verify all
accessed request fields exist in the declared DTO. Flag fields accessed but not declared.
- [ ] Orphaned Environment Variables (runtime-topology x inventory): Compare env vars
used in code (process.env.*, os.getenv(), viper.Get()) against .env.example or documented vars. Report used-but-undeclared and declared-but-unused.
- [ ] Dead Runtime Paths (runtime-topology x api-contracts): Services in topology with
no routes. Routes referencing services not in topology.
- [ ] Stale Documentation (all layers x docs/): Docs referencing routes, services, or
env vars that no longer exist in code.
- [ ] Layer 7 Structural Issues (service-components): Services in topology with no
discoverable internal packages. Internal packages imported by 3+ siblings (high coupling).
- [ ] Layer 8 Dead Code (ast-lsp-bindings): Exported symbols never referenced.
Symbols on api-contracts routes listed in dead-code report.
Pass 1 Output Format
One file per bug: docs/atlas/bug-reports/{YYYY-MM-DD}-pass1-{slug}.md
## Bug: {Title}
**Layer**: {slug} x {slug}
**Severity**: Critical | High | Medium | Low
**Pass**: 1
**Evidence**:
- {description of evidence with relative file:line references}
- code_quote: `{relevant code snippet}`
**Impact**: {What breaks and when}
**Fix**: {Recommended action}Every bug requires at least one code_quote with a relative file path. No speculation.
---
Pass 2: Fresh-Eyes Cross-Check
"Re-examine the atlas from scratch in a new context window. Validate, overturn, or strengthen Pass 1 findings."
Checklist
- [ ] Fresh atlas read: Reviewer receives all layer output files without Pass 1 bug reports.
Independently identifies contradictions.
- [ ] Cross-check each Pass 1 finding: For each, assign verdict:
CONFIRMED-- independently found the same issue; severity upgradedOVERTURNED-- evidence does not support the finding; closed with explanationNEEDS_ATTENTION-- ambiguous; requires human review- [ ] New findings: Any contradiction found in Pass 2 but missed in Pass 1 is filed as
a new Pass 2 bug.
Pass 2 Output Format
One file per cross-check: docs/atlas/bug-reports/{YYYY-MM-DD}-pass2-{slug}.md
## Pass 2 Cross-Check: {pass1-bug-slug}
**Pass 1 verdict:** {severity} -- {title}
**Pass 2 verdict:** CONFIRMED | OVERTURNED | NEEDS_ATTENTION
**Rationale:** {One paragraph explaining Pass 2's independent finding.}---
Pass 3: Scenario Deep-Dive
"Trace each user-journeys journey end-to-end. Produce a PASS/FAIL/NEEDS_ATTENTION verdict for every journey."
Checklist
For each journey in docs/atlas/user-journeys/*.mmd:
- [ ] Trace every step through api-contracts, data-flow, runtime-topology, service-components,
and ast-lsp-bindings
- [ ] For each step, verify:
| Check | Source Layer | Question |
|---|---|---|
| Route exists | api-contracts | Does the endpoint appear in the route inventory? |
| DTO complete | data-flow | Are all request fields declared? Any response fields never populated? |
| Topology matches | runtime-topology | Does the inter-service call appear in the topology? |
| Component reachable | service-components | Are handler and service components in the per-service diagram? |
| No dead code | ast-lsp-bindings | Are any symbols on this path in the dead-code report? |
Pass 3 Output Format
One file per journey: docs/atlas/bug-reports/{YYYY-MM-DD}-pass3-{journey-slug}.md
## Journey: {journey-slug}
### Verdict: PASS | FAIL | NEEDS_ATTENTION
| Criterion | Status | Evidence |
| ----------------------------- | --------- | ---------------------------------- |
| api-contracts routes match | pass/fail | {evidence with relative file:line} |
| data-flow complete | pass/fail | {evidence} |
| service-components reachable | pass/fail | {evidence} |
| No dead code on critical path | pass/warn | {evidence} |
**Verdict Rationale:** {One paragraph explaining the verdict with specific file:line references.}Verdict Semantics
| Verdict | Condition |
|---|---|
PASS | All criteria pass |
FAIL | At least one criterion fails (critical or major bug on path) |
NEEDS_ATTENTION | At least one criterion is a warning and none fail |
---
Multi-Agent Validation
After all three passes, verdict adjudication happens during the multi-agent validation stage (not in this guide). The bug-hunt guide covers detection only. Final triage and filing decisions are made by the reviewer agent during validation.
Evidence Rules
1. All file:line references must be relative paths (SEC-16) 2. Every filed bug must include at least one code_quote 3. No bugs filed without code evidence -- no speculation 4. Bug report code_quote fields are redacted of credential patterns (SEC-15)
Code Atlas Diagram Examples
Per-layer Mermaid and DOT examples with recommended diagram types.
runtime-topology
Recommended: DOT digraph with subgraph clusters (handles complex multi-service layouts).
Graphviz DOT
digraph runtime {
rankdir=LR
node [shape=box style=filled]
subgraph cluster_frontend {
label="Frontend"
web [label="web-app\n:3000" fillcolor="#AED6F1"]
}
subgraph cluster_backend {
label="Backend"
api [label="api-service\n:8080" fillcolor="#A9DFBF"]
auth [label="auth-service\n:8081" fillcolor="#A9DFBF"]
}
subgraph cluster_data {
label="Data"
pg [label="PostgreSQL\n:5432" shape=cylinder fillcolor="#FAD7A0"]
redis [label="Redis\n:6379" shape=cylinder fillcolor="#FAD7A0"]
}
web -> api [label="HTTP/REST"]
api -> auth [label="gRPC"]
api -> pg [label="SQL"]
api -> redis [label="cache"]
auth -> pg [label="SQL"]
}Mermaid
flowchart LR
subgraph frontend["Frontend"]
web["web-app :3000"]
end
subgraph backend["Backend"]
api["api-service :8080"]
auth["auth-service :8081"]
end
subgraph data["Data"]
pg[("PostgreSQL :5432")]
redis[("Redis :6379")]
end
web -->|HTTP/REST| api
api -->|gRPC| auth
api -->|SQL| pg
api -->|cache| redis
auth -->|SQL| pg---
compile-deps
Recommended: DOT digraph (handles large dependency trees better than Mermaid).
Mermaid
flowchart TD
subgraph services["Services"]
api["api-service"]
auth["auth-service"]
worker["worker"]
end
subgraph shared["Shared Libraries"]
models["@org/models"]
utils["@org/utils"]
proto["@org/proto"]
end
subgraph external["External"]
express["express ^4.18"]
grpc["@grpc/grpc-js ^1.9"]
pg["pg ^8.11"]
end
api --> models
api --> proto
api --> express
api --> pg
auth --> models
auth --> proto
auth --> grpc
worker --> models
worker --> utils
models --> utilsInventory Table (required companion)
| Package | Version | Consumers | Direct? | License |
|---|---|---|---|---|
| express | ^4.18 | api-service | Yes | MIT |
| @grpc/grpc-js | ^1.9 | auth-service | Yes | Apache-2.0 |
| pg | ^8.11 | api-service | Yes | MIT |
| @org/models | workspace | api-service, auth-service, worker | Yes | Internal |
---
api-contracts
Recommended: Mermaid flowchart TD (route hierarchies render cleanly).
Mermaid
flowchart TD
subgraph public["Public Routes"]
POST_login["POST /api/auth/login"]
POST_register["POST /api/auth/register"]
GET_health["GET /health"]
end
subgraph protected["Protected Routes (JWT Required)"]
GET_users["GET /api/users"]
GET_user["GET /api/users/:id"]
PUT_user["PUT /api/users/:id"]
DELETE_user["DELETE /api/users/:id"]
POST_orders["POST /api/orders"]
GET_orders["GET /api/orders"]
end
subgraph middleware["Middleware Chain"]
cors["CORS"]
ratelimit["RateLimit"]
jwt["JWTValidate"]
audit["AuditLog"]
end
POST_login --> UserController
GET_users --> jwt --> UserController
POST_orders --> jwt --> ratelimit --> OrderControllerInventory Table (required companion)
| Method | Path | Handler | Auth | DTO In | DTO Out | Middleware |
|---|---|---|---|---|---|---|
| POST | /api/auth/login | AuthController.login | None | LoginRequest | TokenResponse | cors |
| GET | /api/users | UserController.list | JWT | -- | UserListResponse | cors, jwt, audit |
| POST | /api/orders | OrderController.create | JWT | CreateOrderRequest | OrderResponse | cors, jwt, ratelimit |
---
data-flow
Recommended: Mermaid flowchart LR (left-to-right matches request flow intuition).
Mermaid
flowchart LR
req["HTTP Request\nCreateOrderRequest"] --> validate["Validate DTO"]
validate -->|valid| enrich["Enrich with\nuser context"]
validate -->|invalid| err["400 Bad Request"]
enrich --> business["Apply business rules\n(pricing, inventory)"]
business --> db["INSERT orders\n+ INSERT order_items"]
business --> event["Publish OrderCreated\nevent to Kafka"]
db --> resp["OrderResponse DTO"]
event --> worker["Worker: send\nconfirmation email"]
resp --> client["HTTP 201 Response"]---
service-components
Recommended: Mermaid graph TD (one diagram per service).
Mermaid (per service)
graph TD
subgraph api_service["api-service"]
handler["handlers/"]
service["services/"]
repo["repositories/"]
dto["dto/"]
mid["middleware/"]
end
handler -->|"uses"| service
handler -->|"reads/writes"| dto
service -->|"calls"| repo
mid -->|"wraps"| handler
subgraph exports["Key Exported Symbols"]
OrderHandler["OrderHandler"]
UserService["UserService"]
PostgresRepo["PostgresRepository"]
end
handler --> OrderHandler
service --> UserService
repo --> PostgresRepo---
user-journeys
Recommended: Mermaid sequenceDiagram (natural fit for request flow tracing).
Mermaid
sequenceDiagram
actor User
participant Web as Web App
participant API as api-service
participant Auth as auth-service
participant DB as PostgreSQL
participant Queue as Kafka
User->>Web: Fill registration form
Web->>API: POST /api/auth/register {email, password, name}
API->>API: Validate RegisterRequest DTO
API->>Auth: gRPC HashPassword(password)
Auth-->>API: hashedPassword
API->>DB: INSERT users (email, hashedPassword, name)
DB-->>API: userId
API->>Queue: Publish UserRegistered {userId, email}
Queue-->>API: ack
API-->>Web: 201 {userId, email}
Web-->>User: "Check email for verification"
Note over Queue: Worker picks up UserRegistered
Queue->>Worker: UserRegistered event
Worker->>EmailSvc: Send verification email---
ast-lsp-bindings
Recommended: Mermaid flowchart LR or DOT digraph (for symbol reference graphs).
Dead Code Report (table format)
# Dead Code Report
**Mode:** static-approximation
**Date:** 2026-03-16
| Symbol | File | Line | Last Referenced | Notes |
| ----------------------------- | ------------------------- | ---- | ----------------------- | ---------------------------- |
| `LegacyUserExporter.export()` | `src/exporters/legacy.ts` | 45 | Never (static analysis) | Candidate for removal |
| `calculateTaxV1()` | `src/billing/tax.go` | 102 | Never (static analysis) | Superseded by calculateTaxV2 |Interface Mismatch Report (table format)
# Interface Mismatch Report
**Mode:** lsp-assisted
**Date:** 2026-03-16
| Symbol | Definition | Call Site | Mismatch |
| --------------------- | ------------------------------------------------ | ------------------------------ | ------------------------------- |
| `OrderService.create` | `(ctx, dto: CreateOrderRequest): Promise<Order>` | `src/api/handlers/order.ts:67` | Called with 1 arg (missing ctx) |---
repo-surface
Recommended: Mermaid flowchart TD (directory tree overview).
Typically the simplest layer -- a top-level directory tree diagram showing project structure, build entry points, and configuration files. Not every file is shown; group by directory.
---
Language-Agnostic Discovery Commands
These commands are used across layers to explore any codebase:
Go
find . -name "main.go" | head -10
grep -r "\.Get\|\.Post\|\.Handle" --include="*.go" . | grep -v _test.go
grep -r "type.*struct {" --include="*.go" . | grep -i "request\|response\|dto"TypeScript / Node.js
cat package.json | jq '.main, .scripts.start'
grep -r "\.get\|\.post\|router\.\|@Controller" --include="*.ts" src/ | head -30
find . -name "*.dto.ts" -o -name "*.schema.ts" | grep -v node_modulesPython (FastAPI, Django, Flask)
find . -name "app.py" -o -name "main.py" -o -name "wsgi.py" -o -name "asgi.py"
grep -r "@app\.\|@router\." --include="*.py" . | grep -v test
grep -r "class.*BaseModel\|class.*Serializer" --include="*.py" ..NET (ASP.NET Core)
find . -name "Program.cs" -o -name "Startup.cs"
find . -name "*Controller.cs" | xargs grep "\[Http\|MapGet\|MapPost"
find . -name "*Dto.cs" -o -name "*Request.cs" -o -name "*Response.cs"Rust (Axum, Actix-web)
find . -name "main.rs" | head -5
grep -r "Router::new\|\.route\|get!\|post!" --include="*.rs" src/
grep -r "#\[derive.*Deserialize\|#\[derive.*Serialize\]" --include="*.rs" src/# LAYERS.yaml — Single source of truth for code-atlas layer definitions.
#
# REORDERING LAYERS: Change display_order values here. Nothing else changes.
# Directory names use the 'slug' field, not numbers. References throughout
# the codebase use slugs. Numbers are display metadata only.
#
# ADDING A LAYER: Add an entry here. The slug becomes the directory name
# under docs/atlas/{slug}/. Add staleness triggers to enable CI detection.
#
# SCOPE TARGET: Tells agents how deep to go for each layer. Without this,
# agents either go too shallow (missing bugs) or too deep (hitting context limits).
#
# DIAGRAM TYPE: Recommended Mermaid/DOT diagram type for this layer.
layers:
- slug: repo-surface
display_order: 1
name: Repository Surface
description: All source files, project structure, build systems, configuration
scope_target: "List all top-level directories and their purpose. For src/, show one level of subpackages. For config files, list at root. Group test files as a single node."
diagram_type:
mermaid: "graph TD"
dot: "digraph with subgraph clusters"
staleness_triggers:
- "**/*"
- slug: ast-lsp-bindings
display_order: 2
name: AST+LSP Symbol Bindings
description: Cross-file symbol references, dead code detection, interface mismatch analysis
scope_target: "Focus on public API boundaries (__all__ exports, pub use, exported functions). Map cross-package imports. Skip intra-module function calls. Flag symbols exported but never imported elsewhere."
diagram_type:
mermaid: "graph LR"
dot: "digraph with record nodes"
staleness_triggers:
- "*.go"
- "*.ts"
- "*.py"
- "*.rs"
- "*.cs"
- "*.js"
- "*.java"
- slug: compile-deps
display_order: 3
name: Compile-time Dependencies
description: Package/module imports, dependency trees, circular dependency detection
scope_target: "Map all direct dependencies from manifest files (go.mod, package.json, Cargo.toml, pyproject.toml). Show internal package import graph at the package level (not file level). Flag circular dependencies."
diagram_type:
mermaid: "graph TD"
dot: "digraph with edge labels"
staleness_triggers:
- "go.mod"
- "*/go.mod"
- "package.json"
- "*/package.json"
- "*.csproj"
- "Cargo.toml"
- "*/Cargo.toml"
- "requirements*.txt"
- "*/requirements*.txt"
- "pyproject.toml"
- "*/pyproject.toml"
- slug: runtime-topology
display_order: 4
name: Runtime Topology
description: Services, containers, ports, inter-service connections
scope_target: "Map every service/process from docker-compose, k8s manifests, or process spawn code. Show ports, protocols, and inter-service connections. Include databases and external services. For single-service/monolith repos: show the main process, its spawned subprocesses, and all external connections (APIs, DBs, file stores)."
diagram_type:
mermaid: "graph LR"
dot: "digraph with component shapes"
staleness_triggers:
- "docker-compose*.yml"
- "docker-compose*.yaml"
- "*/k8s/*.yaml"
- "k8s/*.yaml"
- "kubernetes/*.yaml"
- "*/kubernetes/*.yaml"
- "helm/*.yaml"
- "helm/*/*.yaml"
- "*/helm/*.yaml"
- "*/helm/*/*.yaml"
- slug: api-contracts
display_order: 5
name: API Contracts
description: HTTP routes, gRPC services, GraphQL schemas, OpenAPI specs, DTOs, middleware
scope_target: "List every public endpoint/command/hook. For HTTP: method + path + handler. For CLI: subcommand + handler. For hooks: event + script. For gRPC/GraphQL: service + methods. Include request/response types."
diagram_type:
mermaid: "graph TD"
dot: "digraph with record nodes"
staleness_triggers:
- "*route*.ts"
- "*route*.go"
- "*controller*.go"
- "*controller*.ts"
- "*controller*.cs"
- "*views*.py"
- "*router*.ts"
- "*router*.go"
- "*handler*.go"
- "*.proto"
- "*.graphql"
- "*.gql"
- "*openapi*.yaml"
- "*openapi*.json"
- "*swagger*.yaml"
- "*swagger*.json"
- slug: data-flow
display_order: 6
name: Data Flow
description: DTO-to-storage chains, data transformation steps, persistence mapping
scope_target: "Trace data from API entry point through transformation to storage. Show DTO types, validation steps, and database tables/collections. One flowchart per major data path."
diagram_type:
mermaid: "flowchart TD"
dot: "digraph with edge labels"
staleness_triggers:
- "*dto*.ts"
- "*schema*.py"
- "*_request.go"
- "*_response.go"
- "*types*.ts"
- "*model*.go"
- slug: service-components
display_order: 7
name: Service Component Architecture
description: Per-service internal module/package structure, component boundaries
scope_target: "For each service from runtime-topology: show internal packages/modules, their public interfaces, and internal dependency arrows. One diagram per service. Skip services with fewer than 3 internal modules. For monolith repos: show the major subsystems as pseudo-services and map internal package boundaries."
diagram_type:
mermaid: "graph TB"
dot: "digraph with subgraph per service"
staleness_triggers:
- "services/*/*.go"
- "services/*/*.ts"
- "services/*/*.py"
- "services/*/*.rs"
- "services/*/*.cs"
- "apps/*/*.go"
- "apps/*/*.ts"
- "src/*/__init__.py"
- "*/mod.rs"
- slug: user-journeys
display_order: 8
name: User Journey Scenarios
description: End-to-end paths from entry point to outcome, traced through all layers
scope_target: "Identify 3-5 key user journeys from CLI commands, UI pages, or API endpoints. Trace each from entry point through all layers to final outcome. One sequence diagram per journey."
diagram_type:
mermaid: "sequenceDiagram"
dot: "digraph with rank constraints"
staleness_triggers:
- "*page*.tsx"
- "*page*.ts"
- "cmd/*.go"
- "*/cmd/*.go"
- "cli/*.py"
- "*/cli/*.py"
Publication Guide
CI integration, GitHub Pages deployment, mkdocs configuration, and SVG rendering for code-atlas.
Output Directory Structure
docs/
atlas/
index.md # Atlas landing page with layer overview
repo-surface/
*.dot, *.mmd, *.svg, README.md
ast-lsp-bindings/
README.md # Line 1: **Mode:** lsp-assisted|static-approximation
symbol-references.mmd
dead-code.md
mismatched-interfaces.md
compile-deps/
dependencies.mmd, dependencies.svg
inventory.md
README.md
runtime-topology/
topology.dot, topology.mmd, topology.svg
README.md
api-contracts/
routing.mmd, routing.svg
route-inventory.md
README.md
data-flow/
dataflow.mmd, dataflow.svg
README.md
user-journeys/
journey-{name}.mmd, *.svg
README.md
service-components/
README.md
{service-name}.mmd # One per service (SEC-11: name sanitised)
{service-name}.svg
bug-reports/
{YYYY-MM-DD}-pass{N}-{slug}.mdSVG Generation Commands
Graphviz DOT to SVG
dot -Tsvg docs/atlas/runtime-topology/topology.dot \
-o docs/atlas/runtime-topology/topology.svgMermaid to SVG
Requires mmdc from @mermaid-js/mermaid-cli:
mmdc -i docs/atlas/compile-deps/dependencies.mmd \
-o docs/atlas/compile-deps/dependencies.svg \
--backgroundColor transparentBatch Render All Diagrams
# Mermaid files
find docs/atlas -name "*.mmd" | while read f; do
svg="${f%.mmd}.svg"
mmdc -i "$f" -o "$svg" --backgroundColor transparent
echo "Rendered: $svg"
done
# DOT files
find docs/atlas -name "*.dot" | while read f; do
svg="${f%.dot}.svg"
dot -Tsvg "$f" -o "$svg"
echo "Rendered: $svg"
doneCI Integration Patterns
Pattern 1: Post-Merge Atlas Refresh Gate
Runs on push to main. Detects stale layers and rebuilds them.
# .github/workflows/atlas-refresh.yml
name: Refresh Code Atlas
on:
push:
branches: [main]
paths:
- "src/**"
- "services/**"
- "docker-compose*.yml"
- "**/package.json"
- "**/go.mod"
- "**/*.csproj"
jobs:
refresh-atlas:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Detect stale atlas layers
id: stale
run: |
bash scripts/check-atlas-staleness.sh --strict > stale-report.txt
cat stale-report.txt
echo "stale=$(wc -l < stale-report.txt)" >> $GITHUB_OUTPUT
- name: Rebuild stale layers
if: steps.stale.outputs.stale != '0'
run: |
echo "Atlas rebuild triggered -- stale layers detected"
git config user.name "atlas-bot"
git config user.email "atlas@ci"
git add docs/atlas/
git commit -m "chore: refresh code atlas [skip ci]" || echo "No changes"
git pushPattern 2: PR Architecture Impact Check
Runs on PRs. Annotates which atlas layers the PR touches.
# .github/workflows/pr-atlas-impact.yml
name: PR Atlas Impact
on:
pull_request:
branches: [main]
jobs:
atlas-impact:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Detect atlas impact
run: |
git diff --name-only origin/main...HEAD | while read f; do
case "$f" in
*route*|*controller*) echo "api-contracts layer may need update" ;;
*docker-compose*) echo "runtime-topology layer may need update" ;;
*dto*|*schema*) echo "data-flow layer may need update" ;;
esac
donePattern 3: Scheduled Full Rebuild
Runs weekly. Creates an issue on failure.
# .github/workflows/scheduled-atlas.yml
name: Scheduled Atlas Rebuild
on:
schedule:
- cron: "0 6 * * 1" # Every Monday 6am UTC
workflow_dispatch:
jobs:
full-atlas-rebuild:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Full atlas rebuild
run: bash scripts/rebuild-atlas-all.sh
- name: Open issue if stale
if: failure()
run: gh issue create --title "Code atlas rebuild failed" --body "See workflow run"mkdocs Integration
Add to your mkdocs.yml:
nav:
- Code Atlas:
- Overview: atlas/index.md
- Repository Surface: atlas/repo-surface/README.md
- AST+LSP Bindings: atlas/ast-lsp-bindings/README.md
- Compile-time Deps: atlas/compile-deps/README.md
- Runtime Topology: atlas/runtime-topology/README.md
- API Contracts: atlas/api-contracts/README.md
- Data Flow: atlas/data-flow/README.md
- Service Components: atlas/service-components/README.md
- User Journeys: atlas/user-journeys/README.md
- Bug Reports: atlas/bug-reports/
plugins:
- search
- mermaid2 # pip install mkdocs-mermaid2-pluginGitHub Pages Deployment
# .github/workflows/docs.yml
- name: Deploy docs with atlas
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./site # mkdocs build output
- name: Verify atlas pages
run: |
curl -sf "https://<org>.github.io/<repo>/atlas/" | grep "Code Atlas" || \
echo "WARNING: Atlas index page not found"Prerequisites for CI
- Graphviz:
apt-get install graphviz(for DOT rendering) - Mermaid CLI:
npm install -g @mermaid-js/mermaid-cli(for Mermaid SVG export) - mkdocs:
pip install mkdocs mkdocs-material mkdocs-mermaid2-plugin(for docs site)
Code Atlas
Builds comprehensive, living architecture atlases as multi-layer documents derived from code-first truth. Language-agnostic (Go, TypeScript, Python, .NET, Rust, Java).
Quick Start
Build a code atlas for this repositoryRun code atlas bug hunting passes on this serviceCheck if the atlas is stale after my last commitPublish the atlas to GitHub PagesWhat It Produces
A complete atlas has eight layers plus a bug report. Layer definitions are in LAYERS.yaml.
| Slug | Name | Description |
|---|---|---|
repo-surface | Repository Surface | All source files, project structure, build systems |
ast-lsp-bindings | AST+LSP Symbol Bindings | Cross-file symbol references, dead code, interface mismatches |
compile-deps | Compile-time Dependencies | Package imports, dependency trees, circular deps |
runtime-topology | Runtime Topology | Services, containers, ports, inter-service connections |
api-contracts | API Contracts | HTTP routes, gRPC, GraphQL, middleware chains |
data-flow | Data Flow | DTO-to-storage chains, transformation steps |
service-components | Service Component Architecture | Per-service internal module/package structure |
user-journeys | User Journey Scenarios | End-to-end paths from entry to outcome |
Every layer is committed to docs/atlas/{slug}/ with .mmd, .dot, .svg, and a README.md narrative. The atlas is regeneratable at any time from code alone.
Defaults to both Graphviz DOT and Mermaid formats. User can override to single format.
Features
- Code-First Truth: All diagrams derive from real code -- parsed imports, route
definitions, env var references, Docker Compose ports, OpenAPI specs
- Three-Pass Bug Hunting: Pass 1 (build + hunt), Pass 2 (fresh-eyes cross-check),
Pass 3 (per-journey verdicts)
- Staleness Detection: Git diff pattern matching against layer triggers
- CI Integration: Three GitHub Actions patterns (post-merge, PR impact, scheduled rebuild)
- Publication: GitHub Pages-ready structure, mkdocs compatible
- Density Management: Auto-splits dense diagrams by package/service boundary
File Structure
skills/code-atlas/
SKILL.md # Core instructions (under 500 lines)
LAYERS.yaml # Layer definitions (single source of truth)
SECURITY.md # Security controls (SEC-01 through SEC-19)
API-CONTRACTS.md # Typed contracts for all delegations + filesystem layout
bug-hunt-guide.md # Three-pass bug hunt checklists and templates
publication-guide.md # CI, GitHub Pages, mkdocs, SVG rendering
examples.md # Per-layer Mermaid/DOT examples and diagram type guidance
reference.md # Staleness triggers, error codes, Kuzu schema, language coverage
README.md # This file
tests/ # Test suitesDelegation Architecture
code-atlas (orchestrator)
code-visualizer Python AST module analysis
mermaid-diagram-generator Mermaid syntax and formatting
lsp-setup Symbol queries, dead code (ast-lsp-bindings layer)
visualization-architect Complex DOT layouts
analyzer Deep dependency mapping
reviewer Contradiction hunting (all 3 passes)Limitations
- Not a static analysis tool: Uses grep, AST, config parsing -- not a compiler
- Staleness is heuristic: Git diff patterns, not semantic analysis
- Bug hunting is probabilistic: Human review required before filing
- Single-repository focus: Cross-repo deps require manual configuration
See SKILL.md for complete details.
Philosophy Alignment
| Principle | How This Skill Follows It |
|---|---|
| Ruthless Simplicity | Code is truth; every diagram regeneratable from one command |
| Zero-BS | Real parsing, no invented topology, honest about limits |
| Modular Design | One brick (atlas orchestration), delegates to specialist bricks |
Code Atlas Reference
Error codes, staleness trigger table, Kuzu ingestion schema, and other reference material.
Staleness Trigger Table
File changes are matched against these patterns (from LAYERS.yaml) to determine which atlas layers are stale. Run git diff --name-only and match against the patterns below.
| File Change Pattern | Atlas Layer (slug) | Rebuild Command |
|---|---|---|
docker-compose*.yml, k8s/**/*.yaml, kubernetes/**/*.yaml, helm/**/*.yaml | runtime-topology | /code-atlas rebuild runtime-topology |
go.mod, package.json, *.csproj, Cargo.toml, pyproject.toml, requirements*.txt | compile-deps | /code-atlas rebuild compile-deps |
*route*.ts, *controller*.*, *handler*.go, *.proto, *.graphql, *openapi*.*, *swagger*.*, *views*.py, *router*.* | api-contracts | /code-atlas rebuild api-contracts |
*dto*.ts, *schema*.py, *_request.go, *_response.go, *model*.go, *types*.ts | data-flow | /code-atlas rebuild data-flow |
*page*.tsx, *page*.ts, cmd/*.go, cli/*.py | user-journeys | /code-atlas rebuild user-journeys |
.env.example, service README.md | inventory tables | /code-atlas rebuild inventory |
**/__init__.py, **/package.json (workspace), **/*.mod, services/*/*.go, services/*/*.ts | service-components | /code-atlas rebuild service-components |
*.go, *.ts, *.py, *.rs, *.cs, *.js, *.java (any source file) | ast-lsp-bindings | /code-atlas rebuild ast-lsp-bindings |
**/* (any file) | repo-surface | /code-atlas rebuild repo-surface |
| Any of the above | Full atlas | /code-atlas rebuild all |
Staleness Detection Script
# Check atlas staleness against current HEAD
git diff --name-only HEAD~1 HEAD | while read f; do
case "$f" in
*docker-compose*|*k8s/*|*kubernetes/*|*helm/*) echo "STALE: runtime-topology -- $f" ;;
*go.mod|*package.json|*.csproj|*Cargo.toml|*pyproject.toml) echo "STALE: compile-deps -- $f" ;;
*route*|*controller*|*handler*|*.proto|*.graphql|*views*) echo "STALE: api-contracts -- $f" ;;
*dto*|*schema*|*request*|*response*|*model*) echo "STALE: data-flow -- $f" ;;
*.env.example) echo "STALE: inventory -- $f" ;;
*page*.tsx|*page*.ts|cmd/*|cli/*) echo "STALE: user-journeys -- $f" ;;
esac
doneIncremental Rebuild Strategy
1. Full rebuild (/code-atlas rebuild all): First atlas creation and major refactors 2. Layer rebuild (/code-atlas rebuild {slug}): Triggered by CI on file pattern match 3. Staleness check (/code-atlas check): Fast -- reads git diff, reports stale layers, no rebuild
Error Codes
| Code | Description | Resolution |
|---|---|---|
LAYER8_LSP_UNAVAILABLE | No LSP server available for ast-lsp-bindings | Falls back to static-approximation mode. Install LSP for verified analysis. |
DENSITY_SPLIT_APPLIED | Diagram was split into sub-diagrams due to density | Informational. Review sub-diagrams in the layer directory. |
SEC_11_INVALID_SERVICE_NAME | Service name failed [a-zA-Z0-9_-]{1,64} validation | Sanitise the service name before using in file paths. |
SEC_13_INVALID_THRESHOLD | Density threshold value outside valid range | Use positive integers only. |
SEC_14_INVALID_INPUT | Unrecognised user input at a prompt | Re-prompt the user. |
SEC_15_CREDENTIAL_REDACTED | Credential pattern detected and redacted from output | Review redacted content manually if needed. |
SEC_16_ABSOLUTE_PATH | Absolute path detected in bug report evidence | Convert to relative path before filing. |
STALENESS_DETECTED | One or more atlas layers are stale | Run rebuild for affected layers. |
SVG_RENDER_SKIPPED | Graphviz or Mermaid CLI not installed | Install dot and/or mmdc for SVG rendering. |
Kuzu Ingestion Schema
When ingesting the atlas into a Kuzu code graph for queryable traversal, use these node and relationship types:
Node Types
CREATE NODE TABLE Service(name STRING, language STRING, port INT64, path STRING, PRIMARY KEY(name))
CREATE NODE TABLE Package(name STRING, version STRING, service STRING, PRIMARY KEY(name))
CREATE NODE TABLE Route(method STRING, path STRING, handler STRING, auth STRING, PRIMARY KEY(path))
CREATE NODE TABLE DTO(name STRING, file STRING, line INT64, PRIMARY KEY(name))
CREATE NODE TABLE Symbol(name STRING, file STRING, line INT64, exported BOOLEAN, PRIMARY KEY(name))
CREATE NODE TABLE EnvVar(name STRING, required BOOLEAN, default_value STRING, PRIMARY KEY(name))
CREATE NODE TABLE DataStore(name STRING, type STRING, version STRING, PRIMARY KEY(name))
CREATE NODE TABLE Journey(name STRING, verdict STRING, PRIMARY KEY(name))Relationship Types
CREATE REL TABLE DEPENDS_ON(FROM Package, TO Package)
CREATE REL TABLE CALLS(FROM Service, TO Service, protocol STRING)
CREATE REL TABLE EXPOSES(FROM Service, TO Route)
CREATE REL TABLE USES_DTO(FROM Route, TO DTO, direction STRING)
CREATE REL TABLE REFERENCES(FROM Symbol, TO Symbol)
CREATE REL TABLE READS_FROM(FROM Service, TO DataStore)
CREATE REL TABLE WRITES_TO(FROM Service, TO DataStore)
CREATE REL TABLE USES_ENV(FROM Service, TO EnvVar)
CREATE REL TABLE TRAVERSES(FROM Journey, TO Route, step_order INT64)Example Queries
-- Show all paths from login to database write
MATCH p = (r:Route {path: '/api/auth/login'})-[:USES_DTO]->(d:DTO)
RETURN p
-- Which services are affected by this env var?
MATCH (s:Service)-[:USES_ENV]->(e:EnvVar {name: 'DATABASE_URL'})
RETURN s.name, s.port
-- Find dead symbols (exported but never referenced)
MATCH (s:Symbol {exported: true})
WHERE NOT EXISTS { MATCH (other:Symbol)-[:REFERENCES]->(s) }
RETURN s.name, s.file, s.line
-- Trace a journey through all routes
MATCH (j:Journey {name: 'user-checkout'})-[t:TRAVERSES]->(r:Route)
RETURN r.method, r.path, t.step_order
ORDER BY t.step_orderLanguage Coverage
| Language Feature | Coverage | Notes |
|---|---|---|
| Python modules (AST) | 95% | Delegates to code-visualizer; dynamic imports missed |
| TypeScript/JS routes | 85% | Static grep-based; decorated routes (NestJS) require extra patterns |
| Go routes (chi/gin/echo) | 80% | Most router patterns covered; generated routes may be missed |
| .NET (ASP.NET Core) | 75% | Controllers and minimal API both covered; Razor Pages partially |
| Rust (axum/actix-web) | 70% | Core patterns covered; macro-heavy code harder to parse |
| gRPC services | 60% | Proto files provide contract; service mesh requires runtime data |
| GraphQL APIs | 40% | Not a primary target; resolver mapping requires special handling |
Code Atlas — Security Controls
Version: 1.1.0 Classification: Required reading before implementing any layer that writes to docs/atlas/
This document defines the security controls that every implementation contributing to the code atlas MUST enforce. Controls are numbered SEC-NN. CRITICAL and HIGH controls are not optional.
---
Control Summary
| Control | Severity | Area | Status |
|---|---|---|---|
| SEC-01 | CRITICAL | Secret redaction — env var values | Required |
| SEC-02 | CRITICAL | Path traversal prevention | Required |
| SEC-03 | HIGH | XSS prevention — label sanitization | Required |
| SEC-04 | HIGH | Safe config/manifest parsing | Required |
| SEC-05 | HIGH | Output confinement to docs/atlas/ | Required |
| SEC-06 | HIGH | Shell injection prevention | Required |
| SEC-07 | MEDIUM | Symlink attack prevention | Required |
| SEC-08 | MEDIUM | Large file DoS prevention | Required |
| SEC-09 | CRITICAL | Credential redaction in bug reports + L8 output | Required |
| SEC-10 | HIGH | DOT/Mermaid injection prevention (+ experiments/) | Required |
| SEC-11 | HIGH | Layer 7 service name sanitization | Required |
| SEC-12 | HIGH | Layer 8 LSP output sanitization | Required |
| SEC-13 | HIGH | Density threshold parameter validation | Required |
| SEC-14 | MEDIUM | Density prompt — accept only valid choices | Required |
| SEC-15 | CRITICAL | Credential redaction in all Layer 8 outputs | Required |
| SEC-16 | MEDIUM | Relative-path enforcement in evidence fields | Required |
| SEC-17 | HIGH | Recipe YAML parameter injection prevention | Required |
| SEC-18 | LOW | Experiment filename date/layer validation | Required |
| SEC-19 | HIGH | Git push output credential sanitization | Required |
---
CRITICAL Controls
SEC-01: Secret Value Redaction (CRITICAL)
Rule: When reading .env, .env.*, docker-compose.yml, Kubernetes Secrets, or any config file containing key=value pairs, extract key names only. Never write values to docs/atlas/.
Required output format:
DATABASE_URL=***REDACTED***
JWT_SECRET=***REDACTED***
REDIS_URL=***REDACTED***Implementation pattern:
# Safe: extract key names only
grep "^[A-Z_]" .env.example | cut -d= -f1
# Safe: show key=REDACTED pairs
grep "^[A-Z_]" .env | sed 's/=.*/=***REDACTED***/'
# UNSAFE — never do this:
cat .env # exposes values
grep "DATABASE_URL" .env # exposes connection string with passwordScope: Layer 6b (env var inventory), Layer 1 discovery (Docker Compose env: blocks), Pass 1 orphan detection, all bug report evidence fields. Scope extended in v1.1.0: also covers all Layer 8 output files (symbol-references.mmd, dead-code.md, mismatched-interfaces.md, README.md) and all Pass 3 per-journey verdict blocks (SEC-09 extension).
---
SEC-02: Path Traversal Prevention (CRITICAL)
Rule: All file reads must stay within codebase_path. Use realpath() to resolve the canonical path and assert it starts with codebase_path before reading.
Implementation pattern:
import os
def safe_read(codebase_path: str, relative_path: str) -> str:
"""Read a file, asserting it stays within codebase_path."""
canonical = os.path.realpath(os.path.join(codebase_path, relative_path))
if not canonical.startswith(os.path.realpath(codebase_path)):
raise SecurityError(f"Path traversal detected: {relative_path}")
with open(canonical) as f:
return f.read()# Safe: validate path before reading
canonical=$(realpath "$CODEBASE_PATH/$RELATIVE_FILE")
if [[ "$canonical" != "$CODEBASE_PATH"* ]]; then
echo "Error: path traversal detected" >&2
exit 1
fiTriggers: Any file discovery using find, glob, or user-provided paths.
---
SEC-09: Credential Redaction in Bug Reports (CRITICAL)
Rule: Before writing any code quote to a bug report's evidence[].content field, scan the content for credential patterns. Replace matched values with ***REDACTED***.
Credential patterns to redact:
password\s*=\s*\S+
passwd\s*=\s*\S+
secret\s*=\s*\S+
token\s*=\s*\S+
api_key\s*=\s*\S+
apikey\s*=\s*\S+
private_key\s*=\s*\S+
-----BEGIN.*PRIVATE KEY-----
[A-Za-z0-9+/]{40,}={0,2} # base64 blobs (API tokens)Implementation pattern:
import re
CREDENTIAL_PATTERNS = [
(r'(?i)(password|passwd|secret|token|api_key|apikey|private_key)\s*=\s*\S+',
r'\1=***REDACTED***'),
(r'-----BEGIN.*?PRIVATE KEY-----.*?-----END.*?PRIVATE KEY-----',
'***REDACTED PRIVATE KEY***'),
]
def redact_credentials(content: str) -> str:
for pattern, replacement in CREDENTIAL_PATTERNS:
content = re.sub(pattern, replacement, content)
return content---
HIGH Controls
SEC-03: Label Sanitization — XSS Prevention (HIGH)
Rule: All user-derived strings written into Mermaid, DOT, or SVG output must have HTML special characters escaped before rendering.
Required escaping:
| Character | Escape |
|---|---|
< | < |
> | > |
& | & |
" | " |
' | ' |
Implementation pattern:
def sanitize_label(raw: str) -> str:
"""Escape HTML special characters in diagram labels."""
return (raw
.replace('&', '&')
.replace('<', '<')
.replace('>', '>')
.replace('"', '"')
.replace("'", '''))Scope: All node labels, edge labels, subgraph titles, and inventory table cell values derived from source code identifiers, file paths, or route strings. Scope extended in v1.1.0 to include experiment docs under docs/atlas/experiments/ (SEC-10 extension).
---
SEC-04: Safe Manifest Parsing (HIGH)
Rule: Parse YAML and JSON using a safe parser with size limits. Never use eval or dynamic code execution to read config files.
Safe patterns:
import yaml
import json
# Safe YAML (never use yaml.load without Loader)
with open("docker-compose.yml") as f:
config = yaml.safe_load(f)
# Safe JSON
with open("package.json") as f:
pkg = json.load(f)# Safe: use yq or python for YAML parsing, not bash eval
yq e '.services | keys' docker-compose.yml
python3 -c "import yaml,sys; d=yaml.safe_load(sys.stdin); print(list(d.get('services',{}).keys()))" < docker-compose.ymlAnti-pattern:
# UNSAFE — never source .env files
source .env # executes arbitrary code
. .env.production # same risk
eval $(cat .env) # direct injection---
SEC-05: Output Confinement (HIGH)
Rule: All atlas output files must be written to docs/atlas/ or a user-configured output_dir. Never write outside the output directory.
Validation:
def safe_write(output_dir: str, relative_path: str, content: str) -> None:
canonical = os.path.realpath(os.path.join(output_dir, relative_path))
if not canonical.startswith(os.path.realpath(output_dir)):
raise SecurityError(f"Output path escapes output_dir: {relative_path}")
os.makedirs(os.path.dirname(canonical), exist_ok=True)
with open(canonical, 'w') as f:
f.write(content)---
SEC-06: Shell Injection Prevention (HIGH)
Rule: Never construct shell commands with unsanitized user input or file-derived strings. Use subprocess with argument arrays, never shell=True with string concatenation.
# Safe
import subprocess
result = subprocess.run(
["dot", "-Tsvg", input_path, "-o", output_path],
capture_output=True, timeout=30
)
# UNSAFE
os.system(f"dot -Tsvg {user_input} -o {output}") # shell injection
subprocess.run(f"mmdc -i {path}", shell=True) # shell injection---
SEC-10: DOT/Mermaid Injection Prevention (HIGH)
Rule: Code-derived strings inserted into DOT or Mermaid syntax must not allow diagram structure injection. Specifically:
- DOT labels: wrap in
"..."and escape embedded"as\" - Mermaid labels: wrap node labels in
["..."]syntax; escape[,],(,)in content - Route strings (e.g.
/api/users/:id): replace:with﹕(U+FE13) or wrap in quotes
DOT safe label:
def dot_label(raw: str) -> str:
return '"' + raw.replace('\\', '\\\\').replace('"', '\\"') + '"'Mermaid safe node:
def mermaid_node(node_id: str, label: str) -> str:
safe = label.replace('[', '[').replace(']', ']')
return f'{node_id}["{safe}"]'---
MEDIUM Controls
SEC-07: Symlink Attack Prevention (MEDIUM)
Rule: When discovering files with find/glob, check that resolved paths are not symlinks pointing outside codebase_path.
# Safe: resolve and validate before reading
for f in $(find . -name "*.go" -not -type l); do
# Process regular files only (-not -type l excludes symlinks)
process "$f"
done---
SEC-08: Large File DoS Prevention (MEDIUM)
Rule: Skip files larger than 10MB during discovery. Log a SkillError with code FILE_TOO_LARGE and continue.
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
def safe_read_bounded(path: str) -> str | None:
stat = os.stat(path)
if stat.st_size > MAX_FILE_SIZE:
log_skill_error("FILE_TOO_LARGE", path, f"Skipped: {stat.st_size} bytes exceeds 10MB limit")
return None
with open(path) as f:
return f.read()---
---
Controls Added in v1.1.0 (SEC-11 through SEC-19)
SEC-11: Layer 7 Service Name Sanitization (HIGH)
Rule: Service names used as filenames in docs/atlas/service-components/ must be sanitised to [a-zA-Z0-9_-]{1,64} before any filesystem path construction. Apply realpath() boundary check identical to SEC-02 to confirm output stays within output_dir.
Implementation pattern:
import re
import os
SERVICE_NAME_PATTERN = re.compile(r'^[a-zA-Z0-9_-]{1,64}$')
def safe_service_name(raw: str) -> str:
"""Sanitise a service name for use in filesystem paths."""
# Replace unsafe chars with hyphens, truncate to 64
sanitised = re.sub(r'[^a-zA-Z0-9_-]', '-', raw)[:64]
if not SERVICE_NAME_PATTERN.match(sanitised):
raise SecurityError(f"Service name cannot be sanitised: {raw!r}")
return sanitised
def layer7_output_path(output_dir: str, service_name: str) -> str:
safe_name = safe_service_name(service_name)
path = os.path.join(output_dir, "service-components", f"{safe_name}.mmd")
canonical = os.path.realpath(path)
if not canonical.startswith(os.path.realpath(output_dir)):
raise SecurityError(f"Path traversal detected for service: {service_name!r}")
return canonicalAnti-pattern: Never use a raw service name (from docker-compose, k8s, or any file) directly in a path without this sanitisation.
---
SEC-12: Layer 8 LSP Output Sanitization (HIGH)
Rule: All data returned by the lsp-setup skill (symbol names, file paths, type signatures, call contexts) is treated as untrusted input before embedding in any atlas file.
Required steps:
1. Validate JSON schema of LSPSymbolReport before accessing fields 2. Apply SEC-03 HTML-escaping to all symbol names and type strings written to .mmd files 3. Apply SEC-02 path boundary check to all file fields before using in evidence links 4. Apply SEC-09 credential pattern scan to all context (surrounding code) fields
def sanitise_lsp_output(report: dict, codebase_path: str) -> dict:
"""Sanitise all LSP output fields before atlas embedding."""
for symbol in report.get("symbols", []):
symbol["name"] = sanitize_label(symbol["name"]) # SEC-03
symbol["file"] = validate_relative_path( # SEC-02
symbol["file"], codebase_path)
for ref in symbol.get("references", []):
ref["context"] = redact_credentials(ref["context"]) # SEC-09
ref["file"] = validate_relative_path(ref["file"], codebase_path)
return report---
SEC-13: Density Threshold Parameter Validation (HIGH)
Rule: The --density-threshold override parameter must be validated as positive integers in range 1–10,000. Reject values outside this range with a clear error message and halt the invocation.
Rejected values:
| Value | Reason |
|---|---|
0 | Disables guard via spam; not a meaningful threshold |
| Negative numbers | Invalid; makes no semantic sense |
| Non-integers | Parameter type violation |
> 10,000 | Effectively disables guard for any real codebase |
null, undefined, empty | Reverts to defaults (no error) |
def validate_density_threshold(nodes: any, edges: any) -> tuple[int, int]:
for name, value in [("nodes", nodes), ("edges", edges)]:
if not isinstance(value, int):
raise ValueError(f"density-threshold {name} must be an integer, got: {value!r}")
if not (1 <= value <= 10_000):
raise ValueError(
f"density-threshold {name}={value} out of valid range 1–10,000"
)
return int(nodes), int(edges)---
SEC-14: Density Prompt — Accept Only Valid Choices (MEDIUM)
Rule: The density prompt accepts only 'a', 'b', or 'c' (case-insensitive, whitespace-stripped). Any other input must re-prompt. Never silently default or fall through to a hidden choice.
VALID_DENSITY_CHOICES = {'a', 'b', 'c'}
def prompt_density_choice(node_count: int, edge_count: int) -> str:
while True:
raw = input(
f"This diagram has {node_count} nodes and {edge_count} edges, "
f"which may render poorly.\n"
f"Please choose:\n"
f" (a) Full diagram anyway\n"
f" (b) Simplified/clustered diagram\n"
f" (c) Table representation\n"
f"> "
).strip().lower()
if raw in VALID_DENSITY_CHOICES:
log_audit(f"density_choice={raw}") # Log choice, not raw input
return raw
print(f"Invalid choice: {raw!r}. Please enter a, b, or c.")
# Loop: re-prompt unconditionallyNon-interactive context (CI/batch): Default to 'b'; log SkillError with DENSITY_THRESHOLD_EXCEEDED. Never default silently.
---
SEC-15: Credential Redaction in All Layer 8 Outputs (CRITICAL)
Rule: The CREDENTIAL_PATTERNS regex from SEC-09 must be applied before writing each of the four Layer 8 output files. This is a mandatory step in the SecureAtlasBuilder pipeline for Layer 8.
Files that require redaction:
docs/atlas/ast-lsp-bindings/symbol-references.mmddocs/atlas/ast-lsp-bindings/dead-code.mddocs/atlas/ast-lsp-bindings/mismatched-interfaces.mddocs/atlas/ast-lsp-bindings/README.md
Caution: The CREDENTIAL_PATTERNS for Layer 8 must use targeted key=value format patterns — not bare base64 scanning — to avoid false positives on legitimate symbol names that happen to be long alphanumeric strings.
LAYER8_CREDENTIAL_PATTERNS = [
# key=value patterns only (not bare base64, to avoid false positives on symbol names)
(r'(?i)(password|passwd|secret|token|api_key|apikey|private_key)\s*=\s*\S+',
r'\1=***REDACTED***'),
(r'-----BEGIN.*?PRIVATE KEY-----.*?-----END.*?PRIVATE KEY-----',
'***REDACTED PRIVATE KEY***'),
(r'https?://[^@\s]+@', # URLs with embedded credentials
'https://***@'),
]---
SEC-16: Relative-Path Enforcement in Evidence Fields (MEDIUM)
Rule: All file:line evidence references in Pass 3 verdict blocks and in all bug reports must be relative to codebase_path. Absolute paths are rejected.
import os
def validate_relative_path(path: str, codebase_path: str) -> str:
"""Ensure path is relative to codebase_path and stays within it."""
if os.path.isabs(path):
raise SecurityError(f"Absolute path in evidence: {path!r}. Must be relative.")
canonical = os.path.realpath(os.path.join(codebase_path, path))
if not canonical.startswith(os.path.realpath(codebase_path)):
raise SecurityError(f"Path escapes codebase root: {path!r}")
return os.path.relpath(canonical, os.path.realpath(codebase_path))Anti-pattern: Never write /home/user/project/src/orders.ts:47 in an evidence field. Write src/orders.ts:47 instead.
---
SEC-17: Recipe YAML Parameter Injection Prevention (HIGH)
Rule: Recipe YAML parameters (codebase_path, output_dir) must be passed as structured data to sub-skills — never interpolated into shell command strings. Use yaml.safe_load() for recipe loading. Validate codebase_path at recipe entry.
Validation at recipe entry:
import yaml
import re
NULL_BYTE_PATTERN = re.compile(r'\x00')
SHELL_META_PATTERN = re.compile(r'[;&|`$><\\!]')
def validate_recipe_path(raw: str) -> str:
"""Validate a path parameter from recipe YAML."""
if NULL_BYTE_PATTERN.search(raw):
raise ValueError(f"Null byte in codebase_path: {raw!r}")
if SHELL_META_PATTERN.search(raw):
raise ValueError(f"Shell metacharacter in codebase_path: {raw!r}")
return raw
# Safe recipe loading (never yaml.load())
with open("amplifier-bundle/recipes/code-atlas.yaml") as f:
recipe = yaml.safe_load(f)
codebase_path = validate_recipe_path(recipe["parameters"]["codebase_path"])---
SEC-18: Experiment Filename Date/Layer Validation (LOW)
Rule: Experiment filenames under docs/atlas/experiments/ use system date (datetime.date.today().isoformat()) and a validated layer ID from the allowlist {1, 2, 3, 4, 5, 6, 7, 8}. The layer ID must never come from raw user input without integer validation against this allowlist.
import datetime
VALID_LAYER_IDS = frozenset({1, 2, 3, 4, 5, 6, 7, 8})
def experiment_filename(layer_id: any, renderer: str) -> str:
if not isinstance(layer_id, int) or layer_id not in VALID_LAYER_IDS:
raise ValueError(f"Layer ID must be in {VALID_LAYER_IDS}, got: {layer_id!r}")
safe_renderer = re.sub(r'[^a-z-]', '', renderer.lower())[:20]
date_str = datetime.date.today().isoformat()
return f"{date_str}-{safe_renderer}-L{layer_id}.md"---
SEC-19: Git Push Output Credential Sanitization (HIGH)
Rule: Git push stdout and stderr must be sanitised with the CREDENTIAL_URL_PATTERN before any display or logging. Replace embedded credentials in URLs with https://***@.
import re
import subprocess
CREDENTIAL_URL_PATTERN = re.compile(r'https?://[^@\s]+@')
def safe_git_push(remote: str, branch: str) -> None:
result = subprocess.run(
["git", "push", remote, branch],
capture_output=True, text=True
)
safe_stdout = CREDENTIAL_URL_PATTERN.sub('https://***@', result.stdout)
safe_stderr = CREDENTIAL_URL_PATTERN.sub('https://***@', result.stderr)
print(safe_stdout)
if result.returncode != 0:
raise RuntimeError(f"git push failed: {safe_stderr}")---
SecureAtlasBuilder Pipeline
All layer implementations MUST follow this pipeline order:
1. Receive codebase_path (validated by SEC-02 at skill entry; SEC-17 if from recipe YAML)
2. Discover files (SEC-07: skip symlinks; SEC-08: skip >10MB)
3. Parse manifests/configs (SEC-04: safe parsers only)
4. Extract key names for env vars (SEC-01: values never collected)
5. Build node/edge data structures (plain Python objects — no shell)
6. Sanitize all labels (SEC-03: escape HTML specials; SEC-11 for Layer 7 service names)
7. Check density (ALL layers): if node_count > 50 OR edge_count > 100 → invoke density prompt
a. Validate threshold override (SEC-13: integer range 1–10,000)
b. Prompt user, accept only a/b/c (SEC-14: re-prompt on invalid input)
8. Generate diagram syntax (SEC-10: injection-safe label wrapping)
9. If Layer 8: sanitise all LSP output before embedding (SEC-12)
10. Write to output_dir (SEC-05: path confinement validated)
11. If Layer 8: apply LAYER8_CREDENTIAL_PATTERNS to all four output files (SEC-15)
12. If writing bug reports or Pass 3 verdicts:
a. Redact credentials (SEC-09)
b. Validate all evidence paths are relative (SEC-16: reject absolute paths)
13. If writing experiments/: validate layer ID from allowlist; use system date (SEC-18)
14. If git push: sanitise stdout/stderr with CREDENTIAL_URL_PATTERN (SEC-19)---
Per-Language Safe Parsing
| Source | Safe Method | Unsafe — Never Use |
|---|---|---|
.env files | `grep "^[A-Z_]" \ | cut -d= -f1` |
docker-compose.yml | yaml.safe_load(), yq e | yaml.load(), bash eval |
package.json | json.load(), jq | eval, require() with untrusted paths |
| Go source | Regex on file content | go run with untrusted code |
.csproj | xml.etree.ElementTree.parse() | lxml with resolve_entities=True |
| Kubernetes Secrets | Extract metadata.name only | Never read data: or stringData: blocks |
---
Security Checklist
Before any layer implementation is considered complete:
- [ ] SEC-01: Env var values are never written to any output file
- [ ] SEC-02: All file reads use
realpath()boundary validation - [ ] SEC-03: All diagram labels have HTML special characters escaped
- [ ] SEC-04: All YAML/JSON parsed with safe loaders (no eval, no source)
- [ ] SEC-05: All output files written inside
output_dirwith path validation - [ ] SEC-06: No shell=True subprocess calls with variable interpolation
- [ ] SEC-07: Symlinks excluded from file discovery
- [ ] SEC-08: Files >10MB skipped with SkillError logged
- [ ] SEC-09: Bug report evidence fields (+ Layer 8 outputs + Pass 3 verdicts) scanned for credential patterns
- [ ] SEC-10: DOT/Mermaid label strings are injection-safe (includes experiments/ output)
- [ ] SEC-11: Layer 7 service names sanitised to
[a-zA-Z0-9_-]{1,64}before path construction - [ ] SEC-12: Layer 8 LSP output validated (schema + SEC-03 + SEC-02 + SEC-09 applied to all fields)
- [ ] SEC-13:
--density-thresholdvalues validated as integers in range 1–10,000 - [ ] SEC-14: Density prompt only accepts
a,b,c; re-prompts on any other input - [ ] SEC-15: LAYER8_CREDENTIAL_PATTERNS applied before writing all four Layer 8 output files
- [ ] SEC-16: All evidence
file:linereferences useos.path.relpath()— no absolute paths - [ ] SEC-17: Recipe YAML
codebase_path/output_dirvalidated (no null bytes, no shell metacharacters) - [ ] SEC-18: Experiment filenames use system date + allowlisted layer ID only
- [ ] SEC-19: Git push output sanitised with CREDENTIAL_URL_PATTERN before display or logging
---
_This document must be read before implementing Layer 1 (env discovery), Layer 3 (route extraction), Layer 6 (inventory tables), or the bug-hunting passes._
#!/bin/bash
# .claude/skills/code-atlas/tests/run_all_tests.sh
#
# Unified test runner for the code-atlas skill.
# Runs all test suites and reports a combined pass/fail summary.
#
# Usage:
# bash .claude/skills/code-atlas/tests/run_all_tests.sh
# bash .claude/skills/code-atlas/tests/run_all_tests.sh --fast # skip integration tests
#
# Exit: 0 = all suites passed, non-zero = one or more failures
#
# Test Suites:
# 1. test_staleness_triggers.sh — Layer detection for all 8 layer patterns
# 2. test_rebuild_script.sh — rebuild-atlas-all.sh behaviors
# 3. test_security_controls.sh — SEC-01 through SEC-10 controls
# 4. test_atlas_output_structure.sh — docs/atlas/ output directory structure
# 5. test_layer_contracts.sh — Per-layer content contracts (Layers 1–8)
# 6. test_bug_hunt_workflow.sh — Three-pass bug hunt report format
# 7. test_ci_workflow.sh — CI YAML structure and script path checks
# 8. test_publication_workflow.sh — SVG generation and GitHub Pages readiness
# 9. test_layer7_8.sh — Layer 7/8 output contracts + SEC-11/12/15/16
# 10. test_no_silent_degradation.sh — Density guard FORBIDDEN_PATTERNS §2 compliance
# Intentionally omits -e: test failures must not abort the suite runner.
# Individual test scripts use set -euo pipefail.
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FAST_MODE=false
[[ "${1:-}" == "--fast" ]] && FAST_MODE=true
# ---------------------------------------------------------------------------
# ANSI colors (if terminal supports them)
# ---------------------------------------------------------------------------
if [[ -t 1 ]]; then
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RESET='\033[0m'
BOLD='\033[1m'
else
RED=''; GREEN=''; YELLOW=''; RESET=''; BOLD=''
fi
# ---------------------------------------------------------------------------
# Suite runner
# ---------------------------------------------------------------------------
TOTAL_PASS=0
TOTAL_FAIL=0
SUITE_RESULTS=()
run_suite() {
local name="$1"
local script="$2"
local skip_in_fast="${3:-false}"
if [[ "$FAST_MODE" == "true" && "$skip_in_fast" == "true" ]]; then
echo -e "${YELLOW}SKIP${RESET}: $name (--fast mode)"
SUITE_RESULTS+=("SKIP: $name")
return
fi
echo ""
echo -e "${BOLD}━━━ Suite: $name ━━━${RESET}"
if [[ ! -f "$script" ]]; then
echo -e "${RED}ERROR${RESET}: Script not found: $script"
SUITE_RESULTS+=("ERROR: $name — script not found")
TOTAL_FAIL=$((TOTAL_FAIL + 1))
return
fi
# Run the suite, capture output and exit code
suite_output=$(bash "$script" 2>&1)
suite_exit=$?
# Show output
echo "$suite_output"
# Extract pass/fail counts — single grep, then pure bash string ops (no PCRE, no extra forks).
local results_line
results_line=$(grep -o 'Results: [0-9]* passed, [0-9]* failed' <<< "$suite_output" | tail -1)
if [[ -n "$results_line" ]]; then
pass_count="${results_line#Results: }"; pass_count="${pass_count%% *}"
fail_count="${results_line##*, }"; fail_count="${fail_count%% *}"
else
pass_count=0
fail_count=0
fi
TOTAL_PASS=$((TOTAL_PASS + pass_count))
TOTAL_FAIL=$((TOTAL_FAIL + fail_count))
if [[ "$suite_exit" -eq 0 ]]; then
SUITE_RESULTS+=("$(echo -e "${GREEN}PASS${RESET}"): $name ($pass_count passed)")
else
SUITE_RESULTS+=("$(echo -e "${RED}FAIL${RESET}"): $name ($pass_count passed, $fail_count failed)")
fi
}
# ---------------------------------------------------------------------------
# Header
# ---------------------------------------------------------------------------
echo ""
echo -e "${BOLD}╔════════════════════════════════════════╗${RESET}"
echo -e "${BOLD}║ Code Atlas — TDD Test Runner ║${RESET}"
echo -e "${BOLD}╚════════════════════════════════════════╝${RESET}"
echo ""
echo "Running all test suites..."
[[ "$FAST_MODE" == "true" ]] && echo "(Fast mode: integration tests skipped)"
# ---------------------------------------------------------------------------
# Suite 1: Staleness Triggers
# ---------------------------------------------------------------------------
run_suite \
"Staleness Triggers (check-atlas-staleness.sh)" \
"${SCRIPT_DIR}/test_staleness_triggers.sh"
# ---------------------------------------------------------------------------
# Suite 2: Rebuild Script
# ---------------------------------------------------------------------------
run_suite \
"Rebuild Script (rebuild-atlas-all.sh)" \
"${SCRIPT_DIR}/test_rebuild_script.sh"
# ---------------------------------------------------------------------------
# Suite 3: Security Controls
# ---------------------------------------------------------------------------
run_suite \
"Security Controls (SEC-01 through SEC-10)" \
"${SCRIPT_DIR}/test_security_controls.sh"
# ---------------------------------------------------------------------------
# Suite 4: Atlas Output Structure
# ---------------------------------------------------------------------------
run_suite \
"Atlas Output Structure (docs/atlas/ directory contract)" \
"${SCRIPT_DIR}/test_atlas_output_structure.sh" \
"false" # not skipped in fast mode — but tests will fail until /code-atlas runs
# ---------------------------------------------------------------------------
# Suite 5: Layer Content Contracts
# ---------------------------------------------------------------------------
run_suite \
"Layer Content Contracts (per-layer output requirements)" \
"${SCRIPT_DIR}/test_layer_contracts.sh"
# ---------------------------------------------------------------------------
# Suite 6: Bug Hunt Workflow
# ---------------------------------------------------------------------------
run_suite \
"Bug Hunt Workflow (Pass 1 + Pass 2 report format)" \
"${SCRIPT_DIR}/test_bug_hunt_workflow.sh"
# ---------------------------------------------------------------------------
# Suite 7: CI Workflow
# ---------------------------------------------------------------------------
run_suite \
"CI Workflow (atlas-ci.yml structure + integration)" \
"${SCRIPT_DIR}/test_ci_workflow.sh"
# ---------------------------------------------------------------------------
# Suite 8: Publication Workflow
# ---------------------------------------------------------------------------
run_suite \
"Publication Workflow (SVG generation + GitHub Pages readiness)" \
"${SCRIPT_DIR}/test_publication_workflow.sh"
# ---------------------------------------------------------------------------
# Suite 9: Layer 7 and Layer 8 Contracts (v1.1.0)
# ---------------------------------------------------------------------------
run_suite \
"Layer 7 and 8 Contracts (service components + AST/LSP bindings)" \
"${SCRIPT_DIR}/test_layer7_8.sh"
# ---------------------------------------------------------------------------
# Suite 10: No Silent Degradation — FORBIDDEN_PATTERNS §2 Compliance (v1.1.0)
# ---------------------------------------------------------------------------
run_suite \
"No Silent Degradation (density guard + FORBIDDEN_PATTERNS §2)" \
"${SCRIPT_DIR}/test_no_silent_degradation.sh"
# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
echo ""
echo -e "${BOLD}════════════════════════════════════════${RESET}"
echo -e "${BOLD} Test Suite Summary ${RESET}"
echo -e "${BOLD}════════════════════════════════════════${RESET}"
echo ""
for result in "${SUITE_RESULTS[@]}"; do
echo " $result"
done
echo ""
echo -e " Total: ${GREEN}${TOTAL_PASS} passed${RESET}, ${RED}${TOTAL_FAIL} failed${RESET}"
echo ""
if [[ "$TOTAL_FAIL" -gt 0 ]]; then
echo -e "${RED}Some tests failed.${RESET}"
echo ""
echo "Expected failures (require /code-atlas to run first):"
echo " • test_atlas_output_structure.sh: docs/atlas/ doesn't exist (run /code-atlas first)"
echo " • test_layer_contracts.sh: docs/atlas/ doesn't exist (run /code-atlas first)"
echo " • test_publication_workflow.sh: SVGs not generated (run /code-atlas publish first)"
echo " • test_bug_hunt_workflow.sh: bug reports not generated (run /code-atlas first)"
echo " • test_layer7_8.sh (output structure section): layer7/8 dirs not yet created (run /code-atlas first)"
echo " • test_no_silent_degradation.sh: should pass on documentation alone (no atlas run needed)"
echo ""
echo "Unexpected failures need investigation."
exit 1
else
echo -e "${GREEN}All 10 test suites passed. Atlas skill is fully implemented.${RESET}"
exit 0
fi
#!/bin/bash
# .claude/skills/code-atlas/tests/test_publication_workflow.sh
#
# TDD tests for atlas publication workflow:
# - SVG companion generation (dot → SVG, mmd → SVG)
# - mkdocs navigation structure
# - GitHub Pages readiness (all referenced files exist)
# - index.md landing page quality
#
# THESE TESTS WILL FAIL until publication workflow is implemented.
#
# Usage: bash .claude/skills/code-atlas/tests/test_publication_workflow.sh [atlas_dir]
# Exit: 0 = all tests passed, non-zero = failures
set -uo pipefail
shopt -s globstar nullglob # enable ** recursive globs; unmatched globs expand to nothing
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
ATLAS="${1:-${REPO_ROOT}/docs/atlas}"
PASS=0
FAIL=0
# ---------------------------------------------------------------------------
# Test harness
# ---------------------------------------------------------------------------
assert_file_exists() {
local label="$1"; local path="$2"
if [[ -f "$path" ]]; then
echo "PASS: $label"; PASS=$((PASS + 1))
else
echo "FAIL: $label — not found: $path"; FAIL=$((FAIL + 1))
fi
}
assert_file_contains() {
local label="$1"; local pattern="$2"; local file="$3"
if [[ ! -f "$file" ]]; then
echo "FAIL: $label — file not found: $file"; FAIL=$((FAIL + 1)); return
fi
if grep -q "$pattern" "$file" 2>/dev/null; then
echo "PASS: $label"; PASS=$((PASS + 1))
else
echo "FAIL: $label — pattern '$pattern' not in $file"; FAIL=$((FAIL + 1))
fi
}
assert_file_size_gt() {
local label="$1"; local file="$2"; local min_bytes="$3"
if [[ ! -f "$file" ]]; then
echo "FAIL: $label — file not found: $file"; FAIL=$((FAIL + 1)); return
fi
size=$(wc -c < "$file" 2>/dev/null || echo 0)
if [[ "$size" -gt "$min_bytes" ]]; then
echo "PASS: $label (${size} bytes)"
PASS=$((PASS + 1))
else
echo "FAIL: $label — file too small (${size} bytes, expected > ${min_bytes})"
FAIL=$((FAIL + 1))
fi
}
# ============================================================================
# Test Group 1: SVG Companion Files
# ============================================================================
echo ""
echo "=== SVG Companion Files ==="
# Every .mmd and .dot file must have a matching .svg companion
for mmd_file in "${ATLAS}"/**/*.mmd "${ATLAS}"/*.mmd; do
[[ -f "$mmd_file" ]] || continue
svg_file="${mmd_file%.mmd}.svg"
layer_dir=$(dirname "$mmd_file" | sed "s|${REPO_ROOT}/||")
fname=$(basename "$mmd_file")
assert_file_exists "SVG exists for ${layer_dir}/${fname}" "$svg_file"
if [[ -f "$svg_file" ]]; then
assert_file_size_gt "SVG not empty: ${fname%.mmd}.svg" "$svg_file" 100
assert_file_contains "SVG has valid SVG content" "<svg\|xmlns.*svg" "$svg_file"
fi
done
for dot_file in "${ATLAS}"/**/*.dot "${ATLAS}"/*.dot; do
[[ -f "$dot_file" ]] || continue
svg_file="${dot_file%.dot}.svg"
layer_dir=$(dirname "$dot_file" | sed "s|${REPO_ROOT}/||")
fname=$(basename "$dot_file")
assert_file_exists "SVG exists for ${layer_dir}/${fname}" "$svg_file"
if [[ -f "$svg_file" ]]; then
assert_file_size_gt "SVG not empty: ${fname%.dot}.svg" "$svg_file" 100
assert_file_contains "SVG has valid SVG content (dot)" "<svg\|xmlns.*svg" "$svg_file"
fi
done
# ============================================================================
# Test Group 2: index.md Landing Page Quality
# ============================================================================
echo ""
echo "=== index.md Landing Page ==="
INDEX="${ATLAS}/index.md"
assert_file_exists "docs/atlas/index.md exists" "$INDEX"
if [[ -f "$INDEX" ]]; then
# Must have a title heading
assert_file_contains "index.md: has H1 title" "^# " "$INDEX"
# Must link to all 8 layers
for layer in "layer1" "layer2" "layer3" "layer4" "layer5" "layer6"; do
assert_file_contains "index.md: links to $layer" "$layer" "$INDEX"
done
# Must link to bug-reports
assert_file_contains "index.md: links to bug-reports" "bug-report\|[Bb]ug [Rr]eport" "$INDEX"
# Must mention atlas generation date or .build-stamp reference
assert_file_contains "index.md: has generation metadata" \
"[Gg]enerated\|[Bb]uilt\|[Cc]reated\|[Rr]efreshed\|[Aa]tlas" "$INDEX"
# Must NOT contain raw paths (should use relative links)
if grep -q "^/home/\|^/tmp/\|^/root/" "$INDEX" 2>/dev/null; then
echo "FAIL: index.md contains absolute filesystem paths (should use relative links)"
FAIL=$((FAIL + 1))
else
echo "PASS: index.md uses relative links (no absolute paths)"
PASS=$((PASS + 1))
fi
fi
# ============================================================================
# Test Group 3: Layer README Files Quality
# ============================================================================
echo ""
echo "=== Layer README Files ==="
for layer_dir in repo-surface compile-deps api-contracts data-flow user-journeys inventory; do
readme="${ATLAS}/${layer_dir}/README.md"
assert_file_exists "${layer_dir}/README.md exists" "$readme"
if [[ -f "$readme" ]]; then
# Must have H1 title
assert_file_contains "${layer_dir}/README.md: has H1" "^# " "$readme"
# Must have at least 100 chars of content (not just a title)
char_count=$(wc -c < "$readme" 2>/dev/null || echo 0)
if [[ "$char_count" -gt 100 ]]; then
echo "PASS: ${layer_dir}/README.md: has meaningful content (${char_count} chars)"
PASS=$((PASS + 1))
else
echo "FAIL: ${layer_dir}/README.md: too short (${char_count} chars, need > 100)"
FAIL=$((FAIL + 1))
fi
# Must NOT contain absolute paths
if grep -q "^/home/\|^/tmp/\|^/root/" "$readme" 2>/dev/null; then
echo "FAIL: ${layer_dir}/README.md: contains absolute filesystem paths"
FAIL=$((FAIL + 1))
else
echo "PASS: ${layer_dir}/README.md: no absolute paths"
PASS=$((PASS + 1))
fi
fi
done
# ============================================================================
# Test Group 4: mkdocs Integration File
# ============================================================================
echo ""
echo "=== mkdocs Integration ==="
MKDOCS="${REPO_ROOT}/mkdocs.yml"
if [[ -f "$MKDOCS" ]]; then
# mkdocs.yml must reference atlas layers in nav
assert_file_contains "mkdocs.yml: references Code Atlas" "Code Atlas\|atlas" "$MKDOCS"
assert_file_contains "mkdocs.yml: references layer1" "layer1\|Runtime Topology" "$MKDOCS"
assert_file_contains "mkdocs.yml: references layer6" "layer6\|Inventory" "$MKDOCS"
assert_file_contains "mkdocs.yml: references bug-reports" "bug-report\|Bug Report" "$MKDOCS"
else
echo "SKIP: mkdocs.yml not present (not required for initial implementation)"
fi
# ============================================================================
# Test Group 5: GitHub Pages Readiness
# ============================================================================
echo ""
echo "=== GitHub Pages Readiness ==="
# All internal links in index.md must resolve to real files
if [[ -f "$INDEX" ]]; then
broken_links=0
while IFS= read -r link; do
# Extract relative path from markdown link [text](path)
link_path="${ATLAS}/${link}"
if [[ ! -f "$link_path" && ! -d "$link_path" ]]; then
echo "FAIL: GitHub Pages: broken link in index.md → $link"
broken_links=$((broken_links + 1))
FAIL=$((FAIL + 1))
fi
done < <(grep -oP '\]\(\K[^)]+' "$INDEX" 2>/dev/null | grep -v "^http\|^#" | head -30)
if [[ "$broken_links" -eq 0 ]]; then
echo "PASS: GitHub Pages: all internal links in index.md resolve"
PASS=$((PASS + 1))
fi
fi
# All SVGs must be valid (not empty, contain <svg> tag)
svg_count=0
invalid_svg=0
while IFS= read -r svg_file; do
svg_count=$((svg_count + 1))
if ! grep -q "<svg" "$svg_file" 2>/dev/null; then
echo "FAIL: Invalid SVG (no <svg> tag): $svg_file"
invalid_svg=$((invalid_svg + 1))
FAIL=$((FAIL + 1))
fi
done < <(find "${ATLAS}" -name "*.svg" 2>/dev/null)
if [[ "$svg_count" -gt 0 && "$invalid_svg" -eq 0 ]]; then
echo "PASS: GitHub Pages: all $svg_count SVG files are valid"
PASS=$((PASS + 1))
elif [[ "$svg_count" -eq 0 ]]; then
echo "FAIL: GitHub Pages: no SVG files found — publication workflow not run"
FAIL=$((FAIL + 1))
fi
# ============================================================================
# Test Group 6: Staleness Map YAML Contract
# ============================================================================
echo ""
echo "=== Staleness Map YAML ==="
STALENESS_MAP="${ATLAS}/.staleness-map.yaml"
# staleness-map.yaml is generated alongside atlas and tracks layer build times
# This file is referenced in API-CONTRACTS.md
assert_file_exists "docs/atlas/.staleness-map.yaml exists" "$STALENESS_MAP"
if [[ -f "$STALENESS_MAP" ]]; then
# Must have entries for all 8 layers
for layer in 1 2 3 4 5 6; do
assert_file_contains ".staleness-map.yaml: layer $layer entry" \
"layer${layer}\|layer_${layer}" "$STALENESS_MAP"
done
# Must have last_built timestamps
assert_file_contains ".staleness-map.yaml: last_built field" \
"last_built\|built_at\|timestamp" "$STALENESS_MAP"
# Must have git ref
assert_file_contains ".staleness-map.yaml: git_ref field" \
"git_ref\|git.ref\|commit" "$STALENESS_MAP"
fi
# ---------------------------------------------------------------------------
# Results
# ---------------------------------------------------------------------------
echo ""
echo "=================================="
echo "Results: ${PASS} passed, ${FAIL} failed"
echo "=================================="
echo ""
echo "NOTE: SVG and publication tests fail until 'mmdc'/'dot' render commands run."
echo "Run: /code-atlas publish — to generate SVGs and publish to docs/atlas/"
[[ $FAIL -eq 0 ]] && exit 0 || exit 1