@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
@@ -0,0 +1,1153 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+ const { safeReadFile, execGit, findPhaseInternal, validateGitRef, output, error, } = require('./utils');
7
+ const { extractFrontmatter, parseMustHavesBlock, } = require('./frontmatter');
8
+ // Module-level cache for file reads within a single process invocation.
9
+ // Safe for verify functions since they never write files.
10
+ const _fileReadCache = new Map();
11
+ function readFileCached(fullPath) {
12
+ if (!_fileReadCache.has(fullPath)) {
13
+ _fileReadCache.set(fullPath, safeReadFile(fullPath));
14
+ }
15
+ return _fileReadCache.get(fullPath);
16
+ }
17
+ /** Clear the module-level file read cache. Call in test beforeEach to prevent stale reads across tests. */
18
+ function clearVerifyCache() {
19
+ _fileReadCache.clear();
20
+ }
21
+ // ─── Verification Command Functions ──────────────────────────────────────────
22
+ /**
23
+ * CLI command: Verify SUMMARY.md structure including file existence, commit hashes, and self-check.
24
+ * @param cwd - Project working directory
25
+ * @param summaryPath - Relative path to the SUMMARY.md file
26
+ * @param checkFileCount - Number of mentioned files to spot-check for existence
27
+ * @param raw - Output raw 'passed'/'failed' instead of JSON
28
+ */
29
+ function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
30
+ if (!summaryPath) {
31
+ error('summary-path required');
32
+ }
33
+ const fullPath = path.join(cwd, summaryPath);
34
+ const checkCount = checkFileCount || 2;
35
+ // Check 1: Summary exists
36
+ let content;
37
+ try {
38
+ content = fs.readFileSync(fullPath, 'utf-8');
39
+ }
40
+ catch {
41
+ const result = {
42
+ passed: false,
43
+ checks: {
44
+ summary_exists: false,
45
+ files_created: { checked: 0, found: 0, missing: [] },
46
+ commits_exist: false,
47
+ self_check: 'not_found',
48
+ },
49
+ errors: ['SUMMARY.md not found'],
50
+ };
51
+ output(result, raw, 'failed');
52
+ return;
53
+ }
54
+ const errors = [];
55
+ // Check 2: Spot-check files mentioned in summary
56
+ const mentionedFiles = new Set();
57
+ const patterns = [
58
+ /`([^`]+\.[a-zA-Z]+)`/g,
59
+ /(?:Created|Modified|Added|Updated|Edited):\s*`?([^\s`]+\.[a-zA-Z]+)`?/gi,
60
+ ];
61
+ for (const pattern of patterns) {
62
+ let m;
63
+ while ((m = pattern.exec(content)) !== null) {
64
+ const filePath = m[1];
65
+ if (filePath && !filePath.startsWith('http') && filePath.includes('/')) {
66
+ mentionedFiles.add(filePath);
67
+ }
68
+ }
69
+ }
70
+ const filesToCheck = Array.from(mentionedFiles).slice(0, checkCount);
71
+ const missing = [];
72
+ for (const file of filesToCheck) {
73
+ if (!fs.existsSync(path.join(cwd, file))) {
74
+ missing.push(file);
75
+ }
76
+ }
77
+ // Check 3: Commits exist. Codex r15 P2: every referenced commit must
78
+ // exist (was sampling 3 and passing if any one resolved). Check the
79
+ // first ~10 unique hashes to keep the cost bounded but catch
80
+ // partial-failure cases.
81
+ // Codex r27 P2: a context-free hex-token regex also matches
82
+ // checksums, cache keys, content-hash IDs, and other non-commit
83
+ // hex strings. Anchor on explicit commit labels first (commit:,
84
+ // SHA:, ref:, hash:, parent:, `**Commit**`, hyperlinks to
85
+ // /commit/<sha>, conventional `(abcdef1)` parens), and only fall
86
+ // back to the bare hex scan if the labelled set is empty AND the
87
+ // SUMMARY explicitly mentions "commit" somewhere (so we keep the
88
+ // backward-compatible behaviour without false-failing on summaries
89
+ // that legitimately reference no commits).
90
+ // Codex r28 P2: a labelled `Commits: <a>, <b>, <c>` list contains
91
+ // multiple hashes. Capture the full label line (up to newline or
92
+ // next section) and pull every hex token from it, instead of only
93
+ // matching one hash per label.
94
+ // Codex r30 P2: only collect hex tokens that appear in commit
95
+ // contexts. Three kinds of context count:
96
+ // 1. Labelled lines: `Commit: <sha>`, `SHA: <sha>`, etc., and
97
+ // multi-hash lists like `Commits: <a>, <b>`. The line itself
98
+ // is the context; harvest every hex token on it.
99
+ // 2. /commit/<sha> hyperlinks.
100
+ // 3. A commits-block heading (`## (Task )?Commits`, `### Commits`,
101
+ // `# Commits`) — harvest every hex token in lines until the
102
+ // next heading at the same or shallower level, or the next
103
+ // blank line followed by a non-list line.
104
+ // Bare `(deadbeef)` parens and the prior whole-document scan are
105
+ // dropped — they re-introduced the false positives r27 was trying
106
+ // to fix.
107
+ const labelledHashes = [];
108
+ // Codex r32 P2: accept bold/bulleted label forms documented in
109
+ // agents/grd-executor.md, e.g.:
110
+ // - **Commits:** abc, def
111
+ // **Commits:**
112
+ // - abc
113
+ // Match the *label line* generically, then if it's a bare label
114
+ // (no hash on the same line) sweep subsequent bullet rows.
115
+ const linesAll = content.split('\n');
116
+ for (let i = 0; i < linesAll.length; i++) {
117
+ const line = linesAll[i];
118
+ // Codex r34 P2: also accept colonless forms used in real
119
+ // SUMMARYs:
120
+ // - `Commit 29c6883 exists` (label + space + hash)
121
+ // - `### Task 1 ... (29c6883)` (paren-suffix on a
122
+ // heading/task line)
123
+ // - `- [x] Task X completed (abc1234)` (paren-suffix on a
124
+ // checklist line)
125
+ const isColonLabel = /(?:[-*]\s+|^|\*\*)\s*(?:commit|sha|ref|hash|parent)s?\s*[:*]/i.test(line);
126
+ // Codex r38 P2: colonless `Commits a, b, c` should capture every
127
+ // hash on the line, not just the first. Detect the colonless
128
+ // label and then harvest *all* hex tokens from the line.
129
+ // Codex r39 P2: also accept backticked hashes after a colonless
130
+ // label, e.g. `- [x] Commit \`8880489\` exists`. Allow optional
131
+ // backticks between the label and the hash.
132
+ const hasColonlessLabel = /\b(?:commit|sha|ref|hash|parent)s?\s+`?[0-9a-f]{7,40}`?\b/i.test(line);
133
+ const colonlessHashes = hasColonlessLabel
134
+ ? line.match(/\b[0-9a-f]{7,40}\b/gi) ?? []
135
+ : [];
136
+ // Codex r35 P2: paren-suffix `(<sha>)` is ambiguous — it's also
137
+ // used for checksums/artifact IDs. Require the line itself to
138
+ // mention something commit-flavored OR be a task-completion
139
+ // checklist marker (`- [x]`). Plain headings like
140
+ // `### Artifact checksum (deadbeef)` are no longer matched.
141
+ const isCheckedTask = /^\s*[-*]\s+\[x\]\s+/i.test(line);
142
+ const lineHasCommitWord = /\b(?:commit|merge|landed|shipped)\b/i.test(line);
143
+ // Codex r41 P2: also accept task-heading paren suffixes such as
144
+ // `### Task 1: add parser (deadbee)`. The heading-with-"Task"
145
+ // signal disambiguates from `### Artifact checksum (deadbeef)`.
146
+ const isTaskHeading = /^#{1,6}\s+(?:Task|Step|Plan|Phase|Subtask)\b/i.test(line);
147
+ const parenSuffixMatch = (isCheckedTask || lineHasCommitWord || isTaskHeading)
148
+ ? line.match(/\(([0-9a-f]{7,40})\)\s*$/i)
149
+ : null;
150
+ for (const h of colonlessHashes) {
151
+ labelledHashes.push(h.toLowerCase());
152
+ }
153
+ if (parenSuffixMatch) {
154
+ labelledHashes.push(parenSuffixMatch[1].toLowerCase());
155
+ }
156
+ if (!isColonLabel) {
157
+ continue;
158
+ }
159
+ // Codex r36 P2: use word boundaries so a SHA-256 artifact hash
160
+ // (64 hex chars) isn't truncated to its first 40 and treated as
161
+ // a commit. Boundary-aware match is consistent with the table
162
+ // and block scanners below.
163
+ const hashesOnLine = line.match(/\b[0-9a-f]{7,40}\b/gi) ?? [];
164
+ if (hashesOnLine.length > 0) {
165
+ for (const h of hashesOnLine)
166
+ labelledHashes.push(h.toLowerCase());
167
+ continue;
168
+ }
169
+ // Bare label — sweep following bullet lines until indent drops
170
+ // back or a non-bullet line appears.
171
+ for (let j = i + 1; j < linesAll.length; j++) {
172
+ const row = linesAll[j];
173
+ if (/^\s*$/.test(row))
174
+ continue;
175
+ if (!/^\s*[-*]\s+/.test(row))
176
+ break;
177
+ for (const h of row.match(/\b[0-9a-f]{7,40}\b/gi) ?? []) {
178
+ labelledHashes.push(h.toLowerCase());
179
+ }
180
+ }
181
+ }
182
+ for (const m of content.matchAll(/\/commit\/([0-9a-f]{7,40})\b/gi)) {
183
+ labelledHashes.push(m[1].toLowerCase());
184
+ }
185
+ // Codex r35 P2: a `## Commits` section can contain nested `### Task N`
186
+ // subheadings with the actual hashes. The prior pattern stopped at
187
+ // any heading of any depth, missing those. Walk lines explicitly:
188
+ // when we hit a `## Commits` heading at depth D, harvest hashes
189
+ // from following lines until we see a heading at depth ≤ D
190
+ // (siblings or shallower).
191
+ const headingRe = /^(#{1,6})\s+(?:Task\s+)?Commits?\s*$/i;
192
+ for (let i = 0; i < linesAll.length; i++) {
193
+ const headingMatch = linesAll[i].match(headingRe);
194
+ if (!headingMatch)
195
+ continue;
196
+ const depth = headingMatch[1].length;
197
+ for (let j = i + 1; j < linesAll.length; j++) {
198
+ const nextHeading = linesAll[j].match(/^(#{1,6})\s+/);
199
+ if (nextHeading && nextHeading[1].length <= depth)
200
+ break;
201
+ for (const h of linesAll[j].match(/\b[0-9a-f]{7,40}\b/gi) ?? []) {
202
+ labelledHashes.push(h.toLowerCase());
203
+ }
204
+ }
205
+ }
206
+ // Codex r31 P2 / r33 P2: markdown tables with a `Commit` column
207
+ // header. Find the commit-column INDEX from the header row, then
208
+ // only harvest hex tokens from that specific cell in each row —
209
+ // otherwise a `| task | commit | checksum |` table would also try
210
+ // to validate the unrelated `checksum` column against git.
211
+ const lines = content.split('\n');
212
+ // Codex r37 P2: only drop the trailing-pipe artifact when one
213
+ // actually exists. Otherwise tables without a trailing `|`
214
+ // (`| Task | Commit` / `| 1 | deadbeef`) lose their last real
215
+ // cell — the Commit column — and the scanner misses every hash.
216
+ const splitCells = (s) => {
217
+ const trimmed = s.trimEnd();
218
+ const hasTrailingPipe = trimmed.endsWith('|');
219
+ const cells = trimmed.split('|').map((c) => c.trim());
220
+ cells.shift(); // drop leading empty before first `|`
221
+ if (hasTrailingPipe)
222
+ cells.pop();
223
+ return cells;
224
+ };
225
+ for (let i = 0; i < lines.length; i++) {
226
+ // Codex r40 P2: trim leading whitespace before checking for table
227
+ // start — indented tables (inside a list or quoted block) also
228
+ // need their commit column scanned.
229
+ const line = lines[i].trimStart();
230
+ if (!line.startsWith('|') ||
231
+ !/\bcommit\b/i.test(line) ||
232
+ !lines[i + 1]?.match(/^\s*\|?\s*[-:]+/)) {
233
+ continue;
234
+ }
235
+ const headerCells = splitCells(line);
236
+ const commitColIdx = headerCells.findIndex((c) => /\bcommit\b/i.test(c));
237
+ if (commitColIdx === -1)
238
+ continue;
239
+ for (let j = i + 2; j < lines.length; j++) {
240
+ const row = lines[j].trimStart();
241
+ if (!row.startsWith('|'))
242
+ break;
243
+ const rowCells = splitCells(row);
244
+ const cell = rowCells[commitColIdx] ?? '';
245
+ for (const h of cell.match(/\b[0-9a-f]{7,40}\b/gi) ?? []) {
246
+ labelledHashes.push(h.toLowerCase());
247
+ }
248
+ }
249
+ }
250
+ const hashes = Array.from(new Set(labelledHashes));
251
+ let commitsExist = false;
252
+ const invalidHashes = [];
253
+ if (hashes.length > 0) {
254
+ const uniqueHashes = Array.from(new Set(hashes)).slice(0, 10);
255
+ let allValid = true;
256
+ for (const hash of uniqueHashes) {
257
+ try {
258
+ validateGitRef(hash);
259
+ }
260
+ catch {
261
+ allValid = false;
262
+ invalidHashes.push(hash);
263
+ continue;
264
+ }
265
+ const result = execGit(cwd, ['cat-file', '-t', hash]);
266
+ if (!(result.exitCode === 0 && result.stdout === 'commit')) {
267
+ allValid = false;
268
+ invalidHashes.push(hash);
269
+ }
270
+ }
271
+ commitsExist = allValid;
272
+ }
273
+ // Check 4: Self-check section
274
+ let selfCheck = 'not_found';
275
+ const selfCheckPattern = /##\s*(?:Self[- ]?Check|Verification|Quality Check)/i;
276
+ if (selfCheckPattern.test(content)) {
277
+ const passPattern = /(?:all\s+)?(?:pass|✓|✅|complete|succeeded)/i;
278
+ const failPattern = /(?:fail|✗|❌|incomplete|blocked)/i;
279
+ const checkSection = content.slice(content.search(selfCheckPattern));
280
+ if (failPattern.test(checkSection)) {
281
+ selfCheck = 'failed';
282
+ }
283
+ else if (passPattern.test(checkSection)) {
284
+ selfCheck = 'passed';
285
+ }
286
+ }
287
+ if (missing.length > 0)
288
+ errors.push('Missing files: ' + missing.join(', '));
289
+ if (!commitsExist && hashes.length > 0)
290
+ errors.push(invalidHashes.length > 0
291
+ ? `Referenced commit hashes not found in git history: ${invalidHashes.join(', ')}`
292
+ : 'Referenced commit hashes not found in git history');
293
+ if (selfCheck === 'failed')
294
+ errors.push('Self-check section indicates failure');
295
+ const checks = {
296
+ summary_exists: true,
297
+ files_created: {
298
+ checked: filesToCheck.length,
299
+ found: filesToCheck.length - missing.length,
300
+ missing,
301
+ },
302
+ commits_exist: commitsExist,
303
+ self_check: selfCheck,
304
+ };
305
+ const passed = missing.length === 0 && selfCheck !== 'failed' && (commitsExist || hashes.length === 0);
306
+ const result = { passed, checks, errors };
307
+ output(result, raw, passed ? 'passed' : 'failed');
308
+ }
309
+ /**
310
+ * CLI command: Verify PLAN.md structure, frontmatter fields, and task element completeness.
311
+ * @param cwd - Project working directory
312
+ * @param filePath - Path to the PLAN.md file to validate
313
+ * @param raw - Output raw 'valid'/'invalid' instead of JSON
314
+ */
315
+ function cmdVerifyPlanStructure(cwd, filePath, raw) {
316
+ if (!filePath) {
317
+ error('file path required');
318
+ }
319
+ const fullPath = path.isAbsolute(filePath) ? filePath : path.join(cwd, filePath);
320
+ const content = readFileCached(fullPath);
321
+ if (!content) {
322
+ output({ error: 'File not found', path: filePath }, raw);
323
+ return;
324
+ }
325
+ const fm = extractFrontmatter(content);
326
+ const errors = [];
327
+ const warnings = [];
328
+ // Check required frontmatter fields
329
+ const required = [
330
+ 'phase',
331
+ 'plan',
332
+ 'type',
333
+ 'wave',
334
+ 'depends_on',
335
+ 'files_modified',
336
+ 'autonomous',
337
+ 'must_haves',
338
+ ];
339
+ const missingFields = [];
340
+ for (const field of required) {
341
+ if (fm[field] === undefined) {
342
+ errors.push(`Missing required frontmatter field: ${field}`);
343
+ missingFields.push(field);
344
+ }
345
+ }
346
+ // Include found frontmatter fields context when fields are missing
347
+ if (missingFields.length > 0) {
348
+ const foundFields = Object.keys(fm);
349
+ if (foundFields.length > 0) {
350
+ errors.push(`Found frontmatter fields: ${foundFields.join(', ')}`);
351
+ }
352
+ }
353
+ // Parse and check task elements
354
+ const taskPattern = /<task[^>]*>([\s\S]*?)<\/task>/g;
355
+ const tasks = [];
356
+ let taskMatch;
357
+ while ((taskMatch = taskPattern.exec(content)) !== null) {
358
+ const taskContent = taskMatch[1];
359
+ const nameMatch = taskContent.match(/<name>([\s\S]*?)<\/name>/);
360
+ const taskName = nameMatch ? nameMatch[1].trim() : 'unnamed';
361
+ const hasFiles = /<files>/.test(taskContent);
362
+ const hasAction = /<action>/.test(taskContent);
363
+ const hasVerify = /<verify>/.test(taskContent);
364
+ const hasDone = /<done>/.test(taskContent);
365
+ if (!nameMatch)
366
+ errors.push('Task missing <name> element');
367
+ if (!hasAction)
368
+ errors.push(`Task '${taskName}' missing <action>`);
369
+ if (!hasVerify)
370
+ warnings.push(`Task '${taskName}' missing <verify>`);
371
+ if (!hasDone)
372
+ warnings.push(`Task '${taskName}' missing <done>`);
373
+ if (!hasFiles)
374
+ warnings.push(`Task '${taskName}' missing <files>`);
375
+ tasks.push({ name: taskName, hasFiles, hasAction, hasVerify, hasDone });
376
+ }
377
+ if (tasks.length === 0)
378
+ warnings.push('No <task> elements found');
379
+ // Wave/depends_on consistency
380
+ if (fm.wave &&
381
+ parseInt(String(fm.wave)) > 1 &&
382
+ (!fm.depends_on || (Array.isArray(fm.depends_on) && fm.depends_on.length === 0))) {
383
+ warnings.push('Wave > 1 but depends_on is empty');
384
+ }
385
+ // Autonomous/checkpoint consistency
386
+ const hasCheckpoints = /<task\s+type=["']?checkpoint/.test(content);
387
+ // fm.autonomous may arrive as boolean or string from YAML parsing -- check both
388
+ const autonomousVal = fm.autonomous;
389
+ if (hasCheckpoints && autonomousVal !== 'false' && autonomousVal !== false) {
390
+ errors.push('Has checkpoint tasks but autonomous is not false');
391
+ }
392
+ // Extract markdown headings for found_sections
393
+ const headingPattern = /^#{1,6}\s+.+$/gm;
394
+ const found_sections = (content.match(headingPattern) || []).map((h) => h.trim());
395
+ const result = {
396
+ valid: errors.length === 0,
397
+ errors,
398
+ warnings,
399
+ task_count: tasks.length,
400
+ tasks,
401
+ frontmatter_fields: Object.keys(fm),
402
+ found_sections,
403
+ };
404
+ output(result, raw, errors.length === 0 ? 'valid' : 'invalid');
405
+ }
406
+ /**
407
+ * CLI command: Check that all plans in a phase have corresponding summaries.
408
+ * @param cwd - Project working directory
409
+ * @param phase - Phase number to check
410
+ * @param raw - Output raw 'complete'/'incomplete' instead of JSON
411
+ */
412
+ function cmdVerifyPhaseCompleteness(cwd, phase, raw) {
413
+ if (!phase) {
414
+ error('phase required');
415
+ }
416
+ const phaseInfo = findPhaseInternal(cwd, phase);
417
+ if (!phaseInfo || !phaseInfo.found) {
418
+ output({ error: 'Phase not found', phase }, raw);
419
+ return;
420
+ }
421
+ const errors = [];
422
+ const warnings = [];
423
+ const phaseDir = path.join(cwd, phaseInfo.directory);
424
+ // List plans and summaries
425
+ let files;
426
+ try {
427
+ files = fs.readdirSync(phaseDir);
428
+ }
429
+ catch {
430
+ output({ error: 'Cannot read phase directory' }, raw);
431
+ return;
432
+ }
433
+ const plans = files.filter((f) => f.match(/-PLAN\.md$/i));
434
+ const summaries = files.filter((f) => f.match(/-SUMMARY\.md$/i));
435
+ // Extract plan IDs (everything before -PLAN.md)
436
+ const planIds = new Set(plans.map((p) => p.replace(/-PLAN\.md$/i, '')));
437
+ const summaryIds = new Set(summaries.map((s) => s.replace(/-SUMMARY\.md$/i, '')));
438
+ // Plans without summaries
439
+ const incompletePlans = [...planIds].filter((id) => !summaryIds.has(id));
440
+ if (incompletePlans.length > 0) {
441
+ errors.push(`Plans without summaries: ${incompletePlans.join(', ')}`);
442
+ }
443
+ // Summaries without plans (orphans)
444
+ const orphanSummaries = [...summaryIds].filter((id) => !planIds.has(id));
445
+ if (orphanSummaries.length > 0) {
446
+ warnings.push(`Summaries without plans: ${orphanSummaries.join(', ')}`);
447
+ }
448
+ const result = {
449
+ complete: errors.length === 0,
450
+ phase: phaseInfo.phase_number,
451
+ plan_count: plans.length,
452
+ summary_count: summaries.length,
453
+ incomplete_plans: incompletePlans,
454
+ orphan_summaries: orphanSummaries,
455
+ errors,
456
+ warnings,
457
+ };
458
+ output(result, raw, errors.length === 0 ? 'complete' : 'incomplete');
459
+ }
460
+ /**
461
+ * CLI command: Validate @-references and backtick file paths in a markdown file.
462
+ * @param cwd - Project working directory
463
+ * @param filePath - Path to the markdown file to check
464
+ * @param raw - Output raw 'valid'/'invalid' instead of JSON
465
+ */
466
+ function cmdVerifyReferences(cwd, filePath, raw) {
467
+ if (!filePath) {
468
+ error('file path required');
469
+ }
470
+ const fullPath = path.isAbsolute(filePath) ? filePath : path.join(cwd, filePath);
471
+ const content = readFileCached(fullPath);
472
+ if (!content) {
473
+ output({ error: 'File not found', path: filePath }, raw);
474
+ return;
475
+ }
476
+ const found = [];
477
+ const missing = [];
478
+ // Find @-references: @path/to/file (must contain / to be a file path)
479
+ const atRefs = content.match(/@([^\s\n,)]+\/[^\s\n,)]+)/g) || [];
480
+ for (const ref of atRefs) {
481
+ const cleanRef = ref.slice(1); // remove @
482
+ // Skip templated/dynamic refs (e.g. @${CLAUDE_PLUGIN_ROOT}/...) — same
483
+ // guard used by the backtick-ref branch below.
484
+ if (cleanRef.includes('${') || cleanRef.includes('{{'))
485
+ continue;
486
+ const resolved = cleanRef.startsWith('~/')
487
+ ? path.join(process.env.HOME || os.homedir() || '', cleanRef.slice(2))
488
+ : path.join(cwd, cleanRef);
489
+ if (fs.existsSync(resolved)) {
490
+ found.push(cleanRef);
491
+ }
492
+ else {
493
+ missing.push(cleanRef);
494
+ }
495
+ }
496
+ // Find backtick file paths that look like real paths (contain / and have extension)
497
+ const backtickRefs = content.match(/`([^`]+\/[^`]+\.[a-zA-Z]{1,10})`/g) || [];
498
+ for (const ref of backtickRefs) {
499
+ const cleanRef = ref.slice(1, -1); // remove backticks
500
+ if (cleanRef.startsWith('http') || cleanRef.includes('${') || cleanRef.includes('{{'))
501
+ continue;
502
+ if (found.includes(cleanRef) || missing.includes(cleanRef))
503
+ continue; // dedup
504
+ const resolved = path.join(cwd, cleanRef);
505
+ if (fs.existsSync(resolved)) {
506
+ found.push(cleanRef);
507
+ }
508
+ else {
509
+ missing.push(cleanRef);
510
+ }
511
+ }
512
+ const result = {
513
+ valid: missing.length === 0,
514
+ found: found.length,
515
+ missing,
516
+ total: found.length + missing.length,
517
+ };
518
+ output(result, raw, missing.length === 0 ? 'valid' : 'invalid');
519
+ }
520
+ /**
521
+ * CLI command: Batch verify that git commit hashes exist in the repository.
522
+ * @param cwd - Project working directory
523
+ * @param hashes - Array of commit hashes to verify
524
+ * @param raw - Output raw 'valid'/'invalid' instead of JSON
525
+ */
526
+ function cmdVerifyCommits(cwd, hashes, raw) {
527
+ if (!hashes || hashes.length === 0) {
528
+ error('At least one commit hash required. Usage: verify commits <hash1> [hash2 ...]. Run "git log --oneline" to find commit hashes');
529
+ }
530
+ const valid = [];
531
+ const invalid = [];
532
+ for (const hash of hashes) {
533
+ try {
534
+ validateGitRef(hash);
535
+ }
536
+ catch {
537
+ invalid.push(hash);
538
+ continue;
539
+ }
540
+ const result = execGit(cwd, ['cat-file', '-t', hash]);
541
+ if (result.exitCode === 0 && result.stdout.trim() === 'commit') {
542
+ valid.push(hash);
543
+ }
544
+ else {
545
+ invalid.push(hash);
546
+ }
547
+ }
548
+ const verifyResult = {
549
+ all_valid: invalid.length === 0,
550
+ valid,
551
+ invalid,
552
+ total: hashes.length,
553
+ };
554
+ output(verifyResult, raw, invalid.length === 0 ? 'valid' : 'invalid');
555
+ }
556
+ /**
557
+ * CLI command: Check that must_haves.artifacts from a plan exist on disk with required content.
558
+ * @param cwd - Project working directory
559
+ * @param planFilePath - Path to the PLAN.md file containing must_haves.artifacts
560
+ * @param raw - Output raw 'valid'/'invalid' instead of JSON
561
+ */
562
+ function cmdVerifyArtifacts(cwd, planFilePath, raw) {
563
+ if (!planFilePath) {
564
+ error('plan file path required');
565
+ }
566
+ const fullPath = path.isAbsolute(planFilePath)
567
+ ? planFilePath
568
+ : path.join(cwd, planFilePath);
569
+ const content = readFileCached(fullPath);
570
+ if (!content) {
571
+ output({ error: 'File not found', path: planFilePath }, raw);
572
+ return;
573
+ }
574
+ const artifacts = parseMustHavesBlock(content, 'artifacts');
575
+ if (artifacts.length === 0) {
576
+ output({ error: 'No must_haves.artifacts found in frontmatter', path: planFilePath }, raw);
577
+ return;
578
+ }
579
+ const results = [];
580
+ for (const artifact of artifacts) {
581
+ if (typeof artifact === 'string')
582
+ continue; // skip simple string items
583
+ const artPath = artifact.path;
584
+ if (!artPath)
585
+ continue;
586
+ const artFullPath = path.join(cwd, artPath);
587
+ const exists = fs.existsSync(artFullPath);
588
+ const check = {
589
+ path: artPath,
590
+ exists,
591
+ issues: [],
592
+ passed: false,
593
+ plan_file: planFilePath,
594
+ must_haves_field: 'must_haves.artifacts',
595
+ };
596
+ if (exists) {
597
+ const fileContent = safeReadFile(artFullPath) || '';
598
+ const lineCount = fileContent.split('\n').length;
599
+ const artTyped = artifact;
600
+ if (artTyped.min_lines && lineCount < artTyped.min_lines) {
601
+ check.issues.push(`Only ${lineCount} lines, need ${artTyped.min_lines}`);
602
+ }
603
+ if (artTyped.contains && !fileContent.includes(artTyped.contains)) {
604
+ check.issues.push(`Missing pattern: ${artTyped.contains}`);
605
+ }
606
+ if (artTyped.exports) {
607
+ const exports = Array.isArray(artTyped.exports)
608
+ ? artTyped.exports
609
+ : [artTyped.exports];
610
+ for (const exp of exports) {
611
+ if (!fileContent.includes(exp))
612
+ check.issues.push(`Missing export: ${exp}`);
613
+ }
614
+ }
615
+ check.passed = check.issues.length === 0;
616
+ }
617
+ else {
618
+ check.issues.push('File not found');
619
+ check.remediation = `Create the missing file at: ${artPath}`;
620
+ }
621
+ results.push(check);
622
+ }
623
+ const passed = results.filter((r) => r.passed).length;
624
+ const verifyResult = {
625
+ all_passed: passed === results.length,
626
+ passed,
627
+ total: results.length,
628
+ artifacts: results,
629
+ };
630
+ output(verifyResult, raw, passed === results.length ? 'valid' : 'invalid');
631
+ }
632
+ /**
633
+ * CLI command: Validate must_haves.key_links patterns between source and target files.
634
+ * @param cwd - Project working directory
635
+ * @param planFilePath - Path to the PLAN.md file containing must_haves.key_links
636
+ * @param raw - Output raw 'valid'/'invalid' instead of JSON
637
+ */
638
+ function cmdVerifyKeyLinks(cwd, planFilePath, raw) {
639
+ if (!planFilePath) {
640
+ error('plan file path required');
641
+ }
642
+ const fullPath = path.isAbsolute(planFilePath)
643
+ ? planFilePath
644
+ : path.join(cwd, planFilePath);
645
+ const content = readFileCached(fullPath);
646
+ if (!content) {
647
+ output({ error: 'File not found', path: planFilePath }, raw);
648
+ return;
649
+ }
650
+ const keyLinks = parseMustHavesBlock(content, 'key_links');
651
+ if (keyLinks.length === 0) {
652
+ output({ error: 'No must_haves.key_links found in frontmatter', path: planFilePath }, raw);
653
+ return;
654
+ }
655
+ const results = [];
656
+ for (const link of keyLinks) {
657
+ if (typeof link === 'string')
658
+ continue;
659
+ const linkTyped = link;
660
+ const check = {
661
+ from: linkTyped.from,
662
+ to: linkTyped.to,
663
+ via: linkTyped.via || '',
664
+ verified: false,
665
+ detail: '',
666
+ };
667
+ const sourceContent = safeReadFile(path.join(cwd, linkTyped.from || ''));
668
+ if (!sourceContent) {
669
+ check.detail = 'Source file not found';
670
+ }
671
+ else if (linkTyped.pattern) {
672
+ try {
673
+ const regex = new RegExp(linkTyped.pattern);
674
+ if (regex.test(sourceContent)) {
675
+ check.verified = true;
676
+ check.detail = 'Pattern found in source';
677
+ }
678
+ else {
679
+ const targetContent = safeReadFile(path.join(cwd, linkTyped.to || ''));
680
+ if (targetContent && regex.test(targetContent)) {
681
+ check.verified = true;
682
+ check.detail = 'Pattern found in target';
683
+ }
684
+ else {
685
+ check.detail = `Pattern "${linkTyped.pattern}" not found in source or target`;
686
+ }
687
+ }
688
+ }
689
+ catch {
690
+ check.detail = `Invalid regex pattern: ${linkTyped.pattern}`;
691
+ }
692
+ }
693
+ else {
694
+ // No pattern: just check source references target
695
+ if (sourceContent.includes(linkTyped.to || '')) {
696
+ check.verified = true;
697
+ check.detail = 'Target referenced in source';
698
+ }
699
+ else {
700
+ check.detail = 'Target not referenced in source';
701
+ }
702
+ }
703
+ results.push(check);
704
+ }
705
+ const verified = results.filter((r) => r.verified).length;
706
+ const verifyResult = {
707
+ all_verified: verified === results.length,
708
+ verified,
709
+ total: results.length,
710
+ links: results,
711
+ };
712
+ output(verifyResult, raw, verified === results.length ? 'valid' : 'invalid');
713
+ }
714
+ /**
715
+ * Bundle the four PLAN.md mechanical checks (frontmatter, artifacts,
716
+ * key_links, references) plus a phase-level plan/summary completeness
717
+ * check into a single aggregated JSON result. Reuses the same helpers
718
+ * as the discrete verify commands so behavior stays consistent.
719
+ *
720
+ * Required PLAN.md frontmatter fields are kept in sync with
721
+ * cmdVerifyPlanStructure. Frontmatter check passes if all required
722
+ * fields are present; artifact and key-link checks pass when every
723
+ * declared item resolves; reference check passes when every @-reference
724
+ * and backtick path resolves; completeness check passes when every
725
+ * PLAN has a matching SUMMARY.
726
+ *
727
+ * @param cwd - Project working directory
728
+ * @param phase - Phase number or name passed to findPhaseInternal
729
+ * @param raw - Output 'pass'/'fail' instead of JSON
730
+ */
731
+ function cmdVerifyMechanical(cwd, phase, raw) {
732
+ if (!phase) {
733
+ error('phase required');
734
+ }
735
+ const phaseInfo = findPhaseInternal(cwd, phase);
736
+ if (!phaseInfo || !phaseInfo.found) {
737
+ output({ error: 'Phase not found', phase }, raw);
738
+ return;
739
+ }
740
+ const phaseDir = path.join(cwd, phaseInfo.directory);
741
+ let files;
742
+ try {
743
+ files = fs.readdirSync(phaseDir);
744
+ }
745
+ catch {
746
+ output({ error: 'Cannot read phase directory', phase }, raw);
747
+ return;
748
+ }
749
+ // Accept both prefixed (`01-01-PLAN.md`) and bare (`PLAN.md`) filenames —
750
+ // matches the convention used across the codebase (phase.ts:336, utils.ts:1046,
751
+ // gates.ts:199, knowledge.ts:230, roadmap.ts:614).
752
+ const plans = files.filter((f) => /-PLAN\.md$/i.test(f) || f === 'PLAN.md');
753
+ const summaries = files.filter((f) => /-SUMMARY\.md$/i.test(f) || f === 'SUMMARY.md');
754
+ const checks = [];
755
+ // A phase with zero PLAN.md files cannot pass the mechanical gate by
756
+ // vacuously satisfying every check. Emit an explicit failing check so the
757
+ // aggregate result correctly reports passed=false.
758
+ checks.push({
759
+ check: 'plan_summary_completeness',
760
+ scope: `phase:${phaseInfo.phase_number}`,
761
+ passed: plans.length > 0,
762
+ detail: plans.length > 0
763
+ ? `Phase has ${plans.length} PLAN.md file(s)`
764
+ : 'Phase has no PLAN.md files — nothing to verify',
765
+ data: { plan_count: plans.length },
766
+ });
767
+ if (plans.length === 0) {
768
+ const result = {
769
+ passed: false,
770
+ phase: phaseInfo.phase_number,
771
+ plan_count: 0,
772
+ total_checks: checks.length,
773
+ passed_count: 0,
774
+ failed_count: checks.length,
775
+ checks,
776
+ };
777
+ output(result, raw, 'fail');
778
+ return;
779
+ }
780
+ // The placeholder above will be replaced by the real plan_summary_completeness
781
+ // check below; pop it so we don't double-report.
782
+ checks.pop();
783
+ const requiredFrontmatterFields = [
784
+ 'phase',
785
+ 'plan',
786
+ 'type',
787
+ 'wave',
788
+ 'depends_on',
789
+ 'files_modified',
790
+ 'autonomous',
791
+ 'must_haves',
792
+ ];
793
+ for (const planFile of plans) {
794
+ const planPath = path.join(phaseDir, planFile);
795
+ const content = readFileCached(planPath);
796
+ if (!content) {
797
+ checks.push({
798
+ check: 'frontmatter',
799
+ scope: `plan:${planFile}`,
800
+ passed: false,
801
+ detail: 'PLAN.md unreadable',
802
+ });
803
+ continue;
804
+ }
805
+ const fm = extractFrontmatter(content);
806
+ // frontmatter check
807
+ const missingFields = requiredFrontmatterFields.filter((f) => fm[f] === undefined);
808
+ checks.push({
809
+ check: 'frontmatter',
810
+ scope: `plan:${planFile}`,
811
+ passed: missingFields.length === 0,
812
+ detail: missingFields.length === 0
813
+ ? `All ${requiredFrontmatterFields.length} required fields present`
814
+ : `Missing: ${missingFields.join(', ')}`,
815
+ data: { missing: missingFields, required: [...requiredFrontmatterFields] },
816
+ });
817
+ // artifacts check — mirror cmdVerifyArtifacts: existence AND content
818
+ // constraints (min_lines / contains / exports).
819
+ const artifacts = parseMustHavesBlock(content, 'artifacts');
820
+ if (artifacts.length > 0) {
821
+ const failed = [];
822
+ for (const art of artifacts) {
823
+ if (typeof art === 'string')
824
+ continue;
825
+ const artTyped = art;
826
+ const artPath = artTyped.path;
827
+ if (!artPath)
828
+ continue;
829
+ const artFullPath = path.join(cwd, artPath);
830
+ const issues = [];
831
+ if (!fs.existsSync(artFullPath)) {
832
+ issues.push('File not found');
833
+ }
834
+ else {
835
+ const fileContent = safeReadFile(artFullPath) || '';
836
+ const lineCount = fileContent.split('\n').length;
837
+ if (artTyped.min_lines && lineCount < artTyped.min_lines) {
838
+ issues.push(`Only ${lineCount} lines, need ${artTyped.min_lines}`);
839
+ }
840
+ if (artTyped.contains && !fileContent.includes(artTyped.contains)) {
841
+ issues.push(`Missing pattern: ${artTyped.contains}`);
842
+ }
843
+ if (artTyped.exports) {
844
+ const exps = Array.isArray(artTyped.exports)
845
+ ? artTyped.exports
846
+ : [artTyped.exports];
847
+ for (const exp of exps) {
848
+ if (!fileContent.includes(exp))
849
+ issues.push(`Missing export: ${exp}`);
850
+ }
851
+ }
852
+ }
853
+ if (issues.length > 0)
854
+ failed.push({ path: artPath, issues });
855
+ }
856
+ checks.push({
857
+ check: 'artifacts',
858
+ scope: `plan:${planFile}`,
859
+ passed: failed.length === 0,
860
+ detail: failed.length === 0
861
+ ? `All ${artifacts.length} artifacts present and satisfy content constraints`
862
+ : `Failed: ${failed.map((f) => `${f.path} (${f.issues.join('; ')})`).join('; ')}`,
863
+ data: { failed },
864
+ });
865
+ }
866
+ // key_links check
867
+ const keyLinks = parseMustHavesBlock(content, 'key_links');
868
+ if (keyLinks.length > 0) {
869
+ const failed = [];
870
+ for (const link of keyLinks) {
871
+ if (typeof link === 'string')
872
+ continue;
873
+ const linkTyped = link;
874
+ const fromContent = safeReadFile(path.join(cwd, linkTyped.from || ''));
875
+ const toPath = path.join(cwd, linkTyped.to || '');
876
+ let verified = false;
877
+ if (fromContent) {
878
+ if (linkTyped.pattern) {
879
+ try {
880
+ const regex = new RegExp(linkTyped.pattern);
881
+ if (regex.test(fromContent))
882
+ verified = true;
883
+ else {
884
+ const toContent = safeReadFile(toPath);
885
+ if (toContent && regex.test(toContent))
886
+ verified = true;
887
+ }
888
+ }
889
+ catch {
890
+ verified = false;
891
+ }
892
+ }
893
+ else {
894
+ verified = fromContent.includes(linkTyped.to || '');
895
+ }
896
+ }
897
+ if (!verified)
898
+ failed.push(`${linkTyped.from} → ${linkTyped.to}`);
899
+ }
900
+ checks.push({
901
+ check: 'key_links',
902
+ scope: `plan:${planFile}`,
903
+ passed: failed.length === 0,
904
+ detail: failed.length === 0
905
+ ? `All ${keyLinks.length} key links verified`
906
+ : `Failed: ${failed.join('; ')}`,
907
+ data: { failed },
908
+ });
909
+ }
910
+ // references check
911
+ const missingRefs = [];
912
+ const atRefs = content.match(/@([^\s\n,)]+\/[^\s\n,)]+)/g) || [];
913
+ for (const ref of atRefs) {
914
+ const cleanRef = ref.slice(1);
915
+ // Skip templated/dynamic refs (e.g. @${CLAUDE_PLUGIN_ROOT}/...) — they
916
+ // are not literal paths. Same guard the backtick branch uses below.
917
+ if (cleanRef.includes('${') || cleanRef.includes('{{'))
918
+ continue;
919
+ const resolved = cleanRef.startsWith('~/')
920
+ ? path.join(process.env.HOME || os.homedir() || '', cleanRef.slice(2))
921
+ : path.join(cwd, cleanRef);
922
+ if (!fs.existsSync(resolved))
923
+ missingRefs.push(cleanRef);
924
+ }
925
+ const backtickRefs = content.match(/`([^`]+\/[^`]+\.[a-zA-Z]{1,10})`/g) || [];
926
+ for (const ref of backtickRefs) {
927
+ const cleanRef = ref.slice(1, -1);
928
+ if (cleanRef.startsWith('http') || cleanRef.includes('${') || cleanRef.includes('{{'))
929
+ continue;
930
+ if (missingRefs.includes(cleanRef))
931
+ continue;
932
+ if (!fs.existsSync(path.join(cwd, cleanRef)))
933
+ missingRefs.push(cleanRef);
934
+ }
935
+ const totalRefs = atRefs.length + backtickRefs.length;
936
+ if (totalRefs > 0) {
937
+ checks.push({
938
+ check: 'references',
939
+ scope: `plan:${planFile}`,
940
+ passed: missingRefs.length === 0,
941
+ detail: missingRefs.length === 0
942
+ ? `All ${totalRefs} references resolve`
943
+ : `Missing: ${missingRefs.join(', ')}`,
944
+ data: { missing: missingRefs, total: totalRefs },
945
+ });
946
+ }
947
+ }
948
+ // phase-level: plan/summary completeness — bare PLAN.md / SUMMARY.md
949
+ // normalise to '' so they pair off.
950
+ const stripPlanId = (n) => n === 'PLAN.md' ? '' : n.replace(/-PLAN\.md$/i, '');
951
+ const stripSummaryId = (n) => n === 'SUMMARY.md' ? '' : n.replace(/-SUMMARY\.md$/i, '');
952
+ const planIds = new Set(plans.map(stripPlanId));
953
+ const summaryIds = new Set(summaries.map(stripSummaryId));
954
+ const incomplete = [...planIds].filter((id) => !summaryIds.has(id));
955
+ checks.push({
956
+ check: 'plan_summary_completeness',
957
+ scope: `phase:${phaseInfo.phase_number}`,
958
+ passed: incomplete.length === 0,
959
+ detail: incomplete.length === 0
960
+ ? `All ${plans.length} plans have summaries`
961
+ : `Plans without summaries: ${incomplete.join(', ')}`,
962
+ data: { incomplete, plan_count: plans.length, summary_count: summaries.length },
963
+ });
964
+ const passedCount = checks.filter((c) => c.passed).length;
965
+ const failedCount = checks.length - passedCount;
966
+ const result = {
967
+ passed: failedCount === 0,
968
+ phase: phaseInfo.phase_number,
969
+ plan_count: plans.length,
970
+ total_checks: checks.length,
971
+ passed_count: passedCount,
972
+ failed_count: failedCount,
973
+ checks,
974
+ };
975
+ output(result, raw, failedCount === 0 ? 'pass' : 'fail');
976
+ }
977
+ /**
978
+ * CLI command: Diagnose a failed phase by reading VERIFICATION.md, plan files,
979
+ * and running git diff to produce a ranked root-cause list.
980
+ *
981
+ * Intended as a quick forensics tool after `gd verify-phase N` fails.
982
+ * Reads:
983
+ * - .planning/milestones/{m}/phases/{N}/VERIFICATION.md (verdict + failed checks)
984
+ * - *-PLAN.md files in phase dir (detect plans without summaries)
985
+ * - `git diff HEAD` (scope estimate of uncommitted changes)
986
+ * Ranks causes by heuristic signal strength.
987
+ *
988
+ * @param cwd - Project working directory
989
+ * @param phase - Phase number or name
990
+ * @param raw - Output raw text instead of JSON
991
+ */
992
+ function cmdDiagnosePhase(cwd, phase, raw) {
993
+ if (!phase) {
994
+ error('phase required. Usage: gd diagnose <phase>');
995
+ }
996
+ const phaseInfo = findPhaseInternal(cwd, phase);
997
+ if (!phaseInfo || !phaseInfo.found) {
998
+ output({ error: 'Phase not found', phase }, raw);
999
+ return;
1000
+ }
1001
+ const phaseDir = path.join(cwd, phaseInfo.directory);
1002
+ // Codex r20 P2: scaffold/execution flow produces prefixed names like
1003
+ // `75-VERIFICATION.md`. Match both forms.
1004
+ let verificationPath = path.join(phaseDir, 'VERIFICATION.md');
1005
+ try {
1006
+ const files = require('fs').readdirSync(phaseDir);
1007
+ const prefixed = files.find((f) => /-VERIFICATION\.md$/.test(f));
1008
+ if (prefixed && !require('fs').existsSync(verificationPath)) {
1009
+ verificationPath = path.join(phaseDir, prefixed);
1010
+ }
1011
+ }
1012
+ catch { /* fall through */ }
1013
+ const verificationContent = safeReadFile(verificationPath);
1014
+ // Parse failed checks from VERIFICATION.md
1015
+ const failedChecks = [];
1016
+ let verdict = 'unknown';
1017
+ if (verificationContent) {
1018
+ const verdictMatch = verificationContent.match(/\*\*verdict\*\*[:\s]*([^\n]+)/i);
1019
+ if (verdictMatch)
1020
+ verdict = verdictMatch[1].trim();
1021
+ // Extract lines starting with ❌ or [FAIL] or "- FAIL"
1022
+ const failLines = verificationContent.match(/^(?:❌|[-*]\s*\[?FAIL[^]]*]?).*$/gim) || [];
1023
+ for (const line of failLines) {
1024
+ const clean = line.replace(/^[-*\s❌✗x]+/i, '').trim();
1025
+ if (clean)
1026
+ failedChecks.push(clean);
1027
+ }
1028
+ // Also parse "check: X passed: false" patterns in JSON-like blocks
1029
+ const checkFailMatches = verificationContent.match(/"check"\s*:\s*"([^"]+)"[^}]*"passed"\s*:\s*false/g) || [];
1030
+ for (const m of checkFailMatches) {
1031
+ const nameMatch = m.match(/"check"\s*:\s*"([^"]+)"/);
1032
+ if (nameMatch && !failedChecks.includes(nameMatch[1])) {
1033
+ failedChecks.push(nameMatch[1]);
1034
+ }
1035
+ }
1036
+ }
1037
+ // Check for plans without summaries
1038
+ let files = [];
1039
+ try {
1040
+ files = fs.readdirSync(phaseDir);
1041
+ }
1042
+ catch {
1043
+ // phase dir unreadable
1044
+ }
1045
+ const plans = files.filter((f) => /-PLAN\.md$/i.test(f) || f === 'PLAN.md');
1046
+ const summaries = files.filter((f) => /-SUMMARY\.md$/i.test(f) || f === 'SUMMARY.md');
1047
+ const planIds = plans.map((f) => (f === 'PLAN.md' ? '' : f.replace(/-PLAN\.md$/i, '')));
1048
+ const summaryIds = new Set(summaries.map((f) => (f === 'SUMMARY.md' ? '' : f.replace(/-SUMMARY\.md$/i, ''))));
1049
+ const plansMissingSummaries = planIds.filter((id) => !summaryIds.has(id)).length;
1050
+ // Measure uncommitted git diff size
1051
+ let gitDiffLines = 0;
1052
+ try {
1053
+ const diffResult = execGit(cwd, ['diff', 'HEAD', '--stat'], { allowBlocked: true });
1054
+ if (diffResult.stdout) {
1055
+ gitDiffLines = (diffResult.stdout.match(/\n/g) || []).length;
1056
+ }
1057
+ }
1058
+ catch {
1059
+ // git not available or not a repo
1060
+ }
1061
+ // Build ranked root causes
1062
+ const rootCauses = [];
1063
+ let rank = 1;
1064
+ if (plansMissingSummaries > 0) {
1065
+ rootCauses.push({
1066
+ rank: rank++,
1067
+ cause: `${plansMissingSummaries} plan(s) missing SUMMARY.md`,
1068
+ evidence: `Found ${plans.length} PLAN.md files, ${summaries.length} SUMMARY.md files`,
1069
+ suggestion: 'Run gd execute-phase N or manually write SUMMARY.md for each incomplete plan',
1070
+ });
1071
+ }
1072
+ if (!verificationContent) {
1073
+ rootCauses.push({
1074
+ rank: rank++,
1075
+ cause: 'VERIFICATION.md not found',
1076
+ evidence: `Expected at ${path.relative(cwd, verificationPath)}`,
1077
+ suggestion: 'Run gd verify-phase N to generate VERIFICATION.md before diagnosing',
1078
+ });
1079
+ }
1080
+ else if (verdict.toLowerCase().includes('fail') || verdict === 'unknown') {
1081
+ rootCauses.push({
1082
+ rank: rank++,
1083
+ cause: `Verification verdict: ${verdict}`,
1084
+ evidence: `${failedChecks.length} failed check(s) recorded`,
1085
+ suggestion: `Address failed checks: ${failedChecks.slice(0, 3).join(', ')}${failedChecks.length > 3 ? '...' : ''}`,
1086
+ });
1087
+ }
1088
+ for (const check of failedChecks.slice(0, 5)) {
1089
+ const cause = `Failed check: ${check}`;
1090
+ if (rootCauses.some((c) => c.cause === cause))
1091
+ continue;
1092
+ rootCauses.push({
1093
+ rank: rank++,
1094
+ cause,
1095
+ evidence: `Recorded in VERIFICATION.md`,
1096
+ suggestion: _checkSuggestion(check),
1097
+ });
1098
+ }
1099
+ if (gitDiffLines > 10) {
1100
+ rootCauses.push({
1101
+ rank: rank,
1102
+ cause: `${gitDiffLines} uncommitted lines in working tree`,
1103
+ evidence: 'git diff HEAD --stat shows pending changes',
1104
+ suggestion: 'Commit or stash changes before re-running verification',
1105
+ });
1106
+ }
1107
+ if (rootCauses.length === 0) {
1108
+ rootCauses.push({
1109
+ rank: 1,
1110
+ cause: 'No obvious failure signals found',
1111
+ evidence: 'VERIFICATION.md exists, no missing summaries, no large diffs',
1112
+ suggestion: 'Review VERIFICATION.md manually or re-run gd verify-phase N for details',
1113
+ });
1114
+ }
1115
+ const result = {
1116
+ phase: phaseInfo.phase_number,
1117
+ verdict,
1118
+ root_causes: rootCauses,
1119
+ failed_checks: failedChecks,
1120
+ git_diff_lines: gitDiffLines,
1121
+ plans_missing_summaries: plansMissingSummaries,
1122
+ };
1123
+ const summary = `Phase ${phaseInfo.phase_number}: ${rootCauses.length} root cause(s) — top: ${rootCauses[0].cause}`;
1124
+ output(result, raw, summary);
1125
+ }
1126
+ /** Map a failed check name to a human-readable next-step suggestion. */
1127
+ function _checkSuggestion(check) {
1128
+ if (/frontmatter/i.test(check))
1129
+ return 'Ensure PLAN.md has all required frontmatter fields (phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves)';
1130
+ if (/artifact/i.test(check))
1131
+ return 'Verify all must_haves artifacts exist at the declared paths with required content';
1132
+ if (/reference/i.test(check))
1133
+ return 'Fix broken @file or `path` references in PLAN.md';
1134
+ if (/key.?link/i.test(check))
1135
+ return 'Confirm all key_links pairs are wired together in source/target files';
1136
+ if (/summary|completeness/i.test(check))
1137
+ return 'Write a SUMMARY.md for each PLAN.md in the phase directory';
1138
+ return `Review the "${check}" section in VERIFICATION.md for details`;
1139
+ }
1140
+ // ─── Exports ─────────────────────────────────────────────────────────────────
1141
+ module.exports = {
1142
+ cmdVerifySummary,
1143
+ cmdVerifyPlanStructure,
1144
+ cmdVerifyPhaseCompleteness,
1145
+ cmdVerifyReferences,
1146
+ cmdVerifyCommits,
1147
+ cmdVerifyArtifacts,
1148
+ cmdVerifyKeyLinks,
1149
+ cmdVerifyMechanical,
1150
+ cmdDiagnosePhase,
1151
+ clearVerifyCache,
1152
+ };
1153
+ //# sourceMappingURL=verify.js.map