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,253 @@
1
+ // Pipeline event factory and helpers for the event-sourced state machine.
2
+ //
3
+ // Pipeline events are the audit log. Every phase transition, agent action,
4
+ // claim lifecycle change, and project status change is recorded as an immutable
5
+ // event row in the pipeline_events SQLite table. The PipelineEngine reads these
6
+ // rows to reconstruct cycle counts and provides the full history to callers.
7
+ //
8
+ // PipelineEvent here is the deserialized domain object (camelCase fields), not
9
+ // the raw row. The storage layer handles the mapping between the two.
10
+
11
+ import type {
12
+ PipelineEvent,
13
+ PipelineEventPayload,
14
+ EventType,
15
+ PipelinePhase,
16
+ } from '../util/types.js';
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Event factory
20
+ // ---------------------------------------------------------------------------
21
+
22
+ /**
23
+ * Builds a PipelineEvent (without id — that is assigned by SQLite AUTOINCREMENT)
24
+ * with a generated timestamp and sensible defaults.
25
+ */
26
+ export function createEvent(
27
+ projectId: string,
28
+ type: EventType,
29
+ data: {
30
+ fromPhase?: PipelinePhase | null;
31
+ toPhase?: PipelinePhase | null;
32
+ agent?: string | null;
33
+ payload?: PipelineEventPayload;
34
+ } = {},
35
+ ): Omit<PipelineEvent, 'id'> {
36
+ return {
37
+ projectId,
38
+ eventType: type,
39
+ fromPhase: data.fromPhase ?? null,
40
+ toPhase: data.toPhase ?? null,
41
+ agent: data.agent ?? null,
42
+ payload: data.payload ?? {},
43
+ createdAt: Date.now(),
44
+ };
45
+ }
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // Convenience constructors for common event patterns
49
+ // ---------------------------------------------------------------------------
50
+
51
+ /** Emitted when the engine transitions a project to a new phase. */
52
+ export function phaseTransitionEvent(
53
+ projectId: string,
54
+ fromPhase: PipelinePhase,
55
+ toPhase: PipelinePhase,
56
+ agent?: string | null,
57
+ extra?: PipelineEventPayload,
58
+ ): Omit<PipelineEvent, 'id'> {
59
+ return createEvent(projectId, 'phase_transition', {
60
+ fromPhase,
61
+ toPhase,
62
+ agent: agent ?? null,
63
+ payload: extra ?? {},
64
+ });
65
+ }
66
+
67
+ /** Emitted when an agent begins work on a phase. */
68
+ export function agentStartedEvent(
69
+ projectId: string,
70
+ phase: PipelinePhase,
71
+ agent: string,
72
+ extra?: PipelineEventPayload,
73
+ ): Omit<PipelineEvent, 'id'> {
74
+ return createEvent(projectId, 'agent_started', {
75
+ fromPhase: phase,
76
+ toPhase: phase,
77
+ agent,
78
+ payload: extra ?? {},
79
+ });
80
+ }
81
+
82
+ /** Emitted when an agent successfully completes a phase. */
83
+ export function agentCompletedEvent(
84
+ projectId: string,
85
+ phase: PipelinePhase,
86
+ agent: string,
87
+ extra?: PipelineEventPayload,
88
+ ): Omit<PipelineEvent, 'id'> {
89
+ return createEvent(projectId, 'agent_completed', {
90
+ fromPhase: phase,
91
+ toPhase: phase,
92
+ agent,
93
+ payload: extra ?? {},
94
+ });
95
+ }
96
+
97
+ /** Emitted when an agent fails a phase. */
98
+ export function agentFailedEvent(
99
+ projectId: string,
100
+ phase: PipelinePhase,
101
+ agent: string,
102
+ error: string,
103
+ extra?: PipelineEventPayload,
104
+ ): Omit<PipelineEvent, 'id'> {
105
+ return createEvent(projectId, 'agent_failed', {
106
+ fromPhase: phase,
107
+ toPhase: phase,
108
+ agent,
109
+ payload: { error, ...(extra ?? {}) },
110
+ });
111
+ }
112
+
113
+ /** Emitted when the project is first created. */
114
+ export function projectCreatedEvent(
115
+ projectId: string,
116
+ extra?: PipelineEventPayload,
117
+ ): Omit<PipelineEvent, 'id'> {
118
+ return createEvent(projectId, 'project_created', {
119
+ payload: extra ?? {},
120
+ });
121
+ }
122
+
123
+ /** Emitted when the project is paused. */
124
+ export function projectPausedEvent(
125
+ projectId: string,
126
+ phase: PipelinePhase,
127
+ extra?: PipelineEventPayload,
128
+ ): Omit<PipelineEvent, 'id'> {
129
+ return createEvent(projectId, 'project_paused', {
130
+ fromPhase: phase,
131
+ payload: extra ?? {},
132
+ });
133
+ }
134
+
135
+ /** Emitted when the project is resumed from pause. */
136
+ export function projectResumedEvent(
137
+ projectId: string,
138
+ phase: PipelinePhase,
139
+ extra?: PipelineEventPayload,
140
+ ): Omit<PipelineEvent, 'id'> {
141
+ return createEvent(projectId, 'project_resumed', {
142
+ fromPhase: phase,
143
+ payload: extra ?? {},
144
+ });
145
+ }
146
+
147
+ /** Emitted when the project reaches completed status. */
148
+ export function projectCompletedEvent(
149
+ projectId: string,
150
+ extra?: PipelineEventPayload,
151
+ ): Omit<PipelineEvent, 'id'> {
152
+ return createEvent(projectId, 'project_completed', {
153
+ toPhase: 'complete',
154
+ payload: extra ?? {},
155
+ });
156
+ }
157
+
158
+ /** Emitted when a new work claim is created for a module. */
159
+ export function claimCreatedEvent(
160
+ projectId: string,
161
+ claimId: string,
162
+ moduleName: string,
163
+ agent: string,
164
+ ): Omit<PipelineEvent, 'id'> {
165
+ return createEvent(projectId, 'claim_created', {
166
+ agent,
167
+ payload: { claim_id: claimId, module_name: moduleName },
168
+ });
169
+ }
170
+
171
+ /** Emitted when a claim is successfully completed. */
172
+ export function claimCompletedEvent(
173
+ projectId: string,
174
+ claimId: string,
175
+ moduleName: string,
176
+ agent: string,
177
+ result?: string,
178
+ ): Omit<PipelineEvent, 'id'> {
179
+ return createEvent(projectId, 'claim_completed', {
180
+ agent,
181
+ payload: { claim_id: claimId, module_name: moduleName, result: result ?? null },
182
+ });
183
+ }
184
+
185
+ /** Emitted when a claim fails. */
186
+ export function claimFailedEvent(
187
+ projectId: string,
188
+ claimId: string,
189
+ moduleName: string,
190
+ agent: string,
191
+ reason: string,
192
+ ): Omit<PipelineEvent, 'id'> {
193
+ return createEvent(projectId, 'claim_failed', {
194
+ agent,
195
+ payload: { claim_id: claimId, module_name: moduleName, error: reason },
196
+ });
197
+ }
198
+
199
+ // ---------------------------------------------------------------------------
200
+ // Row mapping helpers
201
+ // ---------------------------------------------------------------------------
202
+
203
+ /**
204
+ * Deserializes a raw pipeline_events row (snake_case TEXT columns) into a
205
+ * typed PipelineEvent domain object. Used by the engine when reading rows
206
+ * back from SQLite.
207
+ */
208
+ export function rowToEvent(row: {
209
+ id: number;
210
+ project_id: string;
211
+ event_type: string;
212
+ from_phase: string | null;
213
+ to_phase: string | null;
214
+ agent: string | null;
215
+ payload: string;
216
+ created_at: number;
217
+ }): PipelineEvent {
218
+ let payload: PipelineEventPayload;
219
+ try {
220
+ payload = JSON.parse(row.payload) as PipelineEventPayload;
221
+ } catch {
222
+ payload = {};
223
+ }
224
+
225
+ return {
226
+ id: row.id,
227
+ projectId: row.project_id,
228
+ eventType: row.event_type as EventType,
229
+ fromPhase: (row.from_phase as PipelinePhase | null) ?? null,
230
+ toPhase: (row.to_phase as PipelinePhase | null) ?? null,
231
+ agent: row.agent,
232
+ payload,
233
+ createdAt: row.created_at,
234
+ };
235
+ }
236
+
237
+ /**
238
+ * Serializes a PipelineEvent domain object to the named parameter map
239
+ * expected by `PipelineDB.run()` for an INSERT into pipeline_events.
240
+ */
241
+ export function eventToParams(
242
+ event: Omit<PipelineEvent, 'id'>,
243
+ ): Record<string, unknown> {
244
+ return {
245
+ project_id: event.projectId,
246
+ event_type: event.eventType,
247
+ from_phase: event.fromPhase,
248
+ to_phase: event.toPhase,
249
+ agent: event.agent,
250
+ payload: JSON.stringify(event.payload),
251
+ created_at: event.createdAt,
252
+ };
253
+ }
@@ -0,0 +1,394 @@
1
+ // ParallelDispatch — manages work claims for parallel implementation phases.
2
+ //
3
+ // During the implementation phase, multiple specialist agents work concurrently
4
+ // on separate modules. ParallelDispatch creates and tracks per-module claims,
5
+ // emits lifecycle events, and provides helpers to check overall completion so
6
+ // the engine can auto-advance to inspection when all work is done.
7
+ //
8
+ // Claims are persisted in the SQLite `claims` table. All writes are
9
+ // synchronous (better-sqlite3). Claim lifecycle events are also written to
10
+ // `pipeline_events` for the audit log.
11
+
12
+ import { randomUUID } from 'node:crypto';
13
+
14
+ import type { PipelineDB } from '../storage/sqlite.js';
15
+ import type { Claim, ClaimRow, ClaimStatus } from '../util/types.js';
16
+ import {
17
+ claimCreatedEvent,
18
+ claimCompletedEvent,
19
+ claimFailedEvent,
20
+ eventToParams,
21
+ } from './events.js';
22
+ import { logger } from '../util/logger.js';
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Row deserializer
26
+ // ---------------------------------------------------------------------------
27
+
28
+ function rowToClaim(row: ClaimRow): Claim {
29
+ return {
30
+ id: row.id,
31
+ projectId: row.project_id,
32
+ moduleName: row.module_name,
33
+ agent: row.agent,
34
+ branch: row.branch,
35
+ status: row.status,
36
+ claimedAt: row.claimed_at,
37
+ completedAt: row.completed_at,
38
+ result: row.result,
39
+ };
40
+ }
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // SQL helper: insert a pipeline event row using positional params.
44
+ // eventToParams returns keys in the order the INSERT expects.
45
+ // ---------------------------------------------------------------------------
46
+
47
+ function insertEvent(
48
+ db: PipelineDB,
49
+ event: ReturnType<typeof claimCreatedEvent>,
50
+ ): void {
51
+ db.run(
52
+ `INSERT INTO pipeline_events
53
+ (project_id, event_type, from_phase, to_phase, agent, payload, created_at)
54
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,
55
+ Object.values(eventToParams(event)),
56
+ );
57
+ }
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // ParallelDispatch
61
+ // ---------------------------------------------------------------------------
62
+
63
+ export class ParallelDispatch {
64
+ constructor(private readonly db: PipelineDB) {}
65
+
66
+ // -------------------------------------------------------------------------
67
+ // Claim creation
68
+ // -------------------------------------------------------------------------
69
+
70
+ /**
71
+ * Creates one claim per entry in `modules`. Each claim starts with status
72
+ * 'claimed' and is immediately usable by a specialist agent.
73
+ *
74
+ * A claim_created pipeline event is emitted for each created claim.
75
+ *
76
+ * Returns the full array of created Claim objects so callers can distribute
77
+ * them to agents.
78
+ */
79
+ createClaims(
80
+ projectId: string,
81
+ modules: Array<{ name: string; agent: string }>,
82
+ ): Claim[] {
83
+ const now = Date.now();
84
+ const created: Claim[] = [];
85
+
86
+ for (const mod of modules) {
87
+ const id = randomUUID();
88
+
89
+ this.db.run(
90
+ `INSERT INTO claims (id, project_id, module_name, agent, status, claimed_at)
91
+ VALUES (?, ?, ?, ?, 'claimed', ?)`,
92
+ [id, projectId, mod.name, mod.agent, now],
93
+ );
94
+
95
+ const event = claimCreatedEvent(projectId, id, mod.name, mod.agent);
96
+ insertEvent(this.db, event);
97
+
98
+ created.push({
99
+ id,
100
+ projectId,
101
+ moduleName: mod.name,
102
+ agent: mod.agent,
103
+ branch: null,
104
+ status: 'claimed',
105
+ claimedAt: now,
106
+ completedAt: null,
107
+ result: null,
108
+ });
109
+
110
+ logger.info('ParallelDispatch: claim created', { projectId, claimId: id, module: mod.name, agent: mod.agent });
111
+ }
112
+
113
+ return created;
114
+ }
115
+
116
+ // -------------------------------------------------------------------------
117
+ // Claim status updates
118
+ // -------------------------------------------------------------------------
119
+
120
+ /**
121
+ * Updates the status of a claim. Optionally sets the result text and branch
122
+ * name. This is a general-purpose setter; use completeClaim / failClaim for
123
+ * the semantic updates that also emit events.
124
+ *
125
+ * Throws when the claim does not exist.
126
+ */
127
+ updateClaim(
128
+ claimId: string,
129
+ status: ClaimStatus,
130
+ result?: string,
131
+ branch?: string,
132
+ ): void {
133
+ const row = this._requireClaim(claimId);
134
+ const now = Date.now();
135
+
136
+ this.db.run(
137
+ `UPDATE claims
138
+ SET status = ?,
139
+ branch = COALESCE(?, branch),
140
+ result = COALESCE(?, result),
141
+ completed_at = CASE WHEN ? IN ('complete', 'failed') THEN ? ELSE completed_at END
142
+ WHERE id = ?`,
143
+ [
144
+ status,
145
+ branch ?? null,
146
+ result ?? null,
147
+ status,
148
+ now,
149
+ claimId,
150
+ ],
151
+ );
152
+
153
+ logger.info('ParallelDispatch: claim updated', {
154
+ claimId,
155
+ projectId: row.project_id,
156
+ module: row.module_name,
157
+ status,
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Marks a claim as 'complete' and emits a claim_completed event.
163
+ * Records the optional result text (e.g., git branch name, summary).
164
+ *
165
+ * Returns { remainingCount, allComplete } so the caller can check whether
166
+ * to auto-advance the project to inspection.
167
+ *
168
+ * Throws when the claim does not exist.
169
+ */
170
+ completeClaim(claimId: string, result?: string): { remainingCount: number; allComplete: boolean } {
171
+ const row = this._requireClaim(claimId);
172
+ const now = Date.now();
173
+
174
+ this.db.run(
175
+ `UPDATE claims SET status = 'complete', completed_at = ?, result = ? WHERE id = ?`,
176
+ [now, result ?? null, claimId],
177
+ );
178
+
179
+ const event = claimCompletedEvent(
180
+ row.project_id,
181
+ claimId,
182
+ row.module_name,
183
+ row.agent,
184
+ result,
185
+ );
186
+ insertEvent(this.db, event);
187
+
188
+ logger.info('ParallelDispatch: claim completed', {
189
+ claimId,
190
+ projectId: row.project_id,
191
+ module: row.module_name,
192
+ });
193
+
194
+ const remaining = this.db.all<{ id: string }>(
195
+ `SELECT id FROM claims WHERE project_id = ? AND status NOT IN ('complete', 'failed')`,
196
+ [row.project_id],
197
+ );
198
+
199
+ return {
200
+ remainingCount: remaining.length,
201
+ allComplete: remaining.length === 0,
202
+ };
203
+ }
204
+
205
+ /**
206
+ * Marks a claim as 'failed' and emits a claim_failed event.
207
+ *
208
+ * Throws when the claim does not exist.
209
+ */
210
+ failClaim(claimId: string, reason: string): void {
211
+ const row = this._requireClaim(claimId);
212
+
213
+ this.db.run(
214
+ `UPDATE claims SET status = 'failed', completed_at = ? WHERE id = ?`,
215
+ [Date.now(), claimId],
216
+ );
217
+
218
+ const event = claimFailedEvent(
219
+ row.project_id,
220
+ claimId,
221
+ row.module_name,
222
+ row.agent,
223
+ reason,
224
+ );
225
+ insertEvent(this.db, event);
226
+
227
+ logger.warn('ParallelDispatch: claim failed', {
228
+ claimId,
229
+ projectId: row.project_id,
230
+ module: row.module_name,
231
+ reason,
232
+ });
233
+ }
234
+
235
+ // -------------------------------------------------------------------------
236
+ // Completion checks
237
+ // -------------------------------------------------------------------------
238
+
239
+ /**
240
+ * Returns true when every claim for the project is in a terminal state
241
+ * ('complete' or 'failed') — i.e., no claim remains in 'claimed' or
242
+ * 'stealable' status.
243
+ *
244
+ * Returns true vacuously when there are no claims at all (no modules were
245
+ * dispatched). Callers should check that at least one claim exists before
246
+ * using this to gate phase advance.
247
+ */
248
+ allClaimsComplete(projectId: string): boolean {
249
+ const pending = this.db.get<{ count: number }>(
250
+ `SELECT COUNT(*) as count FROM claims
251
+ WHERE project_id = ? AND status NOT IN ('complete', 'failed')`,
252
+ [projectId],
253
+ );
254
+ return (pending?.count ?? 0) === 0;
255
+ }
256
+
257
+ // -------------------------------------------------------------------------
258
+ // Query methods
259
+ // -------------------------------------------------------------------------
260
+
261
+ /**
262
+ * Returns claims for a project, optionally filtered by status.
263
+ * Ordered by claimed_at ASC.
264
+ */
265
+ getClaims(projectId: string, status?: ClaimStatus): Claim[] {
266
+ if (status !== undefined) {
267
+ return this.db.all<ClaimRow>(
268
+ `SELECT * FROM claims WHERE project_id = ? AND status = ? ORDER BY claimed_at ASC`,
269
+ [projectId, status],
270
+ ).map(rowToClaim);
271
+ }
272
+ return this.db.all<ClaimRow>(
273
+ `SELECT * FROM claims WHERE project_id = ? ORDER BY claimed_at ASC`,
274
+ [projectId],
275
+ ).map(rowToClaim);
276
+ }
277
+
278
+ /**
279
+ * Returns a single claim by id, or null if it does not exist.
280
+ */
281
+ getClaim(claimId: string): Claim | null {
282
+ const row = this.db.get<ClaimRow>(`SELECT * FROM claims WHERE id = ?`, [claimId]);
283
+ return row ? rowToClaim(row) : null;
284
+ }
285
+
286
+ // -------------------------------------------------------------------------
287
+ // Cycle reset
288
+ // -------------------------------------------------------------------------
289
+
290
+ /**
291
+ * Resets failed claims when the inspection phase sends the project back to
292
+ * implementation. Re-creates claims for the specified modules (or all failed
293
+ * claims when `modules` is omitted) so specialists can retry.
294
+ *
295
+ * The failed rows are left in place for the audit trail. New 'claimed' rows
296
+ * are inserted with new IDs, and claim_created events are emitted for each.
297
+ *
298
+ * Returns the newly created Claim objects.
299
+ */
300
+ resetFailedClaims(projectId: string, modules?: string[]): Claim[] {
301
+ let failedRows: ClaimRow[];
302
+
303
+ if (modules !== undefined && modules.length > 0) {
304
+ // Use multiple individual queries rather than a parameterised IN clause
305
+ // to avoid the need for dynamic SQL placeholders.
306
+ failedRows = [];
307
+ for (const moduleName of modules) {
308
+ const rows = this.db.all<ClaimRow>(
309
+ `SELECT * FROM claims
310
+ WHERE project_id = ? AND module_name = ? AND status = 'failed'
311
+ ORDER BY claimed_at DESC`,
312
+ [projectId, moduleName],
313
+ );
314
+ // Take the most recent failed claim for each module.
315
+ if (rows.length > 0 && rows[0] !== undefined) {
316
+ failedRows.push(rows[0]);
317
+ }
318
+ }
319
+ } else {
320
+ // All failed claims for the project.
321
+ failedRows = this.db.all<ClaimRow>(
322
+ `SELECT * FROM claims WHERE project_id = ? AND status = 'failed' ORDER BY claimed_at ASC`,
323
+ [projectId],
324
+ );
325
+ }
326
+
327
+ if (failedRows.length === 0) {
328
+ logger.info('ParallelDispatch: resetFailedClaims — no failed claims to reset', { projectId });
329
+ return [];
330
+ }
331
+
332
+ const now = Date.now();
333
+ const recreated: Claim[] = [];
334
+
335
+ for (const failed of failedRows) {
336
+ const newId = randomUUID();
337
+
338
+ this.db.run(
339
+ `INSERT INTO claims (id, project_id, module_name, agent, status, claimed_at)
340
+ VALUES (?, ?, ?, ?, 'claimed', ?)`,
341
+ [newId, failed.project_id, failed.module_name, failed.agent, now],
342
+ );
343
+
344
+ const event = claimCreatedEvent(
345
+ failed.project_id,
346
+ newId,
347
+ failed.module_name,
348
+ failed.agent,
349
+ );
350
+ insertEvent(this.db, event);
351
+
352
+ recreated.push({
353
+ id: newId,
354
+ projectId: failed.project_id,
355
+ moduleName: failed.module_name,
356
+ agent: failed.agent,
357
+ branch: null,
358
+ status: 'claimed',
359
+ claimedAt: now,
360
+ completedAt: null,
361
+ result: null,
362
+ });
363
+
364
+ logger.info('ParallelDispatch: claim reset after inspection failure', {
365
+ projectId,
366
+ oldClaimId: failed.id,
367
+ newClaimId: newId,
368
+ module: failed.module_name,
369
+ });
370
+ }
371
+
372
+ return recreated;
373
+ }
374
+
375
+ // -------------------------------------------------------------------------
376
+ // Private helpers
377
+ // -------------------------------------------------------------------------
378
+
379
+ /**
380
+ * Retrieves a raw ClaimRow by id and throws when not found.
381
+ * We return the raw row so callers can access project_id, module_name, and
382
+ * agent for event emission without an extra round-trip.
383
+ */
384
+ private _requireClaim(claimId: string): ClaimRow {
385
+ const row = this.db.get<ClaimRow>(
386
+ `SELECT * FROM claims WHERE id = ?`,
387
+ [claimId],
388
+ );
389
+ if (!row) {
390
+ throw new Error(`ParallelDispatch: claim '${claimId}' does not exist`);
391
+ }
392
+ return row;
393
+ }
394
+ }