@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,760 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * GRD Citation Graph -- Parse PAPERS.md files and build typed citation graphs
5
+ *
6
+ * Satisfies REQ-182 (Citation Graph Data Structures), REQ-183 (buildCitationGraph),
7
+ * REQ-184 (Citation Recovery), and REQ-185 (Citation Recovery Tests).
8
+ *
9
+ * Functions:
10
+ * - parseMissingComponents: Parse missing_components sections from PAPERS.md content
11
+ * - parseBorrowedComponents: Parse borrowed_components sections from PAPERS.md content
12
+ * - buildCitationGraph: Read a directory of .md files, construct a CitationGraph,
13
+ * and write per-paper JSON to citations/{slug}.json
14
+ * - resolveCitations: Fetch paper metadata from arXiv/Semantic Scholar APIs
15
+ * - findUnresolved: Return unresolved CitationNodes, optionally filtered by priority
16
+ *
17
+ * @module citations
18
+ */
19
+
20
+ import type {
21
+ CitationNode,
22
+ CitationEdge,
23
+ CitationGraph,
24
+ MissingComponent,
25
+ BorrowedComponent,
26
+ ApiConfig,
27
+ TraversalOptions,
28
+ TraversalResult,
29
+ } from './types';
30
+
31
+ const fs = require('fs') as typeof import('fs');
32
+ const path = require('path') as typeof import('path');
33
+ const { safeReadFile } = require('./utils') as { safeReadFile: (p: string) => string | null };
34
+
35
+ // --- Helpers ------------------------------------------------------------------
36
+
37
+ /**
38
+ * Extract the content of a named section from markdown.
39
+ * Returns the text after `## Section Name` until the next `##` heading or end of file.
40
+ * The sectionName may be a regex pattern (e.g., 'missing.?components').
41
+ */
42
+ function extractSection(content: string, sectionName: string): string {
43
+ const pattern = new RegExp(
44
+ `(?:^|\\n)#{2,3}\\s+${sectionName}[^\\n]*\\n([\\s\\S]*?)(?=\\n#{2,3}\\s|$)`,
45
+ 'i'
46
+ );
47
+ const match = content.match(pattern);
48
+ return match ? match[1].trim() : '';
49
+ }
50
+
51
+ /**
52
+ * Parse a yes/no/true/false string into a boolean.
53
+ */
54
+ function parseBool(value: string): boolean {
55
+ const lower = value.trim().toLowerCase();
56
+ return lower === 'yes' || lower === 'true';
57
+ }
58
+
59
+ // --- parseMissingComponents ---------------------------------------------------
60
+
61
+ /**
62
+ * Parse missing_components section from PAPERS.md content.
63
+ *
64
+ * Supports two formats:
65
+ * Table: | Name | Source Paper | Description | Code Available |
66
+ * List: - **Name**: description (source: paper, code: yes/no)
67
+ *
68
+ * Also supports the plan-specified structured list format:
69
+ * - **name:** ComponentName
70
+ * - source_paper: paper-slug-or-title
71
+ * - description: What the component does
72
+ * - code_available: true|false
73
+ *
74
+ * Returns empty array if no section found or no entries parsed.
75
+ *
76
+ * @param content - Raw markdown content of a PAPERS.md entry
77
+ * @returns Array of MissingComponent objects
78
+ */
79
+ function parseMissingComponents(content: string): MissingComponent[] {
80
+ const section = extractSection(content, 'missing.?components');
81
+ if (!section) return [];
82
+
83
+ const results: MissingComponent[] = [];
84
+
85
+ // Table format: | Name | Source Paper | Description | Code Available |
86
+ // Skip header row and separator row (contains ---)
87
+ const tableRowPattern = /^\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|/gm;
88
+ let tableMatch: RegExpExecArray | null;
89
+ let hasTableRows = false;
90
+ while ((tableMatch = tableRowPattern.exec(section)) !== null) {
91
+ const name = tableMatch[1].trim();
92
+ const sourcePaper = tableMatch[2].trim();
93
+ const description = tableMatch[3].trim();
94
+ const codeAvailableStr = tableMatch[4].trim();
95
+ // Skip header/separator rows
96
+ if (name.toLowerCase() === 'name' || /^[-\s]+$/.test(name)) continue;
97
+ hasTableRows = true;
98
+ results.push({
99
+ name,
100
+ source_paper: sourcePaper,
101
+ description,
102
+ code_available: parseBool(codeAvailableStr),
103
+ });
104
+ }
105
+
106
+ if (hasTableRows) return results;
107
+
108
+ // Structured list format:
109
+ // - **name:** ComponentName
110
+ // - source_paper: paper-slug
111
+ // - description: text
112
+ // - code_available: true/false
113
+ const structuredBlockPattern =
114
+ /^-\s+\*\*name:\*\*\s+(.+)\n(?:\s+-\s+source_paper:\s+(.+)\n)?(?:\s+-\s+description:\s+(.+)\n)?(?:\s+-\s+code_available:\s+(.+))?/gim;
115
+ let structuredMatch: RegExpExecArray | null;
116
+ let hasStructured = false;
117
+ while ((structuredMatch = structuredBlockPattern.exec(section)) !== null) {
118
+ hasStructured = true;
119
+ results.push({
120
+ name: structuredMatch[1].trim(),
121
+ source_paper: structuredMatch[2] ? structuredMatch[2].trim() : '',
122
+ description: structuredMatch[3] ? structuredMatch[3].trim() : '',
123
+ code_available: structuredMatch[4] ? parseBool(structuredMatch[4]) : false,
124
+ });
125
+ }
126
+
127
+ if (hasStructured) return results;
128
+
129
+ // Inline list format: - **Name**: description (source: paper, code: yes/no)
130
+ const listPattern =
131
+ /^-\s+\*\*([^*]+)\*\*\s*:\s*([^(]+)\(source:\s*([^,]+),\s*code:\s*([^)]+)\)/gm;
132
+ let listMatch: RegExpExecArray | null;
133
+ while ((listMatch = listPattern.exec(section)) !== null) {
134
+ results.push({
135
+ name: listMatch[1].trim(),
136
+ source_paper: listMatch[3].trim(),
137
+ description: listMatch[2].trim(),
138
+ code_available: parseBool(listMatch[4]),
139
+ });
140
+ }
141
+
142
+ return results;
143
+ }
144
+
145
+ // --- parseBorrowedComponents --------------------------------------------------
146
+
147
+ /**
148
+ * Parse borrowed_components section from PAPERS.md content.
149
+ *
150
+ * Supports two formats:
151
+ * Table: | Name | Source Paper | Description |
152
+ * List: - **Name**: description (source: paper)
153
+ *
154
+ * The code_available field is not relevant for borrowed components.
155
+ * Returns empty array if no section found or no entries parsed.
156
+ *
157
+ * @param content - Raw markdown content of a PAPERS.md entry
158
+ * @returns Array of BorrowedComponent objects
159
+ */
160
+ function parseBorrowedComponents(content: string): BorrowedComponent[] {
161
+ const section = extractSection(content, 'borrowed.?components');
162
+ if (!section) return [];
163
+
164
+ const results: BorrowedComponent[] = [];
165
+
166
+ // Table format: | Name | Source Paper | Description |
167
+ const tableRowPattern = /^\|([^|]+)\|([^|]+)\|([^|]+)\|/gm;
168
+ let tableMatch: RegExpExecArray | null;
169
+ let hasTableRows = false;
170
+ while ((tableMatch = tableRowPattern.exec(section)) !== null) {
171
+ const name = tableMatch[1].trim();
172
+ const sourcePaper = tableMatch[2].trim();
173
+ const description = tableMatch[3].trim();
174
+ if (name.toLowerCase() === 'name' || /^[-\s]+$/.test(name)) continue;
175
+ hasTableRows = true;
176
+ results.push({ name, source_paper: sourcePaper, description });
177
+ }
178
+
179
+ if (hasTableRows) return results;
180
+
181
+ // Structured list format:
182
+ // - **name:** ComponentName
183
+ // - source_paper: paper-slug
184
+ // - description: text
185
+ const structuredBlockPattern =
186
+ /^-\s+\*\*name:\*\*\s+(.+)\n(?:\s+-\s+source_paper:\s+(.+)\n)?(?:\s+-\s+description:\s+(.+))?/gim;
187
+ let structuredMatch: RegExpExecArray | null;
188
+ let hasStructured = false;
189
+ while ((structuredMatch = structuredBlockPattern.exec(section)) !== null) {
190
+ hasStructured = true;
191
+ results.push({
192
+ name: structuredMatch[1].trim(),
193
+ source_paper: structuredMatch[2] ? structuredMatch[2].trim() : '',
194
+ description: structuredMatch[3] ? structuredMatch[3].trim() : '',
195
+ });
196
+ }
197
+
198
+ if (hasStructured) return results;
199
+
200
+ // Inline list format: - **Name**: description (source: paper)
201
+ const listPattern =
202
+ /^-\s+\*\*([^*]+)\*\*\s*:\s*([^(]+)\(source:\s*([^,)]+)[^)]*\)/gm;
203
+ let listMatch: RegExpExecArray | null;
204
+ while ((listMatch = listPattern.exec(section)) !== null) {
205
+ results.push({
206
+ name: listMatch[1].trim(),
207
+ source_paper: listMatch[3].trim(),
208
+ description: listMatch[2].trim(),
209
+ });
210
+ }
211
+
212
+ return results;
213
+ }
214
+
215
+ // --- buildCitationGraph -------------------------------------------------------
216
+
217
+ /**
218
+ * Read all .md files in papersDir and build a typed CitationGraph.
219
+ *
220
+ * For each file:
221
+ * - Extracts the paper slug from the filename (without .md extension)
222
+ * - Parses missing_components and borrowed_components sections
223
+ * - Creates CitationNode entries for the paper itself and all referenced papers
224
+ * - Creates CitationEdge entries for each dependency relationship
225
+ * - Writes per-paper JSON to {papersDir}/../citations/{paper-slug}.json
226
+ *
227
+ * Priority escalation: MissingComponent with code_available=false => dep node priority='critical'
228
+ * All nodes start with resolved=false.
229
+ * Returns a graph with empty arrays when the directory is empty or missing.
230
+ *
231
+ * @param papersDir - Absolute or relative path to directory containing .md files
232
+ * @returns CitationGraph with nodes, edges, and built_at ISO timestamp
233
+ */
234
+ function buildCitationGraph(papersDir: string): CitationGraph {
235
+ const built_at = new Date().toISOString();
236
+
237
+ // Handle missing or non-directory paths gracefully
238
+ if (!fs.existsSync(papersDir)) {
239
+ return { nodes: [], edges: [], built_at };
240
+ }
241
+
242
+ let files: string[];
243
+ try {
244
+ const entries = fs.readdirSync(papersDir) as string[];
245
+ files = entries.filter((f: string) => f.endsWith('.md'));
246
+ } catch {
247
+ return { nodes: [], edges: [], built_at };
248
+ }
249
+
250
+ if (files.length === 0) {
251
+ return { nodes: [], edges: [], built_at };
252
+ }
253
+
254
+ // Track nodes by slug to avoid duplicates; edges are collected in order
255
+ const nodeMap = new Map<string, CitationNode>();
256
+ const edges: CitationEdge[] = [];
257
+
258
+ /**
259
+ * Ensure a node exists for slug. Escalates priority to 'critical' if needed.
260
+ * Merges component arrays for the primary paper node.
261
+ */
262
+ function ensureNode(
263
+ slug: string,
264
+ priority: 'critical' | 'normal' | 'low' = 'normal',
265
+ missing: MissingComponent[] = [],
266
+ borrowed: BorrowedComponent[] = []
267
+ ): void {
268
+ if (!nodeMap.has(slug)) {
269
+ nodeMap.set(slug, {
270
+ slug,
271
+ title: slug,
272
+ resolved: false,
273
+ priority,
274
+ technique_summary: '',
275
+ missing_components: missing,
276
+ borrowed_components: borrowed,
277
+ });
278
+ } else {
279
+ const existing = nodeMap.get(slug)!;
280
+ if (priority === 'critical') {
281
+ existing.priority = 'critical';
282
+ }
283
+ // Merge component arrays when the primary paper node is registered
284
+ if (missing.length > 0) existing.missing_components = missing;
285
+ if (borrowed.length > 0) existing.borrowed_components = borrowed;
286
+ }
287
+ }
288
+
289
+ for (const file of files) {
290
+ const slug = path.basename(file, '.md');
291
+ const filePath = path.join(papersDir, file);
292
+
293
+ // Use safeReadFile for reading; fall back to empty string on null
294
+ const raw = safeReadFile(filePath);
295
+ const content: string = raw !== null ? raw : '';
296
+
297
+ const missing = parseMissingComponents(content);
298
+ const borrowed = parseBorrowedComponents(content);
299
+
300
+ ensureNode(slug, 'normal', missing, borrowed);
301
+
302
+ for (const component of missing) {
303
+ const depSlug = component.source_paper;
304
+ const depPriority: 'critical' | 'normal' = component.code_available ? 'normal' : 'critical';
305
+ ensureNode(depSlug, depPriority);
306
+ edges.push({
307
+ from_slug: slug,
308
+ to_slug: depSlug,
309
+ type: 'missing',
310
+ component_name: component.name,
311
+ });
312
+ }
313
+
314
+ for (const component of borrowed) {
315
+ const depSlug = component.source_paper;
316
+ ensureNode(depSlug, 'normal');
317
+ edges.push({
318
+ from_slug: slug,
319
+ to_slug: depSlug,
320
+ type: 'borrowed',
321
+ component_name: component.name,
322
+ });
323
+ }
324
+ }
325
+
326
+ const graph: CitationGraph = {
327
+ nodes: Array.from(nodeMap.values()),
328
+ edges,
329
+ built_at,
330
+ };
331
+
332
+ // Write per-paper JSON to {papersDir}/../citations/{paper-slug}.json
333
+ const citationsDir = path.join(papersDir, '..', 'citations');
334
+ try {
335
+ fs.mkdirSync(citationsDir, { recursive: true });
336
+ for (const node of graph.nodes) {
337
+ const jsonPath = path.join(citationsDir, `${node.slug}.json`);
338
+ fs.writeFileSync(jsonPath, JSON.stringify(node, null, 2), 'utf-8');
339
+ }
340
+ } catch {
341
+ // Non-fatal: if we cannot write JSON, still return the complete graph
342
+ }
343
+
344
+ return graph;
345
+ }
346
+
347
+ // --- resolveCitations ---------------------------------------------------------
348
+
349
+ /**
350
+ * Default fetch function using Node's built-in https module.
351
+ * Returns the response body as a string, or null on any error.
352
+ */
353
+ function defaultFetchFn(url: string, _timeoutMs: number): Promise<string | null> {
354
+ return new Promise((resolve) => {
355
+ const https = require('https') as typeof import('https');
356
+ const http = require('http') as typeof import('http');
357
+ const parsed = new URL(url);
358
+ const transport = parsed.protocol === 'https:' ? https : http;
359
+
360
+ try {
361
+ const req = transport.get(url, (res) => {
362
+ if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
363
+ resolve(null);
364
+ return;
365
+ }
366
+ const chunks: Buffer[] = [];
367
+ res.on('data', (chunk: Buffer) => chunks.push(chunk));
368
+ res.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
369
+ res.on('error', () => resolve(null));
370
+ });
371
+ req.on('error', () => resolve(null));
372
+ req.setTimeout(_timeoutMs, () => {
373
+ req.destroy();
374
+ resolve(null);
375
+ });
376
+ } catch {
377
+ resolve(null);
378
+ }
379
+ });
380
+ }
381
+
382
+ /**
383
+ * Extract a text summary from an arXiv Atom XML response.
384
+ * Returns the first 200 chars of the summary element, or null.
385
+ */
386
+ function extractArxivSummary(xml: string): string | null {
387
+ const match = xml.match(/<summary[^>]*>([\s\S]*?)<\/summary>/i);
388
+ if (!match) return null;
389
+ const text = match[1].replace(/\s+/g, ' ').trim();
390
+ return text ? text.slice(0, 200) : null;
391
+ }
392
+
393
+ /**
394
+ * Extract a text abstract from a Semantic Scholar JSON response.
395
+ * Returns the first 200 chars of the abstract field, or null.
396
+ */
397
+ function extractSemanticAbstract(json: string): string | null {
398
+ try {
399
+ const data = JSON.parse(json) as Record<string, unknown>;
400
+ // Response is { data: [ { title, abstract, ... } ] }
401
+ const dataArr = Array.isArray(data.data) ? (data.data as Record<string, unknown>[]) : null;
402
+ if (dataArr && dataArr.length > 0) {
403
+ const abstract = dataArr[0].abstract;
404
+ if (typeof abstract === 'string' && abstract.trim()) {
405
+ return abstract.slice(0, 200);
406
+ }
407
+ }
408
+ } catch {
409
+ // not valid JSON
410
+ }
411
+ return null;
412
+ }
413
+
414
+ /**
415
+ * Iterate over unresolved CitationNodes and attempt to fetch metadata from
416
+ * arXiv and/or Semantic Scholar APIs.
417
+ *
418
+ * Accepts an optional fetchFn for dependency injection (enables mocking in tests).
419
+ * The default fetchFn uses Node's built-in https.get.
420
+ *
421
+ * @param graph - The CitationGraph to update (mutated in place)
422
+ * @param apiConfig - Controls which APIs are queried and timeout behaviour
423
+ * @param fetchFn - Optional injectable fetch function for testing
424
+ * @returns The updated CitationGraph (same reference as input)
425
+ */
426
+ async function resolveCitations(
427
+ graph: CitationGraph,
428
+ apiConfig: ApiConfig,
429
+ fetchFn?: (url: string, timeoutMs: number) => Promise<string | null>
430
+ ): Promise<CitationGraph> {
431
+ const fetch = fetchFn ?? defaultFetchFn;
432
+ const timeoutMs = apiConfig.timeout_ms ?? 5000;
433
+
434
+ for (const node of graph.nodes) {
435
+ if (node.resolved) continue;
436
+
437
+ const titleEncoded = encodeURIComponent(node.title);
438
+ let summary: string | null = null;
439
+
440
+ if (apiConfig.arxiv_enabled) {
441
+ const arxivUrl = `https://export.arxiv.org/api/query?search_query=ti:${titleEncoded}&max_results=1`;
442
+ try {
443
+ const body = await fetch(arxivUrl, timeoutMs);
444
+ if (body) {
445
+ summary = extractArxivSummary(body);
446
+ }
447
+ } catch {
448
+ // non-fatal
449
+ }
450
+ }
451
+
452
+ if (!summary && apiConfig.semantic_scholar_enabled) {
453
+ const ssUrl = `https://api.semanticscholar.org/graph/v1/paper/search?query=${titleEncoded}&limit=1`;
454
+ try {
455
+ const body = await fetch(ssUrl, timeoutMs);
456
+ if (body) {
457
+ summary = extractSemanticAbstract(body);
458
+ }
459
+ } catch {
460
+ // non-fatal
461
+ }
462
+ }
463
+
464
+ if (summary !== null) {
465
+ node.resolved = true;
466
+ node.technique_summary = summary;
467
+ }
468
+ }
469
+
470
+ return graph;
471
+ }
472
+
473
+ // --- findUnresolved -----------------------------------------------------------
474
+
475
+ /**
476
+ * Return all unresolved CitationNodes in the graph.
477
+ * If priority is provided, only nodes with that priority are returned.
478
+ *
479
+ * @param graph - The CitationGraph to search
480
+ * @param priority - Optional priority filter ('critical' | 'normal' | 'low')
481
+ * @returns Array of CitationNode objects where resolved is false
482
+ */
483
+ function findUnresolved(
484
+ graph: CitationGraph,
485
+ priority?: 'critical' | 'normal' | 'low'
486
+ ): CitationNode[] {
487
+ return graph.nodes.filter((node) => {
488
+ if (node.resolved) return false;
489
+ if (priority !== undefined) return node.priority === priority;
490
+ return true;
491
+ });
492
+ }
493
+
494
+ // --- traverseCitationGraph ---------------------------------------------------
495
+
496
+ /**
497
+ * Perform BFS traversal of the citation graph from all root nodes (nodes with
498
+ * no incoming edges), respecting depth and node-count limits.
499
+ *
500
+ * Cycle detection: tracks visited slugs in a Set; any slug already visited is
501
+ * skipped, preventing infinite loops on circular citation chains.
502
+ *
503
+ * Limits:
504
+ * - max_depth: BFS depth from root nodes. Nodes at this depth are visited but
505
+ * their children are not enqueued.
506
+ * - max_nodes: Total node visit cap. Processing halts once total_visited
507
+ * reaches this limit.
508
+ *
509
+ * Unresolved leaves: A node with no outgoing edges in the adjacency map and
510
+ * resolved=false is added to unresolved_leaves.
511
+ *
512
+ * @param graph - The CitationGraph to traverse
513
+ * @param options - Optional partial TraversalOptions (merged with defaults)
514
+ * @returns TraversalResult with visited nodes, traversed edges, and statistics
515
+ */
516
+ function traverseCitationGraph(
517
+ graph: CitationGraph,
518
+ options?: Partial<TraversalOptions>
519
+ ): TraversalResult {
520
+ const opts: Required<Omit<TraversalOptions, 'fetchFn'>> = {
521
+ max_depth: options?.max_depth ?? 3,
522
+ max_nodes: options?.max_nodes ?? 50,
523
+ };
524
+
525
+ const emptyResult: TraversalResult = {
526
+ visited_nodes: [],
527
+ edges_traversed: [],
528
+ unresolved_leaves: [],
529
+ depth_reached: 0,
530
+ total_visited: 0,
531
+ };
532
+
533
+ if (graph.nodes.length === 0) {
534
+ return emptyResult;
535
+ }
536
+
537
+ // Build adjacency map: slug → outgoing edges
538
+ const adjacency = new Map<string, CitationEdge[]>();
539
+ for (const edge of graph.edges) {
540
+ if (!adjacency.has(edge.from_slug)) {
541
+ adjacency.set(edge.from_slug, []);
542
+ }
543
+ adjacency.get(edge.from_slug)!.push(edge);
544
+ }
545
+
546
+ // Build node lookup map: slug → CitationNode
547
+ const nodeMap = new Map<string, CitationNode>();
548
+ for (const node of graph.nodes) {
549
+ nodeMap.set(node.slug, node);
550
+ }
551
+
552
+ // Find root nodes: nodes that appear as from_slug but never as to_slug
553
+ // (i.e., have no incoming edges). If all nodes have incoming edges (e.g., cycle),
554
+ // treat all nodes as roots to avoid empty traversal.
555
+ const hasIncoming = new Set<string>();
556
+ for (const edge of graph.edges) {
557
+ hasIncoming.add(edge.to_slug);
558
+ }
559
+ const rootNodes = graph.nodes.filter((n) => !hasIncoming.has(n.slug));
560
+ const seeds = rootNodes.length > 0 ? rootNodes : graph.nodes;
561
+
562
+ // BFS
563
+ const visited = new Set<string>();
564
+ const visitedNodes: CitationNode[] = [];
565
+ const edgesTraversed: CitationEdge[] = [];
566
+ const unresolvedLeaves: CitationNode[] = [];
567
+ let depthReached = 0;
568
+ let totalVisited = 0;
569
+
570
+ interface QueueEntry {
571
+ node: CitationNode;
572
+ depth: number;
573
+ }
574
+
575
+ const queue: QueueEntry[] = [];
576
+ for (const seed of seeds) {
577
+ if (!visited.has(seed.slug)) {
578
+ visited.add(seed.slug);
579
+ queue.push({ node: seed, depth: 0 });
580
+ }
581
+ }
582
+
583
+ let qi = 0;
584
+ while (qi < queue.length) {
585
+ if (totalVisited >= opts.max_nodes) break;
586
+
587
+ const { node, depth } = queue[qi++];
588
+
589
+ visitedNodes.push(node);
590
+ totalVisited++;
591
+ if (depth > depthReached) depthReached = depth;
592
+
593
+ if (totalVisited >= opts.max_nodes) break;
594
+
595
+ const outgoing = adjacency.get(node.slug) ?? [];
596
+
597
+ // Check if leaf (no outgoing edges)
598
+ if (outgoing.length === 0 && !node.resolved) {
599
+ unresolvedLeaves.push(node);
600
+ }
601
+
602
+ // If at max depth, do not enqueue children
603
+ if (depth >= opts.max_depth) continue;
604
+
605
+ for (const edge of outgoing) {
606
+ const targetNode = nodeMap.get(edge.to_slug);
607
+ if (!targetNode) continue;
608
+ if (visited.has(edge.to_slug)) continue;
609
+ if (totalVisited + (queue.length - qi) >= opts.max_nodes) {
610
+ // Approximate cap: stop enqueuing if we're near the limit
611
+ // (exact cap enforced at dequeue time above)
612
+ }
613
+ visited.add(edge.to_slug);
614
+ edgesTraversed.push(edge);
615
+ queue.push({ node: targetNode, depth: depth + 1 });
616
+ }
617
+ }
618
+
619
+ return {
620
+ visited_nodes: visitedNodes,
621
+ edges_traversed: edgesTraversed,
622
+ unresolved_leaves: unresolvedLeaves,
623
+ depth_reached: depthReached,
624
+ total_visited: totalVisited,
625
+ };
626
+ }
627
+
628
+ // --- resolveTransitiveDeps ---------------------------------------------------
629
+
630
+ /**
631
+ * Expand a CitationGraph by performing BFS traversal and merging all
632
+ * transitively discovered nodes and edges into the graph.
633
+ *
634
+ * Deduplication:
635
+ * - Nodes: only added if their slug is not already in graph.nodes
636
+ * - Edges: only added if not already present (keyed by from_slug + to_slug + component_name)
637
+ *
638
+ * Returns a new CitationGraph (does not mutate the input).
639
+ *
640
+ * @param graph - The CitationGraph to expand
641
+ * @param options - Optional partial TraversalOptions passed to traverseCitationGraph
642
+ * @returns A new CitationGraph with merged transitive nodes and edges
643
+ */
644
+ function resolveTransitiveDeps(
645
+ graph: CitationGraph,
646
+ options?: Partial<TraversalOptions>
647
+ ): CitationGraph {
648
+ const result = traverseCitationGraph(graph, options);
649
+
650
+ // Build set of existing node slugs
651
+ const existingSlugs = new Set(graph.nodes.map((n) => n.slug));
652
+
653
+ // Merge new nodes (not already in graph)
654
+ const newNodes = result.visited_nodes.filter((n) => !existingSlugs.has(n.slug));
655
+ const mergedNodes = [...graph.nodes, ...newNodes];
656
+
657
+ // Build set of existing edge keys for deduplication
658
+ const edgeKey = (e: CitationEdge): string =>
659
+ `${e.from_slug}::${e.to_slug}::${e.component_name}`;
660
+ const existingEdgeKeys = new Set(graph.edges.map(edgeKey));
661
+
662
+ // Merge new edges
663
+ const newEdges = result.edges_traversed.filter((e) => !existingEdgeKeys.has(edgeKey(e)));
664
+ const mergedEdges = [...graph.edges, ...newEdges];
665
+
666
+ return {
667
+ nodes: mergedNodes,
668
+ edges: mergedEdges,
669
+ built_at: new Date().toISOString(),
670
+ };
671
+ }
672
+
673
+ // --- fetchExternalPaper -------------------------------------------------------
674
+
675
+ /**
676
+ * Attempt to auto-retrieve metadata for a single paper slug from external APIs.
677
+ *
678
+ * Uses arXiv-first, Semantic Scholar-fallback strategy (same as resolveCitations),
679
+ * but operates on a single slug rather than iterating over a graph.
680
+ *
681
+ * Accepts an optional fetchFn for dependency injection (enables mocking in tests).
682
+ * The default fetchFn uses Node's built-in https.get with a 5-second timeout.
683
+ *
684
+ * On success: returns a CitationNode with resolved=true and technique_summary populated.
685
+ * On failure (both APIs return null): writes a warning to stderr and returns null.
686
+ * Any thrown error is caught and returns null.
687
+ *
688
+ * @param slug - Paper slug to look up (used as query title)
689
+ * @param fetchFn - Optional injectable fetch function for testing
690
+ * @returns CitationNode with resolved=true on success, null on failure
691
+ */
692
+ async function fetchExternalPaper(
693
+ slug: string,
694
+ fetchFn?: (url: string, timeoutMs: number) => Promise<string | null>
695
+ ): Promise<CitationNode | null> {
696
+ const fetch = fetchFn ?? defaultFetchFn;
697
+ const timeoutMs = 5000;
698
+
699
+ try {
700
+ const slugEncoded = encodeURIComponent(slug);
701
+ let summary: string | null = null;
702
+
703
+ // arXiv-first: search by title
704
+ const arxivUrl = `https://export.arxiv.org/api/query?search_query=ti:${slugEncoded}&max_results=1`;
705
+ try {
706
+ const body = await fetch(arxivUrl, timeoutMs);
707
+ if (body) {
708
+ summary = extractArxivSummary(body);
709
+ }
710
+ } catch {
711
+ // non-fatal
712
+ }
713
+
714
+ // Semantic Scholar fallback: only if arXiv returned no summary
715
+ if (summary === null) {
716
+ const ssUrl = `https://api.semanticscholar.org/graph/v1/paper/search?query=${slugEncoded}&limit=1`;
717
+ try {
718
+ const body = await fetch(ssUrl, timeoutMs);
719
+ if (body) {
720
+ summary = extractSemanticAbstract(body);
721
+ }
722
+ } catch {
723
+ // non-fatal
724
+ }
725
+ }
726
+
727
+ if (summary !== null) {
728
+ return {
729
+ slug,
730
+ title: slug,
731
+ resolved: true,
732
+ priority: 'normal',
733
+ technique_summary: summary,
734
+ missing_components: [],
735
+ borrowed_components: [],
736
+ };
737
+ }
738
+
739
+ // Both APIs failed — warn and return null
740
+ process.stderr.write(
741
+ `[grd] WARNING: fetchExternalPaper: could not resolve "${slug}" from arXiv or Semantic Scholar\n`
742
+ );
743
+ return null;
744
+ } catch {
745
+ return null;
746
+ }
747
+ }
748
+
749
+ // --- Exports -----------------------------------------------------------------
750
+
751
+ module.exports = {
752
+ parseMissingComponents,
753
+ parseBorrowedComponents,
754
+ buildCitationGraph,
755
+ resolveCitations,
756
+ findUnresolved,
757
+ traverseCitationGraph,
758
+ resolveTransitiveDeps,
759
+ fetchExternalPaper,
760
+ };