--- name: bundle-to-dot description: "Convention for the v3 bundle documentation system: a single bundle.dot + bundle.png per repo, generated by bundle_repo_dot(). Use when generating, validating, or interpreting bundle documentation files. Covers 7-cluster DOT structure, token cost model, color conventions, external reference distinction, freshness tracking via source_hash, generation recipes, and the lifecycle model." version: 3.0.0 --- # Bundle Documentation Convention (v3) ## Overview The v3 bundle documentation system produces a single DOT diagram per repository: | Output | What it is | Location | |--------|-----------|----------| | `bundle.dot` | Full 7-cluster structural diagram of the entire repo | Repo root | | `bundle.png` | Rendered PNG of the diagram | Repo root | Both files embed a `source_hash` for freshness tracking. The diagram is generated by calling `bundle_repo_dot(repo_root)` from `amplifier_foundation.bundle_docs`. --- ## What the DOT Shows The `bundle.dot` diagram maps the entire repository into **7 cluster subgraphs**: | Cluster | Directory | What it contains | |---------|-----------|-----------------| | **Behaviors** | `behaviors/` | Reusable capability packages (thin bundles) | | **Standalones** | `bundles/` | Self-contained session bundles | | **Agents** | `agents/` | Agent `.md` files with frontmatter | | **Modules** | tools/modules | Tool and module declarations | | **Providers** | `providers/` | Provider configurations | | **Experiments** | `experiments/` | Experimental bundles (exp-* naming) | | **Context Files** | `context/` | Shared context files | The root bundle node is rendered at the center with edges to the clusters that it composes. External references (bundles from other repos) appear with visual distinction (see **External References** below). --- ## Token Cost Model The structural DOT encodes the **token cost** of each component: | Component | Cost source | |-----------|------------| | Tool/module | Tool schema token count (estimated from schema YAML) | | Agent | `meta.description` token count + body | | Context file | Full file content token count (recursive @mention expansion) | | Bundle instruction | Markdown body token count | Edges in the DOT reflect composition relationships. Heavier nodes (high token count) appear in more prominent visual styles. The summary node at the bottom of each diagram shows total estimated token cost for the composition. --- ## Visual Conventions ### Node Colors (actual code constants from `bundle_to_dot.py`) | Element | Fill color | Hex | Notes | |---------|-----------|-----|-------| | Root bundle | teal/mint | `#80cbc4` | `bundle.md` at repo root | | Behavior | light teal | `#e0f2f1` | Entries in `behaviors/` | | Standalone | teal/mint | `#80cbc4` | Entries in `bundles/` (same as root) | | Agent | light green | `#c8e6c9` | Agent `.md` files | | Module/tool | light blue | `#bbdefb` | Tool/module declarations | | Provider | light grey | `#e0e0e0` | Provider configurations | | Experiment | light purple | `#e1bee7` | Entries in `experiments/` | | Context file | light purple | `#e1bee7` | Context `.md` files | | Cluster fill | near white | `#f9f9f9` | Subgraph background | | Summary node | blue-grey | `#eceff1` | Cost summary footer node | ### External References External bundles (referenced by URI, not local to the repo) are visually distinct from local nodes: | Edge style | Meaning | |------------|---------| | **Solid** | Local reference — included in token cost count | | **Dashed + red border** | External with hidden cost (`_COLOR_EXTERNAL_COST = "red"`) — the external bundle contributes tokens at runtime but is NOT counted in the local total | | **Dashed + muted fill** (`#f5f5f5`) | External with no additional cost — referenced externally but costs are borne elsewhere | The legend node embedded in the DOT explains these conventions inline. ### LLM Enhancement By default, the `generate-bundle-docs` recipe sends the structural DOT to `foundation:zen-architect` for **label enhancement**: node labels are rewritten with concise, accessible English summaries rather than raw filenames. To skip LLM enhancement (structural-only, faster): ```yaml # In recipe context enhance_diagrams: "false" ``` Rules for the LLM enhancement step: - Keep ALL structural elements unchanged (node IDs, edges, shapes, colors, clusters) - ONLY rewrite `label="..."` values on nodes and clusters, plus the graph title - Keep the `source_hash="..."` graph attribute exactly as-is - Labels must be ≤2-3 lines; use `\n` for line breaks --- ## Freshness Model `bundle.dot` embeds `source_hash=""` as a graph attribute. The hash is derived from all repository entry points combined (all bundle, behavior, agent, tool, context, and hook files). If any of these change, the hash changes and `bundle.dot` is considered stale. ### Findings | Code | Severity | Meaning | |------|----------|---------| | `BUNDLE_DOT_MISSING` | SUGGESTION | No `bundle.dot` found at repo root | | `BUNDLE_DOT_STALE` | WARNING | `bundle.dot` source_hash doesn't match current repo state | --- ## Generation ### Direct (bulk generation) ``` generate-bundle-docs ``` Calls `bundle_repo_dot(repo_path)`, checks freshness via `source_hash`, writes `bundle.dot` (optionally LLM-enhanced) and renders `bundle.png` at the repo root. ### Via validation (automatic) `validate-bundle-repo` auto-regenerates a stale or missing `bundle.dot` as a side effect of validation: ``` validate-bundle-repo → detects missing/stale → regenerates bundle.dot + bundle.png ``` --- ## Lifecycle: When to Regenerate Regenerate when any of the following change in the repository: - `bundle.md` / `bundle.yaml` at repo root - Any file in `behaviors/` (behavior bundles) - Any file in `bundles/` (standalone bundles) - Any file in `agents/` (agent definitions) - Any file in `context/` (context files) - Any tool/module declaration - Any hook definition - Any file in `providers/`, `experiments/` **Tip:** If unsure, run `validate-bundle-repo` — it checks hashes and regenerates only if stale. --- ## API Reference ```python from amplifier_foundation.bundle_docs import bundle_repo_dot dot_content = bundle_repo_dot(repo_root) # returns DOT string with source_hash ``` The function is the sole public entry point. It takes a `str | Path` pointing to the repository root and returns a complete DOT graph string. --- ## Checklist Before committing a bundle or behavior change: - [ ] `bundle.dot` exists at repo root - [ ] `source_hash` in `bundle.dot` matches current repo state (or run `generate-bundle-docs`) - [ ] `bundle.png` exists and is fresh