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,337 @@
1
+ /**
2
+ * Section-aware markdown chunker.
3
+ * Replaces chunkFixed for .md/.mdx files during indexing.
4
+ *
5
+ * Strategy:
6
+ * 1. Parse markdown into a section tree by headings (H1 → H2 → H3)
7
+ * 2. Each section becomes a chunk with heading breadcrumb as context header
8
+ * 3. Code blocks stay attached to their parent section
9
+ * 4. Sections exceeding 1024 tokens split at sub-heading or paragraph boundaries
10
+ * 5. Sections under ~30 tokens merge with the next sibling
11
+ * 6. Frontmatter (YAML between ---) becomes its own chunk
12
+ */
13
+
14
+ import type { CodeChunk } from '../util/types.js';
15
+ import { estimateTokens } from '../util/token-counter.js';
16
+ import { makeChunk } from './chunker.js';
17
+
18
+ const SECTION_MAX_TOKENS = 1024;
19
+ const SECTION_MIN_TOKENS = 30;
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Section tree types
23
+ // ---------------------------------------------------------------------------
24
+
25
+ interface MarkdownSection {
26
+ heading: string; // The heading text (e.g. "## Authentication")
27
+ level: number; // Heading level (1-6), 0 for root/frontmatter
28
+ breadcrumb: string; // Full path: "Authentication > JWT Flow"
29
+ lines: string[]; // Body lines (excluding heading line itself)
30
+ startLine: number; // 1-based line number of heading
31
+ endLine: number; // 1-based line number of last body line
32
+ }
33
+
34
+ // ---------------------------------------------------------------------------
35
+ // Public API
36
+ // ---------------------------------------------------------------------------
37
+
38
+ /**
39
+ * Chunk a markdown file into section-aware chunks.
40
+ * Each section gets a dk-forge context header with heading breadcrumb.
41
+ */
42
+ export function chunkMarkdown(
43
+ content: string,
44
+ filePath: string,
45
+ repoId: string,
46
+ indexedAt: number,
47
+ ): CodeChunk[] {
48
+ const allLines = content.split('\n');
49
+ const chunks: CodeChunk[] = [];
50
+
51
+ // Extract frontmatter first
52
+ const { frontmatter, bodyStartLine } = extractFrontmatter(allLines);
53
+ if (frontmatter) {
54
+ const fmContent = `// [dk-forge] file: ${filePath} | section: "frontmatter" | lines: 1-${bodyStartLine - 1}\n` +
55
+ frontmatter;
56
+ chunks.push(makeChunk(
57
+ fmContent, filePath, repoId, 'markdown',
58
+ 1, bodyStartLine - 1, 'markdown', indexedAt, 'frontmatter',
59
+ ));
60
+ }
61
+
62
+ // Parse body into sections
63
+ const bodyLines = allLines.slice(bodyStartLine - 1);
64
+ const sections = parseSections(bodyLines, bodyStartLine);
65
+
66
+ // Merge tiny sections with their next sibling
67
+ const merged = mergeTinySections(sections);
68
+
69
+ // Emit chunks, splitting oversized sections
70
+ for (const section of merged) {
71
+ const sectionChunks = sectionToChunks(section, filePath, repoId, indexedAt);
72
+ chunks.push(...sectionChunks);
73
+ }
74
+
75
+ return chunks;
76
+ }
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // Frontmatter extraction
80
+ // ---------------------------------------------------------------------------
81
+
82
+ function extractFrontmatter(lines: string[]): { frontmatter: string | null; bodyStartLine: number } {
83
+ if (lines.length === 0 || lines[0]!.trim() !== '---') {
84
+ return { frontmatter: null, bodyStartLine: 1 };
85
+ }
86
+
87
+ // Find closing ---
88
+ for (let i = 1; i < lines.length; i++) {
89
+ if (lines[i]!.trim() === '---') {
90
+ const fmLines = lines.slice(0, i + 1);
91
+ return {
92
+ frontmatter: fmLines.join('\n'),
93
+ bodyStartLine: i + 2, // 1-based, line after closing ---
94
+ };
95
+ }
96
+ }
97
+
98
+ // No closing --- found, treat entire file as body
99
+ return { frontmatter: null, bodyStartLine: 1 };
100
+ }
101
+
102
+ // ---------------------------------------------------------------------------
103
+ // Section parsing
104
+ // ---------------------------------------------------------------------------
105
+
106
+ const HEADING_RE = /^(#{1,6})\s+(.+)$/;
107
+
108
+ function parseSections(lines: string[], lineOffset: number): MarkdownSection[] {
109
+ const sections: MarkdownSection[] = [];
110
+ const headingStack: Array<{ level: number; text: string }> = [];
111
+
112
+ let currentSection: MarkdownSection | null = null;
113
+
114
+ for (let i = 0; i < lines.length; i++) {
115
+ const line = lines[i]!;
116
+ const match = HEADING_RE.exec(line);
117
+
118
+ if (match) {
119
+ // Flush current section
120
+ if (currentSection) {
121
+ currentSection.endLine = lineOffset + i - 1;
122
+ sections.push(currentSection);
123
+ }
124
+
125
+ const level = match[1]!.length;
126
+ const headingText = match[2]!.trim();
127
+
128
+ // Update heading stack for breadcrumb
129
+ while (headingStack.length > 0 && headingStack[headingStack.length - 1]!.level >= level) {
130
+ headingStack.pop();
131
+ }
132
+ headingStack.push({ level, text: headingText });
133
+
134
+ const breadcrumb = headingStack.map(h => h.text).join(' > ');
135
+
136
+ currentSection = {
137
+ heading: headingText,
138
+ level,
139
+ breadcrumb,
140
+ lines: [],
141
+ startLine: lineOffset + i,
142
+ endLine: lineOffset + i, // Will be updated
143
+ };
144
+ } else {
145
+ if (currentSection) {
146
+ currentSection.lines.push(line);
147
+ } else {
148
+ // Content before first heading — create a root section
149
+ if (line.trim()) {
150
+ currentSection = {
151
+ heading: '',
152
+ level: 0,
153
+ breadcrumb: '',
154
+ lines: [line],
155
+ startLine: lineOffset + i,
156
+ endLine: lineOffset + i,
157
+ };
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ // Flush final section
164
+ if (currentSection) {
165
+ currentSection.endLine = lineOffset + lines.length - 1;
166
+ sections.push(currentSection);
167
+ }
168
+
169
+ return sections;
170
+ }
171
+
172
+ // ---------------------------------------------------------------------------
173
+ // Merge tiny sections
174
+ // ---------------------------------------------------------------------------
175
+
176
+ function mergeTinySections(sections: MarkdownSection[]): MarkdownSection[] {
177
+ if (sections.length <= 1) return sections;
178
+
179
+ const result: MarkdownSection[] = [];
180
+ let i = 0;
181
+
182
+ while (i < sections.length) {
183
+ const section = sections[i]!;
184
+ const bodyText = section.lines.join('\n');
185
+ const tokens = estimateTokens(bodyText);
186
+
187
+ if (tokens < SECTION_MIN_TOKENS && i + 1 < sections.length) {
188
+ // Merge with next section
189
+ const next = sections[i + 1]!;
190
+ const merged: MarkdownSection = {
191
+ heading: section.heading || next.heading,
192
+ level: Math.min(section.level, next.level) || section.level || next.level,
193
+ breadcrumb: section.breadcrumb || next.breadcrumb,
194
+ lines: [
195
+ ...(section.heading ? [`# ${section.heading}`, ''] : []),
196
+ ...section.lines,
197
+ '',
198
+ ...(next.heading ? [`${'#'.repeat(next.level)} ${next.heading}`, ''] : []),
199
+ ...next.lines,
200
+ ],
201
+ startLine: section.startLine,
202
+ endLine: next.endLine,
203
+ };
204
+ // Replace next with merged, re-check merged against following
205
+ sections[i + 1] = merged;
206
+ i++;
207
+ } else {
208
+ result.push(section);
209
+ i++;
210
+ }
211
+ }
212
+
213
+ return result;
214
+ }
215
+
216
+ // ---------------------------------------------------------------------------
217
+ // Section to chunks (with splitting for oversized)
218
+ // ---------------------------------------------------------------------------
219
+
220
+ function sectionToChunks(
221
+ section: MarkdownSection,
222
+ filePath: string,
223
+ repoId: string,
224
+ indexedAt: number,
225
+ ): CodeChunk[] {
226
+ const bodyText = section.lines.join('\n');
227
+ const headerComment = buildSectionHeader(filePath, section.breadcrumb, section.startLine, section.endLine);
228
+ const fullContent = headerComment + (section.heading ? `${'#'.repeat(section.level || 1)} ${section.heading}\n\n` : '') + bodyText;
229
+
230
+ const tokens = estimateTokens(fullContent);
231
+
232
+ if (tokens <= SECTION_MAX_TOKENS) {
233
+ return [makeChunk(
234
+ fullContent, filePath, repoId, 'markdown',
235
+ section.startLine, section.endLine,
236
+ 'markdown', indexedAt,
237
+ section.heading || undefined,
238
+ )];
239
+ }
240
+
241
+ // Split oversized section at paragraph boundaries
242
+ return splitOversizedSection(section, filePath, repoId, indexedAt);
243
+ }
244
+
245
+ function splitOversizedSection(
246
+ section: MarkdownSection,
247
+ filePath: string,
248
+ repoId: string,
249
+ indexedAt: number,
250
+ ): CodeChunk[] {
251
+ const chunks: CodeChunk[] = [];
252
+ const paragraphs = splitIntoParagraphs(section.lines);
253
+
254
+ let currentLines: string[] = [];
255
+ let currentTokens = 0;
256
+ let chunkStartLine = section.startLine;
257
+ let partIndex = 0;
258
+
259
+ const flush = (endLine: number) => {
260
+ if (currentLines.length === 0) return;
261
+ const headerComment = buildSectionHeader(filePath, section.breadcrumb, chunkStartLine, endLine);
262
+ const content = headerComment + currentLines.join('\n');
263
+ const entityName = section.heading
264
+ ? `${section.heading}_part${partIndex++}`
265
+ : `section_part${partIndex++}`;
266
+ chunks.push(makeChunk(
267
+ content, filePath, repoId, 'markdown',
268
+ chunkStartLine, endLine,
269
+ 'markdown', indexedAt, entityName,
270
+ ));
271
+ currentLines = [];
272
+ currentTokens = 0;
273
+ chunkStartLine = endLine + 1;
274
+ };
275
+
276
+ for (const para of paragraphs) {
277
+ const paraTokens = estimateTokens(para.text);
278
+
279
+ if (currentTokens + paraTokens > SECTION_MAX_TOKENS && currentLines.length > 0) {
280
+ flush(chunkStartLine + currentLines.length - 1);
281
+ }
282
+
283
+ currentLines.push(...para.lines);
284
+ currentTokens += paraTokens;
285
+ }
286
+
287
+ if (currentLines.length > 0) {
288
+ flush(section.endLine);
289
+ }
290
+
291
+ return chunks;
292
+ }
293
+
294
+ interface Paragraph {
295
+ lines: string[];
296
+ text: string;
297
+ }
298
+
299
+ function splitIntoParagraphs(lines: string[]): Paragraph[] {
300
+ const paragraphs: Paragraph[] = [];
301
+ let currentLines: string[] = [];
302
+
303
+ for (const line of lines) {
304
+ if (line.trim() === '' && currentLines.length > 0) {
305
+ paragraphs.push({
306
+ lines: [...currentLines, ''],
307
+ text: currentLines.join('\n'),
308
+ });
309
+ currentLines = [];
310
+ } else {
311
+ currentLines.push(line);
312
+ }
313
+ }
314
+
315
+ if (currentLines.length > 0) {
316
+ paragraphs.push({
317
+ lines: currentLines,
318
+ text: currentLines.join('\n'),
319
+ });
320
+ }
321
+
322
+ return paragraphs;
323
+ }
324
+
325
+ // ---------------------------------------------------------------------------
326
+ // Header builder
327
+ // ---------------------------------------------------------------------------
328
+
329
+ function buildSectionHeader(
330
+ filePath: string,
331
+ breadcrumb: string,
332
+ startLine: number,
333
+ endLine: number,
334
+ ): string {
335
+ const sectionStr = breadcrumb ? ` | section: "${breadcrumb}"` : '';
336
+ return `// [dk-forge] file: ${filePath}${sectionStr} | lines: ${startLine}-${endLine}\n`;
337
+ }
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Markdown knowledge extractor.
3
+ * Scans markdown document headings for keywords that signal knowledge items
4
+ * (gotchas, patterns, decisions, conventions) and extracts matching sections.
5
+ *
6
+ * Used during indexing to automatically populate the knowledge collection
7
+ * from documentation files without manual YAML curation.
8
+ */
9
+
10
+ import { createHash } from 'crypto';
11
+ import type { KnowledgeItem, KnowledgeCategory } from '../util/types.js';
12
+
13
+ const MAX_CONTENT_LENGTH = 2000;
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Heading keyword patterns
17
+ // ---------------------------------------------------------------------------
18
+
19
+ interface CategoryMatcher {
20
+ category: KnowledgeCategory;
21
+ keywords: string[];
22
+ }
23
+
24
+ const CATEGORY_MATCHERS: CategoryMatcher[] = [
25
+ {
26
+ category: 'gotcha',
27
+ keywords: ['gotcha', 'warning', 'caveat', 'pitfall', 'watch out', 'known issue'],
28
+ },
29
+ {
30
+ category: 'pattern',
31
+ keywords: ['pattern', 'best practice', 'convention', 'approach'],
32
+ },
33
+ {
34
+ category: 'decision',
35
+ keywords: ['decision', 'adr', 'why we', 'trade-off', 'tradeoff', 'we chose'],
36
+ },
37
+ {
38
+ category: 'convention',
39
+ keywords: ['convention', 'rule', 'standard', 'naming'],
40
+ },
41
+ ];
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Public API
45
+ // ---------------------------------------------------------------------------
46
+
47
+ /**
48
+ * Extract knowledge items from a markdown file's content.
49
+ * Scans headings for category keywords and returns matching sections
50
+ * as KnowledgeItem objects with deterministic IDs.
51
+ *
52
+ * @param content - Raw markdown file content
53
+ * @param filePath - Absolute path to the file (used for ID generation)
54
+ * @param repoId - Repository ID (not used in item directly but available for caller context)
55
+ * @param stackTags - Stack tags from repo manifest to attach to items
56
+ */
57
+ export function extractKnowledge(
58
+ content: string,
59
+ filePath: string,
60
+ _repoId: string,
61
+ stackTags: string[] = [],
62
+ ): KnowledgeItem[] {
63
+ const items: KnowledgeItem[] = [];
64
+ const sections = parseIntoSections(content);
65
+ const now = Date.now();
66
+
67
+ for (const section of sections) {
68
+ const category = matchCategory(section.heading);
69
+ if (!category) continue;
70
+
71
+ const id = generateDeterministicId(filePath, section.heading, category);
72
+ const body = section.body.slice(0, MAX_CONTENT_LENGTH).trim();
73
+
74
+ if (!body) continue;
75
+
76
+ items.push({
77
+ id,
78
+ title: section.heading,
79
+ content: body,
80
+ stack_tags: stackTags,
81
+ confidence: 0.6,
82
+ source: 'agent',
83
+ source_phase: null,
84
+ source_agent: 'indexer',
85
+ created_at: now,
86
+ updated_at: now,
87
+ });
88
+ }
89
+
90
+ return items;
91
+ }
92
+
93
+ // ---------------------------------------------------------------------------
94
+ // Section parsing
95
+ // ---------------------------------------------------------------------------
96
+
97
+ interface HeadingSection {
98
+ heading: string;
99
+ level: number;
100
+ body: string;
101
+ }
102
+
103
+ const HEADING_RE = /^(#{1,6})\s+(.+)$/;
104
+
105
+ function parseIntoSections(content: string): HeadingSection[] {
106
+ const lines = content.split('\n');
107
+ const sections: HeadingSection[] = [];
108
+ let current: HeadingSection | null = null;
109
+ let bodyLines: string[] = [];
110
+
111
+ const flush = () => {
112
+ if (current) {
113
+ current.body = bodyLines.join('\n');
114
+ sections.push(current);
115
+ bodyLines = [];
116
+ }
117
+ };
118
+
119
+ for (const line of lines) {
120
+ const match = HEADING_RE.exec(line);
121
+ if (match) {
122
+ flush();
123
+ current = {
124
+ heading: match[2]!.trim(),
125
+ level: match[1]!.length,
126
+ body: '',
127
+ };
128
+ } else if (current) {
129
+ bodyLines.push(line);
130
+ }
131
+ }
132
+
133
+ flush();
134
+ return sections;
135
+ }
136
+
137
+ // ---------------------------------------------------------------------------
138
+ // Category matching
139
+ // ---------------------------------------------------------------------------
140
+
141
+ function matchCategory(heading: string): KnowledgeCategory | null {
142
+ const lower = heading.toLowerCase();
143
+
144
+ for (const matcher of CATEGORY_MATCHERS) {
145
+ for (const keyword of matcher.keywords) {
146
+ if (lower.includes(keyword)) {
147
+ return matcher.category;
148
+ }
149
+ }
150
+ }
151
+
152
+ return null;
153
+ }
154
+
155
+ // ---------------------------------------------------------------------------
156
+ // Deterministic ID generation
157
+ // ---------------------------------------------------------------------------
158
+
159
+ /**
160
+ * Generate a deterministic ID from filePath + heading.
161
+ * Format: `<category>-<hash-first-12>` to match the convention used by
162
+ * KnowledgeHydrator._categoryFromId().
163
+ *
164
+ * Idempotent: re-indexing the same file produces the same IDs, so Qdrant
165
+ * upserts overwrite rather than duplicate.
166
+ */
167
+ function generateDeterministicId(
168
+ filePath: string,
169
+ heading: string,
170
+ category: KnowledgeCategory,
171
+ ): string {
172
+ const input = `${filePath}::${heading}`;
173
+ const hash = createHash('sha256').update(input).digest('hex').slice(0, 12);
174
+ return `${category}-auto-${hash}`;
175
+ }