@winspan/claude-forge 8.51.1 → 8.54.3

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 (409) hide show
  1. package/DEVELOPMENT.md +290 -221
  2. package/README.md +50 -8
  3. package/dist/cli/commands/skills.d.ts.map +1 -1
  4. package/dist/cli/commands/skills.js +121 -2
  5. package/dist/cli/commands/skills.js.map +1 -1
  6. package/dist/cli/init/hook-manager.d.ts +1 -1
  7. package/dist/cli/init/hook-manager.d.ts.map +1 -1
  8. package/dist/cli/init/hook-manager.js +1 -0
  9. package/dist/cli/init/hook-manager.js.map +1 -1
  10. package/dist/core/constants.d.ts +2 -0
  11. package/dist/core/constants.d.ts.map +1 -1
  12. package/dist/core/constants.js +4 -0
  13. package/dist/core/constants.js.map +1 -1
  14. package/dist/core/storage/events.d.ts.map +1 -1
  15. package/dist/core/storage/events.js +0 -1
  16. package/dist/core/storage/events.js.map +1 -1
  17. package/dist/core/storage/maintenance.d.ts +25 -3
  18. package/dist/core/storage/maintenance.d.ts.map +1 -1
  19. package/dist/core/storage/maintenance.js +33 -4
  20. package/dist/core/storage/maintenance.js.map +1 -1
  21. package/dist/core/storage/routing.d.ts +4 -0
  22. package/dist/core/storage/routing.d.ts.map +1 -1
  23. package/dist/core/storage/routing.js +10 -4
  24. package/dist/core/storage/routing.js.map +1 -1
  25. package/dist/core/storage/sessions.d.ts +17 -0
  26. package/dist/core/storage/sessions.d.ts.map +1 -1
  27. package/dist/core/storage/sessions.js +64 -0
  28. package/dist/core/storage/sessions.js.map +1 -1
  29. package/dist/core/storage/skills.d.ts +4 -0
  30. package/dist/core/storage/skills.d.ts.map +1 -1
  31. package/dist/core/storage/skills.js +10 -2
  32. package/dist/core/storage/skills.js.map +1 -1
  33. package/dist/core/storage/sqlite.d.ts +5 -0
  34. package/dist/core/storage/sqlite.d.ts.map +1 -1
  35. package/dist/core/storage/sqlite.js +6 -0
  36. package/dist/core/storage/sqlite.js.map +1 -1
  37. package/dist/core/storage/tasks.d.ts.map +1 -1
  38. package/dist/core/storage/tasks.js +2 -0
  39. package/dist/core/storage/tasks.js.map +1 -1
  40. package/dist/core/types.d.ts +7 -0
  41. package/dist/core/types.d.ts.map +1 -1
  42. package/dist/daemon/index.d.ts.map +1 -1
  43. package/dist/daemon/index.js +30 -5
  44. package/dist/daemon/index.js.map +1 -1
  45. package/dist/daemon/skill-sync.d.ts +21 -0
  46. package/dist/daemon/skill-sync.d.ts.map +1 -0
  47. package/dist/daemon/skill-sync.js +75 -0
  48. package/dist/daemon/skill-sync.js.map +1 -0
  49. package/dist/hooks/notification.sh +1 -1
  50. package/dist/hooks/post-tool-use.sh +1 -1
  51. package/dist/hooks/pre-tool-use.sh +1 -1
  52. package/dist/hooks/stop.sh +1 -1
  53. package/dist/hooks/user-prompt-submit.sh +1 -1
  54. package/dist/skills/official/code-simplifier.md +37 -1
  55. package/dist/skills/official/find-skills.md +120 -1
  56. package/dist/skills/official/official-api-design.md +14 -1
  57. package/dist/skills/official/official-architecture-decision.md +22 -1
  58. package/dist/skills/official/official-db-schema-design.md +19 -1
  59. package/dist/skills/official/official-debug.md +9 -1
  60. package/dist/skills/official/official-pr-review.md +1 -1
  61. package/dist/skills/official/official-security-hardening.md +7 -1
  62. package/dist/skills/official/planning-with-files.md +206 -2
  63. package/dist/skills/official/ui-ux-pro-max.md +88 -1
  64. package/dist/skills/official/webapp-testing.md +85 -1
  65. package/dist/skills/registry.d.ts +1 -1
  66. package/dist/skills/registry.d.ts.map +1 -1
  67. package/dist/skills/registry.js +15 -4
  68. package/dist/skills/registry.js.map +1 -1
  69. package/dist/skills/semantic-matcher.d.ts +4 -3
  70. package/dist/skills/semantic-matcher.d.ts.map +1 -1
  71. package/dist/skills/semantic-matcher.js +20 -22
  72. package/dist/skills/semantic-matcher.js.map +1 -1
  73. package/dist/skills/upgrade-engine.d.ts +93 -0
  74. package/dist/skills/upgrade-engine.d.ts.map +1 -0
  75. package/dist/skills/upgrade-engine.js +447 -0
  76. package/dist/skills/upgrade-engine.js.map +1 -0
  77. package/dist/skills/upgrade-prompt.d.ts +20 -0
  78. package/dist/skills/upgrade-prompt.d.ts.map +1 -0
  79. package/dist/skills/upgrade-prompt.js +75 -0
  80. package/dist/skills/upgrade-prompt.js.map +1 -0
  81. package/dist/web/analytics/weekly-report.d.ts.map +1 -1
  82. package/dist/web/analytics/weekly-report.js +21 -29
  83. package/dist/web/analytics/weekly-report.js.map +1 -1
  84. package/dist/web/routes/patch.d.ts.map +1 -1
  85. package/dist/web/routes/patch.js +32 -2
  86. package/dist/web/routes/patch.js.map +1 -1
  87. package/dist/web/routes/sessions.d.ts.map +1 -1
  88. package/dist/web/routes/sessions.js +9 -7
  89. package/dist/web/routes/sessions.js.map +1 -1
  90. package/dist/web/routes/trace.d.ts.map +1 -1
  91. package/dist/web/routes/trace.js +2 -3
  92. package/dist/web/routes/trace.js.map +1 -1
  93. package/dist/web/server.d.ts.map +1 -1
  94. package/dist/web/server.js +3 -2
  95. package/dist/web/server.js.map +1 -1
  96. package/package.json +12 -2
  97. package/scripts/postinstall.cjs +21 -0
  98. package/.claude/CLAUDE.md +0 -17
  99. package/.eslintrc.js +0 -23
  100. package/.prettierrc +0 -8
  101. package/ARCHITECTURE_ISSUES.md +0 -249
  102. package/CLAUDE.md +0 -265
  103. package/CLAUDE.md.backup +0 -488
  104. package/docs/concurrent-agents.md +0 -129
  105. package/docs/design/architecture-review-20260516.md +0 -232
  106. package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +0 -219
  107. package/docs/design/h1-storage-aggregation-spec-20260518-1121.md +0 -299
  108. package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +0 -191
  109. package/docs/design/h3-fallback-removal-spec-20260518-1245.md +0 -76
  110. package/docs/design/h4-index-dedup-spec-20260518-1230.md +0 -109
  111. package/docs/design/h6-services-migration-spec-20260518-1355.md +0 -82
  112. package/docs/design/hook-failure-queue-spec-20260516-1530.md +0 -204
  113. package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +0 -106
  114. package/docs/design/m10-forge-paths-spec-20260518-1320.md +0 -121
  115. package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +0 -131
  116. package/docs/design/m7-routing-event-association-spec-20260518-1545.md +0 -103
  117. package/docs/design/project-path-gitroot-spec-20260518-1715.md +0 -134
  118. package/docs/design/refactor-phase1-spec-20260515-1600.md +0 -543
  119. package/docs/design/refactor-phase2-spec-20260515-1700.md +0 -424
  120. package/docs/design/task-active-gc-spec-20260518-1745.md +0 -146
  121. package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +0 -208
  122. package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +0 -104
  123. package/docs/implementation/h1-storage-aggregation-changelog-20260518-1121.md +0 -82
  124. package/docs/implementation/h2-final-changelog-20260518-1530.md +0 -61
  125. package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +0 -70
  126. package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +0 -120
  127. package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +0 -71
  128. package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +0 -71
  129. package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +0 -60
  130. package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +0 -46
  131. package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +0 -46
  132. package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +0 -196
  133. package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +0 -56
  134. package/docs/implementation/l1-swarm-protocol-extract-changelog-20260518-1605.md +0 -45
  135. package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +0 -63
  136. package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +0 -38
  137. package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +0 -58
  138. package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +0 -60
  139. package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +0 -43
  140. package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +0 -56
  141. package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +0 -69
  142. package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +0 -63
  143. package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +0 -354
  144. package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +0 -421
  145. package/docs/implementation/task-active-gc-changelog-20260518-1745.md +0 -35
  146. package/docs/implementation/task-title-summary-changelog-20260518-1130.md +0 -39
  147. package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +0 -22
  148. package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +0 -72
  149. package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +0 -56
  150. package/docs/reviews/claudemd-template-sync.md +0 -54
  151. package/docs/reviews/task-title-summary.md +0 -92
  152. package/docs/reviews/tasks-detail-back-loses-filters.md +0 -58
  153. package/docs/reviews/tasks-filter-pagination.md +0 -80
  154. package/docs/reviews/tasks-page-white-screen-hotfix.md +0 -126
  155. package/docs/ruflo-learning-strategy.md +0 -322
  156. package/docs/skills-deduplication-analysis.md +0 -83
  157. package/docs/skills-multiformat-support.md +0 -177
  158. package/docs/skills-third-party.md +0 -183
  159. package/docs/testing/tasks-filter-pagination-test-report.md +0 -86
  160. package/forge +0 -321
  161. package/playwright.config.ts +0 -40
  162. package/scripts/demo-v2.ts +0 -91
  163. package/scripts/dev-daemon.sh +0 -232
  164. package/scripts/dev-web.ts +0 -109
  165. package/scripts/e2e-mcp-link.ts +0 -423
  166. package/scripts/e2e-methodology-quality.ts +0 -253
  167. package/scripts/e2e-routing.ts +0 -456
  168. package/scripts/e2e-user-methodology.ts +0 -326
  169. package/scripts/e2e-web-workflows.ts +0 -299
  170. package/scripts/migrate-legacy-to-dynamic.sql +0 -108
  171. package/scripts/regenerate-execution-docs.ts +0 -116
  172. package/scripts/sync-agent-skills.ts +0 -193
  173. package/scripts/test-hook.sh +0 -71
  174. package/scripts/verify-skill-loading.ts +0 -62
  175. package/src/claudemd/claudemd-generator.ts +0 -568
  176. package/src/claudemd/convention-extractor.ts +0 -69
  177. package/src/claudemd/index.ts +0 -35
  178. package/src/claudemd/persona-manager.ts +0 -88
  179. package/src/claudemd/resume-manager.ts +0 -236
  180. package/src/claudemd/tech-detector.ts +0 -220
  181. package/src/claudemd/templates/swarm-protocol.md +0 -222
  182. package/src/cli/commands/claudemd.ts +0 -84
  183. package/src/cli/commands/config.ts +0 -46
  184. package/src/cli/commands/daemon.ts +0 -310
  185. package/src/cli/commands/executions.ts +0 -115
  186. package/src/cli/commands/init.ts +0 -204
  187. package/src/cli/commands/logs.ts +0 -181
  188. package/src/cli/commands/mcp.ts +0 -242
  189. package/src/cli/commands/menu.ts +0 -357
  190. package/src/cli/commands/skills.ts +0 -185
  191. package/src/cli/commands/stats.ts +0 -73
  192. package/src/cli/commands/status.ts +0 -69
  193. package/src/cli/commands/template.ts +0 -77
  194. package/src/cli/commands/trace.ts +0 -148
  195. package/src/cli/index.ts +0 -42
  196. package/src/cli/init/hook-manager.ts +0 -132
  197. package/src/core/ai/provider.ts +0 -308
  198. package/src/core/ai/types.ts +0 -51
  199. package/src/core/config.ts +0 -124
  200. package/src/core/constants.ts +0 -62
  201. package/src/core/event-fields.ts +0 -32
  202. package/src/core/queue/index.ts +0 -192
  203. package/src/core/storage/base.ts +0 -302
  204. package/src/core/storage/events.ts +0 -434
  205. package/src/core/storage/injections.ts +0 -78
  206. package/src/core/storage/maintenance.ts +0 -59
  207. package/src/core/storage/migrations/002_add_skill_tracking.sql +0 -6
  208. package/src/core/storage/migrations/003_add_skill_invocations.sql +0 -23
  209. package/src/core/storage/performance-indexes.sql +0 -23
  210. package/src/core/storage/routing.ts +0 -322
  211. package/src/core/storage/rows.ts +0 -112
  212. package/src/core/storage/schema.sql +0 -224
  213. package/src/core/storage/sessions.ts +0 -168
  214. package/src/core/storage/skills.ts +0 -233
  215. package/src/core/storage/sqlite.ts +0 -293
  216. package/src/core/storage/tasks.ts +0 -318
  217. package/src/core/storage/token-usage.ts +0 -93
  218. package/src/core/types.ts +0 -181
  219. package/src/core/utils/error-handler.ts +0 -257
  220. package/src/core/utils/forge-resume-block.ts +0 -74
  221. package/src/core/utils/format.ts +0 -69
  222. package/src/core/utils/git.ts +0 -23
  223. package/src/core/utils/logger.ts +0 -134
  224. package/src/core/utils/lru-cache.ts +0 -54
  225. package/src/core/utils/path.ts +0 -19
  226. package/src/core/utils/session.ts +0 -26
  227. package/src/core/utils/time.ts +0 -37
  228. package/src/core/utils/token-tracker.ts +0 -97
  229. package/src/daemon/event-parser.ts +0 -36
  230. package/src/daemon/handlers/history-exporter.ts +0 -117
  231. package/src/daemon/handlers/post-tool-use.ts +0 -54
  232. package/src/daemon/handlers/stop.ts +0 -208
  233. package/src/daemon/handlers/user-prompt.ts +0 -178
  234. package/src/daemon/hook-sync.ts +0 -91
  235. package/src/daemon/index.ts +0 -302
  236. package/src/daemon/launchd/com.claude-forge.daemon.plist.template +0 -47
  237. package/src/daemon/launchd-installer.ts +0 -260
  238. package/src/daemon/lifecycle.ts +0 -128
  239. package/src/daemon/router.ts +0 -40
  240. package/src/daemon/server.ts +0 -196
  241. package/src/daemon/services/task-segmenter.ts +0 -112
  242. package/src/hooks/hook-lib.sh +0 -118
  243. package/src/hooks/notification.sh +0 -35
  244. package/src/hooks/post-tool-use.sh +0 -61
  245. package/src/hooks/pre-tool-use.sh +0 -63
  246. package/src/hooks/stop.sh +0 -43
  247. package/src/hooks/user-prompt-submit.sh +0 -69
  248. package/src/mcp/server.ts +0 -322
  249. package/src/skills/index.ts +0 -2
  250. package/src/skills/invocation-guard.ts +0 -177
  251. package/src/skills/matcher.ts +0 -148
  252. package/src/skills/official/code-simplifier.md +0 -16
  253. package/src/skills/official/find-skills.md +0 -23
  254. package/src/skills/official/official-api-design.md +0 -17
  255. package/src/skills/official/official-architecture-decision.md +0 -20
  256. package/src/skills/official/official-bmad.md +0 -118
  257. package/src/skills/official/official-db-schema-design.md +0 -16
  258. package/src/skills/official/official-debug.md +0 -17
  259. package/src/skills/official/official-doc-driven.md +0 -31
  260. package/src/skills/official/official-harness-engineering.md +0 -108
  261. package/src/skills/official/official-performance-optimization.md +0 -30
  262. package/src/skills/official/official-pr-review.md +0 -35
  263. package/src/skills/official/official-release-checklist.md +0 -30
  264. package/src/skills/official/official-security-hardening.md +0 -26
  265. package/src/skills/official/official-spec-driven-design.md +0 -31
  266. package/src/skills/official/planning-with-files.md +0 -37
  267. package/src/skills/official/ui-ux-pro-max.md +0 -18
  268. package/src/skills/official/webapp-testing.md +0 -12
  269. package/src/skills/official-skills.ts +0 -89
  270. package/src/skills/registry.ts +0 -355
  271. package/src/skills/semantic-matcher.ts +0 -231
  272. package/src/skills/tools/pipeline-suggest.ts +0 -226
  273. package/src/skills/tools/skill-invoke.ts +0 -168
  274. package/src/skills/tools/skill-list.ts +0 -59
  275. package/src/templates/go.yaml +0 -53
  276. package/src/templates/python.yaml +0 -59
  277. package/src/templates/react.yaml +0 -55
  278. package/src/templates/template-manager.ts +0 -170
  279. package/src/web/analytics/anti-pattern-detector.ts +0 -367
  280. package/src/web/analytics/drift-detector.ts +0 -219
  281. package/src/web/analytics/weekly-report.ts +0 -431
  282. package/src/web/auth-middleware.ts +0 -54
  283. package/src/web/routes/_helpers.ts +0 -34
  284. package/src/web/routes/ai.ts +0 -204
  285. package/src/web/routes/auth.ts +0 -22
  286. package/src/web/routes/drift.ts +0 -25
  287. package/src/web/routes/error-handler.ts +0 -120
  288. package/src/web/routes/events.ts +0 -47
  289. package/src/web/routes/insights.ts +0 -43
  290. package/src/web/routes/patch.ts +0 -117
  291. package/src/web/routes/reports.ts +0 -34
  292. package/src/web/routes/rules.ts +0 -76
  293. package/src/web/routes/sessions.ts +0 -250
  294. package/src/web/routes/skill-stats.ts +0 -92
  295. package/src/web/routes/skills.ts +0 -350
  296. package/src/web/routes/static.ts +0 -67
  297. package/src/web/routes/stats.ts +0 -50
  298. package/src/web/routes/status.ts +0 -30
  299. package/src/web/routes/tasks.ts +0 -193
  300. package/src/web/routes/token-usage.ts +0 -20
  301. package/src/web/routes/trace.ts +0 -126
  302. package/src/web/routes/types.ts +0 -57
  303. package/src/web/server.ts +0 -134
  304. package/src/web/ssrf-guard.ts +0 -112
  305. package/src/web/static/index.html +0 -3251
  306. package/src/web/static/vendor/chart.umd.min.js +0 -20
  307. package/tests/e2e/dashboard.spec.ts +0 -205
  308. package/tests/e2e/routing-skill-e2e.test.ts +0 -39
  309. package/tests/helpers/mock-ai.ts +0 -92
  310. package/tests/helpers/mock-storage.ts +0 -159
  311. package/tests/integration/claudemd-generator.test.ts +0 -90
  312. package/tests/integration/queue-replay.integration.test.ts +0 -193
  313. package/tests/integration/tasks-filter.integration.test.ts +0 -154
  314. package/tests/integration/web-analytics.integration.test.ts +0 -133
  315. package/tests/integration/web-stats.integration.test.ts +0 -135
  316. package/tests/integration/web-trace.integration.test.ts +0 -175
  317. package/tests/performance/database.benchmark.ts +0 -161
  318. package/tests/semantic-matcher.test.ts +0 -99
  319. package/tests/skill-matcher.test.ts +0 -110
  320. package/tests/unit/ai-provider-retry.test.ts +0 -194
  321. package/tests/unit/ai-provider-vision.test.ts +0 -224
  322. package/tests/unit/claudemd-generator.test.ts +0 -68
  323. package/tests/unit/cli-mcp.test.ts +0 -141
  324. package/tests/unit/core/forge-paths.test.ts +0 -99
  325. package/tests/unit/daemon/hook-sync.test.ts +0 -71
  326. package/tests/unit/daemon/post-tool-use.test.ts +0 -121
  327. package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +0 -202
  328. package/tests/unit/daemon/task-segmenter-recover.test.ts +0 -84
  329. package/tests/unit/event-fields.test.ts +0 -88
  330. package/tests/unit/event-parser.test.ts +0 -55
  331. package/tests/unit/handlers.test.ts +0 -171
  332. package/tests/unit/hooks/resolve-project-path.test.ts +0 -122
  333. package/tests/unit/invocation-guard.test.ts +0 -125
  334. package/tests/unit/queue.test.ts +0 -272
  335. package/tests/unit/router.test.ts +0 -138
  336. package/tests/unit/security.test.ts +0 -128
  337. package/tests/unit/skill-invocations-workflow.test.ts +0 -495
  338. package/tests/unit/skill-registry.test.ts +0 -94
  339. package/tests/unit/skills/invocation-guard-ttl.test.ts +0 -211
  340. package/tests/unit/skills/official-skills-loader.test.ts +0 -126
  341. package/tests/unit/skills/registry-multiformat.test.ts +0 -92
  342. package/tests/unit/socket-server.test.ts +0 -183
  343. package/tests/unit/storage/event-operations-aggregates.test.ts +0 -342
  344. package/tests/unit/storage/migration-idempotent.test.ts +0 -304
  345. package/tests/unit/storage/routing-aggregates.test.ts +0 -276
  346. package/tests/unit/storage/routing.test.ts +0 -117
  347. package/tests/unit/storage/schema-missing.test.ts +0 -81
  348. package/tests/unit/storage/session-operations-aggregates.test.ts +0 -120
  349. package/tests/unit/storage/sessions-aggregate.test.ts +0 -435
  350. package/tests/unit/storage/skill-operations-counts.test.ts +0 -106
  351. package/tests/unit/storage/skills-aggregates.test.ts +0 -104
  352. package/tests/unit/storage/sqlite-refactor-harness.test.ts +0 -314
  353. package/tests/unit/storage/task-operations-counts.test.ts +0 -46
  354. package/tests/unit/storage/tasks-getById.test.ts +0 -343
  355. package/tests/unit/storage/tasks-stale-gc.test.ts +0 -86
  356. package/tests/unit/storage.test.ts +0 -172
  357. package/tests/unit/token-usage.test.ts +0 -144
  358. package/tests/unit/type-guards.test.ts +0 -201
  359. package/tests/unit/utils/format.test.ts +0 -189
  360. package/tests/unit/utils/session.test.ts +0 -89
  361. package/tests/unit/utils/time.test.ts +0 -112
  362. package/tests/unit/web/navigation-back-contract.test.ts +0 -134
  363. package/tests/unit/web/routes-auth.test.ts +0 -93
  364. package/tests/unit/web/routes-events.test.ts +0 -101
  365. package/tests/unit/web/routes-rules.test.ts +0 -182
  366. package/tests/unit/web/routes-sessions.test.ts +0 -181
  367. package/tests/unit/web/routes-skill-stats.test.ts +0 -179
  368. package/tests/unit/web/routes-stats.test.ts +0 -92
  369. package/tests/unit/web/routes-tasks.test.ts +0 -385
  370. package/tests/unit/web/task-title-contract.test.ts +0 -210
  371. package/tests/unit/web/tasks-component-contract.test.ts +0 -179
  372. package/tsconfig.json +0 -22
  373. package/vitest.config.ts +0 -21
  374. package/vitest.integration.config.ts +0 -16
  375. package/web/CLAUDE.md +0 -20
  376. package/web/index.html +0 -13
  377. package/web/package-lock.json +0 -4854
  378. package/web/package.json +0 -35
  379. package/web/postcss.config.js +0 -6
  380. package/web/src/App.tsx +0 -110
  381. package/web/src/components/CodeBlock.tsx +0 -31
  382. package/web/src/components/Confirm.tsx +0 -96
  383. package/web/src/components/Drawer.tsx +0 -60
  384. package/web/src/components/Layout.tsx +0 -145
  385. package/web/src/components/MarkdownRenderer.tsx +0 -77
  386. package/web/src/components/SearchInput.tsx +0 -31
  387. package/web/src/components/SessionDetailContent.tsx +0 -157
  388. package/web/src/components/Toast.tsx +0 -92
  389. package/web/src/index.css +0 -19
  390. package/web/src/main.tsx +0 -31
  391. package/web/src/pages/AIConfig.tsx +0 -233
  392. package/web/src/pages/Dashboard.tsx +0 -572
  393. package/web/src/pages/Events.tsx +0 -271
  394. package/web/src/pages/Reports.tsx +0 -428
  395. package/web/src/pages/SessionDetail.tsx +0 -162
  396. package/web/src/pages/Sessions.tsx +0 -205
  397. package/web/src/pages/Skills.tsx +0 -180
  398. package/web/src/pages/TaskDetail.tsx +0 -515
  399. package/web/src/pages/Tasks.tsx +0 -415
  400. package/web/src/utils/auth.ts +0 -59
  401. package/web/src/utils/export.ts +0 -54
  402. package/web/src/utils/navigation.ts +0 -25
  403. package/web/src/utils/task-title.ts +0 -49
  404. package/web/src/utils/time.ts +0 -13
  405. package/web/tailwind.config.js +0 -11
  406. package/web/tsconfig.json +0 -21
  407. package/web/tsconfig.node.json +0 -10
  408. package/web/vite.config.ts +0 -76
  409. package/winspan-claude-forge-8.43.0.tgz +0 -0
@@ -1,299 +0,0 @@
1
- # H1: Storage 层 SQL 聚合改造 Spec
2
-
3
- ## 目标
4
-
5
- 把 `web/routes/{rules,skill-stats,tasks}.ts` 里的"全表 SELECT + JS GROUP BY"模式下沉为 SQL 聚合,消除单进程内存放大(最大 100k 行 × 2),同时把 `tasks/:taskId` 的 5000 行二段全扫改为 PK 直查 + JOIN。纯增量改动,旧 API 不动。
6
-
7
- ## 涉及文件
8
-
9
- - 改动 storage:`src/core/storage/routing.ts`、`src/core/storage/skills.ts`、`src/core/storage/tasks.ts`、`src/core/storage/sqlite.ts`(facade 转发)
10
- - 改动 routes:`src/web/routes/rules.ts`、`src/web/routes/skill-stats.ts`、`src/web/routes/tasks.ts`
11
- - 索引:`src/core/storage/schema.sql` + `src/core/storage/base.ts`(runMigrations)
12
- - 测试新增:`tests/unit/storage/routing-aggregates.test.ts`、`tests/unit/storage/skills-aggregates.test.ts`、`tests/unit/storage/tasks-getById.test.ts`
13
- - 测试保留契约:`tests/unit/web/routes-skill-stats.test.ts`、`tests/unit/web/routes-tasks.test.ts`
14
- - 测试缺口:rules 路由无测试 → spec 标注需补 `tests/unit/web/routes-rules.test.ts`
15
-
16
- ## 现状分析
17
-
18
- | 文件:行 | 问题 | 行为 |
19
- |---|---|---|
20
- | `rules.ts:24,34` | `limit: 100000` ×2 | 全表 routing/skill 拉进内存后 JS reduce |
21
- | `skill-stats.ts:19,44,65,113` | 5 个 `limit: 10000` | 4 个聚合 + 1 个 trend by-day |
22
- | `skill-stats.ts:94` | `limit: 1000` invocations | by-skill 频次聚合 |
23
- | `tasks.ts:63-64` | 拉 5000 tasks 再 `.find(id)` | 应 PK 直查 |
24
- | `tasks.ts:71-75` | 拉 5000 events 后 `Set.has` 过滤 | 应 JOIN `task_events` |
25
-
26
- ## 设计方案
27
-
28
- ### 1. 新增 storage 方法
29
-
30
- **命名约定**:聚合方法用 `aggregate` 前缀(CLAUDE.md 未明确,spec 明确为硬约束)。
31
-
32
- #### `RoutingOperations` (`src/core/storage/routing.ts`)
33
-
34
- ```ts
35
- // 一次返回 rules.ts 和 skill-stats.ts 共用的 routing 汇总
36
- aggregateRoutingStats(filter: { since_ts: number; project_path?: string }): {
37
- total: number;
38
- obeyed: number; // obeyed = 1
39
- refused: number; // obeyed = 0
40
- unknown: number; // obeyed IS NULL
41
- by_type: Array<{ type: 'agent' | 'skill' | 'none'; count: number }>;
42
- by_agent: Array<{ agent: string; count: number }>; // obeyed=1 AND routed_to_name NOT NULL
43
- by_skill_routed: Array<{ skill: string; count: number }>; // routed_to_type='skill' (for frequency)
44
- }
45
- ```
46
-
47
- SQL(在事务里跑 4 个独立聚合,全部走 `idx_routing_events_ts` / `idx_routing_events_obeyed_ts` / `idx_routing_events_agent`):
48
-
49
- ```sql
50
- -- total + obeyed counts
51
- SELECT COUNT(*) AS total,
52
- SUM(CASE WHEN obeyed=1 THEN 1 ELSE 0 END) AS obeyed,
53
- SUM(CASE WHEN obeyed=0 THEN 1 ELSE 0 END) AS refused,
54
- SUM(CASE WHEN obeyed IS NULL THEN 1 ELSE 0 END) AS unknown
55
- FROM routing_events WHERE ts >= @since AND (@project IS NULL OR project_path = @project);
56
-
57
- -- by_type (distribution)
58
- SELECT COALESCE(routed_to_type,'none') AS type, COUNT(*) AS count
59
- FROM routing_events WHERE ts >= @since [...] GROUP BY type;
60
-
61
- -- by_agent
62
- SELECT routed_to_name AS agent, COUNT(*) AS count
63
- FROM routing_events
64
- WHERE ts >= @since AND obeyed=1 AND routed_to_name IS NOT NULL [...]
65
- GROUP BY routed_to_name ORDER BY count DESC;
66
-
67
- -- by_skill_routed (frequency)
68
- SELECT routed_to_name AS skill, COUNT(*) AS count
69
- FROM routing_events
70
- WHERE ts >= @since AND routed_to_type='skill' AND routed_to_name IS NOT NULL [...]
71
- GROUP BY routed_to_name ORDER BY count DESC;
72
- ```
73
-
74
- ```ts
75
- // trend by day(skill-stats.ts:62)— SQLite 用 strftime
76
- aggregateRoutingTrendByDay(filter: { since_ts: number }): Array<{
77
- day: string; // 'YYYY-MM-DD'
78
- total: number;
79
- skill: number;
80
- }>
81
- ```
82
-
83
- SQL:
84
-
85
- ```sql
86
- SELECT strftime('%Y-%m-%d', ts/1000, 'unixepoch') AS day,
87
- COUNT(*) AS total,
88
- SUM(CASE WHEN routed_to_type='skill' THEN 1 ELSE 0 END) AS skill
89
- FROM routing_events WHERE ts >= @since
90
- GROUP BY day ORDER BY day ASC;
91
- ```
92
-
93
- 调用方:`rules.ts`(hit-rate)、`skill-stats.ts`(distribution / frequency / trend / routing-stats)
94
-
95
- #### `SkillOperations` (`src/core/storage/skills.ts`)
96
-
97
- ```ts
98
- aggregateSkillInvocationsBySkill(filter: { since: number; limit?: number }): Array<{
99
- skill_id: string;
100
- total: number;
101
- success: number; // success = 1
102
- failed: number; // success = 0
103
- }>
104
- ```
105
-
106
- SQL(走 `idx_skill_invocations_timestamp` + group):
107
-
108
- ```sql
109
- SELECT skill_id,
110
- COUNT(*) AS total,
111
- SUM(CASE WHEN success=1 THEN 1 ELSE 0 END) AS success,
112
- SUM(CASE WHEN success=0 THEN 1 ELSE 0 END) AS failed
113
- FROM skill_invocations
114
- WHERE timestamp >= @since
115
- GROUP BY skill_id ORDER BY total DESC;
116
- ```
117
-
118
- 调用方:`rules.ts`(per-skill)、`skill-stats.ts:91`(invocations)
119
-
120
- #### `TaskOperations` (`src/core/storage/tasks.ts`)
121
-
122
- ```ts
123
- getTask(taskId: string): TaskRecord | null;
124
- queryEventsByTaskId(taskId: string, opts?: { limit?: number }): ForgeEvent[];
125
- queryInjectionsByTaskId(taskId: string): Injection[];
126
- querySkillInvocationsByTaskWindow(taskId: string): SkillInvocationRow[]; // 用 task 的 start_time / end_time 直接 SQL 过滤
127
- ```
128
-
129
- SQL:
130
-
131
- ```sql
132
- -- getTask
133
- SELECT t.*, s.project_path FROM tasks t
134
- LEFT JOIN sessions s ON s.session_id = t.session_id
135
- WHERE t.id = ?;
136
-
137
- -- queryEventsByTaskId
138
- SELECT e.* FROM events e
139
- JOIN task_events te ON te.event_id = e.event_id
140
- WHERE te.task_id = ?
141
- ORDER BY e.timestamp ASC
142
- LIMIT ?;
143
-
144
- -- queryInjectionsByTaskId
145
- SELECT i.* FROM injections i
146
- JOIN task_events te ON te.event_id = i.event_id
147
- WHERE te.task_id = ?
148
- ORDER BY i.timestamp ASC;
149
-
150
- -- querySkillInvocationsByTaskWindow(避免 detail 路由再做时间过滤)
151
- SELECT si.* FROM skill_invocations si
152
- JOIN tasks t ON t.session_id = si.session_id
153
- WHERE t.id = ?
154
- AND si.timestamp >= CAST(strftime('%s', t.start_time) AS INTEGER) * 1000
155
- AND si.timestamp <= COALESCE(CAST(strftime('%s', t.end_time) AS INTEGER) * 1000, @now_ms)
156
- ORDER BY si.timestamp ASC;
157
- ```
158
-
159
- 调用方:`tasks.ts:59` detail route
160
-
161
- > **决策**:`querySkillInvocationsByTaskWindow` 把 `now` 通过参数传入而不是 SQL 端拿,便于测试时 mock 时间。
162
-
163
- ### 2. 索引调整
164
-
165
- **复查现状**:
166
- - `idx_routing_events_ts` ✓ — 覆盖 `since_ts`
167
- - `idx_routing_events_agent (routed_to_name, obeyed)` ✓ — 覆盖 by_agent
168
- - `idx_routing_events_obeyed_ts` ✓ — 覆盖 obeyed group
169
- - `idx_skill_invocations_timestamp` ✓ — 覆盖 since filter
170
- - `idx_skill_invocations_skill` ✓ — 覆盖 by skill_id group(不一定需要)
171
- - `idx_task_events_task` ✓ — 覆盖 JOIN
172
- - `tasks.id` 是 PK ✓
173
-
174
- **新增(一处)**:
175
-
176
- ```sql
177
- -- routing_events: routed_to_type 走 distribution 分组高频用
178
- CREATE INDEX IF NOT EXISTS idx_routing_events_type_ts ON routing_events(routed_to_type, ts DESC);
179
- ```
180
-
181
- 放置:`schema.sql` 末尾 + `base.ts` runMigrations 末段(与 Phase 1 indexes 同样的 try/catch 块)。**不要重复放两份**——H4 已记录"schema.sql 与 base.ts 索引重复"问题。本 spec 决定:**只加在 schema.sql,base.ts 的 runMigrations 也加同一条 idempotent CREATE INDEX**(已有先例),不算重复。其它索引保持原样。
182
-
183
- ### 3. Routes 改造
184
-
185
- #### `rules.ts` (hit-rate)
186
-
187
- ```ts
188
- // before: queryRoutingEvents({limit:100000}) + querySkillInvocations({limit:100000}) + JS reduce
189
- // after:
190
- const routing = storage.aggregateRoutingStats({ since_ts: since });
191
- const skillsAgg = storage.aggregateSkillInvocationsBySkill({ since });
192
- const totalPrompts = routing.total;
193
- const agentDelegations = routing.obeyed;
194
- const skills = skillsAgg.map(s => ({...s, rate: pct(s.total, totalPrompts)}));
195
- const agents = routing.by_agent.map(a => ({...a, rate: pct(a.count, totalPrompts)}));
196
- const triggered = new Set(skillsAgg.map(s => s.skill_id));
197
- const neverTriggered = skillRegistry?.getAll().map(s=>s.id).filter(id=>!triggered.has(id)) ?? [];
198
- ```
199
-
200
- #### `skill-stats.ts`
201
-
202
- | Endpoint | 旧 | 新 |
203
- |---|---|---|
204
- | `/distribution` | `queryRoutingEvents{limit:10000}` + JS group | `aggregateRoutingStats(...).by_type` |
205
- | `/frequency` | 同上 | `aggregateRoutingStats(...).by_skill_routed` |
206
- | `/trend` | 同上 + by-day JS group | `aggregateRoutingTrendByDay({since_ts})` 再 JS map 成 `{day, skillRate}` |
207
- | `/invocations` | `querySkillInvocations{limit:1000}` + JS group | `aggregateSkillInvocationsBySkill({since})` |
208
- | `/api/routing/stats` | `queryRoutingEvents{limit:10000}` + JS filter | `aggregateRoutingStats` 中 `obeyed/total/by_agent` |
209
-
210
- #### `tasks.ts:/:taskId`
211
-
212
- ```ts
213
- // before:
214
- // const allTasks = storage.queryTasks({limit:5000}); task = allTasks.find(...)
215
- // const eventIds = new Set(storage.getTaskEventIds(taskId));
216
- // const allEvents = storage.queryEvents({session_id, limit:5000}); filter by eventIds
217
- // const allInjections = storage.queryInjections({session_id, limit:500}); filter by eventIds
218
- // const allSkillInvocations = storage.querySkillInvocations({session_id, limit:200}); JS time filter
219
- // after:
220
- const task = storage.getTask(taskId); if (!task) return 404;
221
- const taskEvents = storage.queryEventsByTaskId(taskId, { limit: 5000 });
222
- const allInjections = storage.queryInjectionsByTaskId(taskId);
223
- const skillInvocations = storage.querySkillInvocationsByTaskWindow(taskId);
224
- // 后续 timeline / artifacts / userPrompts 逻辑不变
225
- ```
226
-
227
- ## 关键决策
228
-
229
- 1. **聚合方法用 `aggregate` 前缀**(CLAUDE.md 未规定,本 spec 固化)— `aggregateRoutingStats` / `aggregateSkillInvocationsBySkill` / `aggregateRoutingTrendByDay`。理由:与 `query*` / `list*` / `get*` 区分语义,调用方一眼能看出"这是 SQL 端 GROUP BY"。
230
- 2. **新方法挂在各自 Operations 类**,sqlite.ts facade 仅做转发。理由:保持职责拆分,不在 facade 写 SQL。
231
- 3. **不合并 routing 4 个聚合到单条 SQL**。理由:SQLite 无 GROUPING SETS / CUBE,强行 UNION ALL 反而难读;分 4 条 prepared statement 各走自己的索引更快。
232
- 4. **trend by-day 用 `strftime('%Y-%m-%d', ts/1000, 'unixepoch')`**,已验证 better-sqlite3 完全支持。
233
- 5. **`queryEventsByTaskId` 保留 `limit` 参数**(默认 5000)— 防御过大 task;前端不分页,但要有上限。
234
- 6. **`task_events` PK 是 `(task_id, event_id)`**,但 `task_events(event_id)` 的反向 JOIN 已有 `idx_task_events_event`;正向 `idx_task_events_task` 也存在,JOIN 性能 OK。
235
-
236
- ## 测试策略
237
-
238
- ### 单元测试(必加)
239
-
240
- - `tests/unit/storage/routing-aggregates.test.ts`
241
- - 空表返回 `{total:0, obeyed:0, refused:0, unknown:0, by_type:[], ...}`
242
- - 混合 `obeyed=1/0/NULL` 计数正确
243
- - `since_ts` 过滤边界(等于 / 小于)
244
- - `by_agent` 排除 `obeyed≠1` 和 `routed_to_name IS NULL`
245
- - `aggregateRoutingTrendByDay` 跨日聚合 + 时区一致性(UTC)
246
- - `tests/unit/storage/skills-aggregates.test.ts`
247
- - `success=1/0` 分别计数;按 total 降序
248
- - `since` 过滤
249
- - `tests/unit/storage/tasks-getById.test.ts`
250
- - `getTask` 命中 / null
251
- - `queryEventsByTaskId` JOIN 正确性 + 排序
252
- - `querySkillInvocationsByTaskWindow` 时间窗包含/排除(含 end_time IS NULL 取 now)
253
- - `queryInjectionsByTaskId` event_id 关联
254
-
255
- ### 集成 / 路由测试
256
-
257
- - `tests/unit/web/routes-skill-stats.test.ts` — 保留现有契约(响应字段不变),跑过即可
258
- - `tests/unit/web/routes-tasks.test.ts` — 保留,detail 路由响应结构不变
259
- - `tests/unit/web/routes-rules.test.ts` — **缺口,本任务新增**:空数据、混合数据下 totalPrompts / agentDelegations / skills / agents / neverTriggered 均符合预期
260
-
261
- ### 性能基准(可选,给 coder agent)
262
-
263
- 写一个 `scripts/bench/h1-aggregation.ts`(不入 git CI):
264
- - 灌 100k routing_events + 10k skill_invocations
265
- - 测 `aggregateRoutingStats` vs 旧 `queryRoutingEvents({limit:100000})` + JS reduce 的耗时
266
- - 目标:新 ≤ 旧 / 10,内存峰值下降 ≥ 90%
267
-
268
- ## 风险与回滚
269
-
270
- | 风险 | 应对 |
271
- |---|---|
272
- | `strftime('%Y-%m-%d', ts/1000, 'unixepoch')` 在 ts=0 / 负值时返回 NULL | 聚合前 WHERE `ts > 0` 兜底;测试覆盖 |
273
- | `routed_to_type` 历史值含 NULL | `COALESCE(routed_to_type,'none')`,与旧逻辑 `e.routed_to_type \|\| 'none'` 一致 |
274
- | 新索引 `idx_routing_events_type_ts` 与 H4 索引重复隐患 | 检查 `base.ts` 已存在的 5 类索引前缀,确认未重复;只在 schema.sql + base.ts 的 Phase 1 块各加一处 idempotent CREATE |
275
- | `getTask` 响应字段需要包含 `project_path`(旧 detail 路由没用到,但 list 用了) | 用 LEFT JOIN sessions,缺失时返回 undefined,detail 路由对此字段无依赖 |
276
- | 测试缺口:rules 路由 0 测试 → 改造时可能行为漂移 | **强制先补 routes-rules.test.ts,再改 route**(TDD 顺序) |
277
-
278
- **回滚**:纯增量,新方法 + 新索引 + route 内部实现替换。回滚 = revert route 改动(storage 新方法保留无害)。
279
-
280
- ## 实施顺序(给 coder agent)
281
-
282
- 1. **Storage 层先**
283
- - a. 新增 3 个 aggregate 方法 + 4 个 task 方法 + sqlite.ts facade 转发
284
- - b. 新增索引(schema.sql + base.ts 同步)
285
- - c. 跑 `npx vitest run tests/unit/storage/ --reporter=verbose`
286
- 2. **补 routes-rules.test.ts**(基于旧实现先建立行为基线)
287
- 3. **一次改一个 route,每改完跑对应测试**
288
- - rules.ts → routes-rules.test.ts
289
- - skill-stats.ts → routes-skill-stats.test.ts
290
- - tasks.ts → routes-tasks.test.ts
291
- 4. **`npx tsc --noEmit` + 全量测试**
292
- 5. **可选基准脚本验证**
293
-
294
- ## 命名遵循(CLAUDE.md 约束 + 本 spec 扩展)
295
-
296
- - 单条查询:`getTask(id)` ✓
297
- - 列表/查询:`queryEventsByTaskId`、`queryInjectionsByTaskId`、`querySkillInvocationsByTaskWindow` ✓
298
- - 聚合(**本 spec 固化**):`aggregate*` — `aggregateRoutingStats`、`aggregateRoutingTrendByDay`、`aggregateSkillInvocationsBySkill`
299
- - 写入:本任务无新增
@@ -1,191 +0,0 @@
1
- # H2: getDatabase 越权 SQL 收敛到 Operations 层 Spec
2
-
3
- ## 目标
4
-
5
- 消除 `web/routes/`、`web/analytics/`、`cli/commands/`、`daemon/handlers/` 中对 `storage.getDatabase().prepare()` 的直写,按"查询动词 + 资源"命名下沉到对应 `*Operations` 类,以 `SQLiteStorage` facade 为唯一对外入口,便于后续 schema 重构。
6
-
7
- ## 调研结果
8
-
9
- ### 越权 SQL 清单(主线程封闭性扫描后修订:27 处)
10
-
11
- | 位置 | SQL 用途 | 表 | 应归属 |
12
- |---|---|---|---|
13
- | `daemon/handlers/stop.ts:154-158` | 按 session 统计 tool_name 调用 | events | EventOperations |
14
- | `daemon/handlers/stop.ts:163-168` | 按 session 统计 Agent/Task subagent_type 调用 | events | EventOperations |
15
- | `daemon/handlers/stop.ts:176-178` | 按 session 计数 skill 调用 | skill_invocations | SkillOperations |
16
- | `web/routes/stats.ts:13` | 全局 events 计数 | events | EventOperations |
17
- | `web/routes/stats.ts:14` | 全局 sessions 计数 | sessions | SessionOperations |
18
- | `web/routes/stats.ts:17-21` | Top 15 tool 使用分布 | events | EventOperations |
19
- | `web/routes/stats.ts:28-33` | 最近 7 天每日事件数 | events | EventOperations |
20
- | `web/routes/stats.ts:35-40` | 最近 7 天每日会话数 | sessions | SessionOperations |
21
- | `web/routes/stats.ts:50` | 全局 skill 调用计数 | skill_invocations | SkillOperations |
22
- | `web/routes/trace.ts:106-109` | 按 session 聚合 hook_type 分布 | events | EventOperations |
23
- | `web/routes/trace.ts:111-116` | 按 session 聚合 subagent_type 分布 | events | EventOperations |
24
- | `web/routes/trace.ts:118-120` | 按 session 列出 distinct skill_id | skill_invocations | SkillOperations |
25
- | **`cli/commands/trace.ts:115`** | hook_type 分布(CLI 版) | events | EventOperations |
26
- | **`cli/commands/trace.ts:124`** | subagent_type 分布(CLI 版) | events | EventOperations |
27
- | **`cli/commands/trace.ts:135`** | distinct skill_id(CLI 版) | skill_invocations | SkillOperations |
28
- | `web/analytics/drift-detector.ts:125-128` | 时间窗内 distinct skill 数 | skill_invocations | SkillOperations |
29
- | `web/analytics/drift-detector.ts:154-157` | 最近 7 天有事件的活跃日数 | events | EventOperations |
30
- | `web/analytics/drift-detector.ts:185-187` | 时间窗内 session 计数 | sessions | SessionOperations |
31
- | `web/analytics/drift-detector.ts:190-192` | 时间窗内 task 计数 | tasks | TaskOperations |
32
- | `web/analytics/weekly-report.ts:100-109` | 周内 events overview | events | EventOperations |
33
- | `web/analytics/weekly-report.ts:111-116` | 周内 distinct project_path | events | EventOperations |
34
- | `web/analytics/weekly-report.ts:118-122` | 周内 task 计数 | tasks | TaskOperations |
35
- | `web/analytics/weekly-report.ts:214-222` | 周内 PreToolUse top tools | events | EventOperations |
36
- | `web/analytics/weekly-report.ts:228-244` | 周内 PostToolUse 失败/总数 | events | EventOperations |
37
- | `web/analytics/weekly-report.ts:261-268` | 周内 file edit tool_input | events | EventOperations |
38
- | `web/analytics/anti-pattern-detector.ts:83-86` | 时间窗内全字段 events | events | EventOperations |
39
- | `web/analytics/anti-pattern-detector.ts:104-114` | 时间窗内 session 概览 | sessions | SessionOperations |
40
-
41
- **关键修订**:`cli/commands/trace.ts` 有 3 段与 web/routes/trace.ts 同模式的 SQL,调用同一组聚合方法。
42
-
43
- ### Operations 类现状
44
-
45
- | 类 | 文件 | 现有方法(节选) |
46
- |---|---|---|
47
- | EventOperations | `core/storage/events.ts` | writeEvent / queryEvents / countEvents / searchEvents |
48
- | SessionOperations | `core/storage/sessions.ts` | upsertSession / querySessions |
49
- | TaskOperations | `core/storage/tasks.ts` | writeTask / queryTasks / queryTasksFiltered |
50
- | SkillOperations | `core/storage/skills.ts` | writeSkillInvocation / aggregateSkillInvocationsBySkill |
51
- | RoutingOperations | `core/storage/routing.ts` | aggregateRoutingStats / aggregateRoutingTrendByDay |
52
-
53
- H1 已固化 `aggregate*` 命名模式。
54
-
55
- ### `getDatabase()` 调用方现状
56
-
57
- | 调用方 | 类型 | 处理 |
58
- |---|---|---|
59
- | `web/routes/{stats,trace}.ts` | 越权 | 消除 |
60
- | `web/analytics/*` | 越权 | 消除 |
61
- | `cli/commands/trace.ts` | 越权 | 消除 |
62
- | `daemon/handlers/stop.ts` | 越权 | 消除 |
63
- | 测试 fixture / migration | 合法 | 保留 |
64
-
65
- ### 测试覆盖现状
66
-
67
- | 模块 | 现有测试 | safety-net 评级 |
68
- |---|---|---|
69
- | `web/routes/stats.ts` | 无 | **必补** |
70
- | `web/routes/trace.ts` | 无 | **必补** |
71
- | `cli/commands/trace.ts` | 无 | 可补(跑得到的话) |
72
- | `web/analytics/*` | `tests/integration/web-analytics.integration.test.ts`(仅 200 + shape) | 增强字段值断言 |
73
- | `daemon/handlers/stop.ts` behavior summary | 无 | **必补**(fixture + 断言摘要) |
74
- | Operations 新增方法 | 无 | 每个新方法配单测 |
75
-
76
- ## 方案选择
77
-
78
- **方案 A(推荐)**:所有越权 SQL 下沉到 `*Operations`,作为聚合/计数方法暴露给 facade,调用方改用 facade。
79
-
80
- `getDatabase()` 处理:**保留 public** + jsdoc `@internal — Operations 子类使用。Routes/Handlers/Analytics 禁止调用,请使用 facade 方法。` 不改 protected(架构非继承)。
81
-
82
- ## 新增 Operations 方法清单
83
-
84
- ```ts
85
- // EventOperations(11 个)
86
- countAllEvents(): number;
87
- aggregateToolUsage(opts: { since?: string; limit?: number; hook_type?: 'PreToolUse' | 'PostToolUse' }): Array<{ tool_name: string; count: number }>;
88
- aggregateDailyEventCounts(opts: { since: string; until?: string }): Array<{ date: string; count: number }>;
89
- aggregateHookTypeBySession(session_id: string): Array<{ hook_type: string; count: number }>;
90
- aggregateAgentTypeBySession(session_id: string): Array<{ agent_type: string | null; count: number }>;
91
- aggregateToolUsageBySession(session_id: string): Array<{ tool_name: string; count: number }>;
92
- countActiveDays(opts: { since: string; until?: string }): number;
93
- aggregateOverviewByRange(opts: { since: string; until: string }): { event_count: number; session_count: number; day_count: number };
94
- queryDistinctProjects(opts: { since: string; until: string }): string[];
95
- aggregateToolFailureRate(opts: { since: string; until: string }): { post_total: number; failed: number };
96
- queryFileEditInputs(opts: { since: string; until: string; tool_names: string[] }): Array<{ tool_input: string }>;
97
- queryEventsByTimeRange(opts: { since: string; until?: string }): ForgeEvent[];
98
-
99
- // SessionOperations(4 个)
100
- countAllSessions(): number;
101
- aggregateDailySessionCounts(opts: { since: string; until?: string }): Array<{ date: string; count: number }>;
102
- querySessionsByTimeRange(opts: { since: string; until?: string }): SessionSummary[];
103
- countSessionsByRange(opts: { since: string; until?: string }): number;
104
-
105
- // TaskOperations(1 个)
106
- countTasksByRange(opts: { since: string; until?: string }): number;
107
-
108
- // SkillOperations(4 个)
109
- countAllSkillInvocations(): number;
110
- countSkillInvocationsBySession(session_id: string): number;
111
- countDistinctSkillsSince(since_ms: number): number;
112
- queryDistinctSkillIdsBySession(session_id: string): string[];
113
- ```
114
-
115
- **总计:~20 个新增方法**。命名 `count*` / `aggregate*` / `query*`。
116
-
117
- ## safety-net 设计
118
-
119
- | 测试文件 | 覆盖目标 | 状态 |
120
- |---|---|---|
121
- | `tests/integration/web-stats.integration.test.ts` | GET `/api/stats` 200 + totalEvents/totalSessions/toolUsage/dailyActivity/skillInvocations 字段 | **新增** |
122
- | `tests/integration/web-trace.integration.test.ts` | GET `/api/trace/:commit` 多分支(无 project / 非 git / 无 note / 有 note)+ sessions[] shape | **新增**(用 tmp git repo 或 mock) |
123
- | `src/tests/stop-handler-behavior-summary.test.ts` | StopHandler.generateBehaviorSummary 输出字符串断言 | **新增** |
124
- | `tests/integration/web-analytics.integration.test.ts` | 现有 shape + 加 fixture 数据断言关键字段值 | **增强** |
125
- | `src/tests/event-operations-aggregates.test.ts` | EventOperations 11 个新方法 | **新增** |
126
- | `src/tests/session-operations-aggregates.test.ts` | SessionOperations 4 个 | **新增** |
127
- | `src/tests/skill-operations-counts.test.ts` | SkillOperations 4 个 | **新增** |
128
-
129
- ## 改造范围
130
-
131
- | 文件 | 改动点 | 行数估计 |
132
- |---|---|---|
133
- | `core/storage/events.ts` | +11 方法 | +200 |
134
- | `core/storage/sessions.ts` | +4 方法 | +80 |
135
- | `core/storage/tasks.ts` | +1 方法 | +20 |
136
- | `core/storage/skills.ts` | +4 方法 | +60 |
137
- | `core/storage/sqlite.ts` | facade 转发 | +60 |
138
- | `daemon/handlers/stop.ts` | 删 db.prepare → facade | -25 / +15 |
139
- | `web/routes/stats.ts` | 全文重写无 SQL | -50 / +30 |
140
- | `web/routes/trace.ts` | SQL 段改 facade | -25 / +12 |
141
- | `cli/commands/trace.ts` | 3 段 SQL 改 facade | -20 / +10 |
142
- | `web/analytics/drift-detector.ts` | 4 段 SQL 改 facade | -25 / +15 |
143
- | `web/analytics/weekly-report.ts` | 6 段 SQL 改 facade | -55 / +30 |
144
- | `web/analytics/anti-pattern-detector.ts` | 2 段 SQL 改 facade | -30 / +12 |
145
- | **新增测试 7 文件** | safety-net + 聚合单测 | +600 |
146
-
147
- **总计:~13 文件改 + 7 文件新增,净 +750 / -230 ≈ 980 行**
148
-
149
- ## 风险与回滚
150
-
151
- | 风险 | 应对 |
152
- |---|---|
153
- | GROUP BY/ORDER BY/NULL 处理细节不一致 | safety-net 字段值断言;逐方法 diff 旧 SQL |
154
- | `LIKE '%error%'` 失败检测被新方法弱化 | weekly-report 失败率单测覆盖原 SQL 3 个 OR 条件 |
155
- | `date('now', '-7 days')` 与传入 since 字符串语义差异 | 新方法统一接收 ISO 字符串,调用方负责 now() 计算 |
156
- | 周报 file edit `IN ?` placeholders | `queryFileEditInputs({ tool_names })` 内部展开 |
157
- | 改动量大致命合并冲突 | 分多 commit,每 commit 独立可 revert |
158
-
159
- ## 实施顺序(refactor-safe 5 phase)
160
-
161
- ### Phase 1: safety-net(commit 1)
162
- 1. `tests/integration/web-stats.integration.test.ts` 新增
163
- 2. `tests/integration/web-trace.integration.test.ts` 新增(tmp git repo)
164
- 3. `src/tests/stop-handler-behavior-summary.test.ts` 新增
165
- 4. 增强 `web-analytics.integration.test.ts`
166
- 5. 跑全量确认 baseline 通过
167
-
168
- ### Phase 2: Operations 新方法(commit 2)
169
- 1. 4 个 Operations 类加方法
170
- 2. 4 个单测文件加 fixture + 断言
171
- 3. sqlite.ts facade 转发
172
- 4. 不删旧 SQL,并行存在
173
-
174
- ### Phase 3: 替换调用方(每文件独立 commit,共 7 commit)
175
- 1. stats.ts → 跑 stats 集成测试
176
- 2. trace.ts (web) → 跑 trace 集成测试
177
- 3. trace.ts (cli) → 同样断言(如有测试)
178
- 4. stop.ts → 跑 stop handler 单测
179
- 5. drift-detector.ts → 跑 web-analytics
180
- 6. weekly-report.ts → 同上
181
- 7. anti-pattern-detector.ts → 同上
182
-
183
- ### Phase 4: 收尾(commit 3)
184
- 1. `getDatabase()` 加 jsdoc 警告
185
- 2. `npx tsc --noEmit` + `npm test` 全量
186
- 3. 可选:CLAUDE.md 「常见陷阱」补 1 条
187
-
188
- ## 命名遵循
189
-
190
- - 计数 `count*` / 聚合 `aggregate*` / 列表 `query*`
191
- - 遵循 H1 已固化的 `aggregateRoutingStats` 等模式
@@ -1,76 +0,0 @@
1
- # H3: 删除 schema.sql inline fallback Spec
2
-
3
- ## 目标
4
- 消除 `SQLiteBase.initSchema()` 中残缺的 inline fallback,schema.sql 缺失时 fail-fast,杜绝静默降级导致的生产数据写炸。
5
-
6
- ## 涉及文件
7
- - `src/core/storage/base.ts`(主改)
8
- - `package.json`(build script 加 postbuild 校验)
9
- - `tests/unit/storage/schema-missing.test.ts`(新增)
10
- - `src/core/storage/index.ts` / `sqlite.ts` 类导出(无需改,构造签名不变)
11
-
12
- ## 现状分析
13
- - inline fallback 位置:`src/core/storage/base.ts:61-84`(`initSchema` 的 else 分支,70-82 行)
14
- - fallback 内容:仅建 `events` 1 张表 + 4 个旧索引(idx_events_session/project/timestamp/distilled)
15
- - schema.sql 真实:8 张活表(events / sessions / injections / tasks / task_events / routing_events / token_usage / skill_invocations)+ 33 个 CREATE TABLE/INDEX 语句,含 FK ON DELETE CASCADE 与若干复合索引
16
- - 缺漏表:sessions / injections / tasks / task_events / routing_events / token_usage / skill_invocations 全部缺失 — 一旦走 fallback,所有 routing/skill/task/token 路径首次 prepared statement 即报 `no such table`
17
- - npm 发布拷贝:`package.json:13` 的 build script —
18
- `cp src/core/storage/schema.sql dist/core/storage/schema.sql`(裸 `cp`,无失败检测,且依赖前置 `tsc` 已创建 `dist/core/storage/` 目录)
19
-
20
- ## 方案选择
21
-
22
- | 方案 | 改动量 | 优点 | 缺点 |
23
- |------|------|------|------|
24
- | A 删 fallback + fail-fast | 小(~15 行) | 简单;schema 缺失立即抛错 | 单点失败:发布翻车一次即生产 daemon 起不来(但 silent corruption 更糟) |
25
- | B 嵌入 schema 为 TS 常量 | 中(新增构建步骤 + 1 文件) | 彻底脱离运行时文件依赖;npm 安装零拷贝 | tsc 无 raw-loader;要么手写常量易漂移,要么加 prebuild 脚本生成 `schema-embedded.ts` |
26
- | C A + postbuild 校验 | 小(~20 行 + 1 行脚本) | 删 fallback 防 silent failure;postbuild 校验防发布事故;不引入构建复杂度 | 仍依赖运行时 fs(开发期问题不大) |
27
-
28
- **推荐:C**
29
-
30
- 理由:B 的常量化听起来最干净,但本项目用 `tsc` 直接编译,引入 codegen 脚本会增加 prebuild 链路(且 schema.sql 改动频率不高,收益不匹配复杂度)。A 解决了核心问题(不再 silent),但发布事故仍可能爆。C 用一行 `test -f` 把发布事故拦截在 `npm run build` 阶段,是性价比最高的组合。
31
-
32
- ## 设计细节(方案 C)
33
-
34
- **改动 1:`src/core/storage/base.ts` `initSchema()` 重写**
35
- - 删除 70-82 行 inline fallback
36
- - 删除 `existsSync(schemaPath)` 分支判断;改为:若文件不存在或读取失败,抛 `Error(`[SQLiteStorage] schema.sql not found at ${schemaPath}. ...`)`
37
- - 错误信息示例:
38
- ```
39
- [SQLiteStorage] schema.sql not found at /path/to/dist/core/storage/schema.sql.
40
- This indicates a broken build/install. Run `npm run build` or reinstall the package.
41
- ```
42
- - 更新文件头注释:删 "或 inline fallback"
43
-
44
- **改动 2:`package.json` build script**
45
- - 在 build 命令末尾追加 `&& test -f dist/core/storage/schema.sql || (echo "[build] FATAL: dist/core/storage/schema.sql missing" && exit 1)`
46
- - 拷贝命令保留原样(一次失败立即被 test -f 抓出来)
47
-
48
- **改动 3:注释清理**
49
- - `base.ts` 行 6 注释更新为"加载 schema.sql(缺失则抛错)"
50
- - 文件头注释列表同步
51
-
52
- ## 测试策略
53
-
54
- 新增 `tests/unit/storage/schema-missing.test.ts`:
55
-
56
- | case | 输入 | 预期 |
57
- |------|------|------|
58
- | 1 | 正常环境(schema.sql 存在)| `new SQLiteStorage(tmpDb)` 成功,`sqlite_master` 有 `sessions` 表 |
59
- | 2 | 临时 rename `dist/core/storage/schema.sql` 或 mock `readFileSync` 抛错 | 构造抛 Error,message 含 `schema.sql not found`;**断言不存在 events 表**(确认未走旧 fallback) |
60
-
61
- 实现要点:
62
- - case 2 不能真改 dist/(影响其他测试),用 `vi.mock('node:fs', ...)` 截 `existsSync` 返回 false
63
- - 现有 `tests/unit/storage/migration-idempotent.test.ts` 不变,验证回归(schema.sql 存在路径仍 idempotent)
64
- - 跑 `npx vitest run tests/unit/storage --reporter=verbose` + `npx tsc --noEmit`
65
-
66
- ## 风险与回滚
67
-
68
- - **风险 1(开发期)**:开发者本地未跑 `npm run build`,直接 `node src/cli/index.js` 这种从 src 启动?— 实际启动路径都从 `dist/` 走(`bin` 指向 `dist/cli/index.js`),不存在 src 直跑场景;vitest 跑测试用的是源码路径下的 schema.sql(`src/core/storage/schema.sql`),同样存在,无影响
69
- - **风险 2(首次升级)**:旧版本用户残留 dist 缺 schema.sql?— 升级走 `npm i`,`prebuild` 已 `rm -rf dist`,必然重 build;新 postbuild 校验拦截
70
- - **回滚**:纯增量改动;revert 单 commit 即可恢复旧 fallback 行为
71
-
72
- ## 命名遵循
73
-
74
- - 测试文件 `schema-missing.test.ts`:kebab-case ✓
75
- - 不引入新函数/常量;保留 `initSchema()` 私有方法名 ✓
76
- - 错误信息以 `[SQLiteStorage]` 前缀(与现有 logger 调用一致)✓