@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,495 +0,0 @@
1
- /**
2
- * skill_invocations 工作流追踪扩展测试
3
- *
4
- * 覆盖:
5
- * 1. parseWorkflowMeta() 各种 reason 输入下的解析行为
6
- * 2. writeSkillInvocation 持久化新字段并能被 querySkillInvocations 取回
7
- * 3. queryWorkflowProgress 按 route_request_id 聚合 phases / 计数 / 时间戳
8
- * 4. 增量迁移:模拟旧库(没有 workflow / phase / feature_slug / artifact_path 列),
9
- * 重建 storage 后 runMigrations 应自动补齐列与索引
10
- */
11
-
12
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
13
- import { mkdtempSync, rmSync } from 'node:fs';
14
- import { tmpdir } from 'node:os';
15
- import { join } from 'node:path';
16
- import { randomUUID } from 'node:crypto';
17
- import Database from 'better-sqlite3';
18
- import { SQLiteStorage } from '../../src/core/storage/sqlite.js';
19
- import { parseWorkflowMeta } from '../../src/skills/tools/skill-invoke.js';
20
-
21
- describe('parseWorkflowMeta', () => {
22
- it('解析 "bmad/analyze" → workflow + phase, feature_slug 为 null', () => {
23
- expect(parseWorkflowMeta('bmad/analyze')).toEqual({
24
- workflow: 'bmad',
25
- phase: 'analyze',
26
- feature_slug: null,
27
- });
28
- });
29
-
30
- it('解析 "bmad/design:login-feature" → 三个字段都有值', () => {
31
- expect(parseWorkflowMeta('bmad/design:login-feature')).toEqual({
32
- workflow: 'bmad',
33
- phase: 'design',
34
- feature_slug: 'login-feature',
35
- });
36
- });
37
-
38
- it('解析 "harness/safety-net" → 支持 phase 中含连字符', () => {
39
- expect(parseWorkflowMeta('harness/safety-net')).toEqual({
40
- workflow: 'harness',
41
- phase: 'safety-net',
42
- feature_slug: null,
43
- });
44
- });
45
-
46
- it('解析普通文本("plain text") → 全部为 null', () => {
47
- expect(parseWorkflowMeta('plain text')).toEqual({
48
- workflow: null,
49
- phase: null,
50
- feature_slug: null,
51
- });
52
- });
53
-
54
- it('空字符串 / undefined / null → 全部为 null', () => {
55
- expect(parseWorkflowMeta('')).toEqual({ workflow: null, phase: null, feature_slug: null });
56
- expect(parseWorkflowMeta(undefined)).toEqual({ workflow: null, phase: null, feature_slug: null });
57
- expect(parseWorkflowMeta(null)).toEqual({ workflow: null, phase: null, feature_slug: null });
58
- });
59
-
60
- it('大小写归一化:Bmad/Analyze → bmad/analyze', () => {
61
- expect(parseWorkflowMeta('Bmad/Analyze')).toEqual({
62
- workflow: 'bmad',
63
- phase: 'analyze',
64
- feature_slug: null,
65
- });
66
- });
67
-
68
- it('大小写归一化:BMAD/DESIGN:Login-Feature → 全部小写', () => {
69
- expect(parseWorkflowMeta('BMAD/DESIGN:Login-Feature')).toEqual({
70
- workflow: 'bmad',
71
- phase: 'design',
72
- feature_slug: 'login-feature',
73
- });
74
- });
75
-
76
- it('容忍尾部空白', () => {
77
- expect(parseWorkflowMeta('bmad/analyze ')).toEqual({
78
- workflow: 'bmad',
79
- phase: 'analyze',
80
- feature_slug: null,
81
- });
82
- });
83
-
84
- it('非法格式(空格在中间、workflow/phase 不符合规则)→ 全部为 null', () => {
85
- expect(parseWorkflowMeta('bmad / analyze')).toEqual({
86
- workflow: null,
87
- phase: null,
88
- feature_slug: null,
89
- });
90
- expect(parseWorkflowMeta('代码审查')).toEqual({
91
- workflow: null,
92
- phase: null,
93
- feature_slug: null,
94
- });
95
- // 数字开头不允许
96
- expect(parseWorkflowMeta('1bmad/analyze')).toEqual({
97
- workflow: null,
98
- phase: null,
99
- feature_slug: null,
100
- });
101
- });
102
-
103
- it('支持中文 feature_slug', () => {
104
- expect(parseWorkflowMeta('bmad/analyze:用户认证')).toEqual({
105
- workflow: 'bmad',
106
- phase: 'analyze',
107
- feature_slug: '用户认证',
108
- });
109
- });
110
-
111
- it('支持日文 feature_slug', () => {
112
- expect(parseWorkflowMeta('harness/reproduce:ログイン機能')).toEqual({
113
- workflow: 'harness',
114
- phase: 'reproduce',
115
- feature_slug: 'ログイン機能',
116
- });
117
- });
118
-
119
- it('支持混合字符 feature_slug', () => {
120
- expect(parseWorkflowMeta('bmad/design:user-auth-用户认证')).toEqual({
121
- workflow: 'bmad',
122
- phase: 'design',
123
- feature_slug: 'user-auth-用户认证',
124
- });
125
- });
126
-
127
- it('feature_slug 不允许包含空格或冒号', () => {
128
- expect(parseWorkflowMeta('bmad/analyze:user auth')).toEqual({
129
- workflow: null,
130
- phase: null,
131
- feature_slug: null,
132
- });
133
- expect(parseWorkflowMeta('bmad/analyze:user:auth')).toEqual({
134
- workflow: null,
135
- phase: null,
136
- feature_slug: null,
137
- });
138
- });
139
- });
140
-
141
- describe('SQLiteStorage: skill_invocations 工作流字段', () => {
142
- let tmp: string;
143
- let dbPath: string;
144
- let storage: SQLiteStorage;
145
-
146
- beforeEach(() => {
147
- tmp = mkdtempSync(join(tmpdir(), 'forge-skill-wf-'));
148
- dbPath = join(tmp, 'data.db');
149
- storage = new SQLiteStorage(dbPath);
150
- });
151
-
152
- afterEach(() => {
153
- try {
154
- storage.getDatabase().close();
155
- } catch {
156
- // already closed
157
- }
158
- rmSync(tmp, { recursive: true, force: true });
159
- });
160
-
161
- it('writeSkillInvocation 写入工作流字段后 query 能正确返回', () => {
162
- storage.writeSkillInvocation({
163
- id: 'inv-1',
164
- route_request_id: 'route-A',
165
- session_id: 'sess-1',
166
- agent_id: 'agent-x',
167
- skill_id: 'official-tdd',
168
- invocation_type: 'dynamic',
169
- reason: 'bmad/analyze',
170
- workflow: 'bmad',
171
- phase: 'analyze',
172
- feature_slug: null,
173
- artifact_path: null,
174
- depth: 0,
175
- success: 1,
176
- error: null,
177
- timestamp: Date.now(),
178
- });
179
-
180
- const rows = storage.querySkillInvocations({ session_id: 'sess-1' });
181
- expect(rows).toHaveLength(1);
182
- expect(rows[0].workflow).toBe('bmad');
183
- expect(rows[0].phase).toBe('analyze');
184
- expect(rows[0].feature_slug).toBeNull();
185
- expect(rows[0].artifact_path).toBeNull();
186
- });
187
-
188
- it('feature_slug + artifact_path 写入回读', () => {
189
- storage.writeSkillInvocation({
190
- id: 'inv-2',
191
- route_request_id: 'route-B',
192
- session_id: 'sess-1',
193
- agent_id: null,
194
- skill_id: 'official-design',
195
- invocation_type: 'dynamic',
196
- reason: 'bmad/design:login-feature',
197
- workflow: 'bmad',
198
- phase: 'design',
199
- feature_slug: 'login-feature',
200
- artifact_path: 'docs/login.md',
201
- depth: 0,
202
- success: 1,
203
- error: null,
204
- timestamp: Date.now(),
205
- });
206
-
207
- const rows = storage.querySkillInvocations({ session_id: 'sess-1' });
208
- expect(rows[0].feature_slug).toBe('login-feature');
209
- expect(rows[0].artifact_path).toBe('docs/login.md');
210
- });
211
-
212
- it('null 工作流字段写入回读为 null(向后兼容)', () => {
213
- storage.writeSkillInvocation({
214
- id: 'inv-3',
215
- route_request_id: null,
216
- session_id: 'sess-2',
217
- agent_id: null,
218
- skill_id: 'plain-skill',
219
- invocation_type: 'dynamic',
220
- reason: '普通调用,没有工作流标记',
221
- workflow: null,
222
- phase: null,
223
- feature_slug: null,
224
- artifact_path: null,
225
- depth: 0,
226
- success: 1,
227
- error: null,
228
- timestamp: Date.now(),
229
- });
230
-
231
- const rows = storage.querySkillInvocations({ session_id: 'sess-2' });
232
- expect(rows[0].workflow).toBeNull();
233
- expect(rows[0].phase).toBeNull();
234
- });
235
- });
236
-
237
- describe('SQLiteStorage: queryWorkflowProgress', () => {
238
- let tmp: string;
239
- let dbPath: string;
240
- let storage: SQLiteStorage;
241
-
242
- beforeEach(() => {
243
- tmp = mkdtempSync(join(tmpdir(), 'forge-wf-progress-'));
244
- dbPath = join(tmp, 'data.db');
245
- storage = new SQLiteStorage(dbPath);
246
- });
247
-
248
- afterEach(() => {
249
- try {
250
- storage.getDatabase().close();
251
- } catch {
252
- // already closed
253
- }
254
- rmSync(tmp, { recursive: true, force: true });
255
- });
256
-
257
- function seed(
258
- overrides: Partial<{
259
- route_request_id: string;
260
- session_id: string;
261
- workflow: string | null;
262
- phase: string | null;
263
- feature_slug: string | null;
264
- success: number;
265
- timestamp: number;
266
- }>,
267
- ): void {
268
- const t = overrides.timestamp ?? Date.now();
269
- storage.writeSkillInvocation({
270
- id: randomUUID(),
271
- route_request_id: overrides.route_request_id ?? 'route-default',
272
- session_id: overrides.session_id ?? 'sess-1',
273
- agent_id: 'agent-x',
274
- skill_id: 'skill-x',
275
- invocation_type: 'dynamic',
276
- reason: 'seed',
277
- workflow: overrides.workflow ?? null,
278
- phase: overrides.phase ?? null,
279
- feature_slug: overrides.feature_slug ?? null,
280
- artifact_path: null,
281
- depth: 0,
282
- success: overrides.success ?? 1,
283
- error: null,
284
- timestamp: t,
285
- });
286
- }
287
-
288
- it('按 route_request_id 聚合 phases,按时间顺序排列且去重', () => {
289
- const base = Date.now();
290
- seed({ route_request_id: 'route-A', workflow: 'bmad', phase: 'analyze', timestamp: base + 100 });
291
- seed({ route_request_id: 'route-A', workflow: 'bmad', phase: 'design', timestamp: base + 200 });
292
- // 同 phase 重复调用,去重后只算一次
293
- seed({ route_request_id: 'route-A', workflow: 'bmad', phase: 'design', timestamp: base + 300 });
294
- seed({ route_request_id: 'route-A', workflow: 'bmad', phase: 'implement', timestamp: base + 400 });
295
-
296
- const result = storage.queryWorkflowProgress({ session_id: 'sess-1' });
297
- expect(result).toHaveLength(1);
298
- expect(result[0].route_request_id).toBe('route-A');
299
- expect(result[0].workflow).toBe('bmad');
300
- expect(result[0].phases_completed).toEqual(['analyze', 'design', 'implement']);
301
- expect(result[0].total_invocations).toBe(4);
302
- expect(result[0].success_count).toBe(4);
303
- expect(result[0].first_at).toBe(base + 100);
304
- expect(result[0].last_at).toBe(base + 400);
305
- });
306
-
307
- it('忽略 workflow 为 null 的调用', () => {
308
- const base = Date.now();
309
- seed({ route_request_id: 'route-A', workflow: 'bmad', phase: 'analyze', timestamp: base + 100 });
310
- // 普通调用,不应被纳入聚合
311
- seed({ route_request_id: 'route-A', workflow: null, phase: null, timestamp: base + 200 });
312
-
313
- const result = storage.queryWorkflowProgress({ session_id: 'sess-1' });
314
- expect(result[0].total_invocations).toBe(1);
315
- expect(result[0].phases_completed).toEqual(['analyze']);
316
- });
317
-
318
- it('按 workflow 过滤', () => {
319
- const base = Date.now();
320
- seed({ route_request_id: 'route-A', workflow: 'bmad', phase: 'analyze', timestamp: base + 100 });
321
- seed({ route_request_id: 'route-B', workflow: 'harness', phase: 'safety-net', timestamp: base + 200 });
322
-
323
- const bmadOnly = storage.queryWorkflowProgress({ workflow: 'bmad' });
324
- expect(bmadOnly).toHaveLength(1);
325
- expect(bmadOnly[0].workflow).toBe('bmad');
326
-
327
- const harnessOnly = storage.queryWorkflowProgress({ workflow: 'harness' });
328
- expect(harnessOnly).toHaveLength(1);
329
- expect(harnessOnly[0].workflow).toBe('harness');
330
- });
331
-
332
- it('feature_slug 取首个非空值,success_count 正确累加', () => {
333
- const base = Date.now();
334
- seed({
335
- route_request_id: 'route-A',
336
- workflow: 'bmad',
337
- phase: 'analyze',
338
- feature_slug: 'login',
339
- success: 1,
340
- timestamp: base + 100,
341
- });
342
- seed({
343
- route_request_id: 'route-A',
344
- workflow: 'bmad',
345
- phase: 'design',
346
- feature_slug: 'login',
347
- success: 0,
348
- timestamp: base + 200,
349
- });
350
-
351
- const result = storage.queryWorkflowProgress({ session_id: 'sess-1' });
352
- expect(result[0].feature_slug).toBe('login');
353
- expect(result[0].total_invocations).toBe(2);
354
- expect(result[0].success_count).toBe(1);
355
- });
356
-
357
- it('多个 route 时按 last_at DESC 排序', () => {
358
- const base = Date.now();
359
- seed({ route_request_id: 'route-old', workflow: 'bmad', phase: 'analyze', timestamp: base + 100 });
360
- seed({ route_request_id: 'route-new', workflow: 'bmad', phase: 'analyze', timestamp: base + 1000 });
361
-
362
- const result = storage.queryWorkflowProgress({ session_id: 'sess-1' });
363
- expect(result).toHaveLength(2);
364
- expect(result[0].route_request_id).toBe('route-new');
365
- expect(result[1].route_request_id).toBe('route-old');
366
- });
367
-
368
- it('无匹配时返回空数组', () => {
369
- seed({ route_request_id: 'route-A', workflow: null, phase: null });
370
- const result = storage.queryWorkflowProgress({ session_id: 'sess-1' });
371
- expect(result).toEqual([]);
372
- });
373
- });
374
-
375
- describe('SQLiteStorage: skill_invocations 增量迁移', () => {
376
- let tmp: string;
377
- let dbPath: string;
378
-
379
- beforeEach(() => {
380
- tmp = mkdtempSync(join(tmpdir(), 'forge-skill-mig-'));
381
- dbPath = join(tmp, 'data.db');
382
- });
383
-
384
- afterEach(() => {
385
- rmSync(tmp, { recursive: true, force: true });
386
- });
387
-
388
- it('旧库(没有 workflow / phase / feature_slug / artifact_path 列)经 runMigrations 后字段被加上', () => {
389
- // Step 1: 模拟旧版本数据库 — 直接用 better-sqlite3 建一个旧 schema 的 skill_invocations 表
390
- const legacyDb = new Database(dbPath);
391
- legacyDb.exec(`
392
- CREATE TABLE skill_invocations (
393
- id TEXT PRIMARY KEY,
394
- route_request_id TEXT,
395
- session_id TEXT NOT NULL,
396
- agent_id TEXT,
397
- skill_id TEXT NOT NULL,
398
- invocation_type TEXT NOT NULL,
399
- reason TEXT,
400
- depth INTEGER DEFAULT 0,
401
- success INTEGER DEFAULT 1,
402
- error TEXT,
403
- timestamp INTEGER NOT NULL,
404
- created_at TEXT DEFAULT (datetime('now'))
405
- );
406
- `);
407
- // 写一行旧数据
408
- legacyDb.prepare(`
409
- INSERT INTO skill_invocations
410
- (id, route_request_id, session_id, agent_id, skill_id, invocation_type, reason, depth, success, error, timestamp)
411
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
412
- `).run(
413
- 'legacy-1',
414
- 'route-legacy',
415
- 'sess-legacy',
416
- 'agent-old',
417
- 'old-skill',
418
- 'dynamic',
419
- 'old reason',
420
- 0,
421
- 1,
422
- null,
423
- Date.now() - 10000,
424
- );
425
-
426
- // 验证旧库不存在新列
427
- const oldCols = legacyDb.prepare(`PRAGMA table_info(skill_invocations)`).all() as Array<{ name: string }>;
428
- const oldNames = oldCols.map(c => c.name);
429
- expect(oldNames).not.toContain('workflow');
430
- expect(oldNames).not.toContain('phase');
431
- expect(oldNames).not.toContain('feature_slug');
432
- expect(oldNames).not.toContain('artifact_path');
433
- legacyDb.close();
434
-
435
- // Step 2: 用 SQLiteStorage 打开同一个 db 文件,runMigrations 应自动补齐列
436
- const storage = new SQLiteStorage(dbPath);
437
- try {
438
- // 验证新列已加上
439
- const newCols = storage
440
- .getDatabase()
441
- .prepare(`PRAGMA table_info(skill_invocations)`)
442
- .all() as Array<{ name: string }>;
443
- const newNames = newCols.map(c => c.name);
444
- expect(newNames).toContain('workflow');
445
- expect(newNames).toContain('phase');
446
- expect(newNames).toContain('feature_slug');
447
- expect(newNames).toContain('artifact_path');
448
-
449
- // 旧数据应该还在,且新列默认为 NULL
450
- const legacyRows = storage.querySkillInvocations({ session_id: 'sess-legacy' });
451
- expect(legacyRows).toHaveLength(1);
452
- expect(legacyRows[0].id).toBe('legacy-1');
453
- expect(legacyRows[0].workflow).toBeNull();
454
- expect(legacyRows[0].phase).toBeNull();
455
- expect(legacyRows[0].feature_slug).toBeNull();
456
- expect(legacyRows[0].artifact_path).toBeNull();
457
-
458
- // 新数据可以正常写入工作流字段
459
- storage.writeSkillInvocation({
460
- id: 'new-1',
461
- route_request_id: 'route-new',
462
- session_id: 'sess-legacy',
463
- agent_id: 'agent-new',
464
- skill_id: 'official-tdd',
465
- invocation_type: 'dynamic',
466
- reason: 'bmad/analyze',
467
- workflow: 'bmad',
468
- phase: 'analyze',
469
- feature_slug: null,
470
- artifact_path: null,
471
- depth: 0,
472
- success: 1,
473
- error: null,
474
- timestamp: Date.now(),
475
- });
476
-
477
- const allRows = storage.querySkillInvocations({ session_id: 'sess-legacy' });
478
- expect(allRows).toHaveLength(2);
479
- const newRow = allRows.find(r => r.id === 'new-1');
480
- expect(newRow?.workflow).toBe('bmad');
481
- expect(newRow?.phase).toBe('analyze');
482
-
483
- // 验证新索引已创建
484
- const indexes = storage
485
- .getDatabase()
486
- .prepare(`SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='skill_invocations'`)
487
- .all() as Array<{ name: string }>;
488
- const indexNames = indexes.map(i => i.name);
489
- expect(indexNames).toContain('idx_skill_invocations_workflow');
490
- expect(indexNames).toContain('idx_skill_invocations_feature');
491
- } finally {
492
- storage.getDatabase().close();
493
- }
494
- });
495
- });
@@ -1,94 +0,0 @@
1
- import { describe, it, expect, vi, beforeAll, afterAll } from 'vitest';
2
- import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
-
6
- // Set up temp dir before module import (SKILLS_DIR is computed at load time)
7
- const tempDir = mkdtempSync(join(tmpdir(), 'forge-test-'));
8
- const skillsDir = join(tempDir, '.claude', 'skills');
9
- mkdirSync(skillsDir, { recursive: true });
10
-
11
- writeFileSync(
12
- join(skillsDir, 'refactor.md'),
13
- `---\nname: "Refactor Skill"\nkeywords: ["refactor", "重构", "cleanup", "restructure"]\n---\nThis skill helps with refactoring.`
14
- );
15
- writeFileSync(
16
- join(skillsDir, 'debug.md'),
17
- `---\nname: "Debug Skill"\nkeywords: ["debug", "调试", "bug"]\n---\nThis skill helps with debugging.`
18
- );
19
-
20
- vi.mock('node:os', async (importOriginal) => {
21
- const actual = await importOriginal<typeof import('node:os')>();
22
- return { ...actual, homedir: () => tempDir };
23
- });
24
-
25
- // Import after mock is set up
26
- const { SkillRegistry } = await import('../../src/skills/registry.js');
27
-
28
- describe('SkillRegistry', () => {
29
- afterAll(() => {
30
- vi.restoreAllMocks();
31
- rmSync(tempDir, { recursive: true, force: true });
32
- });
33
-
34
- describe('scan', () => {
35
- it('loads official skills plus user skills from ~/.claude/skills/', () => {
36
- const registry = new SkillRegistry();
37
- const skills = registry.getAll();
38
-
39
- // 17 official skills + 2 user skills (user 'debug' overrides official 'official-debug' by different id)
40
- expect(skills.length).toBeGreaterThanOrEqual(17);
41
- expect(skills.map(s => s.id)).toContain('refactor');
42
- expect(skills.map(s => s.id)).toContain('debug');
43
- // Official skills should be present
44
- expect(skills.map(s => s.id)).toContain('official-harness-engineering');
45
- });
46
- });
47
-
48
- describe('match', () => {
49
- it('returns a skill when keywords match', async () => {
50
- const registry = new SkillRegistry();
51
- const skill = await registry.match('I need to refactor and cleanup this code');
52
-
53
- expect(skill).not.toBeNull();
54
- expect(skill!.name).toBe('Refactor Skill');
55
- });
56
-
57
- it('returns null when no match', async () => {
58
- const registry = new SkillRegistry();
59
- const skill = await registry.match('just a simple task');
60
-
61
- expect(skill).toBeNull();
62
- });
63
-
64
- it('matches Chinese keywords', async () => {
65
- const registry = new SkillRegistry();
66
- const skill = await registry.match('需要重构和cleanup这个模块');
67
-
68
- expect(skill).not.toBeNull();
69
- expect(skill!.name).toBe('Refactor Skill');
70
- });
71
-
72
- it('matches extra keywords parameter', async () => {
73
- const registry = new SkillRegistry();
74
- const skill = await registry.match('help me', ['debug', 'issue']);
75
-
76
- expect(skill).not.toBeNull();
77
- // Either official-debug or user debug skill can match (official loads first)
78
- expect(skill!.keywords).toContain('debug');
79
- });
80
- });
81
-
82
- describe('getAll', () => {
83
- it('returns all loaded skills (official + user)', () => {
84
- const registry = new SkillRegistry();
85
- const skills = registry.getAll();
86
-
87
- // 17 official + 2 user = 19
88
- expect(skills.length).toBeGreaterThanOrEqual(17);
89
- // User skills should be present alongside official ones
90
- const userSkills = skills.filter(s => !s.isOfficial);
91
- expect(userSkills.length).toBe(2);
92
- });
93
- });
94
- });