@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,204 @@
1
+ 'use strict';
2
+
3
+ /** GRD Commands/Estimate -- Token cost preview for a phase before execution */
4
+
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ const {
10
+ output,
11
+ error,
12
+ findPhaseInternal,
13
+ loadConfig,
14
+ }: {
15
+ output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
16
+ error: (message: string) => never;
17
+ findPhaseInternal: (cwd: string, phase: string) => import('../types').PhaseInfo | null;
18
+ loadConfig: (cwd: string) => { model_profile?: string; [key: string]: unknown };
19
+ } = require('../utils');
20
+
21
+ // ─── Domain Types ────────────────────────────────────────────────────────────
22
+
23
+ interface PlanEstimate {
24
+ plan_file: string;
25
+ wave: number;
26
+ agent_type: string;
27
+ effort: string;
28
+ estimated_tokens: number;
29
+ estimated_usd: number;
30
+ }
31
+
32
+ interface WaveEstimate {
33
+ wave: number;
34
+ plans: PlanEstimate[];
35
+ wave_tokens: number;
36
+ wave_usd: number;
37
+ }
38
+
39
+ interface EstimateResult {
40
+ phase: string;
41
+ model_profile: string;
42
+ wave_count: number;
43
+ total_plans: number;
44
+ total_tokens: number;
45
+ total_usd: number;
46
+ waves: WaveEstimate[];
47
+ note: string;
48
+ }
49
+
50
+ // ─── Token + USD Bands ───────────────────────────────────────────────────────
51
+
52
+ // Effort-level token bands (input+output combined estimate)
53
+ const EFFORT_TOKENS: Record<string, number> = {
54
+ high: 200_000,
55
+ medium: 80_000,
56
+ low: 30_000,
57
+ };
58
+
59
+ // Approximate per-token cost in USD by model profile (blended input+output)
60
+ // Based on claude-sonnet-4 and claude-opus-4 pricing (illustrative)
61
+ const PROFILE_COST_PER_TOKEN: Record<string, number> = {
62
+ quality: 15 / 1_000_000, // ~opus tier
63
+ balanced: 3 / 1_000_000, // ~sonnet tier
64
+ budget: 0.8 / 1_000_000, // ~haiku tier
65
+ };
66
+
67
+ // Effort level resolved per agent type. Unknown agents default to 'medium'.
68
+ const AGENT_EFFORT_DEFAULTS: Record<string, Record<string, string>> = {
69
+ 'grd-planner': { quality: 'high', balanced: 'high', budget: 'low' },
70
+ 'grd-executor': { quality: 'high', balanced: 'medium', budget: 'low' },
71
+ 'grd-verifier': { quality: 'medium', balanced: 'low', budget: 'low' },
72
+ 'grd-debugger': { quality: 'high', balanced: 'medium', budget: 'low' },
73
+ 'grd-phase-researcher': { quality: 'high', balanced: 'medium', budget: 'low' },
74
+ 'grd-codebase-mapper': { quality: 'medium', balanced: 'low', budget: 'low' },
75
+ 'grd-plan-checker': { quality: 'medium', balanced: 'medium', budget: 'low' },
76
+ 'grd-surveyor': { quality: 'medium', balanced: 'medium', budget: 'low' },
77
+ 'grd-deep-diver': { quality: 'high', balanced: 'medium', budget: 'low' },
78
+ 'grd-code-reviewer': { quality: 'high', balanced: 'medium', budget: 'low' },
79
+ };
80
+
81
+ function resolveEffort(agentType: string, profile: string): string {
82
+ const agentMap = AGENT_EFFORT_DEFAULTS[agentType];
83
+ if (!agentMap) return 'medium';
84
+ return agentMap[profile] || agentMap['balanced'] || 'medium';
85
+ }
86
+
87
+ // ─── Estimate ────────────────────────────────────────────────────────────────
88
+
89
+ /**
90
+ * CLI command: Preview token cost and agent dispatch plan for a phase before execution.
91
+ *
92
+ * Reads all plan files for phase N, groups by wave, maps effort levels to token bands
93
+ * using the project model_profile from config.json, and outputs a per-wave cost table.
94
+ *
95
+ * @param cwd - Project working directory
96
+ * @param phase - Phase number (e.g., "3" or "03")
97
+ * @param raw - Output raw text instead of JSON
98
+ */
99
+ function cmdEstimate(cwd: string, phase: string, raw: boolean): void {
100
+ if (!phase) {
101
+ error('phase required. Usage: gd estimate <phase>');
102
+ return;
103
+ }
104
+
105
+ const phaseInfo = findPhaseInternal(cwd, phase);
106
+ if (!phaseInfo || !phaseInfo.found) {
107
+ error(`Phase ${phase} not found`);
108
+ }
109
+
110
+ let modelProfile = 'balanced';
111
+ try {
112
+ const config = loadConfig(cwd);
113
+ if (config.model_profile && typeof config.model_profile === 'string') {
114
+ modelProfile = config.model_profile;
115
+ }
116
+ } catch {
117
+ // Config unavailable — use default
118
+ }
119
+
120
+ const costPerToken = PROFILE_COST_PER_TOKEN[modelProfile] ?? PROFILE_COST_PER_TOKEN['balanced'];
121
+
122
+ const phaseDir = path.join(cwd, (phaseInfo as import('../types').PhaseInfo).directory);
123
+ // Read plan files
124
+ let planFiles: string[] = [];
125
+ try {
126
+ planFiles = (fs.readdirSync(phaseDir) as string[])
127
+ .filter((f: string) => f.endsWith('-PLAN.md') || f === 'PLAN.md')
128
+ .sort();
129
+ } catch {
130
+ error(`Cannot read phase directory: ${phaseDir}`);
131
+ }
132
+
133
+ const waveMap = new Map<number, PlanEstimate[]>();
134
+
135
+ for (const file of planFiles) {
136
+ const filePath = path.join(phaseDir, file);
137
+ let content: string;
138
+ try { content = fs.readFileSync(filePath, 'utf-8') as string; } catch { continue; }
139
+
140
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
141
+ const fm = fmMatch ? fmMatch[1] : '';
142
+
143
+ const waveMatch = fm.match(/^wave:\s*(\d+)/m);
144
+ const waveNum = waveMatch ? parseInt(waveMatch[1], 10) : 1;
145
+
146
+ const agentMatch = fm.match(/^agent_type:\s*(.+)$/m);
147
+ const agentType = agentMatch ? agentMatch[1].trim() : 'grd-executor';
148
+
149
+ const effort = resolveEffort(agentType, modelProfile);
150
+ const tokens = EFFORT_TOKENS[effort] ?? EFFORT_TOKENS['medium'];
151
+ const usd = tokens * costPerToken;
152
+
153
+ const estimate: PlanEstimate = { plan_file: file, wave: waveNum, agent_type: agentType, effort, estimated_tokens: tokens, estimated_usd: usd };
154
+ const bucket = waveMap.get(waveNum) ?? [];
155
+ bucket.push(estimate);
156
+ waveMap.set(waveNum, bucket);
157
+ }
158
+
159
+ const waves: WaveEstimate[] = Array.from(waveMap.entries())
160
+ .sort(([a], [b]) => a - b)
161
+ .map(([wave, plans]) => ({
162
+ wave,
163
+ plans,
164
+ wave_tokens: plans.reduce((s, p) => s + p.estimated_tokens, 0),
165
+ wave_usd: plans.reduce((s, p) => s + p.estimated_usd, 0),
166
+ }));
167
+
168
+ const totalTokens = waves.reduce((s, w) => s + w.wave_tokens, 0);
169
+ const totalUsd = waves.reduce((s, w) => s + w.wave_usd, 0);
170
+ const totalPlans = waves.reduce((s, w) => s + w.plans.length, 0);
171
+
172
+ const result: EstimateResult = {
173
+ phase,
174
+ model_profile: modelProfile,
175
+ wave_count: waves.length,
176
+ total_plans: totalPlans,
177
+ total_tokens: totalTokens,
178
+ total_usd: Math.round(totalUsd * 100) / 100,
179
+ waves,
180
+ note: 'Token estimates are approximate. Actual usage depends on context size and agent behavior.',
181
+ };
182
+
183
+ if (raw) {
184
+ const lines = [
185
+ `Phase ${phase} cost estimate [${modelProfile} profile]`,
186
+ `${'─'.repeat(60)}`,
187
+ ];
188
+ for (const w of waves) {
189
+ lines.push(`Wave ${w.wave}: ${w.plans.length} plan(s) — ${(w.wave_tokens / 1000).toFixed(0)}K tokens ≈ $${w.wave_usd.toFixed(2)}`);
190
+ for (const p of w.plans) {
191
+ lines.push(` ${p.plan_file} [${p.agent_type}/${p.effort}] ${(p.estimated_tokens / 1000).toFixed(0)}K tokens`);
192
+ }
193
+ }
194
+ lines.push(`${'─'.repeat(60)}`);
195
+ lines.push(`Total: ${totalPlans} plans, ${(totalTokens / 1000).toFixed(0)}K tokens ≈ $${totalUsd.toFixed(2)}`);
196
+ output(result, raw, lines.join('\n'));
197
+ } else {
198
+ output(result, raw, `Phase ${phase}: ${totalPlans} plans, ~${(totalTokens / 1000).toFixed(0)}K tokens, ~$${totalUsd.toFixed(2)} (${modelProfile})`);
199
+ }
200
+ }
201
+
202
+ // ─── Exports ─────────────────────────────────────────────────────────────────
203
+
204
+ module.exports = { cmdEstimate };
@@ -0,0 +1,252 @@
1
+ 'use strict';
2
+
3
+ /** GRD Commands/EvalDiff -- Side-by-side EVAL.md metric comparison across phases */
4
+
5
+ const fs = require('fs') as typeof import('fs');
6
+ const path = require('path') as typeof import('path');
7
+
8
+ const {
9
+ output,
10
+ error,
11
+ }: {
12
+ output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
13
+ error: (msg: string) => never;
14
+ } = require('../utils');
15
+
16
+ const {
17
+ phasesDir: getPhasesDirPath,
18
+ }: {
19
+ phasesDir: (cwd: string, milestone?: string | null) => string;
20
+ } = require('../paths');
21
+
22
+ interface MetricDelta {
23
+ metric: string;
24
+ value_a: number;
25
+ value_b: number;
26
+ delta: number;
27
+ delta_pct: number;
28
+ direction: 'improved' | 'regressed' | 'unchanged';
29
+ }
30
+
31
+ interface EvalDiffResult {
32
+ phase_a: string;
33
+ phase_b: string;
34
+ metrics_in_a: number;
35
+ metrics_in_b: number;
36
+ common_metrics: number;
37
+ deltas: MetricDelta[];
38
+ }
39
+
40
+ function _findPhaseDir(cwd: string, phaseNum: string): string | null {
41
+ const phasesPath = getPhasesDirPath(cwd);
42
+ const normalized = phaseNum.padStart(2, '0');
43
+ try {
44
+ const entries = fs.readdirSync(phasesPath, { withFileTypes: true }) as import('fs').Dirent[];
45
+ const match = entries.find(
46
+ (e) =>
47
+ e.isDirectory() &&
48
+ (e.name.startsWith(normalized + '-') || e.name.startsWith(phaseNum + '-'))
49
+ );
50
+ return match ? path.join(phasesPath, match.name) : null;
51
+ } catch {
52
+ return null;
53
+ }
54
+ }
55
+
56
+ function _findEvalFile(phaseDir: string): string | null {
57
+ try {
58
+ const files = fs.readdirSync(phaseDir) as string[];
59
+ const evalFile = files.find((f: string) => f.endsWith('-EVAL.md') || f === 'EVAL.md');
60
+ return evalFile ? path.join(phaseDir, evalFile) : null;
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+
66
+ function _parseMetrics(content: string): Record<string, number> {
67
+ const metrics: Record<string, number> = {};
68
+ const re = /\b([A-Za-z][A-Za-z0-9_\-/ ]{0,30}):\s*([\d]+(?:\.[\d]+)?)\s*(?:%|dB|ms|s|min)?\b/g;
69
+ for (const m of content.matchAll(re)) {
70
+ const key = m[1].trim().toLowerCase().replace(/\s+/g, '_');
71
+ const val = parseFloat(m[2]);
72
+ if (!isNaN(val) && key.length > 1) {
73
+ metrics[key] = val;
74
+ }
75
+ }
76
+ return metrics;
77
+ }
78
+
79
+ function _resolveLatestTwoPhases(cwd: string): [string, string] | null {
80
+ const phasesPath = getPhasesDirPath(cwd);
81
+ try {
82
+ // Codex r8 P2: only consider phases that actually have EVAL.md.
83
+ // Picking the last two by name fails when the newest phases are
84
+ // still planned/in-progress (no EVAL.md yet).
85
+ const dirs = (fs.readdirSync(phasesPath, { withFileTypes: true }) as import('fs').Dirent[])
86
+ .filter((e) => e.isDirectory())
87
+ .map((e) => e.name)
88
+ .filter((n) => /^\d{2}/.test(n))
89
+ .filter((n) => {
90
+ // Codex r9 P2: phase dirs commonly use prefixed EVAL names like
91
+ // `100-EVAL.md`. Match both forms (same as _findEvalFile).
92
+ try {
93
+ return (fs.readdirSync(path.join(phasesPath, n)) as string[]).some(
94
+ (f: string) => f === 'EVAL.md' || /-EVAL\.md$/.test(f)
95
+ );
96
+ } catch {
97
+ return false;
98
+ }
99
+ })
100
+ // Codex r13 P2: lexicographic sort puts `100-...` before `99-...`.
101
+ // Sort by numeric prefix; ties broken lexicographically as a
102
+ // safety net.
103
+ .sort((a, b) => {
104
+ const na = parseInt(a.match(/^(\d+)/)?.[1] ?? '0', 10);
105
+ const nb = parseInt(b.match(/^(\d+)/)?.[1] ?? '0', 10);
106
+ if (na !== nb) return na - nb;
107
+ return a.localeCompare(b);
108
+ });
109
+ if (dirs.length < 2) return null;
110
+ const last = dirs[dirs.length - 1].match(/^(\d+)/)?.[1] ?? '';
111
+ const secondLast = dirs[dirs.length - 2].match(/^(\d+)/)?.[1] ?? '';
112
+ return secondLast && last ? [secondLast, last] : null;
113
+ } catch {
114
+ return null;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * CLI command: Compare EVAL.md metrics between two phases side-by-side.
120
+ * Use 'latest' as phaseB to auto-compare the last two completed phases.
121
+ */
122
+ function cmdEvalDiff(cwd: string, phaseA: string, phaseB: string, raw: boolean): void {
123
+ if (!phaseA || !phaseB) {
124
+ error('Usage: gd eval diff <phaseA> <phaseB> — or: gd eval diff latest');
125
+ }
126
+
127
+ let resolvedA = phaseA;
128
+ let resolvedB = phaseB;
129
+
130
+ // Codex r12 P2: only resolve sides that are literally `latest`. The
131
+ // prior branch overwrote both sides whenever either was `latest`,
132
+ // so `gd eval diff 5 latest` discarded the explicit `5`. When both
133
+ // are `latest`, fall back to the previous behaviour (last two with
134
+ // EVAL.md). When only one is `latest`, pick the most recent phase
135
+ // with EVAL.md that differs from the explicit side.
136
+ const aLatest = phaseA === 'latest';
137
+ const bLatest = phaseB === 'latest';
138
+ if (aLatest && bLatest) {
139
+ const pair = _resolveLatestTwoPhases(cwd);
140
+ if (!pair) {
141
+ error('Could not find two completed phases with EVAL.md files');
142
+ }
143
+ [resolvedA, resolvedB] = pair!;
144
+ } else if (aLatest || bLatest) {
145
+ const pair = _resolveLatestTwoPhases(cwd);
146
+ if (!pair) {
147
+ error('Could not find a phase with EVAL.md to resolve `latest`');
148
+ }
149
+ // Codex r22 P2: compare phase ids by their numeric value so zero-
150
+ // padding does not cause `05` vs `5` to be treated as different.
151
+ const explicit = aLatest ? phaseB : phaseA;
152
+ const sameNum = (a: string, b: string): boolean => parseInt(a, 10) === parseInt(b, 10);
153
+ const latestResolved = sameNum(pair![1], explicit) ? pair![0] : pair![1];
154
+ if (aLatest) resolvedA = latestResolved;
155
+ else resolvedB = latestResolved;
156
+ }
157
+
158
+ const dirA = _findPhaseDir(cwd, resolvedA);
159
+ const dirB = _findPhaseDir(cwd, resolvedB);
160
+
161
+ if (!dirA) error(`Phase ${resolvedA} directory not found`);
162
+ if (!dirB) error(`Phase ${resolvedB} directory not found`);
163
+
164
+ const evalPathA = _findEvalFile(dirA!);
165
+ const evalPathB = _findEvalFile(dirB!);
166
+
167
+ if (!evalPathA) error(`No EVAL.md found in phase ${resolvedA}`);
168
+ if (!evalPathB) error(`No EVAL.md found in phase ${resolvedB}`);
169
+
170
+ let contentA: string;
171
+ let contentB: string;
172
+ try {
173
+ contentA = fs.readFileSync(evalPathA!, 'utf-8');
174
+ } catch {
175
+ error(`Cannot read EVAL.md for phase ${resolvedA}`);
176
+ return;
177
+ }
178
+ try {
179
+ contentB = fs.readFileSync(evalPathB!, 'utf-8');
180
+ } catch {
181
+ error(`Cannot read EVAL.md for phase ${resolvedB}`);
182
+ return;
183
+ }
184
+
185
+ const metricsA = _parseMetrics(contentA);
186
+ const metricsB = _parseMetrics(contentB);
187
+
188
+ const commonKeys = Object.keys(metricsA).filter((k) => k in metricsB);
189
+
190
+ // Codex r11 P2 + r12 P2: lower-is-better metrics need direction flip.
191
+ // `_parseMetrics` normalizes labels to snake_case (`Response time` →
192
+ // `response_time`), so the regex needs to match underscore-separated
193
+ // tokens too. Normalize underscores to spaces before testing.
194
+ const lowerIsBetterRe = /\b(latency|duration|elapsed|time|error|fail|loss|cost|memory|leak|bytes|ms|seconds?|minutes?)\b/i;
195
+ const deltas: MetricDelta[] = commonKeys.map((metric) => {
196
+ const vA = metricsA[metric];
197
+ const vB = metricsB[metric];
198
+ const delta = vB - vA;
199
+ const lowerBetter = lowerIsBetterRe.test(metric.replace(/_/g, ' '));
200
+ const improvedSign = lowerBetter ? delta < 0 : delta > 0;
201
+ // Codex r27/r29 P2: zero-baseline metrics. Direction comes from
202
+ // delta sign; magnitude can't be expressed as a percentage of 0,
203
+ // so use Infinity (clamped to 999.99 on display so the user sees
204
+ // a huge but bounded value, and so sorting puts these changes at
205
+ // the top instead of burying them at 0%).
206
+ const isZeroBaseline = vA === 0;
207
+ const deltaPct = isZeroBaseline
208
+ ? (delta === 0 ? 0 : Number.POSITIVE_INFINITY)
209
+ : (delta / Math.abs(vA)) * 100;
210
+ const direction: MetricDelta['direction'] = isZeroBaseline
211
+ ? (delta === 0 ? 'unchanged' : improvedSign ? 'improved' : 'regressed')
212
+ : Math.abs(deltaPct) < 0.5 ? 'unchanged' : improvedSign ? 'improved' : 'regressed';
213
+ const displayPct = isZeroBaseline
214
+ ? (delta === 0 ? 0 : (delta > 0 ? 999.99 : -999.99))
215
+ : Math.round(deltaPct * 100) / 100;
216
+ return { metric, value_a: vA, value_b: vB, delta, delta_pct: displayPct, direction };
217
+ });
218
+
219
+ deltas.sort((a, b) => Math.abs(b.delta_pct) - Math.abs(a.delta_pct));
220
+
221
+ const result: EvalDiffResult = {
222
+ phase_a: resolvedA,
223
+ phase_b: resolvedB,
224
+ metrics_in_a: Object.keys(metricsA).length,
225
+ metrics_in_b: Object.keys(metricsB).length,
226
+ common_metrics: commonKeys.length,
227
+ deltas,
228
+ };
229
+
230
+ if (raw) {
231
+ const pad = (s: string, n: number) => s.padEnd(n).slice(0, n);
232
+ const lines = [
233
+ `Eval diff: Phase ${resolvedA} vs Phase ${resolvedB}`,
234
+ `${'─'.repeat(70)}`,
235
+ `${pad('Metric', 30)} ${pad('Phase ' + resolvedA, 12)} ${pad('Phase ' + resolvedB, 12)} Delta`,
236
+ `${'─'.repeat(70)}`,
237
+ ];
238
+ for (const d of deltas) {
239
+ const arrow = d.direction === 'improved' ? '+' : d.direction === 'regressed' ? '-' : ' ';
240
+ lines.push(
241
+ `${pad(d.metric, 30)} ${pad(String(d.value_a), 12)} ${pad(String(d.value_b), 12)} ${arrow}${Math.abs(d.delta_pct).toFixed(1)}%`
242
+ );
243
+ }
244
+ if (deltas.length === 0) lines.push(' No common metrics found.');
245
+ lines.push(`${'─'.repeat(70)}`);
246
+ output(result, raw, lines.join('\n'));
247
+ } else {
248
+ output(result, raw, `${commonKeys.length} common metrics, ${deltas.filter((d) => d.direction === 'regressed').length} regressions`);
249
+ }
250
+ }
251
+
252
+ module.exports = { cmdEvalDiff };
@@ -0,0 +1,213 @@
1
+ 'use strict';
2
+
3
+ /** GRD Commands/Freshness -- Research freshness scanner for RESEARCH.md and LANDSCAPE.md */
4
+
5
+ const fs = require('fs') as typeof import('fs');
6
+ const path = require('path') as typeof import('path');
7
+
8
+ const {
9
+ safeReadFile,
10
+ output,
11
+ error,
12
+ findPhaseInternal,
13
+ }: {
14
+ safeReadFile: (p: string) => string | null;
15
+ output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
16
+ error: (message: string) => never;
17
+ findPhaseInternal: (cwd: string, phase: string) => { found: boolean; directory: string } | null;
18
+ } = require('../utils');
19
+
20
+ const {
21
+ phasesDir: getPhasesDirPath,
22
+ researchDir: getResearchDir,
23
+ currentMilestone,
24
+ }: {
25
+ phasesDir: (cwd: string, milestone?: string | null) => string;
26
+ researchDir: (cwd: string, milestone?: string | null) => string;
27
+ currentMilestone: (cwd: string) => string;
28
+ } = require('../paths');
29
+
30
+ interface FreshnessItem {
31
+ title: string;
32
+ type: 'paper' | 'repo' | 'url';
33
+ url?: string;
34
+ research_date?: string;
35
+ days_since_research: number;
36
+ staleness: 'fresh' | 'aging' | 'stale';
37
+ source_file: string;
38
+ }
39
+
40
+ interface FreshnessResult {
41
+ phase?: string;
42
+ items: FreshnessItem[];
43
+ stale_count: number;
44
+ aging_count: number;
45
+ fresh_count: number;
46
+ files_scanned: number;
47
+ }
48
+
49
+ const STALE_DAYS = 30;
50
+ const AGING_DAYS = 14;
51
+
52
+ function _classifyStaleness(days: number): 'fresh' | 'aging' | 'stale' {
53
+ if (days >= STALE_DAYS) return 'stale';
54
+ if (days >= AGING_DAYS) return 'aging';
55
+ return 'fresh';
56
+ }
57
+
58
+ function _extractResearchDate(content: string): string | undefined {
59
+ // Look for frontmatter date field or explicit "research_date:" line
60
+ const fm = content.match(/^---\n([\s\S]*?)\n---/);
61
+ if (fm) {
62
+ const d = fm[1].match(/(?:date|research_date):\s*(\d{4}-\d{2}-\d{2})/);
63
+ if (d) return d[1];
64
+ }
65
+ const inline = content.match(/research_date:\s*(\d{4}-\d{2}-\d{2})/);
66
+ if (inline) return inline[1];
67
+ return undefined;
68
+ }
69
+
70
+ function _extractCitations(content: string): Array<{ title: string; url?: string; type: 'paper' | 'repo' | 'url' }> {
71
+ const items: Array<{ title: string; url?: string; type: 'paper' | 'repo' | 'url' }> = [];
72
+ const seen = new Set<string>();
73
+
74
+ // arXiv links
75
+ for (const m of content.matchAll(/https?:\/\/arxiv\.org\/abs\/[\d.]+/g)) {
76
+ const url = m[0];
77
+ if (!seen.has(url)) {
78
+ seen.add(url);
79
+ const titleMatch = content.slice(Math.max(0, m.index! - 200), m.index!).match(/#+\s+(.+)$|["']([^"']{5,80})["']/m);
80
+ items.push({ title: titleMatch ? (titleMatch[1] ?? titleMatch[2] ?? url) : url, url, type: 'paper' });
81
+ }
82
+ }
83
+
84
+ // GitHub repos
85
+ for (const m of content.matchAll(/https?:\/\/github\.com\/[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+/g)) {
86
+ const url = m[0].replace(/[)\].,]+$/, '');
87
+ if (!seen.has(url)) {
88
+ seen.add(url);
89
+ const parts = url.split('/');
90
+ items.push({ title: parts.slice(-2).join('/'), url, type: 'repo' });
91
+ }
92
+ }
93
+
94
+ // Markdown headings that look like paper titles (heuristic: ## Title with year)
95
+ for (const m of content.matchAll(/^#{2,3}\s+(.{10,120})\s*\(\d{4}\)/gm)) {
96
+ const title = m[1].trim();
97
+ if (!seen.has(title)) {
98
+ seen.add(title);
99
+ items.push({ title, type: 'paper' });
100
+ }
101
+ }
102
+
103
+ return items;
104
+ }
105
+
106
+ function _scanFile(filePath: string, today: Date): FreshnessItem[] {
107
+ const content = safeReadFile(filePath);
108
+ if (!content) return [];
109
+
110
+ const researchDate = _extractResearchDate(content);
111
+ const citations = _extractCitations(content);
112
+
113
+ const refDate = researchDate ? new Date(researchDate) : null;
114
+ const daysSince = refDate
115
+ ? Math.floor((today.getTime() - refDate.getTime()) / 86400000)
116
+ : 999;
117
+
118
+ return citations.map((c) => ({
119
+ title: c.title,
120
+ type: c.type,
121
+ url: c.url,
122
+ research_date: researchDate,
123
+ days_since_research: daysSince,
124
+ staleness: _classifyStaleness(daysSince),
125
+ source_file: filePath,
126
+ }));
127
+ }
128
+
129
+ /**
130
+ * CLI command: Check research freshness for a phase or all phases.
131
+ *
132
+ * Reads RESEARCH.md and LANDSCAPE.md files, extracts paper titles and
133
+ * GitHub repo URLs, and flags stale citations with days-since-research.
134
+ */
135
+ function cmdFreshness(cwd: string, phaseArg: string | null, raw: boolean): void {
136
+ let milestone: string;
137
+ try {
138
+ milestone = currentMilestone(cwd);
139
+ } catch {
140
+ error('No active milestone found. Run gd init first.');
141
+ }
142
+
143
+ const today = new Date();
144
+ const allItems: FreshnessItem[] = [];
145
+ const filePaths: string[] = [];
146
+
147
+ if (phaseArg) {
148
+ // Codex r2 P2: numeric phase ids resolve through findPhaseInternal.
149
+ const phaseInfo = findPhaseInternal(cwd, phaseArg);
150
+ if (!phaseInfo || !phaseInfo.found) {
151
+ error(`Phase not found: ${phaseArg}`);
152
+ }
153
+ // Codex r4 P2: directory is cwd-relative.
154
+ // Codex r9 P2: phase research artifacts commonly use prefixed names
155
+ // like `83-RESEARCH.md`. Match both bare and prefixed forms.
156
+ const phaseDir = path.join(cwd, phaseInfo!.directory);
157
+ try {
158
+ for (const f of fs.readdirSync(phaseDir) as string[]) {
159
+ if (f === 'RESEARCH.md' || f === 'LANDSCAPE.md' || /-(RESEARCH|LANDSCAPE)\.md$/.test(f)) {
160
+ filePaths.push(path.join(phaseDir, f));
161
+ }
162
+ }
163
+ } catch { /* skip */ }
164
+ } else {
165
+ // Scan all phases and the milestone research dir
166
+ const resDir = getResearchDir(cwd, milestone!);
167
+ for (const f of ['RESEARCH.md', 'LANDSCAPE.md']) {
168
+ const p = path.join(resDir, f);
169
+ if (fs.existsSync(p)) filePaths.push(p);
170
+ }
171
+
172
+ const phasesBase = getPhasesDirPath(cwd, milestone!);
173
+ if (fs.existsSync(phasesBase)) {
174
+ try {
175
+ for (const phaseDir of fs.readdirSync(phasesBase) as string[]) {
176
+ const phaseFull = path.join(phasesBase, phaseDir);
177
+ try {
178
+ for (const f of fs.readdirSync(phaseFull) as string[]) {
179
+ if (f === 'RESEARCH.md' || f === 'LANDSCAPE.md' || /-(RESEARCH|LANDSCAPE)\.md$/.test(f)) {
180
+ filePaths.push(path.join(phaseFull, f));
181
+ }
182
+ }
183
+ } catch { /* skip */ }
184
+ }
185
+ } catch { /* skip */ }
186
+ }
187
+ }
188
+
189
+ if (filePaths.length === 0) {
190
+ output({ items: [], stale_count: 0, aging_count: 0, fresh_count: 0, files_scanned: 0 }, raw, 'No RESEARCH.md or LANDSCAPE.md files found');
191
+ return;
192
+ }
193
+
194
+ for (const fp of filePaths) {
195
+ allItems.push(..._scanFile(fp, today));
196
+ }
197
+
198
+ allItems.sort((a, b) => b.days_since_research - a.days_since_research);
199
+
200
+ const result: FreshnessResult = {
201
+ phase: phaseArg ?? undefined,
202
+ items: allItems,
203
+ stale_count: allItems.filter((i) => i.staleness === 'stale').length,
204
+ aging_count: allItems.filter((i) => i.staleness === 'aging').length,
205
+ fresh_count: allItems.filter((i) => i.staleness === 'fresh').length,
206
+ files_scanned: filePaths.length,
207
+ };
208
+
209
+ const summary = `${filePaths.length} files: ${result.stale_count} stale, ${result.aging_count} aging, ${result.fresh_count} fresh citations`;
210
+ output(result, raw, summary);
211
+ }
212
+
213
+ module.exports = { cmdFreshness };