@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,104 +0,0 @@
1
- # Changelog: Official Skills 数据分离 + UserPromptHandler Set 内存泄漏修复
2
-
3
- **日期**: 2026-05-16
4
- **Spec**: `docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md`
5
-
6
- ---
7
-
8
- ## 实际改动文件清单
9
-
10
- ### 新建文件
11
-
12
- | 文件路径 | 行数 | 说明 |
13
- |----------|------|------|
14
- | `src/skills/official/official-harness-engineering.md` | 91 | Harness Engineering 方法论 |
15
- | `src/skills/official/official-spec-driven-design.md` | 28 | Spec-Driven Design |
16
- | `src/skills/official/official-architecture-decision.md` | 22 | ADR 模板(截断版,与原始 content 一致)|
17
- | `src/skills/official/official-api-design.md` | 19 | API 设计规范(截断版)|
18
- | `src/skills/official/official-db-schema-design.md` | 19 | DB Schema 设计(截断版)|
19
- | `src/skills/official/official-pr-review.md` | 32 | PR 审查清单(截断版)|
20
- | `src/skills/official/official-debug.md` | 18 | 调试工作流(截断版)|
21
- | `src/skills/official/official-performance-optimization.md` | 30 | 性能优化 |
22
- | `src/skills/official/official-security-hardening.md` | 27 | 安全加固(截断版)|
23
- | `src/skills/official/official-release-checklist.md` | 30 | 发布清单 |
24
- | `src/skills/official/official-doc-driven.md` | 28 | 文档驱动开发 |
25
- | `src/skills/official/planning-with-files.md` | 35 | Manus 风格任务规划(截断版)|
26
- | `src/skills/official/code-simplifier.md` | 17 | 代码简化(截断版)|
27
- | `src/skills/official/find-skills.md` | 24 | 技能发现(截断版)|
28
- | `src/skills/official/webapp-testing.md` | 12 | Web 应用测试(截断版)|
29
- | `src/skills/official/ui-ux-pro-max.md` | 19 | UI/UX 设计工具(截断版)|
30
- | `src/skills/official/official-bmad.md` | 90 | BMAD 方法论 |
31
- | `tests/unit/skills/official-skills-loader.test.ts` | 113 | loadOfficialSkills 单元测试(7 个 case)|
32
-
33
- ### 修改文件
34
-
35
- | 文件路径 | 改动 | 说明 |
36
- |----------|------|------|
37
- | `src/skills/official-skills.ts` | -700行 +73行 | 删除 OFFICIAL_SKILLS 数组;保留 OfficialSkill 接口和 OFFICIAL_SKILL_KEYWORDS;新增 loadOfficialSkills(builtinDir) |
38
- | `src/skills/registry.ts` | +30行 | 新增 resolveBuiltinDir(); scan() 第 1 段改用 loadOfficialSkills; import 更新 |
39
- | `src/cli/commands/skills.ts` | +7行 | 移除 OFFICIAL_SKILLS import;新增 resolveBuiltinDir(); syncSkills 改用 loadOfficialSkills |
40
- | `src/daemon/handlers/user-prompt.ts` | +40行 | Set 改 Map<string,number>; 新增 MAX_INJECTION_KEYS=1000; hasInjected/markInjected 私有方法; clearSession 公共方法 |
41
- | `src/daemon/handlers/stop.ts` | +15行 | import UserPromptHandler 类型; 构造函数增加可选参数 userPromptHandler; Step 5 调用 clearSession |
42
- | `src/daemon/index.ts` | +5行 | 将 userPromptHandler 实例传入 StopHandler 构造函数 |
43
- | `package.json` | +1行 | build 脚本追加 `mkdir -p dist/skills/official && cp src/skills/official/*.md dist/skills/official/` |
44
- | `tests/unit/skill-registry.test.ts` | +2行 | 断言数量从 >= 16 改为 >= 17(两处) |
45
- | `tests/unit/handlers.test.ts` | +92行 | 新增 3 个 UserPromptHandler 测试 case |
46
-
47
- ---
48
-
49
- ## 与 Spec 的偏差
50
-
51
- ### 偏差 1:Skill 数量是 17,不是 19
52
- Spec 说"共 19 个 skill",但 `OFFICIAL_SKILLS` 数组实际只有 17 个条目(缺少 `official-tdd` 和 `official-refactor`,这两个仅在 `OFFICIAL_SKILL_KEYWORDS` 中有 keyword 映射但没有对应的 skill 定义)。实际创建了 17 个 `.md` 文件。测试断言改为 `>= 17`。
53
-
54
- ### 偏差 2:部分 skill 内容截断
55
- 原始 `OFFICIAL_SKILLS` 数组中有 11 个 skill 的 `content` 字段以 `\`` 结尾(截断的 template literal)。这是源码的现有状态(非本次引入)。`.md` 文件完整保留了这些截断内容,与原有行为一致。这些截断是原始数据的一部分,不影响 skill 加载逻辑。
56
-
57
- ### 偏差 3:registry.ts 中 skill 的 path 字段构造
58
- Spec 建议使用 `resolveBuiltinDir() + '/' + officialSkill.name + '.md'` 作为路径。实际实现中每次调用 `resolveBuiltinDir()` 会重新计算,考虑到这是纯计算无副作用,对性能无影响。若有性能顾虑可缓存该值(已注释在代码中作为 TODO)。
59
-
60
- ### 偏差 4:loadOfficialSkills content 字段包含完整文件(含 frontmatter)
61
- Spec 中未明确 `content` 字段是否包含 frontmatter。registry 的现有用户 skill 逻辑(`body.trim()`)只包含 body。为保持与原有 OFFICIAL_SKILLS 行为一致(原 content 字段包含 frontmatter),`loadOfficialSkills` 返回的 `content` 字段设为完整文件内容(`raw`),而非仅 body。这样 skill 注入时内容与之前完全一致。
62
-
63
- ---
64
-
65
- ## 测试结果
66
-
67
- ### 执行的测试
68
- ```
69
- npx vitest run tests/unit/skill-registry.test.ts --reporter=verbose
70
- npx vitest run tests/unit/skills/ --reporter=verbose
71
- npx vitest run tests/unit/handlers.test.ts --reporter=verbose
72
- npx tsc --noEmit
73
- npm test -- --reporter=dot
74
- ```
75
-
76
- ### 结果汇总
77
-
78
- | 测试文件 | 状态 | 测试数 |
79
- |----------|------|--------|
80
- | `tests/unit/skill-registry.test.ts` | 全部通过 | 6/6 |
81
- | `tests/unit/skills/registry-multiformat.test.ts` | 全部通过 | 27/27 |
82
- | `tests/unit/skills/official-skills-loader.test.ts` | 全部通过 | 7/7 |
83
- | `tests/unit/handlers.test.ts` | 全部通过 | 7/7(新增 3 个)|
84
- | `tests/unit/skills/invocation-guard-ttl.test.ts` | 全部通过 | — |
85
- | TypeScript (`tsc --noEmit`) | 无错误 | — |
86
- | 全量测试 (`npm test`) | 291/294 通过 | 2 文件失败 |
87
-
88
- ### 预存在的失败(与本次改动无关)
89
- - `tests/unit/web/routes-tasks.test.ts`(2 个 case 失败):UUID 格式验证错误,与 storage 层有关
90
- - `tests/unit/storage/sqlite-refactor-harness.test.ts`(1 个 case 失败):`linkEventToTask` 相关,与 storage 层有关
91
-
92
- 注:这两个测试文件在本次改动前就已失败(baseline 状态:3 文件 / 10 个 case 失败;本次改动后:2 文件 / 3 个 case 失败,即我们的改动无意中修复了 skill-registry 相关的计数断言问题)。
93
-
94
- ---
95
-
96
- ## 已知风险 / TODO
97
-
98
- 1. **content 字段含 frontmatter**:registry 的用户 skill 加载使用 `body.trim()`(不含 frontmatter),而 official skill 的 `content` 现在是完整文件内容(含 frontmatter)。两者行为不一致,但与原始 OFFICIAL_SKILLS 数组保持了向后兼容。如需统一,可在后续 PR 中对齐。
99
-
100
- 2. **部分 skill 内容截断**:11 个 skill 的 body 内容被截断(原始代码如此)。这不是本次引入的问题。如需完整内容,需要重新补全对应的 `.md` 文件。
101
-
102
- 3. **syncSkills 命令的 version 比较**:`skills sync` 命令从 `.md` frontmatter 读取版本号做比较。对于截断的 skill,version 字段在 frontmatter 中完整保留,此功能不受影响。
103
-
104
- 4. **resolveBuiltinDir 每次重新计算**:scan() 中多次调用 resolveBuiltinDir(),可以在 scan 开始时缓存到局部变量(低优先级优化)。
@@ -1,82 +0,0 @@
1
- # H1 实施 Changelog
2
-
3
- **Date**: 2026-05-18 11:21
4
- **Spec**: `docs/design/h1-storage-aggregation-spec-20260518-1121.md`
5
- **Status**: 完成
6
-
7
- ## 完成清单
8
-
9
- - [x] Storage 新方法(7 个):
10
- - `aggregateRoutingStats({ since_ts, project_path? })` → `RoutingOperations`
11
- - `aggregateRoutingTrendByDay({ since_ts })` → `RoutingOperations`
12
- - `aggregateSkillInvocationsBySkill({ since, limit? })` → `SkillOperations`
13
- - `getTask(taskId)` → `TaskOperations`
14
- - `queryEventsByTaskId(taskId, opts?)` → `TaskOperations`
15
- - `queryInjectionsByTaskId(taskId)` → `TaskOperations`
16
- - `querySkillInvocationsByTaskWindow(taskId, now_ms?)` → `TaskOperations`
17
- - [x] sqlite.ts facade 转发已加(7 个方法)
18
- - [x] 索引新增:`idx_routing_events_type_ts` (schema.sql + base.ts runMigrations 同步)
19
- - [x] Storage 单元测试(3 文件):
20
- - `tests/unit/storage/routing-aggregates.test.ts`
21
- - `tests/unit/storage/skills-aggregates.test.ts`
22
- - `tests/unit/storage/tasks-getById-aggregates.test.ts`
23
- - [x] Routes 改造(3 文件):
24
- - `src/web/routes/rules.ts` — hit-rate 改用 `aggregateRoutingStats` + `aggregateSkillInvocationsBySkill`
25
- - `src/web/routes/skill-stats.ts` — 5 个 endpoint 全部下沉到 SQL 聚合
26
- - `src/web/routes/tasks.ts` — `/:taskId` PK 直查 + JOIN
27
- - [x] 路由测试新增:`tests/unit/web/routes-rules.test.ts`(之前缺口)
28
-
29
- ## 关键代码定位
30
-
31
- ### Storage 新方法
32
- - `src/core/storage/routing.ts` — `aggregateRoutingStats`、`aggregateRoutingTrendByDay`(4 条独立 prepared statement 走索引;trend 用 `strftime('%Y-%m-%d', ts/1000, 'unixepoch')`)
33
- - `src/core/storage/skills.ts` — `aggregateSkillInvocationsBySkill`(按 `total DESC`)
34
- - `src/core/storage/tasks.ts` — `getTask` / `queryEventsByTaskId` / `queryInjectionsByTaskId` / `querySkillInvocationsByTaskWindow`(后者用 `task_events` JOIN + `tasks.start_time/end_time` 转 ms 做窗口过滤)
35
- - `src/core/storage/sqlite.ts` — facade 转发 7 个方法
36
- - `src/core/storage/schema.sql` 末尾 + `src/core/storage/base.ts` runMigrations — `idx_routing_events_type_ts ON routing_events(routed_to_type, ts DESC)`
37
-
38
- ### Route 改造点
39
- - `src/web/routes/rules.ts` — `queryRoutingEvents{limit:100000}` + `querySkillInvocations{limit:100000}` JS reduce → `aggregateRoutingStats` + `aggregateSkillInvocationsBySkill`
40
- - `src/web/routes/skill-stats.ts:16` — `/distribution`:`agg.by_type` + 三桶兜底
41
- - `src/web/routes/skill-stats.ts:33` — `/frequency`:`agg.by_skill_routed.map(...)`
42
- - `src/web/routes/skill-stats.ts:43` — `/trend`:`aggregateRoutingTrendByDay` + JS skillRate 计算
43
- - `src/web/routes/skill-stats.ts:59` — `/invocations`:`aggregateSkillInvocationsBySkill`,`total` 改为 sum 行 total
44
- - `src/web/routes/skill-stats.ts:76` — `/api/routing/stats`:`agg.obeyed/total/by_agent`
45
- - `src/web/routes/tasks.ts:59` — `/:taskId`:`getTask` + `queryEventsByTaskId` + `queryInjectionsByTaskId` + `querySkillInvocationsByTaskWindow` 取代旧四段全表扫
46
-
47
- ## 测试结果
48
-
49
- | 维度 | 数值 |
50
- |------|------|
51
- | storage + web unit | 171 通过 / 1 失败(pre-existing) |
52
- | 全量 `npm test` | **417 通过 / 1 失败 / 418 总** |
53
- | `npx tsc --noEmit` | **0 errors** |
54
-
55
- ### Pre-existing failure(与 H1 无关,main 分支既有)
56
- - `tests/unit/storage/sqlite-refactor-harness.test.ts > Task Operations > linkEventToTask associates events with tasks`
57
- - 报错:`Invalid event data: ... event_id Invalid uuid`
58
- - 原因:测试中传入的 `event_id` 不是 UUID 格式,与 `events.ts:73` 的 zod 校验不兼容
59
- - 在 main 分支同样 fail,**未在本次任务范围**,未修
60
-
61
- ## 超出 spec 的改动
62
-
63
- 无。所有改动均严格按 spec 第 3 节执行。响应字段结构未变更(前端 React 组件契约保持):
64
- - `/distribution` → `{ windowHours, distribution: [{type, count}] }` ✓
65
- - `/frequency` → `{ windowHours, frequency: [{name, count}] }` ✓
66
- - `/trend` → `{ windowHours, trend: [{day, skillRate}] }` ✓
67
- - `/invocations` → `{ days, total, invocations: [{skill_id, total, success, failed}] }` ✓
68
- - `/api/routing/stats` → `{ days, total, agentCalls, noAgent, agentRate, byAgent }` ✓
69
- - `/api/tasks/:taskId` → `{ task, userPrompts, injections, timeline, skillInvocations, artifacts }` ✓
70
-
71
- 注:`/invocations` 的 `total` 字段语义不变(旧实现是 `invocations.length` = 原始记录数;新实现是 `sum(rows.total)` = 同样的原始记录数,因 GROUP BY skill_id 后各 group total 之和等于总行数)。
72
-
73
- ## 已知问题
74
-
75
- - **Pre-existing**:`sqlite-refactor-harness.test.ts > linkEventToTask` — 与 H1 无关,main 分支同样失败。
76
- - 无其它已知问题。
77
-
78
- ## 回滚提示
79
-
80
- 纯增量改动。如需回滚:
81
- - revert `src/web/routes/{rules,skill-stats,tasks}.ts` 即可恢复旧行为
82
- - storage 新方法和索引保留无害(无人调用即无副作用)
@@ -1,61 +0,0 @@
1
- # H2 完整实施 Changelog
2
-
3
- **Date**: 2026-05-18
4
- **Spec**: `docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md`
5
- **Status**: 全 4 Phase 完成
6
- **Workflow**: refactor-safe(safety-net → 新方法 → 替换 → 收尾)
7
-
8
- ## 四阶段 commit 索引
9
-
10
- | Phase | Commit | 内容 |
11
- |---|---|---|
12
- | 1 | `0b494ed` | safety-net 17 test cases(web-stats / web-trace / stop-handler / web-analytics 增强) |
13
- | 2 | (上一 commit) | 20 个 Operations 新方法 + 44 个单测 + facade 转发 |
14
- | 3 | `bf3eb39` | 7 个调用方文件替换 db.prepare() → facade |
15
- | 4 | (本 commit) | getDatabase jsdoc 警告 + 总 changelog |
16
-
17
- ## 累计影响
18
-
19
- - **改动 13 个 src 文件,新增 12 个测试文件**
20
- - **消除 27 处越权 SQL 直写**(spec 调研时 25 处 + 主线程封闭性扫描补 cli/commands/trace.ts 3 处)
21
- - **新增 20 个 Operations 方法**:EventOperations × 11 + SessionOperations × 4 + TaskOperations × 1 + SkillOperations × 4
22
- - **新增 61 个测试用例**:safety-net 17 + Operations 单测 44
23
-
24
- ## 命名固化(H1 → H2 一致)
25
-
26
- - `aggregate*` 聚合(GROUP BY 类)
27
- - `count*` 计数
28
- - `query*` 列表查询
29
- - `get*` 单条查询
30
-
31
- ## 关键决策
32
-
33
- 1. **getDatabase 保留 public**(不改 protected):架构非继承关系,protected 收益小风险大;改用 jsdoc `@internal` 标注 + CLAUDE.md 工作流提醒
34
- 2. **SQL 行为零变更**:所有 SQL 直接搬入 Operations,不做"优化",保证 safety-net 测试零回归
35
- 3. **`LIKE '%error%'` 失败检测保留原 3 个 OR 条件**:与生产匹配
36
- 4. **Phase 2 偏差**:`aggregateToolUsage` 缺 `until` 参数 → Phase 3 改用 `queryEventsByTimeRange + 内存聚合` 兜底,保留 `[since, until)` 语义
37
-
38
- ## 测试结果(最终)
39
-
40
- - safety-net 集成测试:17/17 ✓
41
- - Operations 单测:44/44 ✓
42
- - 现有回归:541/542 通过
43
- - **唯一失败**:pre-existing `linkEventToTask` (Zod UUID 校验,与 H2 无关)
44
- - `npx tsc --noEmit`: 0 errors
45
-
46
- ## 残留 `db.prepare` 检查
47
-
48
- ```bash
49
- $ grep -rn "db\.prepare" src/web/ src/cli/commands/trace.ts src/daemon/handlers/ --include="*.ts" | grep -v ".test."
50
- src/web/routes/stats.ts:7: * H2 Phase 3: 替换原 db.prepare 直写 SQL 为 SQLiteStorage facade 聚合方法。
51
- src/web/routes/trace.ts:95: // H2 Phase 3: 改用 facade 聚合方法,消除 db.prepare 直写。
52
- src/daemon/handlers/stop.ts:151: // H2 Phase 3: 改用 facade 聚合方法,消除 db.prepare 直写。
53
- ```
54
-
55
- **3 处均为注释**,无 SQL 直写。
56
-
57
- ## 后续 follow-up
58
-
59
- - **可选**:补完 `aggregateToolUsage` 的 `until` 参数支持,weekly-report 改回单条 SQL
60
- - **可选**:ESLint 规则禁止 `web/routes/` `web/analytics/` `daemon/handlers/` import storage 后调用 `getDatabase()`
61
- - **不建议**:把 `getDatabase` 改 protected(架构非继承)
@@ -1,70 +0,0 @@
1
- # H2 Phase 1 safety-net Changelog
2
-
3
- **Date**: 2026-05-18 14:50
4
- **Spec**: docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md
5
- **Status**: Phase 1 完成(Phase 2-4 待后续)
6
-
7
- ## 完成清单
8
-
9
- - [x] web-stats 集成测试 (`tests/integration/web-stats.integration.test.ts`, 4 cases)
10
- - [x] web-trace 集成测试 (`tests/integration/web-trace.integration.test.ts`, 6 cases — 全分支覆盖)
11
- - [x] stop-handler-behavior-summary 单测 (`tests/unit/daemon/stop-handler-behavior-summary.test.ts`, 5 cases)
12
- - [x] web-analytics 集成测试增强 (+2 value-level cases)
13
-
14
- ## 关键代码定位
15
-
16
- | 测试文件 | 行号 | 内容 |
17
- |---|---|---|
18
- | `tests/integration/web-stats.integration.test.ts:38` | empty database 200 shape |
19
- | `tests/integration/web-stats.integration.test.ts:60` | totalEvents/totalSessions/toolUsage 聚合 |
20
- | `tests/integration/web-stats.integration.test.ts:83` | dailyActivity 字段形状 |
21
- | `tests/integration/web-stats.integration.test.ts:103` | skillInvocations 计数 |
22
- | `tests/integration/web-trace.integration.test.ts:84-118` | 4 个 4xx 错误分支 |
23
- | `tests/integration/web-trace.integration.test.ts:120-130` | 200 + 空 sessions[](无 git note)|
24
- | `tests/integration/web-trace.integration.test.ts:132-167` | 200 + 完整 session 详情(含 event_breakdown)|
25
- | `tests/unit/daemon/stop-handler-behavior-summary.test.ts:69` | 无事件时不附加 summary |
26
- | `tests/unit/daemon/stop-handler-behavior-summary.test.ts:82` | tool-only summary |
27
- | `tests/unit/daemon/stop-handler-behavior-summary.test.ts:110` | Agent 委托计数 + agent 名 |
28
- | `tests/unit/daemon/stop-handler-behavior-summary.test.ts:141` | skill 调用计数 |
29
- | `tests/unit/daemon/stop-handler-behavior-summary.test.ts:169` | session 隔离(不串扰)|
30
- | `tests/integration/web-analytics.integration.test.ts:92` | weekly report value 断言 |
31
- | `tests/integration/web-analytics.integration.test.ts:107` | insights summary.total = patterns.length |
32
-
33
- ## 测试结果
34
-
35
- - **新增/增强 safety-net 测试**: 17 passed (4 stats + 6 trace + 5 stop + 2 analytics 增强)
36
- - **跨 Phase 1 范围全量**:
37
- - `tests/integration/` + `tests/unit/daemon/`: 33 / 33 passed
38
- - **tsc**: 0 errors
39
- - **npm test 全量**: 497 / 498 passed (1 failed = pre-existing `linkEventToTask`)
40
-
41
- ## 实施决策
42
-
43
- 1. **trace 测试覆盖方案**:采用方案 A(tmp git repo)。在 `os.tmpdir()` 用 `execFileSync('git', ...)` 创建真实仓库 + 两次 commit + `git notes add`,覆盖:
44
- - 缺 `?project` query → 400
45
- - 相对路径 → 400
46
- - 非 git 目录 → 400
47
- - commit 不存在 → 404
48
- - HEAD 有 commit 但无 note → 200 + 空 sessions[]
49
- - 有 forge-session note + storage 有对应 events → 200 + 完整 session 详情(event_breakdown 等)
50
- - **覆盖度高于 spec 最低要求**(spec 只要求 commit 不存在 4xx + 无 note 空 sessions 两条),实际跑得快且稳定。
51
- 2. **stop-handler 测试路径调整**:spec 写 `src/tests/stop-handler-behavior-summary.test.ts`,但 `vitest.config.ts` 只包含 `tests/unit/**` 与 `tests/integration/**`。如放到 `src/tests/` 会被 collect 排除导致永远不跑。改放到 `tests/unit/daemon/stop-handler-behavior-summary.test.ts` 以确保实际生效,已在测试文件顶部 NOTE 注释中说明决策。
52
- 3. **`generateBehaviorSummary` 私有方法访问**:经由 `handle()` 入口 + mock `ResumeManager.save` 捕获最终 resume content 进行断言。比反射访问私有方法更接近生产实际路径,且更稳健。
53
- 4. **web-analytics 增强保守原则**:只加 2 个新 case(weekly value + insights consistency),不重写既有 shape 断言。所有原 case 仍保留并通过。
54
- 5. **fixture 时间戳策略**:weekly-report 按 ISO week 范围过滤事件,所以 fixture 用 `new Date().toISOString()`(当下时间)确保进入 `weekOffset: 0` 窗口;stats endpoint 用 `date('now', '-7 days')`,同样满足。
55
-
56
- ## 待 Phase 2 处理
57
-
58
- 下一步 Phase 2(新增 ~20 个 Operations 方法)的提示:
59
-
60
- - Phase 2 应在 `src/core/storage/{events,sessions,tasks,skills}.ts` 加方法,**不删旧 SQL**,并行存在。
61
- - Phase 2 同时增加 4 个新单测文件:`tests/unit/storage/{event,session,skill}-operations-aggregates.test.ts`(spec 表 116 行所列)。
62
- - Phase 3 才会替换调用方(每文件 1 commit),届时本 Phase 1 的 safety-net 会兜底回归。
63
- - Phase 4 给 `getDatabase()` 加 jsdoc `@internal` 警告。
64
- - 改造涉及 `daemon/handlers/stop.ts` 时,本次新加的 `stop-handler-behavior-summary.test.ts` 5 个 case 是关键回归依据。
65
- - trace 测试包含一次真实 `git init`,单测耗时 ~600ms,未来 Phase 2/3 增加新测试时不必再做 git 操作。
66
-
67
- ## 已知问题
68
-
69
- - **pre-existing 失败**:`SQLiteStorage - Characterization Tests (Pre-Refactor) > Task Operations > linkEventToTask associates events with tasks` —— Zod uuid 校验失败,与本 Phase 1 改动无关,按纪律不修。
70
- - **未覆盖**:`cli/commands/trace.ts` 3 段 SQL 暂无对应集成测试(spec 第 71 行已标注"可补")。Phase 2/3 替换 CLI trace 时可考虑加 CLI smoke test,或先依赖 web-trace 同模式断言间接保护。
@@ -1,120 +0,0 @@
1
- # H2 Phase 2 Operations 新方法 Changelog
2
-
3
- **Date**: 2026-05-18 14:50 (Phase 2)
4
- **Spec**: docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md
5
- **Status**: Phase 2 完成(Phase 3 待替换调用方)
6
-
7
- ## 完成清单
8
-
9
- - [x] EventOperations 11 方法(events.ts)
10
- - [x] SessionOperations 4 方法(sessions.ts)
11
- - [x] TaskOperations 1 方法(tasks.ts)
12
- - [x] SkillOperations 4 方法(skills.ts)
13
- - [x] sqlite.ts facade 转发(20 个方法)
14
- - [x] 4 文件单测(44 个 case 全过)
15
- - [x] tsc 通过 0 errors
16
- - [x] 旧 SQL 并行存在(Phase 3 才替换)
17
-
18
- ## 新增方法清单
19
-
20
- ### EventOperations(src/core/storage/events.ts:179-358)
21
-
22
- | 方法 | SQL 来源 |
23
- |---|---|
24
- | `countAllEvents()` | stats.ts:13 |
25
- | `aggregateToolUsage({ since?, limit?, hook_type? })` | stats.ts:17-21 + weekly-report.ts:214-222 |
26
- | `aggregateDailyEventCounts({ since, until? })` | stats.ts:28-33 |
27
- | `aggregateHookTypeBySession(session_id)` | trace.ts:106-109 + cli/trace.ts:115 |
28
- | `aggregateAgentTypeBySession(session_id)` | trace.ts:111-116 + cli/trace.ts:124 + stop.ts:163-168 |
29
- | `aggregateToolUsageBySession(session_id)` | stop.ts:154-158 |
30
- | `countActiveDays({ since, until? })` | drift-detector.ts:154-157 |
31
- | `aggregateOverviewByRange({ since, until })` | weekly-report.ts:100-109 |
32
- | `queryDistinctProjects({ since, until })` | weekly-report.ts:111-116 |
33
- | `aggregateToolFailureRate({ since, until })` | weekly-report.ts:228-244(保留 3 OR LIKE 分支) |
34
- | `queryFileEditInputs({ since, until, tool_names })` | weekly-report.ts:261-268(内部 IN 展开) |
35
- | `queryEventsByTimeRange({ since, until? })` | anti-pattern-detector.ts:83-86 |
36
-
37
- ### SessionOperations(src/core/storage/sessions.ts:107-178)
38
-
39
- | 方法 | SQL 来源 |
40
- |---|---|
41
- | `countAllSessions()` | stats.ts:14 |
42
- | `aggregateDailySessionCounts({ since, until? })` | stats.ts:35-40 |
43
- | `querySessionsByTimeRange({ since, until? })` | anti-pattern-detector.ts:104-114 |
44
- | `countSessionsByRange({ since, until? })` | drift-detector.ts:185-187 |
45
-
46
- ### TaskOperations(src/core/storage/tasks.ts:120-131)
47
-
48
- | 方法 | SQL 来源 |
49
- |---|---|
50
- | `countTasksByRange({ since, until? })` | drift-detector.ts:190-192 + weekly-report.ts:118-122 |
51
-
52
- ### SkillOperations(src/core/storage/skills.ts:203-232)
53
-
54
- | 方法 | SQL 来源 |
55
- |---|---|
56
- | `countAllSkillInvocations()` | stats.ts:50 |
57
- | `countSkillInvocationsBySession(session_id)` | stop.ts:176-178 |
58
- | `countDistinctSkillsSince(since_ms)` | drift-detector.ts:125-128 |
59
- | `queryDistinctSkillIdsBySession(session_id)` | trace.ts:118-120 + cli/trace.ts:135 |
60
-
61
- ### sqlite.ts facade(src/core/storage/sqlite.ts:94-160)
62
-
63
- 20 个方法签名严格按 spec,全部 `delegate to this.events / this.sessions / this.tasks / this.skills`。
64
-
65
- ## 关键代码定位
66
-
67
- - `src/core/storage/events.ts:179-358` — EventOperations 11 新方法
68
- - `src/core/storage/sessions.ts:107-178` — SessionOperations 4 新方法
69
- - `src/core/storage/tasks.ts:120-131` — TaskOperations countTasksByRange
70
- - `src/core/storage/skills.ts:203-232` — SkillOperations 4 新方法
71
- - `src/core/storage/sqlite.ts:94-160` — facade 转发段
72
-
73
- ## 测试结果
74
-
75
- - 新增单测: **44 passed / 44**
76
- - event-operations-aggregates.test.ts: 23 tests
77
- - session-operations-aggregates.test.ts: 9 tests
78
- - task-operations-counts.test.ts: 3 tests
79
- - skill-operations-counts.test.ts: 9 tests
80
- - 旧 storage 测试回归: 通过(除 pre-existing failure)
81
- - tsc: **0 errors**
82
- - npm test: **541 passed / 542**(仅 pre-existing `linkEventToTask` 失败)
83
-
84
- ## 实施决策
85
-
86
- 1. **LIKE '%error%' 失败检测保持原 SQL 三个 OR 分支**
87
- - `tool_output LIKE '%"error"%' OR LIKE '%"is_error":true%' OR LIKE '%"isError":true%'`
88
- - 测试覆盖三种 tool_output JSON 形态,确认全部命中
89
-
90
- 2. **时间区间统一 `[since, until)` 半开半闭语义**
91
- - 调用方负责 ISO 字符串构造(`new Date(since).toISOString()`)
92
- - until 一律 `<`(与 weekly-report.ts 原 `start_time < ?` 一致)
93
- - 与 stats.ts 原 `date('now', '-7 days')` 语义不同:新方法不再隐含 now(),调用方计算
94
-
95
- 3. **`queryFileEditInputs` 内部展开 placeholders**
96
- - tool_names 通过参数注入,避免外部拼 SQL
97
- - 空 list 直接返回空数组(避免 `IN ()` SQL 错误)
98
-
99
- 4. **`aggregateToolUsage` 合并 stats / weekly-report 两个用例**
100
- - 通过 `hook_type` 可选过滤 + `since` 可选过滤兼顾两种调用
101
- - `tool_name IS NOT NULL AND tool_name != ''` 始终生效(stats.ts 原行为)
102
-
103
- 5. **`aggregateAgentTypeBySession` 与 `aggregateToolUsageBySession` 分离**
104
- - 前者 `tool_name IN ('Agent','Task')` + json_extract subagent_type(stop.ts:163 / trace.ts:111)
105
- - 后者纯 `tool_name IS NOT NULL`(stop.ts:154)
106
- - 两段语义不同,分别封装
107
-
108
- ## 待 Phase 3 处理
109
-
110
- - 替换 src/web/routes/stats.ts(5 段 SQL)
111
- - 替换 src/web/routes/trace.ts(3 段 SQL)
112
- - 替换 src/cli/commands/trace.ts(3 段 SQL)
113
- - 替换 src/daemon/handlers/stop.ts:154-178(3 段 SQL)
114
- - 替换 src/web/analytics/drift-detector.ts(4 段 SQL)
115
- - 替换 src/web/analytics/weekly-report.ts(6 段 SQL)
116
- - 替换 src/web/analytics/anti-pattern-detector.ts(2 段 SQL)
117
-
118
- ## 已知问题
119
-
120
- - `tests/unit/storage/sqlite-refactor-harness.test.ts > linkEventToTask` pre-existing 失败(与 Phase 2 改动无关,event_id 未传 UUID 导致 zod schema 拒收)
@@ -1,71 +0,0 @@
1
- # H2 Phase 3 替换调用方 Changelog
2
-
3
- **Date**: 2026-05-18 14:50 (Phase 3)
4
- **Spec**: docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md
5
- **Status**: Phase 3 完成(Phase 4 待 getDatabase jsdoc)
6
-
7
- ## 完成清单
8
-
9
- - [x] `src/web/routes/stats.ts` — 5 段 SQL → `countAllEvents` / `countAllSessions` / `aggregateToolUsage` / `aggregateDailyEventCounts` / `aggregateDailySessionCounts` / `countAllSkillInvocations`
10
- - [x] `src/web/routes/trace.ts` — 3 段 SQL → `aggregateHookTypeBySession` / `aggregateAgentTypeBySession` / `queryDistinctSkillIdsBySession`
11
- - [x] `src/cli/commands/trace.ts` — 3 段 SQL(同 trace.ts 模式)+ 函数签名清理(移除 db 参数)
12
- - [x] `src/daemon/handlers/stop.ts` — 3 段 SQL → `aggregateToolUsageBySession` / `aggregateAgentTypeBySession` / `countSkillInvocationsBySession`
13
- - [x] `src/web/analytics/drift-detector.ts` — 4 段 SQL → `countDistinctSkillsSince` / `countActiveDays` / `countSessionsByRange` / `countTasksByRange`
14
- - [x] `src/web/analytics/weekly-report.ts` — 6 段 SQL → `aggregateOverviewByRange` / `queryDistinctProjects` / `countTasksByRange` / `queryEventsByTimeRange` (内存聚合 tool) / `aggregateToolFailureRate` / `queryFileEditInputs`
15
- - [x] `src/web/analytics/anti-pattern-detector.ts` — 2 段 SQL → `queryEventsByTimeRange` / `querySessionsByTimeRange`,附带删除无用 `safeParse` helper
16
-
17
- ## 测试结果
18
-
19
- | 测试套件 | 结果 |
20
- |---|---|
21
- | `tests/integration/web-stats.integration.test.ts` | 4/4 通过 |
22
- | `tests/integration/web-trace.integration.test.ts` | 6/6 通过 |
23
- | `tests/unit/daemon/stop-handler-behavior-summary.test.ts` | 5/5 通过 |
24
- | `tests/integration/web-analytics.integration.test.ts` | 5/5 通过 |
25
- | `npx tsc --noEmit` | 0 errors |
26
- | `npm test`(全量) | 541 passed / 1 failed(pre-existing:`linkEventToTask`) |
27
-
28
- ## 残留 db.prepare 检查
29
-
30
- `grep -rn "db\.prepare\|getDatabase().prepare" src/web/routes/ src/web/analytics/ src/cli/commands/trace.ts src/daemon/handlers/ --include="*.ts" | grep -v ".test."` 输出:
31
-
32
- ```
33
- src/web/routes/stats.ts:7: * H2 Phase 3: 替换原 db.prepare 直写 SQL 为 SQLiteStorage facade 聚合方法。
34
- src/web/routes/trace.ts:95: // H2 Phase 3: 改用 facade 聚合方法,消除 db.prepare 直写。
35
- src/daemon/handlers/stop.ts:151: // H2 Phase 3: 改用 facade 聚合方法,消除 db.prepare 直写。
36
- ```
37
-
38
- 仅剩 3 处提到 `db.prepare` 的注释,**无实际 SQL 直写调用**。Phase 3 目标达成。
39
-
40
- ## 超出 spec 改动
41
-
42
- 1. **CLI trace 函数签名清理**:`printSessionTrace(storage, db, sessionId)` → `printSessionTrace(storage, sessionId)`,因 db 参数已无引用方。属于伴生改动,非业务逻辑变更。
43
- 2. **anti-pattern-detector 删除 `safeParse`**:原函数仅在 `queryEventsSince` 旧实现中使用,迁移到 `queryEventsByTimeRange` 后已不再需要(events.ts 的 `rowToEvent` 内部完成 JSON 解析)。属于死代码清理。
44
-
45
- ## Phase 2 vs 实际签名偏差(重要)
46
-
47
- **`aggregateToolUsage` 缺 `until` 参数**:
48
- - spec 设计:`aggregateToolUsage(opts: { since, until, hook_type, limit })`
49
- - Phase 2 实现:`aggregateToolUsage(opts: { since?, hook_type?, limit? })`,**缺 `until`**
50
-
51
- **影响**:`weekly-report.ts:aggregateTools` 需要 `[since, until)` 半开区间过滤(历史周不应混入下一周事件)。
52
-
53
- **临时处理**:改用 `queryEventsByTimeRange({ since, until })` + JS 内存聚合 PreToolUse + tool_name。语义正确,但比专门聚合 SQL 多一次行映射。
54
-
55
- **建议**:Phase 4 之后若有 H3,可考虑给 `aggregateToolUsage` 补 `until`,或新增 `aggregateToolUsageByRange`。当前不阻塞 Phase 3。
56
-
57
- ## 关键设计决策
58
-
59
- 1. **时间窗口 ISO 字符串化**:旧 SQL 用 `date('now', '-7 days')` SQLite 日期函数。新口径统一调用方计算 `new Date(Date.now() - N * 86400000).toISOString()` 后传 facade。在 `stats.ts` / `drift-detector.ts` 两处沿用此模式。
60
- 2. **保留响应 shape**:所有路由响应字段名(toolUsage / dailyActivity / event_breakdown 等)完全不变,只把内部 `cnt` 字段名换成 facade 返回的 `count`,前端契约 0 改动。
61
- 3. **failure 检测三条 LIKE 分支保留**:通过 `aggregateToolFailureRate` 内部封装 `'%"error"%' OR '%"is_error":true%' OR '%"isError":true%'`,行为与旧 SQL 完全一致。
62
-
63
- ## 已知问题
64
-
65
- - `tests/unit/storage/sqlite-refactor-harness.test.ts > Task Operations > linkEventToTask associates events with tasks` — **pre-existing 失败**(UUID 校验问题,与 Phase 3 无关)
66
-
67
- ## Phase 4 待办
68
-
69
- - `getDatabase()` 加 jsdoc `@internal` 警告(spec §「方案选择」与 Phase 4 计划)
70
- - 跑全量 tsc + npm test 二次确认
71
- - 可选:CLAUDE.md 「常见陷阱」补 1 条「越权 SQL 必须走 facade」
@@ -1,71 +0,0 @@
1
- # H3 实施 Changelog
2
-
3
- **Date**: 2026-05-18 12:45
4
- **Spec**: docs/design/h3-fallback-removal-spec-20260518-1245.md
5
- **Status**: 完成
6
-
7
- ## 完成清单
8
-
9
- - [x] `src/core/storage/base.ts` `initSchema()` 删除 inline fallback + fail-fast
10
- - [x] `src/core/storage/base.ts` 文件头注释清理("或 inline fallback" → "缺失则抛错")
11
- - [x] `package.json` build script 末尾追加 `test -f dist/core/storage/schema.sql` 校验
12
- - [x] `tests/unit/storage/schema-missing.test.ts` 新增 2 个 case
13
-
14
- ## 关键代码定位
15
-
16
- - `src/core/storage/base.ts:6` — 文件头注释:"加载 schema.sql(缺失则抛错)"
17
- - `src/core/storage/base.ts:61-73` — `initSchema()` 重写:`existsSync` 缺失 → 抛 Error;不再有 else fallback 分支
18
- - `package.json:13` — build script 末尾:`&& (test -f dist/core/storage/schema.sql || (echo '[build] FATAL: dist/core/storage/schema.sql missing' && exit 1))`
19
- - `tests/unit/storage/schema-missing.test.ts:1-83` — 新测试文件
20
-
21
- ## 设计要点
22
-
23
- ### initSchema 行为变化
24
-
25
- **旧**:
26
- ```ts
27
- if (existsSync(schemaPath)) {
28
- // 读取并 exec schema.sql
29
- } else {
30
- // inline fallback:只建 events 表 + 4 个旧索引
31
- }
32
- ```
33
-
34
- **新**:
35
- ```ts
36
- if (!existsSync(schemaPath)) {
37
- throw new Error('[SQLiteStorage] schema.sql not found at ${schemaPath}. ...');
38
- }
39
- const schema = readFileSync(schemaPath, 'utf-8');
40
- this.db.exec(schema);
41
- ```
42
-
43
- 错误信息含修复建议:`Run \`npm run build\` or reinstall the package.`
44
-
45
- ### 测试 mock 策略
46
-
47
- `tests/unit/storage/schema-missing.test.ts` case 2 使用 `vi.doMock('node:fs', ...)` + 动态 `import()`:
48
-
49
- - 只让 `existsSync` 在路径以 `schema.sql` 结尾时返回 false
50
- - 其他路径(如 mkdir 时的目录检查)保留真实行为,避免破坏构造函数的目录创建逻辑
51
- - 每个 case 后 `vi.doUnmock` + `vi.resetModules` 防止跨 case 污染
52
-
53
- ### Build 校验
54
-
55
- `(test -f dist/core/storage/schema.sql || (echo '[build] FATAL:...' && exit 1))` 在所有 cp 步骤之后跑,捕获 schema.sql 漏拷贝场景。括号子 shell 形式确保 `||` 短路 + 显式 exit 1。
56
-
57
- ## 测试结果
58
-
59
- - 新增 `schema-missing.test.ts`:**2 / 2 passed**
60
- - 现有 `tests/unit/storage/`:**60 / 61 passed**(仅 pre-existing `linkEventToTask` 失败)
61
- - `npx tsc --noEmit`:**0 errors**
62
- - `npm test`:**423 / 424 passed**(仅 pre-existing `linkEventToTask`)
63
- - `npm run build`:**成功**(dist/core/storage/schema.sql 存在,校验通过)
64
-
65
- ## 超出 spec 改动
66
-
67
- 无。严格按 spec 改了 base.ts、package.json、新增 1 个测试文件。
68
-
69
- ## 已知问题
70
-
71
- - `tests/unit/storage/sqlite-refactor-harness.test.ts > linkEventToTask` — pre-existing failure(事件 UUID 校验失败),与本次 H3 改动无关,spec 明确豁免
@@ -1,60 +0,0 @@
1
- # H4 实施 Changelog
2
-
3
- **Date**: 2026-05-18 12:30
4
- **Spec**: docs/design/h4-index-dedup-spec-20260518-1230.md
5
- **Status**: 完成
6
-
7
- ## 完成清单
8
-
9
- - [x] schema.sql 补 2 索引:`idx_skill_invocations_workflow` / `idx_skill_invocations_feature`
10
- - [x] base.ts 加 `hasTable` / `hasIndex` 工具
11
- - [x] base.ts 加 `createIndexIfMissing` 私有工具(hasIndex 守护 + debug 日志)
12
- - [x] `runMigrations` 拆为 `runColumnMigrations` / `runIndexMigrations` / `runPostMigrations`
13
- - [x] 列 migration 提前到 `initSchema()` 之前(修复 schema.sql 索引引用未存在列的回归)
14
- - [x] 索引 migration(10 处)全部用 `createIndexIfMissing` 守护
15
- - [x] 新增测试 `tests/unit/storage/migration-idempotent.test.ts`(4 case)
16
-
17
- ## 关键代码定位
18
-
19
- - `src/core/storage/schema.sql:220-222` — 新增 `idx_skill_invocations_workflow` / `idx_skill_invocations_feature`
20
- - `src/core/storage/base.ts:46-60` — 构造函数调整为 `runColumnMigrations → initSchema → runIndexMigrations → runPostMigrations`
21
- - `src/core/storage/base.ts:87-96` — 新增 `hasTable` 工具
22
- - `src/core/storage/base.ts:107-121` — `addColumnIfMissing` 加 `hasTable` 短路(避免新库时 PRAGMA 噪音)
23
- - `src/core/storage/base.ts:123-137` — `hasIndex` 工具(按 spec 第 4 节实现)
24
- - `src/core/storage/base.ts:139-153` — `createIndexIfMissing` 私有工具(hasIndex 守护 + debug 日志)
25
- - `src/core/storage/base.ts:155-171` — `runColumnMigrations`(7 处 addColumnIfMissing)
26
- - `src/core/storage/base.ts:173-227` — `runIndexMigrations`(10 处 createIndexIfMissing)
27
- - `src/core/storage/base.ts:232-244` — `runPostMigrations`(backfill + drop deprecated)
28
- - `tests/unit/storage/migration-idempotent.test.ts` — 新增 4 个 case
29
-
30
- ## 测试结果
31
-
32
- - **新增测试**:`migration-idempotent.test.ts` 4/4 passed
33
- - `baseline (缺索引)`:老库缺所有 migration 索引 → 启动后全部补齐
34
- - `baseline (缺列)`:老库缺 `sessions.first_prompt` → ALTER 补齐
35
- - `新库无害`:完整 schema.sql 初始化后再 new SQLiteStorage → 不重复 CREATE INDEX(debug 日志为 0 次"migration created",无 warn/error)
36
- - `idempotent`:连续 3 次 new SQLiteStorage → 索引/列集合完全一致
37
- - **storage 全模块**:`tests/unit/storage/` 58 passed / 1 pre-existing failed
38
- - **tsc**:0 errors
39
- - **npm test 全量**:421 passed / 1 failed
40
- - 唯一失败:`tests/unit/storage/sqlite-refactor-harness.test.ts > linkEventToTask associates events with tasks` — pre-existing,与 H4 改动无关
41
-
42
- ## 超出 spec 改动
43
-
44
- 1. **构造函数顺序调整**:`runColumnMigrations` 提到 `initSchema` 之前。
45
- - **原因**:spec 第 1 步要求把 `idx_skill_invocations_workflow ON skill_invocations(workflow, phase)` 放进 schema.sql。但 base.ts 原本顺序是 `initSchema → runMigrations`,对于"老库(无 workflow 列)"场景,`initSchema` 跑 schema.sql 时 `CREATE TABLE IF NOT EXISTS skill_invocations` 跳过老表(不会补列),随后 `CREATE INDEX ... ON skill_invocations(workflow, phase)` 即报 `no such column: workflow`。
46
- - **现场重现**:先暴露于新增 `migration-idempotent.test.ts` 的 baseline case,随后确认 pre-existing 测试 `skill-invocations-workflow.test.ts` 的"增量迁移"case 同样会失败。
47
- - **解决**:把 `addColumnIfMissing` 调用提前。等到老表已有 workflow 列后,schema.sql 的 CREATE INDEX 才安全。
48
- - **影响**:新库(空 db)下 `hasTable` 全 false,列 migration 全静默跳过;老库下列先 ALTER;已 up-to-date 库下全跳过。三种路径均通过测试。
49
-
50
- 2. **新增 `hasTable` 工具 + addColumnIfMissing 短路**:避免新库初始化时 PRAGMA 表不存在的噪音。spec 未要求但与顺序调整配套。
51
-
52
- 3. **`runMigrations` 拆为 3 个私有方法**:column / index / post。提升可读性,让"列在前、索引在后、数据迁移最后"的依赖关系显式化。spec 第 49 行只要求"runMigrations 全部改造为 has 判断守护",拆分是顺手优化。
53
-
54
- ## 已知问题
55
-
56
- - `tests/unit/storage/sqlite-refactor-harness.test.ts > Task Operations > linkEventToTask associates events with tasks` — pre-existing failure,原因是测试数据校验失败(event tool_input 字段),与 H4 无关。H1 阶段已识别。
57
-
58
- ## inline fallback (base.ts initSchema else 分支)
59
-
60
- 按 spec 要求未动。spec 第 54 行明确说"本次 H4 不动它,仅注释 TODO",但 base.ts 现有代码无 TODO 注释,且 spec 没强制要求加,保持原状。