@seanyao/roll 0.5.0 → 2.602.2

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 (181) hide show
  1. package/CHANGELOG.md +736 -0
  2. package/LICENSE +21 -0
  3. package/README.md +65 -165
  4. package/bin/dream-test-quality-scan +110 -0
  5. package/bin/roll +15030 -814
  6. package/conventions/config.yaml +17 -1
  7. package/conventions/global/AGENTS.md +146 -100
  8. package/conventions/global/CLAUDE.md +1 -21
  9. package/conventions/global/GEMINI.md +8 -22
  10. package/conventions/global/project_rules.md +9 -0
  11. package/conventions/templates/backend-service/AGENTS.md +30 -81
  12. package/conventions/templates/backend-service/GEMINI.md +3 -3
  13. package/conventions/templates/backend-service/project_rules.md +16 -0
  14. package/conventions/templates/cli/AGENTS.md +31 -58
  15. package/conventions/templates/cli/CLAUDE.md +3 -5
  16. package/conventions/templates/cli/GEMINI.md +3 -3
  17. package/conventions/templates/cli/project_rules.md +16 -0
  18. package/conventions/templates/frontend-only/AGENTS.md +29 -64
  19. package/conventions/templates/frontend-only/GEMINI.md +3 -3
  20. package/conventions/templates/frontend-only/project_rules.md +14 -0
  21. package/conventions/templates/fullstack/AGENTS.md +31 -79
  22. package/conventions/templates/fullstack/CLAUDE.md +1 -1
  23. package/conventions/templates/fullstack/GEMINI.md +3 -3
  24. package/conventions/templates/fullstack/project_rules.md +15 -0
  25. package/lib/README.md +42 -0
  26. package/lib/__pycache__/github_sync.cpython-314.pyc +0 -0
  27. package/lib/__pycache__/loop-fmt.cpython-314.pyc +0 -0
  28. package/lib/__pycache__/loop_result_eval.cpython-314.pyc +0 -0
  29. package/lib/__pycache__/loop_unstick.cpython-314.pyc +0 -0
  30. package/lib/__pycache__/model_prices.cpython-314.pyc +0 -0
  31. package/lib/__pycache__/prices_fetcher.cpython-314.pyc +0 -0
  32. package/lib/__pycache__/roll-home.cpython-314.pyc +0 -0
  33. package/lib/__pycache__/roll-loop-status.cpython-314.pyc +0 -0
  34. package/lib/__pycache__/roll_git.cpython-314.pyc +0 -0
  35. package/lib/__pycache__/roll_render.cpython-314.pyc +0 -0
  36. package/lib/__pycache__/slides-render.cpython-314.pyc +0 -0
  37. package/lib/agent_usage/README.md +49 -0
  38. package/lib/agent_usage/__init__.py +108 -0
  39. package/lib/agent_usage/__pycache__/__init__.cpython-314.pyc +0 -0
  40. package/lib/agent_usage/__pycache__/gemini.cpython-314.pyc +0 -0
  41. package/lib/agent_usage/__pycache__/kimi.cpython-314.pyc +0 -0
  42. package/lib/agent_usage/__pycache__/openai.cpython-314.pyc +0 -0
  43. package/lib/agent_usage/__pycache__/pi.cpython-314.pyc +0 -0
  44. package/lib/agent_usage/__pycache__/pi_emit.cpython-314.pyc +0 -0
  45. package/lib/agent_usage/__pycache__/qwen.cpython-314.pyc +0 -0
  46. package/lib/agent_usage/gemini.py +127 -0
  47. package/lib/agent_usage/kimi.py +278 -0
  48. package/lib/agent_usage/kimi_emit.py +123 -0
  49. package/lib/agent_usage/openai.py +126 -0
  50. package/lib/agent_usage/pi.py +200 -0
  51. package/lib/agent_usage/pi_emit.py +135 -0
  52. package/lib/agent_usage/qwen.py +128 -0
  53. package/lib/backfill-pi-usage.py +243 -0
  54. package/lib/changelog_audit.py +155 -0
  55. package/lib/changelog_generate.py +263 -0
  56. package/lib/context_feed_budget.sh +194 -0
  57. package/lib/github_sync.py +876 -0
  58. package/lib/i18n/README.md +54 -0
  59. package/lib/i18n/agent.sh +75 -0
  60. package/lib/i18n/alert.sh +20 -0
  61. package/lib/i18n/backlog.sh +96 -0
  62. package/lib/i18n/brief.sh +5 -0
  63. package/lib/i18n/changelog.sh +5 -0
  64. package/lib/i18n/ci.sh +15 -0
  65. package/lib/i18n/debug.sh +0 -0
  66. package/lib/i18n/doctor.sh +44 -0
  67. package/lib/i18n/dream.sh +0 -0
  68. package/lib/i18n/init.sh +91 -0
  69. package/lib/i18n/lang.sh +10 -0
  70. package/lib/i18n/loop.sh +140 -0
  71. package/lib/i18n/migrate.sh +74 -0
  72. package/lib/i18n/offboard.sh +31 -0
  73. package/lib/i18n/onboard.sh +0 -0
  74. package/lib/i18n/peer.sh +41 -0
  75. package/lib/i18n/peer_help.sh +25 -0
  76. package/lib/i18n/peer_reset.sh +7 -0
  77. package/lib/i18n/peer_status.sh +5 -0
  78. package/lib/i18n/prices.sh +3 -0
  79. package/lib/i18n/prices_refresh.sh +17 -0
  80. package/lib/i18n/prices_show.sh +7 -0
  81. package/lib/i18n/propose.sh +0 -0
  82. package/lib/i18n/release.sh +0 -0
  83. package/lib/i18n/research.sh +0 -0
  84. package/lib/i18n/review_pr.sh +0 -0
  85. package/lib/i18n/sentinel.sh +0 -0
  86. package/lib/i18n/setup.sh +3 -0
  87. package/lib/i18n/shared.sh +157 -0
  88. package/lib/i18n/skills/roll-brief.sh +47 -0
  89. package/lib/i18n/skills/roll-build.sh +97 -0
  90. package/lib/i18n/skills/roll-design.sh +18 -0
  91. package/lib/i18n/skills/roll-fix.sh +53 -0
  92. package/lib/i18n/skills/roll-loop.sh +28 -0
  93. package/lib/i18n/skills/roll-onboard.sh +33 -0
  94. package/lib/i18n/skills_catalog.sh +30 -0
  95. package/lib/i18n/slides.sh +3 -0
  96. package/lib/i18n/slides_build.sh +38 -0
  97. package/lib/i18n/slides_delete.sh +19 -0
  98. package/lib/i18n/slides_list.sh +14 -0
  99. package/lib/i18n/slides_logs.sh +12 -0
  100. package/lib/i18n/slides_new.sh +15 -0
  101. package/lib/i18n/slides_preview.sh +14 -0
  102. package/lib/i18n/slides_templates.sh +7 -0
  103. package/lib/i18n/status.sh +21 -0
  104. package/lib/i18n/update.sh +24 -0
  105. package/lib/i18n.sh +211 -0
  106. package/lib/loop-exit-summary.py +393 -0
  107. package/lib/loop-fmt.py +589 -0
  108. package/lib/loop_pick_agent.py +316 -0
  109. package/lib/loop_result_eval.py +469 -0
  110. package/lib/loop_unstick.py +180 -0
  111. package/lib/model_prices.py +194 -0
  112. package/lib/prices/README.md +35 -0
  113. package/lib/prices/snapshot-2026-05-22.json +22 -0
  114. package/lib/prices/snapshot-2026-05-23-deepseek.json +15 -0
  115. package/lib/prices/snapshot-2026-05-23-kimi.json +15 -0
  116. package/lib/prices_fetcher.py +285 -0
  117. package/lib/roll-backlog.py +225 -0
  118. package/lib/roll-brief.py +286 -0
  119. package/lib/roll-help.py +158 -0
  120. package/lib/roll-home.py +556 -0
  121. package/lib/roll-init.py +156 -0
  122. package/lib/roll-loop-status.py +1683 -0
  123. package/lib/roll-loop-story.py +191 -0
  124. package/lib/roll-onboard-render.py +378 -0
  125. package/lib/roll-peer.py +252 -0
  126. package/lib/roll-plan-validate.py +386 -0
  127. package/lib/roll-setup.py +102 -0
  128. package/lib/roll-status.py +367 -0
  129. package/lib/roll_git.py +41 -0
  130. package/lib/roll_render.py +414 -0
  131. package/lib/slides/components/README.md +123 -0
  132. package/lib/slides/components/cards-2.html +9 -0
  133. package/lib/slides/components/cards-3.html +9 -0
  134. package/lib/slides/components/cards-4.html +9 -0
  135. package/lib/slides/components/compare.html +22 -0
  136. package/lib/slides/components/highlight.html +9 -0
  137. package/lib/slides/components/pipeline.html +12 -0
  138. package/lib/slides/components/plain.html +7 -0
  139. package/lib/slides/components/quote.html +4 -0
  140. package/lib/slides/components/timeline.html +9 -0
  141. package/lib/slides/templates/introduction-v3.html +571 -0
  142. package/lib/slides/templates/pitch.html +0 -0
  143. package/lib/slides-render.py +778 -0
  144. package/lib/slides-validate.py +357 -0
  145. package/lib/test_quality_gate.py +143 -0
  146. package/package.json +8 -7
  147. package/skills/roll-.changelog/SKILL.md +406 -33
  148. package/skills/roll-.clarify/SKILL.md +5 -2
  149. package/skills/roll-.dream/SKILL.md +374 -0
  150. package/skills/roll-.echo/SKILL.md +5 -2
  151. package/skills/roll-.qa/SKILL.md +57 -3
  152. package/skills/roll-.review/SKILL.md +42 -3
  153. package/skills/roll-brief/SKILL.md +209 -0
  154. package/skills/roll-build/SKILL.md +308 -63
  155. package/skills/roll-debug/SKILL.md +341 -162
  156. package/skills/roll-debug/injectable-bb.js +263 -0
  157. package/skills/roll-deck/SKILL.md +296 -0
  158. package/skills/roll-design/ENGINEERING_CHECKLIST.md +1 -1
  159. package/skills/roll-design/SKILL.md +733 -94
  160. package/skills/roll-doc/SKILL.md +595 -0
  161. package/skills/roll-doctor/SKILL.md +192 -0
  162. package/skills/roll-fix/SKILL.md +149 -32
  163. package/skills/{roll-jot → roll-idea}/SKILL.md +18 -10
  164. package/skills/roll-loop/SKILL.md +579 -0
  165. package/skills/roll-notes/SKILL.md +103 -0
  166. package/skills/roll-onboard/SKILL.md +234 -0
  167. package/skills/roll-peer/SKILL.md +336 -0
  168. package/skills/roll-propose/SKILL.md +157 -0
  169. package/skills/roll-review-pr/SKILL.md +58 -0
  170. package/skills/roll-sentinel/SKILL.md +11 -2
  171. package/skills/roll-spar/SKILL.md +8 -6
  172. package/template/.github/workflows/ci.yml +5 -2
  173. package/template/AGENTS.md +20 -74
  174. package/skills/roll-research/SKILL.md +0 -307
  175. package/skills/roll-research/references/schema.json +0 -162
  176. package/skills/roll-research/scripts/md_to_pdf.py +0 -289
  177. package/tools/roll-fetch/SKILL.md +0 -182
  178. package/tools/roll-fetch/package.json +0 -15
  179. package/tools/roll-fetch/smart-web-fetch.js +0 -558
  180. package/tools/roll-probe/SKILL.md +0 -84
  181. /package/template/{BACKLOG.md → .roll/backlog.md} +0 -0
@@ -0,0 +1,595 @@
1
+ ---
2
+ name: roll-doc
3
+ license: MIT
4
+ allowed-tools: "Read, Write, Edit, Glob, Grep, Bash(date:*,find:*,stat:*,wc:*)"
5
+ description: "Legacy project documentation automation. Scans all docs, builds/updates docs/INDEX.md, identifies undocumented modules, and generates draft fills for gaps. Works on any project."
6
+ ---
7
+
8
+ # roll-doc
9
+
10
+ Four-phase legacy documentation automation (plus deep-read Phase 3b): scan → index → gap analysis → fill (directory-level) → deep read (cross-directory topics).
11
+
12
+ Works on any project root. No manual mode switching — reads the project state and decides what to do.
13
+
14
+ ## When to Use
15
+
16
+ - Starting to work on a legacy project with scattered or missing documentation
17
+ - `docs/INDEX.md` is out of date or doesn't exist yet
18
+ - `roll-.dream` Scan 6 flagged undocumented modules (REFACTOR entry referencing roll-doc)
19
+ - You want a complete picture of what's documented and what isn't
20
+
21
+ ## When Not to Use
22
+
23
+ - The project has up-to-date, maintained docs — no need to rebuild the index
24
+ - You need authoritative documentation reviewed and approved (drafts only; human reviews and commits)
25
+ - You want to write a specific known doc from scratch — write it directly
26
+
27
+ ## Invocation
28
+
29
+ ```
30
+ $roll-doc # Full four-phase run
31
+ $roll-doc --dry-run # Phases 1–2 only; print Phase 3 plan without writing any files
32
+ $roll-doc --force # Re-generate drafts even for existing files
33
+ ```
34
+
35
+ ## Phase 1 — Scan & Index
36
+
37
+ Scan the project root for all `*.md` files and known convention files.
38
+
39
+ **Exclusions — never scan these directories:**
40
+
41
+ ```
42
+ node_modules/ .git/ dist/ build/ .shared/ .roll/dream/ .roll/briefs/
43
+ ```
44
+
45
+ **Convention files — detect by filename anywhere in the tree:**
46
+
47
+ ```
48
+ AGENTS.md CLAUDE.md GEMINI.md CONVENTIONS.md CONTRIBUTING.md
49
+ ARCHITECTURE.md ADR-*.md
50
+ ```
51
+
52
+ **Classification rules:**
53
+
54
+ | Category | Criteria |
55
+ |----------|----------|
56
+ | `guide` | Path under `guide/` |
57
+ | `domain` | Path under `.roll/domain/` |
58
+ | `convention` | Filename matches convention markers list above |
59
+ | `module` | File is `<dir>/README.md` for a source directory |
60
+ | `stray` | None of the above (top-level, unorganized, or orphaned) |
61
+
62
+ **Output — produce/update `docs/INDEX.md`:**
63
+
64
+ ```markdown
65
+ # Documentation Index
66
+
67
+ > Auto-generated by roll-doc on YYYY-MM-DD. Edit individual docs, not this file.
68
+
69
+ ## Index
70
+
71
+ | Path | Title | Category | Last Modified |
72
+ |------|-------|----------|---------------|
73
+ | guide/en/loop.md | Loop User Guide | guide | 2026-05-01 |
74
+ | AGENTS.md | Agent Conventions | convention | 2026-04-28 |
75
+
76
+ ## Coverage Summary
77
+
78
+ - Total docs indexed: N
79
+ - By category: guide (N) / domain (N) / convention (N) / module (N) / stray (N)
80
+
81
+ ## Gap Report
82
+
83
+ Directories with ≥3 source files and no linked documentation:
84
+
85
+ | Directory | Source Files | Missing Doc |
86
+ |-----------|-------------|-------------|
87
+ | src/commands/ | 8 | README.md |
88
+ ```
89
+
90
+ `docs/INDEX.md` is always overwritten on each run — it is a derived artifact, not authoritative content.
91
+
92
+ ## Phase 2 — Gap Analysis
93
+
94
+ Walk every directory (applying Phase 1 exclusions):
95
+
96
+ 1. Count non-hidden, non-`.md` source files directly in the directory
97
+ 2. If count ≥ 3 AND no `README.md` in that directory AND no `docs/INDEX.md` entry links to it → **module gap**
98
+ 3. **High fan-in gap**: a directory imported by **≥ 5 other source files** is a gap targeting `<dir>/README.md`, **even if it has < 3 source files** — critical low-volume modules (shared utils, single-file core) must not be skipped by the file-count threshold. The existing count ≥ 3 rule (rule 2) continues to apply independently; high fan-in only widens what qualifies, it never overrides rule 2.
99
+
100
+ **Special gaps (checked once per project):**
101
+ - No `.roll/domain/` directory or empty → gap: `.roll/domain/context-map.md`
102
+ - No `CONVENTIONS.md` or `docs/CONVENTIONS.md` exists → gap: `docs/CONVENTIONS.md`
103
+
104
+ **Threshold**: a directory qualifies for a module README gap when **file count ≥ 3 OR imported by ≥ 5 other source files** (default). The fan-in count comes from the Phase 3b symbol table `imports` edges; exclude test files (`*.test.*`, `*.spec.*`, `tests/`) when counting referencing files. An existing `<dir>/README.md` is never overwritten unless `--force`. Tune by editing the skill.
105
+
106
+ Record all gaps — they become Phase 3 input.
107
+
108
+ ## Phase 3 — Fill
109
+
110
+ **Skip this phase entirely when:**
111
+ - `--dry-run` was passed (print the fill plan to stdout, write nothing)
112
+ - Phase 2 found zero gaps
113
+
114
+ **Idempotency rule**: Without `--force`, re-running when no new gaps exist is a **no-op** — no files are written, no existing drafts are modified.
115
+
116
+ For each gap:
117
+ 1. Read up to 20 source files from the target directory to infer module purpose, key exports, dependencies, and configuration patterns
118
+ 2. Generate a draft document at the conventional location (see table below)
119
+ 3. **Skip if the target file already exists**, unless `--force` was passed
120
+
121
+ **Draft locations by gap type:**
122
+
123
+ | Gap Type | Draft Location |
124
+ |----------|---------------|
125
+ | Module with no README | `<dir>/README.md` |
126
+ | No `.roll/domain/` entries | `.roll/domain/context-map.md` |
127
+ | No conventions doc | `docs/CONVENTIONS.md` |
128
+ | Missing `AGENTS.md` `## Where to Look` section | `AGENTS.md` (append or create) |
129
+
130
+ **AGENTS.md Where to Look bootstrap:**
131
+
132
+ When `AGENTS.md` has no `## Where to Look` section, generate and append one:
133
+
134
+ 1. Scan which doc directories actually exist: `.roll/domain/`, `.roll/features/`, `.roll/verification/`, etc.
135
+ 2. Generate pointer lines **only for directories that actually exist** — never fabricate pointers to missing paths
136
+ 3. If `.roll/domain/context-map.md` exists, read it to extract Bounded Context names for a one-line summary
137
+ 4. Append the section to the end of `AGENTS.md` with the standard draft header
138
+ 5. **Idempotency**: if `## Where to Look` already present, do not overwrite or duplicate — skip this gap
139
+
140
+ Draft output format:
141
+
142
+ ```markdown
143
+ > **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
144
+
145
+ ## Where to Look
146
+ - **Domain model**: `.roll/domain/context-map.md` — Contexts: {list from context-map, or "see file"}
147
+ - **Story details**: `.roll/features/` — AC, implementation specs, dependencies
148
+ ```
149
+
150
+ Only include lines for directories that already exist in the project.
151
+
152
+ **Every generated file starts with this exact header line:**
153
+
154
+ ```
155
+ > **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
156
+ ```
157
+
158
+ **Minimum draft content:**
159
+
160
+ - Module README: purpose (1–2 sentences), key files with one-line descriptions, dependencies (imports from / depended on by)
161
+ - Context map: bounded contexts identified in the project, their responsibilities, relationships
162
+ - Conventions: detected patterns — ENV vars, naming conventions, repeated file structure templates
163
+
164
+ Do not fabricate details — infer only from source files actually read.
165
+
166
+ ## Phase 3b — Deep Read
167
+
168
+ Deep-read phase that builds a full project symbol table (without truncation) and auto-detects
169
+ cross-directory topics that directory-level Phase 3 alone cannot discover.
170
+
171
+ **Trigger conditions** — Phase 3b runs when either is true:
172
+ - Phase 2 found any gap (module or special gap)
173
+ - The project exhibits code characteristics that Phase 3a cannot capture:
174
+ cross-directory import chains spanning ≥ 3 directories, state enums referenced by
175
+ multiple files, external URL/endpoint calls, or CI pipeline configuration files
176
+
177
+ Pure documentation-only projects (no source code gaps, no code characteristics) skip Phase 3b.
178
+
179
+ ### Step 1 — Build Symbol Table
180
+
181
+ Read each source file through the context-feed budget (US-CTX-001), not by hard-stuffing whole
182
+ files unconditionally. The existing Phase 3 "up to 20 source files" count limit does not apply —
183
+ Phase 3b aims for a complete project symbol table — but per-file material still goes through the
184
+ feed budget: files within budget are read in full, and over-budget files are summarized/chunked
185
+ with an explicit notice (never silently truncated) so the inner agent's context window is not
186
+ blown. This replaces the previous "read every source file in full, no truncation" unbounded path.
187
+
188
+ **Exclusion directories** (same as Phase 1):
189
+
190
+ ```
191
+ node_modules/ .git/ dist/ build/ .shared/ .roll/dream/ .roll/briefs/
192
+ ```
193
+
194
+ **Symbol table fields:**
195
+
196
+ | Field | Content |
197
+ |-------|---------|
198
+ | `exports` | class / interface / type / function / const declarations, per file |
199
+ | `imports` | source file → target file mapping (dependency graph edges) |
200
+ | `enums` | enum declarations with enumerated values, per file |
201
+ | `external_urls` | `fetch(...)` / `axios` / `http.*` calls, `API_ENDPOINT` / `*_URL` / `*_HOST` constants, hardcoded `https?://` strings (exclude comments and test fixtures) |
202
+ | `configs` | CI workflow YAML files, build config paths, test framework config file paths |
203
+
204
+ **`--dry-run` behavior:** print symbol table summary counts per category (e.g. "exports: 42, imports: 156, enums: 7, external_urls: 4, configs: 3") plus top-N examples per category. Write nothing to disk.
205
+
206
+ **`--force` behavior:** unchanged — `--force` only affects draft generation (Phase 3/3b output files).
207
+ The symbol table itself is rebuilt from scratch on every run regardless of flags.
208
+
209
+ ### Step 2 — Topic Detection
210
+
211
+ Using the symbol table from Step 1, detect cross-directory topics. Each topic type has a
212
+ detection rule and a target output file. Skip any topic whose target file already exists
213
+ (unless `--force`). Skip any topic whose detection rule finds no matches.
214
+
215
+ | Topic | Detection Rule | Output |
216
+ |-------|---------------|--------|
217
+ | 数据流 / 调用链 | Entry files (`bin/`, `cmd/`, `main.*`, `index.*`) → trace import chain to leaf nodes; require ≥ 1 chain spanning ≥ 3 directories | `docs/data-flows.md` |
218
+ | 状态机 | Enums matching `*State` / `*Status` referenced by ≥ 2 source files | `docs/state-machines.md` |
219
+ | 外部集成 | `external_urls` entries from symbol table (exclude comment/test-fixture matches) | `docs/integrations.md` |
220
+ | 部署管线 | `.github/workflows/*.yml` / `.gitlab-ci.yml` / `circle.yml` / `Jenkinsfile` present, with deploy URL patterns detected | `docs/deployment.md` |
221
+ | Agent 入口 (AGENTS.md) | Project root has no `AGENTS.md` AND `src/` (or equivalent source root) has ≥ 3 subdirectories | `AGENTS.md` |
222
+ | 高引用目录 | Directory imported by ≥ 5 other source files, even if directory itself has < 3 source files | `<dir>/README.md` |
223
+
224
+ #### Data Flow / Import Chain Tracing
225
+
226
+ **Entry point selection:** start from entry files — any file matching patterns:
227
+ `bin/*`, `cmd/**/*`, `main.*` (e.g. `main.ts`, `main.py`), `index.*` (e.g. `index.ts`, `index.jsx`),
228
+ `App.*`, `server.*`. Exclude `node_modules/`, `dist/`, `build/`, test files (`*.test.*`, `*.spec.*`, `tests/`).
229
+
230
+ **Chain construction:**
231
+ 1. For each entry file, read its imports from the symbol table's `imports` field.
232
+ 2. Recursively follow each imported file to its own imports, building a directed call graph.
233
+ 3. Stop at leaf nodes — files that import nothing or whose imports all point to:
234
+ - External packages (node_modules / stdlib / third-party)
235
+ - Already-visited nodes (cycle termination)
236
+ 4. Each distinct path from an entry file to a leaf is one call chain.
237
+
238
+ **Threshold (cross-directory filter):**
239
+ A call chain is valid for inclusion only if it spans **≥ 3 distinct source directories**.
240
+ Count based on the unique parent directories of files in the chain:
241
+ `src/cli/main.ts → src/commands/build.ts → lib/utils/fs.ts` = 3 directories ✅
242
+ `src/cli/main.ts → src/cli/config.ts → lib/utils/fs.ts` = 2 directories ❌
243
+ If no chain meets the ≥ 3 directory threshold, skip generation entirely (no empty `docs/data-flows.md`).
244
+
245
+ **Output document structure** (`docs/data-flows.md`):
246
+
247
+ ```markdown
248
+ > **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
249
+
250
+ # Data Flows
251
+
252
+ ## Flow: {short descriptive name from entry file purpose}
253
+
254
+ **Entry point:** `{entry_file}:{line}`
255
+ **Directories spanned:** N ({comma-separated list})
256
+
257
+ ### Complete Call Chain
258
+
259
+ {entry_file}
260
+ → import {symbol} from "{file}" ({line})
261
+ → import {symbol} from "{file}" ({line})
262
+ → ... (leaf node)
263
+
264
+ ### Files Involved
265
+
266
+ | Step | File:Line | Function / Method |
267
+ |------|-----------|-------------------|
268
+ | 1 | `path/to/file:12` | `functionName` |
269
+ | 2 | `path/to/file:34` | `otherFunction` |
270
+ | ... | ... | ... |
271
+ ```
272
+
273
+ - Sort flows by number of directories spanned, descending (widest cross-cutting flow first).
274
+ - If an entry file produces multiple distinct call chains, list each one as a separate flow entry.
275
+ - `file:line` annotations must come from actual symbol table records — do not fabricate.
276
+
277
+ **Idempotency:** skip (do not overwrite) if `docs/data-flows.md` already exists, unless `--force`.
278
+
279
+ #### State Machine
280
+
281
+ **Detection rule:** enums whose name matches `*State` or `*Status` (case-insensitive)
282
+ AND that are imported/referenced by **≥ 2 distinct source files**. Only count
283
+ imports from source files — exclude test files (`*.test.*`, `*.spec.*`, `tests/`)
284
+ and declaration files (`*.d.ts`).
285
+
286
+ **Threshold:** if no enum meets the ≥ 2 cross-file reference threshold, skip
287
+ generation entirely (no empty `docs/state-machines.md`).
288
+
289
+ **Output document structure** (`docs/state-machines.md`):
290
+
291
+ ```markdown
292
+ > **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
293
+
294
+ # State Machines
295
+
296
+ ## State: `{EnumName}`
297
+
298
+ **Defined in:** `{file}:{line}`
299
+
300
+ ### States
301
+ {list of all enum values}
302
+
303
+ ### Referenced By
304
+
305
+ | File:Line | Context |
306
+ |-----------|---------|
307
+ | `path/to/file:12` | `function processOrder(status: OrderState)` |
308
+ | `path/to/file:34` | `if (status === OrderState.Pending)` |
309
+
310
+ ### Inferred Transitions
311
+
312
+ | From | To | Evidence |
313
+ |------|----|----------|
314
+ | `Pending` | `Processing` | `order.ts:45` — `if (status === Pending) { status = Processing }` |
315
+ | `Processing` | `Shipped` | `handler.ts:78` — assignment after `ship()` call |
316
+ ```
317
+
318
+ **Transition inference:** scan the referencing files for patterns where an enum
319
+ value is checked (`if (status === X)`, `case X:`) and the status variable is
320
+ reassigned to another enum value in the same block. Record each distinct
321
+ `{from, to, evidence file:line}` pair. Only include transitions backed by
322
+ explicit code — do not fabricate implied transitions.
323
+
324
+ **Output rules:**
325
+ - One top-level `## State:` section per qualifying enum, sorted alphabetically.
326
+ - Each enum section lists all defined values under `### States`.
327
+ - `file:line` annotations must come from actual symbol table records — do not fabricate.
328
+ - Existing `docs/state-machines.md` → skip unless `--force`.
329
+ - No qualifying enum → skip generation entirely (no empty document).
330
+
331
+ #### External Integrations
332
+
333
+ **Detection rule:** scan `external_urls` from the symbol table —
334
+ `fetch(...)` / `axios` / `http.get` (and `http.*`) calls, constants shaped like
335
+ `API_ENDPOINT` / `*_URL` / `*_HOST`, and hardcoded `https?://` strings. Exclude
336
+ matches inside comments and test fixtures (`*.test.*`, `*.spec.*`, `tests/`,
337
+ `fixtures/`).
338
+
339
+ **Threshold:** if no external integration is detected, skip generation entirely
340
+ (no empty `docs/integrations.md`).
341
+
342
+ **Output document structure** (`docs/integrations.md`):
343
+
344
+ ```markdown
345
+ > **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
346
+
347
+ # External Integrations
348
+
349
+ ## Integration: `{endpoint URL}`
350
+
351
+ ### Call Sites
352
+
353
+ | File:Line | Timeout | Error Handling / Fallback |
354
+ |-----------|---------|---------------------------|
355
+ | `path/to/file:12` | `timeout: 5000` | `.catch` retry fallback |
356
+ | `path/to/file:48` | — | try/catch |
357
+ ```
358
+
359
+ **Per-integration fields:**
360
+ - **endpoint URL** — the external URL / endpoint reached.
361
+ - **call file:line** — every source location calling this endpoint.
362
+ - **timeout config** — the value if the calling code carries a `timeout: N` field,
363
+ otherwise `—`.
364
+ - **error handling / fallback** — recorded when the calling code has a `.catch`
365
+ handler or a `try` / `catch` block around the call, otherwise `—`.
366
+
367
+ **Output rules:**
368
+ - The same endpoint reached from multiple sites is merged into **one** integration
369
+ section that lists **all** its call sites — never one section per call.
370
+ - One top-level `## Integration:` section per distinct endpoint, sorted alphabetically.
371
+ - `file:line` annotations must come from actual symbol table records — do not fabricate.
372
+ - Existing `docs/integrations.md` → skip unless `--force`.
373
+ - No external integration detected → skip generation entirely (no empty document).
374
+
375
+ #### Deployment Pipeline
376
+
377
+ **Detection rule:** the project has at least one CI configuration file —
378
+ `.github/workflows/*.yml` (or `*.yaml`) / `.gitlab-ci.yml` / `circle.yml` /
379
+ `.circleci/config.yml` / `Jenkinsfile` — AND a deploy URL pattern appears in the
380
+ code or CI config (vercel / netlify / cloudflare / firebase, or hostnames ending
381
+ in `*.app` / `*.dev`). Pull deploy URLs from the `configs` and `external_urls`
382
+ fields of the symbol table.
383
+
384
+ **Threshold:** if no CI configuration file is detected, skip generation entirely
385
+ (no empty `docs/deployment.md`).
386
+
387
+ **Output document structure** (`docs/deployment.md`):
388
+
389
+ ```markdown
390
+ > **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
391
+
392
+ # Deployment
393
+
394
+ ## Pipeline: `{ci config file}`
395
+
396
+ **CI Platform:** GitHub Actions
397
+ **Trigger events:** push (main), pull_request, release
398
+
399
+ ### Key Jobs
400
+
401
+ | Job | File:Line | Purpose |
402
+ |-----|-----------|---------|
403
+ | `test` | `.github/workflows/deploy.yml:18` | run test suite |
404
+ | `build` | `.github/workflows/deploy.yml:25` | compile artifacts |
405
+ | `deploy` | `.github/workflows/deploy.yml:33` | deploy to Vercel |
406
+
407
+ ### Deploy Targets
408
+
409
+ | URL | File:Line |
410
+ |-----|-----------|
411
+ | `https://my-app.vercel.app` | `.github/workflows/deploy.yml:14` |
412
+
413
+ ### Environment Variables
414
+
415
+ | Name | File:Line |
416
+ |------|-----------|
417
+ | `NODE_ENV` | `.github/workflows/deploy.yml:11` |
418
+ | `VERCEL_TOKEN` | `.github/workflows/deploy.yml:12` |
419
+ ```
420
+
421
+ **Per-pipeline fields:**
422
+ - **CI platform** — inferred from which config file is present (GitHub Actions /
423
+ GitLab CI / CircleCI / Jenkins).
424
+ - **trigger events** — the events that start the pipeline (`push` / `pull_request` /
425
+ `tag` / `release`), read from the CI config.
426
+ - **key jobs** — each job / stage name with its `file:line` location.
427
+ - **deploy target URL** — the deploy URL(s) matched by the detection rule.
428
+ - **environment variable names** — every env var name referenced in the CI config,
429
+ listed **without values** (never emit secret values, only names).
430
+
431
+ **Output rules:**
432
+ - One top-level `## Pipeline:` section per CI configuration file, sorted alphabetically.
433
+ - `file:line` annotations must come from actual symbol table / CI config records — do not fabricate.
434
+ - Existing `docs/deployment.md` → skip unless `--force`.
435
+ - No CI configuration detected → skip generation entirely (no empty document).
436
+
437
+ #### Agent Entrypoint (AGENTS.md)
438
+
439
+ This topic handles the **「文件不存在 → 创建」** case: when a project has no agent-facing
440
+ convention file at all, generate a complete baseline `AGENTS.md`. It is complementary to the
441
+ Phase 2 **"AGENTS.md Where to Look bootstrap"** rule, which handles the **「文件存在 → 补章节」**
442
+ case (append a missing `## Where to Look` section to an existing `AGENTS.md`). The two rules
443
+ never overlap — this one only fires when no `AGENTS.md` exists.
444
+
445
+ **Detection rule:** project root has **no** `AGENTS.md` AND the source root (`src/`, or the
446
+ equivalent — `lib/`, `app/`, `pkg/`, etc.) contains **≥ 3 subdirectories**. If `AGENTS.md`
447
+ already exists, skip entirely (do not overwrite unless `--force`). If the source root has
448
+ fewer than 3 subdirectories, skip — the project is too small to warrant a baseline doc.
449
+
450
+ **Output document structure** (`AGENTS.md`) — at minimum three required sections:
451
+
452
+ ```markdown
453
+ > **Draft** — auto-generated by roll-doc on YYYY-MM-DD. Review before treating as authoritative.
454
+
455
+ # {Project Name}
456
+
457
+ {One-sentence positioning: what this project is, inferred from README / package metadata.}
458
+
459
+ ## Where to Look
460
+
461
+ - **Domain model**: `.roll/domain/context-map.md` — Contexts: {list, or "see file"}
462
+ - **Story details**: `.roll/features/` — AC, implementation specs, dependencies
463
+ - **Doc index**: `docs/INDEX.md` — generated documentation map
464
+
465
+ ## Source Layout
466
+
467
+ | Directory | Purpose |
468
+ |-----------|---------|
469
+ | `src/parser/` | tokenize and parse input (≤ 2 lines each) |
470
+ | `src/codegen/` | emit output artifacts |
471
+ | `src/cli/` | command-line entry and option wiring |
472
+ ```
473
+
474
+ **Per-section rules:**
475
+ - **Project positioning** — a single sentence describing what the project does, inferred from
476
+ the README / package metadata; never fabricate beyond what the source supports.
477
+ - **`## Where to Look`** — pointer lines **only for directories that actually exist**
478
+ (`.roll/domain/`, `.roll/features/`, `docs/INDEX.md`, etc.); never fabricate pointers to
479
+ missing paths. If `.roll/domain/context-map.md` exists, read it for Bounded Context names.
480
+ - **Source Layout** — one row per key source subdirectory, each description **≤ 2 lines**,
481
+ inferred from the files actually read in the symbol table.
482
+
483
+ **Output rules:**
484
+ - Existing `AGENTS.md` → skip unless `--force` (never overwrite a human-authored file).
485
+ - Source root with < 3 subdirectories → skip generation entirely (no empty `AGENTS.md`).
486
+ - All three sections must be present in the generated file.
487
+
488
+ #### High Fan-in Directory (README)
489
+
490
+ This topic complements the Phase 2 file-count threshold. A directory may hold only one or two
491
+ source files yet be imported across the whole codebase (shared utils, a single-file core
492
+ module). The file-count rule (≥ 3 files) alone skips such hot paths, so high fan-in widens the
493
+ threshold to **「文件数 ≥ 3 OR 被 ≥ 5 个文件引用」**.
494
+
495
+ **Detection rule:** using the symbol table's `imports` edges, count the **distinct source files
496
+ that import any file in the directory**. If that count is **≥ 5**, the directory qualifies for a
497
+ `<dir>/README.md` gap, **even when it contains < 3 source files**. Only count referencing files
498
+ that are source files — exclude test files (`*.test.*`, `*.spec.*`, `tests/`) and files inside
499
+ the directory itself. This rule operates **in addition to** the Phase 2 count ≥ 3 rule, never
500
+ replacing it: directories meeting either condition get a README.
501
+
502
+ **Output rules:**
503
+ - Target file is `<dir>/README.md`, generated with the same Module README content as Phase 3
504
+ (purpose, key files, dependencies).
505
+ - Existing `<dir>/README.md` → skip unless `--force` (never overwrite).
506
+ - Directory imported by < 5 source files **and** holding < 3 source files → skip (no gap).
507
+ - A directory already qualifying under the count ≥ 3 rule is not double-counted — one README.
508
+
509
+ ### Step 3 — Source Annotations
510
+
511
+ Every topic document generated in Step 2 must cite `file:line` for each claim (function call,
512
+ endpoint URL, state transition, CI job, import path). Annotations must come from actual
513
+ symbol table records — do not fabricate line numbers. Follows the same "Do not fabricate"
514
+ rule as Phase 3.
515
+
516
+ **Mandatory `file:line` column** — each topic document's source-reference tables MUST carry a
517
+ dedicated `file:line` column so the reader can jump straight to the code:
518
+ - 「涉及文件」/ Files Involved table → one `file:line` per row.
519
+ - 「引用文件」/ Referenced By table → one `file:line` per referencing site.
520
+ - 「调用链」/ Complete Call Chain table → one `file:line` per hop.
521
+
522
+ Do **not** fabricate a `file:line` value: every annotation MUST come from an actual symbol
523
+ table record (the same "Do not fabricate" rule as above). If the symbol table has no line for
524
+ a claim, omit the row rather than invent a location.
525
+
526
+ ---
527
+
528
+ ## Phase 4 — Report
529
+
530
+ After all phases complete, output a summary:
531
+
532
+ ```
533
+ 📚 roll-doc complete
534
+
535
+ Phase 1 — Index
536
+ N docs scanned, docs/INDEX.md updated
537
+ Categories: guide(N) domain(N) convention(N) module(N) stray(N)
538
+
539
+ Phase 2 — Gaps
540
+ N undocumented module directories found
541
+ N special gaps (domain map / conventions)
542
+
543
+ Phase 3 — Fill
544
+ N drafts generated: [list of paths]
545
+ N skipped (already exist; use --force to regenerate)
546
+
547
+ Phase 3b — Deep Read
548
+ Symbol table: exports(N) imports(N) enums(N) external_urls(N) configs(N)
549
+ N topic documents generated:
550
+ - docs/dataflow.md (data-flow) source entries: N
551
+ - docs/state-machines.md (state-machine) source entries: N
552
+ - docs/integrations.md (external-integration) source entries: N
553
+ N topics skipped (no matches or already exist; use --force to regenerate)
554
+
555
+ 📋 Review priority (largest / most active modules first):
556
+ 1. src/commands/README.md — 8 source files
557
+ 2. docs/CONVENTIONS.md — 6 patterns detected
558
+ ```
559
+
560
+ Each generated topic document is listed with its **path**, **type**, and **来源条目数 /
561
+ source entries** (how many symbol-table records back the document). When Phase 3b produced no
562
+ subject-level documents, print exactly one line and do **not** error:
563
+
564
+ ```
565
+ Phase 3b: no subject-level drafts generated
566
+ ```
567
+
568
+ If `--dry-run`, the `Phase 3b — Deep Read` section is shown the same way but every generated
569
+ line is tagged `(plan)` — matching Phase 3's dry-run convention (nothing is written):
570
+
571
+ ```
572
+ Phase 3b — Deep Read (plan)
573
+ N topic documents would be generated:
574
+ - docs/dataflow.md (data-flow) source entries: N (plan)
575
+ ```
576
+
577
+ If no gaps were found:
578
+
579
+ ```
580
+ ✅ roll-doc: no gaps found. docs/INDEX.md updated.
581
+ ```
582
+
583
+ If `--dry-run`:
584
+
585
+ ```
586
+ 🔍 roll-doc --dry-run: N drafts would be generated (nothing written).
587
+ ```
588
+
589
+ ## Rules
590
+
591
+ - Never modify existing documentation files — only generate new drafts
592
+ - `docs/INDEX.md` is the only existing file that may be overwritten (derived artifact)
593
+ - Draft files are never committed by this skill — human reviews and commits them
594
+ - Works on any project; always read project structure before acting
595
+ - Do not fabricate module details — infer only from source files actually read