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,263 @@
1
+ /**
2
+ * Hybrid search engine combining vector similarity + graph neighbor boost.
3
+ * Final scoring: 0.6 * vector_score + 0.3 * graph_centrality + 0.1 * recency_boost
4
+ *
5
+ * Phase 2: Full graph neighbor expansion.
6
+ * For each vector hit, traverse graph neighbors (IMPORTS, CALLS, TESTS, CO_MODIFIED)
7
+ * up to pivot_depth hops, collect neighbor file paths, and boost their scores.
8
+ * Graph centrality = number of times a file appears as a neighbor / max neighbor appearances.
9
+ */
10
+ import { embedText } from '../ingestion/embedder.js';
11
+ import { computeScore, deduplicateByFile, buildMatchReason } from './ranking.js';
12
+ import { QUERY_FILE_NEIGHBORS, QUERY_FILE_HOTSPOTS } from './graph-queries.js';
13
+ import { logger } from '../util/logger.js';
14
+ /**
15
+ * Perform hybrid search over indexed code chunks.
16
+ * Returns deduplicated, ranked results by file.
17
+ */
18
+ export async function hybridSearch(vectorStore, graphStore, options) {
19
+ const startTime = Date.now();
20
+ const { query, repoId, limit = 20, includeTests = false, pivotDepth = 2, vectorWeight = 0.55, graphWeight = 0.20, intent, } = options;
21
+ try {
22
+ // Step 1: Embed query
23
+ const queryVector = await embedText(query);
24
+ // Step 2: Vector search
25
+ const filter = {};
26
+ if (repoId)
27
+ filter['repo_id'] = repoId;
28
+ const vectorResults = await vectorStore.searchCodeChunks(queryVector, {
29
+ limit: limit * 2, // Get extra to allow deduplication
30
+ filter: Object.keys(filter).length > 0 ? filter : undefined,
31
+ scoreThreshold: 0.1,
32
+ });
33
+ // Step 3: Filter test files if needed
34
+ const filteredResults = vectorResults.filter(r => {
35
+ const payload = r.payload;
36
+ if (!includeTests) {
37
+ const fp = payload.file_path ?? '';
38
+ if (fp.includes('.spec.') || fp.includes('.test.') || fp.includes('__tests__')) {
39
+ return false;
40
+ }
41
+ }
42
+ return true;
43
+ });
44
+ // Step 4: Graph neighbor expansion
45
+ // For each unique file in vector results, traverse graph neighbors and
46
+ // collect how often each neighboring file appears (centrality count).
47
+ const neighborCounts = new Map(); // filePath -> appearance count
48
+ const vectorFileSet = new Set(filteredResults.map(r => r.payload.file_path));
49
+ const graphHealthy = await graphStore.isHealthy();
50
+ if (!graphHealthy && repoId) {
51
+ logger.warn('Graph store is unhealthy — skipping graph expansion (vector-only mode)', {
52
+ query: query.slice(0, 50),
53
+ repoId,
54
+ });
55
+ }
56
+ if (graphHealthy && repoId) {
57
+ const uniqueFiles = Array.from(vectorFileSet);
58
+ // Query graph neighbors for each vector hit file
59
+ await Promise.all(uniqueFiles.map(async (filePath) => {
60
+ try {
61
+ const result = await graphStore.query(QUERY_FILE_NEIGHBORS(filePath, repoId, pivotDepth));
62
+ // Parse neighbor paths from raw result
63
+ const rows = result.raw ?? [];
64
+ for (const row of rows) {
65
+ const neighborPath = extractNeighborPath(row);
66
+ if (neighborPath && neighborPath !== filePath) {
67
+ neighborCounts.set(neighborPath, (neighborCounts.get(neighborPath) ?? 0) + 1);
68
+ }
69
+ }
70
+ }
71
+ catch {
72
+ // Graph query failure is non-fatal — degrade to vector-only
73
+ }
74
+ }));
75
+ }
76
+ // Step 5: Compute normalized graph centrality scores
77
+ const maxNeighborCount = neighborCounts.size > 0
78
+ ? Math.max(...neighborCounts.values())
79
+ : 1;
80
+ // Step 5b: Fetch file hotspot scores from FalkorDB File node commit_count
81
+ const hotspotMap = new Map(); // filePath -> normalized hotspot score
82
+ const useHotspot = intent === 'modify' || intent === 'debug' || intent === 'refactor';
83
+ if (useHotspot && graphHealthy && repoId) {
84
+ try {
85
+ const hotspotResult = await graphStore.query(QUERY_FILE_HOTSPOTS(repoId, 100));
86
+ const rows = hotspotResult.raw ?? [];
87
+ let maxCommitCount = 1;
88
+ // First pass: find max commit count
89
+ for (const row of rows) {
90
+ const commitCount = extractHotspotCommitCount(row);
91
+ if (commitCount > maxCommitCount)
92
+ maxCommitCount = commitCount;
93
+ }
94
+ // Second pass: normalize
95
+ for (const row of rows) {
96
+ const path = extractHotspotPath(row);
97
+ const commitCount = extractHotspotCommitCount(row);
98
+ if (path && commitCount > 0) {
99
+ hotspotMap.set(path, commitCount / maxCommitCount);
100
+ }
101
+ }
102
+ }
103
+ catch {
104
+ // Hotspot query failure is non-fatal
105
+ logger.debug('Hotspot query failed — skipping hotspot scoring');
106
+ }
107
+ }
108
+ // Step 6: Convert to ScoredResult with combined scores
109
+ const scored = filteredResults.map(r => {
110
+ const payload = r.payload;
111
+ const filePath = payload.file_path;
112
+ // Graph score: normalized neighbor appearance count
113
+ // Files that appear as neighbors of many vector hits get boosted
114
+ const rawGraphScore = neighborCounts.get(filePath) ?? 0;
115
+ const graphCentrality = maxNeighborCount > 0 ? rawGraphScore / maxNeighborCount : 0;
116
+ // Hotspot score: normalized commit count (0 for read intent)
117
+ const hotspotScore = useHotspot ? (hotspotMap.get(filePath) ?? 0) : 0;
118
+ const { finalScore, recencyScore } = computeScore(r.score, graphCentrality, payload.indexed_at ?? Date.now(), vectorWeight, graphWeight, undefined, // recencyWeight — use default
119
+ hotspotScore, undefined, // hotspotWeight — use default
120
+ 0, // observationScore — Phase 4
121
+ undefined // observationWeight — use default
122
+ );
123
+ return {
124
+ filePath,
125
+ repoId: payload.repo_id,
126
+ vectorScore: r.score,
127
+ graphScore: graphCentrality,
128
+ recencyScore,
129
+ hotspotScore,
130
+ observationScore: 0,
131
+ finalScore,
132
+ entityName: payload.entity_name,
133
+ entityType: payload.entity_type,
134
+ startLine: payload.start_line,
135
+ endLine: payload.end_line,
136
+ matchReason: buildMatchReason(r.score, graphCentrality, payload.entity_name, payload.entity_type, hotspotScore),
137
+ indexedAt: payload.indexed_at,
138
+ };
139
+ });
140
+ // Step 7: Add neighbor files that scored above threshold but weren't in vector results
141
+ // These are files boosted purely by graph centrality (indirect relevance)
142
+ for (const [neighborPath, count] of neighborCounts) {
143
+ if (vectorFileSet.has(neighborPath))
144
+ continue; // Already in vector results
145
+ // Skip test files if not requested
146
+ if (!includeTests) {
147
+ if (neighborPath.includes('.spec.') ||
148
+ neighborPath.includes('.test.') ||
149
+ neighborPath.includes('__tests__'))
150
+ continue;
151
+ }
152
+ const normalizedCount = count / maxNeighborCount;
153
+ if (normalizedCount < 0.3)
154
+ continue; // Only include strongly-connected neighbors
155
+ const neighborHotspot = useHotspot ? (hotspotMap.get(neighborPath) ?? 0) : 0;
156
+ const { finalScore, recencyScore } = computeScore(0, // No direct vector score
157
+ normalizedCount, Date.now(), // Unknown indexed_at for neighbor-only results
158
+ vectorWeight, graphWeight, undefined, neighborHotspot, undefined, 0, undefined);
159
+ scored.push({
160
+ filePath: neighborPath,
161
+ repoId: repoId ?? '',
162
+ vectorScore: 0,
163
+ graphScore: normalizedCount,
164
+ recencyScore,
165
+ hotspotScore: neighborHotspot,
166
+ observationScore: 0,
167
+ finalScore,
168
+ entityName: null,
169
+ entityType: 'file_level',
170
+ startLine: 0,
171
+ endLine: 0,
172
+ matchReason: buildMatchReason(0, normalizedCount, null, 'file_level', neighborHotspot),
173
+ indexedAt: undefined,
174
+ });
175
+ }
176
+ // Step 8: Deduplicate by file, keep highest score per file
177
+ const deduplicated = deduplicateByFile(scored);
178
+ logger.debug('Hybrid search completed', {
179
+ query: query.slice(0, 50),
180
+ vectorHits: vectorResults.length,
181
+ filteredHits: filteredResults.length,
182
+ neighborFiles: neighborCounts.size,
183
+ uniqueFiles: deduplicated.length,
184
+ durationMs: Date.now() - startTime,
185
+ });
186
+ return {
187
+ results: deduplicated.slice(0, limit),
188
+ cacheHits: 0, // Tracked by FileContentCache in tool handler
189
+ executionTimeMs: Date.now() - startTime,
190
+ };
191
+ }
192
+ catch (err) {
193
+ logger.error('Hybrid search failed', { query: query.slice(0, 50), error: String(err) });
194
+ return {
195
+ results: [],
196
+ cacheHits: 0,
197
+ executionTimeMs: Date.now() - startTime,
198
+ };
199
+ }
200
+ }
201
+ /**
202
+ * Extract neighbor file path from a raw FalkorDB query result row.
203
+ * QUERY_FILE_NEIGHBORS returns: RETURN neighbor.path as path, ...
204
+ * FalkorDB non-compact format: [header, [rows], stats]
205
+ * Each row cell for an alias like `path` is a scalar string.
206
+ */
207
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
208
+ function extractNeighborPath(row) {
209
+ if (!row)
210
+ return null;
211
+ // Row is an array of cell values (one per column in SELECT)
212
+ // Column order: [path, rel_type, depth]
213
+ if (Array.isArray(row)) {
214
+ const first = row[0];
215
+ if (typeof first === 'string')
216
+ return first;
217
+ }
218
+ // Object row format (some parsers return keyed objects)
219
+ if (typeof row === 'object' && row !== null) {
220
+ if (typeof row.path === 'string')
221
+ return row.path;
222
+ }
223
+ return null;
224
+ }
225
+ /**
226
+ * Extract file path from a QUERY_FILE_HOTSPOTS result row.
227
+ * Column order: [path, commit_count, stability_score, change_velocity]
228
+ */
229
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
230
+ function extractHotspotPath(row) {
231
+ if (!row)
232
+ return null;
233
+ if (Array.isArray(row)) {
234
+ const first = row[0];
235
+ if (typeof first === 'string')
236
+ return first;
237
+ }
238
+ if (typeof row === 'object' && row !== null) {
239
+ if (typeof row.path === 'string')
240
+ return row.path;
241
+ }
242
+ return null;
243
+ }
244
+ /**
245
+ * Extract commit_count from a QUERY_FILE_HOTSPOTS result row.
246
+ * Column order: [path, commit_count, stability_score, change_velocity]
247
+ */
248
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
249
+ function extractHotspotCommitCount(row) {
250
+ if (!row)
251
+ return 0;
252
+ if (Array.isArray(row)) {
253
+ const second = row[1];
254
+ if (typeof second === 'number')
255
+ return second;
256
+ }
257
+ if (typeof row === 'object' && row !== null) {
258
+ if (typeof row.commit_count === 'number')
259
+ return row.commit_count;
260
+ }
261
+ return 0;
262
+ }
263
+ //# sourceMappingURL=hybrid-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid-search.js","sourceRoot":"","sources":["../../src/query/hybrid-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Query intent classifier using keyword matching (Phase 1).
3
+ * Classifies queries as: read | modify | debug | refactor
4
+ * Phase 4 will enhance with ML-based classification.
5
+ */
6
+ import type { QueryIntent } from '../util/types.js';
7
+ /**
8
+ * Detect the intent of a query string.
9
+ * Returns the intent category with highest keyword match count.
10
+ * Default: 'read' (safest, most common).
11
+ */
12
+ export declare function detectIntent(query: string): QueryIntent;
13
+ /**
14
+ * Get retrieval strategy adjustments based on intent.
15
+ * These affect ranking weights and result composition.
16
+ *
17
+ * Phase 4: 5-signal weights (vector, graph, recency, hotspot, observation).
18
+ *
19
+ * | Intent | Vector | Graph | Recency | Hotspot | Observation |
20
+ * |----------|--------|-------|---------|---------|-------------|
21
+ * | read | 0.55 | 0.20 | 0.05 | 0.10 | 0.10 |
22
+ * | modify | 0.50 | 0.20 | 0.08 | 0.12 | 0.10 |
23
+ * | debug | 0.40 | 0.25 | 0.05 | 0.10 | 0.20 |
24
+ * | refactor | 0.35 | 0.30 | 0.05 | 0.15 | 0.15 |
25
+ */
26
+ export declare function getIntentStrategy(intent: QueryIntent): {
27
+ vectorWeight: number;
28
+ graphWeight: number;
29
+ recencyWeight: number;
30
+ hotspotWeight: number;
31
+ observationWeight: number;
32
+ includeTests: boolean;
33
+ expandDepth: number;
34
+ };
35
+ //# sourceMappingURL=intent-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-detector.d.ts","sourceRoot":"","sources":["../../src/query/intent-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA2BpD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAyBvD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB,CA4CA"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Query intent classifier using keyword matching (Phase 1).
3
+ * Classifies queries as: read | modify | debug | refactor
4
+ * Phase 4 will enhance with ML-based classification.
5
+ */
6
+ const INTENT_KEYWORDS = {
7
+ debug: [
8
+ 'error', 'bug', 'fix', 'broken', 'failing', 'crash', 'exception',
9
+ 'undefined', 'null', 'TypeError', 'undefined is not', 'cannot read',
10
+ 'stack trace', 'stacktrace', 'traceback', 'debug', 'diagnose', 'why is',
11
+ 'not working', 'breaks', 'issue', 'problem', 'wrong', 'incorrect',
12
+ ],
13
+ refactor: [
14
+ 'refactor', 'restructure', 'reorganize', 'extract', 'move', 'rename',
15
+ 'split', 'merge', 'clean up', 'cleanup', 'simplify', 'optimize',
16
+ 'performance', 'improve', 'better', 'smell', 'technical debt', 'dead code',
17
+ 'duplicate', 'dry', 'abstract',
18
+ ],
19
+ modify: [
20
+ 'add', 'implement', 'create', 'build', 'write', 'update', 'change',
21
+ 'modify', 'edit', 'extend', 'enhance', 'feature', 'new', 'support',
22
+ 'integrate', 'connect', 'wire', 'hook up', 'plug in', 'configure',
23
+ ],
24
+ read: [
25
+ 'how', 'what', 'where', 'explain', 'understand', 'show', 'list',
26
+ 'find', 'search', 'look', 'describe', 'overview', 'structure', 'schema',
27
+ 'architecture', 'flow', 'logic', 'context', 'about', 'definition',
28
+ ],
29
+ };
30
+ /**
31
+ * Detect the intent of a query string.
32
+ * Returns the intent category with highest keyword match count.
33
+ * Default: 'read' (safest, most common).
34
+ */
35
+ export function detectIntent(query) {
36
+ const lowerQuery = query.toLowerCase();
37
+ const scores = { debug: 0, refactor: 0, modify: 0, read: 0 };
38
+ for (const [intent, keywords] of Object.entries(INTENT_KEYWORDS)) {
39
+ for (const keyword of keywords) {
40
+ if (lowerQuery.includes(keyword)) {
41
+ scores[intent]++;
42
+ }
43
+ }
44
+ }
45
+ // Find intent with highest score
46
+ let maxScore = 0;
47
+ let detectedIntent = 'read';
48
+ // Priority: debug > refactor > modify > read (more specific wins on tie)
49
+ for (const intent of ['debug', 'refactor', 'modify', 'read']) {
50
+ if (scores[intent] > maxScore) {
51
+ maxScore = scores[intent];
52
+ detectedIntent = intent;
53
+ }
54
+ }
55
+ return detectedIntent;
56
+ }
57
+ /**
58
+ * Get retrieval strategy adjustments based on intent.
59
+ * These affect ranking weights and result composition.
60
+ *
61
+ * Phase 4: 5-signal weights (vector, graph, recency, hotspot, observation).
62
+ *
63
+ * | Intent | Vector | Graph | Recency | Hotspot | Observation |
64
+ * |----------|--------|-------|---------|---------|-------------|
65
+ * | read | 0.55 | 0.20 | 0.05 | 0.10 | 0.10 |
66
+ * | modify | 0.50 | 0.20 | 0.08 | 0.12 | 0.10 |
67
+ * | debug | 0.40 | 0.25 | 0.05 | 0.10 | 0.20 |
68
+ * | refactor | 0.35 | 0.30 | 0.05 | 0.15 | 0.15 |
69
+ */
70
+ export function getIntentStrategy(intent) {
71
+ switch (intent) {
72
+ case 'debug':
73
+ return {
74
+ vectorWeight: 0.40,
75
+ graphWeight: 0.25,
76
+ recencyWeight: 0.05,
77
+ hotspotWeight: 0.10,
78
+ observationWeight: 0.20, // Observations are critical for debugging
79
+ includeTests: true, // Tests often show error scenarios
80
+ expandDepth: 3,
81
+ };
82
+ case 'refactor':
83
+ return {
84
+ vectorWeight: 0.35,
85
+ graphWeight: 0.30, // Blast radius is critical for refactoring
86
+ recencyWeight: 0.05,
87
+ hotspotWeight: 0.15, // Hotspots indicate high-churn areas
88
+ observationWeight: 0.15,
89
+ includeTests: true,
90
+ expandDepth: 3,
91
+ };
92
+ case 'modify':
93
+ return {
94
+ vectorWeight: 0.50,
95
+ graphWeight: 0.20,
96
+ recencyWeight: 0.08,
97
+ hotspotWeight: 0.12,
98
+ observationWeight: 0.10,
99
+ includeTests: false,
100
+ expandDepth: 2,
101
+ };
102
+ case 'read':
103
+ default:
104
+ return {
105
+ vectorWeight: 0.55,
106
+ graphWeight: 0.20,
107
+ recencyWeight: 0.05,
108
+ hotspotWeight: 0.10,
109
+ observationWeight: 0.10,
110
+ includeTests: false,
111
+ expandDepth: 2,
112
+ };
113
+ }
114
+ }
115
+ //# sourceMappingURL=intent-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-detector.js","sourceRoot":"","sources":["../../src/query/intent-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Result ranking and scoring for hybrid search.
3
+ * Phase 1: Vector score only (graph_centrality added in Phase 2).
4
+ * Phase 3: 4-signal scoring with hotspot.
5
+ * Phase 4: 5-signal scoring with observation relevance.
6
+ *
7
+ * Default weights: 0.55 vector + 0.20 graph + 0.05 recency + 0.10 hotspot + 0.10 observation
8
+ * All new weights are backward-compatible (default to 0).
9
+ */
10
+ export interface ScoredResult {
11
+ filePath: string;
12
+ repoId: string;
13
+ vectorScore: number;
14
+ graphScore: number;
15
+ recencyScore: number;
16
+ hotspotScore: number;
17
+ observationScore: number;
18
+ finalScore: number;
19
+ entityName: string | null;
20
+ entityType: string;
21
+ startLine: number;
22
+ endLine: number;
23
+ matchReason: string;
24
+ indexedAt?: number;
25
+ }
26
+ /**
27
+ * Compute final ranking score combining up to 5 signals:
28
+ * vector, graph, recency, hotspot, observation.
29
+ *
30
+ * Backward-compatible: hotspotScore and observationScore default to 0,
31
+ * with their weights redistributed to maintain consistent scoring
32
+ * when callers haven't been updated to supply them.
33
+ */
34
+ export declare function computeScore(vectorScore: number, graphScore: number, indexedAt: number, vectorWeight?: number, graphWeight?: number, recencyWeight?: number, hotspotScore?: number, hotspotWeight?: number, observationScore?: number, observationWeight?: number): {
35
+ finalScore: number;
36
+ recencyScore: number;
37
+ };
38
+ /**
39
+ * Deduplicate results by file path, keeping the highest-scored entry per file.
40
+ */
41
+ export declare function deduplicateByFile(results: ScoredResult[]): ScoredResult[];
42
+ /**
43
+ * Split results into pivot files (full content) and skeletons (summaries) using actual token sizes.
44
+ * If fileSizes is provided (map of filePath -> estimated tokens), uses real sizes.
45
+ * Otherwise falls back to avgFileTokens estimate.
46
+ */
47
+ export declare function splitPivotsAndSkeletons(results: ScoredResult[], tokenBudget: number, fileSizes?: Map<string, number>, avgFileTokens?: number): {
48
+ pivots: ScoredResult[];
49
+ skeletons: ScoredResult[];
50
+ };
51
+ /**
52
+ * Generate a human-readable match reason string.
53
+ * Phase 3: includes hotspot info.
54
+ * Phase 4: includes observation info.
55
+ */
56
+ export declare function buildMatchReason(vectorScore: number, graphScore: number, entityName: string | null, entityType: string, hotspotScore?: number, observationScore?: number): string;
57
+ //# sourceMappingURL=ranking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ranking.d.ts","sourceRoot":"","sources":["../../src/query/ranking.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,YAAY,SAAgB,EAC5B,WAAW,SAAe,EAC1B,aAAa,SAAiB,EAC9B,YAAY,GAAE,MAAU,EACxB,aAAa,GAAE,MAAuB,EACtC,gBAAgB,GAAE,MAAU,EAC5B,iBAAiB,GAAE,MAA2B,GAC7C;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAa9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAWzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,YAAY,EAAE,EACvB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,aAAa,GAAE,MAAY,GAC1B;IAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,SAAS,EAAE,YAAY,EAAE,CAAA;CAAE,CAgBvD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,MAAU,EACxB,gBAAgB,GAAE,MAAU,GAC3B,MAAM,CAkCR"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Result ranking and scoring for hybrid search.
3
+ * Phase 1: Vector score only (graph_centrality added in Phase 2).
4
+ * Phase 3: 4-signal scoring with hotspot.
5
+ * Phase 4: 5-signal scoring with observation relevance.
6
+ *
7
+ * Default weights: 0.55 vector + 0.20 graph + 0.05 recency + 0.10 hotspot + 0.10 observation
8
+ * All new weights are backward-compatible (default to 0).
9
+ */
10
+ const VECTOR_WEIGHT = 0.55;
11
+ const GRAPH_WEIGHT = 0.20;
12
+ const RECENCY_WEIGHT = 0.05;
13
+ const HOTSPOT_WEIGHT = 0.10;
14
+ const OBSERVATION_WEIGHT = 0.10;
15
+ // Recency boost: files indexed within the last hour get a small boost
16
+ const RECENCY_WINDOW_MS = 60 * 60 * 1000; // 1 hour
17
+ /**
18
+ * Compute final ranking score combining up to 5 signals:
19
+ * vector, graph, recency, hotspot, observation.
20
+ *
21
+ * Backward-compatible: hotspotScore and observationScore default to 0,
22
+ * with their weights redistributed to maintain consistent scoring
23
+ * when callers haven't been updated to supply them.
24
+ */
25
+ export function computeScore(vectorScore, graphScore, indexedAt, vectorWeight = VECTOR_WEIGHT, graphWeight = GRAPH_WEIGHT, recencyWeight = RECENCY_WEIGHT, hotspotScore = 0, hotspotWeight = HOTSPOT_WEIGHT, observationScore = 0, observationWeight = OBSERVATION_WEIGHT) {
26
+ const now = Date.now();
27
+ const age = now - indexedAt;
28
+ const recencyScore = age < RECENCY_WINDOW_MS ? 1.0 - (age / RECENCY_WINDOW_MS) : 0;
29
+ const finalScore = vectorWeight * vectorScore +
30
+ graphWeight * graphScore +
31
+ recencyWeight * recencyScore +
32
+ hotspotWeight * hotspotScore +
33
+ observationWeight * observationScore;
34
+ return { finalScore, recencyScore };
35
+ }
36
+ /**
37
+ * Deduplicate results by file path, keeping the highest-scored entry per file.
38
+ */
39
+ export function deduplicateByFile(results) {
40
+ const byFile = new Map();
41
+ for (const result of results) {
42
+ const existing = byFile.get(result.filePath);
43
+ if (!existing || result.finalScore > existing.finalScore) {
44
+ byFile.set(result.filePath, result);
45
+ }
46
+ }
47
+ return Array.from(byFile.values()).sort((a, b) => b.finalScore - a.finalScore);
48
+ }
49
+ /**
50
+ * Split results into pivot files (full content) and skeletons (summaries) using actual token sizes.
51
+ * If fileSizes is provided (map of filePath -> estimated tokens), uses real sizes.
52
+ * Otherwise falls back to avgFileTokens estimate.
53
+ */
54
+ export function splitPivotsAndSkeletons(results, tokenBudget, fileSizes, avgFileTokens = 500) {
55
+ const pivots = [];
56
+ const skeletons = [];
57
+ let usedTokens = 0;
58
+ for (const result of results) {
59
+ const fileTokens = fileSizes?.get(result.filePath) ?? avgFileTokens;
60
+ if (usedTokens + fileTokens <= tokenBudget) {
61
+ pivots.push(result);
62
+ usedTokens += fileTokens;
63
+ }
64
+ else {
65
+ skeletons.push(result);
66
+ }
67
+ }
68
+ return { pivots, skeletons };
69
+ }
70
+ /**
71
+ * Generate a human-readable match reason string.
72
+ * Phase 3: includes hotspot info.
73
+ * Phase 4: includes observation info.
74
+ */
75
+ export function buildMatchReason(vectorScore, graphScore, entityName, entityType, hotspotScore = 0, observationScore = 0) {
76
+ const parts = [];
77
+ if (vectorScore > 0.8) {
78
+ parts.push('high semantic similarity');
79
+ }
80
+ else if (vectorScore > 0.5) {
81
+ parts.push('semantic match');
82
+ }
83
+ else {
84
+ parts.push('partial semantic match');
85
+ }
86
+ if (graphScore > 0.5) {
87
+ parts.push('high graph centrality');
88
+ }
89
+ else if (graphScore > 0) {
90
+ parts.push('graph neighbor');
91
+ }
92
+ if (hotspotScore > 0.7) {
93
+ parts.push('change hotspot');
94
+ }
95
+ else if (hotspotScore > 0.3) {
96
+ parts.push('frequently changed');
97
+ }
98
+ if (observationScore > 0.5) {
99
+ parts.push('has relevant observations');
100
+ }
101
+ else if (observationScore > 0) {
102
+ parts.push('has observations');
103
+ }
104
+ if (entityName) {
105
+ parts.push(`entity: ${entityName} (${entityType})`);
106
+ }
107
+ return parts.join(', ');
108
+ }
109
+ //# sourceMappingURL=ranking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ranking.js","sourceRoot":"","sources":["../../src/query/ranking.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function createForgeServer(): Promise<McpServer>;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqDpE,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,SAAS,CAAC,CAyP5D"}