@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,1121 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const { fs, path, execFileSync, safeReadFile, safeReadMarkdown, stripShippedSections, loadConfig, output, error, } = require('./utils');
4
+ const { computeSchedule, getScheduleForPhase, getScheduleForMilestone, } = require('./roadmap');
5
+ const { phasesDir: getPhasesDirPath, } = require('./paths');
6
+ // ─── Tracker Config & Mapping ─────────────────────────────────────────────────
7
+ /**
8
+ * Load tracker configuration from config.json, with auto-migration of legacy formats.
9
+ * @param cwd - Project working directory
10
+ * @returns Tracker config object with provider field ('github', 'mcp-atlassian', or 'none')
11
+ */
12
+ function loadTrackerConfig(cwd) {
13
+ const configPath = path.join(cwd, '.planning', 'config.json');
14
+ const raw = safeReadFile(configPath);
15
+ if (!raw)
16
+ return { provider: 'none' };
17
+ try {
18
+ const config = JSON.parse(raw);
19
+ // New tracker config format
20
+ if (config.tracker) {
21
+ const tracker = config.tracker;
22
+ // Auto-migrate old "jira" provider to "mcp-atlassian"
23
+ if (tracker.provider === 'jira') {
24
+ tracker.provider = 'mcp-atlassian';
25
+ if (tracker.jira && !tracker.mcp_atlassian) {
26
+ const jira = tracker.jira;
27
+ tracker.mcp_atlassian = {
28
+ project_key: jira.project_key || '',
29
+ milestone_issue_type: jira.epic_issue_type || 'Epic',
30
+ phase_issue_type: jira.task_issue_type || 'Task',
31
+ plan_issue_type: 'Sub-task',
32
+ };
33
+ }
34
+ }
35
+ // Auto-migrate old epic/task config to milestone/phase/plan config
36
+ if (tracker.mcp_atlassian) {
37
+ const mcp = tracker.mcp_atlassian;
38
+ if (mcp.epic_issue_type && !mcp.milestone_issue_type) {
39
+ mcp.milestone_issue_type = mcp.epic_issue_type;
40
+ delete mcp.epic_issue_type;
41
+ }
42
+ if (mcp.task_issue_type && !mcp.phase_issue_type) {
43
+ mcp.phase_issue_type = mcp.task_issue_type;
44
+ delete mcp.task_issue_type;
45
+ }
46
+ if (!mcp.plan_issue_type) {
47
+ mcp.plan_issue_type = 'Sub-task';
48
+ }
49
+ }
50
+ // Validate required fields for github provider
51
+ if (tracker.provider === 'github' && tracker.github) {
52
+ const gh = tracker.github;
53
+ if (!gh.project_board) {
54
+ process.stderr.write('Warning: github tracker missing required field: project_board\n');
55
+ }
56
+ }
57
+ return tracker;
58
+ }
59
+ // Backward compat: migrate old github_integration format
60
+ if (config.github_integration && config.github_integration.enabled) {
61
+ const gi = config.github_integration;
62
+ return {
63
+ provider: 'github',
64
+ auto_sync: gi.auto_issues || false,
65
+ github: {
66
+ project_board: gi.project_board || gi.project_name || '',
67
+ default_assignee: gi.default_assignee || '',
68
+ default_labels: gi.default_labels || gi.labels
69
+ ? Object.values(gi.labels || {})
70
+ : ['research', 'implementation', 'evaluation', 'integration'],
71
+ auto_issues: gi.auto_issues || false,
72
+ pr_per_phase: gi.pr_per_phase || false,
73
+ },
74
+ };
75
+ }
76
+ return { provider: 'none' };
77
+ }
78
+ catch (e) {
79
+ process.stderr.write('Warning: failed to parse config.json: ' + e.message + '\n');
80
+ return { provider: 'none' };
81
+ }
82
+ }
83
+ // Cache for loadTrackerMapping: keyed by cwd, stores { mtime, mapping, index }
84
+ const _trackerMappingCache = new Map();
85
+ /**
86
+ * Split a markdown table row into column strings (preserves empty cells).
87
+ * @param row - A single markdown table row string
88
+ * @returns Array of trimmed cell values
89
+ */
90
+ function _splitTableRow(row) {
91
+ const parts = row.split('|').map((c) => c.trim());
92
+ if (parts.length > 0 && parts[0] === '')
93
+ parts.shift();
94
+ if (parts.length > 0 && parts[parts.length - 1] === '')
95
+ parts.pop();
96
+ return parts;
97
+ }
98
+ /**
99
+ * Build a Map index over a loaded mapping for O(1) lookups.
100
+ * Keys: milestone version strings, phase number strings, and "phase-plan" composite strings.
101
+ * @param mapping - Parsed mapping object with milestones, phases, and plans
102
+ * @returns Index map keyed by identifier
103
+ */
104
+ function _buildTrackerIndex(mapping) {
105
+ const index = new Map();
106
+ for (const [k, v] of Object.entries(mapping.milestones || {}))
107
+ index.set(k, v);
108
+ for (const [k, v] of Object.entries(mapping.phases || {}))
109
+ index.set(k, v);
110
+ for (const [k, v] of Object.entries(mapping.plans || {}))
111
+ index.set(k, v);
112
+ return index;
113
+ }
114
+ /**
115
+ * Load the tracker ID mapping from TRACKER.md, parsing milestone/phase/plan tables.
116
+ * Results are cached in memory; the cache is invalidated when the file's mtime changes.
117
+ * A Map index (_trackerIndex) is attached to the returned object for O(1) lookups.
118
+ * @param cwd - Project working directory
119
+ * @returns Mapping object with provider, last_synced, milestones, phases, plans, and _trackerIndex
120
+ */
121
+ function loadTrackerMapping(cwd) {
122
+ const mappingPath = path.join(cwd, '.planning', 'TRACKER.md');
123
+ // Check mtime for cache invalidation
124
+ let mtime = null;
125
+ try {
126
+ mtime = fs.statSync(mappingPath).mtimeMs;
127
+ }
128
+ catch {
129
+ /* file does not exist */
130
+ }
131
+ const cached = _trackerMappingCache.get(cwd);
132
+ if (cached && cached.mtime === mtime && mtime !== null) {
133
+ return cached.mapping;
134
+ }
135
+ const content = safeReadFile(mappingPath);
136
+ if (!content) {
137
+ const empty = {
138
+ provider: null,
139
+ last_synced: null,
140
+ milestones: {},
141
+ phases: {},
142
+ plans: {},
143
+ _trackerIndex: new Map(),
144
+ };
145
+ // Cache the empty result keyed on null mtime so repeated misses are cheap
146
+ _trackerMappingCache.set(cwd, { mtime: null, mapping: empty });
147
+ return empty;
148
+ }
149
+ const result = {
150
+ provider: null,
151
+ last_synced: null,
152
+ milestones: {},
153
+ phases: {},
154
+ plans: {},
155
+ _trackerIndex: new Map(),
156
+ };
157
+ const providerMatch = content.match(/^Provider:\s*(.+)$/m);
158
+ if (providerMatch)
159
+ result.provider = providerMatch[1].trim();
160
+ const syncMatch = content.match(/^Last Synced:\s*(.+)$/m);
161
+ if (syncMatch)
162
+ result.last_synced = syncMatch[1].trim();
163
+ // Parse milestone table (Epics) -- handles optional blank line between heading and table
164
+ const milestoneTableMatch = content.match(/## Milestone Issues\n\n?\|[^\n]+\n\|[^\n]+\n([\s\S]*?)(?=\n##|\n$|$)/);
165
+ if (milestoneTableMatch) {
166
+ const rows = milestoneTableMatch[1]
167
+ .trim()
168
+ .split('\n')
169
+ .filter((r) => r.startsWith('|'));
170
+ for (const row of rows) {
171
+ const cols = _splitTableRow(row);
172
+ if (cols.length >= 4) {
173
+ result.milestones[cols[0]] = {
174
+ issueRef: cols[1],
175
+ url: cols[2],
176
+ status: cols[3],
177
+ };
178
+ }
179
+ }
180
+ }
181
+ // Parse phase table (Tasks) -- handles optional blank line between heading and table
182
+ const phaseTableMatch = content.match(/## Phase Issues\n\n?\|[^\n]+\n\|[^\n]+\n([\s\S]*?)(?=\n##|\n$|$)/);
183
+ if (phaseTableMatch) {
184
+ const rows = phaseTableMatch[1]
185
+ .trim()
186
+ .split('\n')
187
+ .filter((r) => r.startsWith('|'));
188
+ for (const row of rows) {
189
+ const cols = _splitTableRow(row);
190
+ if (cols.length >= 5) {
191
+ result.phases[cols[0]] = {
192
+ issueRef: cols[1],
193
+ url: cols[2],
194
+ parentRef: cols[3],
195
+ status: cols[4],
196
+ };
197
+ }
198
+ }
199
+ }
200
+ // Parse plan table (Sub-tasks) -- handles optional blank line between heading and table
201
+ const planTableMatch = content.match(/## Plan Issues\n\n?\|[^\n]+\n\|[^\n]+\n([\s\S]*?)(?=\n##|\n$|$)/);
202
+ if (planTableMatch) {
203
+ const rows = planTableMatch[1]
204
+ .trim()
205
+ .split('\n')
206
+ .filter((r) => r.startsWith('|'));
207
+ for (const row of rows) {
208
+ const cols = _splitTableRow(row);
209
+ if (cols.length >= 6) {
210
+ const key = `${cols[0]}-${cols[1]}`;
211
+ result.plans[key] = {
212
+ issueRef: cols[2],
213
+ url: cols[3],
214
+ parentRef: cols[4],
215
+ status: cols[5],
216
+ };
217
+ }
218
+ }
219
+ }
220
+ // Attach O(1) lookup index
221
+ result._trackerIndex = _buildTrackerIndex(result);
222
+ _trackerMappingCache.set(cwd, { mtime, mapping: result });
223
+ return result;
224
+ }
225
+ /**
226
+ * Save the tracker ID mapping to TRACKER.md with formatted markdown tables.
227
+ * @param cwd - Project working directory
228
+ * @param mapping - Mapping object with provider, milestones, phases, and plans entries
229
+ */
230
+ function saveTrackerMapping(cwd, mapping) {
231
+ const mappingPath = path.join(cwd, '.planning', 'TRACKER.md');
232
+ const timestamp = new Date()
233
+ .toISOString()
234
+ .replace('T', ' ')
235
+ .replace(/\.\d+Z$/, ' UTC');
236
+ let content = `# Tracker Mapping\n\nProvider: ${mapping.provider || 'none'}\nLast Synced: ${timestamp}\n\n`;
237
+ content += `## Milestone Issues\n\n| Milestone | Issue Ref | URL | Status |\n|-----------|-----------|-----|--------|\n`;
238
+ for (const [milestone, info] of Object.entries(mapping.milestones || {})) {
239
+ content += `| ${milestone} | ${info.issueRef} | ${info.url} | ${info.status} |\n`;
240
+ }
241
+ content += `\n## Phase Issues\n\n| Phase | Issue Ref | URL | Parent Ref | Status |\n|-------|-----------|-----|------------|--------|\n`;
242
+ for (const [phase, info] of Object.entries(mapping.phases || {})) {
243
+ content += `| ${phase} | ${info.issueRef} | ${info.url} | ${info.parentRef || ''} | ${info.status} |\n`;
244
+ }
245
+ content += `\n## Plan Issues\n\n| Phase | Plan | Issue Ref | URL | Parent Ref | Status |\n|-------|------|-----------|-----|------------|--------|\n`;
246
+ for (const [key, info] of Object.entries(mapping.plans || {})) {
247
+ const [phase, plan] = key.split('-');
248
+ content += `| ${phase} | ${plan} | ${info.issueRef} | ${info.url} | ${info.parentRef} | ${info.status} |\n`;
249
+ }
250
+ const planningDir = path.join(cwd, '.planning');
251
+ if (!fs.existsSync(planningDir))
252
+ fs.mkdirSync(planningDir, { recursive: true });
253
+ fs.writeFileSync(mappingPath, content, 'utf-8');
254
+ // Invalidate cache so the next loadTrackerMapping call re-reads the updated file
255
+ _trackerMappingCache.delete(cwd);
256
+ }
257
+ // ─── GitHub Tracker ───────────────────────────────────────────────────────────
258
+ /**
259
+ * Create a GitHub Issues tracker operations object with methods for issue CRUD.
260
+ * @param cwd - Project working directory
261
+ * @param config - Tracker config with github sub-object for labels, assignees, etc.
262
+ * @returns Tracker object with createPhaseIssue, createTaskIssue, updateIssueStatus, addComment, syncRoadmap, syncPhase methods
263
+ */
264
+ function createGitHubTracker(cwd, config) {
265
+ const gh = config.github || {};
266
+ const mainConfig = loadConfig(cwd);
267
+ // NOTE: execFileSync is already the safe alternative (no shell injection).
268
+ // This is used for gh CLI calls which require direct process execution.
269
+ function ghExec(args) {
270
+ try {
271
+ return execFileSync('gh', args, {
272
+ cwd,
273
+ encoding: 'utf-8',
274
+ timeout: mainConfig.timeouts.tracker_gh_ms,
275
+ stdio: 'pipe',
276
+ }).trim();
277
+ }
278
+ catch {
279
+ return null;
280
+ }
281
+ }
282
+ function ghAvailable() {
283
+ return ghExec(['--version']) !== null;
284
+ }
285
+ return {
286
+ provider: 'github',
287
+ createPhaseIssue(_phaseNum, title, body, labels) {
288
+ if (!ghAvailable())
289
+ return { issueRef: null, url: null };
290
+ const args = [
291
+ 'issue',
292
+ 'create',
293
+ '--title',
294
+ title,
295
+ '--body',
296
+ body || '',
297
+ '--label',
298
+ 'epic',
299
+ ];
300
+ for (const l of labels || gh.default_labels || []) {
301
+ args.push('--label', l);
302
+ }
303
+ if (gh.default_assignee) {
304
+ args.push('--assignee', gh.default_assignee);
305
+ }
306
+ const url = ghExec(args);
307
+ if (!url)
308
+ return { issueRef: null, url: null };
309
+ const issueRef = url.match(/\/(\d+)$/)?.[1] || url;
310
+ return { issueRef: `#${issueRef}`, url };
311
+ },
312
+ createTaskIssue(phaseNum, planNum, title, parentRef) {
313
+ if (!ghAvailable())
314
+ return { issueRef: null, url: null };
315
+ const bodyText = `Parent: ${parentRef}\nPhase: ${phaseNum}\nPlan: ${planNum}`;
316
+ const url = ghExec([
317
+ 'issue',
318
+ 'create',
319
+ '--title',
320
+ title,
321
+ '--body',
322
+ bodyText,
323
+ '--label',
324
+ 'task',
325
+ ]);
326
+ if (!url)
327
+ return { issueRef: null, url: null };
328
+ const issueRef = url.match(/\/(\d+)$/)?.[1] || url;
329
+ // Try to link as sub-issue
330
+ if (parentRef) {
331
+ const parentNum = parentRef.replace('#', '');
332
+ ghExec(['sub-issue', 'add', parentNum, '--child', issueRef]);
333
+ }
334
+ return { issueRef: `#${issueRef}`, url };
335
+ },
336
+ updateIssueStatus(issueRef, status) {
337
+ if (!ghAvailable())
338
+ return { success: false };
339
+ const num = String(issueRef).replace('#', '');
340
+ const statusLabels = {
341
+ pending: 'status:todo',
342
+ in_progress: 'status:in-progress',
343
+ complete: 'status:done',
344
+ };
345
+ const label = statusLabels[status];
346
+ if (label) {
347
+ // Remove other status labels, add new one
348
+ for (const sl of Object.values(statusLabels)) {
349
+ ghExec(['issue', 'edit', num, '--remove-label', sl]);
350
+ }
351
+ ghExec(['issue', 'edit', num, '--add-label', label]);
352
+ }
353
+ if (status === 'complete') {
354
+ ghExec(['issue', 'close', num]);
355
+ }
356
+ return { success: true };
357
+ },
358
+ addComment(issueRef, markdownBody) {
359
+ if (!ghAvailable())
360
+ return { success: false };
361
+ const num = String(issueRef).replace('#', '');
362
+ ghExec(['issue', 'comment', num, '--body', markdownBody]);
363
+ return { success: true };
364
+ },
365
+ syncRoadmap(roadmapData) {
366
+ const mapping = loadTrackerMapping(cwd);
367
+ mapping.provider = 'github';
368
+ const stats = {
369
+ created: 0,
370
+ updated: 0,
371
+ skipped: 0,
372
+ errors: 0,
373
+ };
374
+ for (const phase of roadmapData.phases || []) {
375
+ const key = String(phase.number);
376
+ if (mapping.phases[key]) {
377
+ stats.skipped = (stats.skipped || 0) + 1;
378
+ continue;
379
+ }
380
+ const result = this.createPhaseIssue(phase.number, `Phase ${phase.number}: ${phase.name}`, phase.goal || '', phase.labels || []);
381
+ if (result.issueRef) {
382
+ mapping.phases[key] = {
383
+ issueRef: result.issueRef,
384
+ url: result.url || '',
385
+ parentRef: '',
386
+ status: 'pending',
387
+ };
388
+ stats.created++;
389
+ }
390
+ else {
391
+ stats.errors++;
392
+ }
393
+ }
394
+ saveTrackerMapping(cwd, mapping);
395
+ return stats;
396
+ },
397
+ syncPhase(phaseNum, phaseData) {
398
+ const mapping = loadTrackerMapping(cwd);
399
+ mapping.provider = 'github';
400
+ const stats = { created: 0, updated: 0, errors: 0 };
401
+ const parentRef = mapping.phases[String(phaseNum)]?.issueRef || null;
402
+ for (const plan of phaseData.plans || []) {
403
+ const key = `${phaseNum}-${plan.number}`;
404
+ if (mapping.plans[key]) {
405
+ stats.updated++;
406
+ continue;
407
+ }
408
+ const result = this.createTaskIssue(phaseNum, plan.number, `Plan ${phaseNum}-${plan.number}: ${plan.objective || ''}`, parentRef);
409
+ if (result.issueRef) {
410
+ mapping.plans[key] = {
411
+ issueRef: result.issueRef,
412
+ url: result.url || '',
413
+ parentRef: parentRef || '',
414
+ status: 'pending',
415
+ };
416
+ stats.created++;
417
+ }
418
+ else {
419
+ stats.errors++;
420
+ }
421
+ }
422
+ saveTrackerMapping(cwd, mapping);
423
+ return stats;
424
+ },
425
+ };
426
+ }
427
+ // Note: Jira integration is now handled via mcp-atlassian MCP server.
428
+ // grd-tools.js provides prepare/record commands; Claude agents call MCP tools directly.
429
+ // See references/mcp-tracker-protocol.md for the full protocol.
430
+ /**
431
+ * Factory function: create a tracker instance based on the configured provider.
432
+ * @param cwd - Project working directory
433
+ * @returns Tracker instance for GitHub, or null for mcp-atlassian/none
434
+ */
435
+ function createTracker(cwd) {
436
+ const config = loadTrackerConfig(cwd);
437
+ if (config.provider === 'github')
438
+ return createGitHubTracker(cwd, config);
439
+ // mcp-atlassian provider is handled by Claude agents via MCP tools, not by grd-tools.js
440
+ return null;
441
+ }
442
+ /**
443
+ * Provider factory map -- maps provider names to factory functions.
444
+ * Each factory takes (cwd, config) and returns a tracker instance.
445
+ */
446
+ const PROVIDERS = {
447
+ github: (cwd, config) => createGitHubTracker(cwd, config),
448
+ };
449
+ // ─── Tracker Subcommand Handlers ──────────────────────────────────────────────
450
+ function handleGetConfig(cwd, _args, raw) {
451
+ const config = loadTrackerConfig(cwd);
452
+ const mainConfig = loadConfig(cwd);
453
+ let authStatus = 'not_configured';
454
+ if (config.provider === 'github') {
455
+ try {
456
+ execFileSync('gh', ['auth', 'status'], {
457
+ cwd,
458
+ encoding: 'utf-8',
459
+ timeout: mainConfig.timeouts.tracker_auth_ms,
460
+ stdio: 'pipe',
461
+ });
462
+ authStatus = 'authenticated';
463
+ }
464
+ catch {
465
+ authStatus = 'not_authenticated';
466
+ }
467
+ }
468
+ else if (config.provider === 'mcp-atlassian') {
469
+ authStatus = 'mcp_server';
470
+ }
471
+ output({ ...config, auth_status: authStatus }, raw);
472
+ }
473
+ function handleSyncRoadmap(cwd, args, raw) {
474
+ const isDryRun = args.includes('--dry-run');
475
+ const config = loadTrackerConfig(cwd);
476
+ if (config.provider === 'mcp-atlassian') {
477
+ output({
478
+ error: 'Use "tracker prepare-roadmap-sync" for mcp-atlassian provider. Agent executes MCP calls.',
479
+ created: 0,
480
+ updated: 0,
481
+ skipped: 0,
482
+ errors: 0,
483
+ }, raw);
484
+ return;
485
+ }
486
+ const tracker = createTracker(cwd);
487
+ if (!tracker) {
488
+ output({
489
+ error: 'No tracker configured',
490
+ created: 0,
491
+ updated: 0,
492
+ skipped: 0,
493
+ errors: 0,
494
+ }, raw);
495
+ return;
496
+ }
497
+ const roadmapContent = safeReadMarkdown(path.join(cwd, '.planning', 'ROADMAP.md'));
498
+ if (!roadmapContent) {
499
+ output({
500
+ error: 'No ROADMAP.md found',
501
+ created: 0,
502
+ updated: 0,
503
+ skipped: 0,
504
+ errors: 0,
505
+ }, raw);
506
+ return;
507
+ }
508
+ const activeContent = stripShippedSections(roadmapContent);
509
+ const phases = [];
510
+ const phaseRegex = /^##\s+Phase\s+(\d+(?:\.\d+)?)\s*[:\-\u2014]\s*(.+)$/gm;
511
+ let match;
512
+ while ((match = phaseRegex.exec(activeContent)) !== null) {
513
+ const number = match[1];
514
+ const name = match[2].trim();
515
+ const afterPhase = activeContent.slice(match.index + match[0].length, match.index + match[0].length + 500);
516
+ const goalMatch = afterPhase.match(/(?:\*\*Goal:\*\*|Goal:)\s*(.+)/);
517
+ phases.push({
518
+ number,
519
+ name,
520
+ goal: goalMatch ? goalMatch[1].trim() : '',
521
+ });
522
+ }
523
+ if (isDryRun) {
524
+ // Dry-run mode: report what would be created/skipped without executing
525
+ const mapping = loadTrackerMapping(cwd);
526
+ const wouldCreate = [];
527
+ const wouldSkip = [];
528
+ for (const p of phases) {
529
+ if (mapping.phases && mapping.phases[p.number]) {
530
+ wouldSkip.push({
531
+ number: p.number,
532
+ name: p.name,
533
+ reason: 'already_mapped',
534
+ });
535
+ }
536
+ else {
537
+ wouldCreate.push({ number: p.number, name: p.name });
538
+ }
539
+ }
540
+ output({
541
+ dry_run: true,
542
+ would_create: wouldCreate,
543
+ would_skip: wouldSkip,
544
+ created: 0,
545
+ }, raw);
546
+ return;
547
+ }
548
+ const stats = tracker.syncRoadmap({ phases });
549
+ output(stats, raw, `Roadmap synced: created ${stats.created}, updated ${stats.updated}, errors ${stats.errors}`);
550
+ }
551
+ function handleSyncPhase(cwd, args, raw) {
552
+ const phaseNum = args[0];
553
+ if (!phaseNum) {
554
+ error('Usage: tracker sync-phase <phase-number>. Example: tracker sync-phase 3. Make sure you are in a GRD project directory and have a tracker configured in .planning/config.json. Run: tracker sync-phase <N> where N is the phase number.');
555
+ return; // unreachable after error() but helps TS narrowing
556
+ }
557
+ const config = loadTrackerConfig(cwd);
558
+ if (config.provider === 'mcp-atlassian') {
559
+ output({
560
+ error: 'Use "tracker prepare-phase-sync" for mcp-atlassian provider. Agent executes MCP calls.',
561
+ created: 0,
562
+ updated: 0,
563
+ errors: 0,
564
+ }, raw);
565
+ return;
566
+ }
567
+ const tracker = createTracker(cwd);
568
+ if (!tracker) {
569
+ output({ error: 'No tracker configured', created: 0, updated: 0, errors: 0 }, raw);
570
+ return;
571
+ }
572
+ const planningDir = getPhasesDirPath(cwd);
573
+ let phaseDir = null;
574
+ try {
575
+ const dirs = fs.readdirSync(planningDir);
576
+ phaseDir =
577
+ dirs.find((d) => d.startsWith(`${phaseNum}-`) || d === String(phaseNum)) || null;
578
+ }
579
+ catch {
580
+ /* no phases dir */
581
+ }
582
+ const plans = [];
583
+ if (phaseDir) {
584
+ const fullPhaseDir = path.join(planningDir, phaseDir);
585
+ try {
586
+ const files = fs
587
+ .readdirSync(fullPhaseDir)
588
+ .filter((f) => f.match(/-PLAN\.md$/));
589
+ for (const f of files) {
590
+ const planMatch = f.match(/(\d+)-(\d+)-PLAN\.md$/);
591
+ if (planMatch) {
592
+ const planContent = safeReadFile(path.join(fullPhaseDir, f));
593
+ const objMatch = planContent?.match(/(?:objective|title):\s*["']?(.+?)["']?\s*$/m);
594
+ plans.push({
595
+ number: planMatch[2],
596
+ objective: objMatch ? objMatch[1] : f,
597
+ });
598
+ }
599
+ }
600
+ }
601
+ catch {
602
+ /* no plan files */
603
+ }
604
+ }
605
+ const stats = tracker.syncPhase(phaseNum, { plans });
606
+ output(stats, raw, `Phase ${phaseNum} synced: created ${stats.created}, updated ${stats.updated}, errors ${stats.errors}`);
607
+ }
608
+ function handleUpdateStatus(cwd, args, raw) {
609
+ const phaseNum = args[0];
610
+ const status = args[1];
611
+ if (!phaseNum || !status) {
612
+ error('Usage: tracker update-status <phase-number> <status>. Provide phase number and one of the valid status values (in-progress, completed, blocked). Example: tracker update-status 3 completed. To see current phase numbers: grd-tools.js roadmap get-phase <N>');
613
+ return; // unreachable after error() but helps TS narrowing
614
+ }
615
+ const config = loadTrackerConfig(cwd);
616
+ if (config.provider === 'mcp-atlassian') {
617
+ const mapping = loadTrackerMapping(cwd);
618
+ const phaseInfo = mapping.phases[String(phaseNum)];
619
+ if (!phaseInfo) {
620
+ output({ success: false, error: 'Phase not synced to tracker' }, raw);
621
+ return;
622
+ }
623
+ phaseInfo.status = status;
624
+ saveTrackerMapping(cwd, mapping);
625
+ output({ success: true, issue_key: phaseInfo.issueRef, status }, raw);
626
+ return;
627
+ }
628
+ const tracker = createTracker(cwd);
629
+ if (!tracker) {
630
+ output({ success: false, error: 'No tracker configured' }, raw);
631
+ return;
632
+ }
633
+ const mapping = loadTrackerMapping(cwd);
634
+ const phaseInfo = mapping.phases[String(phaseNum)];
635
+ if (!phaseInfo) {
636
+ output({ success: false, error: 'Phase not synced to tracker' }, raw);
637
+ return;
638
+ }
639
+ const result = tracker.updateIssueStatus(phaseInfo.issueRef, status);
640
+ if (result.success) {
641
+ phaseInfo.status = status;
642
+ saveTrackerMapping(cwd, mapping);
643
+ }
644
+ output(result, raw, `Status ${result.success ? `updated to '${status}'` : 'update failed'}`);
645
+ }
646
+ function handleAddComment(cwd, args, raw) {
647
+ const phaseNum = args[0];
648
+ const filePath = args[1];
649
+ if (!phaseNum || !filePath) {
650
+ error('Usage: tracker add-comment <phase-number> <file-path>');
651
+ return; // unreachable after error() but helps TS narrowing
652
+ }
653
+ const config = loadTrackerConfig(cwd);
654
+ if (config.provider === 'mcp-atlassian') {
655
+ const mapping = loadTrackerMapping(cwd);
656
+ const phaseInfo = mapping.phases[String(phaseNum)];
657
+ if (!phaseInfo) {
658
+ output({ success: false, error: 'Phase not synced to tracker' }, raw);
659
+ return;
660
+ }
661
+ const content = safeReadFile(path.join(cwd, filePath));
662
+ if (!content) {
663
+ output({ success: false, error: 'File not found: ' + filePath }, raw);
664
+ return;
665
+ }
666
+ output({
667
+ provider: 'mcp-atlassian',
668
+ issue_key: phaseInfo.issueRef,
669
+ file_path: filePath,
670
+ content_length: content.length,
671
+ content,
672
+ }, raw);
673
+ return;
674
+ }
675
+ const tracker = createTracker(cwd);
676
+ if (!tracker) {
677
+ output({ success: false, error: 'No tracker configured' }, raw);
678
+ return;
679
+ }
680
+ const mapping = loadTrackerMapping(cwd);
681
+ const phaseInfo = mapping.phases[String(phaseNum)];
682
+ if (!phaseInfo) {
683
+ output({ success: false, error: 'Phase not synced to tracker' }, raw);
684
+ return;
685
+ }
686
+ const content = safeReadFile(path.join(cwd, filePath));
687
+ if (!content) {
688
+ output({ success: false, error: 'File not found: ' + filePath }, raw);
689
+ return;
690
+ }
691
+ const result = tracker.addComment(phaseInfo.issueRef, content);
692
+ output(result, raw, `Comment ${result.success ? 'added successfully' : 'failed'}`);
693
+ }
694
+ /**
695
+ * Parse all milestones from active roadmap content.
696
+ * @param content - Roadmap content with shipped sections already stripped
697
+ * @returns Ordered milestone list
698
+ */
699
+ function _parseAllMilestones(content) {
700
+ const milestoneRegex = /^##\s*(.*v(\d+\.\d+)[^(\n]*)/gim;
701
+ let mMatch;
702
+ const milestonePositions = [];
703
+ while ((mMatch = milestoneRegex.exec(content)) !== null) {
704
+ milestonePositions.push({
705
+ heading: mMatch[1].trim(),
706
+ version: 'v' + mMatch[2],
707
+ index: mMatch.index,
708
+ });
709
+ }
710
+ return milestonePositions;
711
+ }
712
+ /**
713
+ * Parse all phases from active roadmap content, associating each with its milestone.
714
+ * @param content - Roadmap content with shipped sections already stripped
715
+ * @param milestonePositions - Parsed milestone list
716
+ * @returns Parsed phase positions
717
+ */
718
+ function _parseAllPhases(content, milestonePositions) {
719
+ const phaseRegex = /^##\s+Phase\s+(\d+(?:\.\d+)?)\s*[:\-\u2014]\s*(.+)$/gm;
720
+ let match;
721
+ const allPhases = [];
722
+ while ((match = phaseRegex.exec(content)) !== null) {
723
+ const number = match[1];
724
+ const name = match[2].trim();
725
+ const afterPhase = content.slice(match.index + match[0].length, match.index + match[0].length + 500);
726
+ const goalMatch = afterPhase.match(/(?:\*\*Goal:\*\*|Goal:)\s*(.+)/);
727
+ const goal = goalMatch ? goalMatch[1].trim() : '';
728
+ let milestone = milestonePositions.length > 0 ? milestonePositions[0].version : null;
729
+ for (const ms of milestonePositions) {
730
+ if (match.index > ms.index)
731
+ milestone = ms.version;
732
+ }
733
+ allPhases.push({ number, name, goal, milestone, index: match.index });
734
+ }
735
+ return allPhases;
736
+ }
737
+ /**
738
+ * Build the operations array for a roadmap sync, covering milestones and phases.
739
+ * @param milestones - Parsed milestones
740
+ * @param phases - Parsed phases
741
+ * @param ctx - Loaded mapping and computed schedule
742
+ * @returns Operations array (create/skip entries)
743
+ */
744
+ function _buildMilestoneOperations(milestones, phases, ctx) {
745
+ const { mapping, schedule } = ctx;
746
+ const operations = [];
747
+ for (const ms of milestones) {
748
+ if (mapping.milestones[ms.version]) {
749
+ operations.push({
750
+ action: 'skip',
751
+ type: 'milestone',
752
+ milestone: ms.version,
753
+ issue_key: mapping.milestones[ms.version].issueRef,
754
+ reason: 'already_synced',
755
+ });
756
+ }
757
+ else {
758
+ const msSchedule = getScheduleForMilestone(schedule, ms.version);
759
+ const op = {
760
+ action: 'create',
761
+ type: 'milestone',
762
+ milestone: ms.version,
763
+ summary: ms.heading,
764
+ description: `Milestone ${ms.version}`,
765
+ };
766
+ if (msSchedule && msSchedule.start)
767
+ op.start_date = msSchedule.start;
768
+ if (msSchedule && msSchedule.target)
769
+ op.due_date = msSchedule.target;
770
+ operations.push(op);
771
+ }
772
+ }
773
+ for (const phase of phases) {
774
+ const milestoneKey = phase.milestone && mapping.milestones[phase.milestone]
775
+ ? mapping.milestones[phase.milestone].issueRef
776
+ : null;
777
+ if (mapping.phases[phase.number]) {
778
+ operations.push({
779
+ action: 'skip',
780
+ type: 'phase',
781
+ phase: phase.number,
782
+ issue_key: mapping.phases[phase.number].issueRef,
783
+ reason: 'already_synced',
784
+ });
785
+ }
786
+ else {
787
+ const phaseSchedule = getScheduleForPhase(schedule, phase.number);
788
+ const op = {
789
+ action: 'create',
790
+ type: 'phase',
791
+ phase: phase.number,
792
+ milestone: phase.milestone || undefined,
793
+ parent_key: milestoneKey,
794
+ summary: `Phase ${phase.number}: ${phase.name}`,
795
+ description: phase.goal,
796
+ };
797
+ if (phaseSchedule && phaseSchedule.start_date) {
798
+ op.start_date = phaseSchedule.start_date;
799
+ op.due_date = phaseSchedule.due_date || undefined;
800
+ op.duration_days = phaseSchedule.duration_days;
801
+ }
802
+ operations.push(op);
803
+ }
804
+ }
805
+ return operations;
806
+ }
807
+ function handlePrepareRoadmapSync(cwd, _args, raw) {
808
+ const config = loadTrackerConfig(cwd);
809
+ if (config.provider !== 'mcp-atlassian') {
810
+ output({
811
+ error: 'prepare-roadmap-sync is only for mcp-atlassian provider. Use "tracker sync-roadmap" for GitHub.',
812
+ }, raw);
813
+ return;
814
+ }
815
+ const mcpConfig = config.mcp_atlassian || {};
816
+ const roadmapContent = safeReadMarkdown(path.join(cwd, '.planning', 'ROADMAP.md'));
817
+ if (!roadmapContent) {
818
+ output({ error: 'No ROADMAP.md found', operations: [] }, raw);
819
+ return;
820
+ }
821
+ const activeContent = stripShippedSections(roadmapContent);
822
+ const mapping = loadTrackerMapping(cwd);
823
+ const schedule = computeSchedule(cwd);
824
+ const milestonePositions = _parseAllMilestones(activeContent);
825
+ const allPhases = _parseAllPhases(activeContent, milestonePositions);
826
+ const operations = _buildMilestoneOperations(milestonePositions, allPhases, {
827
+ mapping,
828
+ schedule,
829
+ });
830
+ output({
831
+ provider: 'mcp-atlassian',
832
+ project_key: mcpConfig.project_key || '',
833
+ start_date_field: mcpConfig.start_date_field || 'customfield_10015',
834
+ milestone_issue_type: mcpConfig.milestone_issue_type || 'Epic',
835
+ phase_issue_type: mcpConfig.phase_issue_type || 'Task',
836
+ operations,
837
+ }, raw);
838
+ }
839
+ function handlePreparePhaseSync(cwd, args, raw) {
840
+ const phaseNum = args[0];
841
+ if (!phaseNum) {
842
+ error('Usage: tracker prepare-phase-sync <phase-number>. Provide the phase number to sync, e.g.: tracker prepare-phase-sync 3. To see available phase numbers: grd-tools.js roadmap analyze');
843
+ return; // unreachable after error() but helps TS narrowing
844
+ }
845
+ const config = loadTrackerConfig(cwd);
846
+ if (config.provider !== 'mcp-atlassian') {
847
+ output({
848
+ error: 'prepare-phase-sync is only for mcp-atlassian provider. Use "tracker sync-phase" for GitHub.',
849
+ }, raw);
850
+ return;
851
+ }
852
+ const mcpConfig = config.mcp_atlassian || {};
853
+ const mapping = loadTrackerMapping(cwd);
854
+ const parentInfo = mapping.phases[String(phaseNum)];
855
+ const parentKey = parentInfo ? parentInfo.issueRef : null;
856
+ const planningDir = getPhasesDirPath(cwd);
857
+ let phaseDir = null;
858
+ try {
859
+ const dirs = fs.readdirSync(planningDir);
860
+ phaseDir =
861
+ dirs.find((d) => d.startsWith(`${phaseNum}-`) || d === String(phaseNum)) || null;
862
+ }
863
+ catch {
864
+ /* no phases dir */
865
+ }
866
+ const operations = [];
867
+ if (phaseDir) {
868
+ const fullPhaseDir = path.join(planningDir, phaseDir);
869
+ try {
870
+ const files = fs
871
+ .readdirSync(fullPhaseDir)
872
+ .filter((f) => f.match(/-PLAN\.md$/));
873
+ for (const f of files) {
874
+ const planMatch = f.match(/(\d+)-(\d+)-PLAN\.md$/);
875
+ if (planMatch) {
876
+ const planNum = planMatch[2];
877
+ const key = `${phaseNum}-${planNum}`;
878
+ if (mapping.plans[key]) {
879
+ operations.push({
880
+ action: 'skip',
881
+ type: 'plan',
882
+ phase: phaseNum,
883
+ plan: planNum,
884
+ issue_key: mapping.plans[key].issueRef,
885
+ reason: 'already_synced',
886
+ });
887
+ }
888
+ else {
889
+ const planContent = safeReadFile(path.join(fullPhaseDir, f));
890
+ const objMatch = planContent?.match(/(?:objective|title):\s*["']?(.+?)["']?\s*$/m);
891
+ operations.push({
892
+ action: 'create',
893
+ type: 'plan',
894
+ phase: phaseNum,
895
+ plan: planNum,
896
+ summary: `Plan ${phaseNum}-${planNum}: ${objMatch ? objMatch[1] : f}`,
897
+ description: '',
898
+ });
899
+ }
900
+ }
901
+ }
902
+ }
903
+ catch {
904
+ /* no plan files */
905
+ }
906
+ }
907
+ output({
908
+ provider: 'mcp-atlassian',
909
+ project_key: mcpConfig.project_key || '',
910
+ plan_issue_type: mcpConfig.plan_issue_type || 'Sub-task',
911
+ parent_key: parentKey,
912
+ operations,
913
+ }, raw);
914
+ }
915
+ function handleRecordMapping(cwd, args, raw) {
916
+ const typeIdx = args.indexOf('--type');
917
+ const milestoneIdx = args.indexOf('--milestone');
918
+ const phaseIdx = args.indexOf('--phase');
919
+ const planIdx = args.indexOf('--plan');
920
+ const keyIdx = args.indexOf('--key');
921
+ const urlIdx = args.indexOf('--url');
922
+ const parentIdx = args.indexOf('--parent');
923
+ const type = typeIdx !== -1 ? args[typeIdx + 1] : null;
924
+ const milestoneVer = milestoneIdx !== -1 ? args[milestoneIdx + 1] : null;
925
+ const phaseNum = phaseIdx !== -1 ? args[phaseIdx + 1] : null;
926
+ const planNum = planIdx !== -1 ? args[planIdx + 1] : null;
927
+ const issueKey = keyIdx !== -1 ? args[keyIdx + 1] : null;
928
+ const issueUrl = urlIdx !== -1 ? args[urlIdx + 1] : null;
929
+ const parentKey = parentIdx !== -1 ? args[parentIdx + 1] : '';
930
+ if (!type || !issueKey) {
931
+ error('Usage: tracker record-mapping --type milestone|phase|plan [--milestone V] [--phase N] [--plan M] --key PROJ-1 --url URL [--parent PROJ-0]. Example: tracker record-mapping --type phase --phase 2 --key PROJ-5 --url https://.... Ensure --type and --key flags are provided at minimum.');
932
+ return; // unreachable after error() but helps TS narrowing
933
+ }
934
+ const mapping = loadTrackerMapping(cwd);
935
+ mapping.provider = 'mcp-atlassian';
936
+ if (type === 'milestone') {
937
+ if (!milestoneVer) {
938
+ error('--milestone is required for type "milestone"');
939
+ return; // unreachable after error() but helps TS narrowing
940
+ }
941
+ mapping.milestones[milestoneVer] = {
942
+ issueRef: issueKey,
943
+ url: issueUrl || '',
944
+ status: 'pending',
945
+ };
946
+ }
947
+ else if (type === 'phase') {
948
+ if (!phaseNum) {
949
+ error('--phase is required for type "phase"');
950
+ return; // unreachable after error() but helps TS narrowing
951
+ }
952
+ mapping.phases[phaseNum] = {
953
+ issueRef: issueKey,
954
+ url: issueUrl || '',
955
+ parentRef: parentKey,
956
+ status: 'pending',
957
+ };
958
+ }
959
+ else if (type === 'plan') {
960
+ if (!phaseNum) {
961
+ error('--phase is required for type "plan"');
962
+ return; // unreachable after error() but helps TS narrowing
963
+ }
964
+ if (!planNum) {
965
+ error('--plan is required for type "plan"');
966
+ return; // unreachable after error() but helps TS narrowing
967
+ }
968
+ const key = `${phaseNum}-${planNum}`;
969
+ mapping.plans[key] = {
970
+ issueRef: issueKey,
971
+ url: issueUrl || '',
972
+ parentRef: parentKey,
973
+ status: 'pending',
974
+ };
975
+ }
976
+ else {
977
+ error(`Unknown mapping type: ${type}. Use "milestone", "phase", or "plan".`);
978
+ return; // unreachable after error() but helps TS narrowing
979
+ }
980
+ saveTrackerMapping(cwd, mapping);
981
+ output({
982
+ success: true,
983
+ type,
984
+ milestone: milestoneVer || null,
985
+ phase: phaseNum || null,
986
+ plan: planNum || null,
987
+ key: issueKey,
988
+ }, raw);
989
+ }
990
+ function handleRecordStatus(cwd, args, raw) {
991
+ const phaseIdx = args.indexOf('--phase');
992
+ const statusIdx = args.indexOf('--status');
993
+ const phaseNum = phaseIdx !== -1 ? args[phaseIdx + 1] : null;
994
+ const status = statusIdx !== -1 ? args[statusIdx + 1] : null;
995
+ if (!phaseNum || !status) {
996
+ error('Usage: tracker record-status --phase N --status pending|in_progress|complete. Example: tracker record-status --phase 2 --status in_progress. Ensure both --phase and --status flags are provided.');
997
+ return; // unreachable after error() but helps TS narrowing
998
+ }
999
+ const mapping = loadTrackerMapping(cwd);
1000
+ const phaseInfo = mapping.phases[String(phaseNum)];
1001
+ if (!phaseInfo) {
1002
+ output({ success: false, error: 'Phase not synced to tracker' }, raw);
1003
+ return;
1004
+ }
1005
+ phaseInfo.status = status;
1006
+ saveTrackerMapping(cwd, mapping);
1007
+ output({ success: true, phase: phaseNum, status, issue_key: phaseInfo.issueRef }, raw);
1008
+ }
1009
+ function handleSyncStatus(cwd, _args, raw) {
1010
+ const config = loadTrackerConfig(cwd);
1011
+ const mapping = loadTrackerMapping(cwd);
1012
+ const roadmapContent = safeReadMarkdown(path.join(cwd, '.planning', 'ROADMAP.md'));
1013
+ const activeContent = stripShippedSections(roadmapContent || '');
1014
+ const phaseRegex = /^##\s+Phase\s+(\d+(?:\.\d+)?)/gm;
1015
+ const roadmapPhases = [];
1016
+ let m;
1017
+ while ((m = phaseRegex.exec(activeContent)) !== null) {
1018
+ roadmapPhases.push(m[1]);
1019
+ }
1020
+ const synced = roadmapPhases.filter((p) => mapping.phases[p]);
1021
+ const unsynced = roadmapPhases.filter((p) => !mapping.phases[p]);
1022
+ output({
1023
+ provider: config.provider,
1024
+ last_synced: mapping.last_synced,
1025
+ total_milestones: Object.keys(mapping.milestones).length,
1026
+ total_phases: roadmapPhases.length,
1027
+ synced_phases: synced.length,
1028
+ unsynced_phases: unsynced.length,
1029
+ synced: synced,
1030
+ unsynced: unsynced,
1031
+ plan_count: Object.keys(mapping.plans).length,
1032
+ }, raw);
1033
+ }
1034
+ function handleSchedule(cwd, _args, raw) {
1035
+ const schedule = computeSchedule(cwd);
1036
+ output(schedule, raw, `${schedule.phases.length} phases scheduled across ${schedule.milestones.length} milestone(s)`);
1037
+ }
1038
+ function handlePrepareReschedule(cwd, _args, raw) {
1039
+ const config = loadTrackerConfig(cwd);
1040
+ if (config.provider !== 'mcp-atlassian') {
1041
+ output({ error: 'prepare-reschedule is only for mcp-atlassian provider.' }, raw);
1042
+ return;
1043
+ }
1044
+ const mcpConfig = config.mcp_atlassian || {};
1045
+ const mapping = loadTrackerMapping(cwd);
1046
+ const schedule = computeSchedule(cwd);
1047
+ const operations = [];
1048
+ for (const ms of schedule.milestones) {
1049
+ const mapped = mapping.milestones[ms.version];
1050
+ if (mapped && (ms.start || ms.target)) {
1051
+ const op = {
1052
+ action: 'update',
1053
+ type: 'milestone',
1054
+ milestone: ms.version,
1055
+ issue_key: mapped.issueRef,
1056
+ };
1057
+ if (ms.start)
1058
+ op.start_date = ms.start;
1059
+ if (ms.target)
1060
+ op.due_date = ms.target;
1061
+ operations.push(op);
1062
+ }
1063
+ }
1064
+ for (const phase of schedule.phases) {
1065
+ const mapped = mapping.phases[phase.number];
1066
+ if (mapped && phase.start_date) {
1067
+ operations.push({
1068
+ action: 'update',
1069
+ type: 'phase',
1070
+ phase: phase.number,
1071
+ issue_key: mapped.issueRef,
1072
+ start_date: phase.start_date,
1073
+ due_date: phase.due_date || undefined,
1074
+ });
1075
+ }
1076
+ }
1077
+ output({
1078
+ provider: 'mcp-atlassian',
1079
+ start_date_field: mcpConfig.start_date_field || 'customfield_10015',
1080
+ operations,
1081
+ }, raw);
1082
+ }
1083
+ const trackerHandlers = {
1084
+ 'get-config': handleGetConfig,
1085
+ 'sync-roadmap': handleSyncRoadmap,
1086
+ 'sync-phase': handleSyncPhase,
1087
+ 'update-status': handleUpdateStatus,
1088
+ 'add-comment': handleAddComment,
1089
+ 'sync-status': handleSyncStatus,
1090
+ 'prepare-roadmap-sync': handlePrepareRoadmapSync,
1091
+ 'prepare-phase-sync': handlePreparePhaseSync,
1092
+ 'record-mapping': handleRecordMapping,
1093
+ 'record-status': handleRecordStatus,
1094
+ schedule: handleSchedule,
1095
+ 'prepare-reschedule': handlePrepareReschedule,
1096
+ };
1097
+ /**
1098
+ * CLI command: Dispatch tracker subcommand (get-config, sync-roadmap, sync-phase, update-status, etc.).
1099
+ * @param cwd - Project working directory
1100
+ * @param subcommand - Tracker subcommand name
1101
+ * @param args - Additional arguments for the subcommand
1102
+ * @param raw - Output raw text instead of JSON
1103
+ */
1104
+ function cmdTracker(cwd, subcommand, args, raw) {
1105
+ const handler = trackerHandlers[subcommand];
1106
+ if (!handler) {
1107
+ error(`Unknown tracker subcommand: '${subcommand}'. Available: ${Object.keys(trackerHandlers).join(', ')}`);
1108
+ return; // unreachable after error() but helps TS narrowing
1109
+ }
1110
+ handler(cwd, args, raw);
1111
+ }
1112
+ module.exports = {
1113
+ loadTrackerConfig,
1114
+ loadTrackerMapping,
1115
+ saveTrackerMapping,
1116
+ createGitHubTracker,
1117
+ PROVIDERS,
1118
+ createTracker,
1119
+ cmdTracker,
1120
+ };
1121
+ //# sourceMappingURL=tracker.js.map