@jokerized/getresearchdone 0.4.1

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 (711) hide show
  1. package/.claude-plugin/plugin.json +103 -0
  2. package/README.md +211 -0
  3. package/agents/grd-baseline-assessor.md +684 -0
  4. package/agents/grd-code-reviewer.md +300 -0
  5. package/agents/grd-codebase-mapper.md +355 -0
  6. package/agents/grd-critique-agent.md +119 -0
  7. package/agents/grd-debugger.md +519 -0
  8. package/agents/grd-deep-diver.md +737 -0
  9. package/agents/grd-eval-planner.md +913 -0
  10. package/agents/grd-eval-reporter.md +717 -0
  11. package/agents/grd-executor.md +683 -0
  12. package/agents/grd-feasibility-analyst.md +624 -0
  13. package/agents/grd-integration-checker.md +367 -0
  14. package/agents/grd-knowledge-miner.md +81 -0
  15. package/agents/grd-migrator.md +88 -0
  16. package/agents/grd-phase-researcher.md +697 -0
  17. package/agents/grd-plan-checker.md +443 -0
  18. package/agents/grd-planner.md +1532 -0
  19. package/agents/grd-product-owner.md +562 -0
  20. package/agents/grd-project-researcher.md +513 -0
  21. package/agents/grd-research-synthesizer.md +273 -0
  22. package/agents/grd-roadmapper.md +798 -0
  23. package/agents/grd-surveyor.md +566 -0
  24. package/agents/grd-verifier.md +893 -0
  25. package/bin/gd.js +4 -0
  26. package/bin/gd.ts +227 -0
  27. package/bin/grd-manifest.js +4 -0
  28. package/bin/grd-manifest.ts +286 -0
  29. package/bin/grd-mcp-server.js +4 -0
  30. package/bin/grd-mcp-server.ts +124 -0
  31. package/bin/grd-tools.js +4 -0
  32. package/bin/grd-tools.ts +2471 -0
  33. package/bin/postinstall.js +4 -0
  34. package/bin/postinstall.ts +80 -0
  35. package/commands/add-phase.md +123 -0
  36. package/commands/add-todo.md +87 -0
  37. package/commands/assess-baseline.md +289 -0
  38. package/commands/autopilot.md +100 -0
  39. package/commands/autoplan.md +55 -0
  40. package/commands/check-todos.md +87 -0
  41. package/commands/compare-methods.md +262 -0
  42. package/commands/complete-milestone.md +225 -0
  43. package/commands/debug.md +372 -0
  44. package/commands/deep-dive.md +288 -0
  45. package/commands/discover.md +281 -0
  46. package/commands/discuss-phase.md +188 -0
  47. package/commands/discuss.md +55 -0
  48. package/commands/eval-report.md +310 -0
  49. package/commands/evolve.md +79 -0
  50. package/commands/execute-phase.md +1017 -0
  51. package/commands/feasibility.md +292 -0
  52. package/commands/help.md +407 -0
  53. package/commands/init.md +1508 -0
  54. package/commands/insert-phase.md +113 -0
  55. package/commands/iterate.md +327 -0
  56. package/commands/list-phase-assumptions.md +217 -0
  57. package/commands/long-term-roadmap.md +202 -0
  58. package/commands/map-codebase.md +111 -0
  59. package/commands/migrate.md +159 -0
  60. package/commands/new-milestone.md +169 -0
  61. package/commands/pause-work.md +83 -0
  62. package/commands/plan-milestone-gaps.md +373 -0
  63. package/commands/plan-phase.md +655 -0
  64. package/commands/principles.md +328 -0
  65. package/commands/product-plan.md +319 -0
  66. package/commands/progress.md +481 -0
  67. package/commands/quick.md +167 -0
  68. package/commands/reapply-patches.md +154 -0
  69. package/commands/remove-phase.md +97 -0
  70. package/commands/requirement.md +96 -0
  71. package/commands/resume-project.md +113 -0
  72. package/commands/settings.md +1144 -0
  73. package/commands/survey.md +242 -0
  74. package/commands/sync.md +246 -0
  75. package/commands/tracker-setup.md +322 -0
  76. package/commands/update.md +202 -0
  77. package/commands/verify-phase.md +335 -0
  78. package/commands/verify-work.md +701 -0
  79. package/commands/wireup.md +29 -0
  80. package/dist/bin/gd.d.ts +3 -0
  81. package/dist/bin/gd.d.ts.map +1 -0
  82. package/dist/bin/gd.js +178 -0
  83. package/dist/bin/gd.js.map +1 -0
  84. package/dist/bin/grd-manifest.d.ts +3 -0
  85. package/dist/bin/grd-manifest.d.ts.map +1 -0
  86. package/dist/bin/grd-manifest.js +202 -0
  87. package/dist/bin/grd-manifest.js.map +1 -0
  88. package/dist/bin/grd-mcp-server.d.ts +3 -0
  89. package/dist/bin/grd-mcp-server.d.ts.map +1 -0
  90. package/dist/bin/grd-mcp-server.js +71 -0
  91. package/dist/bin/grd-mcp-server.js.map +1 -0
  92. package/dist/bin/grd-tools.d.ts +3 -0
  93. package/dist/bin/grd-tools.d.ts.map +1 -0
  94. package/dist/bin/grd-tools.js +1680 -0
  95. package/dist/bin/grd-tools.js.map +1 -0
  96. package/dist/bin/postinstall.d.ts +3 -0
  97. package/dist/bin/postinstall.d.ts.map +1 -0
  98. package/dist/bin/postinstall.js +61 -0
  99. package/dist/bin/postinstall.js.map +1 -0
  100. package/dist/lib/autopilot-milestone.d.ts +2 -0
  101. package/dist/lib/autopilot-milestone.d.ts.map +1 -0
  102. package/dist/lib/autopilot-milestone.js +94 -0
  103. package/dist/lib/autopilot-milestone.js.map +1 -0
  104. package/dist/lib/autopilot-pipeline.d.ts +2 -0
  105. package/dist/lib/autopilot-pipeline.d.ts.map +1 -0
  106. package/dist/lib/autopilot-pipeline.js +830 -0
  107. package/dist/lib/autopilot-pipeline.js.map +1 -0
  108. package/dist/lib/autopilot-waves.d.ts +2 -0
  109. package/dist/lib/autopilot-waves.d.ts.map +1 -0
  110. package/dist/lib/autopilot-waves.js +266 -0
  111. package/dist/lib/autopilot-waves.js.map +1 -0
  112. package/dist/lib/autopilot.d.ts +2 -0
  113. package/dist/lib/autopilot.d.ts.map +1 -0
  114. package/dist/lib/autopilot.js +1314 -0
  115. package/dist/lib/autopilot.js.map +1 -0
  116. package/dist/lib/autoplan.d.ts +2 -0
  117. package/dist/lib/autoplan.d.ts.map +1 -0
  118. package/dist/lib/autoplan.js +198 -0
  119. package/dist/lib/autoplan.js.map +1 -0
  120. package/dist/lib/autoresearch.d.ts +2 -0
  121. package/dist/lib/autoresearch.d.ts.map +1 -0
  122. package/dist/lib/autoresearch.js +626 -0
  123. package/dist/lib/autoresearch.js.map +1 -0
  124. package/dist/lib/backend.d.ts +2 -0
  125. package/dist/lib/backend.d.ts.map +1 -0
  126. package/dist/lib/backend.js +1036 -0
  127. package/dist/lib/backend.js.map +1 -0
  128. package/dist/lib/benchmark.d.ts +99 -0
  129. package/dist/lib/benchmark.d.ts.map +1 -0
  130. package/dist/lib/benchmark.js +278 -0
  131. package/dist/lib/benchmark.js.map +1 -0
  132. package/dist/lib/citations.d.ts +2 -0
  133. package/dist/lib/citations.d.ts.map +1 -0
  134. package/dist/lib/citations.js +642 -0
  135. package/dist/lib/citations.js.map +1 -0
  136. package/dist/lib/cleanup.d.ts +2 -0
  137. package/dist/lib/cleanup.d.ts.map +1 -0
  138. package/dist/lib/cleanup.js +1222 -0
  139. package/dist/lib/cleanup.js.map +1 -0
  140. package/dist/lib/cli/adapters.d.ts +10 -0
  141. package/dist/lib/cli/adapters.d.ts.map +1 -0
  142. package/dist/lib/cli/adapters.js +27 -0
  143. package/dist/lib/cli/adapters.js.map +1 -0
  144. package/dist/lib/cli/agent.d.ts +17 -0
  145. package/dist/lib/cli/agent.d.ts.map +1 -0
  146. package/dist/lib/cli/agent.js +53 -0
  147. package/dist/lib/cli/agent.js.map +1 -0
  148. package/dist/lib/cli/index.d.ts +21 -0
  149. package/dist/lib/cli/index.d.ts.map +1 -0
  150. package/dist/lib/cli/index.js +264 -0
  151. package/dist/lib/cli/index.js.map +1 -0
  152. package/dist/lib/cli/output.d.ts +20 -0
  153. package/dist/lib/cli/output.d.ts.map +1 -0
  154. package/dist/lib/cli/output.js +22 -0
  155. package/dist/lib/cli/output.js.map +1 -0
  156. package/dist/lib/cli/scan-dispatch.d.ts +9 -0
  157. package/dist/lib/cli/scan-dispatch.d.ts.map +1 -0
  158. package/dist/lib/cli/scan-dispatch.js +107 -0
  159. package/dist/lib/cli/scan-dispatch.js.map +1 -0
  160. package/dist/lib/cli/tools.d.ts +16 -0
  161. package/dist/lib/cli/tools.d.ts.map +1 -0
  162. package/dist/lib/cli/tools.js +168 -0
  163. package/dist/lib/cli/tools.js.map +1 -0
  164. package/dist/lib/commands/_dashboard-parsers.d.ts +2 -0
  165. package/dist/lib/commands/_dashboard-parsers.d.ts.map +1 -0
  166. package/dist/lib/commands/_dashboard-parsers.js +192 -0
  167. package/dist/lib/commands/_dashboard-parsers.js.map +1 -0
  168. package/dist/lib/commands/analysis.d.ts +2 -0
  169. package/dist/lib/commands/analysis.d.ts.map +1 -0
  170. package/dist/lib/commands/analysis.js +1418 -0
  171. package/dist/lib/commands/analysis.js.map +1 -0
  172. package/dist/lib/commands/assumptions.d.ts +2 -0
  173. package/dist/lib/commands/assumptions.d.ts.map +1 -0
  174. package/dist/lib/commands/assumptions.js +166 -0
  175. package/dist/lib/commands/assumptions.js.map +1 -0
  176. package/dist/lib/commands/blame.d.ts +2 -0
  177. package/dist/lib/commands/blame.d.ts.map +1 -0
  178. package/dist/lib/commands/blame.js +133 -0
  179. package/dist/lib/commands/blame.js.map +1 -0
  180. package/dist/lib/commands/budget.d.ts +2 -0
  181. package/dist/lib/commands/budget.d.ts.map +1 -0
  182. package/dist/lib/commands/budget.js +100 -0
  183. package/dist/lib/commands/budget.js.map +1 -0
  184. package/dist/lib/commands/check-plans.d.ts +2 -0
  185. package/dist/lib/commands/check-plans.d.ts.map +1 -0
  186. package/dist/lib/commands/check-plans.js +190 -0
  187. package/dist/lib/commands/check-plans.js.map +1 -0
  188. package/dist/lib/commands/config.d.ts +2 -0
  189. package/dist/lib/commands/config.d.ts.map +1 -0
  190. package/dist/lib/commands/config.js +188 -0
  191. package/dist/lib/commands/config.js.map +1 -0
  192. package/dist/lib/commands/dashboard.d.ts +2 -0
  193. package/dist/lib/commands/dashboard.d.ts.map +1 -0
  194. package/dist/lib/commands/dashboard.js +466 -0
  195. package/dist/lib/commands/dashboard.js.map +1 -0
  196. package/dist/lib/commands/estimate.d.ts +2 -0
  197. package/dist/lib/commands/estimate.d.ts.map +1 -0
  198. package/dist/lib/commands/estimate.js +148 -0
  199. package/dist/lib/commands/estimate.js.map +1 -0
  200. package/dist/lib/commands/eval-diff.d.ts +2 -0
  201. package/dist/lib/commands/eval-diff.d.ts.map +1 -0
  202. package/dist/lib/commands/eval-diff.js +213 -0
  203. package/dist/lib/commands/eval-diff.js.map +1 -0
  204. package/dist/lib/commands/freshness.d.ts +2 -0
  205. package/dist/lib/commands/freshness.d.ts.map +1 -0
  206. package/dist/lib/commands/freshness.js +163 -0
  207. package/dist/lib/commands/freshness.js.map +1 -0
  208. package/dist/lib/commands/health.d.ts +2 -0
  209. package/dist/lib/commands/health.d.ts.map +1 -0
  210. package/dist/lib/commands/health.js +435 -0
  211. package/dist/lib/commands/health.js.map +1 -0
  212. package/dist/lib/commands/index.d.ts +2 -0
  213. package/dist/lib/commands/index.d.ts.map +1 -0
  214. package/dist/lib/commands/index.js +128 -0
  215. package/dist/lib/commands/index.js.map +1 -0
  216. package/dist/lib/commands/install.d.ts +56 -0
  217. package/dist/lib/commands/install.d.ts.map +1 -0
  218. package/dist/lib/commands/install.js +214 -0
  219. package/dist/lib/commands/install.js.map +1 -0
  220. package/dist/lib/commands/knowhow-aggregator.d.ts +2 -0
  221. package/dist/lib/commands/knowhow-aggregator.d.ts.map +1 -0
  222. package/dist/lib/commands/knowhow-aggregator.js +279 -0
  223. package/dist/lib/commands/knowhow-aggregator.js.map +1 -0
  224. package/dist/lib/commands/knowledge-search.d.ts +2 -0
  225. package/dist/lib/commands/knowledge-search.d.ts.map +1 -0
  226. package/dist/lib/commands/knowledge-search.js +113 -0
  227. package/dist/lib/commands/knowledge-search.js.map +1 -0
  228. package/dist/lib/commands/long-term-roadmap.d.ts +2 -0
  229. package/dist/lib/commands/long-term-roadmap.d.ts.map +1 -0
  230. package/dist/lib/commands/long-term-roadmap.js +272 -0
  231. package/dist/lib/commands/long-term-roadmap.js.map +1 -0
  232. package/dist/lib/commands/patterns.d.ts +91 -0
  233. package/dist/lib/commands/patterns.d.ts.map +1 -0
  234. package/dist/lib/commands/patterns.js +391 -0
  235. package/dist/lib/commands/patterns.js.map +1 -0
  236. package/dist/lib/commands/phase-info.d.ts +2 -0
  237. package/dist/lib/commands/phase-info.d.ts.map +1 -0
  238. package/dist/lib/commands/phase-info.js +509 -0
  239. package/dist/lib/commands/phase-info.js.map +1 -0
  240. package/dist/lib/commands/plan-lint.d.ts +56 -0
  241. package/dist/lib/commands/plan-lint.d.ts.map +1 -0
  242. package/dist/lib/commands/plan-lint.js +481 -0
  243. package/dist/lib/commands/plan-lint.js.map +1 -0
  244. package/dist/lib/commands/plan-phase.d.ts +53 -0
  245. package/dist/lib/commands/plan-phase.d.ts.map +1 -0
  246. package/dist/lib/commands/plan-phase.js +288 -0
  247. package/dist/lib/commands/plan-phase.js.map +1 -0
  248. package/dist/lib/commands/progress.d.ts +2 -0
  249. package/dist/lib/commands/progress.d.ts.map +1 -0
  250. package/dist/lib/commands/progress.js +266 -0
  251. package/dist/lib/commands/progress.js.map +1 -0
  252. package/dist/lib/commands/quality.d.ts +2 -0
  253. package/dist/lib/commands/quality.d.ts.map +1 -0
  254. package/dist/lib/commands/quality.js +80 -0
  255. package/dist/lib/commands/quality.js.map +1 -0
  256. package/dist/lib/commands/rollback.d.ts +2 -0
  257. package/dist/lib/commands/rollback.d.ts.map +1 -0
  258. package/dist/lib/commands/rollback.js +145 -0
  259. package/dist/lib/commands/rollback.js.map +1 -0
  260. package/dist/lib/commands/scan.d.ts +25 -0
  261. package/dist/lib/commands/scan.d.ts.map +1 -0
  262. package/dist/lib/commands/scan.js +28 -0
  263. package/dist/lib/commands/scan.js.map +1 -0
  264. package/dist/lib/commands/search.d.ts +2 -0
  265. package/dist/lib/commands/search.d.ts.map +1 -0
  266. package/dist/lib/commands/search.js +212 -0
  267. package/dist/lib/commands/search.js.map +1 -0
  268. package/dist/lib/commands/select-candidate.d.ts +128 -0
  269. package/dist/lib/commands/select-candidate.d.ts.map +1 -0
  270. package/dist/lib/commands/select-candidate.js +518 -0
  271. package/dist/lib/commands/select-candidate.js.map +1 -0
  272. package/dist/lib/commands/singularity.d.ts +2 -0
  273. package/dist/lib/commands/singularity.d.ts.map +1 -0
  274. package/dist/lib/commands/singularity.js +185 -0
  275. package/dist/lib/commands/singularity.js.map +1 -0
  276. package/dist/lib/commands/slug-timestamp.d.ts +2 -0
  277. package/dist/lib/commands/slug-timestamp.d.ts.map +1 -0
  278. package/dist/lib/commands/slug-timestamp.js +54 -0
  279. package/dist/lib/commands/slug-timestamp.js.map +1 -0
  280. package/dist/lib/commands/tail.d.ts +2 -0
  281. package/dist/lib/commands/tail.d.ts.map +1 -0
  282. package/dist/lib/commands/tail.js +100 -0
  283. package/dist/lib/commands/tail.js.map +1 -0
  284. package/dist/lib/commands/todo.d.ts +2 -0
  285. package/dist/lib/commands/todo.d.ts.map +1 -0
  286. package/dist/lib/commands/todo.js +200 -0
  287. package/dist/lib/commands/todo.js.map +1 -0
  288. package/dist/lib/commands/watch.d.ts +2 -0
  289. package/dist/lib/commands/watch.d.ts.map +1 -0
  290. package/dist/lib/commands/watch.js +72 -0
  291. package/dist/lib/commands/watch.js.map +1 -0
  292. package/dist/lib/complexity.d.ts +55 -0
  293. package/dist/lib/complexity.d.ts.map +1 -0
  294. package/dist/lib/complexity.js +80 -0
  295. package/dist/lib/complexity.js.map +1 -0
  296. package/dist/lib/context/agents.d.ts +2 -0
  297. package/dist/lib/context/agents.d.ts.map +1 -0
  298. package/dist/lib/context/agents.js +344 -0
  299. package/dist/lib/context/agents.js.map +1 -0
  300. package/dist/lib/context/base.d.ts +2 -0
  301. package/dist/lib/context/base.d.ts.map +1 -0
  302. package/dist/lib/context/base.js +81 -0
  303. package/dist/lib/context/base.js.map +1 -0
  304. package/dist/lib/context/execute.d.ts +2 -0
  305. package/dist/lib/context/execute.d.ts.map +1 -0
  306. package/dist/lib/context/execute.js +753 -0
  307. package/dist/lib/context/execute.js.map +1 -0
  308. package/dist/lib/context/index.d.ts +2 -0
  309. package/dist/lib/context/index.d.ts.map +1 -0
  310. package/dist/lib/context/index.js +88 -0
  311. package/dist/lib/context/index.js.map +1 -0
  312. package/dist/lib/context/progress.d.ts +2 -0
  313. package/dist/lib/context/progress.d.ts.map +1 -0
  314. package/dist/lib/context/progress.js +178 -0
  315. package/dist/lib/context/progress.js.map +1 -0
  316. package/dist/lib/context/project.d.ts +2 -0
  317. package/dist/lib/context/project.d.ts.map +1 -0
  318. package/dist/lib/context/project.js +413 -0
  319. package/dist/lib/context/project.js.map +1 -0
  320. package/dist/lib/context/research.d.ts +2 -0
  321. package/dist/lib/context/research.d.ts.map +1 -0
  322. package/dist/lib/context/research.js +466 -0
  323. package/dist/lib/context/research.js.map +1 -0
  324. package/dist/lib/dead-ends.d.ts +28 -0
  325. package/dist/lib/dead-ends.d.ts.map +1 -0
  326. package/dist/lib/dead-ends.js +451 -0
  327. package/dist/lib/dead-ends.js.map +1 -0
  328. package/dist/lib/deps.d.ts +2 -0
  329. package/dist/lib/deps.d.ts.map +1 -0
  330. package/dist/lib/deps.js +630 -0
  331. package/dist/lib/deps.js.map +1 -0
  332. package/dist/lib/discussion.d.ts +2 -0
  333. package/dist/lib/discussion.d.ts.map +1 -0
  334. package/dist/lib/discussion.js +1041 -0
  335. package/dist/lib/discussion.js.map +1 -0
  336. package/dist/lib/drift.d.ts +36 -0
  337. package/dist/lib/drift.d.ts.map +1 -0
  338. package/dist/lib/drift.js +481 -0
  339. package/dist/lib/drift.js.map +1 -0
  340. package/dist/lib/evolve/_dimensions-features.d.ts +2 -0
  341. package/dist/lib/evolve/_dimensions-features.d.ts.map +1 -0
  342. package/dist/lib/evolve/_dimensions-features.js +369 -0
  343. package/dist/lib/evolve/_dimensions-features.js.map +1 -0
  344. package/dist/lib/evolve/_dimensions.d.ts +2 -0
  345. package/dist/lib/evolve/_dimensions.d.ts.map +1 -0
  346. package/dist/lib/evolve/_dimensions.js +358 -0
  347. package/dist/lib/evolve/_dimensions.js.map +1 -0
  348. package/dist/lib/evolve/_product-ideation.d.ts +2 -0
  349. package/dist/lib/evolve/_product-ideation.d.ts.map +1 -0
  350. package/dist/lib/evolve/_product-ideation.js +281 -0
  351. package/dist/lib/evolve/_product-ideation.js.map +1 -0
  352. package/dist/lib/evolve/_prompts.d.ts +2 -0
  353. package/dist/lib/evolve/_prompts.d.ts.map +1 -0
  354. package/dist/lib/evolve/_prompts.js +153 -0
  355. package/dist/lib/evolve/_prompts.js.map +1 -0
  356. package/dist/lib/evolve/cli.d.ts +2 -0
  357. package/dist/lib/evolve/cli.d.ts.map +1 -0
  358. package/dist/lib/evolve/cli.js +224 -0
  359. package/dist/lib/evolve/cli.js.map +1 -0
  360. package/dist/lib/evolve/discovery.d.ts +2 -0
  361. package/dist/lib/evolve/discovery.d.ts.map +1 -0
  362. package/dist/lib/evolve/discovery.js +391 -0
  363. package/dist/lib/evolve/discovery.js.map +1 -0
  364. package/dist/lib/evolve/index.d.ts +2 -0
  365. package/dist/lib/evolve/index.d.ts.map +1 -0
  366. package/dist/lib/evolve/index.js +88 -0
  367. package/dist/lib/evolve/index.js.map +1 -0
  368. package/dist/lib/evolve/orchestrator.d.ts +2 -0
  369. package/dist/lib/evolve/orchestrator.d.ts.map +1 -0
  370. package/dist/lib/evolve/orchestrator.js +851 -0
  371. package/dist/lib/evolve/orchestrator.js.map +1 -0
  372. package/dist/lib/evolve/scoring.d.ts +2 -0
  373. package/dist/lib/evolve/scoring.d.ts.map +1 -0
  374. package/dist/lib/evolve/scoring.js +118 -0
  375. package/dist/lib/evolve/scoring.js.map +1 -0
  376. package/dist/lib/evolve/state.d.ts +2 -0
  377. package/dist/lib/evolve/state.d.ts.map +1 -0
  378. package/dist/lib/evolve/state.js +264 -0
  379. package/dist/lib/evolve/state.js.map +1 -0
  380. package/dist/lib/evolve/types.d.ts +249 -0
  381. package/dist/lib/evolve/types.d.ts.map +1 -0
  382. package/dist/lib/evolve/types.js +3 -0
  383. package/dist/lib/evolve/types.js.map +1 -0
  384. package/dist/lib/frontmatter.d.ts +2 -0
  385. package/dist/lib/frontmatter.d.ts.map +1 -0
  386. package/dist/lib/frontmatter.js +513 -0
  387. package/dist/lib/frontmatter.js.map +1 -0
  388. package/dist/lib/gates.d.ts +2 -0
  389. package/dist/lib/gates.d.ts.map +1 -0
  390. package/dist/lib/gates.js +578 -0
  391. package/dist/lib/gates.js.map +1 -0
  392. package/dist/lib/genome.d.ts +10 -0
  393. package/dist/lib/genome.d.ts.map +1 -0
  394. package/dist/lib/genome.js +368 -0
  395. package/dist/lib/genome.js.map +1 -0
  396. package/dist/lib/got.d.ts +2 -0
  397. package/dist/lib/got.d.ts.map +1 -0
  398. package/dist/lib/got.js +280 -0
  399. package/dist/lib/got.js.map +1 -0
  400. package/dist/lib/invariants.d.ts +2 -0
  401. package/dist/lib/invariants.d.ts.map +1 -0
  402. package/dist/lib/invariants.js +298 -0
  403. package/dist/lib/invariants.js.map +1 -0
  404. package/dist/lib/knowledge.d.ts +2 -0
  405. package/dist/lib/knowledge.d.ts.map +1 -0
  406. package/dist/lib/knowledge.js +658 -0
  407. package/dist/lib/knowledge.js.map +1 -0
  408. package/dist/lib/long-term-roadmap.d.ts +2 -0
  409. package/dist/lib/long-term-roadmap.d.ts.map +1 -0
  410. package/dist/lib/long-term-roadmap.js +602 -0
  411. package/dist/lib/long-term-roadmap.js.map +1 -0
  412. package/dist/lib/markdown-split.d.ts +2 -0
  413. package/dist/lib/markdown-split.d.ts.map +1 -0
  414. package/dist/lib/markdown-split.js +199 -0
  415. package/dist/lib/markdown-split.js.map +1 -0
  416. package/dist/lib/mcp-server.d.ts +2 -0
  417. package/dist/lib/mcp-server.d.ts.map +1 -0
  418. package/dist/lib/mcp-server.js +2424 -0
  419. package/dist/lib/mcp-server.js.map +1 -0
  420. package/dist/lib/metrics.d.ts +16 -0
  421. package/dist/lib/metrics.d.ts.map +1 -0
  422. package/dist/lib/metrics.js +48 -0
  423. package/dist/lib/metrics.js.map +1 -0
  424. package/dist/lib/overstory.d.ts +2 -0
  425. package/dist/lib/overstory.d.ts.map +1 -0
  426. package/dist/lib/overstory.js +211 -0
  427. package/dist/lib/overstory.js.map +1 -0
  428. package/dist/lib/parallel.d.ts +2 -0
  429. package/dist/lib/parallel.d.ts.map +1 -0
  430. package/dist/lib/parallel.js +349 -0
  431. package/dist/lib/parallel.js.map +1 -0
  432. package/dist/lib/paths.d.ts +2 -0
  433. package/dist/lib/paths.d.ts.map +1 -0
  434. package/dist/lib/paths.js +254 -0
  435. package/dist/lib/paths.js.map +1 -0
  436. package/dist/lib/phase-complete-llm.d.ts +22 -0
  437. package/dist/lib/phase-complete-llm.d.ts.map +1 -0
  438. package/dist/lib/phase-complete-llm.js +331 -0
  439. package/dist/lib/phase-complete-llm.js.map +1 -0
  440. package/dist/lib/phase-complete.d.ts +46 -0
  441. package/dist/lib/phase-complete.d.ts.map +1 -0
  442. package/dist/lib/phase-complete.js +278 -0
  443. package/dist/lib/phase-complete.js.map +1 -0
  444. package/dist/lib/phase-io.d.ts +2 -0
  445. package/dist/lib/phase-io.d.ts.map +1 -0
  446. package/dist/lib/phase-io.js +126 -0
  447. package/dist/lib/phase-io.js.map +1 -0
  448. package/dist/lib/phase.d.ts +2 -0
  449. package/dist/lib/phase.d.ts.map +1 -0
  450. package/dist/lib/phase.js +1344 -0
  451. package/dist/lib/phase.js.map +1 -0
  452. package/dist/lib/plan-tournament.d.ts +63 -0
  453. package/dist/lib/plan-tournament.d.ts.map +1 -0
  454. package/dist/lib/plan-tournament.js +353 -0
  455. package/dist/lib/plan-tournament.js.map +1 -0
  456. package/dist/lib/refinement.d.ts +74 -0
  457. package/dist/lib/refinement.d.ts.map +1 -0
  458. package/dist/lib/refinement.js +283 -0
  459. package/dist/lib/refinement.js.map +1 -0
  460. package/dist/lib/requirements.d.ts +2 -0
  461. package/dist/lib/requirements.d.ts.map +1 -0
  462. package/dist/lib/requirements.js +355 -0
  463. package/dist/lib/requirements.js.map +1 -0
  464. package/dist/lib/research-bundle.d.ts +2 -0
  465. package/dist/lib/research-bundle.d.ts.map +1 -0
  466. package/dist/lib/research-bundle.js +246 -0
  467. package/dist/lib/research-bundle.js.map +1 -0
  468. package/dist/lib/roadmap.d.ts +2 -0
  469. package/dist/lib/roadmap.d.ts.map +1 -0
  470. package/dist/lib/roadmap.js +541 -0
  471. package/dist/lib/roadmap.js.map +1 -0
  472. package/dist/lib/sample.d.ts +16 -0
  473. package/dist/lib/sample.d.ts.map +1 -0
  474. package/dist/lib/sample.js +20 -0
  475. package/dist/lib/sample.js.map +1 -0
  476. package/dist/lib/scaffold.d.ts +2 -0
  477. package/dist/lib/scaffold.d.ts.map +1 -0
  478. package/dist/lib/scaffold.js +355 -0
  479. package/dist/lib/scaffold.js.map +1 -0
  480. package/dist/lib/scan/_utils.d.ts +11 -0
  481. package/dist/lib/scan/_utils.d.ts.map +1 -0
  482. package/dist/lib/scan/_utils.js +36 -0
  483. package/dist/lib/scan/_utils.js.map +1 -0
  484. package/dist/lib/scan/base64.d.ts +15 -0
  485. package/dist/lib/scan/base64.d.ts.map +1 -0
  486. package/dist/lib/scan/base64.js +66 -0
  487. package/dist/lib/scan/base64.js.map +1 -0
  488. package/dist/lib/scan/ignorefile.d.ts +30 -0
  489. package/dist/lib/scan/ignorefile.d.ts.map +1 -0
  490. package/dist/lib/scan/ignorefile.js +101 -0
  491. package/dist/lib/scan/ignorefile.js.map +1 -0
  492. package/dist/lib/scan/injection.d.ts +14 -0
  493. package/dist/lib/scan/injection.d.ts.map +1 -0
  494. package/dist/lib/scan/injection.js +39 -0
  495. package/dist/lib/scan/injection.js.map +1 -0
  496. package/dist/lib/scan/patterns.d.ts +17 -0
  497. package/dist/lib/scan/patterns.d.ts.map +1 -0
  498. package/dist/lib/scan/patterns.js +123 -0
  499. package/dist/lib/scan/patterns.js.map +1 -0
  500. package/dist/lib/scan/strip-markdown.d.ts +7 -0
  501. package/dist/lib/scan/strip-markdown.d.ts.map +1 -0
  502. package/dist/lib/scan/strip-markdown.js +38 -0
  503. package/dist/lib/scan/strip-markdown.js.map +1 -0
  504. package/dist/lib/scan/types.d.ts +23 -0
  505. package/dist/lib/scan/types.d.ts.map +1 -0
  506. package/dist/lib/scan/types.js +3 -0
  507. package/dist/lib/scan/types.js.map +1 -0
  508. package/dist/lib/scheduler-wait.d.ts +2 -0
  509. package/dist/lib/scheduler-wait.d.ts.map +1 -0
  510. package/dist/lib/scheduler-wait.js +59 -0
  511. package/dist/lib/scheduler-wait.js.map +1 -0
  512. package/dist/lib/scheduler.d.ts +254 -0
  513. package/dist/lib/scheduler.d.ts.map +1 -0
  514. package/dist/lib/scheduler.js +1147 -0
  515. package/dist/lib/scheduler.js.map +1 -0
  516. package/dist/lib/state.d.ts +2 -0
  517. package/dist/lib/state.d.ts.map +1 -0
  518. package/dist/lib/state.js +744 -0
  519. package/dist/lib/state.js.map +1 -0
  520. package/dist/lib/think.d.ts +18 -0
  521. package/dist/lib/think.d.ts.map +1 -0
  522. package/dist/lib/think.js +317 -0
  523. package/dist/lib/think.js.map +1 -0
  524. package/dist/lib/tracker.d.ts +2 -0
  525. package/dist/lib/tracker.d.ts.map +1 -0
  526. package/dist/lib/tracker.js +1121 -0
  527. package/dist/lib/tracker.js.map +1 -0
  528. package/dist/lib/types.d.ts +1514 -0
  529. package/dist/lib/types.d.ts.map +1 -0
  530. package/dist/lib/types.js +4 -0
  531. package/dist/lib/types.js.map +1 -0
  532. package/dist/lib/utils.d.ts +2 -0
  533. package/dist/lib/utils.d.ts.map +1 -0
  534. package/dist/lib/utils.js +1363 -0
  535. package/dist/lib/utils.js.map +1 -0
  536. package/dist/lib/verify.d.ts +2 -0
  537. package/dist/lib/verify.d.ts.map +1 -0
  538. package/dist/lib/verify.js +1153 -0
  539. package/dist/lib/verify.js.map +1 -0
  540. package/dist/lib/wireup/autofix.d.ts +2 -0
  541. package/dist/lib/wireup/autofix.d.ts.map +1 -0
  542. package/dist/lib/wireup/autofix.js +188 -0
  543. package/dist/lib/wireup/autofix.js.map +1 -0
  544. package/dist/lib/wireup/cli.d.ts +2 -0
  545. package/dist/lib/wireup/cli.d.ts.map +1 -0
  546. package/dist/lib/wireup/cli.js +194 -0
  547. package/dist/lib/wireup/cli.js.map +1 -0
  548. package/dist/lib/wireup/detection.d.ts +47 -0
  549. package/dist/lib/wireup/detection.d.ts.map +1 -0
  550. package/dist/lib/wireup/detection.js +410 -0
  551. package/dist/lib/wireup/detection.js.map +1 -0
  552. package/dist/lib/wireup/discovery.d.ts +2 -0
  553. package/dist/lib/wireup/discovery.d.ts.map +1 -0
  554. package/dist/lib/wireup/discovery.js +934 -0
  555. package/dist/lib/wireup/discovery.js.map +1 -0
  556. package/dist/lib/wireup/execution.d.ts +2 -0
  557. package/dist/lib/wireup/execution.d.ts.map +1 -0
  558. package/dist/lib/wireup/execution.js +573 -0
  559. package/dist/lib/wireup/execution.js.map +1 -0
  560. package/dist/lib/wireup/index.d.ts +2 -0
  561. package/dist/lib/wireup/index.d.ts.map +1 -0
  562. package/dist/lib/wireup/index.js +85 -0
  563. package/dist/lib/wireup/index.js.map +1 -0
  564. package/dist/lib/wireup/orchestrator.d.ts +2 -0
  565. package/dist/lib/wireup/orchestrator.d.ts.map +1 -0
  566. package/dist/lib/wireup/orchestrator.js +366 -0
  567. package/dist/lib/wireup/orchestrator.js.map +1 -0
  568. package/dist/lib/wireup/report.d.ts +47 -0
  569. package/dist/lib/wireup/report.d.ts.map +1 -0
  570. package/dist/lib/wireup/report.js +201 -0
  571. package/dist/lib/wireup/report.js.map +1 -0
  572. package/dist/lib/wireup/scenarios.d.ts +2 -0
  573. package/dist/lib/wireup/scenarios.d.ts.map +1 -0
  574. package/dist/lib/wireup/scenarios.js +516 -0
  575. package/dist/lib/wireup/scenarios.js.map +1 -0
  576. package/dist/lib/wireup/state.d.ts +2 -0
  577. package/dist/lib/wireup/state.d.ts.map +1 -0
  578. package/dist/lib/wireup/state.js +102 -0
  579. package/dist/lib/wireup/state.js.map +1 -0
  580. package/dist/lib/wireup/types.d.ts +376 -0
  581. package/dist/lib/wireup/types.d.ts.map +1 -0
  582. package/dist/lib/wireup/types.js +3 -0
  583. package/dist/lib/wireup/types.js.map +1 -0
  584. package/dist/lib/worktree.d.ts +2 -0
  585. package/dist/lib/worktree.d.ts.map +1 -0
  586. package/dist/lib/worktree.js +999 -0
  587. package/dist/lib/worktree.js.map +1 -0
  588. package/lib/autopilot-milestone.ts +136 -0
  589. package/lib/autopilot-pipeline.ts +1179 -0
  590. package/lib/autopilot-waves.ts +361 -0
  591. package/lib/autopilot.ts +1874 -0
  592. package/lib/autoplan.ts +280 -0
  593. package/lib/autoresearch.js +4 -0
  594. package/lib/autoresearch.ts +886 -0
  595. package/lib/backend.ts +1252 -0
  596. package/lib/benchmark.ts +341 -0
  597. package/lib/citations.ts +760 -0
  598. package/lib/cleanup.ts +1588 -0
  599. package/lib/cli/adapters.ts +41 -0
  600. package/lib/cli/agent.ts +83 -0
  601. package/lib/cli/index.ts +273 -0
  602. package/lib/cli/output.ts +33 -0
  603. package/lib/cli/scan-dispatch.ts +130 -0
  604. package/lib/cli/tools.ts +198 -0
  605. package/lib/commands/_dashboard-parsers.ts +275 -0
  606. package/lib/commands/analysis.ts +1851 -0
  607. package/lib/commands/assumptions.ts +232 -0
  608. package/lib/commands/blame.ts +174 -0
  609. package/lib/commands/budget.ts +148 -0
  610. package/lib/commands/check-plans.ts +233 -0
  611. package/lib/commands/config.ts +287 -0
  612. package/lib/commands/dashboard.ts +680 -0
  613. package/lib/commands/estimate.ts +204 -0
  614. package/lib/commands/eval-diff.ts +252 -0
  615. package/lib/commands/freshness.ts +213 -0
  616. package/lib/commands/health.ts +607 -0
  617. package/lib/commands/index.ts +266 -0
  618. package/lib/commands/install.ts +307 -0
  619. package/lib/commands/knowhow-aggregator.ts +345 -0
  620. package/lib/commands/knowledge-search.ts +153 -0
  621. package/lib/commands/long-term-roadmap.ts +390 -0
  622. package/lib/commands/patterns.ts +465 -0
  623. package/lib/commands/phase-info.ts +698 -0
  624. package/lib/commands/plan-lint.ts +546 -0
  625. package/lib/commands/plan-phase.ts +375 -0
  626. package/lib/commands/progress.ts +319 -0
  627. package/lib/commands/quality.ts +138 -0
  628. package/lib/commands/rollback.ts +195 -0
  629. package/lib/commands/scan.ts +72 -0
  630. package/lib/commands/search.ts +300 -0
  631. package/lib/commands/select-candidate.ts +687 -0
  632. package/lib/commands/singularity.ts +222 -0
  633. package/lib/commands/slug-timestamp.ts +74 -0
  634. package/lib/commands/tail.ts +129 -0
  635. package/lib/commands/todo.ts +273 -0
  636. package/lib/commands/watch.ts +80 -0
  637. package/lib/complexity.ts +117 -0
  638. package/lib/context/agents.ts +505 -0
  639. package/lib/context/base.ts +123 -0
  640. package/lib/context/execute.ts +977 -0
  641. package/lib/context/index.ts +110 -0
  642. package/lib/context/progress.ts +278 -0
  643. package/lib/context/project.ts +531 -0
  644. package/lib/context/research.ts +646 -0
  645. package/lib/dead-ends.ts +506 -0
  646. package/lib/deps.ts +773 -0
  647. package/lib/discussion.ts +1275 -0
  648. package/lib/drift.ts +519 -0
  649. package/lib/evolve/_dimensions-features.ts +525 -0
  650. package/lib/evolve/_dimensions.ts +511 -0
  651. package/lib/evolve/_product-ideation.ts +405 -0
  652. package/lib/evolve/_prompts.ts +178 -0
  653. package/lib/evolve/cli.ts +330 -0
  654. package/lib/evolve/discovery.ts +571 -0
  655. package/lib/evolve/index.ts +105 -0
  656. package/lib/evolve/orchestrator.ts +1139 -0
  657. package/lib/evolve/scoring.ts +167 -0
  658. package/lib/evolve/state.ts +330 -0
  659. package/lib/evolve/types.ts +290 -0
  660. package/lib/frontmatter.ts +615 -0
  661. package/lib/gates.ts +695 -0
  662. package/lib/genome.ts +402 -0
  663. package/lib/got.js +4 -0
  664. package/lib/got.ts +361 -0
  665. package/lib/invariants.ts +378 -0
  666. package/lib/knowledge.ts +768 -0
  667. package/lib/long-term-roadmap.ts +806 -0
  668. package/lib/markdown-split.ts +273 -0
  669. package/lib/mcp-server.ts +3292 -0
  670. package/lib/metrics.ts +49 -0
  671. package/lib/overstory.ts +270 -0
  672. package/lib/parallel.ts +570 -0
  673. package/lib/paths.ts +293 -0
  674. package/lib/phase-complete-llm.ts +376 -0
  675. package/lib/phase-complete.ts +366 -0
  676. package/lib/phase-io.ts +101 -0
  677. package/lib/phase.ts +1981 -0
  678. package/lib/plan-tournament.ts +426 -0
  679. package/lib/refinement.ts +349 -0
  680. package/lib/requirements.ts +469 -0
  681. package/lib/research-bundle.ts +300 -0
  682. package/lib/roadmap.ts +775 -0
  683. package/lib/scaffold.ts +480 -0
  684. package/lib/scan/_utils.ts +37 -0
  685. package/lib/scan/base64.ts +90 -0
  686. package/lib/scan/ignorefile.ts +109 -0
  687. package/lib/scan/injection.ts +67 -0
  688. package/lib/scan/patterns.ts +139 -0
  689. package/lib/scan/strip-markdown.ts +39 -0
  690. package/lib/scan/types.ts +28 -0
  691. package/lib/scheduler-wait.ts +58 -0
  692. package/lib/scheduler.ts +1370 -0
  693. package/lib/state.ts +1000 -0
  694. package/lib/think.ts +365 -0
  695. package/lib/tracker.ts +1591 -0
  696. package/lib/types.ts +1663 -0
  697. package/lib/utils.ts +1479 -0
  698. package/lib/verify.ts +1434 -0
  699. package/lib/wireup/autofix.ts +241 -0
  700. package/lib/wireup/cli.ts +278 -0
  701. package/lib/wireup/detection.ts +542 -0
  702. package/lib/wireup/discovery.ts +1063 -0
  703. package/lib/wireup/execution.ts +686 -0
  704. package/lib/wireup/index.ts +117 -0
  705. package/lib/wireup/orchestrator.ts +519 -0
  706. package/lib/wireup/report.ts +286 -0
  707. package/lib/wireup/scenarios.ts +616 -0
  708. package/lib/wireup/state.ts +139 -0
  709. package/lib/wireup/types.ts +436 -0
  710. package/lib/worktree.ts +1309 -0
  711. package/package.json +67 -0
package/lib/deps.ts ADDED
@@ -0,0 +1,773 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * GRD Dependency Analysis -- Phase dependency graph, parallel group computation, cycle detection
5
+ *
6
+ * Provides tooling for analyzing ROADMAP.md phase dependencies to determine
7
+ * which phases can execute in parallel vs. which must be sequential.
8
+ *
9
+ * Depends on: lib/utils.ts (output, error), lib/roadmap.ts (analyzeRoadmap)
10
+ */
11
+
12
+
13
+ import type { DependencyGraph, DependencyNode, DependencyEdge, ArtifactDAG, ArtifactDAGNode, ArtifactDAGEdge, ArtifactDAGValidation, PlanArtifact } from './types';
14
+
15
+ const fs = require('fs') as typeof import('fs');
16
+ const path = require('path') as typeof import('path');
17
+ const { output, error: _depsError, findPhaseInternal } = require('./utils') as {
18
+ output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
19
+ error: (msg: string) => never;
20
+ findPhaseInternal: (cwd: string, phase: string) => import('./types').PhaseInfo | null;
21
+ };
22
+ const { analyzeRoadmap } = require('./roadmap');
23
+
24
+ // ─── Types ──────────────────────────────────────────────────────────────────
25
+
26
+ /**
27
+ * Phase input for building dependency graphs.
28
+ * Compatible with AnalyzedPhaseEntry from roadmap.ts.
29
+ */
30
+ interface PhaseInput {
31
+ number: string;
32
+ name: string;
33
+ depends_on?: string | null;
34
+ }
35
+
36
+ /**
37
+ * Result of dependency analysis with graph, parallel groups, and cycle info.
38
+ */
39
+ interface DepsAnalysisResult {
40
+ nodes: DependencyNode[];
41
+ edges: DependencyEdge[];
42
+ parallel_groups?: string[][];
43
+ has_cycle: boolean;
44
+ phase_count?: number;
45
+ group_count?: number;
46
+ error?: string;
47
+ cycle_path?: string[];
48
+ }
49
+
50
+ // ─── parseDependsOn ──────────────────────────────────────────────────────────
51
+
52
+ /**
53
+ * Parse a raw depends_on string from ROADMAP.md into an array of phase number strings.
54
+ * @param dependsOnStr - Raw depends_on string (e.g., "Phase 27, Phase 29", "Nothing", null)
55
+ * @returns Array of phase number strings (e.g., ['27', '29']), or [] if no dependencies
56
+ */
57
+ function parseDependsOn(dependsOnStr: string | null | undefined): string[] {
58
+ if (!dependsOnStr || typeof dependsOnStr !== 'string' || dependsOnStr.trim() === '') {
59
+ return [];
60
+ }
61
+
62
+ // "Nothing" (case-insensitive) means no dependencies
63
+ if (/nothing/i.test(dependsOnStr)) {
64
+ return [];
65
+ }
66
+
67
+ // Extract all "Phase N" or "Phase N.M" references
68
+ const matches: string[] = [];
69
+ const regex = /Phase\s+(\d+(?:\.\d+)?)/gi;
70
+ let m: RegExpExecArray | null;
71
+ while ((m = regex.exec(dependsOnStr)) !== null) {
72
+ matches.push(m[1]);
73
+ }
74
+
75
+ return matches;
76
+ }
77
+
78
+ // ─── buildDependencyGraph ────────────────────────────────────────────────────
79
+
80
+ /**
81
+ * Build a dependency graph from an array of phase objects.
82
+ * @param phases - Phase objects from roadmap analysis
83
+ * @returns Dependency graph with typed nodes and edges
84
+ */
85
+ function buildDependencyGraph(phases: PhaseInput[]): DependencyGraph {
86
+ const nodeIds = new Set<string>(phases.map((p) => p.number));
87
+
88
+ const nodes: DependencyNode[] = phases.map((p) => ({
89
+ id: p.number,
90
+ name: p.name,
91
+ }));
92
+
93
+ const edges: DependencyEdge[] = [];
94
+ for (const phase of phases) {
95
+ const deps = parseDependsOn(phase.depends_on);
96
+ for (const dep of deps) {
97
+ // Only include edges where the dependency exists in the node set
98
+ if (nodeIds.has(dep)) {
99
+ edges.push({ from: dep, to: phase.number });
100
+ }
101
+ }
102
+ }
103
+
104
+ return { nodes, edges };
105
+ }
106
+
107
+ // ─── computeParallelGroups ───────────────────────────────────────────────────
108
+
109
+ /**
110
+ * Compute parallel execution groups via Kahn's algorithm (topological sort by levels).
111
+ * Each group contains phases that can run concurrently because all their
112
+ * dependencies have been satisfied in previous groups.
113
+ * @param graph - Dependency graph
114
+ * @returns Array of arrays, each inner array is a set of phase IDs that can run together
115
+ */
116
+ function computeParallelGroups(graph: DependencyGraph): string[][] {
117
+ if (graph.nodes.length === 0) {
118
+ return [];
119
+ }
120
+
121
+ // Build adjacency list and in-degree map
122
+ const adjacency = new Map<string, string[]>(); // from -> [to]
123
+ const inDegree = new Map<string, number>();
124
+
125
+ for (const node of graph.nodes) {
126
+ adjacency.set(node.id, []);
127
+ inDegree.set(node.id, 0);
128
+ }
129
+
130
+ for (const edge of graph.edges) {
131
+ (adjacency.get(edge.from) as string[]).push(edge.to);
132
+ inDegree.set(edge.to, (inDegree.get(edge.to) || 0) + 1);
133
+ }
134
+
135
+ const groups: string[][] = [];
136
+ const remaining = new Set<string>(graph.nodes.map((n) => n.id));
137
+
138
+ while (remaining.size > 0) {
139
+ // Collect nodes with in-degree 0 among remaining nodes
140
+ const group: string[] = [];
141
+ for (const nodeId of remaining) {
142
+ if (inDegree.get(nodeId) === 0) {
143
+ group.push(nodeId);
144
+ }
145
+ }
146
+
147
+ if (group.length === 0) {
148
+ // All remaining nodes have dependencies -- cycle exists
149
+ // Return what we have (caller should use detectCycle separately)
150
+ break;
151
+ }
152
+
153
+ // Sort component-wise to avoid parseFloat('1.10') === parseFloat('1.1') collision
154
+ group.sort((a, b) => {
155
+ const pa = a.split('.').map(Number);
156
+ const pb = b.split('.').map(Number);
157
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
158
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
159
+ if (d !== 0) return d;
160
+ }
161
+ return 0;
162
+ });
163
+ groups.push(group);
164
+
165
+ // Remove current group's nodes and decrement in-degrees
166
+ for (const nodeId of group) {
167
+ remaining.delete(nodeId);
168
+ for (const dependent of adjacency.get(nodeId) as string[]) {
169
+ if (remaining.has(dependent)) {
170
+ inDegree.set(dependent, (inDegree.get(dependent) as number) - 1);
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ return groups;
177
+ }
178
+
179
+ // ─── detectCycle ─────────────────────────────────────────────────────────────
180
+
181
+ /**
182
+ * Detect cycles in a dependency graph using DFS.
183
+ * @param graph - Dependency graph
184
+ * @returns Cycle path array if cycle found (e.g., ['27', '28', '27']), or null if acyclic
185
+ */
186
+ function detectCycle(graph: DependencyGraph): string[] | null {
187
+ // Build adjacency list (forward edges: from -> [to])
188
+ const adjacency = new Map<string, string[]>();
189
+ for (const node of graph.nodes) {
190
+ adjacency.set(node.id, []);
191
+ }
192
+ for (const edge of graph.edges) {
193
+ (adjacency.get(edge.from) as string[]).push(edge.to);
194
+ }
195
+
196
+ // Node states: 0 = unvisited, 1 = visiting (in current DFS path), 2 = visited
197
+ const state = new Map<string, number>();
198
+ for (const node of graph.nodes) {
199
+ state.set(node.id, 0);
200
+ }
201
+
202
+ // Track the DFS path for cycle reconstruction
203
+ const pathStack: string[] = [];
204
+
205
+ function dfs(nodeId: string): string[] | null {
206
+ state.set(nodeId, 1); // visiting
207
+ pathStack.push(nodeId);
208
+
209
+ for (const neighbor of adjacency.get(nodeId) as string[]) {
210
+ if (state.get(neighbor) === 1) {
211
+ // Found a back-edge -- reconstruct cycle
212
+ const cycleStart = pathStack.indexOf(neighbor);
213
+ const cyclePath = pathStack.slice(cycleStart);
214
+ cyclePath.push(neighbor); // close the cycle
215
+ return cyclePath;
216
+ }
217
+ if (state.get(neighbor) === 0) {
218
+ const result = dfs(neighbor);
219
+ if (result) return result;
220
+ }
221
+ }
222
+
223
+ pathStack.pop();
224
+ state.set(nodeId, 2); // visited
225
+ return null;
226
+ }
227
+
228
+ for (const node of graph.nodes) {
229
+ if (state.get(node.id) === 0) {
230
+ const cycle = dfs(node.id);
231
+ if (cycle) return cycle;
232
+ }
233
+ }
234
+
235
+ return null;
236
+ }
237
+
238
+ // ─── cmdPhaseAnalyzeDeps ─────────────────────────────────────────────────────
239
+
240
+ /**
241
+ * CLI command: Analyze phase dependencies from ROADMAP.md, build graph, compute parallel groups.
242
+ * Calls analyzeRoadmap(cwd) internally to reuse roadmap parsing (including depends_on extraction).
243
+ * @param cwd - Project working directory
244
+ * @param raw - Output raw text instead of JSON
245
+ * @returns void — outputs JSON or raw text to stdout via the output helper
246
+ */
247
+ function cmdPhaseAnalyzeDeps(cwd: string, raw: boolean): void {
248
+ const roadmapResult = analyzeRoadmap(cwd) as {
249
+ error?: string;
250
+ phases?: PhaseInput[];
251
+ };
252
+
253
+ // Handle missing roadmap or error
254
+ if (roadmapResult.error || !roadmapResult.phases || roadmapResult.phases.length === 0) {
255
+ output({ error: roadmapResult.error || 'ROADMAP.md not found or empty' }, raw);
256
+ return;
257
+ }
258
+
259
+ const phases = roadmapResult.phases;
260
+ const graph: DependencyGraph = buildDependencyGraph(phases);
261
+ const cycle = detectCycle(graph);
262
+
263
+ if (cycle) {
264
+ const result: DepsAnalysisResult = {
265
+ error: 'Circular dependency detected',
266
+ cycle_path: cycle,
267
+ has_cycle: true,
268
+ nodes: graph.nodes,
269
+ edges: graph.edges,
270
+ };
271
+ output(result, raw, `Circular dependency detected: ${cycle.join(' → ')}`);
272
+ return;
273
+ }
274
+
275
+ const parallelGroups = computeParallelGroups(graph);
276
+
277
+ const result: DepsAnalysisResult = {
278
+ nodes: graph.nodes,
279
+ edges: graph.edges,
280
+ parallel_groups: parallelGroups,
281
+ has_cycle: false,
282
+ phase_count: graph.nodes.length,
283
+ group_count: parallelGroups.length,
284
+ };
285
+ output(result, raw, `${graph.nodes.length} phases, ${parallelGroups.length} parallel groups`);
286
+ }
287
+
288
+ // ─── buildArtifactDAG ────────────────────────────────────────────────────────
289
+
290
+ /**
291
+ * Build a directed artifact dependency graph from an array of plan artifacts.
292
+ *
293
+ * 1. Constructs a providers map: artifact_name → plan_id (first declaration wins).
294
+ * 2. Builds ArtifactDAGNode[] from each plan's provides/requires/integration_points.
295
+ * 3. Builds ArtifactDAGEdge[]: for each requires/integration_points entry, look up
296
+ * the provider and create a directed edge (consumer → producer).
297
+ * Integration edges are only created when a matching provider exists.
298
+ * 4. Runs Kahn's algorithm to produce a topologically sorted execution order.
299
+ *
300
+ * @param plans - Array of plan artifacts parsed from PLAN.md frontmatter
301
+ * @returns ArtifactDAG with nodes, edges, sorted_plans, and providers map
302
+ */
303
+ function buildArtifactDAG(plans: PlanArtifact[]): ArtifactDAG {
304
+ // Step 1: Build providers map — first declaration wins
305
+ const providers: Record<string, string> = {};
306
+ for (const plan of plans) {
307
+ const planId = `${plan.phase}-${String(plan.plan).padStart(2, '0')}`;
308
+ for (const artifact of plan.provides) {
309
+ if (!(artifact in providers)) {
310
+ providers[artifact] = planId;
311
+ }
312
+ }
313
+ }
314
+
315
+ // Step 2: Build nodes
316
+ const nodes: ArtifactDAGNode[] = plans.map((plan) => ({
317
+ id: `${plan.phase}-${String(plan.plan).padStart(2, '0')}`,
318
+ plan_number: plan.plan,
319
+ provides: plan.provides,
320
+ requires: plan.requires,
321
+ integration_points: plan.integration_points,
322
+ }));
323
+
324
+ // Step 3: Build edges
325
+ const edges: ArtifactDAGEdge[] = [];
326
+ const missing_requires: string[] = [];
327
+ for (const node of nodes) {
328
+ // Hard dependency edges from requires
329
+ for (const artifact of node.requires) {
330
+ const providerPlanId = providers[artifact];
331
+ if (providerPlanId === undefined) {
332
+ missing_requires.push(artifact);
333
+ } else if (providerPlanId !== node.id) {
334
+ edges.push({
335
+ from_plan: node.id,
336
+ to_plan: providerPlanId,
337
+ artifact,
338
+ type: 'requires',
339
+ });
340
+ }
341
+ }
342
+ // Soft dependency edges from integration_points (only when provider exists)
343
+ for (const artifact of node.integration_points) {
344
+ const providerPlanId = providers[artifact];
345
+ if (providerPlanId !== undefined && providerPlanId !== node.id) {
346
+ edges.push({
347
+ from_plan: node.id,
348
+ to_plan: providerPlanId,
349
+ artifact,
350
+ type: 'integration',
351
+ });
352
+ }
353
+ }
354
+ }
355
+
356
+ // Step 4: Kahn's topological sort
357
+ // adjacency: producer → [consumers] (edge from_plan depends on to_plan,
358
+ // so to_plan must come before from_plan; in Kahn's terms: to_plan → from_plan)
359
+ const adjacency = new Map<string, string[]>();
360
+ const inDegree = new Map<string, number>();
361
+
362
+ for (const node of nodes) {
363
+ adjacency.set(node.id, []);
364
+ inDegree.set(node.id, 0);
365
+ }
366
+
367
+ for (const edge of edges) {
368
+ // to_plan must execute before from_plan → edge in sort graph: to_plan → from_plan
369
+ const producers = adjacency.get(edge.to_plan);
370
+ if (producers !== undefined) {
371
+ producers.push(edge.from_plan);
372
+ }
373
+ inDegree.set(edge.from_plan, (inDegree.get(edge.from_plan) ?? 0) + 1);
374
+ }
375
+
376
+ const sorted_plans: string[] = [];
377
+ const remaining = new Set<string>(nodes.map((n) => n.id));
378
+
379
+ while (remaining.size > 0) {
380
+ const batch: string[] = [];
381
+ for (const nodeId of remaining) {
382
+ if ((inDegree.get(nodeId) ?? 0) === 0) {
383
+ batch.push(nodeId);
384
+ }
385
+ }
386
+
387
+ if (batch.length === 0) {
388
+ // Cycle prevents full sort — return partial (validateArtifactDAG will catch this)
389
+ break;
390
+ }
391
+
392
+ // Sort lexicographically for deterministic output (plan IDs are string slugs, not numeric)
393
+ batch.sort();
394
+ for (const nodeId of batch) {
395
+ sorted_plans.push(nodeId);
396
+ remaining.delete(nodeId);
397
+ for (const dependent of adjacency.get(nodeId) as string[]) {
398
+ if (remaining.has(dependent)) {
399
+ inDegree.set(dependent, (inDegree.get(dependent) as number) - 1);
400
+ }
401
+ }
402
+ }
403
+ }
404
+
405
+ return { nodes, edges, sorted_plans, providers, missing_requires };
406
+ }
407
+
408
+ // ─── validateArtifactDAG ─────────────────────────────────────────────────────
409
+
410
+ /**
411
+ * Validate an ArtifactDAG for cycles, missing dependencies, unused provides, and duplicates.
412
+ *
413
+ * 1. Cycle detection via DFS: walks the requires/integration dependency graph, collecting
414
+ * all distinct cycles found (not just the first).
415
+ * 2. Missing dependency detection: for each plan's requires, checks if dag.providers has
416
+ * a matching entry.
417
+ * 3. Unused provides warning: for each artifact in providers, checks if any plan requires
418
+ * or integrates it.
419
+ * 4. Duplicate provides warning: when multiple plans declare the same provides entry.
420
+ *
421
+ * @param dag - The artifact DAG to validate
422
+ * @param plans - Original plan artifacts (for duplicate provides detection)
423
+ * @returns ArtifactDAGValidation with valid flag, cycles, missing_deps, and warnings
424
+ */
425
+ function validateArtifactDAG(dag: ArtifactDAG, plans: PlanArtifact[]): ArtifactDAGValidation {
426
+ const cycles: string[][] = [];
427
+ const missing_deps: Array<{ plan: string; artifact: string }> = [];
428
+ const warnings: string[] = [];
429
+
430
+ // Step 1: Cycle detection via DFS on the dependency graph
431
+ // Build adjacency: from_plan → [to_plan] (consumer → producer)
432
+ const cycleAdj = new Map<string, string[]>();
433
+ for (const node of dag.nodes) {
434
+ cycleAdj.set(node.id, []);
435
+ }
436
+ for (const edge of dag.edges) {
437
+ const neighbors = cycleAdj.get(edge.from_plan);
438
+ if (neighbors !== undefined) {
439
+ neighbors.push(edge.to_plan);
440
+ }
441
+ }
442
+
443
+ // DFS state: 0 = unvisited, 1 = visiting, 2 = visited
444
+ const state = new Map<string, number>();
445
+ for (const node of dag.nodes) {
446
+ state.set(node.id, 0);
447
+ }
448
+ const pathStack: string[] = [];
449
+ const seenCycles = new Set<string>();
450
+
451
+ function dfsCollect(nodeId: string): void {
452
+ state.set(nodeId, 1);
453
+ pathStack.push(nodeId);
454
+
455
+ for (const neighbor of (cycleAdj.get(nodeId) ?? [])) {
456
+ if (state.get(neighbor) === 1) {
457
+ // Found a back-edge — reconstruct and deduplicate the cycle
458
+ const cycleStart = pathStack.indexOf(neighbor);
459
+ const cyclePath = [...pathStack.slice(cycleStart), neighbor];
460
+ // Canonical form: rotate so lexicographically smallest node is first
461
+ const minIdx = cyclePath.slice(0, -1).reduce(
462
+ (best, id, idx) => (id < cyclePath[best] ? idx : best),
463
+ 0
464
+ );
465
+ const canonical = [
466
+ ...cyclePath.slice(minIdx, -1),
467
+ ...cyclePath.slice(0, minIdx),
468
+ cyclePath[minIdx],
469
+ ];
470
+ const key = canonical.join(',');
471
+ if (!seenCycles.has(key)) {
472
+ seenCycles.add(key);
473
+ cycles.push(canonical);
474
+ }
475
+ } else if (state.get(neighbor) === 0) {
476
+ dfsCollect(neighbor);
477
+ }
478
+ }
479
+
480
+ pathStack.pop();
481
+ state.set(nodeId, 2);
482
+ }
483
+
484
+ for (const node of dag.nodes) {
485
+ if (state.get(node.id) === 0) {
486
+ dfsCollect(node.id);
487
+ }
488
+ }
489
+
490
+ // Step 2: Missing dependency detection
491
+ for (const node of dag.nodes) {
492
+ for (const artifact of node.requires) {
493
+ if (!(artifact in dag.providers)) {
494
+ missing_deps.push({ plan: node.id, artifact });
495
+ }
496
+ }
497
+ }
498
+
499
+ // Step 3: Unused provides warning
500
+ // Collect all referenced artifacts across all plans
501
+ const referencedArtifacts = new Set<string>();
502
+ for (const node of dag.nodes) {
503
+ for (const a of node.requires) {
504
+ referencedArtifacts.add(a);
505
+ }
506
+ for (const a of node.integration_points) {
507
+ referencedArtifacts.add(a);
508
+ }
509
+ }
510
+ for (const artifact of Object.keys(dag.providers)) {
511
+ if (!referencedArtifacts.has(artifact)) {
512
+ warnings.push(`Unused provides: "${artifact}" (provided by ${dag.providers[artifact]}, not required by any plan)`);
513
+ }
514
+ }
515
+
516
+ // Step 4: Duplicate provides warning
517
+ const providerCount = new Map<string, string[]>(); // artifact → [plan_ids]
518
+ for (const plan of plans) {
519
+ const planId = `${plan.phase}-${String(plan.plan).padStart(2, '0')}`;
520
+ for (const artifact of plan.provides) {
521
+ const existing = providerCount.get(artifact);
522
+ if (existing !== undefined) {
523
+ existing.push(planId);
524
+ } else {
525
+ providerCount.set(artifact, [planId]);
526
+ }
527
+ }
528
+ }
529
+ for (const [artifact, planIds] of providerCount) {
530
+ if (planIds.length > 1) {
531
+ warnings.push(`Duplicate provides: "${artifact}" declared by ${planIds.join(', ')} (first provider wins)`);
532
+ }
533
+ }
534
+
535
+ return {
536
+ valid: cycles.length === 0 && missing_deps.length === 0,
537
+ cycles,
538
+ missing_deps,
539
+ warnings,
540
+ };
541
+ }
542
+
543
+ // ─── cmdPhaseDepsVisualize ───────────────────────────────────────────────────
544
+
545
+ /**
546
+ * Render a phase dependency graph as a Mermaid flowchart or ASCII tree.
547
+ *
548
+ * Reads ROADMAP.md for the project, builds the dependency graph using the same
549
+ * Kahn's algorithm as cmdPhaseAnalyzeDeps, then formats for human consumption.
550
+ *
551
+ * Mermaid format: valid `flowchart LR` block (paste into any Mermaid renderer).
552
+ * ASCII format: indented tree showing parallel groups.
553
+ *
554
+ * @param cwd - Project working directory
555
+ * @param opts - Options: milestone (override), format ('mermaid' | 'ascii')
556
+ * @param raw - Output raw text instead of JSON
557
+ */
558
+ function cmdPhaseDepsVisualize(
559
+ cwd: string,
560
+ opts: { milestone?: string | null; format?: string | null },
561
+ raw: boolean
562
+ ): void {
563
+ const roadmapResult = analyzeRoadmap(cwd) as {
564
+ error?: string;
565
+ phases?: PhaseInput[];
566
+ };
567
+
568
+ if (roadmapResult.error || !roadmapResult.phases || roadmapResult.phases.length === 0) {
569
+ output({ error: roadmapResult.error || 'ROADMAP.md not found or empty' }, raw);
570
+ return;
571
+ }
572
+
573
+ let phases = roadmapResult.phases;
574
+
575
+ // Apply milestone filter if specified (match phase names containing milestone string)
576
+ const milestoneFilter = opts.milestone;
577
+ if (milestoneFilter) {
578
+ phases = phases.filter(
579
+ (p) => p.name.toLowerCase().includes(milestoneFilter.toLowerCase()) ||
580
+ String(p.number).startsWith(milestoneFilter)
581
+ );
582
+ if (phases.length === 0) {
583
+ output({ error: `No phases found matching milestone "${milestoneFilter}"` }, raw);
584
+ return;
585
+ }
586
+ }
587
+
588
+ const graph: DependencyGraph = buildDependencyGraph(phases);
589
+ const cycle = detectCycle(graph);
590
+ const parallelGroups = computeParallelGroups(graph);
591
+ const format = opts.format || 'mermaid';
592
+
593
+ let diagram: string;
594
+
595
+ if (format === 'ascii') {
596
+ const lines: string[] = [`Phase Dependency Graph (${graph.nodes.length} phases, ${parallelGroups.length} groups)`];
597
+ lines.push('');
598
+ parallelGroups.forEach((group, i) => {
599
+ lines.push(`Group ${i + 1} [parallel]:`);
600
+ for (const id of group) {
601
+ const node = graph.nodes.find((n) => n.id === id);
602
+ const deps = graph.edges.filter((e) => e.to === id).map((e) => e.from);
603
+ const depStr = deps.length > 0 ? ` ← depends on: ${deps.join(', ')}` : '';
604
+ lines.push(` Phase ${id}: ${node?.name || ''}${depStr}`);
605
+ }
606
+ });
607
+ if (cycle) {
608
+ lines.push('');
609
+ lines.push(`⚠ Cycle detected: ${cycle.join(' → ')}`);
610
+ }
611
+ diagram = lines.join('\n');
612
+ } else {
613
+ // Mermaid flowchart LR
614
+ const lines: string[] = ['flowchart LR'];
615
+ for (const node of graph.nodes) {
616
+ const label = `Phase ${node.id}: ${node.name.replace(/"/g, "'")}`;
617
+ lines.push(` ${_mermaidId(node.id)}["${label}"]`);
618
+ }
619
+ for (const edge of graph.edges) {
620
+ lines.push(` ${_mermaidId(edge.from)} --> ${_mermaidId(edge.to)}`);
621
+ }
622
+ if (cycle) {
623
+ lines.push(` %% WARNING: cycle detected ${cycle.join(' -> ')}`);
624
+ }
625
+ diagram = lines.join('\n');
626
+ }
627
+
628
+ output(
629
+ {
630
+ format,
631
+ phase_count: graph.nodes.length,
632
+ group_count: parallelGroups.length,
633
+ has_cycle: Boolean(cycle),
634
+ cycle_path: cycle ?? null,
635
+ diagram,
636
+ },
637
+ raw,
638
+ diagram
639
+ );
640
+ }
641
+
642
+ /** Sanitize a phase ID for use as a Mermaid node identifier. */
643
+ function _mermaidId(id: string): string {
644
+ return `ph${id.replace(/\./g, '_')}`;
645
+ }
646
+
647
+ // ─── buildWaves ──────────────────────────────────────────────────────────────
648
+
649
+ interface PlanWaveEntry {
650
+ plan_file: string;
651
+ wave: number;
652
+ agent_type: string;
653
+ target_files: string[];
654
+ }
655
+
656
+ /**
657
+ * Read all *-PLAN.md files in phaseDir and group them by their `wave` frontmatter field.
658
+ * Returns an array of wave groups sorted by wave number, each group containing the plan entries.
659
+ * Plans without a wave field are assigned to wave 1.
660
+ *
661
+ * @param phaseDir - Path to the phase directory containing PLAN.md files
662
+ * @returns Array of wave groups: [{wave, plans: PlanWaveEntry[]}]
663
+ */
664
+ function buildWaves(phaseDir: string): { wave: number; plans: PlanWaveEntry[] }[] {
665
+ let files: string[];
666
+ try {
667
+ files = (fs.readdirSync(phaseDir) as string[]).filter(
668
+ (f: string) => f.endsWith('-PLAN.md') || f === 'PLAN.md'
669
+ ).sort();
670
+ } catch {
671
+ return [];
672
+ }
673
+
674
+ const waveMap = new Map<number, PlanWaveEntry[]>();
675
+
676
+ for (const file of files) {
677
+ const content = (() => {
678
+ try { return fs.readFileSync(path.join(phaseDir, file), 'utf-8') as string; } catch { return null; }
679
+ })();
680
+ if (!content) continue;
681
+
682
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
683
+ const fm = fmMatch ? fmMatch[1] : '';
684
+
685
+ const waveMatch = fm.match(/^wave:\s*(\d+)/m);
686
+ const waveNum = waveMatch ? parseInt(waveMatch[1], 10) : 1;
687
+
688
+ const agentMatch = fm.match(/^agent_type:\s*(.+)$/m);
689
+ const agentType = agentMatch ? agentMatch[1].trim() : 'grd-executor';
690
+
691
+ const filesMatch = fm.match(/^files_modified:\s*\[([^\]]*)\]/m);
692
+ const targetFiles = filesMatch
693
+ ? filesMatch[1].split(',').map((f: string) => f.trim()).filter(Boolean)
694
+ : [];
695
+
696
+ const entry: PlanWaveEntry = { plan_file: file, wave: waveNum, agent_type: agentType, target_files: targetFiles };
697
+ const bucket = waveMap.get(waveNum) ?? [];
698
+ bucket.push(entry);
699
+ waveMap.set(waveNum, bucket);
700
+ }
701
+
702
+ return Array.from(waveMap.entries())
703
+ .sort(([a], [b]) => a - b)
704
+ .map(([wave, plans]) => ({ wave, plans }));
705
+ }
706
+
707
+ // Effort-to-token band map for the dry-run preview.
708
+ const EFFORT_TOKEN_BANDS: Record<string, string> = {
709
+ high: '~200K tokens',
710
+ medium: '~80K tokens',
711
+ low: '~30K tokens',
712
+ };
713
+
714
+ /**
715
+ * CLI command: Dry-run preview of gd execute-phase <N>.
716
+ * Reads plan files, groups by wave, and prints a wave table without spawning agents.
717
+ *
718
+ * @param cwd - Project working directory
719
+ * @param phase - Phase number/name
720
+ * @param raw - Output raw text instead of JSON
721
+ */
722
+ function cmdExecutePhaseDryRun(cwd: string, phase: string, raw: boolean): void {
723
+ const phaseInfo = findPhaseInternal(cwd, phase);
724
+ if (!phaseInfo || !phaseInfo.found) {
725
+ _depsError(`Phase ${phase} not found`);
726
+ }
727
+
728
+ const waves = buildWaves(path.join(cwd, (phaseInfo as import('./types').PhaseInfo).directory));
729
+ if (waves.length === 0) {
730
+ output({ dry_run: true, wave_count: 0, waves: [] }, raw, 'No plan files found in phase directory');
731
+ return;
732
+ }
733
+
734
+ const rows = waves.map(({ wave, plans }) => ({
735
+ wave,
736
+ agent_count: plans.length,
737
+ agents: plans.map((p) => ({
738
+ plan_file: p.plan_file,
739
+ agent_type: p.agent_type,
740
+ estimated_tokens: EFFORT_TOKEN_BANDS['medium'],
741
+ target_files: p.target_files,
742
+ })),
743
+ }));
744
+
745
+ if (raw) {
746
+ const lines: string[] = [`Dry-run: Phase ${phase} — ${waves.length} wave(s), ${waves.reduce((s, w) => s + w.plans.length, 0)} plan(s)\n`];
747
+ for (const row of rows) {
748
+ lines.push(`Wave ${row.wave} (${row.agent_count} agent${row.agent_count !== 1 ? 's' : ''}):`);
749
+ for (const a of row.agents) {
750
+ const files = a.target_files.length > 0 ? ` → ${a.target_files.join(', ')}` : '';
751
+ lines.push(` ${a.plan_file} [${a.agent_type}] ${a.estimated_tokens}${files}`);
752
+ }
753
+ }
754
+ output({ dry_run: true, wave_count: waves.length, waves: rows }, raw, lines.join('\n'));
755
+ } else {
756
+ output({ dry_run: true, phase, wave_count: waves.length, waves: rows }, raw, `${waves.length} waves, ${waves.reduce((s, w) => s + w.plans.length, 0)} plans`);
757
+ }
758
+ }
759
+
760
+ // ─── Exports ─────────────────────────────────────────────────────────────────
761
+
762
+ module.exports = {
763
+ parseDependsOn,
764
+ buildDependencyGraph,
765
+ computeParallelGroups,
766
+ detectCycle,
767
+ cmdPhaseAnalyzeDeps,
768
+ cmdPhaseDepsVisualize,
769
+ buildArtifactDAG,
770
+ validateArtifactDAG,
771
+ buildWaves,
772
+ cmdExecutePhaseDryRun,
773
+ };