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,262 @@
1
+ // KnowledgeYamlStore — reads and writes .forge/knowledge/*.yaml files.
2
+ //
3
+ // Each file is a YAML array of KnowledgeItem objects. The store maps
4
+ // KnowledgeCategory values to dedicated files so items can be retrieved
5
+ // by category without loading the full corpus.
6
+ //
7
+ // Design notes:
8
+ // - File I/O is synchronous. The MCP server is single-threaded; sync I/O
9
+ // keeps the surface area small and the error handling straightforward.
10
+ // - The store never caches in memory — every read hits the filesystem.
11
+ // This ensures multi-process safety (e.g. CLI + server running together)
12
+ // and keeps memory pressure low for a local dev tool.
13
+ // - getContentHash() enables cheap change detection by the knowledge-keeper
14
+ // agent without re-parsing every item.
15
+
16
+ import { parse, stringify } from 'yaml';
17
+ import {
18
+ readFileSync,
19
+ writeFileSync,
20
+ existsSync,
21
+ mkdirSync,
22
+ statSync,
23
+ } from 'node:fs';
24
+ import { join } from 'node:path';
25
+ import { createHash } from 'node:crypto';
26
+ import type { KnowledgeCategory, KnowledgeItem } from '../util/types.js';
27
+
28
+ // Re-export so callers can import KnowledgeCategory from this module
29
+ // without having to reach into util/types directly.
30
+ export type { KnowledgeCategory, KnowledgeItem } from '../util/types.js';
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Constants
34
+ // ---------------------------------------------------------------------------
35
+
36
+ const CATEGORY_FILES: Record<KnowledgeCategory, string> = {
37
+ gotcha: 'gotchas.yaml',
38
+ pattern: 'patterns.yaml',
39
+ decision: 'decisions.yaml',
40
+ convention: 'conventions.yaml',
41
+ };
42
+
43
+ const ALL_CATEGORIES: KnowledgeCategory[] = ['gotcha', 'pattern', 'decision', 'convention'];
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // KnowledgeYamlStore
47
+ // ---------------------------------------------------------------------------
48
+
49
+ export class KnowledgeYamlStore {
50
+ private readonly knowledgeDir: string;
51
+
52
+ constructor(private readonly forgeDir: string) {
53
+ this.knowledgeDir = join(forgeDir, 'knowledge');
54
+ }
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Public API
58
+ // ---------------------------------------------------------------------------
59
+
60
+ /**
61
+ * Read all items from a single category file.
62
+ * Returns an empty array if the file does not exist or is empty.
63
+ */
64
+ readCategory(category: KnowledgeCategory): KnowledgeItem[] {
65
+ const filePath = this._filePath(category);
66
+ return this._readFile(filePath);
67
+ }
68
+
69
+ /**
70
+ * Read all items across every category file, concatenated into one array.
71
+ * Items from each category are returned in file order, categories in the
72
+ * order defined by ALL_CATEGORIES.
73
+ */
74
+ readAll(): KnowledgeItem[] {
75
+ const result: KnowledgeItem[] = [];
76
+ for (const category of ALL_CATEGORIES) {
77
+ result.push(...this.readCategory(category));
78
+ }
79
+ return result;
80
+ }
81
+
82
+ /**
83
+ * Overwrite a category file with the supplied items array.
84
+ * Creates the knowledge directory if it does not exist.
85
+ * Passing an empty array produces a file containing `[]`.
86
+ */
87
+ writeCategory(category: KnowledgeCategory, items: KnowledgeItem[]): void {
88
+ this._ensureDir();
89
+ const filePath = this._filePath(category);
90
+ const yaml = stringify(items, {
91
+ indent: 2,
92
+ // Use block scalars for long content strings so diffs are readable.
93
+ defaultStringType: 'PLAIN',
94
+ });
95
+ writeFileSync(filePath, yaml, 'utf8');
96
+ }
97
+
98
+ /**
99
+ * Append a single item to the appropriate category file.
100
+ * The category is derived from the item's id prefix:
101
+ * gotcha-* → gotcha
102
+ * pattern-* → pattern
103
+ * decision-* → decision
104
+ * convention-* → convention
105
+ *
106
+ * If the item does not match any prefix, it falls through to the pattern
107
+ * file as a safe default.
108
+ */
109
+ addItem(item: KnowledgeItem): void {
110
+ const category = this._categoryFromItem(item);
111
+ const existing = this.readCategory(category);
112
+
113
+ // Deduplicate by id — if an item with this id already exists, replace it.
114
+ const idx = existing.findIndex((i) => i.id === item.id);
115
+ if (idx >= 0) {
116
+ existing[idx] = item;
117
+ } else {
118
+ existing.push(item);
119
+ }
120
+
121
+ this.writeCategory(category, existing);
122
+ }
123
+
124
+ /**
125
+ * Update an existing item by id across all category files.
126
+ * Applies the supplied partial updates to the first matching item.
127
+ * Returns true if an item was found and updated, false otherwise.
128
+ */
129
+ updateItem(id: string, updates: Partial<KnowledgeItem>): boolean {
130
+ for (const category of ALL_CATEGORIES) {
131
+ const items = this.readCategory(category);
132
+ const idx = items.findIndex((i) => i.id === id);
133
+ if (idx >= 0) {
134
+ items[idx] = {
135
+ ...items[idx]!,
136
+ ...updates,
137
+ // Always bump updated_at when the caller hasn't supplied it.
138
+ updated_at: updates.updated_at ?? Date.now(),
139
+ };
140
+ this.writeCategory(category, items);
141
+ return true;
142
+ }
143
+ }
144
+ return false;
145
+ }
146
+
147
+ /**
148
+ * Remove an item by id across all category files.
149
+ * Returns true if an item was found and removed, false otherwise.
150
+ */
151
+ removeItem(id: string): boolean {
152
+ for (const category of ALL_CATEGORIES) {
153
+ const items = this.readCategory(category);
154
+ const filtered = items.filter((i) => i.id !== id);
155
+ if (filtered.length < items.length) {
156
+ this.writeCategory(category, filtered);
157
+ return true;
158
+ }
159
+ }
160
+ return false;
161
+ }
162
+
163
+ /**
164
+ * Create the .forge/knowledge/ directory and initialise empty YAML files
165
+ * for every category. Existing files are left untouched — initialize() is
166
+ * safe to call multiple times.
167
+ */
168
+ initialize(): void {
169
+ this._ensureDir();
170
+ for (const category of ALL_CATEGORIES) {
171
+ const filePath = this._filePath(category);
172
+ if (!existsSync(filePath)) {
173
+ // Write an empty YAML array so the file is valid YAML from the start.
174
+ writeFileSync(filePath, '[]\n', 'utf8');
175
+ }
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Compute a SHA-256 hash over the concatenated contents of all category
181
+ * files. Files that do not exist contribute an empty string to the hash.
182
+ * The hash changes whenever any item is added, updated, or removed, making
183
+ * it useful for cheap change detection without re-parsing every item.
184
+ */
185
+ getContentHash(): string {
186
+ const hash = createHash('sha256');
187
+ for (const category of ALL_CATEGORIES) {
188
+ const filePath = this._filePath(category);
189
+ if (existsSync(filePath)) {
190
+ const content = readFileSync(filePath, 'utf8');
191
+ hash.update(content);
192
+ } else {
193
+ hash.update('');
194
+ }
195
+ }
196
+ return hash.digest('hex');
197
+ }
198
+
199
+ // ---------------------------------------------------------------------------
200
+ // Private helpers
201
+ // ---------------------------------------------------------------------------
202
+
203
+ /** Absolute path to the YAML file for a given category. */
204
+ private _filePath(category: KnowledgeCategory): string {
205
+ return join(this.knowledgeDir, CATEGORY_FILES[category]);
206
+ }
207
+
208
+ /** Ensure the knowledge directory exists. */
209
+ private _ensureDir(): void {
210
+ if (!existsSync(this.knowledgeDir)) {
211
+ mkdirSync(this.knowledgeDir, { recursive: true });
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Parse a YAML file and return its items.
217
+ * Returns [] when the file is missing, empty, or contains a YAML null
218
+ * (which is what an empty file or `---` alone produces).
219
+ */
220
+ private _readFile(filePath: string): KnowledgeItem[] {
221
+ if (!existsSync(filePath)) {
222
+ return [];
223
+ }
224
+
225
+ // Guard against zero-byte files — parse('') returns null in the yaml
226
+ // package, not an empty array.
227
+ const stat = statSync(filePath);
228
+ if (stat.size === 0) {
229
+ return [];
230
+ }
231
+
232
+ const content = readFileSync(filePath, 'utf8');
233
+ const parsed: unknown = parse(content);
234
+
235
+ if (parsed === null || parsed === undefined) {
236
+ return [];
237
+ }
238
+
239
+ if (!Array.isArray(parsed)) {
240
+ throw new Error(
241
+ `KnowledgeYamlStore: expected array at ${filePath}, got ${typeof parsed}`,
242
+ );
243
+ }
244
+
245
+ // Cast: the YAML is authoritative. Callers writing items go through our
246
+ // typed addItem/writeCategory methods so the shape is always correct.
247
+ return parsed as KnowledgeItem[];
248
+ }
249
+
250
+ /**
251
+ * Derive the KnowledgeCategory for a given item based on its id prefix.
252
+ * Falls back to 'pattern' when the id does not match a known prefix.
253
+ */
254
+ private _categoryFromItem(item: KnowledgeItem): KnowledgeCategory {
255
+ const id = item.id.toLowerCase();
256
+ if (id.startsWith('gotcha')) return 'gotcha';
257
+ if (id.startsWith('pattern')) return 'pattern';
258
+ if (id.startsWith('decision')) return 'decision';
259
+ if (id.startsWith('convention')) return 'convention';
260
+ return 'pattern';
261
+ }
262
+ }
File without changes
@@ -0,0 +1,193 @@
1
+ // ConfidenceManager — B12
2
+ //
3
+ // Manages confidence score lifecycle for knowledge items stored in Qdrant.
4
+ //
5
+ // Confidence represents how well-validated a knowledge item is:
6
+ // 0.0 – pure speculation, has never proven useful
7
+ // 0.5 – moderate confidence, has been seen in a couple of contexts
8
+ // 1.0 – very high confidence, validated across many projects
9
+ //
10
+ // Two operations:
11
+ //
12
+ // decayAll(vectorStore, decayRate)
13
+ // Applies time-based confidence decay to all items that have not been
14
+ // accessed recently. Items accessed within the last 30 days are not
15
+ // decayed. The default decay rate is 0.01 per run (about 1 percentage
16
+ // point). Items whose confidence would fall below MIN_CONFIDENCE (0.1)
17
+ // are floored there rather than deleted — deletion is a policy decision
18
+ // for operators, not an automatic side effect of decay.
19
+ //
20
+ // boost(vectorStore, knowledgeId, amount)
21
+ // Increases the confidence of a specific item by `amount` (default 0.05).
22
+ // Also bumps accessed_at and access_count. Capped at 1.0.
23
+ //
24
+ // Both methods are async and fail silently on Qdrant errors — confidence
25
+ // management is best-effort. It must never block the pipeline.
26
+
27
+ import type { QdrantVectorStore } from '../storage/qdrant-store.js';
28
+ import type { KnowledgePayload } from '../util/types.js';
29
+ import { logger } from '../util/logger.js';
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Constants
33
+ // ---------------------------------------------------------------------------
34
+
35
+ /** Items accessed within this window (ms) are not decayed. */
36
+ const DECAY_GRACE_PERIOD_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
37
+
38
+ /** Items whose confidence falls at or below this value are not decayed further. */
39
+ const MIN_CONFIDENCE = 0.1;
40
+
41
+ /** Maximum confidence a single boost can reach. */
42
+ const MAX_CONFIDENCE = 1.0;
43
+
44
+ /** How many knowledge items to scroll per Qdrant page during decay. */
45
+ const SCROLL_PAGE_SIZE = 100;
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // ConfidenceManager
49
+ // ---------------------------------------------------------------------------
50
+
51
+ export class ConfidenceManager {
52
+ /**
53
+ * Apply time-based confidence decay to all knowledge items in Qdrant.
54
+ *
55
+ * Algorithm:
56
+ * 1. Scroll through all knowledge items in pages of SCROLL_PAGE_SIZE.
57
+ * 2. For each item whose accessed_at is older than DECAY_GRACE_PERIOD_MS:
58
+ * a. Compute new_confidence = max(MIN_CONFIDENCE, confidence - decayRate).
59
+ * b. If new_confidence != confidence, call setPayload to update.
60
+ * 3. Return the total count of items whose confidence was updated.
61
+ *
62
+ * This method is intentionally slow (one HTTP call per decayed item) because
63
+ * it is designed to run as a background task, not in the hot path. A batch
64
+ * update path can be optimised once the volume of knowledge items justifies it.
65
+ */
66
+ async decayAll(
67
+ vectorStore: QdrantVectorStore,
68
+ decayRate: number = 0.01,
69
+ ): Promise<number> {
70
+ const healthy = await vectorStore.isHealthy();
71
+ if (!healthy) {
72
+ logger.warn('ConfidenceManager.decayAll: Qdrant unavailable, skipping decay');
73
+ return 0;
74
+ }
75
+
76
+ const now = Date.now();
77
+ const graceCutoff = now - DECAY_GRACE_PERIOD_MS;
78
+ let decayedCount = 0;
79
+
80
+ // Use filterKnowledge (scroll with empty filter) to paginate through all
81
+ // knowledge items. setKnowledgePayload is used to patch confidence values.
82
+ // Both methods are real exports on QdrantVectorStore.
83
+
84
+ let page: Array<{ id: string; payload: Record<string, unknown> }>;
85
+ try {
86
+ page = await vectorStore.filterKnowledge({}, SCROLL_PAGE_SIZE);
87
+ } catch (err) {
88
+ logger.warn('ConfidenceManager.decayAll: initial scroll failed, stopping', {
89
+ error: String(err),
90
+ });
91
+ return 0;
92
+ }
93
+
94
+ for (const point of page) {
95
+ const p = point.payload as Partial<KnowledgePayload>;
96
+ const accessedAt = p.accessed_at ?? 0;
97
+ const confidence = p.confidence ?? 0;
98
+
99
+ // Skip recently accessed items
100
+ if (accessedAt >= graceCutoff) continue;
101
+
102
+ // Skip items already at floor
103
+ if (confidence <= MIN_CONFIDENCE) continue;
104
+
105
+ const newConfidence = Math.max(MIN_CONFIDENCE, confidence - decayRate);
106
+
107
+ // Round to 4 decimal places to avoid floating-point drift
108
+ const rounded = Math.round(newConfidence * 10000) / 10000;
109
+ if (rounded === confidence) continue; // No change needed
110
+
111
+ try {
112
+ await vectorStore.setKnowledgePayload(point.id, { confidence: rounded });
113
+ decayedCount++;
114
+
115
+ logger.debug('ConfidenceManager.decayAll: item decayed', {
116
+ id: point.id,
117
+ oldConfidence: confidence,
118
+ newConfidence: rounded,
119
+ });
120
+ } catch (err) {
121
+ // Non-fatal — log and continue to next item
122
+ logger.debug('ConfidenceManager.decayAll: failed to update item', {
123
+ id: point.id,
124
+ error: String(err),
125
+ });
126
+ }
127
+ }
128
+
129
+ logger.info('ConfidenceManager.decayAll: complete', {
130
+ decayedCount,
131
+ decayRate,
132
+ });
133
+
134
+ return decayedCount;
135
+ }
136
+
137
+ /**
138
+ * Boost the confidence of a specific knowledge item.
139
+ *
140
+ * Updates:
141
+ * confidence += amount (capped at MAX_CONFIDENCE)
142
+ * accessed_at = now
143
+ * access_count += 1
144
+ *
145
+ * Fails silently on Qdrant errors — boosting is a best-effort operation.
146
+ */
147
+ async boost(
148
+ vectorStore: QdrantVectorStore,
149
+ knowledgeId: string,
150
+ amount: number = 0.05,
151
+ ): Promise<void> {
152
+ const healthy = await vectorStore.isHealthy();
153
+ if (!healthy) {
154
+ logger.debug('ConfidenceManager.boost: Qdrant unavailable, skip', { knowledgeId });
155
+ return;
156
+ }
157
+
158
+ try {
159
+ let currentConfidence = 0.5;
160
+ let currentAccessCount = 0;
161
+
162
+ const existing = await vectorStore.getKnowledge(knowledgeId);
163
+ if (!existing) {
164
+ logger.debug('ConfidenceManager.boost: item not found', { knowledgeId });
165
+ return;
166
+ }
167
+ const payload = existing as Partial<KnowledgePayload>;
168
+ currentConfidence = (typeof payload.confidence === 'number' ? payload.confidence : null) ?? 0.5;
169
+ currentAccessCount = (typeof payload.access_count === 'number' ? payload.access_count : null) ?? 0;
170
+
171
+ const newConfidence = Math.min(MAX_CONFIDENCE, currentConfidence + amount);
172
+ const rounded = Math.round(newConfidence * 10000) / 10000;
173
+
174
+ await vectorStore.setKnowledgePayload(knowledgeId, {
175
+ confidence: rounded,
176
+ accessed_at: Date.now(),
177
+ access_count: currentAccessCount + 1,
178
+ });
179
+
180
+ logger.debug('ConfidenceManager.boost: boosted', {
181
+ knowledgeId,
182
+ oldConfidence: currentConfidence,
183
+ newConfidence: rounded,
184
+ newAccessCount: currentAccessCount + 1,
185
+ });
186
+ } catch (err) {
187
+ logger.warn('ConfidenceManager.boost: failed (non-fatal)', {
188
+ knowledgeId,
189
+ error: String(err),
190
+ });
191
+ }
192
+ }
193
+ }