@winspan/claude-forge 8.53.2 → 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 (390) 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 +7 -3
  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/storage/events.d.ts.map +1 -1
  11. package/dist/core/storage/events.js +0 -1
  12. package/dist/core/storage/events.js.map +1 -1
  13. package/dist/core/storage/maintenance.d.ts +25 -3
  14. package/dist/core/storage/maintenance.d.ts.map +1 -1
  15. package/dist/core/storage/maintenance.js +33 -4
  16. package/dist/core/storage/maintenance.js.map +1 -1
  17. package/dist/core/storage/routing.d.ts +4 -0
  18. package/dist/core/storage/routing.d.ts.map +1 -1
  19. package/dist/core/storage/routing.js +10 -4
  20. package/dist/core/storage/routing.js.map +1 -1
  21. package/dist/core/storage/sessions.d.ts +17 -0
  22. package/dist/core/storage/sessions.d.ts.map +1 -1
  23. package/dist/core/storage/sessions.js +64 -0
  24. package/dist/core/storage/sessions.js.map +1 -1
  25. package/dist/core/storage/skills.d.ts +4 -0
  26. package/dist/core/storage/skills.d.ts.map +1 -1
  27. package/dist/core/storage/skills.js +10 -2
  28. package/dist/core/storage/skills.js.map +1 -1
  29. package/dist/core/storage/sqlite.d.ts +5 -0
  30. package/dist/core/storage/sqlite.d.ts.map +1 -1
  31. package/dist/core/storage/sqlite.js +6 -0
  32. package/dist/core/storage/sqlite.js.map +1 -1
  33. package/dist/core/storage/tasks.d.ts.map +1 -1
  34. package/dist/core/storage/tasks.js +2 -0
  35. package/dist/core/storage/tasks.js.map +1 -1
  36. package/dist/core/types.d.ts +7 -0
  37. package/dist/core/types.d.ts.map +1 -1
  38. package/dist/daemon/index.d.ts.map +1 -1
  39. package/dist/daemon/index.js +19 -4
  40. package/dist/daemon/index.js.map +1 -1
  41. package/dist/skills/registry.d.ts.map +1 -1
  42. package/dist/skills/registry.js +13 -2
  43. package/dist/skills/registry.js.map +1 -1
  44. package/dist/skills/semantic-matcher.d.ts +2 -2
  45. package/dist/skills/semantic-matcher.d.ts.map +1 -1
  46. package/dist/skills/semantic-matcher.js +14 -19
  47. package/dist/skills/semantic-matcher.js.map +1 -1
  48. package/dist/skills/upgrade-engine.d.ts +3 -1
  49. package/dist/skills/upgrade-engine.d.ts.map +1 -1
  50. package/dist/skills/upgrade-engine.js +25 -14
  51. package/dist/skills/upgrade-engine.js.map +1 -1
  52. package/dist/web/analytics/weekly-report.d.ts.map +1 -1
  53. package/dist/web/analytics/weekly-report.js +21 -29
  54. package/dist/web/analytics/weekly-report.js.map +1 -1
  55. package/dist/web/routes/patch.d.ts.map +1 -1
  56. package/dist/web/routes/patch.js +32 -2
  57. package/dist/web/routes/patch.js.map +1 -1
  58. package/dist/web/routes/sessions.d.ts.map +1 -1
  59. package/dist/web/routes/sessions.js +9 -7
  60. package/dist/web/routes/sessions.js.map +1 -1
  61. package/dist/web/routes/trace.d.ts.map +1 -1
  62. package/dist/web/routes/trace.js +2 -3
  63. package/dist/web/routes/trace.js.map +1 -1
  64. package/dist/web/server.d.ts.map +1 -1
  65. package/dist/web/server.js +3 -2
  66. package/dist/web/server.js.map +1 -1
  67. package/package.json +12 -2
  68. package/scripts/postinstall.cjs +21 -0
  69. package/.claude/CLAUDE.md +0 -17
  70. package/.eslintrc.js +0 -23
  71. package/.prettierrc +0 -8
  72. package/ARCHITECTURE_ISSUES.md +0 -249
  73. package/CLAUDE.md +0 -265
  74. package/CLAUDE.md.backup +0 -488
  75. package/docs/concurrent-agents.md +0 -129
  76. package/docs/design/architecture-review-20260516.md +0 -232
  77. package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +0 -219
  78. package/docs/design/h1-storage-aggregation-spec-20260518-1121.md +0 -299
  79. package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +0 -191
  80. package/docs/design/h3-fallback-removal-spec-20260518-1245.md +0 -76
  81. package/docs/design/h4-index-dedup-spec-20260518-1230.md +0 -109
  82. package/docs/design/h6-services-migration-spec-20260518-1355.md +0 -82
  83. package/docs/design/hook-failure-queue-spec-20260516-1530.md +0 -204
  84. package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +0 -106
  85. package/docs/design/m10-forge-paths-spec-20260518-1320.md +0 -121
  86. package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +0 -131
  87. package/docs/design/m7-routing-event-association-spec-20260518-1545.md +0 -103
  88. package/docs/design/project-path-gitroot-spec-20260518-1715.md +0 -134
  89. package/docs/design/refactor-phase1-spec-20260515-1600.md +0 -543
  90. package/docs/design/refactor-phase2-spec-20260515-1700.md +0 -424
  91. package/docs/design/skill-ai-upgrade-spec-20260518-1930.md +0 -297
  92. package/docs/design/task-active-gc-spec-20260518-1745.md +0 -146
  93. package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +0 -208
  94. package/docs/implementation/daemon-skill-sync-changelog-20260518-2000.md +0 -22
  95. package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +0 -104
  96. package/docs/implementation/h1-storage-aggregation-changelog-20260518-1121.md +0 -82
  97. package/docs/implementation/h2-final-changelog-20260518-1530.md +0 -61
  98. package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +0 -70
  99. package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +0 -120
  100. package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +0 -71
  101. package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +0 -71
  102. package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +0 -60
  103. package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +0 -46
  104. package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +0 -46
  105. package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +0 -196
  106. package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +0 -56
  107. package/docs/implementation/l1-swarm-protocol-extract-changelog-20260518-1605.md +0 -45
  108. package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +0 -63
  109. package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +0 -38
  110. package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +0 -58
  111. package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +0 -60
  112. package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +0 -43
  113. package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +0 -56
  114. package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +0 -69
  115. package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +0 -63
  116. package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +0 -354
  117. package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +0 -421
  118. package/docs/implementation/skill-ai-upgrade-changelog-20260518-1930.md +0 -49
  119. package/docs/implementation/task-active-gc-changelog-20260518-1745.md +0 -35
  120. package/docs/implementation/task-title-summary-changelog-20260518-1130.md +0 -39
  121. package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +0 -22
  122. package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +0 -72
  123. package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +0 -56
  124. package/docs/reviews/claudemd-template-sync.md +0 -54
  125. package/docs/reviews/task-title-summary.md +0 -92
  126. package/docs/reviews/tasks-detail-back-loses-filters.md +0 -58
  127. package/docs/reviews/tasks-filter-pagination.md +0 -80
  128. package/docs/reviews/tasks-page-white-screen-hotfix.md +0 -126
  129. package/docs/ruflo-learning-strategy.md +0 -322
  130. package/docs/skills-deduplication-analysis.md +0 -83
  131. package/docs/skills-multiformat-support.md +0 -177
  132. package/docs/skills-third-party.md +0 -183
  133. package/docs/testing/tasks-filter-pagination-test-report.md +0 -86
  134. package/forge +0 -321
  135. package/playwright.config.ts +0 -40
  136. package/scripts/demo-v2.ts +0 -91
  137. package/scripts/dev-daemon.sh +0 -232
  138. package/scripts/dev-web.ts +0 -109
  139. package/scripts/e2e-mcp-link.ts +0 -423
  140. package/scripts/e2e-methodology-quality.ts +0 -253
  141. package/scripts/e2e-routing.ts +0 -456
  142. package/scripts/e2e-user-methodology.ts +0 -326
  143. package/scripts/e2e-web-workflows.ts +0 -299
  144. package/scripts/migrate-legacy-to-dynamic.sql +0 -108
  145. package/scripts/regenerate-execution-docs.ts +0 -116
  146. package/scripts/sync-agent-skills.ts +0 -193
  147. package/scripts/test-hook.sh +0 -71
  148. package/scripts/verify-skill-loading.ts +0 -62
  149. package/src/claudemd/claudemd-generator.ts +0 -568
  150. package/src/claudemd/convention-extractor.ts +0 -69
  151. package/src/claudemd/index.ts +0 -35
  152. package/src/claudemd/persona-manager.ts +0 -88
  153. package/src/claudemd/resume-manager.ts +0 -236
  154. package/src/claudemd/tech-detector.ts +0 -220
  155. package/src/claudemd/templates/swarm-protocol.md +0 -222
  156. package/src/cli/commands/claudemd.ts +0 -84
  157. package/src/cli/commands/config.ts +0 -46
  158. package/src/cli/commands/daemon.ts +0 -310
  159. package/src/cli/commands/executions.ts +0 -115
  160. package/src/cli/commands/init.ts +0 -204
  161. package/src/cli/commands/logs.ts +0 -181
  162. package/src/cli/commands/mcp.ts +0 -242
  163. package/src/cli/commands/menu.ts +0 -357
  164. package/src/cli/commands/skills.ts +0 -328
  165. package/src/cli/commands/stats.ts +0 -73
  166. package/src/cli/commands/status.ts +0 -69
  167. package/src/cli/commands/template.ts +0 -77
  168. package/src/cli/commands/trace.ts +0 -148
  169. package/src/cli/index.ts +0 -42
  170. package/src/cli/init/hook-manager.ts +0 -132
  171. package/src/core/ai/provider.ts +0 -308
  172. package/src/core/ai/types.ts +0 -51
  173. package/src/core/config.ts +0 -124
  174. package/src/core/constants.ts +0 -67
  175. package/src/core/event-fields.ts +0 -32
  176. package/src/core/queue/index.ts +0 -192
  177. package/src/core/storage/base.ts +0 -302
  178. package/src/core/storage/events.ts +0 -434
  179. package/src/core/storage/injections.ts +0 -78
  180. package/src/core/storage/maintenance.ts +0 -59
  181. package/src/core/storage/migrations/002_add_skill_tracking.sql +0 -6
  182. package/src/core/storage/migrations/003_add_skill_invocations.sql +0 -23
  183. package/src/core/storage/performance-indexes.sql +0 -23
  184. package/src/core/storage/routing.ts +0 -322
  185. package/src/core/storage/rows.ts +0 -112
  186. package/src/core/storage/schema.sql +0 -224
  187. package/src/core/storage/sessions.ts +0 -168
  188. package/src/core/storage/skills.ts +0 -233
  189. package/src/core/storage/sqlite.ts +0 -293
  190. package/src/core/storage/tasks.ts +0 -318
  191. package/src/core/storage/token-usage.ts +0 -93
  192. package/src/core/types.ts +0 -181
  193. package/src/core/utils/error-handler.ts +0 -257
  194. package/src/core/utils/forge-resume-block.ts +0 -74
  195. package/src/core/utils/format.ts +0 -69
  196. package/src/core/utils/git.ts +0 -23
  197. package/src/core/utils/logger.ts +0 -134
  198. package/src/core/utils/lru-cache.ts +0 -54
  199. package/src/core/utils/path.ts +0 -19
  200. package/src/core/utils/session.ts +0 -26
  201. package/src/core/utils/time.ts +0 -37
  202. package/src/core/utils/token-tracker.ts +0 -97
  203. package/src/daemon/event-parser.ts +0 -36
  204. package/src/daemon/handlers/history-exporter.ts +0 -117
  205. package/src/daemon/handlers/post-tool-use.ts +0 -54
  206. package/src/daemon/handlers/stop.ts +0 -208
  207. package/src/daemon/handlers/user-prompt.ts +0 -178
  208. package/src/daemon/hook-sync.ts +0 -91
  209. package/src/daemon/index.ts +0 -312
  210. package/src/daemon/launchd/com.claude-forge.daemon.plist.template +0 -47
  211. package/src/daemon/launchd-installer.ts +0 -260
  212. package/src/daemon/lifecycle.ts +0 -128
  213. package/src/daemon/router.ts +0 -40
  214. package/src/daemon/server.ts +0 -196
  215. package/src/daemon/services/task-segmenter.ts +0 -112
  216. package/src/daemon/skill-sync.ts +0 -88
  217. package/src/hooks/hook-lib.sh +0 -118
  218. package/src/hooks/notification.sh +0 -35
  219. package/src/hooks/post-tool-use.sh +0 -61
  220. package/src/hooks/pre-tool-use.sh +0 -63
  221. package/src/hooks/stop.sh +0 -43
  222. package/src/hooks/user-prompt-submit.sh +0 -69
  223. package/src/mcp/server.ts +0 -322
  224. package/src/skills/index.ts +0 -2
  225. package/src/skills/invocation-guard.ts +0 -177
  226. package/src/skills/matcher.ts +0 -148
  227. package/src/skills/official/code-simplifier.md +0 -52
  228. package/src/skills/official/find-skills.md +0 -142
  229. package/src/skills/official/official-api-design.md +0 -30
  230. package/src/skills/official/official-architecture-decision.md +0 -41
  231. package/src/skills/official/official-bmad.md +0 -118
  232. package/src/skills/official/official-db-schema-design.md +0 -34
  233. package/src/skills/official/official-debug.md +0 -25
  234. package/src/skills/official/official-doc-driven.md +0 -31
  235. package/src/skills/official/official-harness-engineering.md +0 -108
  236. package/src/skills/official/official-performance-optimization.md +0 -30
  237. package/src/skills/official/official-pr-review.md +0 -35
  238. package/src/skills/official/official-release-checklist.md +0 -30
  239. package/src/skills/official/official-security-hardening.md +0 -32
  240. package/src/skills/official/official-spec-driven-design.md +0 -31
  241. package/src/skills/official/planning-with-files.md +0 -241
  242. package/src/skills/official/ui-ux-pro-max.md +0 -105
  243. package/src/skills/official/webapp-testing.md +0 -96
  244. package/src/skills/official-skills.ts +0 -89
  245. package/src/skills/registry.ts +0 -355
  246. package/src/skills/semantic-matcher.ts +0 -234
  247. package/src/skills/tools/pipeline-suggest.ts +0 -226
  248. package/src/skills/tools/skill-invoke.ts +0 -168
  249. package/src/skills/tools/skill-list.ts +0 -59
  250. package/src/skills/upgrade-engine.ts +0 -541
  251. package/src/skills/upgrade-prompt.ts +0 -84
  252. package/src/templates/go.yaml +0 -53
  253. package/src/templates/python.yaml +0 -59
  254. package/src/templates/react.yaml +0 -55
  255. package/src/templates/template-manager.ts +0 -170
  256. package/src/web/analytics/anti-pattern-detector.ts +0 -367
  257. package/src/web/analytics/drift-detector.ts +0 -219
  258. package/src/web/analytics/weekly-report.ts +0 -431
  259. package/src/web/auth-middleware.ts +0 -54
  260. package/src/web/routes/_helpers.ts +0 -34
  261. package/src/web/routes/ai.ts +0 -204
  262. package/src/web/routes/auth.ts +0 -22
  263. package/src/web/routes/drift.ts +0 -25
  264. package/src/web/routes/error-handler.ts +0 -120
  265. package/src/web/routes/events.ts +0 -47
  266. package/src/web/routes/insights.ts +0 -43
  267. package/src/web/routes/patch.ts +0 -117
  268. package/src/web/routes/reports.ts +0 -34
  269. package/src/web/routes/rules.ts +0 -76
  270. package/src/web/routes/sessions.ts +0 -250
  271. package/src/web/routes/skill-stats.ts +0 -92
  272. package/src/web/routes/skills.ts +0 -350
  273. package/src/web/routes/static.ts +0 -67
  274. package/src/web/routes/stats.ts +0 -50
  275. package/src/web/routes/status.ts +0 -30
  276. package/src/web/routes/tasks.ts +0 -193
  277. package/src/web/routes/token-usage.ts +0 -20
  278. package/src/web/routes/trace.ts +0 -126
  279. package/src/web/routes/types.ts +0 -57
  280. package/src/web/server.ts +0 -134
  281. package/src/web/ssrf-guard.ts +0 -112
  282. package/src/web/static/index.html +0 -3251
  283. package/src/web/static/vendor/chart.umd.min.js +0 -20
  284. package/tests/e2e/dashboard.spec.ts +0 -205
  285. package/tests/e2e/routing-skill-e2e.test.ts +0 -39
  286. package/tests/helpers/mock-ai.ts +0 -92
  287. package/tests/helpers/mock-storage.ts +0 -159
  288. package/tests/integration/claudemd-generator.test.ts +0 -90
  289. package/tests/integration/queue-replay.integration.test.ts +0 -193
  290. package/tests/integration/tasks-filter.integration.test.ts +0 -154
  291. package/tests/integration/web-analytics.integration.test.ts +0 -133
  292. package/tests/integration/web-stats.integration.test.ts +0 -135
  293. package/tests/integration/web-trace.integration.test.ts +0 -175
  294. package/tests/performance/database.benchmark.ts +0 -161
  295. package/tests/semantic-matcher.test.ts +0 -99
  296. package/tests/skill-matcher.test.ts +0 -110
  297. package/tests/unit/ai-provider-retry.test.ts +0 -194
  298. package/tests/unit/ai-provider-vision.test.ts +0 -224
  299. package/tests/unit/claudemd-generator.test.ts +0 -68
  300. package/tests/unit/cli-mcp.test.ts +0 -141
  301. package/tests/unit/core/forge-paths.test.ts +0 -99
  302. package/tests/unit/daemon/hook-sync.test.ts +0 -71
  303. package/tests/unit/daemon/post-tool-use.test.ts +0 -121
  304. package/tests/unit/daemon/skill-sync.test.ts +0 -75
  305. package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +0 -202
  306. package/tests/unit/daemon/task-segmenter-recover.test.ts +0 -84
  307. package/tests/unit/event-fields.test.ts +0 -88
  308. package/tests/unit/event-parser.test.ts +0 -55
  309. package/tests/unit/handlers.test.ts +0 -171
  310. package/tests/unit/hooks/resolve-project-path.test.ts +0 -122
  311. package/tests/unit/invocation-guard.test.ts +0 -125
  312. package/tests/unit/queue.test.ts +0 -272
  313. package/tests/unit/router.test.ts +0 -138
  314. package/tests/unit/security.test.ts +0 -128
  315. package/tests/unit/skill-invocations-workflow.test.ts +0 -495
  316. package/tests/unit/skill-registry.test.ts +0 -94
  317. package/tests/unit/skills/invocation-guard-ttl.test.ts +0 -211
  318. package/tests/unit/skills/official-skills-loader.test.ts +0 -126
  319. package/tests/unit/skills/registry-multiformat.test.ts +0 -92
  320. package/tests/unit/skills/upgrade-engine-parse.test.ts +0 -138
  321. package/tests/unit/skills/upgrade-engine.test.ts +0 -401
  322. package/tests/unit/skills/upgrade-prompt.test.ts +0 -89
  323. package/tests/unit/socket-server.test.ts +0 -183
  324. package/tests/unit/storage/event-operations-aggregates.test.ts +0 -342
  325. package/tests/unit/storage/migration-idempotent.test.ts +0 -304
  326. package/tests/unit/storage/routing-aggregates.test.ts +0 -276
  327. package/tests/unit/storage/routing.test.ts +0 -117
  328. package/tests/unit/storage/schema-missing.test.ts +0 -81
  329. package/tests/unit/storage/session-operations-aggregates.test.ts +0 -120
  330. package/tests/unit/storage/sessions-aggregate.test.ts +0 -435
  331. package/tests/unit/storage/skill-operations-counts.test.ts +0 -106
  332. package/tests/unit/storage/skills-aggregates.test.ts +0 -104
  333. package/tests/unit/storage/sqlite-refactor-harness.test.ts +0 -314
  334. package/tests/unit/storage/task-operations-counts.test.ts +0 -46
  335. package/tests/unit/storage/tasks-getById.test.ts +0 -343
  336. package/tests/unit/storage/tasks-stale-gc.test.ts +0 -86
  337. package/tests/unit/storage.test.ts +0 -172
  338. package/tests/unit/token-usage.test.ts +0 -144
  339. package/tests/unit/type-guards.test.ts +0 -201
  340. package/tests/unit/utils/format.test.ts +0 -189
  341. package/tests/unit/utils/session.test.ts +0 -89
  342. package/tests/unit/utils/time.test.ts +0 -112
  343. package/tests/unit/web/navigation-back-contract.test.ts +0 -134
  344. package/tests/unit/web/routes-auth.test.ts +0 -93
  345. package/tests/unit/web/routes-events.test.ts +0 -101
  346. package/tests/unit/web/routes-rules.test.ts +0 -182
  347. package/tests/unit/web/routes-sessions.test.ts +0 -181
  348. package/tests/unit/web/routes-skill-stats.test.ts +0 -179
  349. package/tests/unit/web/routes-stats.test.ts +0 -92
  350. package/tests/unit/web/routes-tasks.test.ts +0 -385
  351. package/tests/unit/web/task-title-contract.test.ts +0 -210
  352. package/tests/unit/web/tasks-component-contract.test.ts +0 -179
  353. package/tsconfig.json +0 -22
  354. package/vitest.config.ts +0 -21
  355. package/vitest.integration.config.ts +0 -16
  356. package/web/CLAUDE.md +0 -20
  357. package/web/index.html +0 -13
  358. package/web/package-lock.json +0 -4854
  359. package/web/package.json +0 -35
  360. package/web/postcss.config.js +0 -6
  361. package/web/src/App.tsx +0 -110
  362. package/web/src/components/CodeBlock.tsx +0 -31
  363. package/web/src/components/Confirm.tsx +0 -96
  364. package/web/src/components/Drawer.tsx +0 -60
  365. package/web/src/components/Layout.tsx +0 -145
  366. package/web/src/components/MarkdownRenderer.tsx +0 -77
  367. package/web/src/components/SearchInput.tsx +0 -31
  368. package/web/src/components/SessionDetailContent.tsx +0 -157
  369. package/web/src/components/Toast.tsx +0 -92
  370. package/web/src/index.css +0 -19
  371. package/web/src/main.tsx +0 -31
  372. package/web/src/pages/AIConfig.tsx +0 -233
  373. package/web/src/pages/Dashboard.tsx +0 -572
  374. package/web/src/pages/Events.tsx +0 -271
  375. package/web/src/pages/Reports.tsx +0 -428
  376. package/web/src/pages/SessionDetail.tsx +0 -162
  377. package/web/src/pages/Sessions.tsx +0 -205
  378. package/web/src/pages/Skills.tsx +0 -180
  379. package/web/src/pages/TaskDetail.tsx +0 -515
  380. package/web/src/pages/Tasks.tsx +0 -415
  381. package/web/src/utils/auth.ts +0 -59
  382. package/web/src/utils/export.ts +0 -54
  383. package/web/src/utils/navigation.ts +0 -25
  384. package/web/src/utils/task-title.ts +0 -49
  385. package/web/src/utils/time.ts +0 -13
  386. package/web/tailwind.config.js +0 -11
  387. package/web/tsconfig.json +0 -21
  388. package/web/tsconfig.node.json +0 -10
  389. package/web/vite.config.ts +0 -76
  390. 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 调用一致)✓