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,393 @@
1
+ // CodebaseContext — B7
2
+ //
3
+ // Wraps the local hybrid-search + file-cache modules so that the ContextInjector
4
+ // can retrieve codebase context without coupling to the query internals directly.
5
+ //
6
+ // When either graph or vector store is unavailable the class degrades gracefully:
7
+ // - If vectorStore is null/unhealthy: returns empty pivot files and a warning.
8
+ // - If graphStore is null/unhealthy: falls back to vector-only search.
9
+ // - If fileCache is null: returns file paths without content.
10
+
11
+ import type { VectorStore, GraphStore, FileContentCache } from '../storage/interfaces.js';
12
+ import type { RepoSharing } from '../util/types.js';
13
+ import { hybridSearch } from '../query/hybrid-search.js';
14
+ import { estimateTokens } from '../util/token-counter.js';
15
+ import { logger } from '../util/logger.js';
16
+ import { readFileSync, existsSync } from 'node:fs';
17
+
18
+ /**
19
+ * Resolves the sharing mode for a given repo ID.
20
+ * Returns undefined if the repo is not found.
21
+ */
22
+ export type SharingResolver = (repoId: string) => RepoSharing | undefined;
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Public types
26
+ // ---------------------------------------------------------------------------
27
+
28
+ export interface CodebaseContextOptions {
29
+ repoId?: string;
30
+ detail?: 'full' | 'skeleton' | 'paths';
31
+ maxResults?: number;
32
+ includeTests?: boolean;
33
+ includeCrossRepo?: boolean;
34
+ maxTokens?: number;
35
+ vectorWeight?: number; // from intent strategy, default 0.6
36
+ graphWeight?: number; // from intent strategy, default 0.3
37
+ }
38
+
39
+ export interface PivotFile {
40
+ filePath: string;
41
+ content: string;
42
+ relevanceScore: number;
43
+ matchReason: string;
44
+ }
45
+
46
+ export interface SupportingSkeleton {
47
+ filePath: string;
48
+ skeleton: string;
49
+ relevanceScore: number;
50
+ }
51
+
52
+ export interface CodebaseContextResult {
53
+ pivotFiles: PivotFile[];
54
+ supportingSkeletons: SupportingSkeleton[];
55
+ warnings: string[];
56
+ tokenCount: number;
57
+ executionTimeMs: number;
58
+ }
59
+
60
+ // ---------------------------------------------------------------------------
61
+ // CodebaseContext
62
+ // ---------------------------------------------------------------------------
63
+
64
+ export class CodebaseContext {
65
+ constructor(
66
+ private readonly graphStore: GraphStore | null,
67
+ private readonly vectorStore: VectorStore | null,
68
+ private readonly fileCache: FileContentCache | null,
69
+ private readonly sharingResolver?: SharingResolver,
70
+ ) {}
71
+
72
+ /**
73
+ * Retrieve codebase context for a natural-language query.
74
+ * Uses hybrid search (vector + graph) when both stores are available.
75
+ * Falls back to vector-only when graph is down.
76
+ * Returns empty results with warnings when vector store is unavailable.
77
+ */
78
+ async getContext(
79
+ query: string,
80
+ options: CodebaseContextOptions = {},
81
+ ): Promise<CodebaseContextResult> {
82
+ const startTime = Date.now();
83
+ const warnings: string[] = [];
84
+ const {
85
+ repoId,
86
+ detail = 'full',
87
+ maxResults = 10,
88
+ includeTests = false,
89
+ includeCrossRepo = true,
90
+ maxTokens = 8000,
91
+ vectorWeight,
92
+ graphWeight,
93
+ } = options;
94
+
95
+ // Guard: no vector store means no code search at all
96
+ if (!this.vectorStore) {
97
+ return {
98
+ pivotFiles: [],
99
+ supportingSkeletons: [],
100
+ warnings: ['Vector store not configured — codebase context unavailable'],
101
+ tokenCount: 0,
102
+ executionTimeMs: Date.now() - startTime,
103
+ };
104
+ }
105
+
106
+ const vectorHealthy = await this.vectorStore.isHealthy();
107
+ if (!vectorHealthy) {
108
+ return {
109
+ pivotFiles: [],
110
+ supportingSkeletons: [],
111
+ warnings: ['Vector store (Qdrant) is unavailable — codebase context unavailable'],
112
+ tokenCount: 0,
113
+ executionTimeMs: Date.now() - startTime,
114
+ };
115
+ }
116
+
117
+ const graphHealthy = this.graphStore
118
+ ? await this.graphStore.isHealthy()
119
+ : false;
120
+ if (!graphHealthy) {
121
+ warnings.push('Graph store (FalkorDB) is unavailable — using vector-only search');
122
+ }
123
+
124
+ // Use a no-op graph store when graph is unhealthy to satisfy hybridSearch signature
125
+ const effectiveGraph = graphHealthy && this.graphStore
126
+ ? this.graphStore
127
+ : createNullGraphStore();
128
+
129
+ let searchResults;
130
+ try {
131
+ searchResults = await hybridSearch(
132
+ this.vectorStore,
133
+ effectiveGraph,
134
+ {
135
+ query,
136
+ repoId,
137
+ limit: maxResults * 2, // fetch extra to fill budget after skeletons split
138
+ includeTests,
139
+ vectorWeight,
140
+ graphWeight,
141
+ },
142
+ );
143
+ } catch (err) {
144
+ logger.warn('CodebaseContext: hybrid search failed', { error: String(err) });
145
+ return {
146
+ pivotFiles: [],
147
+ supportingSkeletons: [],
148
+ warnings: [`Search failed: ${String(err)}`],
149
+ tokenCount: 0,
150
+ executionTimeMs: Date.now() - startTime,
151
+ };
152
+ }
153
+
154
+ // Sharing enforcement: filter out results from private repos that aren't
155
+ // the caller's own repo. Only applies when includeCrossRepo is true and
156
+ // a sharingResolver is available.
157
+ if (includeCrossRepo && this.sharingResolver && repoId) {
158
+ const sharingCache = new Map<string, RepoSharing | undefined>();
159
+ searchResults.results = searchResults.results.filter(r => {
160
+ // Own repo results always pass
161
+ if (r.repoId === repoId) return true;
162
+
163
+ // Look up sharing for the result's repo
164
+ if (!sharingCache.has(r.repoId)) {
165
+ sharingCache.set(r.repoId, this.sharingResolver!(r.repoId));
166
+ }
167
+ const sharing = sharingCache.get(r.repoId);
168
+
169
+ // Only include results from team/public repos
170
+ return sharing === 'team' || sharing === 'public';
171
+ });
172
+ } else if (includeCrossRepo && this.sharingResolver && !repoId) {
173
+ // No caller repo context — only allow team/public repos
174
+ const sharingCache = new Map<string, RepoSharing | undefined>();
175
+ searchResults.results = searchResults.results.filter(r => {
176
+ if (!sharingCache.has(r.repoId)) {
177
+ sharingCache.set(r.repoId, this.sharingResolver!(r.repoId));
178
+ }
179
+ const sharing = sharingCache.get(r.repoId);
180
+ return sharing === 'team' || sharing === 'public';
181
+ });
182
+ }
183
+
184
+ const pivotFiles: PivotFile[] = [];
185
+ const supportingSkeletons: SupportingSkeleton[] = [];
186
+ let usedTokens = 0;
187
+ const tokenBudget = maxTokens;
188
+
189
+ for (const result of searchResults.results.slice(0, maxResults)) {
190
+ const { filePath, finalScore, matchReason } = result;
191
+
192
+ if (detail === 'paths') {
193
+ // No content — just return file paths as minimal pivot entries
194
+ pivotFiles.push({
195
+ filePath,
196
+ content: '',
197
+ relevanceScore: Math.round(finalScore * 1000) / 1000,
198
+ matchReason,
199
+ });
200
+ continue;
201
+ }
202
+
203
+ // Try to read file content
204
+ const content = this.readFile(filePath, repoId);
205
+ if (content === null) {
206
+ // File not readable — add as skeleton with just the path
207
+ supportingSkeletons.push({
208
+ filePath,
209
+ skeleton: `// File not readable: ${filePath}`,
210
+ relevanceScore: Math.round(finalScore * 1000) / 1000,
211
+ });
212
+ continue;
213
+ }
214
+
215
+ const contentTokens = estimateTokens(content);
216
+
217
+ if (detail === 'full' && usedTokens + contentTokens <= tokenBudget) {
218
+ pivotFiles.push({
219
+ filePath,
220
+ content,
221
+ relevanceScore: Math.round(finalScore * 1000) / 1000,
222
+ matchReason,
223
+ });
224
+ usedTokens += contentTokens;
225
+ } else if (detail === 'skeleton' || usedTokens + contentTokens > tokenBudget) {
226
+ // Build a structural skeleton (exports and top-level declarations only)
227
+ const skeleton = buildSkeleton(content, filePath);
228
+ const skeletonTokens = estimateTokens(skeleton);
229
+
230
+ if (usedTokens + skeletonTokens <= tokenBudget) {
231
+ supportingSkeletons.push({
232
+ filePath,
233
+ skeleton,
234
+ relevanceScore: Math.round(finalScore * 1000) / 1000,
235
+ });
236
+ usedTokens += skeletonTokens;
237
+ }
238
+ // If even the skeleton is too big, omit this file entirely
239
+ }
240
+ }
241
+
242
+ const tokenCount = pivotFiles.reduce(
243
+ (sum, f) => sum + estimateTokens(f.content),
244
+ 0,
245
+ ) + supportingSkeletons.reduce(
246
+ (sum, s) => sum + estimateTokens(s.skeleton),
247
+ 0,
248
+ );
249
+
250
+ logger.debug('CodebaseContext: context assembled', {
251
+ query: query.slice(0, 50),
252
+ pivots: pivotFiles.length,
253
+ skeletons: supportingSkeletons.length,
254
+ tokenCount,
255
+ durationMs: Date.now() - startTime,
256
+ });
257
+
258
+ return {
259
+ pivotFiles,
260
+ supportingSkeletons,
261
+ warnings,
262
+ tokenCount,
263
+ executionTimeMs: Date.now() - startTime,
264
+ };
265
+ }
266
+
267
+ /** True when at least the vector store is configured and reachable. */
268
+ isAvailable(): boolean {
269
+ // Synchronous best-effort check — callers that need precision should await getContext()
270
+ return this.vectorStore !== null;
271
+ }
272
+
273
+ // ---------------------------------------------------------------------------
274
+ // Private helpers
275
+ // ---------------------------------------------------------------------------
276
+
277
+ /**
278
+ * Read file content. Checks cache first; falls back to disk read.
279
+ * Returns null if the file cannot be read.
280
+ */
281
+ private readFile(filePath: string, repoId?: string): string | null {
282
+ // Try cache first
283
+ if (this.fileCache && repoId) {
284
+ const cached = this.fileCache.get(repoId, filePath);
285
+ if (cached) return cached.content;
286
+ }
287
+
288
+ // Disk read
289
+ try {
290
+ if (!existsSync(filePath)) return null;
291
+ const content = readFileSync(filePath, 'utf8');
292
+
293
+ // Populate cache for future hits
294
+ if (this.fileCache && repoId) {
295
+ this.fileCache.set(repoId, filePath, content, '');
296
+ }
297
+
298
+ return content;
299
+ } catch {
300
+ return null;
301
+ }
302
+ }
303
+ }
304
+
305
+ // ---------------------------------------------------------------------------
306
+ // Skeleton builder
307
+ // ---------------------------------------------------------------------------
308
+
309
+ /**
310
+ * Build a token-efficient skeleton of a TypeScript/JavaScript file.
311
+ * Extracts export declarations, class names, function signatures, and
312
+ * interface/type definitions without the full bodies.
313
+ */
314
+ function buildSkeleton(content: string, filePath: string): string {
315
+ const lines = content.split('\n');
316
+ const skeleton: string[] = [`// Skeleton: ${filePath}`];
317
+
318
+ const KEEP_PATTERNS = [
319
+ /^export\s+(default\s+)?class\s+/,
320
+ /^export\s+(default\s+)?function\s+/,
321
+ /^export\s+(default\s+)?async\s+function\s+/,
322
+ /^export\s+(default\s+)?interface\s+/,
323
+ /^export\s+(default\s+)?type\s+/,
324
+ /^export\s+(const|let|var)\s+/,
325
+ /^export\s+enum\s+/,
326
+ /^import\s+/,
327
+ /^\/\*\*/, // JSDoc block start
328
+ /^\s+\/\*\*/, // indented JSDoc
329
+ /^class\s+/,
330
+ /^function\s+/,
331
+ /^async\s+function\s+/,
332
+ /^\s+(public|private|protected)\s+(static\s+)?(async\s+)?\w+\s*\(/,
333
+ /^\s+(public|private|protected)\s+(readonly\s+)?\w+[\?!]?\s*:/,
334
+ ];
335
+
336
+ let inDocBlock = false;
337
+ let depth = 0;
338
+
339
+ for (let i = 0; i < lines.length; i++) {
340
+ const line = lines[i]!;
341
+ const trimmed = line.trim();
342
+
343
+ // Track JSDoc blocks
344
+ if (trimmed.startsWith('/**')) {
345
+ inDocBlock = true;
346
+ }
347
+ if (inDocBlock) {
348
+ skeleton.push(line);
349
+ if (trimmed.includes('*/')) inDocBlock = false;
350
+ continue;
351
+ }
352
+
353
+ // Track brace depth to identify top-level vs nested
354
+ const openBraces = (line.match(/\{/g) ?? []).length;
355
+ const closeBraces = (line.match(/\}/g) ?? []).length;
356
+
357
+ // Include lines that match key patterns OR are at top level (depth 0)
358
+ const isKeyLine = KEEP_PATTERNS.some((p) => p.test(line));
359
+
360
+ if (depth <= 1 && (isKeyLine || trimmed === '')) {
361
+ // For function/class bodies, show only the signature line
362
+ if (trimmed.endsWith('{') && !trimmed.startsWith('//')) {
363
+ skeleton.push(line.replace(/\{$/, '{ ... }'));
364
+ } else {
365
+ skeleton.push(line);
366
+ }
367
+ }
368
+
369
+ depth += openBraces - closeBraces;
370
+ if (depth < 0) depth = 0;
371
+ }
372
+
373
+ return skeleton.join('\n');
374
+ }
375
+
376
+ // ---------------------------------------------------------------------------
377
+ // Null graph store for vector-only degradation
378
+ // ---------------------------------------------------------------------------
379
+
380
+ function createNullGraphStore(): GraphStore {
381
+ return {
382
+ connect: async () => {},
383
+ disconnect: async () => {},
384
+ isHealthy: async () => false,
385
+ query: async () => ({ nodes: [], edges: [], raw: [] }),
386
+ upsertNode: async () => {},
387
+ upsertEdge: async () => {},
388
+ deleteFile: async () => {},
389
+ deleteRepo: async () => {},
390
+ getCounts: async () => ({ totalNodes: 0, totalEdges: 0, byLabel: {} }),
391
+ ensureIndexes: async () => {},
392
+ };
393
+ }