@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,219 +0,0 @@
1
- /**
2
- * DriftDetector — CLAUDE.md 漂移检测引擎
3
- *
4
- * 对比 CLAUDE.md 中声明的行为预期与实际事件流数据,
5
- * 生成合规度报告(DriftReport)。
6
- *
7
- * 只读 storage,不写入任何数据。
8
- */
9
-
10
- import type { SQLiteStorage } from '../../core/storage/sqlite.js';
11
-
12
- export interface DriftReport {
13
- generatedAt: string;
14
- period: { days: number; since: string };
15
- checks: DriftCheck[];
16
- overallScore: number; // 0-100, 100=完全符合
17
- }
18
-
19
- export interface DriftCheck {
20
- rule: string;
21
- expected: string;
22
- actual: string;
23
- status: 'pass' | 'warn' | 'fail';
24
- detail?: string;
25
- }
26
-
27
- export class DriftDetector {
28
- constructor(private storage: SQLiteStorage) {}
29
-
30
- /**
31
- * 执行全部漂移检测规则,返回报告。
32
- */
33
- run(days: number = 7): DriftReport {
34
- const since = Date.now() - days * 24 * 3600 * 1000;
35
- const sinceISO = new Date(since).toISOString();
36
-
37
- const checks: DriftCheck[] = [
38
- this.checkAgentDelegationRate(since),
39
- this.checkSkillTriggerRate(since),
40
- this.checkActiveSkillCoverage(since),
41
- this.checkEventContinuity(),
42
- this.checkTaskSegmentation(since),
43
- ];
44
-
45
- const overallScore = this.computeScore(checks);
46
-
47
- return {
48
- generatedAt: new Date().toISOString(),
49
- period: { days, since: sinceISO },
50
- checks,
51
- overallScore,
52
- };
53
- }
54
-
55
- /**
56
- * 规则 1: Agent 委托率
57
- * 预期: CLAUDE.md 声明"默认 spawn Agent",obeyed 率应 >30%
58
- */
59
- private checkAgentDelegationRate(since: number): DriftCheck {
60
- const events = this.storage.queryRoutingEvents({ since_ts: since, limit: 10000 });
61
- const total = events.length;
62
- const obeyed = events.filter(e => e.obeyed === 1).length;
63
- const rate = total > 0 ? Math.round((obeyed / total) * 1000) / 10 : 0;
64
-
65
- let status: DriftCheck['status'];
66
- if (total === 0) {
67
- status = 'warn';
68
- } else if (rate >= 30) {
69
- status = 'pass';
70
- } else if (rate >= 10) {
71
- status = 'warn';
72
- } else {
73
- status = 'fail';
74
- }
75
-
76
- return {
77
- rule: 'Agent 委托率',
78
- expected: '>30% 路由事件被 Agent 执行 (obeyed=1)',
79
- actual: `${rate}% (${obeyed}/${total})`,
80
- status,
81
- detail: total === 0 ? '期间无路由事件' : undefined,
82
- };
83
- }
84
-
85
- /**
86
- * 规则 2: Skill 触发率
87
- * 预期: 有 Skill 系统就应该有触发,>10%
88
- */
89
- private checkSkillTriggerRate(since: number): DriftCheck {
90
- const routingEvents = this.storage.queryRoutingEvents({ since_ts: since, limit: 10000 });
91
- const totalRouting = routingEvents.length;
92
- const invocations = this.storage.querySkillInvocations({ since, limit: 10000 });
93
- const totalInvocations = invocations.length;
94
-
95
- const rate = totalRouting > 0
96
- ? Math.round((totalInvocations / totalRouting) * 1000) / 10
97
- : 0;
98
-
99
- let status: DriftCheck['status'];
100
- if (totalRouting === 0) {
101
- status = 'warn';
102
- } else if (rate >= 10) {
103
- status = 'pass';
104
- } else if (rate >= 5) {
105
- status = 'warn';
106
- } else {
107
- status = 'fail';
108
- }
109
-
110
- return {
111
- rule: 'Skill 触发率',
112
- expected: '>10% (skill_invocations / routing_events)',
113
- actual: `${rate}% (${totalInvocations}/${totalRouting})`,
114
- status,
115
- detail: totalRouting === 0 ? '期间无路由事件' : undefined,
116
- };
117
- }
118
-
119
- /**
120
- * 规则 3: 活跃 Skill 覆盖率
121
- * 预期: 至少 3 个不同 Skill 被调用
122
- */
123
- private checkActiveSkillCoverage(since: number): DriftCheck {
124
- // H2 Phase 3: 改用 facade。countDistinctSkillsSince 接收 unix ms。
125
- const distinctCount = this.storage.countDistinctSkillsSince(since);
126
-
127
- let status: DriftCheck['status'];
128
- if (distinctCount >= 3) {
129
- status = 'pass';
130
- } else if (distinctCount >= 1) {
131
- status = 'warn';
132
- } else {
133
- status = 'fail';
134
- }
135
-
136
- return {
137
- rule: '活跃 Skill 覆盖率',
138
- expected: '>=3 个不同 Skill 被调用',
139
- actual: `${distinctCount} 个不同 Skill`,
140
- status,
141
- };
142
- }
143
-
144
- /**
145
- * 规则 4: 事件记录连续性
146
- * 预期: 最近 7 天中至少 5 天有事件(工作日)
147
- */
148
- private checkEventContinuity(): DriftCheck {
149
- // H2 Phase 3: 改用 facade。
150
- // 旧 SQL: timestamp >= date('now', '-7 days')
151
- // 新口径:调用方计算 ISO 字符串。
152
- const sevenDaysAgoIso = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
153
- const activeDays = this.storage.countActiveDays({ since: sevenDaysAgoIso });
154
-
155
- let status: DriftCheck['status'];
156
- if (activeDays >= 5) {
157
- status = 'pass';
158
- } else if (activeDays >= 3) {
159
- status = 'warn';
160
- } else {
161
- status = 'fail';
162
- }
163
-
164
- return {
165
- rule: '事件记录连续性',
166
- expected: '最近 7 天中 >=5 天有事件',
167
- actual: `${activeDays} 天有事件`,
168
- status,
169
- };
170
- }
171
-
172
- /**
173
- * 规则 5: 任务分段有效性
174
- * 预期: 每个 session 至少有 1 个 task (tasks/sessions >= 0.8)
175
- */
176
- private checkTaskSegmentation(since: number): DriftCheck {
177
- // H2 Phase 3: 改用 facade。
178
- const sinceISO = new Date(since).toISOString();
179
- const sessionCount = this.storage.countSessionsByRange({ since: sinceISO });
180
- const taskCount = this.storage.countTasksByRange({ since: sinceISO });
181
-
182
- const ratio = sessionCount > 0
183
- ? Math.round((taskCount / sessionCount) * 100) / 100
184
- : 0;
185
-
186
- let status: DriftCheck['status'];
187
- if (sessionCount === 0) {
188
- status = 'warn';
189
- } else if (ratio >= 0.8) {
190
- status = 'pass';
191
- } else if (ratio >= 0.5) {
192
- status = 'warn';
193
- } else {
194
- status = 'fail';
195
- }
196
-
197
- return {
198
- rule: '任务分段有效性',
199
- expected: 'tasks/sessions >= 0.8',
200
- actual: `${ratio} (${taskCount} tasks / ${sessionCount} sessions)`,
201
- status,
202
- detail: sessionCount === 0 ? '期间无会话' : undefined,
203
- };
204
- }
205
-
206
- /**
207
- * 计算总体合规分数 (0-100)
208
- * pass=20, warn=10, fail=0 (每条规则满分 20)
209
- */
210
- private computeScore(checks: DriftCheck[]): number {
211
- const maxPerCheck = 100 / checks.length;
212
- let total = 0;
213
- for (const check of checks) {
214
- if (check.status === 'pass') total += maxPerCheck;
215
- else if (check.status === 'warn') total += maxPerCheck * 0.5;
216
- }
217
- return Math.round(total);
218
- }
219
- }
@@ -1,431 +0,0 @@
1
- /**
2
- * WeeklyReportGenerator — 周报生成引擎
3
- *
4
- * 基于现有 events / sessions / routing_events / skill_invocations / tasks 表
5
- * 聚合上一周(ISO week,周一 00:00 — 周日 23:59)的关键指标,并提供
6
- * Markdown 渲染输出。
7
- *
8
- * 不修改任何 schema:完全基于现有表。
9
- */
10
-
11
- import type { SQLiteStorage } from '../../core/storage/sqlite.js';
12
-
13
- export interface WeeklyReport {
14
- generatedAt: string;
15
- week: { start: string; end: string; isoWeekNumber: number };
16
- overview: {
17
- totalSessions: number;
18
- totalEvents: number;
19
- totalTasks: number;
20
- activeProjects: string[];
21
- activeDays: number;
22
- };
23
- agentDelegation: {
24
- totalPrompts: number;
25
- delegations: number;
26
- rate: string;
27
- weekOverWeek: string;
28
- topAgents: Array<{ agent: string; count: number }>;
29
- };
30
- skills: {
31
- invocations: number;
32
- distinct: number;
33
- topSkills: Array<{ skill_id: string; count: number }>;
34
- neverUsed: string[];
35
- };
36
- tools: {
37
- totalCalls: number;
38
- topTools: Array<{ name: string; count: number }>;
39
- failureRate: string;
40
- };
41
- files: {
42
- topEdited: Array<{ path: string; editCount: number }>;
43
- totalEdits: number;
44
- };
45
- anomalies: Array<{ type: string; description: string }>;
46
- }
47
-
48
- interface WeekRange {
49
- startMs: number;
50
- endMs: number;
51
- startISO: string;
52
- endISO: string;
53
- isoWeekNumber: number;
54
- }
55
-
56
- const FILE_EDIT_TOOLS = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);
57
-
58
- export class WeeklyReportGenerator {
59
- constructor(
60
- private storage: SQLiteStorage,
61
- private skillRegistry?: { getAll(): Array<{ id: string }> },
62
- ) {}
63
-
64
- /**
65
- * 生成周报
66
- * @param weekOffset 周偏移:0 = 本周, -1 = 上周, -2 = 上上周
67
- */
68
- generate(weekOffset: number = 0): WeeklyReport {
69
- const week = this.computeWeekRange(weekOffset);
70
- const previousWeek = this.computeWeekRange(weekOffset - 1);
71
-
72
- const overview = this.aggregateOverview(week);
73
- const agentDelegation = this.aggregateAgentDelegation(week, previousWeek);
74
- const skills = this.aggregateSkills(week);
75
- const tools = this.aggregateTools(week);
76
- const files = this.aggregateFiles(week);
77
- const anomalies = this.aggregateAnomalies(week);
78
-
79
- return {
80
- generatedAt: new Date().toISOString(),
81
- week: {
82
- start: week.startISO,
83
- end: week.endISO,
84
- isoWeekNumber: week.isoWeekNumber,
85
- },
86
- overview,
87
- agentDelegation,
88
- skills,
89
- tools,
90
- files,
91
- anomalies,
92
- };
93
- }
94
-
95
- // ── Aggregation methods ──────────────────────────────────────────────
96
-
97
- private aggregateOverview(week: WeekRange): WeeklyReport['overview'] {
98
- // H2 Phase 3: 改用 facade 聚合方法。
99
- const overview = this.storage.aggregateOverviewByRange({
100
- since: week.startISO,
101
- until: week.endISO,
102
- });
103
- const activeProjects = this.storage.queryDistinctProjects({
104
- since: week.startISO,
105
- until: week.endISO,
106
- });
107
- const totalTasks = this.storage.countTasksByRange({
108
- since: week.startISO,
109
- until: week.endISO,
110
- });
111
-
112
- return {
113
- totalSessions: overview.session_count || 0,
114
- totalEvents: overview.event_count || 0,
115
- totalTasks: totalTasks || 0,
116
- activeProjects,
117
- activeDays: overview.day_count || 0,
118
- };
119
- }
120
-
121
- private aggregateAgentDelegation(
122
- week: WeekRange,
123
- previousWeek: WeekRange,
124
- ): WeeklyReport['agentDelegation'] {
125
- const current = this.computeAgentRate(week);
126
- const previous = this.computeAgentRate(previousWeek);
127
-
128
- const diff = current.rateNum - previous.rateNum;
129
- const weekOverWeek = `${diff >= 0 ? '+' : ''}${diff.toFixed(1)}pp`;
130
-
131
- return {
132
- totalPrompts: current.totalPrompts,
133
- delegations: current.delegations,
134
- rate: `${current.rateNum.toFixed(1)}%`,
135
- weekOverWeek,
136
- topAgents: current.topAgents,
137
- };
138
- }
139
-
140
- private computeAgentRate(week: WeekRange): {
141
- totalPrompts: number;
142
- delegations: number;
143
- rateNum: number;
144
- topAgents: Array<{ agent: string; count: number }>;
145
- } {
146
- const events = this.storage.queryRoutingEvents({
147
- since_ts: week.startMs,
148
- limit: 100000,
149
- }).filter(e => e.ts < week.endMs);
150
-
151
- const totalPrompts = events.length;
152
- const delegations = events.filter(e => e.obeyed === 1).length;
153
- const rateNum = totalPrompts > 0 ? (delegations / totalPrompts) * 100 : 0;
154
-
155
- const agentMap = new Map<string, number>();
156
- for (const e of events) {
157
- if (e.obeyed === 1 && e.routed_to_name) {
158
- agentMap.set(e.routed_to_name, (agentMap.get(e.routed_to_name) || 0) + 1);
159
- }
160
- }
161
- const topAgents = Array.from(agentMap.entries())
162
- .map(([agent, count]) => ({ agent, count }))
163
- .sort((a, b) => b.count - a.count)
164
- .slice(0, 5);
165
-
166
- return { totalPrompts, delegations, rateNum, topAgents };
167
- }
168
-
169
- private aggregateSkills(week: WeekRange): WeeklyReport['skills'] {
170
- const invocations = this.storage.querySkillInvocations({
171
- since: week.startMs,
172
- limit: 100000,
173
- }).filter(inv => inv.timestamp < week.endMs);
174
-
175
- const skillMap = new Map<string, number>();
176
- for (const inv of invocations) {
177
- skillMap.set(inv.skill_id, (skillMap.get(inv.skill_id) || 0) + 1);
178
- }
179
-
180
- const topSkills = Array.from(skillMap.entries())
181
- .map(([skill_id, count]) => ({ skill_id, count }))
182
- .sort((a, b) => b.count - a.count)
183
- .slice(0, 5);
184
-
185
- const allSkillIds = this.skillRegistry
186
- ? this.skillRegistry.getAll().map(s => s.id)
187
- : [];
188
- const usedSet = new Set(skillMap.keys());
189
- const neverUsed = allSkillIds.filter(id => !usedSet.has(id));
190
-
191
- return {
192
- invocations: invocations.length,
193
- distinct: skillMap.size,
194
- topSkills,
195
- neverUsed,
196
- };
197
- }
198
-
199
- private aggregateTools(week: WeekRange): WeeklyReport['tools'] {
200
- // H2 Phase 3: 改用 facade。
201
- // Phase 2 偏差:spec 列出的 aggregateToolUsage({ since, until, ... }) 实际只实现了
202
- // since/limit/hook_type,缺 until。这里用 queryEventsByTimeRange + 内存聚合保留
203
- // 旧 SQL 的 [since, until) 半开区间语义(changelog 已记)。
204
- const preEvents = this.storage.queryEventsByTimeRange({
205
- since: week.startISO,
206
- until: week.endISO,
207
- }).filter(e => e.hook_type === 'PreToolUse' && e.tool_name);
208
-
209
- const toolCount = new Map<string, number>();
210
- for (const ev of preEvents) {
211
- const name = ev.tool_name as string;
212
- if (!name) continue;
213
- toolCount.set(name, (toolCount.get(name) || 0) + 1);
214
- }
215
- const toolRows = Array.from(toolCount.entries())
216
- .map(([tool_name, cnt]) => ({ tool_name, cnt }))
217
- .sort((a, b) => b.cnt - a.cnt);
218
-
219
- const totalCalls = toolRows.reduce((sum, r) => sum + r.cnt, 0);
220
- const topTools = toolRows.slice(0, 5).map(r => ({ name: r.tool_name, count: r.cnt }));
221
-
222
- // Failure rate: facade 提供 [since, until) 半开区间精确计算。
223
- const failure = this.storage.aggregateToolFailureRate({
224
- since: week.startISO,
225
- until: week.endISO,
226
- });
227
-
228
- const failureRate = failure.post_total > 0
229
- ? `${((failure.failed / failure.post_total) * 100).toFixed(1)}%`
230
- : '0.0%';
231
-
232
- return {
233
- totalCalls,
234
- topTools,
235
- failureRate,
236
- };
237
- }
238
-
239
- private aggregateFiles(week: WeekRange): WeeklyReport['files'] {
240
- // H2 Phase 3: 改用 facade 聚合方法。
241
- const rows = this.storage.queryFileEditInputs({
242
- since: week.startISO,
243
- until: week.endISO,
244
- tool_names: Array.from(FILE_EDIT_TOOLS),
245
- });
246
-
247
- const fileMap = new Map<string, number>();
248
- let totalEdits = 0;
249
- for (const row of rows) {
250
- try {
251
- const input = JSON.parse(row.tool_input) as { file_path?: string; notebook_path?: string };
252
- const path = input.file_path || input.notebook_path;
253
- if (typeof path === 'string' && path.length > 0) {
254
- fileMap.set(path, (fileMap.get(path) || 0) + 1);
255
- totalEdits++;
256
- }
257
- } catch {
258
- // skip malformed JSON
259
- }
260
- }
261
-
262
- const topEdited = Array.from(fileMap.entries())
263
- .map(([path, editCount]) => ({ path, editCount }))
264
- .sort((a, b) => b.editCount - a.editCount)
265
- .slice(0, 5);
266
-
267
- return { topEdited, totalEdits };
268
- }
269
-
270
- private aggregateAnomalies(_week: WeekRange): WeeklyReport['anomalies'] {
271
- // Anomaly aggregation is delegated to AntiPatternDetector
272
- // (exposed separately via /api/insights). Keep empty here.
273
- return [];
274
- }
275
-
276
-
277
- // ── Helper methods ──────────────────────────────────────────────────
278
-
279
- /**
280
- * 计算 ISO 周的起止时间(周一 00:00:00 — 下周一 00:00:00)。
281
- * weekOffset: 0 = 本周, -1 = 上周, -2 = 上上周
282
- */
283
- private computeWeekRange(weekOffset: number): WeekRange {
284
- const now = new Date();
285
- // 计算本周一(ISO week 起点)
286
- const dayOfWeek = now.getDay(); // 0=Sun, 1=Mon, ...
287
- const daysFromMonday = (dayOfWeek + 6) % 7; // Mon=0, Tue=1, ..., Sun=6
288
-
289
- const monday = new Date(
290
- now.getFullYear(),
291
- now.getMonth(),
292
- now.getDate() - daysFromMonday + weekOffset * 7,
293
- 0, 0, 0, 0,
294
- );
295
- const nextMonday = new Date(monday);
296
- nextMonday.setDate(monday.getDate() + 7);
297
-
298
- return {
299
- startMs: monday.getTime(),
300
- endMs: nextMonday.getTime(),
301
- startISO: monday.toISOString(),
302
- endISO: nextMonday.toISOString(),
303
- isoWeekNumber: getISOWeekNumber(monday),
304
- };
305
- }
306
-
307
-
308
- // ── Markdown rendering ──────────────────────────────────────────────
309
-
310
- toMarkdown(report: WeeklyReport): string {
311
- const { week, overview, agentDelegation, skills, tools, files, anomalies } = report;
312
-
313
- const lines: string[] = [];
314
- lines.push(`# 周报 — 第 ${week.isoWeekNumber} 周`);
315
- lines.push('');
316
- lines.push(`**周期**: ${week.start.slice(0, 10)} ~ ${week.end.slice(0, 10)}`);
317
- lines.push(`**生成时间**: ${report.generatedAt}`);
318
- lines.push('');
319
-
320
- lines.push('## 概览');
321
- lines.push('');
322
- lines.push(`- 总会话数: **${overview.totalSessions}**`);
323
- lines.push(`- 总事件数: **${overview.totalEvents}**`);
324
- lines.push(`- 总任务数: **${overview.totalTasks}**`);
325
- lines.push(`- 活跃天数: **${overview.activeDays}** 天`);
326
- lines.push(`- 活跃项目: ${overview.activeProjects.length} 个`);
327
- if (overview.activeProjects.length > 0) {
328
- for (const p of overview.activeProjects) {
329
- lines.push(` - \`${p}\``);
330
- }
331
- }
332
- lines.push('');
333
-
334
- lines.push('## Agent 委托');
335
- lines.push('');
336
- lines.push(`- 总路由数: **${agentDelegation.totalPrompts}**`);
337
- lines.push(`- 委托数: **${agentDelegation.delegations}**`);
338
- lines.push(`- 委托率: **${agentDelegation.rate}** (环比 ${agentDelegation.weekOverWeek})`);
339
- if (agentDelegation.topAgents.length > 0) {
340
- lines.push('');
341
- lines.push('**Top Agents**:');
342
- lines.push('');
343
- lines.push('| Agent | 调用次数 |');
344
- lines.push('| --- | ---: |');
345
- for (const a of agentDelegation.topAgents) {
346
- lines.push(`| ${a.agent} | ${a.count} |`);
347
- }
348
- }
349
- lines.push('');
350
-
351
- lines.push('## Skills');
352
- lines.push('');
353
- lines.push(`- 调用总数: **${skills.invocations}**`);
354
- lines.push(`- 不同 Skill: **${skills.distinct}**`);
355
- if (skills.topSkills.length > 0) {
356
- lines.push('');
357
- lines.push('**Top Skills**:');
358
- lines.push('');
359
- lines.push('| Skill | 调用次数 |');
360
- lines.push('| --- | ---: |');
361
- for (const s of skills.topSkills) {
362
- lines.push(`| ${s.skill_id} | ${s.count} |`);
363
- }
364
- }
365
- if (skills.neverUsed.length > 0) {
366
- lines.push('');
367
- lines.push(`**从未使用** (${skills.neverUsed.length}): ${skills.neverUsed.map(s => `\`${s}\``).join(', ')}`);
368
- }
369
- lines.push('');
370
-
371
- lines.push('## Tools');
372
- lines.push('');
373
- lines.push(`- 调用总数: **${tools.totalCalls}**`);
374
- lines.push(`- 失败率: **${tools.failureRate}**`);
375
- if (tools.topTools.length > 0) {
376
- lines.push('');
377
- lines.push('**Top Tools**:');
378
- lines.push('');
379
- lines.push('| Tool | 调用次数 |');
380
- lines.push('| --- | ---: |');
381
- for (const t of tools.topTools) {
382
- lines.push(`| ${t.name} | ${t.count} |`);
383
- }
384
- }
385
- lines.push('');
386
-
387
- lines.push('## Files');
388
- lines.push('');
389
- lines.push(`- 编辑总数: **${files.totalEdits}**`);
390
- if (files.topEdited.length > 0) {
391
- lines.push('');
392
- lines.push('**Top Edited**:');
393
- lines.push('');
394
- lines.push('| 文件 | 编辑次数 |');
395
- lines.push('| --- | ---: |');
396
- for (const f of files.topEdited) {
397
- lines.push(`| \`${f.path}\` | ${f.editCount} |`);
398
- }
399
- }
400
- lines.push('');
401
-
402
- lines.push('## 异常');
403
- lines.push('');
404
- if (anomalies.length === 0) {
405
- lines.push('本周无异常。');
406
- } else {
407
- for (const a of anomalies) {
408
- lines.push(`- **${a.type}**: ${a.description}`);
409
- }
410
- }
411
- lines.push('');
412
-
413
- return lines.join('\n');
414
- }
415
- }
416
-
417
- /**
418
- * 计算 ISO 8601 周数。
419
- */
420
- function getISOWeekNumber(date: Date): number {
421
- const target = new Date(date.getTime());
422
- // ISO 周以周四为锚点
423
- target.setHours(0, 0, 0, 0);
424
- target.setDate(target.getDate() + 3 - ((target.getDay() + 6) % 7));
425
- const week1 = new Date(target.getFullYear(), 0, 4);
426
- return 1 + Math.round(
427
- ((target.getTime() - week1.getTime()) / 86400000
428
- - 3 + ((week1.getDay() + 6) % 7)) / 7,
429
- );
430
- }
431
-
@@ -1,54 +0,0 @@
1
- /**
2
- * Web API Authorization middleware
3
- *
4
- * 复用 daemon 的 auth token 机制(~/.claude-forge/daemon.token),
5
- * 对写操作(POST/PUT/DELETE)强制校验 Authorization: Bearer <token>。
6
- *
7
- * 设计要点:
8
- * - 同源本机场景:token 文件 chmod 600,读到即等价身份确认
9
- * - token 缺失(daemon 极早期启动)时放行以免死锁,由 daemon lifecycle 负责尽快写入
10
- * - 读操作(GET)不走这里,保留前端轮询的向后兼容
11
- */
12
-
13
- import fs from 'fs';
14
- import type { Request, Response, NextFunction } from 'express';
15
- import { FORGE_PATHS } from '../core/constants.js';
16
-
17
- const TOKEN_FILE = FORGE_PATHS.daemonToken();
18
-
19
- /** 读取当前 daemon auth token,不存在或读取失败返回 null */
20
- export function readAuthToken(): string | null {
21
- try {
22
- if (!fs.existsSync(TOKEN_FILE)) return null;
23
- return fs.readFileSync(TOKEN_FILE, 'utf-8').trim() || null;
24
- } catch {
25
- return null;
26
- }
27
- }
28
-
29
- /**
30
- * Express middleware:强制 Authorization: Bearer <token> 校验
31
- *
32
- * - token 文件缺失:放行(早期启动保护)
33
- * - header 缺失或不匹配:401
34
- */
35
- export function requireAuth(req: Request, res: Response, next: NextFunction): void {
36
- const expected = readAuthToken();
37
- if (!expected) {
38
- // 早期启动保护:daemon 尚未写 token,避免自锁
39
- next();
40
- return;
41
- }
42
-
43
- const auth = req.header('Authorization') ?? '';
44
- const match = auth.match(/^Bearer\s+(.+)$/);
45
- if (!match || match[1].trim() !== expected) {
46
- res.status(401).json({
47
- error: 'AUTH_REQUIRED',
48
- message:
49
- 'Include "Authorization: Bearer <token>" header. Token is stored at ~/.claude-forge/daemon.token',
50
- });
51
- return;
52
- }
53
- next();
54
- }