forge-server 0.1.0

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 (412) hide show
  1. package/.claude/hooks/worktree-create.sh +64 -0
  2. package/.claude/hooks/worktree-remove.sh +57 -0
  3. package/.claude/settings.local.json +29 -0
  4. package/.forge/knowledge/conventions.yaml +1 -0
  5. package/.forge/knowledge/decisions.yaml +1 -0
  6. package/.forge/knowledge/gotchas.yaml +1 -0
  7. package/.forge/knowledge/patterns.yaml +1 -0
  8. package/.forge/manifest.yaml +6 -0
  9. package/CLAUDE.md +144 -0
  10. package/bin/setup-forge.sh +132 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +553 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/context/codebase.d.ts +57 -0
  16. package/dist/context/codebase.d.ts.map +1 -0
  17. package/dist/context/codebase.js +301 -0
  18. package/dist/context/codebase.js.map +1 -0
  19. package/dist/context/injector.d.ts +147 -0
  20. package/dist/context/injector.d.ts.map +1 -0
  21. package/dist/context/injector.js +533 -0
  22. package/dist/context/injector.js.map +1 -0
  23. package/dist/context/memory.d.ts +32 -0
  24. package/dist/context/memory.d.ts.map +1 -0
  25. package/dist/context/memory.js +140 -0
  26. package/dist/context/memory.js.map +1 -0
  27. package/dist/context/session-index.d.ts +54 -0
  28. package/dist/context/session-index.d.ts.map +1 -0
  29. package/dist/context/session-index.js +265 -0
  30. package/dist/context/session-index.js.map +1 -0
  31. package/dist/context/session.d.ts +42 -0
  32. package/dist/context/session.d.ts.map +1 -0
  33. package/dist/context/session.js +121 -0
  34. package/dist/context/session.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +37 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/ingestion/chunker.d.ts +19 -0
  40. package/dist/ingestion/chunker.d.ts.map +1 -0
  41. package/dist/ingestion/chunker.js +189 -0
  42. package/dist/ingestion/chunker.js.map +1 -0
  43. package/dist/ingestion/embedder.d.ts +45 -0
  44. package/dist/ingestion/embedder.d.ts.map +1 -0
  45. package/dist/ingestion/embedder.js +152 -0
  46. package/dist/ingestion/embedder.js.map +1 -0
  47. package/dist/ingestion/git-analyzer.d.ts +77 -0
  48. package/dist/ingestion/git-analyzer.d.ts.map +1 -0
  49. package/dist/ingestion/git-analyzer.js +437 -0
  50. package/dist/ingestion/git-analyzer.js.map +1 -0
  51. package/dist/ingestion/indexer.d.ts +79 -0
  52. package/dist/ingestion/indexer.d.ts.map +1 -0
  53. package/dist/ingestion/indexer.js +766 -0
  54. package/dist/ingestion/indexer.js.map +1 -0
  55. package/dist/ingestion/markdown-chunker.d.ts +19 -0
  56. package/dist/ingestion/markdown-chunker.d.ts.map +1 -0
  57. package/dist/ingestion/markdown-chunker.js +243 -0
  58. package/dist/ingestion/markdown-chunker.js.map +1 -0
  59. package/dist/ingestion/markdown-knowledge.d.ts +21 -0
  60. package/dist/ingestion/markdown-knowledge.d.ts.map +1 -0
  61. package/dist/ingestion/markdown-knowledge.js +129 -0
  62. package/dist/ingestion/markdown-knowledge.js.map +1 -0
  63. package/dist/ingestion/parser.d.ts +20 -0
  64. package/dist/ingestion/parser.d.ts.map +1 -0
  65. package/dist/ingestion/parser.js +429 -0
  66. package/dist/ingestion/parser.js.map +1 -0
  67. package/dist/ingestion/watcher.d.ts +28 -0
  68. package/dist/ingestion/watcher.d.ts.map +1 -0
  69. package/dist/ingestion/watcher.js +147 -0
  70. package/dist/ingestion/watcher.js.map +1 -0
  71. package/dist/knowledge/hydrator.d.ts +37 -0
  72. package/dist/knowledge/hydrator.d.ts.map +1 -0
  73. package/dist/knowledge/hydrator.js +220 -0
  74. package/dist/knowledge/hydrator.js.map +1 -0
  75. package/dist/knowledge/registry.d.ts +129 -0
  76. package/dist/knowledge/registry.d.ts.map +1 -0
  77. package/dist/knowledge/registry.js +361 -0
  78. package/dist/knowledge/registry.js.map +1 -0
  79. package/dist/knowledge/search.d.ts +114 -0
  80. package/dist/knowledge/search.d.ts.map +1 -0
  81. package/dist/knowledge/search.js +428 -0
  82. package/dist/knowledge/search.js.map +1 -0
  83. package/dist/knowledge/store.d.ts +76 -0
  84. package/dist/knowledge/store.d.ts.map +1 -0
  85. package/dist/knowledge/store.js +230 -0
  86. package/dist/knowledge/store.js.map +1 -0
  87. package/dist/learning/confidence.d.ts +30 -0
  88. package/dist/learning/confidence.d.ts.map +1 -0
  89. package/dist/learning/confidence.js +165 -0
  90. package/dist/learning/confidence.js.map +1 -0
  91. package/dist/learning/patterns.d.ts +52 -0
  92. package/dist/learning/patterns.d.ts.map +1 -0
  93. package/dist/learning/patterns.js +290 -0
  94. package/dist/learning/patterns.js.map +1 -0
  95. package/dist/learning/trajectory.d.ts +55 -0
  96. package/dist/learning/trajectory.d.ts.map +1 -0
  97. package/dist/learning/trajectory.js +200 -0
  98. package/dist/learning/trajectory.js.map +1 -0
  99. package/dist/memory/memory-compat.d.ts +100 -0
  100. package/dist/memory/memory-compat.d.ts.map +1 -0
  101. package/dist/memory/memory-compat.js +146 -0
  102. package/dist/memory/memory-compat.js.map +1 -0
  103. package/dist/memory/observation-store.d.ts +57 -0
  104. package/dist/memory/observation-store.d.ts.map +1 -0
  105. package/dist/memory/observation-store.js +154 -0
  106. package/dist/memory/observation-store.js.map +1 -0
  107. package/dist/memory/session-tracker.d.ts +81 -0
  108. package/dist/memory/session-tracker.d.ts.map +1 -0
  109. package/dist/memory/session-tracker.js +262 -0
  110. package/dist/memory/session-tracker.js.map +1 -0
  111. package/dist/pipeline/engine.d.ts +179 -0
  112. package/dist/pipeline/engine.d.ts.map +1 -0
  113. package/dist/pipeline/engine.js +691 -0
  114. package/dist/pipeline/engine.js.map +1 -0
  115. package/dist/pipeline/events.d.ts +54 -0
  116. package/dist/pipeline/events.d.ts.map +1 -0
  117. package/dist/pipeline/events.js +157 -0
  118. package/dist/pipeline/events.js.map +1 -0
  119. package/dist/pipeline/parallel.d.ts +83 -0
  120. package/dist/pipeline/parallel.d.ts.map +1 -0
  121. package/dist/pipeline/parallel.js +277 -0
  122. package/dist/pipeline/parallel.js.map +1 -0
  123. package/dist/pipeline/state-machine.d.ts +65 -0
  124. package/dist/pipeline/state-machine.d.ts.map +1 -0
  125. package/dist/pipeline/state-machine.js +176 -0
  126. package/dist/pipeline/state-machine.js.map +1 -0
  127. package/dist/query/graph-queries.d.ts +84 -0
  128. package/dist/query/graph-queries.d.ts.map +1 -0
  129. package/dist/query/graph-queries.js +216 -0
  130. package/dist/query/graph-queries.js.map +1 -0
  131. package/dist/query/hybrid-search.d.ts +34 -0
  132. package/dist/query/hybrid-search.d.ts.map +1 -0
  133. package/dist/query/hybrid-search.js +263 -0
  134. package/dist/query/hybrid-search.js.map +1 -0
  135. package/dist/query/intent-detector.d.ts +35 -0
  136. package/dist/query/intent-detector.d.ts.map +1 -0
  137. package/dist/query/intent-detector.js +115 -0
  138. package/dist/query/intent-detector.js.map +1 -0
  139. package/dist/query/ranking.d.ts +57 -0
  140. package/dist/query/ranking.d.ts.map +1 -0
  141. package/dist/query/ranking.js +109 -0
  142. package/dist/query/ranking.js.map +1 -0
  143. package/dist/server.d.ts +3 -0
  144. package/dist/server.d.ts.map +1 -0
  145. package/dist/server.js +291 -0
  146. package/dist/server.js.map +1 -0
  147. package/dist/storage/falkordb-store.d.ts +73 -0
  148. package/dist/storage/falkordb-store.d.ts.map +1 -0
  149. package/dist/storage/falkordb-store.js +346 -0
  150. package/dist/storage/falkordb-store.js.map +1 -0
  151. package/dist/storage/file-cache.d.ts +32 -0
  152. package/dist/storage/file-cache.d.ts.map +1 -0
  153. package/dist/storage/file-cache.js +115 -0
  154. package/dist/storage/file-cache.js.map +1 -0
  155. package/dist/storage/interfaces.d.ts +151 -0
  156. package/dist/storage/interfaces.d.ts.map +1 -0
  157. package/dist/storage/interfaces.js +7 -0
  158. package/dist/storage/interfaces.js.map +1 -0
  159. package/dist/storage/qdrant-store.d.ts +110 -0
  160. package/dist/storage/qdrant-store.d.ts.map +1 -0
  161. package/dist/storage/qdrant-store.js +467 -0
  162. package/dist/storage/qdrant-store.js.map +1 -0
  163. package/dist/storage/schema.d.ts +4 -0
  164. package/dist/storage/schema.d.ts.map +1 -0
  165. package/dist/storage/schema.js +136 -0
  166. package/dist/storage/schema.js.map +1 -0
  167. package/dist/storage/sqlite.d.ts +35 -0
  168. package/dist/storage/sqlite.d.ts.map +1 -0
  169. package/dist/storage/sqlite.js +132 -0
  170. package/dist/storage/sqlite.js.map +1 -0
  171. package/dist/tools/collaboration-tools.d.ts +111 -0
  172. package/dist/tools/collaboration-tools.d.ts.map +1 -0
  173. package/dist/tools/collaboration-tools.js +174 -0
  174. package/dist/tools/collaboration-tools.js.map +1 -0
  175. package/dist/tools/context-tools.d.ts +293 -0
  176. package/dist/tools/context-tools.d.ts.map +1 -0
  177. package/dist/tools/context-tools.js +437 -0
  178. package/dist/tools/context-tools.js.map +1 -0
  179. package/dist/tools/graph-tools.d.ts +129 -0
  180. package/dist/tools/graph-tools.d.ts.map +1 -0
  181. package/dist/tools/graph-tools.js +237 -0
  182. package/dist/tools/graph-tools.js.map +1 -0
  183. package/dist/tools/ingestion-tools.d.ts +96 -0
  184. package/dist/tools/ingestion-tools.d.ts.map +1 -0
  185. package/dist/tools/ingestion-tools.js +90 -0
  186. package/dist/tools/ingestion-tools.js.map +1 -0
  187. package/dist/tools/learning-tools.d.ts +168 -0
  188. package/dist/tools/learning-tools.d.ts.map +1 -0
  189. package/dist/tools/learning-tools.js +158 -0
  190. package/dist/tools/learning-tools.js.map +1 -0
  191. package/dist/tools/memory-tools.d.ts +183 -0
  192. package/dist/tools/memory-tools.d.ts.map +1 -0
  193. package/dist/tools/memory-tools.js +197 -0
  194. package/dist/tools/memory-tools.js.map +1 -0
  195. package/dist/tools/phase-tools.d.ts +954 -0
  196. package/dist/tools/phase-tools.d.ts.map +1 -0
  197. package/dist/tools/phase-tools.js +1215 -0
  198. package/dist/tools/phase-tools.js.map +1 -0
  199. package/dist/tools/pipeline-tools.d.ts +140 -0
  200. package/dist/tools/pipeline-tools.d.ts.map +1 -0
  201. package/dist/tools/pipeline-tools.js +162 -0
  202. package/dist/tools/pipeline-tools.js.map +1 -0
  203. package/dist/tools/registration-tools.d.ts +220 -0
  204. package/dist/tools/registration-tools.d.ts.map +1 -0
  205. package/dist/tools/registration-tools.js +391 -0
  206. package/dist/tools/registration-tools.js.map +1 -0
  207. package/dist/util/circuit-breaker.d.ts +75 -0
  208. package/dist/util/circuit-breaker.d.ts.map +1 -0
  209. package/dist/util/circuit-breaker.js +159 -0
  210. package/dist/util/circuit-breaker.js.map +1 -0
  211. package/dist/util/config.d.ts +23 -0
  212. package/dist/util/config.d.ts.map +1 -0
  213. package/dist/util/config.js +164 -0
  214. package/dist/util/config.js.map +1 -0
  215. package/dist/util/logger.d.ts +13 -0
  216. package/dist/util/logger.d.ts.map +1 -0
  217. package/dist/util/logger.js +45 -0
  218. package/dist/util/logger.js.map +1 -0
  219. package/dist/util/token-counter.d.ts +24 -0
  220. package/dist/util/token-counter.d.ts.map +1 -0
  221. package/dist/util/token-counter.js +48 -0
  222. package/dist/util/token-counter.js.map +1 -0
  223. package/dist/util/types.d.ts +525 -0
  224. package/dist/util/types.d.ts.map +1 -0
  225. package/dist/util/types.js +5 -0
  226. package/dist/util/types.js.map +1 -0
  227. package/docker-compose.yml +20 -0
  228. package/docs/plans/2026-02-27-swarm-coordination/architecture.md +203 -0
  229. package/docs/plans/2026-02-27-swarm-coordination/vision.md +57 -0
  230. package/docs/plans/completed/2026-02-26-forge-plugin-bundling/architecture.md +1 -0
  231. package/docs/plans/completed/2026-02-26-forge-plugin-bundling/vision.md +300 -0
  232. package/docs/plans/completed/2026-02-27-forge-swarm-learning/architecture.md +480 -0
  233. package/docs/plans/completed/2026-02-27-forge-swarm-learning/verification-checklist.md +462 -0
  234. package/docs/plans/completed/2026-02-27-git-history-atlassian/git-jira-plan.md +181 -0
  235. package/package.json +39 -0
  236. package/plugin/.claude-plugin/plugin.json +8 -0
  237. package/plugin/.mcp.json +15 -0
  238. package/plugin/README.md +134 -0
  239. package/plugin/agents/architect.md +367 -0
  240. package/plugin/agents/backend-specialist.md +263 -0
  241. package/plugin/agents/brainstormer.md +122 -0
  242. package/plugin/agents/data-specialist.md +266 -0
  243. package/plugin/agents/designer.md +408 -0
  244. package/plugin/agents/frontend-specialist.md +241 -0
  245. package/plugin/agents/inspector.md +406 -0
  246. package/plugin/agents/knowledge-keeper.md +443 -0
  247. package/plugin/agents/platform-engineer.md +326 -0
  248. package/plugin/agents/product-manager.md +268 -0
  249. package/plugin/agents/product-owner.md +438 -0
  250. package/plugin/agents/pulse-checker.md +73 -0
  251. package/plugin/agents/qa-strategist.md +500 -0
  252. package/plugin/agents/self-improver.md +310 -0
  253. package/plugin/agents/strategist.md +360 -0
  254. package/plugin/agents/supervisor.md +380 -0
  255. package/plugin/commands/brainstorm.md +25 -0
  256. package/plugin/commands/forge.md +88 -0
  257. package/plugin/docs/atlassian-integration.md +110 -0
  258. package/plugin/docs/workflow.md +126 -0
  259. package/plugin/skills/agent-development/.skillfish.json +10 -0
  260. package/plugin/skills/agent-development/SKILL.md +415 -0
  261. package/plugin/skills/agent-development/examples/agent-creation-prompt.md +238 -0
  262. package/plugin/skills/agent-development/examples/complete-agent-examples.md +427 -0
  263. package/plugin/skills/agent-development/references/agent-creation-system-prompt.md +207 -0
  264. package/plugin/skills/agent-development/references/system-prompt-design.md +411 -0
  265. package/plugin/skills/agent-development/references/triggering-examples.md +491 -0
  266. package/plugin/skills/agent-development/scripts/validate-agent.sh +217 -0
  267. package/plugin/skills/agent-handoff/SKILL.md +335 -0
  268. package/plugin/skills/anti-stub/SKILL.md +317 -0
  269. package/plugin/skills/brainstorm/SKILL.md +31 -0
  270. package/plugin/skills/debugging/SKILL.md +276 -0
  271. package/plugin/skills/fix/SKILL.md +62 -0
  272. package/plugin/skills/frontend-design/.skillfish.json +10 -0
  273. package/plugin/skills/frontend-design/SKILL.md +42 -0
  274. package/plugin/skills/gotchas/SKILL.md +61 -0
  275. package/plugin/skills/graph-orchestrator/SKILL.md +38 -0
  276. package/plugin/skills/history/SKILL.md +58 -0
  277. package/plugin/skills/impact/SKILL.md +59 -0
  278. package/plugin/skills/implementation-execution/SKILL.md +291 -0
  279. package/plugin/skills/index-repo/SKILL.md +55 -0
  280. package/plugin/skills/interviewing/SKILL.md +225 -0
  281. package/plugin/skills/knowledge-curation/SKILL.md +393 -0
  282. package/plugin/skills/learn/SKILL.md +69 -0
  283. package/plugin/skills/mcp-integration/.skillfish.json +10 -0
  284. package/plugin/skills/mcp-integration/SKILL.md +554 -0
  285. package/plugin/skills/mcp-integration/examples/http-server.json +20 -0
  286. package/plugin/skills/mcp-integration/examples/sse-server.json +19 -0
  287. package/plugin/skills/mcp-integration/examples/stdio-server.json +26 -0
  288. package/plugin/skills/mcp-integration/references/authentication.md +549 -0
  289. package/plugin/skills/mcp-integration/references/server-types.md +536 -0
  290. package/plugin/skills/mcp-integration/references/tool-usage.md +538 -0
  291. package/plugin/skills/nestjs/.skillfish.json +10 -0
  292. package/plugin/skills/nestjs/SKILL.md +669 -0
  293. package/plugin/skills/nestjs/drizzle-reference.md +1894 -0
  294. package/plugin/skills/nestjs/reference.md +1447 -0
  295. package/plugin/skills/nestjs/workflow-optimization.md +229 -0
  296. package/plugin/skills/parallel-dispatch/SKILL.md +308 -0
  297. package/plugin/skills/project-discovery/SKILL.md +304 -0
  298. package/plugin/skills/search/SKILL.md +56 -0
  299. package/plugin/skills/security-audit/SKILL.md +362 -0
  300. package/plugin/skills/skill-development/.skillfish.json +10 -0
  301. package/plugin/skills/skill-development/SKILL.md +637 -0
  302. package/plugin/skills/skill-development/references/skill-creator-original.md +209 -0
  303. package/plugin/skills/tdd/SKILL.md +273 -0
  304. package/plugin/skills/terminal-presentation/SKILL.md +395 -0
  305. package/plugin/skills/test-strategy/SKILL.md +365 -0
  306. package/plugin/skills/verification-protocol/SKILL.md +256 -0
  307. package/plugin/skills/visual-explainer/CHANGELOG.md +97 -0
  308. package/plugin/skills/visual-explainer/LICENSE +21 -0
  309. package/plugin/skills/visual-explainer/README.md +137 -0
  310. package/plugin/skills/visual-explainer/SKILL.md +352 -0
  311. package/plugin/skills/visual-explainer/banner.png +0 -0
  312. package/plugin/skills/visual-explainer/package.json +11 -0
  313. package/plugin/skills/visual-explainer/prompts/diff-review.md +68 -0
  314. package/plugin/skills/visual-explainer/prompts/fact-check.md +63 -0
  315. package/plugin/skills/visual-explainer/prompts/generate-slides.md +18 -0
  316. package/plugin/skills/visual-explainer/prompts/generate-web-diagram.md +10 -0
  317. package/plugin/skills/visual-explainer/prompts/plan-review.md +86 -0
  318. package/plugin/skills/visual-explainer/prompts/project-recap.md +61 -0
  319. package/plugin/skills/visual-explainer/references/css-patterns.md +1188 -0
  320. package/plugin/skills/visual-explainer/references/libraries.md +470 -0
  321. package/plugin/skills/visual-explainer/references/responsive-nav.md +212 -0
  322. package/plugin/skills/visual-explainer/references/slide-patterns.md +1403 -0
  323. package/plugin/skills/visual-explainer/templates/architecture.html +596 -0
  324. package/plugin/skills/visual-explainer/templates/data-table.html +540 -0
  325. package/plugin/skills/visual-explainer/templates/mermaid-flowchart.html +435 -0
  326. package/plugin/skills/visual-explainer/templates/slide-deck.html +913 -0
  327. package/src/cli.ts +655 -0
  328. package/src/context/.gitkeep +0 -0
  329. package/src/context/codebase.ts +393 -0
  330. package/src/context/injector.ts +797 -0
  331. package/src/context/memory.ts +187 -0
  332. package/src/context/session-index.ts +327 -0
  333. package/src/context/session.ts +152 -0
  334. package/src/index.ts +47 -0
  335. package/src/ingestion/.gitkeep +0 -0
  336. package/src/ingestion/chunker.ts +277 -0
  337. package/src/ingestion/embedder.ts +167 -0
  338. package/src/ingestion/git-analyzer.ts +545 -0
  339. package/src/ingestion/indexer.ts +984 -0
  340. package/src/ingestion/markdown-chunker.ts +337 -0
  341. package/src/ingestion/markdown-knowledge.ts +175 -0
  342. package/src/ingestion/parser.ts +475 -0
  343. package/src/ingestion/watcher.ts +182 -0
  344. package/src/knowledge/.gitkeep +0 -0
  345. package/src/knowledge/hydrator.ts +246 -0
  346. package/src/knowledge/registry.ts +463 -0
  347. package/src/knowledge/search.ts +565 -0
  348. package/src/knowledge/store.ts +262 -0
  349. package/src/learning/.gitkeep +0 -0
  350. package/src/learning/confidence.ts +193 -0
  351. package/src/learning/patterns.ts +360 -0
  352. package/src/learning/trajectory.ts +268 -0
  353. package/src/memory/.gitkeep +0 -0
  354. package/src/memory/memory-compat.ts +233 -0
  355. package/src/memory/observation-store.ts +224 -0
  356. package/src/memory/session-tracker.ts +332 -0
  357. package/src/pipeline/.gitkeep +0 -0
  358. package/src/pipeline/engine.ts +1139 -0
  359. package/src/pipeline/events.ts +253 -0
  360. package/src/pipeline/parallel.ts +394 -0
  361. package/src/pipeline/state-machine.ts +199 -0
  362. package/src/query/.gitkeep +0 -0
  363. package/src/query/graph-queries.ts +262 -0
  364. package/src/query/hybrid-search.ts +337 -0
  365. package/src/query/intent-detector.ts +131 -0
  366. package/src/query/ranking.ts +161 -0
  367. package/src/server.ts +352 -0
  368. package/src/storage/.gitkeep +0 -0
  369. package/src/storage/falkordb-store.ts +388 -0
  370. package/src/storage/file-cache.ts +141 -0
  371. package/src/storage/interfaces.ts +201 -0
  372. package/src/storage/qdrant-store.ts +557 -0
  373. package/src/storage/schema.ts +139 -0
  374. package/src/storage/sqlite.ts +168 -0
  375. package/src/tools/.gitkeep +0 -0
  376. package/src/tools/collaboration-tools.ts +208 -0
  377. package/src/tools/context-tools.ts +493 -0
  378. package/src/tools/graph-tools.ts +295 -0
  379. package/src/tools/ingestion-tools.ts +122 -0
  380. package/src/tools/learning-tools.ts +181 -0
  381. package/src/tools/memory-tools.ts +234 -0
  382. package/src/tools/phase-tools.ts +1452 -0
  383. package/src/tools/pipeline-tools.ts +188 -0
  384. package/src/tools/registration-tools.ts +450 -0
  385. package/src/util/.gitkeep +0 -0
  386. package/src/util/circuit-breaker.ts +193 -0
  387. package/src/util/config.ts +177 -0
  388. package/src/util/logger.ts +53 -0
  389. package/src/util/token-counter.ts +52 -0
  390. package/src/util/types.ts +710 -0
  391. package/tests/context/.gitkeep +0 -0
  392. package/tests/integration/.gitkeep +0 -0
  393. package/tests/knowledge/.gitkeep +0 -0
  394. package/tests/learning/.gitkeep +0 -0
  395. package/tests/pipeline/.gitkeep +0 -0
  396. package/tests/tools/.gitkeep +0 -0
  397. package/tsconfig.json +21 -0
  398. package/vitest.config.ts +10 -0
  399. package/vscode-extension/.vscodeignore +7 -0
  400. package/vscode-extension/README.md +43 -0
  401. package/vscode-extension/out/edge-collector.js +274 -0
  402. package/vscode-extension/out/edge-collector.js.map +1 -0
  403. package/vscode-extension/out/extension.js +264 -0
  404. package/vscode-extension/out/extension.js.map +1 -0
  405. package/vscode-extension/out/forge-client.js +318 -0
  406. package/vscode-extension/out/forge-client.js.map +1 -0
  407. package/vscode-extension/package-lock.json +59 -0
  408. package/vscode-extension/package.json +71 -0
  409. package/vscode-extension/src/edge-collector.ts +320 -0
  410. package/vscode-extension/src/extension.ts +269 -0
  411. package/vscode-extension/src/forge-client.ts +364 -0
  412. package/vscode-extension/tsconfig.json +19 -0
@@ -0,0 +1,493 @@
1
+ // context-tools.ts — B15
2
+ // MCP tool handlers for codebase context and knowledge search.
3
+ // Tools: search_knowledge, get_codebase_context, get_project_history, get_git_context
4
+
5
+ import { z } from 'zod';
6
+ import type { KnowledgeSearch } from '../knowledge/search.js';
7
+ import type { CodebaseContext } from '../context/codebase.js';
8
+ import type { MemoryBridge } from '../context/memory.js';
9
+ import type { PipelineEngine } from '../pipeline/engine.js';
10
+ import type { VectorStore, GraphStore } from '../storage/interfaces.js';
11
+ import { detectIntent, getIntentStrategy } from '../query/intent-detector.js';
12
+ import { logger } from '../util/logger.js';
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Input schemas
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export const searchKnowledgeSchema = z.object({
19
+ query: z.string().min(1, 'query is required'),
20
+ category: z.enum(['gotcha', 'pattern', 'decision', 'convention']).optional(),
21
+ stack_tags: z.array(z.string()).optional(),
22
+ repo_id: z.string().optional(),
23
+ limit: z.number().int().min(1).max(50).default(10),
24
+ include_cross_repo: z.boolean().default(true),
25
+ });
26
+
27
+ export const getCodebaseContextSchema = z.object({
28
+ query: z.string().min(1, 'query is required'),
29
+ repo_id: z.string().optional(),
30
+ detail: z.enum(['full', 'skeleton', 'paths']).default('full'),
31
+ max_results: z.number().int().min(1).max(20).default(5),
32
+ include_tests: z.boolean().default(false),
33
+ include_cross_repo: z.boolean().default(true),
34
+ });
35
+
36
+ export const getProjectHistorySchema = z.object({
37
+ project_id: z.string().min(1, 'project_id is required'),
38
+ });
39
+
40
+ export const getGitContextSchema = z.object({
41
+ mode: z.enum(['hotspots', 'commit_search', 'file_history']),
42
+ repo_id: z.string().optional(),
43
+ query: z.string().optional(),
44
+ file_path: z.string().optional(),
45
+ limit: z.number().int().min(1).max(100).default(20),
46
+ });
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Tool factory
50
+ // ---------------------------------------------------------------------------
51
+
52
+ export function createContextTools(
53
+ knowledgeSearch: KnowledgeSearch,
54
+ codebaseContext: CodebaseContext,
55
+ engine: PipelineEngine,
56
+ memoryBridge?: MemoryBridge | null,
57
+ vectorStore?: VectorStore | null,
58
+ graphStore?: GraphStore | null,
59
+ ) {
60
+ return {
61
+ 'search_knowledge': {
62
+ schema: searchKnowledgeSchema,
63
+ description: 'Semantic search over knowledge items (gotchas, patterns, decisions, conventions) across all registered repos. PREFER THIS over ad-hoc file searching when looking for known issues, established patterns, or past decisions — it searches curated knowledge, not raw code. Cross-repo results are filtered by repo sharing mode. Provide repo_id to boost same-repo results.',
64
+ handler: async (input: z.infer<typeof searchKnowledgeSchema>) => {
65
+ try {
66
+ const results = await knowledgeSearch.search(input.query, {
67
+ category: input.category,
68
+ stack_tags: input.stack_tags,
69
+ repo_id: input.repo_id,
70
+ limit: input.limit,
71
+ include_cross_repo: input.include_cross_repo,
72
+ });
73
+
74
+ const reposSearched = new Set(results.map(r => r.source_repo)).size;
75
+
76
+ logger.debug('context-tools.search_knowledge: completed', {
77
+ query: input.query.slice(0, 80),
78
+ resultCount: results.length,
79
+ });
80
+
81
+ return {
82
+ results: results.map(r => ({
83
+ id: r.id,
84
+ category: r.category,
85
+ title: r.title,
86
+ content: r.content,
87
+ confidence: r.confidence,
88
+ stack_tags: r.stack_tags,
89
+ source_repo: r.source_repo,
90
+ relevance_score: r.relevance_score,
91
+ })),
92
+ search_method: 'vector' as const,
93
+ repos_searched: reposSearched,
94
+ };
95
+ } catch (err) {
96
+ logger.error('context-tools.search_knowledge: error', { error: String(err) });
97
+ return {
98
+ error: 'SEARCH_KNOWLEDGE_FAILED',
99
+ message: String(err),
100
+ results: [],
101
+ search_method: 'vector' as const,
102
+ repos_searched: 0,
103
+ };
104
+ }
105
+ },
106
+ },
107
+
108
+ 'get_codebase_context': {
109
+ schema: getCodebaseContextSchema,
110
+ description: 'Hybrid search over indexed codebase (vector + graph) to retrieve relevant code context for a query. PREFER THIS over built-in Read/Grep/Glob when the repo is indexed — it combines vector similarity, graph centrality, recency, and hotspot scoring for much better results than keyword search. Cross-repo results are filtered by repo sharing mode. Provide repo_id to scope to a single repo.',
111
+ handler: async (input: z.infer<typeof getCodebaseContextSchema>) => {
112
+ const startTime = Date.now();
113
+ try {
114
+ // Classify query intent and get retrieval strategy weights
115
+ const queryIntent = detectIntent(input.query);
116
+ const strategy = getIntentStrategy(queryIntent);
117
+
118
+ const result = await codebaseContext.getContext(input.query, {
119
+ repoId: input.repo_id,
120
+ detail: input.detail,
121
+ maxResults: input.max_results,
122
+ includeTests: input.include_tests ?? strategy.includeTests,
123
+ includeCrossRepo: input.include_cross_repo,
124
+ maxTokens: 8000,
125
+ vectorWeight: strategy.vectorWeight,
126
+ graphWeight: strategy.graphWeight,
127
+ });
128
+
129
+ // Populate related memories from observation store
130
+ let relatedMemories: Array<{
131
+ content: string;
132
+ relevance_score: number;
133
+ }> = [];
134
+ if (memoryBridge) {
135
+ try {
136
+ const memories = await memoryBridge.searchMemories(input.query, {
137
+ repoId: input.repo_id,
138
+ limit: 3,
139
+ });
140
+ relatedMemories = memories.map(m => ({
141
+ content: m.content,
142
+ relevance_score: m.relevanceScore,
143
+ }));
144
+ } catch (memErr) {
145
+ logger.debug('context-tools.get_codebase_context: memory search failed (non-fatal)', {
146
+ error: String(memErr),
147
+ });
148
+ }
149
+ }
150
+
151
+ const executionTimeMs = Date.now() - startTime;
152
+
153
+ logger.debug('context-tools.get_codebase_context: completed', {
154
+ query: input.query.slice(0, 80),
155
+ queryIntent,
156
+ pivotCount: result.pivotFiles.length,
157
+ tokenCount: result.tokenCount,
158
+ memoryCount: relatedMemories.length,
159
+ executionTimeMs,
160
+ });
161
+
162
+ return {
163
+ pivot_files: result.pivotFiles.map(f => ({
164
+ file_path: f.filePath,
165
+ content: f.content,
166
+ relevance_score: f.relevanceScore,
167
+ match_reason: f.matchReason,
168
+ })),
169
+ supporting_skeletons: result.supportingSkeletons.map(s => ({
170
+ file_path: s.filePath,
171
+ skeleton: s.skeleton,
172
+ relevance_score: s.relevanceScore,
173
+ })),
174
+ related_memories: relatedMemories,
175
+ query_intent: queryIntent,
176
+ token_count: result.tokenCount,
177
+ execution_time_ms: executionTimeMs,
178
+ };
179
+ } catch (err) {
180
+ logger.error('context-tools.get_codebase_context: error', { error: String(err) });
181
+ return {
182
+ error: 'GET_CODEBASE_CONTEXT_FAILED',
183
+ message: String(err),
184
+ pivot_files: [],
185
+ supporting_skeletons: [],
186
+ related_memories: [],
187
+ query_intent: 'read',
188
+ token_count: 0,
189
+ execution_time_ms: Date.now() - startTime,
190
+ };
191
+ }
192
+ },
193
+ },
194
+
195
+ 'get_project_history': {
196
+ schema: getProjectHistorySchema,
197
+ description: 'Returns the full event history and phase outputs for a project. Use this to understand what happened during a pipeline run — phase transitions, agent outputs, broadcasts, and decisions.',
198
+ handler: async (input: z.infer<typeof getProjectHistorySchema>) => {
199
+ try {
200
+ const project = engine.getProject(input.project_id);
201
+ if (!project) {
202
+ return {
203
+ error: 'PROJECT_NOT_FOUND',
204
+ project_id: input.project_id,
205
+ };
206
+ }
207
+
208
+ const { events, outputs } = engine.getHistory(input.project_id);
209
+
210
+ logger.debug('context-tools.get_project_history: completed', {
211
+ projectId: input.project_id,
212
+ eventCount: events.length,
213
+ outputCount: outputs.length,
214
+ });
215
+
216
+ return {
217
+ project_id: input.project_id,
218
+ events: events.map(ev => ({
219
+ type: ev.eventType,
220
+ from_phase: ev.fromPhase ?? undefined,
221
+ to_phase: ev.toPhase ?? undefined,
222
+ agent: ev.agent ?? undefined,
223
+ timestamp: new Date(ev.createdAt).toISOString(),
224
+ payload: ev.payload as Record<string, unknown>,
225
+ })),
226
+ outputs: outputs.map(o => ({
227
+ phase: o.phase,
228
+ type: o.outputType,
229
+ preview: o.content.slice(0, 500),
230
+ file_path: o.filePath ?? undefined,
231
+ timestamp: new Date(o.createdAt).toISOString(),
232
+ })),
233
+ };
234
+ } catch (err) {
235
+ logger.error('context-tools.get_project_history: error', { error: String(err) });
236
+ return {
237
+ error: 'GET_PROJECT_HISTORY_FAILED',
238
+ project_id: input.project_id,
239
+ message: String(err),
240
+ };
241
+ }
242
+ },
243
+ },
244
+
245
+ 'get_git_context': {
246
+ schema: getGitContextSchema,
247
+ description: 'Query git history context: hotspots (frequently changed files), commit_search (semantic search over commit messages), or file_history (commits for a specific file). PREFER THIS over raw `git log` commands — it uses indexed data with semantic search over commit messages. Requires FalkorDB for hotspots/file_history and Qdrant git_commits collection for commit_search.',
248
+ handler: async (input: z.infer<typeof getGitContextSchema>) => {
249
+ try {
250
+ switch (input.mode) {
251
+ // -----------------------------------------------------------------
252
+ // hotspots: top N files by commit_count from FalkorDB File nodes
253
+ // -----------------------------------------------------------------
254
+ case 'hotspots': {
255
+ if (!graphStore) {
256
+ return {
257
+ mode: 'hotspots',
258
+ error: 'GRAPH_UNAVAILABLE',
259
+ message: 'FalkorDB is not connected — hotspots require the graph store',
260
+ results: [],
261
+ };
262
+ }
263
+
264
+ const graphHealthy = await graphStore.isHealthy();
265
+ if (!graphHealthy) {
266
+ return {
267
+ mode: 'hotspots',
268
+ error: 'GRAPH_UNAVAILABLE',
269
+ message: 'FalkorDB is unhealthy — hotspots unavailable',
270
+ results: [],
271
+ };
272
+ }
273
+
274
+ const repoFilter = input.repo_id
275
+ ? `{repo_id: "${escCypher(input.repo_id)}"}`
276
+ : '';
277
+ const cypher = `
278
+ MATCH (f:File ${repoFilter})
279
+ WHERE f.commit_count IS NOT NULL AND f.commit_count > 0
280
+ RETURN f.path AS path, f.commit_count AS commit_count,
281
+ f.stability_score AS stability_score,
282
+ f.change_velocity AS change_velocity
283
+ ORDER BY f.commit_count DESC
284
+ LIMIT ${input.limit}
285
+ `;
286
+
287
+ const result = await graphStore.query(cypher);
288
+ const rows = result.raw ?? [];
289
+
290
+ const hotspots = rows.map((row: unknown) => {
291
+ if (Array.isArray(row)) {
292
+ return {
293
+ file_path: row[0] as string,
294
+ commit_count: row[1] as number,
295
+ stability_score: row[2] as number | null,
296
+ change_velocity: row[3] as number | null,
297
+ };
298
+ }
299
+ const obj = row as Record<string, unknown>;
300
+ return {
301
+ file_path: obj.path as string,
302
+ commit_count: obj.commit_count as number,
303
+ stability_score: (obj.stability_score as number) ?? null,
304
+ change_velocity: (obj.change_velocity as number) ?? null,
305
+ };
306
+ });
307
+
308
+ logger.debug('context-tools.get_git_context: hotspots', {
309
+ repoId: input.repo_id,
310
+ resultCount: hotspots.length,
311
+ });
312
+
313
+ return {
314
+ mode: 'hotspots',
315
+ results: hotspots,
316
+ total: hotspots.length,
317
+ };
318
+ }
319
+
320
+ // -----------------------------------------------------------------
321
+ // commit_search: semantic search over git_commits in Qdrant
322
+ // -----------------------------------------------------------------
323
+ case 'commit_search': {
324
+ if (!input.query) {
325
+ return {
326
+ mode: 'commit_search',
327
+ error: 'MISSING_QUERY',
328
+ message: 'commit_search mode requires a query string',
329
+ results: [],
330
+ };
331
+ }
332
+
333
+ // Guard: searchGitCommits is a QdrantVectorStore-specific method
334
+ // that only exists after git_commits collection is created (Phase 3)
335
+ if (
336
+ !vectorStore ||
337
+ !('searchGitCommits' in vectorStore)
338
+ ) {
339
+ return {
340
+ mode: 'commit_search',
341
+ error: 'GIT_COMMITS_UNAVAILABLE',
342
+ message: 'Git commits collection is not indexed — run index_repo with git enrichment first',
343
+ results: [],
344
+ };
345
+ }
346
+
347
+ const healthy = await vectorStore.isHealthy();
348
+ if (!healthy) {
349
+ return {
350
+ mode: 'commit_search',
351
+ error: 'VECTOR_UNAVAILABLE',
352
+ message: 'Qdrant is unhealthy — commit search unavailable',
353
+ results: [],
354
+ };
355
+ }
356
+
357
+ const qdrantStore = vectorStore as unknown as { searchGitCommits(query: string, opts: { repoId?: string; limit?: number }): Promise<Array<{ id: string; score: number; payload: Record<string, unknown> }>> };
358
+ const commits = await qdrantStore.searchGitCommits(input.query, {
359
+ repoId: input.repo_id,
360
+ limit: input.limit,
361
+ });
362
+
363
+ logger.debug('context-tools.get_git_context: commit_search', {
364
+ query: input.query.slice(0, 80),
365
+ resultCount: Array.isArray(commits) ? commits.length : 0,
366
+ });
367
+
368
+ return {
369
+ mode: 'commit_search',
370
+ results: Array.isArray(commits) ? commits : [],
371
+ total: Array.isArray(commits) ? commits.length : 0,
372
+ };
373
+ }
374
+
375
+ // -----------------------------------------------------------------
376
+ // file_history: recent commits for a specific file from FalkorDB
377
+ // -----------------------------------------------------------------
378
+ case 'file_history': {
379
+ if (!input.file_path) {
380
+ return {
381
+ mode: 'file_history',
382
+ error: 'MISSING_FILE_PATH',
383
+ message: 'file_history mode requires a file_path',
384
+ results: [],
385
+ };
386
+ }
387
+
388
+ if (!graphStore) {
389
+ return {
390
+ mode: 'file_history',
391
+ error: 'GRAPH_UNAVAILABLE',
392
+ message: 'FalkorDB is not connected — file history requires the graph store',
393
+ results: [],
394
+ };
395
+ }
396
+
397
+ const graphHealthy = await graphStore.isHealthy();
398
+ if (!graphHealthy) {
399
+ return {
400
+ mode: 'file_history',
401
+ error: 'GRAPH_UNAVAILABLE',
402
+ message: 'FalkorDB is unhealthy — file history unavailable',
403
+ results: [],
404
+ };
405
+ }
406
+
407
+ const repoMatch = input.repo_id
408
+ ? `, repo_id: "${escCypher(input.repo_id)}"`
409
+ : '';
410
+ const cypher = `
411
+ MATCH (f:File {path: "${escCypher(input.file_path)}"${repoMatch}})
412
+ RETURN f.path AS path, f.commit_count AS commit_count,
413
+ f.stability_score AS stability_score,
414
+ f.change_velocity AS change_velocity,
415
+ f.last_commit_hash AS last_commit_hash,
416
+ f.last_commit_ts AS last_commit_ts
417
+ `;
418
+
419
+ const result = await graphStore.query(cypher);
420
+ const rows = result.raw ?? [];
421
+
422
+ const fileStats = rows.map((row: unknown) => {
423
+ if (Array.isArray(row)) {
424
+ return {
425
+ file_path: row[0] as string,
426
+ commit_count: row[1] as number | null,
427
+ stability_score: row[2] as number | null,
428
+ change_velocity: row[3] as number | null,
429
+ last_commit_hash: row[4] as string | null,
430
+ last_commit_ts: row[5] as number | null,
431
+ };
432
+ }
433
+ const obj = row as Record<string, unknown>;
434
+ return {
435
+ file_path: obj.path as string,
436
+ commit_count: (obj.commit_count as number) ?? null,
437
+ stability_score: (obj.stability_score as number) ?? null,
438
+ change_velocity: (obj.change_velocity as number) ?? null,
439
+ last_commit_hash: (obj.last_commit_hash as string) ?? null,
440
+ last_commit_ts: (obj.last_commit_ts as number) ?? null,
441
+ };
442
+ });
443
+
444
+ logger.debug('context-tools.get_git_context: file_history', {
445
+ filePath: input.file_path,
446
+ found: fileStats.length > 0,
447
+ });
448
+
449
+ return {
450
+ mode: 'file_history',
451
+ results: fileStats,
452
+ total: fileStats.length,
453
+ };
454
+ }
455
+
456
+ default:
457
+ return {
458
+ error: 'INVALID_MODE',
459
+ message: `Unknown mode: ${String((input as Record<string, unknown>).mode)}`,
460
+ };
461
+ }
462
+ } catch (err) {
463
+ logger.error('context-tools.get_git_context: error', {
464
+ mode: input.mode,
465
+ error: String(err),
466
+ });
467
+ return {
468
+ mode: input.mode,
469
+ error: 'GET_GIT_CONTEXT_FAILED',
470
+ message: String(err),
471
+ results: [],
472
+ };
473
+ }
474
+ },
475
+ },
476
+ };
477
+ }
478
+
479
+ // ---------------------------------------------------------------------------
480
+ // Utility
481
+ // ---------------------------------------------------------------------------
482
+
483
+ /**
484
+ * Escape a string for safe embedding in Cypher queries.
485
+ * FalkorDB uses double-quoted strings.
486
+ */
487
+ function escCypher(s: string): string {
488
+ return s
489
+ .replace(/\\/g, '\\\\')
490
+ .replace(/"/g, '\\"')
491
+ .replace(/\n/g, '\\n')
492
+ .replace(/\r/g, '');
493
+ }