@opencodehub/cli 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/commands/ci-templates/github-nightly.yml +35 -0
  2. package/dist/commands/ci-templates/github-rescan.yml +52 -0
  3. package/dist/commands/ci-templates/github-verdict.yml +24 -0
  4. package/dist/commands/ci-templates/github-weekly.yml +49 -0
  5. package/dist/commands/ci-templates/gitlab-ci.yml +56 -0
  6. package/dist/index.js +9 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/plugin-assets/agents/code-analyst.md +18 -0
  9. package/dist/plugin-assets/commands/audit-deps.md +29 -0
  10. package/dist/plugin-assets/commands/owners.md +20 -0
  11. package/dist/plugin-assets/commands/probe.md +21 -0
  12. package/dist/plugin-assets/commands/rename.md +20 -0
  13. package/dist/plugin-assets/commands/verdict.md +18 -0
  14. package/dist/plugin-assets/hooks/augment.sh +128 -0
  15. package/dist/plugin-assets/hooks/docs-staleness.sh +45 -0
  16. package/dist/plugin-assets/hooks.json +34 -0
  17. package/dist/plugin-assets/skills/codehub-code-pack/SKILL.md +181 -0
  18. package/dist/plugin-assets/skills/codehub-code-pack/references/determinism-contract.md +150 -0
  19. package/dist/plugin-assets/skills/codehub-contract-map/SKILL.md +144 -0
  20. package/dist/plugin-assets/skills/codehub-document/SKILL.md +152 -0
  21. package/dist/plugin-assets/skills/codehub-document/references/cross-reference-spec.md +142 -0
  22. package/dist/plugin-assets/skills/codehub-document/references/data-source-map.md +139 -0
  23. package/dist/plugin-assets/skills/codehub-document/references/document-templates.md +347 -0
  24. package/dist/plugin-assets/skills/codehub-document/references/mermaid-patterns.md +181 -0
  25. package/dist/plugin-assets/skills/codehub-document/templates/agents/README.md +64 -0
  26. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-analysis-dead-code.md +104 -0
  27. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-analysis-ownership.md +101 -0
  28. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-analysis-risk-hotspots.md +105 -0
  29. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-architecture-data-flow.md +103 -0
  30. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-architecture-module-map.md +102 -0
  31. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-architecture-system-overview.md +100 -0
  32. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-behavior-processes.md +103 -0
  33. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-behavior-state-machines.md +101 -0
  34. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-cross-repo-contracts-matrix.md +104 -0
  35. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-cross-repo-dependency-flow.md +111 -0
  36. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-cross-repo-portfolio-map.md +106 -0
  37. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-diagrams-components.md +99 -0
  38. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-diagrams-dependency-graph.md +104 -0
  39. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-diagrams-sequences.md +103 -0
  40. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-reference-cli.md +110 -0
  41. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-reference-mcp-tools.md +100 -0
  42. package/dist/plugin-assets/skills/codehub-document/templates/agents/doc-reference-public-api.md +111 -0
  43. package/dist/plugin-assets/skills/codehub-document/templates/orchestrator-prompt.md +110 -0
  44. package/dist/plugin-assets/skills/codehub-onboarding/SKILL.md +111 -0
  45. package/dist/plugin-assets/skills/codehub-pr-description/SKILL.md +122 -0
  46. package/dist/plugin-assets/skills/opencodehub-debugging/SKILL.md +144 -0
  47. package/dist/plugin-assets/skills/opencodehub-exploring/SKILL.md +120 -0
  48. package/dist/plugin-assets/skills/opencodehub-guide/SKILL.md +180 -0
  49. package/dist/plugin-assets/skills/opencodehub-impact-analysis/SKILL.md +151 -0
  50. package/dist/plugin-assets/skills/opencodehub-pr-review/SKILL.md +246 -0
  51. package/dist/plugin-assets/skills/opencodehub-refactoring/SKILL.md +180 -0
  52. package/package.json +16 -14
@@ -0,0 +1,101 @@
1
+ ---
2
+ role: doc-behavior-state-machines
3
+ model: sonnet
4
+ output: "{{ docs_root }}/behavior/state-machines.md"
5
+ depends_on:
6
+ - "{{ context_path }}"
7
+ - "{{ prefetch_path }}"
8
+ status: IN_PROGRESS
9
+ ---
10
+
11
+ # Packet · {{ repo }} · behavior/state-machines.md
12
+
13
+ ## 1. Objective
14
+
15
+ Produce `{{ docs_root }}/behavior/state-machines.md`: one H2 per state machine in `{{ repo }}`, each containing exactly one Mermaid `stateDiagram-v2` block that reflects the states and transitions declared in source, followed by a `path:LOC` citation to the definition site.
16
+
17
+ ## 2. Scope
18
+
19
+ - Create: `{{ docs_root }}/behavior/state-machines.md`
20
+ - Do not touch: `{{ docs_root }}/behavior/processes.md`, any other file under `{{ docs_root }}/`, any source file in the repo, `.context.md`, `.prefetch.md`, or any `.packets/*.md` other than this one.
21
+ - Conditional file — this packet is only seeded when `sql(WHERE kind='StateMachine')` returns ≥ 2 rows. The state-machine count is carried in `{{ context_path }} § State machines`; the orchestrator verified the count before spawning.
22
+
23
+ ## 3. Input specification
24
+
25
+ | Source | Read how | Cache state |
26
+ |---|---|---|
27
+ | Shared context | `Read {{ context_path }}` | always first |
28
+ | Prefetch ledger | `Read {{ prefetch_path }}` | always first |
29
+ | State-machine inventory | `{{ context_path }} § State machines` (count + names + paths) | cached |
30
+ | State-machine nodes (detail) | `mcp__opencodehub__sql({query: "SELECT name, file_path, start_line FROM nodes WHERE kind='StateMachine'"})` | mid-run, only if `.context.md` slice is truncated |
31
+ | States + transitions per machine | `mcp__opencodehub__context({symbol: <machine-name>})` | mid-run |
32
+ | Verbatim state/transition text | `Read <file_path>:<start_line>` | mid-run |
33
+
34
+ ## 4. Process
35
+
36
+ 1. `Read {{ context_path }}` and `Read {{ prefetch_path }}`. Confirm `.context.md § State machines` lists ≥ 2 machines. If the slice is truncated, call the `sql` fallback in Section 3.
37
+ 2. For each state machine: call `mcp__opencodehub__context({symbol: <machine-name>})` to pull states, entry state, transitions, and terminal states.
38
+ 3. For each machine: `Read` the definition file at `start_line..start_line+60` to verify state names and transition labels before drawing. Do not invent transitions.
39
+ 4. Draft `state-machines.md` with H1 = `{{ repo }} · State machines`. One H2 per machine, in alphabetical order by machine name. Under each H2: exactly one fenced Mermaid `stateDiagram-v2` block, then a single-line `Defined at: <backtick path:LOC>` citation.
40
+ 5. Transitions use the source-level event name as the Mermaid edge label (e.g., `start()`, `complete()`). Do not paraphrase event names.
41
+ 6. `Write {{ docs_root }}/behavior/state-machines.md`.
42
+
43
+ ## 5. Document format rules
44
+
45
+ - H1 = `{{ repo }} · State machines`. No decorative titles.
46
+ - No YAML frontmatter on the output file.
47
+ - One H2 per state machine. H2s in alphabetical order.
48
+ - Each H2 contains exactly one Mermaid fence with `stateDiagram-v2`. Not `stateDiagram`, not `flowchart`.
49
+ - Each H2 ends with `Defined at: <backtick path:LOC>` on its own line.
50
+ - Mermaid node names match source state identifiers verbatim; transition labels match source event names verbatim.
51
+ - No emojis. No filler adverbs.
52
+
53
+ ## 6. Tool usage guide
54
+
55
+ | Need | Tool | Why |
56
+ |---|---|---|
57
+ | State-machine roster | `{{ context_path }} § State machines` | precomputed; do not re-call `sql` |
58
+ | States + transitions | `mcp__opencodehub__context` | outbound edges encode transitions |
59
+ | Verbatim state / event names | `Read` at `file_path:start_line` | graph stores the structure, not the literal text |
60
+ | Disambiguate machine names | `mcp__opencodehub__query` | only when two machines share a name |
61
+
62
+ ## 7. Fallback paths
63
+
64
+ - If `.context.md § State machines` is truncated or absent: call `mcp__opencodehub__sql({query: "SELECT name, file_path, start_line FROM nodes WHERE kind='StateMachine'"})`. Cite the fallback in the Work log.
65
+ - If the sql roster returns < 2 machines (the conditional precondition was wrong): write the gap to the Work log, stop, and do not emit an empty or 1-machine file — the orchestrator will prune this packet from the README.
66
+ - If `context` returns no transitions for a machine: `Read` the definition file at `start_line..start_line+60` and parse the states/transitions manually; mark the machine H2 with `*transitions derived by direct read*` in the Work log.
67
+ - If a machine has no terminal state in source: draw the diagram without a `--> [*]` edge and note the absence in the Work log (do not invent a terminal state).
68
+
69
+ ## 8. Success criteria
70
+
71
+ - [ ] `{{ docs_root }}/behavior/state-machines.md` exists on disk.
72
+ - [ ] H1 line reads `# {{ repo }} · State machines`.
73
+ - [ ] At least 2 H2 entries exist (matches the conditional precondition).
74
+ - [ ] Every H2 contains exactly one `stateDiagram-v2` Mermaid fence.
75
+ - [ ] No H2 contains a second Mermaid block or a non-Mermaid diagram.
76
+ - [ ] Every H2 ends with a `Defined at: <backtick path:LOC>` line.
77
+ - [ ] Every state name and transition label in the Mermaid blocks appears in the source file at the cited path (spot-check 1 machine).
78
+ - [ ] No YAML frontmatter on the output.
79
+
80
+ ## 9. Anti-goals
81
+
82
+ - Do not re-call `sql` over `StateMachine` nodes — the count and names are cached in `.context.md`.
83
+ - Do not invent state names or transition labels — every identifier must come from `context` output or a `Read` of the definition file.
84
+ - Do not emit more than one Mermaid block per H2.
85
+ - Do not use `stateDiagram` (v1); use `stateDiagram-v2` only.
86
+ - Do not write YAML frontmatter on the output file.
87
+ - Do not emit emojis.
88
+
89
+ ---
90
+
91
+ ## Work log
92
+
93
+ {{ subagent fills this section per the write protocol }}
94
+
95
+ ## Validation
96
+
97
+ {{ checks run, outputs pasted, any fixes applied }}
98
+
99
+ ## Summary
100
+
101
+ {{ one paragraph — what shipped, which machines were drawn, and any that required a direct-read fallback }}
@@ -0,0 +1,104 @@
1
+ ---
2
+ role: doc-cross-repo-contracts-matrix
3
+ model: sonnet
4
+ output: "{{ group_docs_root }}/cross-repo/contracts-matrix.md"
5
+ depends_on:
6
+ - "{{ group_context_path }}"
7
+ - "{{ group_prefetch_path }}"
8
+ status: IN_PROGRESS
9
+ ---
10
+
11
+ # Packet · {{ group }} · cross-repo/contracts-matrix.md
12
+
13
+ > **Group mode only.** This packet runs when the skill orchestrator is invoked with `--group {{ group }}`. In single-repo mode it is never seeded.
14
+
15
+ ## 1. Objective
16
+
17
+ Produce `{{ group_docs_root }}/cross-repo/contracts-matrix.md`: the N×N producer/consumer matrix for the `{{ group }}` group (rows = producers, columns = consumers, cells = contract counts), followed by a `## Notable contracts` H2 listing the top 10 contracts with both-ends `repo:path:LOC` citations.
18
+
19
+ ## 2. Scope
20
+
21
+ - Create: `{{ group_docs_root }}/cross-repo/contracts-matrix.md`
22
+ - Do not touch: any other file under `{{ group_docs_root }}/`, any file under a member repo (including `{{ member_repos }}/`), `{{ group_context_path }}`, `{{ group_prefetch_path }}`, or any `.packets/*.md` other than this one.
23
+
24
+ ## 3. Input specification
25
+
26
+ | Source | Read how | Cache state |
27
+ |---|---|---|
28
+ | Group shared context | `Read {{ group_context_path }}` | always first |
29
+ | Group prefetch ledger | `Read {{ group_prefetch_path }}` | always first |
30
+ | Member list + freshness | `{{ group_context_path }} § Members` / `{{ group_prefetch_path }} § group_list,group_status` | cached |
31
+ | Group contracts (the spine) | `{{ group_prefetch_path }} § group_contracts` | cached |
32
+ | Per-member route inventory | `{{ group_prefetch_path }} § route_map(<repo>)` per `{{ member_repos }}` | cached |
33
+ | Concept → symbol disambiguation | `mcp__opencodehub__group_query({group: "{{ group }}", text: <concept>})` | mid-run, on demand |
34
+
35
+ ## 4. Process
36
+
37
+ 1. `Read {{ group_context_path }}` and `Read {{ group_prefetch_path }}`. Confirm the member list and re-verify every member is tagged `fresh` in the cached `group_status` digest. Abort to Work log if any member is stale.
38
+ 2. Pull the contract list from `{{ group_prefetch_path }} § group_contracts`. Each row has `{producer_repo, consumer_repo, path, method, shape}`. This is the spine of the entire artifact.
39
+ 3. Build the producer/consumer matrix: rows = producer repos (in `group_list` order), columns = consumer repos (same order). Each cell = the contract count for that `(producer, consumer)` pair. Diagonal cells show `—`. Render as a Markdown table.
40
+ 4. Select the top 10 contracts by consumer count (ties broken by producer path lexicographically). For each, resolve both ends to real files via the cached `route_map` digests — producer file comes from `route_map(<producer>)`, consumer file from the `group_contracts` row's `consumer_repo` + `path`. Cite both with `repo:path:LOC`.
41
+ 5. Draft the `## Notable contracts` H2: a bullet list of the 10 entries in the form `` `<producer-repo>:<producer-path>:<LOC>` ← consumed by `<consumer-repo>:<consumer-path>:<LOC>` (method + shape summary) ``.
42
+ 6. If the matrix has zero non-diagonal contracts, still emit the full N×N matrix (all `0` / `—` cells), add a `> No inter-repo contracts detected — the group graph does not currently encode cross-repo edges` banner immediately beneath the H1, and replace `## Notable contracts` with `## Notable contracts\n\n_None detected._`.
43
+ 7. `Write {{ group_docs_root }}/cross-repo/contracts-matrix.md` with H1 = `{{ group }} · Contracts matrix`.
44
+
45
+ ## 5. Document format rules
46
+
47
+ - **Every citation MUST use the group-qualified `repo:path:LOC` form — on both ends of every Notable contracts bullet.** Phase E's regex depends on this — bare `path:LOC` will not be rewritten.
48
+ - H1 = `{{ group }} · Contracts matrix`. No decorative titles.
49
+ - No YAML frontmatter on the output file.
50
+ - Matrix is a full Markdown table, N×N, even when most cells are zero. Column and row order match `group_list`. Diagonal = `—`; empty cells = `0`.
51
+ - `## Notable contracts` section has at most 10 bullets, each with two `repo:path:LOC` citations (producer end and consumer end) plus a short `(method + shape)` summary.
52
+ - No emojis. No filler adverbs.
53
+
54
+ ## 6. Tool usage guide
55
+
56
+ | Need | Tool | Why |
57
+ |---|---|---|
58
+ | Member list + freshness | `{{ group_prefetch_path }} § group_list,group_status` | precondition gate; precomputed |
59
+ | Contract inventory | `{{ group_prefetch_path }} § group_contracts` | authoritative spine; do not re-call |
60
+ | Producer file resolution | `{{ group_prefetch_path }} § route_map(<repo>)` | maps contract `path` → handler `file:LOC` |
61
+ | Concept disambiguation | `mcp__opencodehub__group_query` | when a contract's target symbol has multiple matches across the group |
62
+
63
+ ## 7. Fallback paths
64
+
65
+ - If `group_contracts` returned zero contracts: follow the all-zero path in step 6. Do not omit the matrix.
66
+ - If a member repo is stale despite Phase 0 checks: abort — write `{{ group_docs_root }}/cross-repo/_stale.md` instead, explaining which repo blocked generation, and stop.
67
+ - If a `route_map` digest is missing for a producer: fall back to the raw `path` string from `group_contracts` and cite `<producer-repo>:<path>:1`. Record the fallback in the Work log.
68
+ - If `group_query` returns empty for a concept while disambiguating: try `"http route"`, `"mcp tool"`, `"message consumer"` in order before giving up and marking the bullet `*consumer unresolved*`.
69
+
70
+ ## 8. Success criteria
71
+
72
+ - [ ] `{{ group_docs_root }}/cross-repo/contracts-matrix.md` exists on disk.
73
+ - [ ] H1 line reads `# {{ group }} · Contracts matrix`.
74
+ - [ ] Matrix is a full N×N Markdown table where N = number of members; diagonals are `—`; cells show integer contract counts.
75
+ - [ ] `## Notable contracts` H2 is present; bullet count = `min(10, total non-diagonal contract count)`.
76
+ - [ ] Every Notable contracts bullet has two `repo:path:LOC` citations (producer + consumer).
77
+ - [ ] Every citation in the file uses the `repo:path:LOC` form — no bare `path:LOC` (grep the output to verify).
78
+ - [ ] If zero contracts: the empty-state banner and `_None detected._` sub-section are present.
79
+ - [ ] No YAML frontmatter on the output.
80
+
81
+ ## 9. Anti-goals
82
+
83
+ - Do not re-call any MCP tool whose digest is already in `{{ group_prefetch_path }}` — read the cached summary.
84
+ - Do not emit a citation in the bare `path:LOC` form; every citation MUST be `repo:path:LOC`.
85
+ - Do not invent contracts, producer/consumer pairs, file paths, or line numbers — every entry must come from a cached tool response.
86
+ - Do not write YAML frontmatter on the output file.
87
+ - Do not omit the matrix when contract count is zero — emit an empty N×N table with the banner.
88
+ - Do not exceed 10 bullets under `## Notable contracts`.
89
+ - Do not collapse the matrix to producer-only or consumer-only — it must be N×N.
90
+ - Do not emit emojis.
91
+
92
+ ---
93
+
94
+ ## Work log
95
+
96
+ {{ subagent fills this section per the write protocol }}
97
+
98
+ ## Validation
99
+
100
+ {{ checks run, outputs pasted, any fixes applied }}
101
+
102
+ ## Summary
103
+
104
+ {{ one paragraph — what shipped, where, why the top-10 contract selection went the way it did }}
@@ -0,0 +1,111 @@
1
+ ---
2
+ role: doc-cross-repo-dependency-flow
3
+ model: sonnet
4
+ output: "{{ group_docs_root }}/cross-repo/dependency-flow.md"
5
+ depends_on:
6
+ - "{{ group_context_path }}"
7
+ - "{{ group_prefetch_path }}"
8
+ status: IN_PROGRESS
9
+ ---
10
+
11
+ # Packet · {{ group }} · cross-repo/dependency-flow.md
12
+
13
+ > **Group mode only.** This packet runs when the skill orchestrator is invoked with `--group {{ group }}`. In single-repo mode it is never seeded.
14
+
15
+ ## 1. Objective
16
+
17
+ Produce `{{ group_docs_root }}/cross-repo/dependency-flow.md`: a single Mermaid `flowchart TB` showing inter-repo data flow across the `{{ group }}` group — nodes are repos (plus events/streams as needed), edges are contract groups labeled by HTTP verb + path or event type.
18
+
19
+ ## 2. Scope
20
+
21
+ - Create: `{{ group_docs_root }}/cross-repo/dependency-flow.md`
22
+ - Do not touch: any other file under `{{ group_docs_root }}/`, any file under a member repo (including `{{ member_repos }}/`), `{{ group_context_path }}`, `{{ group_prefetch_path }}`, or any `.packets/*.md` other than this one.
23
+
24
+ ## 3. Input specification
25
+
26
+ | Source | Read how | Cache state |
27
+ |---|---|---|
28
+ | Group shared context | `Read {{ group_context_path }}` | always first |
29
+ | Group prefetch ledger | `Read {{ group_prefetch_path }}` | always first |
30
+ | Member list + freshness | `{{ group_context_path }} § Members` / `{{ group_prefetch_path }} § group_list,group_status` | cached |
31
+ | Group contracts | `{{ group_prefetch_path }} § group_contracts` | cached |
32
+ | Per-member route inventory | `{{ group_prefetch_path }} § route_map(<repo>)` per `{{ member_repos }}` | cached |
33
+ | Async / event topics | `mcp__opencodehub__group_query({group: "{{ group }}", text: "message consumer"})` or `"publishes"` | mid-run, only if stream edges are suspected |
34
+
35
+ ## 4. Process
36
+
37
+ 1. `Read {{ group_context_path }}` and `Read {{ group_prefetch_path }}`. Confirm the member list and re-verify every member is tagged `fresh` in the cached `group_status` digest. Abort to Work log if any member is stale.
38
+ 2. Pull the contract inventory from `{{ group_prefetch_path }} § group_contracts`. For each `(producer_repo, consumer_repo)` pair, group the contracts by `method + path-prefix` to form a single edge labeled with the representative HTTP verb + path (e.g., `POST /invoices`).
39
+ 3. Scan the contract list for event/stream shapes (kind = `topic` / `queue` / `stream` in the cached digest). For each stream, add a parenthesized node `name[(stream.name)]` and draw dashed edges (`-.->`) from consumers and solid edges (`-->`) from publishers.
40
+ 4. Compose the node set: one node per member repo (`repo["repo"]` plain rectangle) plus one parenthesized node per event/stream. Cap at 20 nodes — if the group plus streams exceed 20, keep the top-20 by edge count and move overflow into a `## Legend (overflow)` table.
41
+ 5. Compose the edge set: solid arrows for synchronous HTTP calls, dashed arrows for async/pub-sub. Each edge label carries the HTTP verb + path (routes) or the event type (streams); ≤ 15 chars.
42
+ 6. Draft the Mermaid `flowchart TB`. Every repo node's string identifier and every path/event on every edge must trace back to `group_contracts` or a `route_map` digest — no invented flows.
43
+ 7. `Write {{ group_docs_root }}/cross-repo/dependency-flow.md` with H1 = `{{ group }} · Dependency flow`.
44
+
45
+ ## 5. Document format rules
46
+
47
+ - **Every citation MUST use the group-qualified `repo:path:LOC` form.** Phase E's regex depends on this — bare `path:LOC` will not be rewritten into cross-repo links. Citations appear in any accompanying narrative text, in per-edge footnotes (if used), and in the Legend table's "source" column.
48
+ - H1 = `{{ group }} · Dependency flow`. No decorative titles.
49
+ - No YAML frontmatter on the output file.
50
+ - Exactly one Mermaid diagram, fenced with ` ```mermaid `, diagram type `flowchart TB`.
51
+ - Repo nodes: plain rectangles — `repo["repo"]`.
52
+ - Event/stream nodes: parenthesized shape — `name[(stream.name)]`.
53
+ - Solid arrows (`-->`) for synchronous calls; dashed arrows (`-.->`) for async/pub-sub.
54
+ - Edge labels = HTTP verb + path for routes, event type for streams; ≤ 15 chars.
55
+ - Max 20 nodes total; overflow goes into a `## Legend (overflow)` table below the fenced block.
56
+ - No emojis. No filler adverbs.
57
+
58
+ ## 6. Tool usage guide
59
+
60
+ | Need | Tool | Why |
61
+ |---|---|---|
62
+ | Member list + freshness | `{{ group_prefetch_path }} § group_list,group_status` | precondition gate; precomputed |
63
+ | Contract inventory | `{{ group_prefetch_path }} § group_contracts` | authoritative spine; source for every edge |
64
+ | Producer file resolution | `{{ group_prefetch_path }} § route_map(<repo>)` | maps contract `path` → handler `file:LOC` for citations |
65
+ | Async/stream discovery | `mcp__opencodehub__group_query` with `"message consumer"` / `"publishes"` | only if stream edges are suspected and not cached |
66
+ | Diagram idioms | `references/mermaid-patterns.md § Cross-repo dependency flow` | canonical `flowchart TB` shape + solid/dashed edge rules |
67
+
68
+ ## 7. Fallback paths
69
+
70
+ - If `group_contracts` returned zero contracts: emit the diagram with isolated (edge-less) repo nodes and add a `> No inter-repo data flow detected in the group graph` banner immediately beneath the H1. Record the fallback in the Work log.
71
+ - If a member repo is stale despite Phase 0 checks: abort — write `{{ group_docs_root }}/cross-repo/_stale.md` instead, explaining which repo blocked generation, and stop.
72
+ - If a `route_map` digest is missing for a producer: derive the edge label from the raw `method + path` in `group_contracts` and cite the bullet's source as `<producer-repo>:<path>:1`. Record the fallback in the Work log.
73
+ - If `group_query` for `"message consumer"` / `"publishes"` returns nothing: assume the group has no stream edges for this pass and emit only HTTP edges.
74
+
75
+ ## 8. Success criteria
76
+
77
+ - [ ] `{{ group_docs_root }}/cross-repo/dependency-flow.md` exists on disk.
78
+ - [ ] H1 line reads `# {{ group }} · Dependency flow`.
79
+ - [ ] Exactly one ` ```mermaid ` fence containing a `flowchart TB`.
80
+ - [ ] Diagram has 1-20 nodes; every repo node matches an entry in `group_list`.
81
+ - [ ] Every event/stream node uses the parenthesized `[( )]` shape.
82
+ - [ ] Every solid edge corresponds to a synchronous contract in `group_contracts`; every dashed edge corresponds to a stream / async contract.
83
+ - [ ] Every edge label ≤ 15 chars and matches a real HTTP verb+path or event type from the cached digest.
84
+ - [ ] Every citation in the file uses the `repo:path:LOC` form — no bare `path:LOC` (grep the output to verify).
85
+ - [ ] If overflow occurred, a `## Legend (overflow)` table lists ≥ 5 elided nodes with edge counts.
86
+ - [ ] No YAML frontmatter on the output.
87
+
88
+ ## 9. Anti-goals
89
+
90
+ - Do not re-call any MCP tool whose digest is already in `{{ group_prefetch_path }}` — read the cached summary.
91
+ - Do not emit a citation in the bare `path:LOC` form; every citation MUST be `repo:path:LOC`.
92
+ - Do not invent repos, streams, routes, HTTP methods, or event types — every identifier must come from a cached tool response.
93
+ - Do not write YAML frontmatter on the output file.
94
+ - Do not emit more than one Mermaid diagram.
95
+ - Do not exceed 20 nodes in the rendered diagram; overflow goes into the Legend table.
96
+ - Do not use solid arrows for async/stream edges, or dashed arrows for synchronous HTTP calls.
97
+ - Do not emit emojis.
98
+
99
+ ---
100
+
101
+ ## Work log
102
+
103
+ {{ subagent fills this section per the write protocol }}
104
+
105
+ ## Validation
106
+
107
+ {{ checks run, outputs pasted, any fixes applied }}
108
+
109
+ ## Summary
110
+
111
+ {{ one paragraph — what shipped, where, why the sync/async edge partitioning went the way it did }}
@@ -0,0 +1,106 @@
1
+ ---
2
+ role: doc-cross-repo-portfolio-map
3
+ model: sonnet
4
+ output: "{{ group_docs_root }}/cross-repo/portfolio-map.md"
5
+ depends_on:
6
+ - "{{ group_context_path }}"
7
+ - "{{ group_prefetch_path }}"
8
+ status: IN_PROGRESS
9
+ ---
10
+
11
+ # Packet · {{ group }} · cross-repo/portfolio-map.md
12
+
13
+ > **Group mode only.** This packet runs when the skill orchestrator is invoked with `--group {{ group }}`. In single-repo mode it is never seeded.
14
+
15
+ ## 1. Objective
16
+
17
+ Produce `{{ group_docs_root }}/cross-repo/portfolio-map.md`: a 2-paragraph narrative of the `{{ group }}` group's shape, a Mermaid `flowchart LR` of its member repos with contract-count edges, and a `## Repos` section with per-member H2 + relative link into each member's own `.codehub/docs/` tree.
18
+
19
+ ## 2. Scope
20
+
21
+ - Create: `{{ group_docs_root }}/cross-repo/portfolio-map.md`
22
+ - Do not touch: any other file under `{{ group_docs_root }}/`, any file under a member repo (including `{{ member_repos }}/.codehub/docs/`), `{{ group_context_path }}`, `{{ group_prefetch_path }}`, or any `.packets/*.md` other than this one.
23
+
24
+ ## 3. Input specification
25
+
26
+ | Source | Read how | Cache state |
27
+ |---|---|---|
28
+ | Group shared context | `Read {{ group_context_path }}` | always first |
29
+ | Group prefetch ledger | `Read {{ group_prefetch_path }}` | always first |
30
+ | Member list + freshness | `{{ group_context_path }} § Members` / `{{ group_prefetch_path }} § group_list,group_status` | cached |
31
+ | Group contracts | `{{ group_prefetch_path }} § group_contracts` | cached |
32
+ | Per-member one-line description | `{{ group_context_path }} § Member profiles` | cached |
33
+ | Member docs-root paths | derived: `../{{ member_repos[i] }}/.codehub/docs/README.md` | n/a |
34
+
35
+ ## 4. Process
36
+
37
+ 1. `Read {{ group_context_path }}` and `Read {{ group_prefetch_path }}`. Confirm the member list under `§ Members` and re-verify that every member is tagged `fresh` in the cached `group_status` digest. If any member is stale, abort and write the gap to Work log — the orchestrator's Phase 0 gate should have caught this.
38
+ 2. Pull the contract inventory from `{{ group_prefetch_path }} § group_contracts`. Aggregate by `(producer_repo, consumer_repo)` into an edge-count table.
39
+ 3. Pull one-line domain descriptions for each member from `{{ group_context_path }} § Member profiles`. These become the second line of each node label via `<br/>`.
40
+ 4. Draft the 2-paragraph narrative: paragraph 1 = what the group does as a whole (domain, scope); paragraph 2 = how the members relate (who produces for whom, which member is the hub). Every factual claim carries a `repo:path:LOC` citation.
41
+ 5. Draft the Mermaid `flowchart LR`: one node per member repo with the two-line label `"<repo><br/><one-line domain>"`; one edge per `(producer, consumer)` pair labeled `contracts: N`. Cap at 20 nodes — if the group has > 20 members, keep the top-20 by inbound+outbound contract count and move the overflow to a `## Legend (overflow)` table.
42
+ 6. Draft the `## Repos` section: one H2 per member (`## <repo> — <one-line description>`), each with 1-2 `repo:path:LOC` citations and a `[See {{ member_repos[i] }} docs →](../{{ member_repos[i] }}/.codehub/docs/README.md)` link.
43
+ 7. `Write {{ group_docs_root }}/cross-repo/portfolio-map.md` with H1 = `{{ group }} · Portfolio map`.
44
+
45
+ ## 5. Document format rules
46
+
47
+ - **Every citation MUST use the group-qualified `repo:path:LOC` form.** Phase E's regex depends on this — bare `path:LOC` will not be rewritten into cross-repo links.
48
+ - H1 = `{{ group }} · Portfolio map`. No decorative titles.
49
+ - No YAML frontmatter on the output file.
50
+ - Exactly one Mermaid diagram, fenced with ` ```mermaid `, diagram type `flowchart LR`.
51
+ - Node labels use the `"<repo><br/><one-line domain>"` two-line form; labels ≤ 20 chars per line.
52
+ - Edge labels `contracts: N` where N comes directly from the aggregated `group_contracts` count; ≤ 15 chars.
53
+ - Member-repo links use a relative path rooted at the group directory: `../<repo>/.codehub/docs/README.md`.
54
+ - `## Repos` section has exactly one H2 per member, in the order returned by `group_list`.
55
+ - No emojis. No filler adverbs.
56
+
57
+ ## 6. Tool usage guide
58
+
59
+ | Need | Tool | Why |
60
+ |---|---|---|
61
+ | Member list + freshness | `{{ group_prefetch_path }} § group_list,group_status` | precondition gate; precomputed |
62
+ | Contract inventory | `{{ group_prefetch_path }} § group_contracts` | authoritative spine; do not re-call |
63
+ | Per-member profile | `{{ group_context_path }} § Member profiles` | cached; source for node labels + H2 text |
64
+ | Diagram idioms | `references/mermaid-patterns.md § Cross-repo portfolio` | canonical `flowchart LR` shape + edge labeling |
65
+
66
+ ## 7. Fallback paths
67
+
68
+ - If `group_contracts` returned zero contracts: keep the diagram with isolated (edge-less) nodes; narrative paragraph 2 becomes a 1-sentence note that the group graph does not currently encode cross-repo edges. Record the fallback in the Work log.
69
+ - If any member is stale despite Phase 0 checks: abort — do not write `portfolio-map.md`. Instead, write `{{ group_docs_root }}/cross-repo/_stale.md` explaining which repo blocked generation, and stop.
70
+ - If `{{ group_context_path }} § Member profiles` lacks a one-liner for a member: call `mcp__opencodehub__project_profile({repo: <member>})` once, extract the summary, cache the digest in Work log, and use it. Do not invent a description.
71
+
72
+ ## 8. Success criteria
73
+
74
+ - [ ] `{{ group_docs_root }}/cross-repo/portfolio-map.md` exists on disk.
75
+ - [ ] H1 line reads `# {{ group }} · Portfolio map`.
76
+ - [ ] Narrative is 2 paragraphs, every factual claim cited with `repo:path:LOC`.
77
+ - [ ] Exactly one ` ```mermaid ` fence containing a `flowchart LR` with 1-20 nodes.
78
+ - [ ] Every node label uses the two-line `"<repo><br/><one-line domain>"` form.
79
+ - [ ] `## Repos` section has one H2 per member; each H2 has at least one `repo:path:LOC` citation and a relative `../<repo>/.codehub/docs/README.md` link.
80
+ - [ ] Every citation in the file uses the `repo:path:LOC` form — no bare `path:LOC` (grep the output to verify).
81
+ - [ ] No YAML frontmatter on the output.
82
+
83
+ ## 9. Anti-goals
84
+
85
+ - Do not re-call any MCP tool whose digest is already in `{{ group_prefetch_path }}` — read the cached summary.
86
+ - Do not emit a citation in the bare `path:LOC` form; every citation MUST be `repo:path:LOC`.
87
+ - Do not invent member repos, contract counts, or domain descriptions — every identifier must come from a cached tool response or `Read` of the source file.
88
+ - Do not write YAML frontmatter on the output file.
89
+ - Do not emit more than one Mermaid diagram.
90
+ - Do not exceed 20 nodes in the rendered diagram; overflow goes into the Legend table.
91
+ - Do not link to a member's docs with an absolute path — relative `../<repo>/.codehub/docs/...` only.
92
+ - Do not emit emojis.
93
+
94
+ ---
95
+
96
+ ## Work log
97
+
98
+ {{ subagent fills this section per the write protocol }}
99
+
100
+ ## Validation
101
+
102
+ {{ checks run, outputs pasted, any fixes applied }}
103
+
104
+ ## Summary
105
+
106
+ {{ one paragraph — what shipped, where, why the member ordering and narrative shape went the way they did }}
@@ -0,0 +1,99 @@
1
+ ---
2
+ role: doc-diagrams-components
3
+ model: sonnet
4
+ output: "{{ docs_root }}/diagrams/architecture/components.md"
5
+ depends_on:
6
+ - "{{ context_path }}"
7
+ - "{{ prefetch_path }}"
8
+ status: IN_PROGRESS
9
+ ---
10
+
11
+ # Packet · {{ repo }} · diagrams/architecture/components.md
12
+
13
+ ## 1. Objective
14
+
15
+ Produce `{{ docs_root }}/diagrams/architecture/components.md`: a single Mermaid `classDiagram` of the top 8 components of `{{ repo }}` with HAS-A / USES edges, capped at 20 total nodes.
16
+
17
+ ## 2. Scope
18
+
19
+ - Create: `{{ docs_root }}/diagrams/architecture/components.md`
20
+ - Do not touch: any other file under `{{ docs_root }}/`, any source file in the repo, `.context.md`, `.prefetch.md`, or any `.packets/*.md` other than this one.
21
+
22
+ ## 3. Input specification
23
+
24
+ | Source | Read how | Cache state |
25
+ |---|---|---|
26
+ | Shared context | `Read {{ context_path }}` | always first |
27
+ | Prefetch ledger | `Read {{ prefetch_path }}` | always first |
28
+ | Top communities | `{{ context_path }} § Top communities` | cached |
29
+ | Community relations | `{{ prefetch_path }} § sql relations` or `mcp__opencodehub__sql({query: "SELECT source, target, kind FROM relations WHERE kind IN ('CONTAINS','CALLS','IMPORTS') LIMIT 500"})` | cached if digest present; mid-run otherwise |
30
+ | Component method list | `mcp__opencodehub__context({symbol: <community-name>})` per top 8 | mid-run |
31
+
32
+ ## 4. Process
33
+
34
+ 1. `Read {{ context_path }}` and `Read {{ prefetch_path }}`. Confirm top-8 community names and their file-path roots.
35
+ 2. Pull the raw edge set from `.prefetch.md § sql relations` (kinds `CONTAINS`, `CALLS`, `IMPORTS`). If not cached, call `mcp__opencodehub__sql` with the query above and cache the digest in this packet's Work log.
36
+ 3. Project file-level edges down to the community level: collapse every `(source_community, target_community, kind)` triple into a single edge, labeled with a one-word verb (`contains`, `invokes`, `imports`, `depends`).
37
+ 4. For each of the top 8 communities, call `mcp__opencodehub__context({symbol: <community-name>})` and select the top 3-5 outbound method names by call count. These populate the `classDiagram` method list for that class.
38
+ 5. If the projected graph has > 20 nodes, keep the top-20 by edge count and move the overflow into a `## Legend (overflow)` table with columns `Node | Edges | Reason for elision`.
39
+ 6. Draft the Mermaid `classDiagram`. Max 8 classes; each class has 3-5 methods; relationships labeled with one-word verbs.
40
+ 7. `Write {{ docs_root }}/diagrams/architecture/components.md` with H1 = `{{ repo }} · Component view`.
41
+
42
+ ## 5. Document format rules
43
+
44
+ - H1 = `{{ repo }} · Component view`. No decorative titles.
45
+ - No YAML frontmatter on the output file.
46
+ - Exactly one Mermaid diagram, fenced with ` ```mermaid `, diagram type `classDiagram`.
47
+ - Max 20 nodes in the diagram; overflow goes into a Legend table below the fenced block.
48
+ - Node labels ≤ 20 chars; edge labels ≤ 15 chars.
49
+ - Every community / class name must match a row in `{{ context_path }} § Top communities` or a symbol returned by `context` — no invented identifiers.
50
+ - No emojis. No filler adverbs.
51
+
52
+ ## 6. Tool usage guide
53
+
54
+ | Need | Tool | Why |
55
+ |---|---|---|
56
+ | Community list | `{{ context_path }} § Top communities` | precomputed; do not re-call `sql` |
57
+ | Edge set | `{{ prefetch_path }} § sql relations` | authoritative; filter to `CONTAINS`/`CALLS`/`IMPORTS` |
58
+ | Class method list | `mcp__opencodehub__context` | picks methods by call count |
59
+ | Diagram idioms | `references/mermaid-patterns.md § Component view` | canonical `classDiagram` shape + rules |
60
+
61
+ ## 7. Fallback paths
62
+
63
+ - If the cached edge set has < 10 `CONTAINS` edges: fall back to `CALLS` edges at file level, collapsing by top-level folder, and label the diagram `Call graph (fallback)` in the H1. Note the fallback in the Work log.
64
+ - If a community's `context` call errors: keep the class in the diagram with an empty method list and append `*methods unavailable*` immediately after the fenced block.
65
+ - If `.context.md § Top communities` is empty: abort and record the gap in the Work log — do not emit a synthetic class list.
66
+
67
+ ## 8. Success criteria
68
+
69
+ - [ ] `{{ docs_root }}/diagrams/architecture/components.md` exists on disk.
70
+ - [ ] H1 line reads `# {{ repo }} · Component view` (or `# {{ repo }} · Call graph (fallback)` if fallback fired).
71
+ - [ ] Exactly one ` ```mermaid ` fence containing a `classDiagram`.
72
+ - [ ] Diagram has 3-20 nodes, each with a label ≤ 20 chars.
73
+ - [ ] Max 8 classes carry method lists; each class has 3-5 methods.
74
+ - [ ] Every edge carries a one-word verb label.
75
+ - [ ] If overflow occurred, a `## Legend (overflow)` table lists ≥ 5 elided nodes with edge counts.
76
+ - [ ] No YAML frontmatter on the output.
77
+
78
+ ## 9. Anti-goals
79
+
80
+ - Do not re-call `sql` or `project_profile` — those are cached in `.prefetch.md` / `.context.md`.
81
+ - Do not invent class names, method names, or edges — every identifier must come from a tool response or a `Read` of the source file.
82
+ - Do not write YAML frontmatter on the output file.
83
+ - Do not emit more than one Mermaid diagram in this file.
84
+ - Do not exceed 20 nodes in the rendered diagram; overflow goes into the Legend table, never back into the diagram.
85
+ - Do not emit emojis.
86
+
87
+ ---
88
+
89
+ ## Work log
90
+
91
+ {{ subagent fills this section per the write protocol }}
92
+
93
+ ## Validation
94
+
95
+ {{ checks run, outputs pasted, any fixes applied }}
96
+
97
+ ## Summary
98
+
99
+ {{ one paragraph — what shipped, where, why the component selection went the way it did }}
@@ -0,0 +1,104 @@
1
+ ---
2
+ role: doc-diagrams-dependency-graph
3
+ model: sonnet
4
+ output: "{{ docs_root }}/diagrams/structural/dependency-graph.md"
5
+ depends_on:
6
+ - "{{ context_path }}"
7
+ - "{{ prefetch_path }}"
8
+ status: IN_PROGRESS
9
+ ---
10
+
11
+ # Packet · {{ repo }} · diagrams/structural/dependency-graph.md
12
+
13
+ ## 1. Objective
14
+
15
+ Produce `{{ docs_root }}/diagrams/structural/dependency-graph.md`: a single Mermaid `flowchart LR` showing `{{ repo }}`'s internal communities alongside external-dep leaf nodes, capped at 20 total nodes.
16
+
17
+ ## 2. Scope
18
+
19
+ - Create: `{{ docs_root }}/diagrams/structural/dependency-graph.md`
20
+ - Do not touch: any other file under `{{ docs_root }}/`, any source file in the repo, `.context.md`, `.prefetch.md`, or any `.packets/*.md` other than this one.
21
+
22
+ ## 3. Input specification
23
+
24
+ | Source | Read how | Cache state |
25
+ |---|---|---|
26
+ | Shared context | `Read {{ context_path }}` | always first |
27
+ | Prefetch ledger | `Read {{ prefetch_path }}` | always first |
28
+ | Top communities | `{{ context_path }} § Top communities` | cached |
29
+ | Internal edges | `{{ prefetch_path }} § sql relations` or `mcp__opencodehub__sql({query: "SELECT source, target, kind FROM relations WHERE kind IN ('CONTAINS','CALLS','IMPORTS') LIMIT 500"})` | cached if digest present; mid-run otherwise |
30
+ | External dependencies | `{{ context_path }} § Stack` or `mcp__opencodehub__dependencies({repo: "{{ repo }}"})` | cached if digest present; mid-run otherwise |
31
+
32
+ ## 4. Process
33
+
34
+ 1. `Read {{ context_path }}` and `Read {{ prefetch_path }}`. Confirm the internal community list and the external-dep list.
35
+ 2. Pull the internal edge set from `.prefetch.md § sql relations`. If not cached, call `mcp__opencodehub__sql` and cache the digest in this packet's Work log.
36
+ 3. Pull the external-dep list from `.context.md § Stack`. If absent, call `mcp__opencodehub__dependencies({repo: "{{ repo }}"})` and keep the top 15 by usage.
37
+ 4. Compose the node set: internal communities (as `name[Label]` plain rectangles) plus the external deps (as `name[(Label)]:::external` parenthesized nodes with a dashed stroke class). Reserve the full 20-node budget; drop lowest-usage externals first when pruning.
38
+ 5. Compose the edge set: internal→internal edges from the `sql` result collapsed to community level; internal→external edges from the dependency list, sourced at the internal community that imports the dep most often.
39
+ 6. If node count > 20 after composition: keep the top-20 by edge count, then add a `## Legend (overflow)` table with columns `Node | Edges | Reason for elision`.
40
+ 7. Draft the Mermaid `flowchart LR`. Include the `classDef external stroke-dasharray: 3 3` line so external leaves render dashed.
41
+ 8. `Write {{ docs_root }}/diagrams/structural/dependency-graph.md` with H1 = `{{ repo }} · Dependency graph`.
42
+
43
+ ## 5. Document format rules
44
+
45
+ - H1 = `{{ repo }} · Dependency graph`. No decorative titles.
46
+ - No YAML frontmatter on the output file.
47
+ - Exactly one Mermaid diagram, fenced with ` ```mermaid `, diagram type `flowchart LR`.
48
+ - Internal communities: plain rectangles — `name[Label]`.
49
+ - External deps: parenthesized shape with external class — `name[(Label)]:::external` + `classDef external stroke-dasharray: 3 3`.
50
+ - Max 20 nodes total; overflow goes into a Legend table below the fenced block.
51
+ - Node labels ≤ 20 chars; edge labels ≤ 15 chars.
52
+ - Every internal node must match a row in `{{ context_path }} § Top communities`; every external node must match a row from `dependencies` or `.context.md § Stack`.
53
+ - No emojis. No filler adverbs.
54
+
55
+ ## 6. Tool usage guide
56
+
57
+ | Need | Tool | Why |
58
+ |---|---|---|
59
+ | Internal node list | `{{ context_path }} § Top communities` | precomputed; do not re-call `sql` for it |
60
+ | Internal edge set | `{{ prefetch_path }} § sql relations` | authoritative; filter to `CONTAINS`/`CALLS`/`IMPORTS` |
61
+ | External leaf nodes | `{{ context_path }} § Stack` or `mcp__opencodehub__dependencies` | do not grep manifests |
62
+ | Diagram idioms | `references/mermaid-patterns.md § Dependency graph` | canonical `flowchart LR` shape + external-node styling |
63
+
64
+ ## 7. Fallback paths
65
+
66
+ - If `dependencies` errors and `.context.md § Stack` is missing: `Read` the root `package.json` / `Cargo.toml` / `pyproject.toml` and extract the top 15 deps by semantic weight. Append a `*manifest fallback*` note immediately after the fenced block and record the fallback in the Work log.
67
+ - If the internal edge set has < 10 `CONTAINS` edges after projection: drop to `CALLS` edges at file level, collapse by top-level folder, and label the diagram `Call graph (fallback)` in the H1.
68
+ - If `.context.md § Top communities` is empty: abort and record the gap in the Work log — do not synthesize internal nodes from bare filesystem layout.
69
+
70
+ ## 8. Success criteria
71
+
72
+ - [ ] `{{ docs_root }}/diagrams/structural/dependency-graph.md` exists on disk.
73
+ - [ ] H1 line reads `# {{ repo }} · Dependency graph` (or the `Call graph (fallback)` variant if the fallback fired).
74
+ - [ ] Exactly one ` ```mermaid ` fence containing a `flowchart LR`.
75
+ - [ ] Diagram has 3-20 nodes, each with a label ≤ 20 chars.
76
+ - [ ] At least one internal community and one external dep appear in the diagram.
77
+ - [ ] External-dep nodes use the parenthesized shape and the `external` class.
78
+ - [ ] The `classDef external stroke-dasharray: 3 3` line is present.
79
+ - [ ] If overflow occurred, a `## Legend (overflow)` table lists ≥ 5 elided nodes with edge counts.
80
+ - [ ] No YAML frontmatter on the output.
81
+
82
+ ## 9. Anti-goals
83
+
84
+ - Do not re-call `sql`, `dependencies`, or `project_profile` — those are cached in `.prefetch.md` / `.context.md`.
85
+ - Do not invent internal or external node names — every identifier must come from a tool response or a `Read` of the source file.
86
+ - Do not write YAML frontmatter on the output file.
87
+ - Do not emit more than one Mermaid diagram in this file.
88
+ - Do not exceed 20 nodes in the rendered diagram; overflow goes into the Legend table.
89
+ - Do not mix internal and external nodes under the same shape — internals are `[ ]`, externals are `[( )]:::external`.
90
+ - Do not emit emojis.
91
+
92
+ ---
93
+
94
+ ## Work log
95
+
96
+ {{ subagent fills this section per the write protocol }}
97
+
98
+ ## Validation
99
+
100
+ {{ checks run, outputs pasted, any fixes applied }}
101
+
102
+ ## Summary
103
+
104
+ {{ one paragraph — what shipped, where, why the internal/external node selection went the way it did }}