@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
@@ -0,0 +1,215 @@
1
+ /**
2
+ * StopHandler — handles Stop hook
3
+ *
4
+ * Responsibilities:
5
+ * 1. Mark current task complete
6
+ * 2. Save resume info
7
+ * 3. Export session history
8
+ * 4. Clear skill invocation guard
9
+ */
10
+
11
+ import type { StopEvent, HookResult } from '../../core/types.js';
12
+ import type { HistoryExporter } from './history-exporter.js';
13
+ import type { ResumeManager } from '../../claudemd/resume-manager.js';
14
+ import type { TaskSegmenter } from '../services/task-segmenter.js';
15
+ import type { SQLiteStorage } from '../../core/storage/sqlite.js';
16
+ import type { InvocationGuard } from '../../skills/invocation-guard.js';
17
+ import type { UserPromptHandler } from './user-prompt.js';
18
+ import { logger } from '../../core/utils/logger.js';
19
+ import { execFileSync } from 'node:child_process';
20
+ import { formatError, truncateString } from '../../core/utils/format.js';
21
+ import { truncateSessionId } from '../../core/utils/session.js';
22
+
23
+ export class StopHandler {
24
+ constructor(
25
+ private exporter: HistoryExporter,
26
+ private resume: ResumeManager | null = null,
27
+ private taskSegmenter: TaskSegmenter | null = null,
28
+ private storage: SQLiteStorage | null = null,
29
+ private invocationGuard: InvocationGuard | null = null,
30
+ private userPromptHandler: UserPromptHandler | null = null,
31
+ ) {}
32
+
33
+ async handle(event: StopEvent): Promise<HookResult> {
34
+ try {
35
+ // 1. Mark current task complete
36
+ if (this.taskSegmenter) {
37
+ try {
38
+ this.taskSegmenter.completeCurrentTask(event.session_id, event.timestamp);
39
+ } catch (err) {
40
+ logger.debug(`[Stop] task completion failed: ${formatError(err)}`);
41
+ }
42
+ }
43
+
44
+ // 2. Save resume info with behavior summary
45
+ if (this.resume) {
46
+ let resumeContent = this.resume.generate(event.session_id, event.project_path);
47
+ if (resumeContent) {
48
+ // Append behavior summary before saving
49
+ const behaviorSummary = this.generateBehaviorSummary(event.session_id);
50
+ if (behaviorSummary) {
51
+ resumeContent = this.appendBehaviorSummary(resumeContent, behaviorSummary);
52
+ }
53
+ this.resume.save(event.project_path, resumeContent);
54
+ logger.info(`[Stop] Resume saved for ${event.project_path}`);
55
+ }
56
+ }
57
+
58
+ // 3. Export history
59
+ logger.info(`[Stop] Exporting history for session ${event.session_id}`);
60
+ await this.exporter.export(event);
61
+
62
+ // 4. Clear skill invocation guard for this session
63
+ if (this.invocationGuard) {
64
+ try {
65
+ this.invocationGuard.clear(event.session_id);
66
+ logger.debug(`[Stop] InvocationGuard cleared for session ${truncateSessionId(event.session_id)}`);
67
+ } catch (err) {
68
+ logger.debug(`[Stop] InvocationGuard clear failed: ${formatError(err)}`);
69
+ }
70
+ }
71
+
72
+ // 5. Clear UserPromptHandler injection tracking for this session
73
+ if (this.userPromptHandler) {
74
+ try {
75
+ const sessionKey = `${event.session_id}:${event.project_path}`;
76
+ this.userPromptHandler.clearSession(sessionKey);
77
+ logger.debug(`[Stop] UserPromptHandler session cleared for ${truncateSessionId(event.session_id)}`);
78
+ } catch (err) {
79
+ logger.debug(`[Stop] UserPromptHandler clear failed: ${formatError(err)}`);
80
+ }
81
+ }
82
+
83
+ // 6. Write session_id to git note on HEAD commit
84
+ this.writeGitNote(event);
85
+
86
+ return { allow: true };
87
+ } catch (err) {
88
+ logger.warn(`[Stop] Handler failed: ${formatError(err)}`);
89
+ return { allow: true };
90
+ }
91
+ }
92
+
93
+ // ── Private: Git Note ──────────────────────────────────────────────────
94
+
95
+ /**
96
+ * Write session_id into a git note on the current HEAD commit.
97
+ * Uses `git notes append` so multiple sessions can be associated with one commit.
98
+ * Silently ignores failures (no git repo, no commits, etc.).
99
+ */
100
+ private writeGitNote(event: StopEvent): void {
101
+ const projectPath = event.project_path;
102
+ if (!projectPath) return;
103
+
104
+ try {
105
+ // Check if inside a git work tree
106
+ execFileSync('git', ['rev-parse', '--is-inside-work-tree'], {
107
+ cwd: projectPath,
108
+ stdio: 'pipe',
109
+ timeout: 5000,
110
+ });
111
+
112
+ // Get HEAD commit hash
113
+ const head = execFileSync('git', ['rev-parse', 'HEAD'], {
114
+ cwd: projectPath,
115
+ stdio: 'pipe',
116
+ timeout: 5000,
117
+ }).toString().trim();
118
+
119
+ if (!head) return;
120
+
121
+ // Append session_id to git note on HEAD
122
+ execFileSync('git', ['notes', 'append', '-m', `forge-session: ${event.session_id}`, head], {
123
+ cwd: projectPath,
124
+ stdio: 'pipe',
125
+ timeout: 5000,
126
+ });
127
+
128
+ logger.debug(`[Stop] Git note appended: forge-session: ${truncateSessionId(event.session_id)} on ${truncateString(head, 8)}`);
129
+ } catch (err) {
130
+ logger.debug(`[Stop] Git note write skipped: ${formatError(err)}`);
131
+ }
132
+ }
133
+
134
+ // ── Private: Behavior Summary ──────────────────────────────────────────
135
+
136
+ /**
137
+ * Generate a brief behavior summary for the session by querying event stats.
138
+ */
139
+ private generateBehaviorSummary(sessionId: string): string | null {
140
+ if (!this.storage) return null;
141
+
142
+ try {
143
+ const db = this.storage.getDatabase();
144
+
145
+ // 1. Tool usage stats
146
+ const toolStats = db.prepare(`
147
+ SELECT tool_name, COUNT(*) as count FROM events
148
+ WHERE session_id = ? AND tool_name IS NOT NULL
149
+ GROUP BY tool_name ORDER BY count DESC
150
+ `).all(sessionId) as Array<{ tool_name: string; count: number }>;
151
+
152
+ const totalToolCalls = toolStats.reduce((sum, row) => sum + row.count, 0);
153
+
154
+ // 2. Agent/Task delegation stats
155
+ const agentStats = db.prepare(`
156
+ SELECT json_extract(tool_input, '$.subagent_type') as agent_type, COUNT(*) as count
157
+ FROM events
158
+ WHERE session_id = ? AND tool_name IN ('Agent', 'Task') AND tool_input IS NOT NULL
159
+ GROUP BY agent_type
160
+ `).all(sessionId) as Array<{ agent_type: string | null; count: number }>;
161
+
162
+ const totalAgentCalls = agentStats.reduce((sum, row) => sum + row.count, 0);
163
+ const agentNames = agentStats
164
+ .filter(row => row.agent_type)
165
+ .map(row => row.agent_type as string);
166
+
167
+ // 3. Skill invocation count
168
+ const skillRow = db.prepare(`
169
+ SELECT COUNT(*) as count FROM skill_invocations WHERE session_id = ?
170
+ `).get(sessionId) as { count: number } | undefined;
171
+
172
+ const skillCount = skillRow?.count ?? 0;
173
+
174
+ // Build summary
175
+ if (totalToolCalls === 0) return null;
176
+
177
+ const parts: string[] = [];
178
+ parts.push(`工具调用 ${totalToolCalls} 次`);
179
+
180
+ if (totalAgentCalls > 0) {
181
+ const agentDetail = agentNames.length > 0
182
+ ? ` (${agentNames.slice(0, 3).join(', ')})`
183
+ : '';
184
+ parts.push(`Agent 委托 ${totalAgentCalls} 次${agentDetail}`);
185
+ } else {
186
+ parts.push('Agent 委托 0 次');
187
+ }
188
+
189
+ parts.push(`Skill 调用 ${skillCount} 次`);
190
+
191
+ return `**会话行为**: ${parts.join(' | ')}`;
192
+ } catch (err) {
193
+ logger.debug(`[Stop] Behavior summary generation failed: ${formatError(err)}`);
194
+ return null;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Append behavior summary to resume content, inserting before the timestamp line.
200
+ */
201
+ private appendBehaviorSummary(resumeContent: string, summary: string): string {
202
+ // Insert before the final "_生成时间:" line
203
+ const timestampPattern = /\n_生成时间:/;
204
+ const match = resumeContent.match(timestampPattern);
205
+ if (match && match.index !== undefined) {
206
+ return (
207
+ resumeContent.slice(0, match.index) +
208
+ '\n' + summary + '\n' +
209
+ resumeContent.slice(match.index)
210
+ );
211
+ }
212
+ // Fallback: append at end
213
+ return resumeContent + '\n' + summary;
214
+ }
215
+ }
@@ -0,0 +1,188 @@
1
+ /**
2
+ * UserPromptHandler — handles UserPromptSubmit hook
3
+ *
4
+ * Pipeline:
5
+ * 1. Inject one-shot context (resume, convention — first prompt of session)
6
+ * 2. Skill fallback (inject skill guidance if matched)
7
+ */
8
+
9
+ import type { UserPromptSubmitEvent, HookResult } from '../../core/types.js';
10
+ import type { ResumeManager } from '../../claudemd/resume-manager.js';
11
+ import type { ConventionExtractor } from '../../claudemd/convention-extractor.js';
12
+ import type { SQLiteStorage } from '../../core/storage/sqlite.js';
13
+ import type { SkillRegistry } from '../../skills/registry.js';
14
+ import { logger } from '../../core/utils/logger.js';
15
+ import { randomUUID } from 'node:crypto';
16
+ import { truncateString } from '../../core/utils/format.js';
17
+
18
+ export class UserPromptHandler {
19
+ private resumeInjected = new Map<string, number>();
20
+ private conventionInjected = new Map<string, number>();
21
+ private static readonly MAX_INJECTION_KEYS = 1000;
22
+
23
+ constructor(
24
+ private resume: ResumeManager | null = null,
25
+ private conventionExtractor: ConventionExtractor | null = null,
26
+ private storage: SQLiteStorage | null = null,
27
+ private skillRegistry: SkillRegistry | null = null,
28
+ ) {}
29
+
30
+ async handle(event: UserPromptSubmitEvent): Promise<HookResult> {
31
+ // UserPromptSubmitEvent.user_prompt is guaranteed by isUserPromptSubmit guard.
32
+ const prompt = event.user_prompt;
33
+ if (!prompt) {
34
+ return { allow: true };
35
+ }
36
+
37
+ try {
38
+ const sessionKey = `${event.session_id}:${event.project_path}`;
39
+ const contextParts: string[] = [];
40
+ const systemParts: string[] = [];
41
+
42
+ // 1. Resume (once per session)
43
+ if (this.resume && !this.hasInjected(this.resumeInjected, sessionKey)) {
44
+ this.markInjected(this.resumeInjected, sessionKey);
45
+ const resumeContent = this.resume.load(event.project_path);
46
+ if (resumeContent) {
47
+ contextParts.push(
48
+ `━━━ Forge Context (Read First) ━━━\n${resumeContent}\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
49
+ );
50
+ logger.info('[UserPrompt] Injected resume context');
51
+ this.resume.clear(event.project_path);
52
+ }
53
+ }
54
+
55
+ // 2. Convention (once per session)
56
+ if (this.conventionExtractor && !this.hasInjected(this.conventionInjected, sessionKey)) {
57
+ this.markInjected(this.conventionInjected, sessionKey);
58
+ const convention = this.conventionExtractor.extract(event.project_path);
59
+ if (convention) {
60
+ contextParts.push(
61
+ `━━━ Project Guidance (Read First) ━━━\n${convention}\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
62
+ );
63
+ logger.info('[UserPrompt] Injected project conventions');
64
+ }
65
+ }
66
+
67
+ // 3. Skill fallback: try skill matching
68
+ if (this.skillRegistry) {
69
+ try {
70
+ const skillMatchResult = await this.skillRegistry.matchWithConfidence(prompt, []);
71
+ if (skillMatchResult) {
72
+ const { skill, source } = skillMatchResult;
73
+ systemParts.push(formatSkillDirective(skill.name, skill.content));
74
+ logger.info(`[UserPrompt] Skill matched: ${skill.id} (${source})`);
75
+
76
+ // Record skill invocation to database
77
+ if (this.storage) {
78
+ try {
79
+ this.storage.writeSkillInvocation({
80
+ id: randomUUID(),
81
+ route_request_id: null,
82
+ session_id: event.session_id,
83
+ agent_id: null,
84
+ skill_id: skill.id,
85
+ invocation_type: 'dynamic',
86
+ reason: `Auto-matched by ${source} matching`,
87
+ workflow: null,
88
+ phase: null,
89
+ feature_slug: null,
90
+ artifact_path: null,
91
+ depth: 0,
92
+ success: 1,
93
+ error: null,
94
+ timestamp: Date.now(),
95
+ });
96
+ logger.debug(`[UserPrompt] Recorded skill invocation: ${skill.id}`);
97
+ } catch (err) {
98
+ logger.warn(`[UserPrompt] Failed to record skill invocation: ${err}`);
99
+ }
100
+ }
101
+ } else {
102
+ logger.debug(`[UserPrompt] No skill matched for prompt: "${truncateString(prompt, 80)}"`);
103
+ }
104
+ } catch (err) {
105
+ logger.warn(`[UserPrompt] Skill matching failed: ${err}`);
106
+ }
107
+ }
108
+
109
+ const result: HookResult = { allow: true };
110
+ if (contextParts.length > 0) result.additionalContext = contextParts.join('\n\n');
111
+ if (systemParts.length > 0) result.systemMessage = systemParts.join('\n\n');
112
+
113
+ // Write routing_event for observation (Agent spawn tracking)
114
+ if (this.storage) {
115
+ try {
116
+ this.storage.writeRoutingEvent({
117
+ session_id: event.session_id,
118
+ project_path: event.project_path,
119
+ ts: Date.now(),
120
+ prompt: prompt.substring(0, 500),
121
+ intent_json: JSON.stringify({ type: 'user_prompt' }),
122
+ routed_to_type: null,
123
+ routed_to_name: null,
124
+ is_forced: 0,
125
+ obeyed: null,
126
+ });
127
+ } catch (err) {
128
+ logger.debug(`[UserPrompt] Failed to write routing_event: ${err}`);
129
+ }
130
+ }
131
+
132
+ return result;
133
+ } catch (err) {
134
+ logger.warn(`[UserPrompt] Handler failed: ${err}`);
135
+ return { allow: true };
136
+ }
137
+ }
138
+ // ── Private: Injection tracking helpers ────────────────────────────────
139
+
140
+ /** Check if a sessionKey has been injected in the given map. */
141
+ private hasInjected(map: Map<string, number>, key: string): boolean {
142
+ return map.has(key);
143
+ }
144
+
145
+ /**
146
+ * Mark a sessionKey as injected, recording the current timestamp.
147
+ * If map size reaches MAX_INJECTION_KEYS, evict the oldest entry (LRU cap).
148
+ */
149
+ private markInjected(map: Map<string, number>, key: string): void {
150
+ if (map.size >= UserPromptHandler.MAX_INJECTION_KEYS) {
151
+ // Evict the entry with the smallest timestamp (oldest)
152
+ let oldestKey: string | undefined;
153
+ let oldestTs = Infinity;
154
+ for (const [k, ts] of map) {
155
+ if (ts < oldestTs) {
156
+ oldestTs = ts;
157
+ oldestKey = k;
158
+ }
159
+ }
160
+ if (oldestKey !== undefined) {
161
+ map.delete(oldestKey);
162
+ }
163
+ }
164
+ map.set(key, Date.now());
165
+ }
166
+
167
+ // ── Public: Session cleanup ──────────────────────────────────────────────
168
+
169
+ /**
170
+ * Remove injection tracking entries for a given sessionKey.
171
+ * Called by StopHandler to clean up after a session ends.
172
+ */
173
+ public clearSession(sessionKey: string): void {
174
+ this.resumeInjected.delete(sessionKey);
175
+ this.conventionInjected.delete(sessionKey);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Format skill injection directive.
181
+ */
182
+ function formatSkillDirective(skillName: string, skillContent: string): string {
183
+ return [
184
+ `[SKILL: ${skillName}] [AUTO_MATCHED]`,
185
+ '',
186
+ skillContent,
187
+ ].join('\n');
188
+ }
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Daemon entry point — starts the Forge daemon process
3
+ *
4
+ * Responsibilities:
5
+ * 1. Load config and initialize logging
6
+ * 2. Manage lifecycle (PID, socket, auth token)
7
+ * 3. Initialize storage, AI provider, and core services
8
+ * 4. Create event handlers and start socket server
9
+ * 5. Handle graceful shutdown
10
+ */
11
+
12
+ import { SocketServer } from './server.js';
13
+ import {
14
+ writePidFile,
15
+ removePidFile,
16
+ cleanSocket,
17
+ getSocketPath,
18
+ writeAuthToken,
19
+ syncMcpToken,
20
+ removeAuthToken,
21
+ } from './lifecycle.js';
22
+ import { routeEvent, type Handlers } from './router.js';
23
+ import { logger, setLogLevel, LogLevel } from '../core/utils/logger.js';
24
+ import { ConfigManager } from '../core/config.js';
25
+ import { SQLiteStorage } from '../core/storage/sqlite.js';
26
+ import { expandPath } from '../core/utils/path.js';
27
+ import { ClaudeProvider } from '../core/ai/provider.js';
28
+ import { TaskSegmenter } from './services/task-segmenter.js';
29
+ import { SkillRegistry } from '../skills/registry.js';
30
+ import { InvocationGuard } from '../skills/invocation-guard.js';
31
+ import { HistoryExporter } from './handlers/history-exporter.js';
32
+ import { ResumeManager } from '../claudemd/resume-manager.js';
33
+ import { ConventionExtractor } from '../claudemd/convention-extractor.js';
34
+ import { UserPromptHandler } from './handlers/user-prompt.js';
35
+ import { PostToolUseHandler } from './handlers/post-tool-use.js';
36
+ import { StopHandler } from './handlers/stop.js';
37
+ import { replayQueue } from '../core/queue/index.js';
38
+ import type { ForgeEvent } from '../core/types.js';
39
+ import type { HookResponse } from './server.js';
40
+
41
+ export interface DaemonOptions {
42
+ /** Whether to enable the web server (default: use config value) */
43
+ web?: boolean;
44
+ }
45
+
46
+ export async function startDaemon(foreground: boolean = false, options: DaemonOptions = {}): Promise<void> {
47
+ // ── 0. Global Exception Handlers ───────────────────────────────────────────
48
+ process.on('uncaughtException', (err) => {
49
+ logger.error(`[Daemon] Uncaught exception: ${err.message}`);
50
+ logger.error(err.stack || '');
51
+ // Don't exit — let daemon continue running
52
+ });
53
+
54
+ process.on('unhandledRejection', (reason, promise) => {
55
+ logger.error(`[Daemon] Unhandled rejection at ${promise}: ${reason}`);
56
+ });
57
+
58
+ // ── 1. Config & Logging ────────────────────────────────────────────────────
59
+ const config = new ConfigManager().get();
60
+
61
+ const envLevel = (process.env.LOG_LEVEL ?? '').toLowerCase();
62
+ const levelMap: Record<string, LogLevel> = {
63
+ debug: LogLevel.DEBUG, info: LogLevel.INFO, warn: LogLevel.WARN, error: LogLevel.ERROR,
64
+ };
65
+ setLogLevel(levelMap[envLevel] ?? LogLevel.INFO);
66
+ logger.info('Claude Forge daemon starting...');
67
+
68
+ // ── 2. Lifecycle (PID, socket, auth token) ─────────────────────────────────
69
+ cleanSocket();
70
+ writePidFile();
71
+ const authToken = writeAuthToken();
72
+ logger.info('[Security] Auth token generated');
73
+ syncMcpToken(authToken, config.web?.port ?? 3721);
74
+
75
+ // ── 3. Storage ─────────────────────────────────────────────────────────────
76
+ const dbPath = expandPath(config.storage.path);
77
+ const storage = new SQLiteStorage(dbPath);
78
+ logger.info(`Storage initialized: ${dbPath}`);
79
+
80
+ // ── 4. AI Provider ─────────────────────────────────────────────────────────
81
+ const apiKey = config.ai.api_key || process.env.ANTHROPIC_API_KEY || '';
82
+ if (!apiKey) {
83
+ logger.warn('No API key configured — AI features disabled');
84
+ }
85
+
86
+ const ai = apiKey
87
+ ? new ClaudeProvider(apiKey, config.ai.model, config.ai.base_url)
88
+ : null;
89
+
90
+ // ── 5. Initialize services ─────────────────────────────────────────────────
91
+ const skillApiKey = config.skill_matching?.api_key || apiKey;
92
+ const skillRegistry = new SkillRegistry(skillApiKey);
93
+ const invocationGuard = new InvocationGuard();
94
+ if (skillApiKey) {
95
+ logger.info('[Skills] Registry loaded with semantic matching support');
96
+ } else {
97
+ logger.info('[Skills] Registry loaded (keyword matching)');
98
+ }
99
+ logger.info('[Skills] InvocationGuard ready (idempotent + depth/total limits)');
100
+
101
+ const exporter = new HistoryExporter(storage);
102
+ const resume = new ResumeManager(storage);
103
+ const conventionExtractor = new ConventionExtractor();
104
+ const taskSegmenter = new TaskSegmenter(storage);
105
+
106
+ logger.info('[Services] Initialized: ResumeManager, TaskSegmenter, SkillRegistry');
107
+
108
+ // ── 5.5. Schedule daily maintenance ────────────────────────────────────────
109
+ // Clean old events every 24 hours
110
+ const MAINTENANCE_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
111
+ setInterval(() => {
112
+ logger.info('[Daemon] Running daily maintenance: cleaning old events');
113
+ try {
114
+ storage.cleanOldEvents(30);
115
+ } catch (err) {
116
+ logger.error(`[Daemon] Maintenance failed: ${err}`);
117
+ }
118
+ }, MAINTENANCE_INTERVAL);
119
+ logger.info('[Daemon] Scheduled daily maintenance (clean events older than 30 days)');
120
+
121
+ // ── 6. Create handlers ─────────────────────────────────────────────────────
122
+ const userPromptHandler = new UserPromptHandler(
123
+ resume,
124
+ conventionExtractor,
125
+ storage,
126
+ skillRegistry,
127
+ );
128
+
129
+ const handlers: Handlers = {
130
+ UserPromptSubmit: userPromptHandler,
131
+ PostToolUse: new PostToolUseHandler(storage),
132
+ Stop: new StopHandler(
133
+ exporter,
134
+ resume,
135
+ taskSegmenter,
136
+ storage,
137
+ invocationGuard,
138
+ userPromptHandler,
139
+ ),
140
+ };
141
+
142
+ // ── 7. Event handler ───────────────────────────────────────────────────────
143
+ const handleEvent = async (event: ForgeEvent): Promise<HookResponse | void> => {
144
+ try {
145
+ try {
146
+ storage.writeEvent(event);
147
+ } catch (writeErr) {
148
+ const writeMsg = writeErr instanceof Error ? writeErr.message : String(writeErr);
149
+ if (writeMsg.includes('UNIQUE constraint failed')) {
150
+ // Duplicate event_id — already in DB (e.g. replayed from queue then re-sent).
151
+ // Log at debug level and continue processing the event normally.
152
+ logger.debug(`[Event] Duplicate event_id ignored: ${event.event_id}`);
153
+ } else {
154
+ throw writeErr;
155
+ }
156
+ }
157
+ logger.debug(`[Event] ${event.hook_type} | tool=${event.tool_name ?? 'N/A'}`);
158
+
159
+ // Task segmentation: UserPromptSubmit starts/continues tasks
160
+ const prompt = event.user_prompt || (event.tool_input as any)?.user_prompt;
161
+ if (event.hook_type === 'UserPromptSubmit' && prompt) {
162
+ taskSegmenter.processPrompt(event.session_id, prompt, event.timestamp, event.event_id);
163
+ } else if (event.event_id) {
164
+ taskSegmenter.linkEvent(event.session_id, event.event_id);
165
+ }
166
+
167
+ // PreToolUse: always allow (governance removed)
168
+ if (event.hook_type === 'PreToolUse') {
169
+ return { allow: true };
170
+ }
171
+
172
+ const result = await routeEvent(event, handlers);
173
+
174
+ if (result) {
175
+ const handlerName = event.hook_type + 'Handler';
176
+ if (result.systemMessage) {
177
+ storage.writeInjection({
178
+ event_id: event.event_id,
179
+ session_id: event.session_id,
180
+ timestamp: event.timestamp,
181
+ source_handler: handlerName,
182
+ injection_type: 'systemMessage',
183
+ content: result.systemMessage,
184
+ });
185
+ const preview = result.systemMessage.slice(0, 200).replace(/\n/g, ' ');
186
+ console.error(`\x1b[36m[${handlerName}] systemMessage (${result.systemMessage.length} chars): ${preview}\x1b[0m`);
187
+ }
188
+ if (result.additionalContext) {
189
+ storage.writeInjection({
190
+ event_id: event.event_id,
191
+ session_id: event.session_id,
192
+ timestamp: event.timestamp,
193
+ source_handler: handlerName,
194
+ injection_type: 'additionalContext',
195
+ content: result.additionalContext,
196
+ });
197
+ const preview = result.additionalContext.slice(0, 200).replace(/\n/g, ' ');
198
+ console.error(`\x1b[36m[${handlerName}] additionalContext: ${preview}\x1b[0m`);
199
+ }
200
+ }
201
+
202
+ return result;
203
+ } catch (err) {
204
+ logger.error(`Event handling failed: ${err}`);
205
+ throw err;
206
+ }
207
+ };
208
+
209
+ // ── 8. Start socket server ─────────────────────────────────────────────────
210
+ const socketPath = getSocketPath();
211
+ const server = new SocketServer(socketPath, handleEvent, authToken);
212
+
213
+ // ── 8.1. Replay queued events (hook failures during daemon downtime) ────────
214
+ // Run after the socket is created so the daemon is ready to receive events.
215
+ // setImmediate ensures the event loop has had a chance to process the listen
216
+ // callback before we touch storage (not strictly required, but defensive).
217
+ setImmediate(() => {
218
+ replayQueue(storage).then(({ replayed, skipped, dead }) => {
219
+ if (replayed > 0 || skipped > 0 || dead > 0) {
220
+ logger.info(`[Queue] Replay: ${replayed} replayed, ${skipped} skipped (dup), ${dead} dead-lettered`);
221
+ }
222
+ }).catch((err) => {
223
+ logger.error(`[Queue] replayQueue failed: ${err}`);
224
+ });
225
+ });
226
+
227
+ // ── 8.5. Start web server (optional) ───────────────────────────────────────
228
+ // Priority: CLI option > env var > config file
229
+ const webEnabled = options.web ?? (process.env.FORGE_DAEMON_NO_WEB === '1' ? false : config.web.enabled);
230
+ let webServer: any = null;
231
+ if (webEnabled) {
232
+ const { WebServer } = await import('../web/server.js');
233
+ webServer = new WebServer({
234
+ port: config.web.port,
235
+ storage,
236
+ skillRegistry,
237
+ invocationGuard,
238
+ });
239
+ await webServer.start();
240
+ } else {
241
+ logger.info('[Web] Server disabled (--no-web or config.web.enabled=false)');
242
+ }
243
+
244
+ // ── 9. Graceful shutdown ───────────────────────────────────────────────────
245
+ let shuttingDown = false;
246
+ const shutdown = async () => {
247
+ if (shuttingDown) return;
248
+ shuttingDown = true;
249
+ logger.info('Shutting down...');
250
+
251
+ if (ai) logger.info(`[AI Stats] ${ai.formatStats()}`);
252
+
253
+ if (webServer) await webServer.stop();
254
+ await server.close();
255
+ storage.close();
256
+ removePidFile();
257
+ cleanSocket();
258
+ removeAuthToken();
259
+ process.exit(0);
260
+ };
261
+
262
+ process.on('SIGTERM', shutdown);
263
+ process.on('SIGINT', shutdown);
264
+
265
+ logger.info(`Daemon started (PID: ${process.pid})`);
266
+ if (foreground) {
267
+ process.stdout.write(`Claude Forge daemon running (PID: ${process.pid})\n`);
268
+ process.stdout.write('Press Ctrl+C to stop\n');
269
+ }
270
+ }
271
+
272
+ // Allow running as standalone script (spawned by `cf daemon start`)
273
+ if (process.env.FORGE_DAEMON_FOREGROUND === '1') {
274
+ startDaemon(true).catch((err) => {
275
+ console.error('Daemon failed to start:', err);
276
+ process.exit(1);
277
+ });
278
+ }