@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,355 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { homedir } from 'node:os';
4
- import matter from 'gray-matter';
5
- import { fileURLToPath } from 'node:url';
6
- import { logger } from '../core/utils/logger.js';
7
- import { loadOfficialSkills, OFFICIAL_SKILL_KEYWORDS } from './official-skills.js';
8
- import { SemanticSkillMatcher } from './semantic-matcher.js';
9
-
10
- const SKILLS_DIR = path.join(homedir(), '.claude', 'skills');
11
-
12
- export interface Skill {
13
- id: string;
14
- name: string;
15
- keywords: string[];
16
- content: string;
17
- path: string;
18
- isOfficial?: boolean; // Mark official built-in skills
19
- description?: string; // Optional description from frontmatter (used by agent-skills format)
20
- }
21
-
22
- /**
23
- * Simple skill registry that scans ~/.claude/skills/*.md
24
- * and matches by keywords in frontmatter
25
- */
26
- export class SkillRegistry {
27
- private skills: Map<string, Skill> = new Map();
28
- private semanticMatcher: SemanticSkillMatcher | null = null;
29
-
30
- constructor(apiKey?: string, model?: string, baseURL?: string) {
31
- this.scan();
32
-
33
- // Initialize semantic matcher if API key is provided
34
- if (apiKey) {
35
- this.semanticMatcher = new SemanticSkillMatcher(apiKey, model, baseURL);
36
- logger.info('[SkillRegistry] Semantic matching enabled');
37
- } else {
38
- logger.debug('[SkillRegistry] Semantic matching disabled (no API key)');
39
- }
40
- }
41
-
42
- /**
43
- * Resolve the directory containing official built-in skill .md files.
44
- * Uses import.meta.url for ESM compatibility (works in both dev and npm-installed environments).
45
- */
46
- private resolveBuiltinDir(): string {
47
- const thisFile = fileURLToPath(import.meta.url);
48
- return path.join(path.dirname(thisFile), 'official');
49
- }
50
-
51
- /**
52
- * Scan ~/.claude/skills/ for markdown files with frontmatter
53
- * Official skills are loaded first, then user skills (which can override)
54
- *
55
- * Supports two formats:
56
- * 1. Flat format: ~/.claude/skills/skill-name.md
57
- * 2. Directory format: ~/.claude/skills/skill-name/SKILL.md (agent-skills format)
58
- */
59
- private scan(): void {
60
- // 1. Load official built-in skills from src/skills/official/*.md
61
- let officialCount = 0;
62
- try {
63
- const officialSkills = loadOfficialSkills(this.resolveBuiltinDir());
64
- for (const officialSkill of officialSkills) {
65
- // Merge extended keywords from OFFICIAL_SKILL_KEYWORDS if available
66
- const extendedKeywords = OFFICIAL_SKILL_KEYWORDS[officialSkill.name] || officialSkill.keywords;
67
- this.skills.set(officialSkill.name, {
68
- id: officialSkill.name,
69
- name: officialSkill.name,
70
- keywords: extendedKeywords,
71
- content: officialSkill.content,
72
- path: this.resolveBuiltinDir() + '/' + officialSkill.name + '.md',
73
- isOfficial: true,
74
- description: officialSkill.description,
75
- });
76
- officialCount++;
77
- }
78
- } catch (err) {
79
- logger.warn(`[SkillRegistry] Failed to load official skills: ${err}`);
80
- }
81
-
82
- logger.info(`Loaded ${officialCount} official skill(s)`);
83
-
84
- // 2. Load user skills from ~/.claude/skills/ (can override official skills)
85
- if (!fs.existsSync(SKILLS_DIR)) {
86
- logger.debug(`Skills directory not found: ${SKILLS_DIR}`);
87
- return;
88
- }
89
-
90
- const entries = fs.readdirSync(SKILLS_DIR, { withFileTypes: true });
91
- let userCount = 0;
92
-
93
- for (const entry of entries) {
94
- try {
95
- let filePath: string;
96
- let id: string;
97
-
98
- if (entry.isFile() && entry.name.endsWith('.md')) {
99
- // Format 1: Flat .md file
100
- filePath = path.join(SKILLS_DIR, entry.name);
101
- id = path.basename(entry.name, '.md');
102
- } else if (entry.isDirectory()) {
103
- // Format 2: Directory with SKILL.md
104
- const skillMdPath = path.join(SKILLS_DIR, entry.name, 'SKILL.md');
105
- if (!fs.existsSync(skillMdPath)) {
106
- continue; // Skip directories without SKILL.md
107
- }
108
- filePath = skillMdPath;
109
- id = entry.name;
110
- } else {
111
- continue; // Skip other file types
112
- }
113
-
114
- const content = fs.readFileSync(filePath, 'utf-8');
115
- const parsed = matter(content);
116
- const { data, content: body } = parsed;
117
-
118
- const name = typeof data.name === 'string' ? data.name : id;
119
- // 兼容两种字段名:keywords(claude-forge 标准)和 tags(Claude Code 官方 skill 约定)
120
- const rawKeywords: unknown = data.keywords ?? data.tags;
121
- const keywords: string[] = Array.isArray(rawKeywords)
122
- ? rawKeywords.filter((k): k is string => typeof k === 'string')
123
- : [];
124
- const description = typeof data.description === 'string' ? data.description : undefined;
125
-
126
- // User skills override official skills, but merge keywords from OFFICIAL_SKILL_KEYWORDS
127
- const extendedKeywords = OFFICIAL_SKILL_KEYWORDS[id];
128
- const mergedKeywords = extendedKeywords
129
- ? [...new Set([...keywords, ...extendedKeywords])]
130
- : keywords;
131
-
132
- this.skills.set(id, {
133
- id,
134
- name,
135
- keywords: mergedKeywords,
136
- content: body.trim(),
137
- path: filePath,
138
- isOfficial: false,
139
- description,
140
- });
141
- userCount++;
142
- } catch (err) {
143
- logger.warn(`Failed to parse skill ${entry.name}: ${err}`);
144
- }
145
- }
146
-
147
- if (userCount > 0) {
148
- logger.info(`Loaded ${userCount} user skill(s) from ${SKILLS_DIR}`);
149
- }
150
- }
151
-
152
- /**
153
- * Match a prompt against skill keywords with hybrid approach:
154
- * 1. Try semantic matching (AI-powered) if available
155
- * 2. Fall back to keyword matching if semantic fails or not configured
156
- */
157
- async match(prompt: string, keywords: string[] = [], context?: { recentFiles?: string[] }): Promise<Skill | null> {
158
- const result = await this.matchWithConfidence(prompt, keywords, context);
159
- return result?.skill ?? null;
160
- }
161
-
162
- /**
163
- * Like match(), but also returns the confidence score (0-100) so callers
164
- * can compare across alternatives (e.g. agent vs skill routing).
165
- */
166
- async matchWithConfidence(
167
- prompt: string,
168
- keywords: string[] = [],
169
- context?: { recentFiles?: string[] },
170
- ): Promise<{ skill: Skill; confidence: number; source: 'semantic' | 'keyword' } | null> {
171
- // Try semantic matching first
172
- if (this.semanticMatcher) {
173
- try {
174
- const semanticResult = await this.semanticMatcher.match(
175
- Array.from(this.skills.values()),
176
- {
177
- prompt,
178
- intentKeywords: keywords,
179
- recentFiles: context?.recentFiles,
180
- }
181
- );
182
-
183
- if (semanticResult) {
184
- logger.info(`[SkillRegistry] Semantic match: ${semanticResult.skill.id} (${semanticResult.confidence}%)`);
185
- return { skill: semanticResult.skill, confidence: semanticResult.confidence, source: 'semantic' };
186
- }
187
- } catch (err) {
188
- logger.warn(`[SkillRegistry] Semantic matching failed, falling back to keyword matching: ${err}`);
189
- }
190
- }
191
-
192
- // Fall back to keyword matching
193
- const kwSkill = await this.matchKeywords(prompt, keywords, context);
194
- if (kwSkill) {
195
- // Keyword matching has no real confidence; assign a conservative 60%
196
- return { skill: kwSkill, confidence: 60, source: 'keyword' };
197
- }
198
- return null;
199
- }
200
-
201
- /**
202
- * Keyword-based matching (fallback method)
203
- * Supports fallback to description-based substring matching when keywords are empty
204
- */
205
- private async matchKeywords(
206
- prompt: string,
207
- keywords: string[] = [],
208
- context?: { recentFiles?: string[] }
209
- ): Promise<Skill | null> {
210
- const promptLower = prompt.toLowerCase();
211
- const extraLower = keywords.map(k => k.toLowerCase());
212
-
213
- let bestSkill: Skill | null = null;
214
- let bestScore = 0;
215
- let bestCandidate: Skill | null = null;
216
- let bestCandidateScore = 0;
217
-
218
- for (const skill of this.skills.values()) {
219
- let score = 0;
220
-
221
- // If skill has keywords, use keyword matching
222
- if (skill.keywords.length > 0) {
223
- for (const kw of skill.keywords) {
224
- const kwLower = kw.toLowerCase();
225
-
226
- // Check if keyword appears in prompt or intent keywords
227
- if (this.matchKeywordFlexible(promptLower, kwLower)) {
228
- score += 1;
229
- }
230
- if (extraLower.some(ek => this.matchKeywordFlexible(ek, kwLower))) {
231
- score += 1;
232
- }
233
- }
234
- } else if (skill.description) {
235
- // Fallback path 1: Use description substring matching when keywords are empty
236
- const descLower = skill.description.toLowerCase();
237
- if (descLower.includes(promptLower) || promptLower.includes(descLower)) {
238
- score = 1; // Give a base score for description match
239
- }
240
- }
241
- // Fallback path 2: If no keywords and no description, score remains 0
242
- // This allows SemanticSkillMatcher to take over
243
-
244
- // Track best candidate regardless of threshold
245
- if (score > bestCandidateScore) {
246
- bestCandidateScore = score;
247
- bestCandidate = skill;
248
- }
249
-
250
- // Official skills get priority: require 1+ match, user skills require 2+ matches
251
- const threshold = skill.isOfficial ? 1 : 2;
252
-
253
- if (score >= threshold && score > bestScore) {
254
- bestScore = score;
255
- bestSkill = skill;
256
- } else if (
257
- score === bestScore &&
258
- score >= threshold &&
259
- skill.isOfficial &&
260
- !bestSkill?.isOfficial
261
- ) {
262
- // Tie-break: prefer official skill when both meet threshold
263
- bestSkill = skill;
264
- }
265
- }
266
-
267
- if (bestSkill) {
268
- logger.info(`[SkillRegistry] Keyword match: ${bestSkill.id} (score: ${bestScore})`);
269
- } else {
270
- logger.debug(`[SkillRegistry] Best keyword candidate: ${bestCandidate?.id ?? 'none'} (score: ${bestCandidateScore})`);
271
- }
272
-
273
- return bestSkill;
274
- }
275
-
276
- /**
277
- * Flexible keyword matching with word boundary for English, substring for Chinese
278
- */
279
- private matchKeywordFlexible(text: string, keyword: string): boolean {
280
- // For Chinese or multi-word keywords, use simple includes
281
- if (/[一-龥]/.test(keyword) || keyword.includes(' ')) {
282
- return text.includes(keyword);
283
- }
284
-
285
- // For single English words, require word boundaries to avoid false positives
286
- // e.g., "test" won't match "latest"
287
- const regex = new RegExp(`\\b${keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`);
288
- return regex.test(text);
289
- }
290
-
291
- /**
292
- * Match with full result details (for debugging/logging)
293
- */
294
- async matchWithDetails(prompt: string, keywords: string[] = [], context?: { recentFiles?: string[] }) {
295
- const promptLower = prompt.toLowerCase();
296
- const extraLower = keywords.map(k => k.toLowerCase());
297
-
298
- const results = [];
299
- for (const skill of this.skills.values()) {
300
- let score = 0;
301
- const matchedKeywords: string[] = [];
302
-
303
- for (const kw of skill.keywords) {
304
- const kwLower = kw.toLowerCase();
305
-
306
- if (this.matchKeywordFlexible(promptLower, kwLower)) {
307
- score += 1;
308
- matchedKeywords.push(kw);
309
- }
310
- if (extraLower.some(ek => this.matchKeywordFlexible(ek, kwLower))) {
311
- score += 1;
312
- }
313
- }
314
-
315
- if (score >= 1) {
316
- results.push({
317
- skill,
318
- confidence: Math.min(100, score * 20), // Simple scoring: 1 match = 20%, 5 matches = 100%
319
- matchedKeywords,
320
- });
321
- }
322
- }
323
-
324
- results.sort((a, b) => b.confidence - a.confidence);
325
- return results;
326
- }
327
-
328
- /** Return all loaded skills */
329
- getAll(): Skill[] {
330
- return Array.from(this.skills.values());
331
- }
332
-
333
- /** Get a skill by ID */
334
- get(id: string): Skill | undefined {
335
- return this.skills.get(id);
336
- }
337
-
338
- /**
339
- * Get skill manifest (id + description + keywords) for Agent pre-declaration
340
- */
341
- getManifest(): Array<{ id: string; name: string; description: string; keywords: string[] }> {
342
- return this.getAll().map(skill => ({
343
- id: skill.id,
344
- name: skill.name,
345
- description: skill.description || '',
346
- keywords: skill.keywords,
347
- }));
348
- }
349
-
350
- /** Re-scan the skills directory */
351
- reload(): void {
352
- this.skills.clear();
353
- this.scan();
354
- }
355
- }
@@ -1,234 +0,0 @@
1
- /**
2
- * AI-powered semantic skill matcher using Claude API
3
- * Provides more accurate skill recommendations by understanding user intent
4
- */
5
-
6
- import Anthropic from '@anthropic-ai/sdk';
7
- import type { Skill } from './registry.js';
8
- import { logger } from '../core/utils/logger.js';
9
- import { DEFAULTS } from '../core/constants.js';
10
-
11
- export interface SemanticMatchResult {
12
- skill: Skill;
13
- confidence: number; // 0-100
14
- reasoning: string;
15
- }
16
-
17
- export interface SemanticMatchContext {
18
- prompt: string;
19
- intentKeywords?: string[];
20
- recentFiles?: string[];
21
- projectPath?: string;
22
- }
23
-
24
- /**
25
- * Semantic matcher using Claude API for intent understanding
26
- */
27
- export class SemanticSkillMatcher {
28
- private client: Anthropic | null = null;
29
- private model: string;
30
- private cache: Map<string, SemanticMatchResult | null> = new Map();
31
- private readonly CACHE_TTL = 5 * 60 * 1000; // 5 minutes
32
- private cacheTimestamps: Map<string, number> = new Map();
33
-
34
- constructor(apiKey?: string, model?: string, baseURL?: string) {
35
- this.model = model || DEFAULTS.AI_MODEL;
36
- if (apiKey) {
37
- this.client = new Anthropic({ apiKey, baseURL });
38
- }
39
- }
40
-
41
- /**
42
- * Match skills using semantic understanding
43
- * Falls back to keyword matching if API is not configured
44
- */
45
- async match(skills: Skill[], context: SemanticMatchContext): Promise<SemanticMatchResult | null> {
46
- // Check cache first
47
- const cacheKey = this.getCacheKey(context.prompt);
48
- const cached = this.getFromCache(cacheKey);
49
- if (cached !== undefined) {
50
- return cached;
51
- }
52
-
53
- // If no API key, return null (caller will fall back to keyword matching)
54
- if (!this.client) {
55
- logger.debug('[SemanticMatcher] No API key configured, skipping semantic matching');
56
- return null;
57
- }
58
-
59
- try {
60
- const result = await this.matchWithAI(skills, context);
61
- this.setCache(cacheKey, result);
62
- return result;
63
- } catch (err) {
64
- logger.warn(`[SemanticMatcher] AI matching failed: ${err}`);
65
- return null; // Fall back to keyword matching
66
- }
67
- }
68
-
69
- /**
70
- * Use Claude API to understand intent and match skills
71
- */
72
- private async matchWithAI(
73
- skills: Skill[],
74
- context: SemanticMatchContext
75
- ): Promise<SemanticMatchResult | null> {
76
- if (!this.client) return null;
77
-
78
- // Build skill descriptions for the prompt
79
- const skillDescriptions = skills
80
- .filter(s => s.isOfficial) // Only consider official skills for AI matching
81
- .map((s, idx) => `${idx + 1}. **${s.id}**: ${s.name} - ${this.extractDescription(s)}`)
82
- .join('\n');
83
-
84
- const prompt = this.buildMatchingPrompt(context, skillDescriptions);
85
-
86
- const response = await this.client.messages.create({
87
- model: this.model,
88
- max_tokens: 500,
89
- temperature: 0,
90
- messages: [
91
- {
92
- role: 'user',
93
- content: prompt,
94
- },
95
- ],
96
- });
97
-
98
- const content = response.content[0];
99
- if (content.type !== 'text') {
100
- return null;
101
- }
102
-
103
- return this.parseAIResponse(content.text, skills);
104
- }
105
-
106
- /**
107
- * Build the matching prompt for Claude API
108
- */
109
- private buildMatchingPrompt(context: SemanticMatchContext, skillDescriptions: string): string {
110
- return `You are a skill recommendation system. Analyze the user's request and recommend the most relevant skill.
111
-
112
- User Request: "${context.prompt}"
113
-
114
- ${context.intentKeywords && context.intentKeywords.length > 0 ? `Intent Keywords: ${context.intentKeywords.join(', ')}` : ''}
115
-
116
- Available Skills:
117
- ${skillDescriptions}
118
-
119
- Instructions:
120
- 1. Understand the user's intent and task type
121
- 2. Match to the MOST relevant skill (only ONE skill)
122
- 3. If no skill is clearly relevant (confidence < 60%), respond with "NONE"
123
- 4. Respond in this exact format:
124
-
125
- SKILL_ID: <skill-id or NONE>
126
- CONFIDENCE: <0-100>
127
- REASONING: <one sentence explaining why this skill matches or why no skill matches>
128
-
129
- Example responses:
130
- - SKILL_ID: official-tdd
131
- CONFIDENCE: 85
132
- REASONING: User wants to write tests before implementation, which is the core of TDD.
133
-
134
- - SKILL_ID: NONE
135
- CONFIDENCE: 30
136
- REASONING: Request is about simple documentation update, no specialized skill needed.`;
137
- }
138
-
139
- /**
140
- * Parse AI response into match result
141
- */
142
- private parseAIResponse(response: string, skills: Skill[]): SemanticMatchResult | null {
143
- const lines = response.trim().split('\n');
144
- let skillId: string | null = null;
145
- let confidence = 0;
146
- let reasoning = '';
147
-
148
- for (const line of lines) {
149
- const trimmed = line.trim();
150
- if (trimmed.startsWith('SKILL_ID:')) {
151
- skillId = trimmed.substring('SKILL_ID:'.length).trim();
152
- } else if (trimmed.startsWith('CONFIDENCE:')) {
153
- confidence = parseInt(trimmed.substring('CONFIDENCE:'.length).trim(), 10);
154
- } else if (trimmed.startsWith('REASONING:')) {
155
- reasoning = trimmed.substring('REASONING:'.length).trim();
156
- }
157
- }
158
-
159
- // If AI says NONE or confidence too low, return null
160
- if (!skillId || skillId === 'NONE' || confidence < 60) {
161
- logger.debug(`[SemanticMatcher] No match: ${reasoning}`);
162
- return null;
163
- }
164
-
165
- // Find the matched skill
166
- const skill = skills.find(s => s.id === skillId);
167
- if (!skill) {
168
- logger.warn(`[SemanticMatcher] AI returned unknown skill: ${skillId}`);
169
- return null;
170
- }
171
-
172
- logger.info(`[SemanticMatcher] Matched ${skillId} with ${confidence}% confidence`);
173
- return { skill, confidence, reasoning };
174
- }
175
-
176
- /**
177
- * Extract description from skill content
178
- * Prioritizes frontmatter description over content extraction
179
- */
180
- private extractDescription(skill: Skill): string {
181
- // Prefer frontmatter description if available (agent-skills format)
182
- if (skill.description) {
183
- return skill.description;
184
- }
185
-
186
- // Fallback: Try to extract first line of description from content
187
- const lines = skill.content.split('\n');
188
- for (const line of lines) {
189
- const trimmed = line.trim();
190
- if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('---')) {
191
- return trimmed.substring(0, 100);
192
- }
193
- }
194
- return skill.keywords.join(', ');
195
- }
196
-
197
- /**
198
- * Cache management
199
- */
200
- private getCacheKey(prompt: string): string {
201
- return prompt.toLowerCase().substring(0, 200);
202
- }
203
-
204
- private getFromCache(key: string): SemanticMatchResult | null | undefined {
205
- const timestamp = this.cacheTimestamps.get(key);
206
- if (!timestamp || Date.now() - timestamp > this.CACHE_TTL) {
207
- this.cache.delete(key);
208
- this.cacheTimestamps.delete(key);
209
- return undefined;
210
- }
211
- return this.cache.get(key);
212
- }
213
-
214
- private setCache(key: string, result: SemanticMatchResult | null): void {
215
- this.cache.set(key, result);
216
- this.cacheTimestamps.set(key, Date.now());
217
-
218
- // Limit cache size to 100 entries
219
- if (this.cache.size > 100) {
220
- const oldestKey = Array.from(this.cacheTimestamps.entries())
221
- .sort((a, b) => a[1] - b[1])[0][0];
222
- this.cache.delete(oldestKey);
223
- this.cacheTimestamps.delete(oldestKey);
224
- }
225
- }
226
-
227
- /**
228
- * Clear cache
229
- */
230
- clearCache(): void {
231
- this.cache.clear();
232
- this.cacheTimestamps.clear();
233
- }
234
- }