@winspan/claude-forge 8.53.2 → 8.54.4

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