@winspan/claude-forge 8.41.0 → 8.50.6

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 (804) hide show
  1. package/.claude/CLAUDE.md +17 -0
  2. package/.eslintrc.js +23 -0
  3. package/.prettierrc +8 -0
  4. package/ARCHITECTURE_ISSUES.md +249 -0
  5. package/CLAUDE.md +265 -0
  6. package/CLAUDE.md.backup +488 -0
  7. package/DEVELOPMENT.md +310 -0
  8. package/dist/claudemd/claudemd-generator.d.ts +38 -3
  9. package/dist/claudemd/claudemd-generator.d.ts.map +1 -1
  10. package/dist/claudemd/claudemd-generator.js +629 -11
  11. package/dist/claudemd/claudemd-generator.js.map +1 -1
  12. package/dist/claudemd/index.d.ts +2 -2
  13. package/dist/claudemd/index.d.ts.map +1 -1
  14. package/dist/claudemd/index.js.map +1 -1
  15. package/dist/claudemd/resume-manager.d.ts.map +1 -1
  16. package/dist/claudemd/resume-manager.js +5 -2
  17. package/dist/claudemd/resume-manager.js.map +1 -1
  18. package/dist/claudemd/tech-detector.d.ts +1 -0
  19. package/dist/claudemd/tech-detector.d.ts.map +1 -1
  20. package/dist/claudemd/tech-detector.js +53 -0
  21. package/dist/claudemd/tech-detector.js.map +1 -1
  22. package/dist/cli/commands/claudemd.js +2 -2
  23. package/dist/cli/commands/claudemd.js.map +1 -1
  24. package/dist/cli/commands/daemon.d.ts +28 -0
  25. package/dist/cli/commands/daemon.d.ts.map +1 -1
  26. package/dist/cli/commands/daemon.js +200 -8
  27. package/dist/cli/commands/daemon.js.map +1 -1
  28. package/dist/cli/commands/init.d.ts.map +1 -1
  29. package/dist/cli/commands/init.js +3 -35
  30. package/dist/cli/commands/init.js.map +1 -1
  31. package/dist/cli/commands/menu.js +10 -10
  32. package/dist/cli/commands/menu.js.map +1 -1
  33. package/dist/cli/commands/skills.d.ts.map +1 -1
  34. package/dist/cli/commands/skills.js +8 -2
  35. package/dist/cli/commands/skills.js.map +1 -1
  36. package/dist/cli/commands/stats.d.ts.map +1 -1
  37. package/dist/cli/commands/stats.js +0 -17
  38. package/dist/cli/commands/stats.js.map +1 -1
  39. package/dist/cli/commands/trace.d.ts +9 -0
  40. package/dist/cli/commands/trace.d.ts.map +1 -0
  41. package/dist/cli/commands/trace.js +137 -0
  42. package/dist/cli/commands/trace.js.map +1 -0
  43. package/dist/cli/index.js +2 -4
  44. package/dist/cli/index.js.map +1 -1
  45. package/dist/core/ai/provider.d.ts +10 -2
  46. package/dist/core/ai/provider.d.ts.map +1 -1
  47. package/dist/core/ai/provider.js.map +1 -1
  48. package/dist/core/ai/types.d.ts +1 -19
  49. package/dist/core/ai/types.d.ts.map +1 -1
  50. package/dist/core/ai/types.js +1 -1
  51. package/dist/core/config.d.ts +2 -1
  52. package/dist/core/config.d.ts.map +1 -1
  53. package/dist/core/config.js +23 -6
  54. package/dist/core/config.js.map +1 -1
  55. package/dist/core/constants.d.ts +2 -2
  56. package/dist/core/constants.js +2 -2
  57. package/dist/core/constants.js.map +1 -1
  58. package/dist/core/queue/index.d.ts +52 -0
  59. package/dist/core/queue/index.d.ts.map +1 -0
  60. package/dist/core/queue/index.js +176 -0
  61. package/dist/core/queue/index.js.map +1 -0
  62. package/dist/core/storage/base.d.ts +33 -0
  63. package/dist/core/storage/base.d.ts.map +1 -0
  64. package/dist/core/storage/base.js +211 -0
  65. package/dist/core/storage/base.js.map +1 -0
  66. package/dist/core/storage/events.d.ts +52 -0
  67. package/dist/core/storage/events.d.ts.map +1 -0
  68. package/dist/core/storage/events.js +201 -0
  69. package/dist/core/storage/events.js.map +1 -0
  70. package/dist/core/storage/injections.d.ts +27 -0
  71. package/dist/core/storage/injections.d.ts.map +1 -0
  72. package/dist/core/storage/injections.js +51 -0
  73. package/dist/core/storage/injections.js.map +1 -0
  74. package/dist/core/storage/maintenance.d.ts +21 -0
  75. package/dist/core/storage/maintenance.d.ts.map +1 -0
  76. package/dist/core/storage/maintenance.js +52 -0
  77. package/dist/core/storage/maintenance.js.map +1 -0
  78. package/dist/core/storage/routing.d.ts +71 -0
  79. package/dist/core/storage/routing.d.ts.map +1 -0
  80. package/dist/core/storage/routing.js +141 -0
  81. package/dist/core/storage/routing.js.map +1 -0
  82. package/dist/core/storage/rows.d.ts +0 -47
  83. package/dist/core/storage/rows.d.ts.map +1 -1
  84. package/dist/core/storage/schema.sql +74 -136
  85. package/dist/core/storage/sessions.d.ts +34 -0
  86. package/dist/core/storage/sessions.d.ts.map +1 -0
  87. package/dist/core/storage/sessions.js +78 -0
  88. package/dist/core/storage/sessions.js.map +1 -0
  89. package/dist/core/storage/skills.d.ts +40 -0
  90. package/dist/core/storage/skills.d.ts.map +1 -0
  91. package/dist/core/storage/skills.js +107 -0
  92. package/dist/core/storage/skills.js.map +1 -0
  93. package/dist/core/storage/sqlite.d.ts +63 -265
  94. package/dist/core/storage/sqlite.d.ts.map +1 -1
  95. package/dist/core/storage/sqlite.js +102 -759
  96. package/dist/core/storage/sqlite.js.map +1 -1
  97. package/dist/core/storage/tasks.d.ts +64 -0
  98. package/dist/core/storage/tasks.d.ts.map +1 -0
  99. package/dist/core/storage/tasks.js +134 -0
  100. package/dist/core/storage/tasks.js.map +1 -0
  101. package/dist/core/storage/token-usage.d.ts +36 -0
  102. package/dist/core/storage/token-usage.d.ts.map +1 -0
  103. package/dist/core/storage/token-usage.js +59 -0
  104. package/dist/core/storage/token-usage.js.map +1 -0
  105. package/dist/core/types.d.ts +60 -4
  106. package/dist/core/types.d.ts.map +1 -1
  107. package/dist/core/types.js +24 -1
  108. package/dist/core/types.js.map +1 -1
  109. package/dist/core/utils/format.d.ts +28 -0
  110. package/dist/core/utils/format.d.ts.map +1 -0
  111. package/dist/core/utils/format.js +68 -0
  112. package/dist/core/utils/format.js.map +1 -0
  113. package/dist/core/utils/logger.d.ts +6 -1
  114. package/dist/core/utils/logger.d.ts.map +1 -1
  115. package/dist/core/utils/logger.js +72 -2
  116. package/dist/core/utils/logger.js.map +1 -1
  117. package/dist/core/utils/session.d.ts +16 -0
  118. package/dist/core/utils/session.d.ts.map +1 -0
  119. package/dist/core/utils/session.js +25 -0
  120. package/dist/core/utils/session.js.map +1 -0
  121. package/dist/core/utils/time.d.ts +22 -0
  122. package/dist/core/utils/time.d.ts.map +1 -0
  123. package/dist/core/utils/time.js +38 -0
  124. package/dist/core/utils/time.js.map +1 -0
  125. package/dist/daemon/handlers/history-exporter.d.ts.map +1 -1
  126. package/dist/daemon/handlers/history-exporter.js +6 -4
  127. package/dist/daemon/handlers/history-exporter.js.map +1 -1
  128. package/dist/daemon/handlers/post-tool-use.d.ts +5 -12
  129. package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
  130. package/dist/daemon/handlers/post-tool-use.js +21 -79
  131. package/dist/daemon/handlers/post-tool-use.js.map +1 -1
  132. package/dist/daemon/handlers/stop.d.ts +24 -12
  133. package/dist/daemon/handlers/stop.d.ts.map +1 -1
  134. package/dist/daemon/handlers/stop.js +141 -42
  135. package/dist/daemon/handlers/stop.js.map +1 -1
  136. package/dist/daemon/handlers/user-prompt.d.ts +18 -19
  137. package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
  138. package/dist/daemon/handlers/user-prompt.js +103 -227
  139. package/dist/daemon/handlers/user-prompt.js.map +1 -1
  140. package/dist/daemon/index.d.ts +6 -2
  141. package/dist/daemon/index.d.ts.map +1 -1
  142. package/dist/daemon/index.js +76 -120
  143. package/dist/daemon/index.js.map +1 -1
  144. package/dist/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
  145. package/dist/daemon/launchd-installer.d.ts +61 -0
  146. package/dist/daemon/launchd-installer.d.ts.map +1 -0
  147. package/dist/daemon/launchd-installer.js +182 -0
  148. package/dist/daemon/launchd-installer.js.map +1 -0
  149. package/dist/daemon/lifecycle.d.ts +11 -0
  150. package/dist/daemon/lifecycle.d.ts.map +1 -1
  151. package/dist/daemon/lifecycle.js +44 -0
  152. package/dist/daemon/lifecycle.js.map +1 -1
  153. package/dist/daemon/router.d.ts +9 -2
  154. package/dist/daemon/router.d.ts.map +1 -1
  155. package/dist/daemon/router.js +27 -3
  156. package/dist/daemon/router.js.map +1 -1
  157. package/dist/daemon/server.d.ts.map +1 -1
  158. package/dist/daemon/server.js +6 -5
  159. package/dist/daemon/server.js.map +1 -1
  160. package/dist/daemon/services/anti-pattern-detector.d.ts +50 -0
  161. package/dist/daemon/services/anti-pattern-detector.d.ts.map +1 -0
  162. package/dist/daemon/services/anti-pattern-detector.js +357 -0
  163. package/dist/daemon/services/anti-pattern-detector.js.map +1 -0
  164. package/dist/daemon/services/drift-detector.d.ts +64 -0
  165. package/dist/daemon/services/drift-detector.d.ts.map +1 -0
  166. package/dist/daemon/services/drift-detector.js +201 -0
  167. package/dist/daemon/services/drift-detector.js.map +1 -0
  168. package/dist/{intelligence → daemon/services}/task-segmenter.d.ts +7 -1
  169. package/dist/daemon/services/task-segmenter.d.ts.map +1 -0
  170. package/dist/{intelligence → daemon/services}/task-segmenter.js +29 -6
  171. package/dist/daemon/services/task-segmenter.js.map +1 -0
  172. package/dist/daemon/services/weekly-report.d.ts +91 -0
  173. package/dist/daemon/services/weekly-report.d.ts.map +1 -0
  174. package/dist/daemon/services/weekly-report.js +327 -0
  175. package/dist/daemon/services/weekly-report.js.map +1 -0
  176. package/dist/hooks/hook-lib.sh +81 -0
  177. package/dist/hooks/notification.sh +7 -3
  178. package/dist/hooks/post-tool-use.sh +8 -4
  179. package/dist/hooks/pre-tool-use.sh +7 -4
  180. package/dist/hooks/stop.sh +1 -1
  181. package/dist/hooks/user-prompt-submit.sh +8 -9
  182. package/dist/mcp/server.d.ts +2 -2
  183. package/dist/mcp/server.d.ts.map +1 -1
  184. package/dist/mcp/server.js +71 -11
  185. package/dist/mcp/server.js.map +1 -1
  186. package/dist/skills/invocation-guard.d.ts +20 -0
  187. package/dist/skills/invocation-guard.d.ts.map +1 -1
  188. package/dist/skills/invocation-guard.js +63 -0
  189. package/dist/skills/invocation-guard.js.map +1 -1
  190. package/dist/skills/matcher.d.ts.map +1 -1
  191. package/dist/skills/matcher.js +12 -3
  192. package/dist/skills/matcher.js.map +1 -1
  193. package/dist/skills/official/code-simplifier.md +16 -0
  194. package/dist/skills/official/find-skills.md +23 -0
  195. package/dist/skills/official/official-api-design.md +17 -0
  196. package/dist/skills/official/official-architecture-decision.md +20 -0
  197. package/dist/skills/official/official-bmad.md +118 -0
  198. package/dist/skills/official/official-db-schema-design.md +16 -0
  199. package/dist/skills/official/official-debug.md +17 -0
  200. package/dist/skills/official/official-doc-driven.md +31 -0
  201. package/dist/skills/official/official-harness-engineering.md +108 -0
  202. package/dist/skills/official/official-performance-optimization.md +30 -0
  203. package/dist/skills/official/official-pr-review.md +35 -0
  204. package/dist/skills/official/official-release-checklist.md +30 -0
  205. package/dist/skills/official/official-security-hardening.md +26 -0
  206. package/dist/skills/official/official-spec-driven-design.md +31 -0
  207. package/dist/skills/official/planning-with-files.md +37 -0
  208. package/dist/skills/official/ui-ux-pro-max.md +18 -0
  209. package/dist/skills/official/webapp-testing.md +12 -0
  210. package/dist/skills/official-skills.d.ts +8 -4
  211. package/dist/skills/official-skills.d.ts.map +1 -1
  212. package/dist/skills/official-skills.js +48 -704
  213. package/dist/skills/official-skills.js.map +1 -1
  214. package/dist/skills/registry.d.ts +5 -0
  215. package/dist/skills/registry.d.ts.map +1 -1
  216. package/dist/skills/registry.js +48 -15
  217. package/dist/skills/registry.js.map +1 -1
  218. package/dist/skills/tools/pipeline-suggest.d.ts +30 -0
  219. package/dist/skills/tools/pipeline-suggest.d.ts.map +1 -0
  220. package/dist/skills/tools/pipeline-suggest.js +178 -0
  221. package/dist/skills/tools/pipeline-suggest.js.map +1 -0
  222. package/dist/web/routes/ai.d.ts.map +1 -1
  223. package/dist/web/routes/ai.js +16 -22
  224. package/dist/web/routes/ai.js.map +1 -1
  225. package/dist/web/routes/drift.d.ts +10 -0
  226. package/dist/web/routes/drift.d.ts.map +1 -0
  227. package/dist/web/routes/drift.js +21 -0
  228. package/dist/web/routes/drift.js.map +1 -0
  229. package/dist/web/routes/error-handler.d.ts +43 -0
  230. package/dist/web/routes/error-handler.d.ts.map +1 -0
  231. package/dist/web/routes/error-handler.js +99 -0
  232. package/dist/web/routes/error-handler.js.map +1 -0
  233. package/dist/web/routes/insights.d.ts +9 -0
  234. package/dist/web/routes/insights.d.ts.map +1 -0
  235. package/dist/web/routes/insights.js +34 -0
  236. package/dist/web/routes/insights.js.map +1 -0
  237. package/dist/web/routes/patch.js +2 -2
  238. package/dist/web/routes/patch.js.map +1 -1
  239. package/dist/web/routes/reports.d.ts +10 -0
  240. package/dist/web/routes/reports.d.ts.map +1 -0
  241. package/dist/web/routes/reports.js +27 -0
  242. package/dist/web/routes/reports.js.map +1 -0
  243. package/dist/web/routes/rules.d.ts +10 -3
  244. package/dist/web/routes/rules.d.ts.map +1 -1
  245. package/dist/web/routes/rules.js +80 -95
  246. package/dist/web/routes/rules.js.map +1 -1
  247. package/dist/web/routes/sessions.d.ts +1 -2
  248. package/dist/web/routes/sessions.d.ts.map +1 -1
  249. package/dist/web/routes/sessions.js +27 -39
  250. package/dist/web/routes/sessions.js.map +1 -1
  251. package/dist/web/routes/skill-stats.d.ts.map +1 -1
  252. package/dist/web/routes/skill-stats.js +38 -0
  253. package/dist/web/routes/skill-stats.js.map +1 -1
  254. package/dist/web/routes/skills.d.ts.map +1 -1
  255. package/dist/web/routes/skills.js +34 -0
  256. package/dist/web/routes/skills.js.map +1 -1
  257. package/dist/web/routes/stats.d.ts +7 -0
  258. package/dist/web/routes/stats.d.ts.map +1 -0
  259. package/dist/web/routes/stats.js +44 -0
  260. package/dist/web/routes/stats.js.map +1 -0
  261. package/dist/web/routes/status.js +1 -1
  262. package/dist/web/routes/status.js.map +1 -1
  263. package/dist/web/routes/tasks.d.ts +4 -0
  264. package/dist/web/routes/tasks.d.ts.map +1 -0
  265. package/dist/web/routes/tasks.js +181 -0
  266. package/dist/web/routes/tasks.js.map +1 -0
  267. package/dist/web/routes/trace.d.ts +10 -0
  268. package/dist/web/routes/trace.d.ts.map +1 -0
  269. package/dist/web/routes/trace.js +123 -0
  270. package/dist/web/routes/trace.js.map +1 -0
  271. package/dist/web/routes/types.d.ts +1 -14
  272. package/dist/web/routes/types.d.ts.map +1 -1
  273. package/dist/web/routes/types.js +8 -17
  274. package/dist/web/routes/types.js.map +1 -1
  275. package/dist/web/server.d.ts +1 -9
  276. package/dist/web/server.d.ts.map +1 -1
  277. package/dist/web/server.js +28 -28
  278. package/dist/web/server.js.map +1 -1
  279. package/dist/web/static/assets/AIConfig-BQCAQE9D.js +2 -0
  280. package/dist/web/static/assets/AIConfig-BQCAQE9D.js.map +1 -0
  281. package/dist/web/static/assets/Dashboard-D7Bo6Kan.js +2 -0
  282. package/dist/web/static/assets/Dashboard-D7Bo6Kan.js.map +1 -0
  283. package/dist/web/static/assets/{Drawer-DcU3ln98.js → Drawer-BeHRQxUS.js} +2 -2
  284. package/dist/web/static/assets/{Drawer-DcU3ln98.js.map → Drawer-BeHRQxUS.js.map} +1 -1
  285. package/dist/web/static/assets/Events-K_tCY2ti.js +2 -0
  286. package/dist/web/static/assets/Events-K_tCY2ti.js.map +1 -0
  287. package/dist/web/static/assets/Reports-BJCmBnc_.js +2 -0
  288. package/dist/web/static/assets/Reports-BJCmBnc_.js.map +1 -0
  289. package/dist/web/static/assets/SearchInput-BX2KhMkw.js +2 -0
  290. package/dist/web/static/assets/SearchInput-BX2KhMkw.js.map +1 -0
  291. package/dist/web/static/assets/SessionDetail-Bkr-kC7V.js +2 -0
  292. package/dist/web/static/assets/SessionDetail-Bkr-kC7V.js.map +1 -0
  293. package/dist/web/static/assets/Sessions-Chx9OCLH.js +2 -0
  294. package/dist/web/static/assets/Sessions-Chx9OCLH.js.map +1 -0
  295. package/dist/web/static/assets/Skills-O0GT1i7m.js +2 -0
  296. package/dist/web/static/assets/Skills-O0GT1i7m.js.map +1 -0
  297. package/dist/web/static/assets/TaskDetail-5SR8zGzv.js +2 -0
  298. package/dist/web/static/assets/TaskDetail-5SR8zGzv.js.map +1 -0
  299. package/dist/web/static/assets/Tasks-DCgDqvOZ.js +2 -0
  300. package/dist/web/static/assets/Tasks-DCgDqvOZ.js.map +1 -0
  301. package/dist/web/static/assets/export-L_VBD2p1.js +4 -0
  302. package/dist/web/static/assets/export-L_VBD2p1.js.map +1 -0
  303. package/dist/web/static/assets/index-D8AKj26b.css +1 -0
  304. package/dist/web/static/assets/index-DxIbmNmr.js +3 -0
  305. package/dist/web/static/assets/index-DxIbmNmr.js.map +1 -0
  306. package/dist/web/static/assets/{lucide-53bR2rki.js → lucide-fJlPI3H7.js} +68 -38
  307. package/dist/web/static/assets/lucide-fJlPI3H7.js.map +1 -0
  308. package/dist/web/static/assets/time-Bxuk0M-C.js +2 -0
  309. package/dist/web/static/assets/time-Bxuk0M-C.js.map +1 -0
  310. package/dist/web/static/index.html +3 -3
  311. package/docs/concurrent-agents.md +129 -0
  312. package/docs/design/architecture-review-20260516.md +232 -0
  313. package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +219 -0
  314. package/docs/design/hook-failure-queue-spec-20260516-1530.md +204 -0
  315. package/docs/design/refactor-phase1-spec-20260515-1600.md +543 -0
  316. package/docs/design/refactor-phase2-spec-20260515-1700.md +424 -0
  317. package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +208 -0
  318. package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +104 -0
  319. package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +196 -0
  320. package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +56 -0
  321. package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +354 -0
  322. package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +421 -0
  323. package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +72 -0
  324. package/docs/reviews/claudemd-template-sync.md +54 -0
  325. package/docs/reviews/tasks-filter-pagination.md +80 -0
  326. package/docs/ruflo-learning-strategy.md +322 -0
  327. package/docs/skills-deduplication-analysis.md +83 -0
  328. package/docs/skills-multiformat-support.md +177 -0
  329. package/docs/skills-third-party.md +183 -0
  330. package/docs/testing/tasks-filter-pagination-test-report.md +86 -0
  331. package/forge +321 -0
  332. package/package.json +28 -62
  333. package/playwright.config.ts +40 -0
  334. package/scripts/demo-v2.ts +91 -0
  335. package/scripts/dev-daemon.sh +232 -0
  336. package/scripts/dev-web.ts +109 -0
  337. package/scripts/e2e-mcp-link.ts +423 -0
  338. package/scripts/e2e-methodology-quality.ts +253 -0
  339. package/scripts/e2e-routing.ts +456 -0
  340. package/scripts/e2e-user-methodology.ts +326 -0
  341. package/scripts/e2e-web-workflows.ts +299 -0
  342. package/scripts/migrate-legacy-to-dynamic.sql +108 -0
  343. package/scripts/regenerate-execution-docs.ts +116 -0
  344. package/scripts/sync-agent-skills.ts +193 -0
  345. package/scripts/test-hook.sh +71 -0
  346. package/scripts/verify-skill-loading.ts +62 -0
  347. package/src/claudemd/claudemd-generator.ts +777 -0
  348. package/src/claudemd/convention-extractor.ts +69 -0
  349. package/src/claudemd/index.ts +35 -0
  350. package/src/claudemd/persona-manager.ts +88 -0
  351. package/src/claudemd/resume-manager.ts +236 -0
  352. package/src/claudemd/tech-detector.ts +220 -0
  353. package/src/cli/commands/claudemd.ts +84 -0
  354. package/src/cli/commands/config.ts +46 -0
  355. package/src/cli/commands/daemon.ts +310 -0
  356. package/src/cli/commands/executions.ts +114 -0
  357. package/src/cli/commands/init.ts +204 -0
  358. package/src/cli/commands/logs.ts +181 -0
  359. package/src/cli/commands/mcp.ts +244 -0
  360. package/src/cli/commands/menu.ts +356 -0
  361. package/src/cli/commands/skills.ts +185 -0
  362. package/src/cli/commands/stats.ts +74 -0
  363. package/src/cli/commands/status.ts +69 -0
  364. package/src/cli/commands/template.ts +77 -0
  365. package/src/cli/commands/trace.ts +164 -0
  366. package/src/cli/index.ts +42 -0
  367. package/src/cli/init/hook-manager.ts +132 -0
  368. package/src/core/ai/provider.ts +308 -0
  369. package/src/core/ai/types.ts +51 -0
  370. package/src/core/config.ts +124 -0
  371. package/src/core/constants.ts +45 -0
  372. package/src/core/queue/index.ts +193 -0
  373. package/src/core/storage/base.ts +226 -0
  374. package/src/core/storage/events.ts +255 -0
  375. package/src/core/storage/injections.ts +78 -0
  376. package/src/core/storage/maintenance.ts +59 -0
  377. package/src/core/storage/migrations/002_add_skill_tracking.sql +6 -0
  378. package/src/core/storage/migrations/003_add_skill_invocations.sql +23 -0
  379. package/src/core/storage/performance-indexes.sql +23 -0
  380. package/src/core/storage/routing.ts +194 -0
  381. package/src/core/storage/rows.ts +112 -0
  382. package/src/core/storage/schema.sql +214 -0
  383. package/src/core/storage/sessions.ts +104 -0
  384. package/src/core/storage/skills.ts +164 -0
  385. package/src/core/storage/sqlite.ts +194 -0
  386. package/src/core/storage/tasks.ts +170 -0
  387. package/src/core/storage/token-usage.ts +93 -0
  388. package/src/core/types.ts +154 -0
  389. package/src/core/utils/error-handler.ts +256 -0
  390. package/src/core/utils/forge-resume-block.ts +74 -0
  391. package/src/core/utils/format.ts +69 -0
  392. package/src/core/utils/logger.ts +119 -0
  393. package/src/core/utils/lru-cache.ts +50 -0
  394. package/src/core/utils/path.ts +19 -0
  395. package/src/core/utils/session.ts +26 -0
  396. package/src/core/utils/time.ts +37 -0
  397. package/src/core/utils/token-tracker.ts +97 -0
  398. package/src/daemon/event-parser.ts +35 -0
  399. package/src/daemon/handlers/history-exporter.ts +117 -0
  400. package/src/daemon/handlers/post-tool-use.ts +50 -0
  401. package/src/daemon/handlers/stop.ts +215 -0
  402. package/src/daemon/handlers/user-prompt.ts +188 -0
  403. package/src/daemon/index.ts +278 -0
  404. package/src/daemon/launchd/com.claude-forge.daemon.plist.template +47 -0
  405. package/src/daemon/launchd-installer.ts +260 -0
  406. package/src/daemon/lifecycle.ts +128 -0
  407. package/src/daemon/router.ts +40 -0
  408. package/src/daemon/server.ts +209 -0
  409. package/src/daemon/services/anti-pattern-detector.ts +412 -0
  410. package/src/daemon/services/drift-detector.ts +232 -0
  411. package/src/daemon/services/task-segmenter.ts +112 -0
  412. package/src/daemon/services/weekly-report.ts +454 -0
  413. package/src/hooks/hook-lib.sh +81 -0
  414. package/src/hooks/notification.sh +35 -0
  415. package/src/hooks/post-tool-use.sh +61 -0
  416. package/src/hooks/pre-tool-use.sh +63 -0
  417. package/src/hooks/stop.sh +40 -0
  418. package/src/hooks/user-prompt-submit.sh +69 -0
  419. package/src/mcp/server.ts +322 -0
  420. package/src/skills/index.ts +2 -0
  421. package/src/skills/invocation-guard.ts +177 -0
  422. package/src/skills/matcher.ts +148 -0
  423. package/src/skills/official/code-simplifier.md +16 -0
  424. package/src/skills/official/find-skills.md +23 -0
  425. package/src/skills/official/official-api-design.md +17 -0
  426. package/src/skills/official/official-architecture-decision.md +20 -0
  427. package/src/skills/official/official-bmad.md +118 -0
  428. package/src/skills/official/official-db-schema-design.md +16 -0
  429. package/src/skills/official/official-debug.md +17 -0
  430. package/src/skills/official/official-doc-driven.md +31 -0
  431. package/src/skills/official/official-harness-engineering.md +108 -0
  432. package/src/skills/official/official-performance-optimization.md +30 -0
  433. package/src/skills/official/official-pr-review.md +35 -0
  434. package/src/skills/official/official-release-checklist.md +30 -0
  435. package/src/skills/official/official-security-hardening.md +26 -0
  436. package/src/skills/official/official-spec-driven-design.md +31 -0
  437. package/src/skills/official/planning-with-files.md +37 -0
  438. package/src/skills/official/ui-ux-pro-max.md +18 -0
  439. package/src/skills/official/webapp-testing.md +12 -0
  440. package/src/skills/official-skills.ts +89 -0
  441. package/src/skills/registry.ts +355 -0
  442. package/src/skills/semantic-matcher.ts +231 -0
  443. package/src/skills/tools/pipeline-suggest.ts +226 -0
  444. package/src/skills/tools/skill-invoke.ts +168 -0
  445. package/src/skills/tools/skill-list.ts +59 -0
  446. package/src/templates/go.yaml +53 -0
  447. package/src/templates/python.yaml +59 -0
  448. package/src/templates/react.yaml +55 -0
  449. package/src/templates/template-manager.ts +170 -0
  450. package/src/web/auth-middleware.ts +55 -0
  451. package/src/web/routes/ai.ts +204 -0
  452. package/src/web/routes/auth.ts +22 -0
  453. package/src/web/routes/drift.ts +25 -0
  454. package/src/web/routes/error-handler.ts +120 -0
  455. package/src/web/routes/events.ts +47 -0
  456. package/src/web/routes/insights.ts +43 -0
  457. package/src/web/routes/patch.ts +117 -0
  458. package/src/web/routes/reports.ts +34 -0
  459. package/src/web/routes/rules.ts +101 -0
  460. package/src/web/routes/sessions.ts +262 -0
  461. package/src/web/routes/skill-stats.ts +132 -0
  462. package/src/web/routes/skills.ts +349 -0
  463. package/src/web/routes/static.ts +67 -0
  464. package/src/web/routes/stats.ts +60 -0
  465. package/src/web/routes/status.ts +30 -0
  466. package/src/web/routes/tasks.ts +218 -0
  467. package/src/web/routes/token-usage.ts +20 -0
  468. package/src/web/routes/trace.ts +138 -0
  469. package/src/web/routes/types.ts +56 -0
  470. package/src/web/server.ts +134 -0
  471. package/src/web/ssrf-guard.ts +112 -0
  472. package/src/web/static/index.html +3251 -0
  473. package/src/web/static/vendor/chart.umd.min.js +20 -0
  474. package/tests/e2e/dashboard.spec.ts +205 -0
  475. package/tests/e2e/routing-skill-e2e.test.ts +39 -0
  476. package/tests/helpers/mock-ai.ts +92 -0
  477. package/tests/helpers/mock-storage.ts +159 -0
  478. package/tests/integration/queue-replay.integration.test.ts +193 -0
  479. package/tests/integration/tasks-filter.integration.test.ts +154 -0
  480. package/tests/performance/database.benchmark.ts +161 -0
  481. package/tests/semantic-matcher.test.ts +99 -0
  482. package/tests/skill-matcher.test.ts +110 -0
  483. package/tests/unit/ai-provider-retry.test.ts +194 -0
  484. package/tests/unit/ai-provider-vision.test.ts +224 -0
  485. package/tests/unit/claudemd-generator.test.ts +68 -0
  486. package/tests/unit/cli-mcp.test.ts +141 -0
  487. package/tests/unit/handlers.test.ts +171 -0
  488. package/tests/unit/invocation-guard.test.ts +125 -0
  489. package/tests/unit/queue.test.ts +272 -0
  490. package/tests/unit/router.test.ts +138 -0
  491. package/tests/unit/security.test.ts +128 -0
  492. package/tests/unit/skill-invocations-workflow.test.ts +495 -0
  493. package/tests/unit/skill-registry.test.ts +94 -0
  494. package/tests/unit/skills/invocation-guard-ttl.test.ts +211 -0
  495. package/tests/unit/skills/official-skills-loader.test.ts +126 -0
  496. package/tests/unit/skills/registry-multiformat.test.ts +92 -0
  497. package/tests/unit/storage/sessions-aggregate.test.ts +435 -0
  498. package/tests/unit/storage/sqlite-refactor-harness.test.ts +314 -0
  499. package/tests/unit/storage.test.ts +172 -0
  500. package/tests/unit/token-usage.test.ts +144 -0
  501. package/tests/unit/type-guards.test.ts +201 -0
  502. package/tests/unit/utils/format.test.ts +189 -0
  503. package/tests/unit/utils/session.test.ts +89 -0
  504. package/tests/unit/utils/time.test.ts +112 -0
  505. package/tests/unit/web/routes-auth.test.ts +93 -0
  506. package/tests/unit/web/routes-events.test.ts +101 -0
  507. package/tests/unit/web/routes-sessions.test.ts +181 -0
  508. package/tests/unit/web/routes-skill-stats.test.ts +179 -0
  509. package/tests/unit/web/routes-stats.test.ts +92 -0
  510. package/tests/unit/web/routes-tasks.test.ts +351 -0
  511. package/tsconfig.json +22 -0
  512. package/vitest.config.ts +21 -0
  513. package/vitest.integration.config.ts +16 -0
  514. package/web/CLAUDE.md +20 -0
  515. package/web/index.html +13 -0
  516. package/web/package-lock.json +4854 -0
  517. package/web/package.json +35 -0
  518. package/web/postcss.config.js +6 -0
  519. package/web/src/App.tsx +110 -0
  520. package/web/src/components/CodeBlock.tsx +31 -0
  521. package/web/src/components/Confirm.tsx +96 -0
  522. package/web/src/components/Drawer.tsx +60 -0
  523. package/web/src/components/Layout.tsx +145 -0
  524. package/web/src/components/MarkdownRenderer.tsx +77 -0
  525. package/web/src/components/SearchInput.tsx +31 -0
  526. package/web/src/components/SessionDetailContent.tsx +157 -0
  527. package/web/src/components/Toast.tsx +92 -0
  528. package/web/src/index.css +19 -0
  529. package/web/src/main.tsx +31 -0
  530. package/web/src/pages/AIConfig.tsx +233 -0
  531. package/web/src/pages/Dashboard.tsx +572 -0
  532. package/web/src/pages/Events.tsx +271 -0
  533. package/web/src/pages/Reports.tsx +428 -0
  534. package/web/src/pages/SessionDetail.tsx +162 -0
  535. package/web/src/pages/Sessions.tsx +205 -0
  536. package/web/src/pages/Skills.tsx +180 -0
  537. package/web/src/pages/TaskDetail.tsx +511 -0
  538. package/web/src/pages/Tasks.tsx +150 -0
  539. package/web/src/utils/auth.ts +59 -0
  540. package/web/src/utils/export.ts +54 -0
  541. package/web/src/utils/time.ts +13 -0
  542. package/web/tailwind.config.js +11 -0
  543. package/web/tsconfig.json +21 -0
  544. package/web/tsconfig.node.json +10 -0
  545. package/web/vite.config.ts +76 -0
  546. package/winspan-claude-forge-8.43.0.tgz +0 -0
  547. package/dist/agents/definition.d.ts +0 -62
  548. package/dist/agents/definition.d.ts.map +0 -1
  549. package/dist/agents/definition.js +0 -27
  550. package/dist/agents/definition.js.map +0 -1
  551. package/dist/agents/distributor.d.ts +0 -23
  552. package/dist/agents/distributor.d.ts.map +0 -1
  553. package/dist/agents/distributor.js +0 -85
  554. package/dist/agents/distributor.js.map +0 -1
  555. package/dist/agents/index.d.ts +0 -5
  556. package/dist/agents/index.d.ts.map +0 -1
  557. package/dist/agents/index.js +0 -5
  558. package/dist/agents/index.js.map +0 -1
  559. package/dist/agents/methodologies/agent-builder.d.ts +0 -21
  560. package/dist/agents/methodologies/agent-builder.d.ts.map +0 -1
  561. package/dist/agents/methodologies/agent-builder.js +0 -149
  562. package/dist/agents/methodologies/agent-builder.js.map +0 -1
  563. package/dist/agents/methodologies/phases/bmad/analyze.d.ts +0 -3
  564. package/dist/agents/methodologies/phases/bmad/analyze.d.ts.map +0 -1
  565. package/dist/agents/methodologies/phases/bmad/analyze.js +0 -19
  566. package/dist/agents/methodologies/phases/bmad/analyze.js.map +0 -1
  567. package/dist/agents/methodologies/phases/bmad/design.d.ts +0 -3
  568. package/dist/agents/methodologies/phases/bmad/design.d.ts.map +0 -1
  569. package/dist/agents/methodologies/phases/bmad/design.js +0 -18
  570. package/dist/agents/methodologies/phases/bmad/design.js.map +0 -1
  571. package/dist/agents/methodologies/phases/bmad/implement.d.ts +0 -3
  572. package/dist/agents/methodologies/phases/bmad/implement.d.ts.map +0 -1
  573. package/dist/agents/methodologies/phases/bmad/implement.js +0 -17
  574. package/dist/agents/methodologies/phases/bmad/implement.js.map +0 -1
  575. package/dist/agents/methodologies/phases/bmad/index.d.ts +0 -6
  576. package/dist/agents/methodologies/phases/bmad/index.d.ts.map +0 -1
  577. package/dist/agents/methodologies/phases/bmad/index.js +0 -6
  578. package/dist/agents/methodologies/phases/bmad/index.js.map +0 -1
  579. package/dist/agents/methodologies/phases/bmad/review.d.ts +0 -3
  580. package/dist/agents/methodologies/phases/bmad/review.d.ts.map +0 -1
  581. package/dist/agents/methodologies/phases/bmad/review.js +0 -17
  582. package/dist/agents/methodologies/phases/bmad/review.js.map +0 -1
  583. package/dist/agents/methodologies/phases/bmad/test.d.ts +0 -3
  584. package/dist/agents/methodologies/phases/bmad/test.d.ts.map +0 -1
  585. package/dist/agents/methodologies/phases/bmad/test.js +0 -21
  586. package/dist/agents/methodologies/phases/bmad/test.js.map +0 -1
  587. package/dist/agents/methodologies/phases/harness/fix.d.ts +0 -3
  588. package/dist/agents/methodologies/phases/harness/fix.d.ts.map +0 -1
  589. package/dist/agents/methodologies/phases/harness/fix.js +0 -17
  590. package/dist/agents/methodologies/phases/harness/fix.js.map +0 -1
  591. package/dist/agents/methodologies/phases/harness/index.d.ts +0 -6
  592. package/dist/agents/methodologies/phases/harness/index.d.ts.map +0 -1
  593. package/dist/agents/methodologies/phases/harness/index.js +0 -6
  594. package/dist/agents/methodologies/phases/harness/index.js.map +0 -1
  595. package/dist/agents/methodologies/phases/harness/reproduce.d.ts +0 -3
  596. package/dist/agents/methodologies/phases/harness/reproduce.d.ts.map +0 -1
  597. package/dist/agents/methodologies/phases/harness/reproduce.js +0 -20
  598. package/dist/agents/methodologies/phases/harness/reproduce.js.map +0 -1
  599. package/dist/agents/methodologies/phases/harness/root-cause.d.ts +0 -3
  600. package/dist/agents/methodologies/phases/harness/root-cause.d.ts.map +0 -1
  601. package/dist/agents/methodologies/phases/harness/root-cause.js +0 -21
  602. package/dist/agents/methodologies/phases/harness/root-cause.js.map +0 -1
  603. package/dist/agents/methodologies/phases/harness/safety-net.d.ts +0 -3
  604. package/dist/agents/methodologies/phases/harness/safety-net.d.ts.map +0 -1
  605. package/dist/agents/methodologies/phases/harness/safety-net.js +0 -17
  606. package/dist/agents/methodologies/phases/harness/safety-net.js.map +0 -1
  607. package/dist/agents/methodologies/phases/harness/verify.d.ts +0 -3
  608. package/dist/agents/methodologies/phases/harness/verify.d.ts.map +0 -1
  609. package/dist/agents/methodologies/phases/harness/verify.js +0 -22
  610. package/dist/agents/methodologies/phases/harness/verify.js.map +0 -1
  611. package/dist/agents/methodologies/presets.d.ts +0 -10
  612. package/dist/agents/methodologies/presets.d.ts.map +0 -1
  613. package/dist/agents/methodologies/presets.js +0 -79
  614. package/dist/agents/methodologies/presets.js.map +0 -1
  615. package/dist/agents/methodologies/types.d.ts +0 -45
  616. package/dist/agents/methodologies/types.d.ts.map +0 -1
  617. package/dist/agents/methodologies/types.js +0 -10
  618. package/dist/agents/methodologies/types.js.map +0 -1
  619. package/dist/agents/methodologies/user-config-loader.d.ts +0 -30
  620. package/dist/agents/methodologies/user-config-loader.d.ts.map +0 -1
  621. package/dist/agents/methodologies/user-config-loader.js +0 -159
  622. package/dist/agents/methodologies/user-config-loader.js.map +0 -1
  623. package/dist/agents/official-agents.d.ts +0 -4
  624. package/dist/agents/official-agents.d.ts.map +0 -1
  625. package/dist/agents/official-agents.js +0 -559
  626. package/dist/agents/official-agents.js.map +0 -1
  627. package/dist/agents/registry.d.ts +0 -57
  628. package/dist/agents/registry.d.ts.map +0 -1
  629. package/dist/agents/registry.js +0 -271
  630. package/dist/agents/registry.js.map +0 -1
  631. package/dist/capability/index.d.ts +0 -10
  632. package/dist/capability/index.d.ts.map +0 -1
  633. package/dist/capability/index.js +0 -10
  634. package/dist/capability/index.js.map +0 -1
  635. package/dist/capability/types.d.ts +0 -10
  636. package/dist/capability/types.d.ts.map +0 -1
  637. package/dist/capability/types.js +0 -10
  638. package/dist/capability/types.js.map +0 -1
  639. package/dist/cli/commands/agents.d.ts +0 -3
  640. package/dist/cli/commands/agents.d.ts.map +0 -1
  641. package/dist/cli/commands/agents.js +0 -62
  642. package/dist/cli/commands/agents.js.map +0 -1
  643. package/dist/cli/commands/rules.d.ts +0 -8
  644. package/dist/cli/commands/rules.d.ts.map +0 -1
  645. package/dist/cli/commands/rules.js +0 -89
  646. package/dist/cli/commands/rules.js.map +0 -1
  647. package/dist/daemon/auto-disable-scheduler.d.ts +0 -53
  648. package/dist/daemon/auto-disable-scheduler.d.ts.map +0 -1
  649. package/dist/daemon/auto-disable-scheduler.js +0 -114
  650. package/dist/daemon/auto-disable-scheduler.js.map +0 -1
  651. package/dist/daemon/handlers/pre-tool-use.d.ts +0 -39
  652. package/dist/daemon/handlers/pre-tool-use.d.ts.map +0 -1
  653. package/dist/daemon/handlers/pre-tool-use.js +0 -166
  654. package/dist/daemon/handlers/pre-tool-use.js.map +0 -1
  655. package/dist/daemon/routing-observer.d.ts +0 -42
  656. package/dist/daemon/routing-observer.d.ts.map +0 -1
  657. package/dist/daemon/routing-observer.js +0 -264
  658. package/dist/daemon/routing-observer.js.map +0 -1
  659. package/dist/daemon/routing-state.d.ts +0 -64
  660. package/dist/daemon/routing-state.d.ts.map +0 -1
  661. package/dist/daemon/routing-state.js +0 -240
  662. package/dist/daemon/routing-state.js.map +0 -1
  663. package/dist/engine/agent-router.d.ts +0 -142
  664. package/dist/engine/agent-router.d.ts.map +0 -1
  665. package/dist/engine/agent-router.js +0 -276
  666. package/dist/engine/agent-router.js.map +0 -1
  667. package/dist/engine/context-builder.d.ts +0 -23
  668. package/dist/engine/context-builder.d.ts.map +0 -1
  669. package/dist/engine/context-builder.js +0 -63
  670. package/dist/engine/context-builder.js.map +0 -1
  671. package/dist/engine/conventions/basic-security.yaml +0 -109
  672. package/dist/engine/conventions/code-quality.yaml +0 -123
  673. package/dist/engine/conventions/database-safety.yaml +0 -74
  674. package/dist/engine/conventions/dependency-safety.yaml +0 -132
  675. package/dist/engine/conventions/docker-safety.yaml +0 -69
  676. package/dist/engine/conventions/git-safety.yaml +0 -118
  677. package/dist/engine/conventions/go-best-practices.yaml +0 -84
  678. package/dist/engine/conventions/python-best-practices.yaml +0 -96
  679. package/dist/engine/conventions/react-best-practices.yaml +0 -96
  680. package/dist/engine/conventions/routing.yaml +0 -378
  681. package/dist/engine/conventions/strict-security.yaml +0 -30
  682. package/dist/engine/conventions/ts-quality.yaml +0 -49
  683. package/dist/engine/dsl/compiler.d.ts +0 -34
  684. package/dist/engine/dsl/compiler.d.ts.map +0 -1
  685. package/dist/engine/dsl/compiler.js +0 -702
  686. package/dist/engine/dsl/compiler.js.map +0 -1
  687. package/dist/engine/dsl/parser.d.ts +0 -25
  688. package/dist/engine/dsl/parser.d.ts.map +0 -1
  689. package/dist/engine/dsl/parser.js +0 -208
  690. package/dist/engine/dsl/parser.js.map +0 -1
  691. package/dist/engine/dsl/runtime.d.ts +0 -46
  692. package/dist/engine/dsl/runtime.d.ts.map +0 -1
  693. package/dist/engine/dsl/runtime.js +0 -173
  694. package/dist/engine/dsl/runtime.js.map +0 -1
  695. package/dist/engine/dsl/types.d.ts +0 -139
  696. package/dist/engine/dsl/types.d.ts.map +0 -1
  697. package/dist/engine/dsl/types.js +0 -11
  698. package/dist/engine/dsl/types.js.map +0 -1
  699. package/dist/engine/evidence-store.d.ts +0 -44
  700. package/dist/engine/evidence-store.d.ts.map +0 -1
  701. package/dist/engine/evidence-store.js +0 -109
  702. package/dist/engine/evidence-store.js.map +0 -1
  703. package/dist/engine/experiment-router.d.ts +0 -102
  704. package/dist/engine/experiment-router.d.ts.map +0 -1
  705. package/dist/engine/experiment-router.js +0 -289
  706. package/dist/engine/experiment-router.js.map +0 -1
  707. package/dist/engine/recommender.d.ts +0 -52
  708. package/dist/engine/recommender.d.ts.map +0 -1
  709. package/dist/engine/recommender.js +0 -162
  710. package/dist/engine/recommender.js.map +0 -1
  711. package/dist/engine/rule-engine.d.ts +0 -33
  712. package/dist/engine/rule-engine.d.ts.map +0 -1
  713. package/dist/engine/rule-engine.js +0 -250
  714. package/dist/engine/rule-engine.js.map +0 -1
  715. package/dist/engine/security-gates.d.ts +0 -42
  716. package/dist/engine/security-gates.d.ts.map +0 -1
  717. package/dist/engine/security-gates.js +0 -210
  718. package/dist/engine/security-gates.js.map +0 -1
  719. package/dist/intelligence/classifier.d.ts +0 -75
  720. package/dist/intelligence/classifier.d.ts.map +0 -1
  721. package/dist/intelligence/classifier.js +0 -352
  722. package/dist/intelligence/classifier.js.map +0 -1
  723. package/dist/intelligence/context-gatherer.d.ts +0 -101
  724. package/dist/intelligence/context-gatherer.d.ts.map +0 -1
  725. package/dist/intelligence/context-gatherer.js +0 -417
  726. package/dist/intelligence/context-gatherer.js.map +0 -1
  727. package/dist/intelligence/cot-classifier.d.ts +0 -95
  728. package/dist/intelligence/cot-classifier.d.ts.map +0 -1
  729. package/dist/intelligence/cot-classifier.js +0 -391
  730. package/dist/intelligence/cot-classifier.js.map +0 -1
  731. package/dist/intelligence/distiller.d.ts +0 -22
  732. package/dist/intelligence/distiller.d.ts.map +0 -1
  733. package/dist/intelligence/distiller.js +0 -108
  734. package/dist/intelligence/distiller.js.map +0 -1
  735. package/dist/intelligence/execution-doc-builder.d.ts +0 -151
  736. package/dist/intelligence/execution-doc-builder.d.ts.map +0 -1
  737. package/dist/intelligence/execution-doc-builder.js +0 -1018
  738. package/dist/intelligence/execution-doc-builder.js.map +0 -1
  739. package/dist/intelligence/intent-types.d.ts +0 -13
  740. package/dist/intelligence/intent-types.d.ts.map +0 -1
  741. package/dist/intelligence/intent-types.js +0 -19
  742. package/dist/intelligence/intent-types.js.map +0 -1
  743. package/dist/intelligence/multimodal-parser.d.ts +0 -105
  744. package/dist/intelligence/multimodal-parser.d.ts.map +0 -1
  745. package/dist/intelligence/multimodal-parser.js +0 -425
  746. package/dist/intelligence/multimodal-parser.js.map +0 -1
  747. package/dist/intelligence/quality-gate.d.ts +0 -45
  748. package/dist/intelligence/quality-gate.d.ts.map +0 -1
  749. package/dist/intelligence/quality-gate.js +0 -193
  750. package/dist/intelligence/quality-gate.js.map +0 -1
  751. package/dist/intelligence/task-segmenter.d.ts.map +0 -1
  752. package/dist/intelligence/task-segmenter.js.map +0 -1
  753. package/dist/web/routes/agents.d.ts +0 -7
  754. package/dist/web/routes/agents.d.ts.map +0 -1
  755. package/dist/web/routes/agents.js +0 -209
  756. package/dist/web/routes/agents.js.map +0 -1
  757. package/dist/web/routes/execution-trace.d.ts +0 -21
  758. package/dist/web/routes/execution-trace.d.ts.map +0 -1
  759. package/dist/web/routes/execution-trace.js +0 -353
  760. package/dist/web/routes/execution-trace.js.map +0 -1
  761. package/dist/web/routes/experiments.d.ts +0 -15
  762. package/dist/web/routes/experiments.d.ts.map +0 -1
  763. package/dist/web/routes/experiments.js +0 -187
  764. package/dist/web/routes/experiments.js.map +0 -1
  765. package/dist/web/routes/routing.d.ts +0 -17
  766. package/dist/web/routes/routing.d.ts.map +0 -1
  767. package/dist/web/routes/routing.js +0 -592
  768. package/dist/web/routes/routing.js.map +0 -1
  769. package/dist/web/routes/workflows.d.ts +0 -19
  770. package/dist/web/routes/workflows.d.ts.map +0 -1
  771. package/dist/web/routes/workflows.js +0 -86
  772. package/dist/web/routes/workflows.js.map +0 -1
  773. package/dist/web/static/assets/AIConfig-R5wZ3ZKT.js +0 -2
  774. package/dist/web/static/assets/AIConfig-R5wZ3ZKT.js.map +0 -1
  775. package/dist/web/static/assets/Agents-Beg34V1g.js +0 -2
  776. package/dist/web/static/assets/Agents-Beg34V1g.js.map +0 -1
  777. package/dist/web/static/assets/CodeBlock--H53gk46.js +0 -2
  778. package/dist/web/static/assets/CodeBlock--H53gk46.js.map +0 -1
  779. package/dist/web/static/assets/Dashboard-Cy1xsj1J.js +0 -2
  780. package/dist/web/static/assets/Dashboard-Cy1xsj1J.js.map +0 -1
  781. package/dist/web/static/assets/Events-mFhXl4zI.js +0 -2
  782. package/dist/web/static/assets/Events-mFhXl4zI.js.map +0 -1
  783. package/dist/web/static/assets/ExecutionTrace-DG901hLR.js +0 -3
  784. package/dist/web/static/assets/ExecutionTrace-DG901hLR.js.map +0 -1
  785. package/dist/web/static/assets/MarkdownRenderer-CCIz1MOz.js +0 -2
  786. package/dist/web/static/assets/MarkdownRenderer-CCIz1MOz.js.map +0 -1
  787. package/dist/web/static/assets/Routing-B7BFLfjh.js +0 -2
  788. package/dist/web/static/assets/Routing-B7BFLfjh.js.map +0 -1
  789. package/dist/web/static/assets/SessionDetail-BT0l4RrK.js +0 -2
  790. package/dist/web/static/assets/SessionDetail-BT0l4RrK.js.map +0 -1
  791. package/dist/web/static/assets/Sessions-C6J_HQ_u.js +0 -2
  792. package/dist/web/static/assets/Sessions-C6J_HQ_u.js.map +0 -1
  793. package/dist/web/static/assets/Skills-4DQWLaTv.js +0 -2
  794. package/dist/web/static/assets/Skills-4DQWLaTv.js.map +0 -1
  795. package/dist/web/static/assets/WorkflowDetail-zhNqUkBE.js +0 -2
  796. package/dist/web/static/assets/WorkflowDetail-zhNqUkBE.js.map +0 -1
  797. package/dist/web/static/assets/Workflows-Btvi-lGw.js +0 -2
  798. package/dist/web/static/assets/Workflows-Btvi-lGw.js.map +0 -1
  799. package/dist/web/static/assets/export-BQQZLaHV.js +0 -4
  800. package/dist/web/static/assets/export-BQQZLaHV.js.map +0 -1
  801. package/dist/web/static/assets/index-Cgr9qMtq.js +0 -3
  802. package/dist/web/static/assets/index-Cgr9qMtq.js.map +0 -1
  803. package/dist/web/static/assets/index-CngWb5gC.css +0 -1
  804. package/dist/web/static/assets/lucide-53bR2rki.js.map +0 -1
@@ -1,812 +1,155 @@
1
1
  /**
2
- * Simplified SQLite storage for minimal Forge
3
- * No repository pattern, no base class — just direct SQL in one file
2
+ * SQLiteStorage 装配入口(facade)
3
+ *
4
+ * 历史上这是一个 1000+ 行的单文件实现。重构后职责拆分到独立的 *Operations 类,
5
+ * 此文件保留为:
6
+ * - 组合 db 实例 + 各个 Operations
7
+ * - 保持原有 API 完全向后兼容(方法签名 / EventEmitter 行为 / 类型 re-export)
8
+ *
9
+ * 职责矩阵:
10
+ * base.ts — 数据库连接、schema、迁移
11
+ * events.ts — events 表读写
12
+ * sessions.ts — sessions 聚合表
13
+ * tasks.ts — tasks / task_events
14
+ * injections.ts — injections
15
+ * routing.ts — routing_events + experiment_assignments
16
+ * skills.ts — skill_invocations + workflow 聚合
17
+ * token-usage.ts — token_usage
18
+ * maintenance.ts — 清理 / VACUUM
4
19
  */
5
- import Database from 'better-sqlite3';
6
- import { readFileSync, existsSync, mkdirSync, statSync } from 'node:fs';
7
- import { dirname, join } from 'node:path';
8
- import { randomUUID } from 'node:crypto';
9
- import { fileURLToPath } from 'node:url';
10
20
  import { EventEmitter } from 'node:events';
11
- import { DATABASE } from '../constants.js';
21
+ import { SQLiteBase } from './base.js';
22
+ import { EventOperations } from './events.js';
23
+ import { SessionOperations } from './sessions.js';
24
+ import { TaskOperations } from './tasks.js';
25
+ import { InjectionOperations } from './injections.js';
26
+ import { RoutingOperations } from './routing.js';
27
+ import { SkillOperations } from './skills.js';
28
+ import { TokenUsageOperations } from './token-usage.js';
29
+ import { MaintenanceOperations } from './maintenance.js';
12
30
  import { logger } from '../utils/logger.js';
13
31
  export class SQLiteStorage extends EventEmitter {
14
- db;
15
- dbPath;
32
+ base;
33
+ events;
34
+ sessions;
35
+ tasks;
36
+ injections;
37
+ routing;
38
+ skills;
39
+ tokenUsage;
40
+ maintenance;
16
41
  constructor(dbPath) {
17
42
  super();
18
- this.dbPath = dbPath;
19
- const dir = dirname(dbPath);
20
- if (!existsSync(dir)) {
21
- mkdirSync(dir, { recursive: true });
22
- }
23
- this.db = new Database(dbPath);
24
- this.db.pragma('journal_mode = WAL');
25
- this.db.pragma('synchronous = NORMAL');
26
- this.db.pragma('wal_autocheckpoint = 100');
27
- this.db.pragma(`cache_size = ${DATABASE.CACHE_SIZE}`);
28
- this.db.pragma(`busy_timeout = ${DATABASE.BUSY_TIMEOUT}`);
29
- this.initSchema();
30
- this.runMigrations();
31
- }
32
- initSchema() {
33
- const thisDir = dirname(fileURLToPath(import.meta.url));
34
- const schemaPath = join(thisDir, 'schema.sql');
35
- if (existsSync(schemaPath)) {
36
- const schema = readFileSync(schemaPath, 'utf-8');
37
- this.db.exec(schema);
38
- }
39
- else {
40
- // Inline fallback — events table only
41
- this.db.exec(`
42
- CREATE TABLE IF NOT EXISTS events (
43
- event_id TEXT PRIMARY KEY, session_id TEXT NOT NULL,
44
- project_path TEXT NOT NULL, timestamp TEXT NOT NULL,
45
- hook_type TEXT NOT NULL, tool_name TEXT, tool_input TEXT,
46
- tool_output TEXT, user_prompt TEXT, ai_response TEXT,
47
- distilled INTEGER DEFAULT 0, created_at TEXT DEFAULT (datetime('now'))
48
- );
49
- CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);
50
- CREATE INDEX IF NOT EXISTS idx_events_project ON events(project_path);
51
- CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp DESC);
52
- CREATE INDEX IF NOT EXISTS idx_events_distilled ON events(distilled);
53
- `);
54
- }
55
- }
56
- hasColumn(table, column) {
57
- try {
58
- const rows = this.db.prepare(`PRAGMA table_info(${table})`).all();
59
- return rows.some(r => r.name === column);
60
- }
61
- catch {
62
- return false;
63
- }
64
- }
65
- addColumnIfMissing(table, column, definition) {
66
- if (!this.hasColumn(table, column)) {
67
- try {
68
- this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
69
- logger.info(`[SQLiteStorage] migration: added ${table}.${column}`);
70
- }
71
- catch (err) {
72
- logger.warn(`[SQLiteStorage] migration: ALTER ${table} ADD ${column} failed: ${err}`);
73
- }
74
- }
75
- }
76
- /**
77
- * Incremental schema migrations. Kept idempotent so daemon restarts are safe.
78
- * New columns since the base schema.sql go here.
79
- */
80
- runMigrations() {
81
- // sessions: first_prompt — 避免 querySessions 再对 events 表做 O(sessions × events)
82
- // 的相关子查询;新增列后若库里已有 sessions 但无 first_prompt,后续 backfill 会补齐。
83
- this.addColumnIfMissing('sessions', 'first_prompt', 'TEXT');
84
- // routing_events: skill_confidence / skill_source (Skill 监控字段)
85
- this.addColumnIfMissing('routing_events', 'skill_confidence', 'REAL');
86
- this.addColumnIfMissing('routing_events', 'skill_source', 'TEXT');
87
- // skill_invocations: 工作流追踪字段(v8.38+)
88
- // 解析 reason 字段的 "<workflow>/<phase>[:feature-slug]" 格式后落库到独立列。
89
- this.addColumnIfMissing('skill_invocations', 'workflow', 'TEXT');
90
- this.addColumnIfMissing('skill_invocations', 'phase', 'TEXT');
91
- this.addColumnIfMissing('skill_invocations', 'feature_slug', 'TEXT');
92
- this.addColumnIfMissing('skill_invocations', 'artifact_path', 'TEXT');
93
- // skill_invocations: 工作流字段索引(CREATE INDEX IF NOT EXISTS 天然幂等)
94
- try {
95
- this.db.exec(`CREATE INDEX IF NOT EXISTS idx_skill_invocations_workflow ON skill_invocations(workflow, phase);
96
- CREATE INDEX IF NOT EXISTS idx_skill_invocations_feature ON skill_invocations(feature_slug);`);
97
- }
98
- catch (err) {
99
- logger.warn(`[SQLiteStorage] migration: create skill_invocations workflow indexes failed: ${err}`);
100
- }
101
- // sessions 聚合表性能索引(幂等):start_time 用于 querySessions 的 ORDER BY
102
- try {
103
- this.db.exec('CREATE INDEX IF NOT EXISTS idx_sessions_start_time ON sessions(start_time DESC)');
104
- }
105
- catch (err) {
106
- logger.warn(`[SQLiteStorage] migration: create idx_sessions_start_time failed: ${err}`);
107
- }
108
- // 一次性回填 sessions 聚合表(仅在 sessions 尚未对齐时触发)
109
- this.backfillSessionsIfNeeded();
110
- }
111
- /**
112
- * 将 events 表按 session_id 聚合回填到 sessions 表,仅在 sessions 尚未对齐
113
- * (没有任何一行带 first_prompt)时触发。旧库升级场景:引入 sessions 聚合表 +
114
- * upsert 写入路径后,历史 events 不会自动同步到 sessions,必须通过一次性回填补齐。
115
- *
116
- * 幂等策略:检测到已有 first_prompt 非空的聚合行就跳过;避免覆盖已被新写路径
117
- * upsert 过的数据。
118
- */
119
- backfillSessionsIfNeeded() {
120
- const eventsExists = this.db
121
- .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='events'`)
122
- .get();
123
- if (!eventsExists)
124
- return;
125
- const aggRow = this.db
126
- .prepare(`SELECT COUNT(*) AS total, COUNT(first_prompt) AS with_prompt FROM sessions`)
127
- .get();
128
- if (aggRow.with_prompt > 0)
129
- return;
130
- logger.info('[SQLiteStorage] backfilling sessions aggregate from events...');
131
- try {
132
- const backfill = this.db.transaction(() => {
133
- this.db.exec(`
134
- INSERT INTO sessions (
135
- session_id, project_path, status, first_prompt,
136
- start_time, end_time, last_event_time, event_count
137
- )
138
- SELECT
139
- e.session_id,
140
- e.project_path,
141
- 'active' AS status,
142
- (SELECT substr(COALESCE(e2.user_prompt, json_extract(e2.tool_input, '$.user_prompt')), 1, 200)
143
- FROM events e2
144
- WHERE e2.session_id = e.session_id
145
- AND e2.hook_type = 'UserPromptSubmit'
146
- AND (e2.user_prompt IS NOT NULL OR json_extract(e2.tool_input, '$.user_prompt') IS NOT NULL)
147
- ORDER BY e2.timestamp ASC LIMIT 1) AS first_prompt,
148
- MIN(e.timestamp) AS start_time,
149
- MAX(e.timestamp) AS end_time,
150
- MAX(e.timestamp) AS last_event_time,
151
- COUNT(*) AS event_count
152
- FROM events e
153
- GROUP BY e.session_id, e.project_path
154
- ON CONFLICT(session_id) DO UPDATE SET
155
- first_prompt = COALESCE(sessions.first_prompt, excluded.first_prompt),
156
- end_time = MAX(COALESCE(sessions.end_time, ''), excluded.end_time),
157
- last_event_time = MAX(COALESCE(sessions.last_event_time, ''), excluded.last_event_time),
158
- event_count = excluded.event_count,
159
- updated_at = datetime('now')
160
- `);
161
- });
162
- backfill();
163
- const migrated = this.db.prepare('SELECT COUNT(*) AS c FROM sessions').get();
164
- logger.info(`[SQLiteStorage] backfilled ${migrated.c} sessions from events`);
165
- }
166
- catch (err) {
167
- logger.warn(`[SQLiteStorage] backfillSessionsIfNeeded failed: ${err}`);
168
- }
169
- }
170
- getDatabase() {
171
- return this.db;
172
- }
173
- getDbPath() {
174
- return this.dbPath;
175
- }
176
- // ── Event Operations ────────────────────────────────────────────────────
177
- writeEvent(event) {
178
- const eventId = event.event_id || randomUUID();
179
- const stmt = this.db.prepare(`
180
- INSERT INTO events (event_id, session_id, project_path, timestamp, hook_type,
181
- tool_name, tool_input, tool_output, user_prompt, ai_response, distilled)
182
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)
183
- `);
184
- stmt.run(eventId, event.session_id, event.project_path, event.timestamp, event.hook_type, event.tool_name ?? null, event.tool_input ? JSON.stringify(event.tool_input) : null, event.tool_output ? JSON.stringify(event.tool_output) : null, event.user_prompt ?? null, event.ai_response ?? null);
185
- // 聚合到 sessions 表。单独 try/catch:一旦聚合失败(比如 schema 升级过程中
186
- // 的短暂窗口),也不能影响原事件的持久化,上层已经 commit 过 events 了。
187
- try {
188
- this.upsertSession(event);
189
- }
190
- catch (err) {
191
- logger.warn(`[SQLiteStorage] upsertSession failed (event still written): ${err}`);
192
- }
193
- this.emit('event', { ...event, event_id: eventId });
194
- }
195
- /**
196
- * 将事件聚合到 sessions 表,供 querySessions 直接读取,避免对 events 做 O(n²)
197
- * 的 GROUP BY + 相关子查询。
198
- *
199
- * 语义:
200
- * - 首次出现 session_id → 插入一行,start/end/last_event_time 都取当前事件时间戳
201
- * - 已存在 → event_count += 1,end/last_event_time 取更晚的,first_prompt 只在
202
- * 原值为 NULL 时才被 UserPromptSubmit 的前 200 字填充(保留"首条"语义)
203
- * - 非 UserPromptSubmit 事件或 user_prompt 为空时 first_prompt 传 NULL,不会
204
- * 覆盖已有值
205
- */
206
- upsertSession(event) {
207
- const firstPrompt = event.hook_type === 'UserPromptSubmit' && event.user_prompt
208
- ? event.user_prompt.slice(0, 200)
209
- : null;
210
- const stmt = this.db.prepare(`
211
- INSERT INTO sessions (
212
- session_id, project_path, status, first_prompt,
213
- start_time, end_time, last_event_time, event_count
214
- )
215
- VALUES (?, ?, 'active', ?, ?, ?, ?, 1)
216
- ON CONFLICT(session_id) DO UPDATE SET
217
- end_time = CASE
218
- WHEN excluded.end_time > COALESCE(sessions.end_time, '') THEN excluded.end_time
219
- ELSE sessions.end_time
220
- END,
221
- last_event_time = CASE
222
- WHEN excluded.last_event_time > COALESCE(sessions.last_event_time, '') THEN excluded.last_event_time
223
- ELSE sessions.last_event_time
224
- END,
225
- event_count = COALESCE(sessions.event_count, 0) + 1,
226
- first_prompt = COALESCE(sessions.first_prompt, excluded.first_prompt),
227
- updated_at = datetime('now')
228
- `);
229
- stmt.run(event.session_id, event.project_path, firstPrompt, event.timestamp, event.timestamp, event.timestamp);
230
- }
231
- writeToolEvent(event) {
232
- const stmt = this.db.prepare(`
233
- INSERT INTO v2_tool_events (session_id, route_request_id, tool, args, result, success, error, timestamp)
234
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
235
- `);
236
- const info = stmt.run(event.session_id, event.route_request_id ?? null, event.tool, JSON.stringify(event.args), event.result ? JSON.stringify(event.result) : null, event.success ? 1 : 0, event.error ?? null, event.timestamp);
237
- const id = Number(info.lastInsertRowid);
238
- this.emit('tool-event', {
239
- ...event,
240
- id,
241
- });
242
- return id;
243
- }
244
- writeDecision(decision) {
245
- const stmt = this.db.prepare(`
246
- INSERT INTO v2_decisions (session_id, event_id, rule_id, level, reason, suggestion, user_choice, timestamp)
247
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
248
- `);
249
- const info = stmt.run(decision.session_id, decision.event_id, decision.rule_id ?? null, decision.level, decision.reason ?? null, decision.suggestion ?? null, decision.user_choice ?? null, decision.timestamp);
250
- const id = Number(info.lastInsertRowid);
251
- this.emit('decision', {
252
- id,
253
- ...decision,
254
- });
255
- return id;
256
- }
43
+ this.base = new SQLiteBase(dbPath);
44
+ const db = this.base.getDatabase();
45
+ this.sessions = new SessionOperations(db);
46
+ this.events = new EventOperations(db, this);
47
+ this.tasks = new TaskOperations(db);
48
+ this.injections = new InjectionOperations(db);
49
+ this.routing = new RoutingOperations(db);
50
+ this.skills = new SkillOperations(db);
51
+ this.tokenUsage = new TokenUsageOperations(db);
52
+ this.maintenance = new MaintenanceOperations(db, dbPath);
53
+ }
54
+ // ── Database accessors ─────────────────────────────────────────────────
55
+ getDatabase() { return this.base.getDatabase(); }
56
+ getDbPath() { return this.base.getDbPath(); }
57
+ // ── Event operations ────────────────────────────────────────────────────
58
+ writeEvent(event) { this.events.writeEvent(event); }
257
59
  queryEvents(filter) {
258
- const conditions = [];
259
- const params = [];
260
- if (filter.session_id) {
261
- conditions.push('session_id = ?');
262
- params.push(filter.session_id);
263
- }
264
- if (filter.project_path) {
265
- conditions.push('project_path = ?');
266
- params.push(filter.project_path);
267
- }
268
- if (filter.hook_type) {
269
- conditions.push('hook_type = ?');
270
- params.push(filter.hook_type);
271
- }
272
- const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
273
- const limit = filter.limit ?? 1000;
274
- const sql = `SELECT * FROM events ${where} ORDER BY timestamp DESC LIMIT ${limit}`;
275
- const rows = this.db.prepare(sql).all(...params);
276
- return rows.map((row) => this.rowToEvent(row));
277
- }
278
- countEvents(filter) {
279
- if (filter.distilled !== undefined) {
280
- const sql = 'SELECT COUNT(*) as count FROM events WHERE distilled = ?';
281
- const result = this.db.prepare(sql).get(filter.distilled ? 1 : 0);
282
- return result.count;
283
- }
284
- const result = this.db.prepare('SELECT COUNT(*) as count FROM events').get();
285
- return result.count;
286
- }
287
- getUndistilledEvents(sessionId, projectPath) {
288
- const sql = `
289
- SELECT * FROM events
290
- WHERE session_id = ? AND project_path = ? AND distilled = 0
291
- ORDER BY timestamp ASC
292
- `;
293
- const rows = this.db.prepare(sql).all(sessionId, projectPath);
294
- return rows.map((row) => this.rowToEvent(row));
60
+ return this.events.queryEvents(filter);
295
61
  }
296
- markEventsDistilled(eventIds) {
297
- if (eventIds.length === 0)
298
- return;
299
- const placeholders = eventIds.map(() => '?').join(',');
300
- const sql = `UPDATE events SET distilled = 1 WHERE event_id IN (${placeholders})`;
301
- this.db.prepare(sql).run(...eventIds);
62
+ countEvents(filter) { return this.events.countEvents(filter); }
63
+ searchEvents(filter) {
64
+ return this.events.searchEvents(filter);
302
65
  }
303
- // ── Session Operations ─────────────────────────────────────────────────
66
+ // ── Session operations ─────────────────────────────────────────────────
67
+ upsertSession(event) { this.sessions.upsertSession(event); }
304
68
  querySessions(filter = {}) {
305
- const conditions = [];
306
- const params = [];
307
- if (filter.project_path) {
308
- conditions.push('project_path = ?');
309
- params.push(filter.project_path);
310
- }
311
- const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
312
- const limit = filter.limit ?? 10;
313
- // 直接读 sessions 聚合表 → O(sessions)。writeEvent 的 upsertSession 路径保证
314
- // 每次事件写入都会同步更新此表;旧库在 runMigrations 里由 backfillSessionsIfNeeded
315
- // 一次性回填,确保历史 session 也可见。
316
- const sql = `
317
- SELECT
318
- session_id,
319
- first_prompt,
320
- event_count,
321
- start_time,
322
- COALESCE(end_time, last_event_time, start_time) AS end_time
323
- FROM sessions
324
- ${where}
325
- ORDER BY start_time DESC
326
- LIMIT ${limit}
327
- `;
328
- const rows = this.db.prepare(sql).all(...params);
329
- return rows.map(r => ({
330
- session_id: r.session_id,
331
- first_prompt: r.first_prompt || '',
332
- event_count: r.event_count ?? 0,
333
- start_time: r.start_time,
334
- end_time: r.end_time,
335
- }));
336
- }
337
- // ── Injection Operations ───────────────────────────────────────────────
338
- writeInjection(injection) {
339
- const id = injection.id || randomUUID();
340
- const stmt = this.db.prepare(`
341
- INSERT INTO injections (id, event_id, session_id, timestamp, source_handler, injection_type, content)
342
- VALUES (?, ?, ?, ?, ?, ?, ?)
343
- `);
344
- stmt.run(id, injection.event_id ?? null, injection.session_id, injection.timestamp, injection.source_handler, injection.injection_type, injection.content);
69
+ return this.sessions.querySessions(filter);
345
70
  }
71
+ // ── Injection operations ───────────────────────────────────────────────
72
+ writeInjection(injection) { this.injections.writeInjection(injection); }
346
73
  queryInjections(filter = {}) {
347
- const conditions = [];
348
- const params = [];
349
- if (filter.session_id) {
350
- conditions.push('session_id = ?');
351
- params.push(filter.session_id);
352
- }
353
- if (filter.event_id) {
354
- conditions.push('event_id = ?');
355
- params.push(filter.event_id);
356
- }
357
- if (filter.source_handler) {
358
- conditions.push('source_handler = ?');
359
- params.push(filter.source_handler);
360
- }
361
- const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
362
- const limit = filter.limit ?? 100;
363
- const sql = `SELECT * FROM injections ${where} ORDER BY timestamp DESC LIMIT ${limit}`;
364
- const rows = this.db.prepare(sql).all(...params);
365
- return rows.map(r => ({
366
- id: r.id,
367
- event_id: r.event_id || undefined,
368
- session_id: r.session_id,
369
- timestamp: r.timestamp,
370
- source_handler: r.source_handler,
371
- injection_type: r.injection_type,
372
- content: r.content,
373
- }));
374
- }
375
- queryQualityIssues(filter = {}) {
376
- const conditions = [];
377
- const params = [];
378
- if (filter.session_id) {
379
- conditions.push('session_id = ?');
380
- params.push(filter.session_id);
381
- }
382
- if (filter.resolved !== undefined) {
383
- conditions.push('resolved = ?');
384
- params.push(filter.resolved ? 1 : 0);
385
- }
386
- const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
387
- const limit = filter.limit ?? 100;
388
- const rows = this.db.prepare(`SELECT * FROM quality_issues ${where} ORDER BY created_at DESC LIMIT ${limit}`).all(...params);
389
- return rows.map(r => ({
390
- file_path: r.file_path, category: r.category,
391
- level: r.level, message: r.message,
392
- resolved: !!r.resolved, created_at: r.created_at,
393
- }));
394
- }
395
- queryDecisions(filter = {}) {
396
- const params = [];
397
- let sessionFilter = '';
398
- if (filter.session_id) {
399
- sessionFilter = 'WHERE d.session_id = ?';
400
- params.push(filter.session_id);
401
- }
402
- const limit = filter.limit ?? 100;
403
- const rows = this.db.prepare(`
404
- SELECT d.rule_id, d.level, d.reason, d.suggestion, e.tool, d.timestamp
405
- FROM v2_decisions d LEFT JOIN v2_tool_events e ON d.event_id = e.id
406
- ${sessionFilter} ORDER BY d.timestamp DESC LIMIT ${limit}
407
- `).all(...params);
408
- return rows.map(r => ({
409
- rule_id: r.rule_id || null, level: r.level,
410
- reason: r.reason || null, suggestion: r.suggestion || null,
411
- tool: r.tool || '', timestamp: r.timestamp,
412
- }));
74
+ return this.injections.queryInjections(filter);
413
75
  }
414
- // ── Task Operations ─────────────────────────────────────────────────
76
+ // ── Task operations ─────────────────────────────────────────────────
415
77
  writeTask(task) {
416
- this.db.prepare(`
417
- INSERT INTO tasks (id, session_id, title, start_time) VALUES (?, ?, ?, ?)
418
- `).run(task.id, task.session_id, task.title, task.start_time);
78
+ this.tasks.writeTask(task);
419
79
  }
420
80
  updateTask(taskId, updates) {
421
- const sets = [];
422
- const params = [];
423
- if (updates.end_time !== undefined) {
424
- sets.push('end_time = ?');
425
- params.push(updates.end_time);
426
- }
427
- if (updates.status !== undefined) {
428
- sets.push('status = ?');
429
- params.push(updates.status);
430
- }
431
- if (updates.event_count !== undefined) {
432
- sets.push('event_count = ?');
433
- params.push(updates.event_count);
434
- }
435
- if (updates.title !== undefined) {
436
- sets.push('title = ?');
437
- params.push(updates.title);
438
- }
439
- if (sets.length === 0)
440
- return;
441
- params.push(taskId);
442
- this.db.prepare(`UPDATE tasks SET ${sets.join(', ')} WHERE id = ?`).run(...params);
81
+ this.tasks.updateTask(taskId, updates);
443
82
  }
444
83
  linkEventToTask(taskId, eventId) {
445
- this.db.prepare(`INSERT OR IGNORE INTO task_events (task_id, event_id) VALUES (?, ?)`).run(taskId, eventId);
446
- this.db.prepare(`UPDATE tasks SET event_count = event_count + 1, end_time = (SELECT timestamp FROM events WHERE event_id = ?) WHERE id = ?`).run(eventId, taskId);
84
+ this.tasks.linkEventToTask(taskId, eventId);
447
85
  }
448
86
  queryTasks(filter = {}) {
449
- const conditions = [];
450
- const params = [];
451
- if (filter.session_id) {
452
- conditions.push('session_id = ?');
453
- params.push(filter.session_id);
454
- }
455
- const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
456
- const limit = filter.limit ?? 50;
457
- const rows = this.db.prepare(`SELECT * FROM tasks ${where} ORDER BY start_time DESC LIMIT ${limit}`).all(...params);
458
- return rows.map(r => ({
459
- id: r.id, session_id: r.session_id,
460
- title: r.title, description: r.description || undefined,
461
- start_time: r.start_time, end_time: r.end_time || undefined,
462
- status: r.status || 'active', event_count: r.event_count || 0,
463
- }));
87
+ return this.tasks.queryTasks(filter);
464
88
  }
465
- getTaskEventIds(taskId) {
466
- const rows = this.db.prepare(`SELECT event_id FROM task_events WHERE task_id = ?`).all(taskId);
467
- return rows.map(r => r.event_id);
89
+ queryTasksFiltered(filter = {}) {
90
+ return this.tasks.queryTasksFiltered(filter);
468
91
  }
469
- // ── Routing Events ─────────────────────────────────────────────────────
92
+ queryTaskProjects() {
93
+ return this.tasks.queryTaskProjects();
94
+ }
95
+ getTaskEventIds(taskId) { return this.tasks.getTaskEventIds(taskId); }
96
+ // ── Routing events ─────────────────────────────────────────────────────
470
97
  writeRoutingEvent(record) {
471
- const result = this.db.prepare(`
472
- INSERT INTO routing_events (
473
- session_id, route_request_id, project_path, ts, prompt, intent_json,
474
- routed_to_type, routed_to_name, is_forced, obeyed,
475
- classification_ms, fallback_used, refusal_reason,
476
- first_tool_name, first_tool_ts, completed_ts,
477
- total_execution_ms, completion_reason, downstream_task_chain,
478
- injection_version, experiment_id, experiment_group
479
- ) VALUES (
480
- @session_id, @route_request_id, @project_path, @ts, @prompt, @intent_json,
481
- @routed_to_type, @routed_to_name, @is_forced, @obeyed,
482
- @classification_ms, @fallback_used, @refusal_reason,
483
- @first_tool_name, @first_tool_ts, @completed_ts,
484
- @total_execution_ms, @completion_reason, @downstream_task_chain,
485
- @injection_version, @experiment_id, @experiment_group
486
- )
487
- `).run({
488
- session_id: record.session_id,
489
- route_request_id: record.route_request_id ?? null,
490
- project_path: record.project_path,
491
- ts: record.ts,
492
- prompt: record.prompt,
493
- intent_json: record.intent_json,
494
- routed_to_type: record.routed_to_type ?? null,
495
- routed_to_name: record.routed_to_name ?? null,
496
- is_forced: record.is_forced ?? 0,
497
- obeyed: record.obeyed ?? null,
498
- classification_ms: record.classification_ms ?? null,
499
- fallback_used: record.fallback_used ?? 0,
500
- refusal_reason: record.refusal_reason ?? null,
501
- first_tool_name: record.first_tool_name ?? null,
502
- first_tool_ts: record.first_tool_ts ?? null,
503
- completed_ts: record.completed_ts ?? null,
504
- total_execution_ms: record.total_execution_ms ?? null,
505
- completion_reason: record.completion_reason ?? null,
506
- downstream_task_chain: record.downstream_task_chain ?? null,
507
- injection_version: record.injection_version ?? null,
508
- experiment_id: record.experiment_id ?? null,
509
- experiment_group: record.experiment_group ?? null,
510
- });
511
- return Number(result.lastInsertRowid);
98
+ return this.routing.writeRoutingEvent(record);
512
99
  }
513
100
  updateRoutingEvent(id, patch) {
514
- const fields = Object.keys(patch).filter((k) => k !== 'id');
515
- if (fields.length === 0)
516
- return;
517
- const setClause = fields.map((f) => `${f} = @${f}`).join(', ');
518
- this.db.prepare(`UPDATE routing_events SET ${setClause} WHERE id = @id`).run({
519
- ...patch,
520
- id,
521
- });
101
+ this.routing.updateRoutingEvent(id, patch);
522
102
  }
523
103
  queryRoutingEvents(filter = {}) {
524
- const conds = [];
525
- const params = {};
526
- if (filter.session_id) {
527
- conds.push('session_id = @session_id');
528
- params.session_id = filter.session_id;
529
- }
530
- if (filter.project_path) {
531
- conds.push('project_path = @project_path');
532
- params.project_path = filter.project_path;
533
- }
534
- if (filter.since_ts !== undefined) {
535
- conds.push('ts >= @since_ts');
536
- params.since_ts = filter.since_ts;
537
- }
538
- if (filter.routed_to_name) {
539
- conds.push('routed_to_name = @routed_to_name');
540
- params.routed_to_name = filter.routed_to_name;
541
- }
542
- if (filter.obeyed !== undefined) {
543
- if (filter.obeyed === null)
544
- conds.push('obeyed IS NULL');
545
- else {
546
- conds.push('obeyed = @obeyed');
547
- params.obeyed = filter.obeyed;
548
- }
549
- }
550
- const where = conds.length > 0 ? `WHERE ${conds.join(' AND ')}` : '';
551
- const limit = filter.limit ?? 100;
552
- const rows = this.db.prepare(`SELECT * FROM routing_events ${where} ORDER BY ts DESC LIMIT ${limit}`).all(params);
553
- return rows;
104
+ return this.routing.queryRoutingEvents(filter);
554
105
  }
555
- /** Pending events with NULL obeyed within the last N seconds; used by daemon restart recovery. */
556
106
  findPendingRoutingEvents(ageMs) {
557
- const cutoff = Date.now() - ageMs;
558
- return this.db.prepare(`SELECT * FROM routing_events WHERE obeyed IS NULL AND ts >= ? ORDER BY ts DESC`).all(cutoff);
107
+ return this.routing.findPendingRoutingEvents(ageMs);
559
108
  }
560
- // ── Experiment Assignments (Phase 5) ───────────────────────────────────
109
+ getRecentRoutingEvent(sessionId) {
110
+ return this.routing.getRecentRoutingEvent(sessionId);
111
+ }
112
+ // ── Experiment assignments ─────────────────────────────────────────────
561
113
  getExperimentAssignment(sessionId, experimentId) {
562
- const row = this.db.prepare(`SELECT group_id FROM experiment_assignments WHERE session_id = ? AND experiment_id = ?`).get(sessionId, experimentId);
563
- return row ? row.group_id : null;
114
+ return this.routing.getExperimentAssignment(sessionId, experimentId);
564
115
  }
565
116
  setExperimentAssignment(sessionId, experimentId, groupId) {
566
- this.db.prepare(`INSERT OR IGNORE INTO experiment_assignments (session_id, experiment_id, group_id)
567
- VALUES (?, ?, ?)`).run(sessionId, experimentId, groupId);
117
+ this.routing.setExperimentAssignment(sessionId, experimentId, groupId);
568
118
  }
569
119
  queryExperimentStats(experimentId) {
570
- const rows = this.db.prepare(`
571
- SELECT
572
- experiment_group AS group_id,
573
- COUNT(*) AS total,
574
- SUM(CASE WHEN obeyed = 1 THEN 1 ELSE 0 END) AS obeyed,
575
- SUM(CASE WHEN obeyed = 0 THEN 1 ELSE 0 END) AS refused,
576
- SUM(CASE WHEN obeyed IS NULL THEN 1 ELSE 0 END) AS unknown,
577
- AVG(classification_ms) AS avg_classification_ms
578
- FROM routing_events
579
- WHERE experiment_id = ? AND experiment_group IS NOT NULL
580
- GROUP BY experiment_group
581
- ORDER BY experiment_group ASC
582
- `).all(experimentId);
583
- return rows;
584
- }
585
- // ── Routing Rule States (Phase 5 Feature 2) ────────────────────────────
586
- getRuleState(taskType, agent) {
587
- const row = this.db.prepare(`SELECT * FROM routing_rule_states WHERE task_type = ? AND agent = ?`).get(taskType, agent);
588
- return row ?? null;
589
- }
590
- listRuleStates(filter = {}) {
591
- const where = filter.disabledOnly ? 'WHERE disabled = 1' : '';
592
- return this.db
593
- .prepare(`SELECT * FROM routing_rule_states ${where} ORDER BY task_type, agent`)
594
- .all();
595
- }
596
- setRuleState(params) {
597
- const now = new Date().toISOString();
598
- this.db.prepare(`
599
- INSERT INTO routing_rule_states (task_type, agent, disabled, disabled_at, disabled_reason, auto_disabled, updated_at)
600
- VALUES (?, ?, ?, ?, ?, ?, ?)
601
- ON CONFLICT(task_type, agent) DO UPDATE SET
602
- disabled = excluded.disabled,
603
- disabled_at = CASE WHEN excluded.disabled = 1 THEN excluded.disabled_at ELSE NULL END,
604
- disabled_reason = CASE WHEN excluded.disabled = 1 THEN excluded.disabled_reason ELSE NULL END,
605
- auto_disabled = excluded.auto_disabled,
606
- updated_at = excluded.updated_at
607
- `).run(params.taskType, params.agent, params.disabled ? 1 : 0, params.disabled ? now : null, params.disabled ? (params.reason ?? null) : null, params.autoDisabled ? 1 : 0, now);
608
- }
609
- /**
610
- * Return a Set of "<taskType>__<agent>" strings that are currently disabled.
611
- * Hot path used by the router on every decide() call.
612
- */
613
- getDisabledRuleKeys() {
614
- const rows = this.db.prepare(`SELECT task_type, agent FROM routing_rule_states WHERE disabled = 1`).all();
615
- return new Set(rows.map(r => `${r.task_type}__${r.agent}`));
616
- }
617
- // ── Maintenance ────────────────────────────────────────────────────────
618
- runMaintenance(maxSizeMb) {
619
- const sizeMb = this.getDbSizeMb();
620
- if (sizeMb < maxSizeMb) {
621
- logger.debug(`[Storage] DB size ${sizeMb.toFixed(1)}MB < ${maxSizeMb}MB, skipping maintenance`);
622
- return;
623
- }
624
- logger.info(`[Storage] Running maintenance (size: ${sizeMb.toFixed(1)}MB)`);
625
- // Delete distilled events older than 7 days
626
- const deleted = this.db.prepare(`
627
- DELETE FROM events
628
- WHERE distilled = 1 AND created_at < datetime('now', '-7 days')
629
- `).run();
630
- logger.info(`[Storage] Deleted ${deleted.changes} old distilled events`);
631
- this.vacuum();
632
- }
633
- vacuum() {
634
- this.db.exec('VACUUM');
120
+ return this.routing.queryExperimentStats(experimentId);
635
121
  }
636
- close() {
637
- try {
638
- this.db.close();
639
- }
640
- catch (err) {
641
- logger.warn(`Failed to close database: ${err}`);
642
- }
643
- }
644
- // ── Private Helpers ────────────────────────────────────────────────────
645
- getDbSizeMb() {
646
- if (!existsSync(this.dbPath))
647
- return 0;
648
- return statSync(this.dbPath).size / (1024 * 1024);
649
- }
650
- rowToEvent(row) {
651
- return {
652
- event_id: row.event_id,
653
- session_id: row.session_id,
654
- project_path: row.project_path,
655
- timestamp: row.timestamp,
656
- hook_type: row.hook_type,
657
- tool_name: row.tool_name || undefined,
658
- tool_input: row.tool_input ? JSON.parse(row.tool_input) : undefined,
659
- tool_output: row.tool_output ? JSON.parse(row.tool_output) : undefined,
660
- user_prompt: row.user_prompt || undefined,
661
- ai_response: row.ai_response || undefined,
662
- };
663
- }
664
- // ── Token Usage ────────────────────────────────────────────────────────
122
+ // ── Token usage ────────────────────────────────────────────────────────
665
123
  recordTokenUsage(params) {
666
- const total_tokens = params.input_tokens + params.output_tokens;
667
- try {
668
- this.db.prepare(`
669
- INSERT INTO token_usage (session_id, timestamp,
670
- input_tokens, output_tokens, total_tokens, model, tool_name)
671
- VALUES (?, ?, ?, ?, ?, ?, ?)
672
- `).run(params.session_id, Date.now(), params.input_tokens, params.output_tokens, total_tokens, params.model ?? null, params.tool_name ?? null);
673
- }
674
- catch (err) {
675
- logger.debug(`[Storage] Failed to record token usage: ${err}`);
676
- }
124
+ this.tokenUsage.recordTokenUsage(params);
677
125
  }
678
126
  getTokenUsageBySession(session_id) {
679
- const result = this.db.prepare(`
680
- SELECT
681
- COALESCE(SUM(input_tokens), 0) as input_tokens,
682
- COALESCE(SUM(output_tokens), 0) as output_tokens,
683
- COALESCE(SUM(total_tokens), 0) as total_tokens
684
- FROM token_usage WHERE session_id = ?
685
- `).get(session_id);
686
- return result;
127
+ return this.tokenUsage.getTokenUsageBySession(session_id);
687
128
  }
688
129
  listTokenUsage(filter = {}) {
689
- const conditions = [];
690
- const params = [];
691
- if (filter.session_id) {
692
- conditions.push('session_id = ?');
693
- params.push(filter.session_id);
694
- }
695
- const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
696
- const limit = filter.limit ?? 100;
697
- const sql = `SELECT * FROM token_usage ${where} ORDER BY timestamp DESC LIMIT ${limit}`;
698
- const rows = this.db.prepare(sql).all(...params);
699
- return rows.map(r => ({
700
- id: r.id,
701
- session_id: r.session_id,
702
- timestamp: r.timestamp,
703
- input_tokens: r.input_tokens,
704
- output_tokens: r.output_tokens,
705
- total_tokens: r.total_tokens,
706
- model: r.model || null,
707
- tool_name: r.tool_name || null,
708
- }));
130
+ return this.tokenUsage.listTokenUsage(filter);
709
131
  }
710
- // ── Skill Invocations ──────────────────────────────────────────────────
711
- // 记录 Agent 动态调用 Skill 的每一次事件。配合 route_request_id 可以串联
712
- // "外层路由 → Agent → 内层 Skill 调用"的证据链。
132
+ // ── Skill invocations ──────────────────────────────────────────────────
713
133
  writeSkillInvocation(row) {
714
- const sql = `INSERT INTO skill_invocations
715
- (id, route_request_id, session_id, agent_id, skill_id, invocation_type,
716
- reason, workflow, phase, feature_slug, artifact_path,
717
- depth, success, error, timestamp)
718
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
719
- this.db.prepare(sql).run(row.id, row.route_request_id, row.session_id, row.agent_id, row.skill_id, row.invocation_type, row.reason, row.workflow, row.phase, row.feature_slug, row.artifact_path, row.depth, row.success, row.error, row.timestamp);
134
+ this.skills.writeSkillInvocation(row);
720
135
  }
721
136
  querySkillInvocations(filter = {}) {
722
- const conditions = [];
723
- const params = [];
724
- if (filter.route_request_id) {
725
- conditions.push('route_request_id = ?');
726
- params.push(filter.route_request_id);
727
- }
728
- if (filter.session_id) {
729
- conditions.push('session_id = ?');
730
- params.push(filter.session_id);
731
- }
732
- if (filter.skill_id) {
733
- conditions.push('skill_id = ?');
734
- params.push(filter.skill_id);
735
- }
736
- const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
737
- const limit = filter.limit ?? 100;
738
- const sql = `SELECT * FROM skill_invocations ${where} ORDER BY timestamp DESC LIMIT ${limit}`;
739
- return this.db.prepare(sql).all(...params);
137
+ return this.skills.querySkillInvocations(filter);
740
138
  }
741
- /**
742
- * 按 route_request_id 聚合工作流进度。
743
- *
744
- * 用途:Web UI 展示「某次路由 / 某个 session 走完了哪些 phase」。仅聚合
745
- * `workflow IS NOT NULL` 的调用(工作流型 reason),普通调用不会被纳入。
746
- *
747
- * 返回字段:
748
- * - `phases_completed` 已按 timestamp 升序排序,并去重;同 phase 多次调用只算一次。
749
- * - `feature_slug` 取该 route 内首个非空的 slug;不同 slug 混用时以最早出现的为准。
750
- * - `total_invocations` / `success_count` 仅统计有 workflow 的行。
751
- */
752
139
  queryWorkflowProgress(filter = {}) {
753
- const conditions = ['workflow IS NOT NULL', 'route_request_id IS NOT NULL'];
754
- const params = [];
755
- if (filter.session_id) {
756
- conditions.push('session_id = ?');
757
- params.push(filter.session_id);
140
+ return this.skills.queryWorkflowProgress(filter);
141
+ }
142
+ // ── Maintenance ────────────────────────────────────────────────────────
143
+ cleanOldEvents(daysToKeep = 30) { return this.maintenance.cleanOldEvents(daysToKeep); }
144
+ runMaintenance(maxSizeMb) { this.maintenance.runMaintenance(maxSizeMb); }
145
+ vacuum() { this.maintenance.vacuum(); }
146
+ close() {
147
+ try {
148
+ this.base.getDatabase().close();
758
149
  }
759
- if (filter.workflow) {
760
- conditions.push('workflow = ?');
761
- params.push(filter.workflow);
150
+ catch (err) {
151
+ logger.warn(`Failed to close database: ${err}`);
762
152
  }
763
- const where = `WHERE ${conditions.join(' AND ')}`;
764
- const limit = filter.limit ?? 100;
765
- // 用 GROUP_CONCAT 收集 phase 序列(保留时间顺序),再在 JS 层去重。
766
- // SQLite 的 GROUP_CONCAT 不保证子查询排序稳定,因此用一个 ORDER BY timestamp
767
- // 的子查询固定顺序。
768
- const sql = `
769
- SELECT
770
- route_request_id,
771
- workflow,
772
- GROUP_CONCAT(phase, '||') AS phases_raw,
773
- MIN(feature_slug) AS feature_slug,
774
- COUNT(*) AS total_invocations,
775
- SUM(success) AS success_count,
776
- MIN(timestamp) AS first_at,
777
- MAX(timestamp) AS last_at
778
- FROM (
779
- SELECT * FROM skill_invocations
780
- ${where}
781
- ORDER BY timestamp ASC
782
- )
783
- GROUP BY route_request_id, workflow
784
- ORDER BY last_at DESC
785
- LIMIT ${limit}
786
- `;
787
- const rows = this.db.prepare(sql).all(...params);
788
- return rows.map(r => {
789
- const phases = r.phases_raw ? r.phases_raw.split('||').filter(Boolean) : [];
790
- // 去重,保留首次出现的顺序
791
- const seen = new Set();
792
- const phases_completed = [];
793
- for (const p of phases) {
794
- if (!seen.has(p)) {
795
- seen.add(p);
796
- phases_completed.push(p);
797
- }
798
- }
799
- return {
800
- route_request_id: r.route_request_id,
801
- workflow: r.workflow,
802
- phases_completed,
803
- feature_slug: r.feature_slug,
804
- total_invocations: r.total_invocations,
805
- success_count: r.success_count ?? 0,
806
- first_at: r.first_at,
807
- last_at: r.last_at,
808
- };
809
- });
810
153
  }
811
154
  }
812
155
  //# sourceMappingURL=sqlite.js.map