@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,934 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { safeReadFile, } = require('../utils');
6
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
7
+ /**
8
+ * Recursively collect all files under a directory matching given extensions.
9
+ * Returns absolute paths.
10
+ */
11
+ function _collectFiles(dir, extensions) {
12
+ const results = [];
13
+ let entries;
14
+ try {
15
+ entries = fs.readdirSync(dir, { withFileTypes: true });
16
+ }
17
+ catch {
18
+ return results;
19
+ }
20
+ for (const entry of entries) {
21
+ const fullPath = path.join(dir, entry.name);
22
+ if (entry.isDirectory()) {
23
+ if (entry.name === 'node_modules' || entry.name.startsWith('.'))
24
+ continue;
25
+ results.push(..._collectFiles(fullPath, extensions));
26
+ }
27
+ else if (entry.isFile()) {
28
+ const ext = path.extname(entry.name);
29
+ if (extensions.includes(ext)) {
30
+ results.push(fullPath);
31
+ }
32
+ }
33
+ }
34
+ return results;
35
+ }
36
+ /**
37
+ * Extract exported function/value names from a TypeScript/JavaScript source file.
38
+ *
39
+ * Handles CJS and ES module patterns:
40
+ * - module.exports = { name1, name2, ... }
41
+ * - exports.name = ...
42
+ * - export function name / export const name / export class name
43
+ * - export default function name
44
+ */
45
+ function _extractExports(content) {
46
+ const names = [];
47
+ // Pattern 1: module.exports = { name1, name2, ... }
48
+ const moduleExportMatch = content.match(/module\.exports\s*=\s*\{([^}]+)\}/);
49
+ if (moduleExportMatch) {
50
+ const inner = moduleExportMatch[1];
51
+ const parts = inner.split(',');
52
+ for (const part of parts) {
53
+ const trimmed = part.trim();
54
+ if (!trimmed)
55
+ continue;
56
+ const colonIdx = trimmed.indexOf(':');
57
+ const name = colonIdx >= 0 ? trimmed.slice(0, colonIdx).trim() : trimmed;
58
+ if (/^\w+$/.test(name)) {
59
+ names.push(name);
60
+ }
61
+ }
62
+ }
63
+ // Pattern 2: exports.name = ...
64
+ const exportsPattern = /\bexports\.(\w+)\s*=/g;
65
+ let match;
66
+ while ((match = exportsPattern.exec(content)) !== null) {
67
+ if (!names.includes(match[1])) {
68
+ names.push(match[1]);
69
+ }
70
+ }
71
+ // Pattern 3: ES module exports — export [async] function/const/class/let/var name
72
+ const esExportPattern = /export\s+(?:async\s+)?(?:function|const|class|let|var)\s+(\w+)/g;
73
+ while ((match = esExportPattern.exec(content)) !== null) {
74
+ if (!names.includes(match[1])) {
75
+ names.push(match[1]);
76
+ }
77
+ }
78
+ // Pattern 4: export default function name (skip anonymous defaults)
79
+ const defaultExportPattern = /export\s+default\s+(?:async\s+)?(?:function|class)\s+(\w+)/g;
80
+ while ((match = defaultExportPattern.exec(content)) !== null) {
81
+ if (match[1] !== 'default' && !names.includes(match[1])) {
82
+ names.push(match[1]);
83
+ }
84
+ }
85
+ return names;
86
+ }
87
+ // ─── Scanner: exported-but-uncalled ─────────────────────────────────────────
88
+ /**
89
+ * Scan lib/*.ts files for exported functions that are never called/imported
90
+ * in lib/, bin/, or commands/.
91
+ */
92
+ function scanExportedButUncalled(cwd) {
93
+ const libDir = path.join(cwd, 'lib');
94
+ const binDir = path.join(cwd, 'bin');
95
+ const commandsDir = path.join(cwd, 'commands');
96
+ let libEntries;
97
+ try {
98
+ libEntries = fs.readdirSync(libDir, { withFileTypes: true });
99
+ }
100
+ catch {
101
+ return [];
102
+ }
103
+ const libFiles = libEntries
104
+ .filter((e) => e.isFile() && e.name.endsWith('.ts'))
105
+ .map((e) => path.join(libDir, e.name));
106
+ const exportMap = new Map();
107
+ const fileContents = new Map();
108
+ for (const filePath of libFiles) {
109
+ const content = safeReadFile(filePath);
110
+ if (!content)
111
+ continue;
112
+ fileContents.set(filePath, content);
113
+ const relPath = path.relative(cwd, filePath);
114
+ const exportedNames = _extractExports(content);
115
+ for (const name of exportedNames) {
116
+ if (!exportMap.has(name)) {
117
+ exportMap.set(name, relPath);
118
+ }
119
+ }
120
+ }
121
+ const searchFiles = [
122
+ ..._collectFiles(libDir, ['.ts', '.js', '.md']),
123
+ ..._collectFiles(binDir, ['.ts', '.js', '.md']),
124
+ ..._collectFiles(commandsDir, ['.ts', '.js', '.md']),
125
+ ];
126
+ const features = [];
127
+ for (const [funcName, relFilePath] of exportMap) {
128
+ const absFilePath = path.join(cwd, relFilePath);
129
+ let referenced = false;
130
+ for (const searchFile of searchFiles) {
131
+ if (path.resolve(searchFile) === path.resolve(absFilePath))
132
+ continue;
133
+ const content = safeReadFile(searchFile);
134
+ if (!content)
135
+ continue;
136
+ if (new RegExp(`\\b${funcName}\\b`).test(content)) {
137
+ referenced = true;
138
+ break;
139
+ }
140
+ }
141
+ if (!referenced) {
142
+ features.push({
143
+ category: 'exported-but-uncalled',
144
+ filePath: relFilePath,
145
+ functionName: funcName,
146
+ suggestedAction: 'Add call site in a command, route, or test',
147
+ });
148
+ }
149
+ }
150
+ return features;
151
+ }
152
+ // ─── Scanner: config-without-surface ────────────────────────────────────────
153
+ /**
154
+ * Scan .planning/config.json for top-level config keys that are not referenced
155
+ * in commands/*.md or bin/*.ts.
156
+ */
157
+ function scanConfigWithoutSurface(cwd) {
158
+ const configPath = path.join(cwd, '.planning', 'config.json');
159
+ const content = safeReadFile(configPath);
160
+ if (!content)
161
+ return [];
162
+ let configObj;
163
+ try {
164
+ configObj = JSON.parse(content);
165
+ }
166
+ catch {
167
+ return [];
168
+ }
169
+ const configKeys = Object.keys(configObj);
170
+ if (configKeys.length === 0)
171
+ return [];
172
+ const searchDirs = [
173
+ { dir: path.join(cwd, 'commands'), exts: ['.md'] },
174
+ { dir: path.join(cwd, 'bin'), exts: ['.ts', '.js'] },
175
+ { dir: path.join(cwd, 'lib'), exts: ['.ts', '.js'] },
176
+ { dir: path.join(cwd, 'src'), exts: ['.ts', '.js'] },
177
+ ];
178
+ const searchFiles = [];
179
+ for (const { dir, exts } of searchDirs) {
180
+ try {
181
+ fs.readdirSync(dir);
182
+ searchFiles.push(..._collectFiles(dir, exts));
183
+ }
184
+ catch {
185
+ // dir doesn't exist
186
+ }
187
+ }
188
+ const combinedContent = searchFiles
189
+ .map((f) => safeReadFile(f) || '')
190
+ .join('\n');
191
+ const features = [];
192
+ for (const key of configKeys) {
193
+ if (key.startsWith('_'))
194
+ continue;
195
+ if (!new RegExp(`\\b${key}\\b`).test(combinedContent)) {
196
+ features.push({
197
+ category: 'config-without-surface',
198
+ filePath: '.planning/config.json',
199
+ functionName: key,
200
+ suggestedAction: 'Expose via CLI flag, command option, or settings UI',
201
+ });
202
+ }
203
+ }
204
+ return features;
205
+ }
206
+ // ─── Scanner: endpoint-without-integration-test ──────────────────────────────
207
+ /**
208
+ * Scan lib/mcp-server.ts for registered MCP tool names and check if they
209
+ * are referenced in tests/integration/.
210
+ */
211
+ function scanEndpointsWithoutTests(cwd) {
212
+ const serverPath = path.join(cwd, 'lib', 'mcp-server.ts');
213
+ const content = safeReadFile(serverPath);
214
+ if (!content)
215
+ return [];
216
+ const toolNamePattern = /name:\s*['"](\w+)['"]/g;
217
+ const toolNames = [];
218
+ let match;
219
+ while ((match = toolNamePattern.exec(content)) !== null) {
220
+ const name = match[1];
221
+ if (name.startsWith('grd_') && !toolNames.includes(name)) {
222
+ toolNames.push(name);
223
+ }
224
+ }
225
+ if (toolNames.length === 0)
226
+ return [];
227
+ const integrationDir = path.join(cwd, 'tests', 'integration');
228
+ const integrationFiles = _collectFiles(integrationDir, ['.ts', '.js']);
229
+ const combinedIntegration = integrationFiles
230
+ .map((f) => safeReadFile(f) || '')
231
+ .join('\n');
232
+ const features = [];
233
+ for (const toolName of toolNames) {
234
+ if (!combinedIntegration.includes(toolName)) {
235
+ features.push({
236
+ category: 'endpoint-without-integration-test',
237
+ filePath: 'lib/mcp-server.ts',
238
+ functionName: toolName,
239
+ suggestedAction: 'Add integration test covering this endpoint',
240
+ });
241
+ }
242
+ }
243
+ return features;
244
+ }
245
+ // ─── Application-Aware Scanners ──────────────────────────────────────────────
246
+ /** Directories to skip when scanning for application source code. */
247
+ const SKIP_DIRS = new Set([
248
+ 'node_modules', '.git', '.planning', '.claude-plugin', 'dist', 'build', 'out',
249
+ 'coverage', '.next', '.nuxt', '.svelte-kit', '__pycache__', '.venv', 'venv',
250
+ 'vendor', 'target', '.cache', '.turbo', '.vercel', '.output',
251
+ // GRD-internal directories — skip so we don't double-count with GRD scanners
252
+ 'agents', 'commands', 'templates', 'examples', 'docs', 'references',
253
+ ]);
254
+ /**
255
+ * Detect source directories in the project by scanning all top-level directories
256
+ * and filtering out infrastructure/config dirs. This is NOT a whitelist — any
257
+ * directory that contains .ts/.js/.tsx/.jsx files is a candidate.
258
+ */
259
+ function _detectAppSourceDirs(cwd) {
260
+ const found = [];
261
+ let entries;
262
+ try {
263
+ entries = fs.readdirSync(cwd, { withFileTypes: true });
264
+ }
265
+ catch {
266
+ return found;
267
+ }
268
+ for (const entry of entries) {
269
+ if (!entry.isDirectory())
270
+ continue;
271
+ if (entry.name.startsWith('.'))
272
+ continue;
273
+ if (SKIP_DIRS.has(entry.name))
274
+ continue;
275
+ // Check if this dir contains at least one source file (quick heuristic)
276
+ const dirPath = path.join(cwd, entry.name);
277
+ const files = _collectFiles(dirPath, ['.ts', '.js', '.tsx', '.jsx']);
278
+ if (files.length > 0) {
279
+ found.push(entry.name);
280
+ }
281
+ }
282
+ return found;
283
+ }
284
+ /**
285
+ * Extract route registrations from Express/Fastify/Hono-style source files.
286
+ *
287
+ * Detects patterns like:
288
+ * app.get('/path', handler)
289
+ * router.post('/path', handler)
290
+ * export async function GET(req) — Next.js App Router
291
+ * @Get('/path') — NestJS
292
+ */
293
+ function _extractRoutes(content, filePath) {
294
+ const routes = [];
295
+ // Express/Fastify/Hono: app.method('/path', ...) or router.method('/path', ...)
296
+ const expressPattern = /(?:app|router|server|fastify|hono)\s*\.\s*(get|post|put|patch|delete|all|use)\s*\(\s*['"`]([^'"`]+)['"`]/gi;
297
+ let match;
298
+ while ((match = expressPattern.exec(content)) !== null) {
299
+ routes.push({ method: match[1].toUpperCase(), route: match[2], filePath });
300
+ }
301
+ // Next.js App Router: export async function GET/POST/PUT/DELETE/PATCH
302
+ const nextAppPattern = /export\s+(?:async\s+)?function\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s*\(/gi;
303
+ while ((match = nextAppPattern.exec(content)) !== null) {
304
+ const routePath = _filePathToRoute(filePath);
305
+ routes.push({ method: match[1].toUpperCase(), route: routePath, filePath });
306
+ }
307
+ // Decorator patterns: @Get('/path'), @Post('/path') etc (NestJS)
308
+ const decoratorPattern = /@(Get|Post|Put|Patch|Delete)\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/gi;
309
+ while ((match = decoratorPattern.exec(content)) !== null) {
310
+ routes.push({ method: match[1].toUpperCase(), route: match[2], filePath });
311
+ }
312
+ return routes;
313
+ }
314
+ /**
315
+ * Convert a file path like `app/api/users/route.ts` or `pages/api/users.ts`
316
+ * to a route path like `/api/users`.
317
+ */
318
+ function _filePathToRoute(filePath) {
319
+ let route = filePath
320
+ .replace(/\\/g, '/')
321
+ .replace(/^.*?\b(app|pages)\//, '/')
322
+ .replace(/\/route\.(ts|js|tsx|jsx)$/, '')
323
+ .replace(/\.(ts|js|tsx|jsx)$/, '')
324
+ .replace(/\/index$/, '');
325
+ if (!route.startsWith('/'))
326
+ route = '/' + route;
327
+ return route;
328
+ }
329
+ /**
330
+ * Scan for application routes/endpoints that have no corresponding test file.
331
+ */
332
+ function scanAppRoutes(cwd) {
333
+ const features = [];
334
+ const appDirs = _detectAppSourceDirs(cwd);
335
+ if (appDirs.length === 0)
336
+ return features;
337
+ // Collect all source files from app directories
338
+ const sourceFiles = [];
339
+ for (const dir of appDirs) {
340
+ sourceFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js', '.tsx', '.jsx']));
341
+ }
342
+ // Also check root-level route files
343
+ const rootFiles = ['routes.ts', 'routes.js', 'server.ts', 'server.js'];
344
+ for (const file of rootFiles) {
345
+ const fullPath = path.join(cwd, file);
346
+ try {
347
+ if (fs.statSync(fullPath).isFile())
348
+ sourceFiles.push(fullPath);
349
+ }
350
+ catch {
351
+ // doesn't exist
352
+ }
353
+ }
354
+ // Extract routes from all source files
355
+ const allRoutes = [];
356
+ for (const file of sourceFiles) {
357
+ const content = safeReadFile(file);
358
+ if (!content)
359
+ continue;
360
+ const relPath = path.relative(cwd, file);
361
+ allRoutes.push(..._extractRoutes(content, relPath));
362
+ }
363
+ if (allRoutes.length === 0)
364
+ return features;
365
+ // Collect test files
366
+ const testDirs = ['tests', 'test', '__tests__', 'spec'];
367
+ const testFiles = [];
368
+ for (const dir of testDirs) {
369
+ testFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js', '.tsx', '.jsx']));
370
+ }
371
+ // Also collect *.test.* and *.spec.* from source dirs
372
+ for (const dir of appDirs) {
373
+ const allFiles = _collectFiles(path.join(cwd, dir), ['.ts', '.js', '.tsx', '.jsx']);
374
+ for (const f of allFiles) {
375
+ const basename = path.basename(f);
376
+ if (basename.includes('.test.') || basename.includes('.spec.')) {
377
+ testFiles.push(f);
378
+ }
379
+ }
380
+ }
381
+ const combinedTests = testFiles
382
+ .map((f) => safeReadFile(f) || '')
383
+ .join('\n');
384
+ // Check each route for test coverage
385
+ const seen = new Set();
386
+ for (const route of allRoutes) {
387
+ const key = `${route.method} ${route.route}`;
388
+ if (seen.has(key))
389
+ continue;
390
+ seen.add(key);
391
+ const routeEscaped = route.route.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
392
+ const routeReferenced = new RegExp(routeEscaped).test(combinedTests) ||
393
+ combinedTests.includes(route.route);
394
+ if (!routeReferenced) {
395
+ features.push({
396
+ category: 'app-route-without-test',
397
+ filePath: route.filePath,
398
+ functionName: `${route.method} ${route.route}`,
399
+ suggestedAction: `Add integration test for ${route.method} ${route.route}`,
400
+ });
401
+ }
402
+ }
403
+ return features;
404
+ }
405
+ /**
406
+ * Scan src/ (or similar) for exported functions/classes that are never imported
407
+ * anywhere in the project.
408
+ */
409
+ function scanAppExportedButUncalled(cwd) {
410
+ const appDirs = _detectAppSourceDirs(cwd);
411
+ if (appDirs.length === 0)
412
+ return [];
413
+ const exportMap = new Map();
414
+ const allAppFiles = [];
415
+ for (const dir of appDirs) {
416
+ allAppFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js', '.tsx', '.jsx']));
417
+ }
418
+ for (const filePath of allAppFiles) {
419
+ const content = safeReadFile(filePath);
420
+ if (!content)
421
+ continue;
422
+ const relPath = path.relative(cwd, filePath);
423
+ // Skip test files
424
+ const basename = path.basename(filePath);
425
+ if (basename.includes('.test.') || basename.includes('.spec.'))
426
+ continue;
427
+ const exportedNames = _extractExports(content);
428
+ // Also detect ES module exports: export function name / export const name
429
+ const esExportPattern = /export\s+(?:async\s+)?(?:function|const|class|let|var)\s+(\w+)/g;
430
+ let match;
431
+ while ((match = esExportPattern.exec(content)) !== null) {
432
+ if (!exportedNames.includes(match[1])) {
433
+ exportedNames.push(match[1]);
434
+ }
435
+ }
436
+ for (const name of exportedNames) {
437
+ if (name === 'default')
438
+ continue;
439
+ if (!exportMap.has(name)) {
440
+ exportMap.set(name, relPath);
441
+ }
442
+ }
443
+ }
444
+ // Search all project files for references
445
+ const searchFiles = [...allAppFiles];
446
+ const testDirs = ['tests', 'test', '__tests__'];
447
+ for (const dir of testDirs) {
448
+ searchFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js', '.tsx', '.jsx']));
449
+ }
450
+ const features = [];
451
+ for (const [funcName, relFilePath] of exportMap) {
452
+ const absFilePath = path.join(cwd, relFilePath);
453
+ let referenced = false;
454
+ for (const searchFile of searchFiles) {
455
+ if (path.resolve(searchFile) === path.resolve(absFilePath))
456
+ continue;
457
+ const content = safeReadFile(searchFile);
458
+ if (!content)
459
+ continue;
460
+ if (new RegExp(`\\b${funcName}\\b`).test(content)) {
461
+ referenced = true;
462
+ break;
463
+ }
464
+ }
465
+ if (!referenced) {
466
+ features.push({
467
+ category: 'app-exported-but-uncalled',
468
+ filePath: relFilePath,
469
+ functionName: funcName,
470
+ suggestedAction: 'Exported but never imported — wire into a route, component, or remove',
471
+ });
472
+ }
473
+ }
474
+ return features;
475
+ }
476
+ /**
477
+ * Scan for ORM model/entity definitions without corresponding CRUD route handlers.
478
+ *
479
+ * Detects Prisma models, TypeORM @Entity classes, and Drizzle table definitions.
480
+ */
481
+ function scanAppModelsWithoutHandlers(cwd) {
482
+ const features = [];
483
+ const modelNames = [];
484
+ // Prisma schema
485
+ const prismaPath = path.join(cwd, 'prisma', 'schema.prisma');
486
+ const prismaContent = safeReadFile(prismaPath);
487
+ if (prismaContent) {
488
+ const modelPattern = /model\s+(\w+)\s*\{/g;
489
+ let match;
490
+ while ((match = modelPattern.exec(prismaContent)) !== null) {
491
+ modelNames.push({ name: match[1], filePath: 'prisma/schema.prisma' });
492
+ }
493
+ }
494
+ // TypeORM/MikroORM entity decorators and Drizzle table definitions
495
+ const appDirs = _detectAppSourceDirs(cwd);
496
+ const sourceFiles = [];
497
+ for (const dir of appDirs) {
498
+ sourceFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js']));
499
+ }
500
+ for (const file of sourceFiles) {
501
+ const content = safeReadFile(file);
502
+ if (!content)
503
+ continue;
504
+ const relPath = path.relative(cwd, file);
505
+ // @Entity() class ClassName
506
+ const entityPattern = /@Entity\s*\([^)]*\)\s*(?:export\s+)?class\s+(\w+)/g;
507
+ let match;
508
+ while ((match = entityPattern.exec(content)) !== null) {
509
+ modelNames.push({ name: match[1], filePath: relPath });
510
+ }
511
+ // Drizzle: const <tableName> = pgTable/mysqlTable/sqliteTable(...)
512
+ const drizzlePattern = /(?:export\s+)?const\s+(\w+)\s*=\s*(?:pgTable|mysqlTable|sqliteTable)\s*\(/g;
513
+ while ((match = drizzlePattern.exec(content)) !== null) {
514
+ modelNames.push({ name: match[1], filePath: relPath });
515
+ }
516
+ }
517
+ if (modelNames.length === 0)
518
+ return features;
519
+ // Check if each model is referenced in route/handler files
520
+ const allSourceFiles = [];
521
+ for (const dir of appDirs) {
522
+ allSourceFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js', '.tsx', '.jsx']));
523
+ }
524
+ const combinedSource = allSourceFiles
525
+ .map((f) => safeReadFile(f) || '')
526
+ .join('\n');
527
+ for (const model of modelNames) {
528
+ const modelLower = model.name.toLowerCase();
529
+ const hasRoute = new RegExp(`['"\`/]${modelLower}`, 'i').test(combinedSource) ||
530
+ new RegExp(`${model.name}\\.(find|create|update|delete|save|remove|insert|select)`, 'i').test(combinedSource);
531
+ if (!hasRoute) {
532
+ features.push({
533
+ category: 'app-model-without-handler',
534
+ filePath: model.filePath,
535
+ functionName: model.name,
536
+ suggestedAction: `Model "${model.name}" has no CRUD handlers — add routes or remove unused model`,
537
+ });
538
+ }
539
+ }
540
+ return features;
541
+ }
542
+ /**
543
+ * Scan for React/Vue components that are defined but never imported anywhere.
544
+ */
545
+ function scanAppComponentsWithoutImport(cwd) {
546
+ const features = [];
547
+ const appDirs = _detectAppSourceDirs(cwd);
548
+ if (appDirs.length === 0)
549
+ return [];
550
+ const componentFiles = [];
551
+ for (const dir of appDirs) {
552
+ componentFiles.push(..._collectFiles(path.join(cwd, dir), ['.tsx', '.jsx']));
553
+ }
554
+ const componentMap = new Map();
555
+ for (const file of componentFiles) {
556
+ const basename = path.basename(file);
557
+ if (basename.includes('.test.') || basename.includes('.spec.'))
558
+ continue;
559
+ if (basename.startsWith('index.'))
560
+ continue;
561
+ const content = safeReadFile(file);
562
+ if (!content)
563
+ continue;
564
+ const relPath = path.relative(cwd, file);
565
+ // Detect: export default function ComponentName / export function ComponentName
566
+ // Only PascalCase names (React components)
567
+ const componentPattern = /export\s+(?:default\s+)?(?:function|const)\s+([A-Z]\w+)/g;
568
+ let match;
569
+ while ((match = componentPattern.exec(content)) !== null) {
570
+ componentMap.set(match[1], relPath);
571
+ }
572
+ }
573
+ // Search for imports of each component
574
+ const allFiles = [];
575
+ for (const dir of appDirs) {
576
+ allFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js', '.tsx', '.jsx']));
577
+ }
578
+ for (const [componentName, relFilePath] of componentMap) {
579
+ const absFilePath = path.join(cwd, relFilePath);
580
+ let referenced = false;
581
+ for (const searchFile of allFiles) {
582
+ if (path.resolve(searchFile) === path.resolve(absFilePath))
583
+ continue;
584
+ const content = safeReadFile(searchFile);
585
+ if (!content)
586
+ continue;
587
+ if (new RegExp(`import\\s+.*\\b${componentName}\\b`).test(content) ||
588
+ new RegExp(`<${componentName}[\\s/>]`).test(content)) {
589
+ referenced = true;
590
+ break;
591
+ }
592
+ }
593
+ if (!referenced) {
594
+ features.push({
595
+ category: 'app-component-without-import',
596
+ filePath: relFilePath,
597
+ functionName: componentName,
598
+ suggestedAction: `Component "${componentName}" is never imported — wire into a page or remove`,
599
+ });
600
+ }
601
+ }
602
+ return features;
603
+ }
604
+ // ─── Generic CLI/Library Scanners ────────────────────────────────────────────
605
+ /** Check if a directory exists. */
606
+ function _dirExists(dirPath) {
607
+ try {
608
+ return fs.statSync(dirPath).isDirectory();
609
+ }
610
+ catch {
611
+ return false;
612
+ }
613
+ }
614
+ /**
615
+ * Scan lib/*.ts for exported functions that have no corresponding test.
616
+ * A function is considered tested if its name appears in any tests/ file.
617
+ */
618
+ function scanLibExportedWithoutTest(cwd) {
619
+ const libDir = path.join(cwd, 'lib');
620
+ const testDirs = ['tests', 'test', '__tests__'];
621
+ const testFiles = [];
622
+ for (const dir of testDirs) {
623
+ testFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js']));
624
+ }
625
+ if (testFiles.length === 0)
626
+ return [];
627
+ const combinedTests = testFiles
628
+ .map((f) => safeReadFile(f) || '')
629
+ .join('\n');
630
+ let libEntries;
631
+ try {
632
+ libEntries = fs.readdirSync(libDir, { withFileTypes: true });
633
+ }
634
+ catch {
635
+ return [];
636
+ }
637
+ const features = [];
638
+ for (const entry of libEntries) {
639
+ if (!entry.isFile() || !entry.name.endsWith('.ts'))
640
+ continue;
641
+ const filePath = path.join(libDir, entry.name);
642
+ const content = safeReadFile(filePath);
643
+ if (!content)
644
+ continue;
645
+ const exports = _extractExports(content);
646
+ for (const funcName of exports) {
647
+ if (!new RegExp(`\\b${funcName}\\b`).test(combinedTests)) {
648
+ features.push({
649
+ category: 'lib-exported-without-test',
650
+ filePath: path.relative(cwd, filePath),
651
+ functionName: funcName,
652
+ suggestedAction: `Add test coverage for ${funcName}`,
653
+ });
654
+ }
655
+ }
656
+ }
657
+ return features;
658
+ }
659
+ /**
660
+ * Scan bin/*.ts entry points for scripts that have no corresponding test.
661
+ * Checks if the bin file's basename (without extension) appears in any test filename.
662
+ */
663
+ function scanBinEntriesWithoutTest(cwd) {
664
+ const binDir = path.join(cwd, 'bin');
665
+ const testDirs = ['tests', 'test', '__tests__'];
666
+ const testFileNames = new Set();
667
+ for (const dir of testDirs) {
668
+ const files = _collectFiles(path.join(cwd, dir), ['.ts', '.js']);
669
+ for (const f of files) {
670
+ testFileNames.add(path.basename(f).toLowerCase());
671
+ }
672
+ }
673
+ // Also collect all test file content for reference checks
674
+ const testFiles = [];
675
+ for (const dir of testDirs) {
676
+ testFiles.push(..._collectFiles(path.join(cwd, dir), ['.ts', '.js']));
677
+ }
678
+ const combinedTests = testFiles
679
+ .map((f) => safeReadFile(f) || '')
680
+ .join('\n');
681
+ let binEntries;
682
+ try {
683
+ binEntries = fs.readdirSync(binDir, { withFileTypes: true });
684
+ }
685
+ catch {
686
+ return [];
687
+ }
688
+ const features = [];
689
+ for (const entry of binEntries) {
690
+ if (!entry.isFile())
691
+ continue;
692
+ if (!entry.name.endsWith('.ts') && !entry.name.endsWith('.js'))
693
+ continue;
694
+ const baseName = entry.name.replace(/\.(ts|js)$/, '');
695
+ // Check if any test file references this bin entry
696
+ const hasTestFile = testFileNames.has(`${baseName}.test.ts`) ||
697
+ testFileNames.has(`${baseName}.test.js`) ||
698
+ testFileNames.has(`${baseName}.spec.ts`);
699
+ const hasReference = new RegExp(`\\b${baseName}\\b`).test(combinedTests);
700
+ if (!hasTestFile && !hasReference) {
701
+ features.push({
702
+ category: 'bin-entry-without-test',
703
+ filePath: path.relative(cwd, path.join(binDir, entry.name)),
704
+ functionName: baseName,
705
+ suggestedAction: `Add integration test for bin/${entry.name}`,
706
+ });
707
+ }
708
+ }
709
+ return features;
710
+ }
711
+ // ─── Claude Code Plugin Scanners ─────────────────────────────────────────────
712
+ /**
713
+ * Detect if this is a Claude Code plugin project by checking for
714
+ * commands/ and/or agents/ directories with .md files.
715
+ */
716
+ function _isPluginProject(cwd) {
717
+ const commandsDir = path.join(cwd, 'commands');
718
+ const agentsDir = path.join(cwd, 'agents');
719
+ return _dirExists(commandsDir) || _dirExists(agentsDir);
720
+ }
721
+ /**
722
+ * Read .md filenames from a directory, returning basenames without extension.
723
+ */
724
+ function _readMdNames(dir) {
725
+ try {
726
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
727
+ return entries
728
+ .filter((e) => e.isFile() && e.name.endsWith('.md'))
729
+ .map((e) => e.name.replace(/\.md$/, ''));
730
+ }
731
+ catch {
732
+ return [];
733
+ }
734
+ }
735
+ /**
736
+ * Extract the set of registered command names from the CLI registry file.
737
+ * Reads lib/cli/index.ts (or similar) and parses TOOL_COMMANDS and AGENT_COMMANDS sets.
738
+ */
739
+ function _extractRegisteredCommands(cwd) {
740
+ const registered = new Set();
741
+ const candidates = [
742
+ path.join(cwd, 'lib', 'cli', 'index.ts'),
743
+ path.join(cwd, 'lib', 'cli', 'index.js'),
744
+ path.join(cwd, 'lib', 'cli.ts'),
745
+ path.join(cwd, 'lib', 'cli.js'),
746
+ ];
747
+ for (const candidate of candidates) {
748
+ const content = safeReadFile(candidate);
749
+ if (!content)
750
+ continue;
751
+ // Match strings inside Set([...]) or array literals
752
+ const stringPattern = /['"]([a-z][\w-]*)['"],?/g;
753
+ let match;
754
+ while ((match = stringPattern.exec(content)) !== null) {
755
+ registered.add(match[1]);
756
+ }
757
+ }
758
+ return registered;
759
+ }
760
+ /**
761
+ * Extract agent names referenced by commands via subagent_type="grd:grd-{name}" patterns.
762
+ */
763
+ function _extractReferencedAgents(cwd) {
764
+ const referenced = new Set();
765
+ const commandsDir = path.join(cwd, 'commands');
766
+ const commandFiles = _collectFiles(commandsDir, ['.md']);
767
+ for (const file of commandFiles) {
768
+ const content = safeReadFile(file);
769
+ if (!content)
770
+ continue;
771
+ // Match subagent_type="grd:grd-{name}" or subagent_type="grd:{name}"
772
+ const agentRefPattern = /subagent_type\s*[=:]\s*["']grd:(?:grd-)?([^"']+)["']/g;
773
+ let match;
774
+ while ((match = agentRefPattern.exec(content)) !== null) {
775
+ referenced.add(match[1]);
776
+ }
777
+ // Also match Agent tool calls with description referencing agents
778
+ const agentFilePattern = /agents\/grd-([^."'\s]+)\.md/g;
779
+ while ((match = agentFilePattern.exec(content)) !== null) {
780
+ referenced.add(match[1]);
781
+ }
782
+ }
783
+ // Also check lib/ files for agent references
784
+ const libFiles = _collectFiles(path.join(cwd, 'lib'), ['.ts', '.js']);
785
+ for (const file of libFiles) {
786
+ const content = safeReadFile(file);
787
+ if (!content)
788
+ continue;
789
+ const agentRefPattern = /subagent_type\s*[=:]\s*["']grd:(?:grd-)?([^"']+)["']/g;
790
+ let match;
791
+ while ((match = agentRefPattern.exec(content)) !== null) {
792
+ referenced.add(match[1]);
793
+ }
794
+ }
795
+ return referenced;
796
+ }
797
+ /**
798
+ * Scan for commands/ .md files that are not registered in the CLI command registry.
799
+ */
800
+ function scanCommandsWithoutRegistration(cwd) {
801
+ const commandNames = _readMdNames(path.join(cwd, 'commands'));
802
+ if (commandNames.length === 0)
803
+ return [];
804
+ const registered = _extractRegisteredCommands(cwd);
805
+ if (registered.size === 0)
806
+ return []; // No registry found — skip
807
+ const features = [];
808
+ for (const name of commandNames) {
809
+ if (!registered.has(name)) {
810
+ features.push({
811
+ category: 'command-without-registration',
812
+ filePath: `commands/${name}.md`,
813
+ functionName: name,
814
+ suggestedAction: `Register "${name}" in TOOL_COMMANDS or AGENT_COMMANDS in the CLI registry`,
815
+ });
816
+ }
817
+ }
818
+ return features;
819
+ }
820
+ /**
821
+ * Scan for agents/ .md files that are not referenced by any command.
822
+ */
823
+ function scanAgentsWithoutCommand(cwd) {
824
+ const agentNames = _readMdNames(path.join(cwd, 'agents'));
825
+ if (agentNames.length === 0)
826
+ return [];
827
+ const referenced = _extractReferencedAgents(cwd);
828
+ const features = [];
829
+ for (const name of agentNames) {
830
+ // Normalize: agent files are grd-{name}.md, references may be just {name} or grd-{name}
831
+ const shortName = name.replace(/^grd-/, '');
832
+ if (!referenced.has(shortName) && !referenced.has(name)) {
833
+ features.push({
834
+ category: 'agent-without-command',
835
+ filePath: `agents/${name}.md`,
836
+ functionName: name,
837
+ suggestedAction: `Agent "${name}" is not spawned by any command — wire it via subagent_type or remove`,
838
+ });
839
+ }
840
+ }
841
+ return features;
842
+ }
843
+ /**
844
+ * Scan commands for agent references that point to non-existent agent files.
845
+ */
846
+ function scanCommandsWithMissingAgents(cwd) {
847
+ const commandsDir = path.join(cwd, 'commands');
848
+ const agentsDir = path.join(cwd, 'agents');
849
+ const commandFiles = _collectFiles(commandsDir, ['.md']);
850
+ if (commandFiles.length === 0)
851
+ return [];
852
+ const existingAgents = new Set(_readMdNames(agentsDir));
853
+ const features = [];
854
+ const seen = new Set();
855
+ for (const file of commandFiles) {
856
+ const content = safeReadFile(file);
857
+ if (!content)
858
+ continue;
859
+ const relPath = path.relative(cwd, file);
860
+ // Match subagent_type references
861
+ const agentRefPattern = /subagent_type\s*[=:]\s*["']grd:(?:grd-)?([^"']+)["']/g;
862
+ let match;
863
+ while ((match = agentRefPattern.exec(content)) !== null) {
864
+ const agentName = match[1];
865
+ const fullName = agentName.startsWith('grd-') ? agentName : `grd-${agentName}`;
866
+ if (!existingAgents.has(fullName) && !seen.has(fullName)) {
867
+ seen.add(fullName);
868
+ features.push({
869
+ category: 'command-without-agent-file',
870
+ filePath: relPath,
871
+ functionName: fullName,
872
+ suggestedAction: `Command references agent "${fullName}" but agents/${fullName}.md does not exist`,
873
+ });
874
+ }
875
+ }
876
+ }
877
+ return features;
878
+ }
879
+ // ─── Public Orchestrator ─────────────────────────────────────────────────────
880
+ /**
881
+ * Discover all unwired features in the codebase using pure filesystem analysis.
882
+ *
883
+ * Runs structural scanners when matching directories exist (lib/, bin/, tests/)
884
+ * AND application-aware scanners that detect routes, exports, models, and
885
+ * components in the target project. Works for web apps, CLI tools, and libraries.
886
+ *
887
+ * NEVER spawns child processes — pure fs.readFileSync/readdirSync only.
888
+ *
889
+ * @param cwd - Absolute path to the project root
890
+ * @returns Array of UnwiredFeature objects describing integration gaps
891
+ */
892
+ function discoverUnwiredFeatures(cwd) {
893
+ const allFeatures = [];
894
+ // Structural scanners — run when matching directories exist (not gated to GRD)
895
+ const hasLib = _dirExists(path.join(cwd, 'lib'));
896
+ const hasBin = _dirExists(path.join(cwd, 'bin'));
897
+ const hasMcpServer = (() => {
898
+ try {
899
+ return fs.statSync(path.join(cwd, 'lib', 'mcp-server.ts')).isFile();
900
+ }
901
+ catch {
902
+ return false;
903
+ }
904
+ })();
905
+ if (hasLib) {
906
+ allFeatures.push(...scanExportedButUncalled(cwd));
907
+ allFeatures.push(...scanLibExportedWithoutTest(cwd));
908
+ }
909
+ if (hasLib || hasBin) {
910
+ allFeatures.push(...scanConfigWithoutSurface(cwd));
911
+ }
912
+ if (hasMcpServer) {
913
+ allFeatures.push(...scanEndpointsWithoutTests(cwd));
914
+ }
915
+ if (hasBin) {
916
+ allFeatures.push(...scanBinEntriesWithoutTest(cwd));
917
+ }
918
+ // Plugin-aware scanners — run when commands/ or agents/ exist
919
+ if (_isPluginProject(cwd)) {
920
+ allFeatures.push(...scanCommandsWithoutRegistration(cwd), ...scanAgentsWithoutCommand(cwd), ...scanCommandsWithMissingAgents(cwd));
921
+ }
922
+ // Application-aware scanners — always run
923
+ allFeatures.push(...scanAppRoutes(cwd), ...scanAppExportedButUncalled(cwd), ...scanAppModelsWithoutHandlers(cwd), ...scanAppComponentsWithoutImport(cwd));
924
+ allFeatures.sort((a, b) => {
925
+ const catCmp = a.category.localeCompare(b.category);
926
+ if (catCmp !== 0)
927
+ return catCmp;
928
+ return a.filePath.localeCompare(b.filePath);
929
+ });
930
+ return allFeatures;
931
+ }
932
+ // ─── Exports ─────────────────────────────────────────────────────────────────
933
+ module.exports = { discoverUnwiredFeatures };
934
+ //# sourceMappingURL=discovery.js.map