@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,108 +0,0 @@
1
- -- Legacy Pipeline 到 Dynamic Pipeline 数据迁移脚本
2
- -- 执行前请备份数据库:cp ~/.claude-forge/data.db ~/.claude-forge/data.db.backup
3
-
4
- -- ============================================
5
- -- 阶段 1:迁移 pipelines → dynamic_pipelines
6
- -- ============================================
7
-
8
- INSERT INTO dynamic_pipelines (
9
- id, requirement, project_path, session_id,
10
- template_id, convention_id, complexity, reasoning,
11
- status, created_at, updated_at
12
- )
13
- SELECT
14
- id,
15
- requirement,
16
- project_path,
17
- session_id,
18
- NULL as template_id, -- Legacy 无模板概念
19
- NULL as convention_id,
20
- COALESCE(complexity, 'moderate') as complexity,
21
- reasoning,
22
- CASE
23
- WHEN phase = 'done' THEN 'completed'
24
- ELSE 'in_progress'
25
- END as status,
26
- created_at,
27
- updated_at
28
- FROM pipelines
29
- WHERE id NOT IN (SELECT id FROM dynamic_pipelines);
30
-
31
- -- ============================================
32
- -- 阶段 2:迁移 pipeline_tasks → dynamic_nodes
33
- -- ============================================
34
-
35
- INSERT INTO dynamic_nodes (
36
- id, pipeline_id, node_type_id, status,
37
- dependencies, bound_skill_name, output,
38
- started_at, completed_at, created_at, updated_at
39
- )
40
- SELECT
41
- id,
42
- pipeline_id,
43
- phase as node_type_id, -- 将 phase 映射为 node_type_id
44
- CASE
45
- WHEN status = 'completed' THEN 'completed'
46
- WHEN status = 'in_progress' THEN 'in_progress'
47
- WHEN status = 'failed' THEN 'failed'
48
- ELSE 'pending'
49
- END as status,
50
- COALESCE(dependencies, '[]') as dependencies,
51
- NULL as bound_skill_name, -- Legacy 无 skill 绑定
52
- output,
53
- NULL as started_at, -- 需要从事件推导
54
- NULL as completed_at,
55
- datetime('now') as created_at, -- pipeline_tasks 无 created_at
56
- COALESCE(updated_at, datetime('now')) as updated_at
57
- FROM pipeline_tasks
58
- WHERE id NOT IN (SELECT id FROM dynamic_nodes);
59
-
60
- -- ============================================
61
- -- 阶段 3:验证迁移结果(删除 current_node_id 更新)
62
- -- ============================================
63
-
64
- -- ============================================
65
- -- 阶段 4:转换 pipeline_events 事件类型
66
- -- ============================================
67
-
68
- -- 将 Legacy 事件类型转换为 Dynamic 事件类型
69
- UPDATE pipeline_events
70
- SET type = CASE
71
- WHEN type = 'pipeline.created' THEN 'dynamic_pipeline.created'
72
- WHEN type = 'task.created' THEN 'dynamic_node.created'
73
- WHEN type = 'task.started' THEN 'dynamic_node.started'
74
- WHEN type = 'task.completed' THEN 'dynamic_node.completed'
75
- WHEN type = 'task.failed' THEN 'dynamic_node.failed'
76
- WHEN type = 'phase.advanced' THEN 'dynamic_node.advanced'
77
- WHEN type = 'pipeline.closed' THEN 'dynamic_pipeline.completed'
78
- ELSE type
79
- END
80
- WHERE pipeline_id IN (SELECT id FROM pipelines);
81
-
82
- -- ============================================
83
- -- 验证迁移结果
84
- -- ============================================
85
-
86
- -- 检查迁移数量
87
- SELECT
88
- 'Migrated Pipelines' as item,
89
- COUNT(*) as count
90
- FROM dynamic_pipelines
91
- WHERE id IN (SELECT id FROM pipelines)
92
-
93
- UNION ALL
94
-
95
- SELECT
96
- 'Migrated Nodes' as item,
97
- COUNT(*) as count
98
- FROM dynamic_nodes
99
- WHERE pipeline_id IN (SELECT id FROM pipelines)
100
-
101
- UNION ALL
102
-
103
- SELECT
104
- 'Converted Events' as item,
105
- COUNT(*) as count
106
- FROM pipeline_events
107
- WHERE pipeline_id IN (SELECT id FROM pipelines)
108
- AND type LIKE 'dynamic_%';
@@ -1,116 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /**
3
- * 一次性脚本:用新的 ExecutionDocBuilder 重新生成所有历史执行文档。
4
- *
5
- * 用法:
6
- * npx tsx scripts/regenerate-execution-docs.ts
7
- *
8
- * 行为:
9
- * 1. 打开 ~/.claude-forge/data.db
10
- * 2. 查询 routing_events 中所有 distinct session_id
11
- * 3. 对每个 session 调用 builder.build(sessionId, projectPath)
12
- * → 会自动覆盖 overview/agent/skill 文件并最后调用 updateIndex
13
- * 4. updateIndex 扫描 by-route/ 下全部目录,因此即便某些路由在 DB 中已无数据,
14
- * 它们的目录仍会被纳入新的 index.md(保留旧文件作为兜底)
15
- *
16
- * 注意:
17
- * - 数据库只读
18
- * - 仅覆盖 <projectRoot>/.claude-forge/executions/ 下的 markdown
19
- * - 不传 AI provider,统一使用 fallback summary(避免网络抖动)
20
- */
21
-
22
- import path from 'node:path';
23
- import fs from 'node:fs';
24
- import { SQLiteStorage } from '../src/core/storage/sqlite.js';
25
- import { ExecutionDocBuilder } from '../src/intelligence/execution-doc-builder.js';
26
- import { FORGE_PATHS } from '../src/core/constants.js';
27
-
28
- async function main(): Promise<void> {
29
- const projectPath = process.cwd();
30
- const dbPath = FORGE_PATHS.database();
31
-
32
- console.log('===========================================');
33
- console.log('Regenerate Execution Docs');
34
- console.log('===========================================');
35
- console.log(`projectPath : ${projectPath}`);
36
- console.log(`database : ${dbPath}`);
37
-
38
- if (!fs.existsSync(dbPath)) {
39
- console.error(`数据库不存在: ${dbPath}`);
40
- process.exit(1);
41
- }
42
-
43
- const byRouteDir = path.join(projectPath, '.claude-forge', 'executions', 'by-route');
44
- const allDirs = fs.existsSync(byRouteDir)
45
- ? fs.readdirSync(byRouteDir, { withFileTypes: true })
46
- .filter(d => d.isDirectory())
47
- .map(d => d.name)
48
- : [];
49
- console.log(`磁盘目录数 : ${allDirs.length}`);
50
-
51
- const storage = new SQLiteStorage(dbPath);
52
- const builder = new ExecutionDocBuilder(storage, null);
53
-
54
- // 查询所有 distinct session_id
55
- const db = storage.getDatabase();
56
- const sessionRows = db
57
- .prepare(
58
- `SELECT DISTINCT session_id, COUNT(*) AS n
59
- FROM routing_events
60
- WHERE session_id IS NOT NULL
61
- GROUP BY session_id
62
- ORDER BY MIN(ts) ASC`,
63
- )
64
- .all() as Array<{ session_id: string; n: number }>;
65
-
66
- console.log(`数据库内 session 数 : ${sessionRows.length}`);
67
- sessionRows.forEach(s => {
68
- console.log(` - ${s.session_id} (${s.n} routes)`);
69
- });
70
- console.log('');
71
-
72
- if (sessionRows.length === 0) {
73
- console.log('数据库中没有可重生的路由记录,但仍尝试调用 updateIndex 重写索引...');
74
- // 没有 session 时,build() 不会被调用,因此 updateIndex 也不会运行。
75
- // 用一个空 sessionId 触发?不行,build 内部会查 0 行就返回。
76
- // 直接构造一个临时 builder 不行(updateIndex 是 private)。
77
- // 兜底:调用任意一个目录名作为 sessionId 让它跑一次。
78
- // 实际场景下 sessionRows 至少有 1 个,此分支多半不会进。
79
- storage.close();
80
- return;
81
- }
82
-
83
- let totalRoutes = 0;
84
- let okSessions = 0;
85
- let failSessions = 0;
86
-
87
- for (const [i, s] of sessionRows.entries()) {
88
- const tag = `[${i + 1}/${sessionRows.length}]`;
89
- try {
90
- console.log(`${tag} 处理 session ${s.session_id} (${s.n} routes)...`);
91
- await builder.build(s.session_id, projectPath);
92
- okSessions++;
93
- totalRoutes += s.n;
94
- } catch (err) {
95
- failSessions++;
96
- console.warn(`${tag} ✗ session ${s.session_id} 失败: ${err}`);
97
- }
98
- }
99
-
100
- console.log('');
101
- console.log('===========================================');
102
- console.log('完成');
103
- console.log('===========================================');
104
- console.log(`session 成功 : ${okSessions}`);
105
- console.log(`session 失败 : ${failSessions}`);
106
- console.log(`重生路由记录数 : ${totalRoutes}`);
107
- console.log(`磁盘目录总数 : ${allDirs.length}`);
108
- console.log(`未覆盖目录数 : ${Math.max(allDirs.length - totalRoutes, 0)} (保留原文件)`);
109
-
110
- storage.close();
111
- }
112
-
113
- main().catch(err => {
114
- console.error('重生失败:', err);
115
- process.exit(1);
116
- });
@@ -1,193 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /**
3
- * sync-agent-skills.ts
4
- *
5
- * 从 GitHub 同步 addyosmani/agent-skills 到本地 ~/.claude/skills/agent-skills/
6
- *
7
- * 功能:
8
- * 1. Clone 或 pull agent-skills 仓库
9
- * 2. 记录 upstream commit hash 到 .sync-metadata.json
10
- * 3. 生成 MIT License NOTICE 文件
11
- * 4. 幂等:重复运行不会重复 clone
12
- */
13
-
14
- import { execSync } from 'child_process';
15
- import * as fs from 'fs';
16
- import * as path from 'path';
17
- import { homedir } from 'os';
18
-
19
- const UPSTREAM_REPO = 'https://github.com/addyosmani/agent-skills.git';
20
- const SKILLS_BASE_DIR = path.join(homedir(), '.claude', 'skills');
21
- const TARGET_DIR = path.join(SKILLS_BASE_DIR, 'agent-skills');
22
- const METADATA_FILE = path.join(TARGET_DIR, '.sync-metadata.json');
23
- const NOTICE_FILE = path.join(TARGET_DIR, 'NOTICE');
24
-
25
- interface SyncMetadata {
26
- upstream_repo: string;
27
- commit_hash: string;
28
- synced_at: string;
29
- }
30
-
31
- /**
32
- * 执行 shell 命令并返回输出
33
- */
34
- function exec(command: string, cwd?: string): string {
35
- try {
36
- return execSync(command, {
37
- cwd,
38
- encoding: 'utf-8',
39
- stdio: ['pipe', 'pipe', 'pipe'],
40
- }).trim();
41
- } catch (error: unknown) {
42
- if (error instanceof Error && 'stderr' in error) {
43
- throw new Error(`Command failed: ${command}\n${(error as { stderr: Buffer }).stderr.toString()}`);
44
- }
45
- throw error;
46
- }
47
- }
48
-
49
- /**
50
- * 检查 git 是否可用
51
- */
52
- function checkGitAvailable(): void {
53
- try {
54
- exec('git --version');
55
- } catch (error) {
56
- console.error('❌ Git 未安装或不可用');
57
- console.error('请先安装 Git: https://git-scm.com/downloads');
58
- process.exit(1);
59
- }
60
- }
61
-
62
- /**
63
- * 确保目录存在
64
- */
65
- function ensureDir(dir: string): void {
66
- if (!fs.existsSync(dir)) {
67
- fs.mkdirSync(dir, { recursive: true });
68
- console.log(`✓ 创建目录: ${dir}`);
69
- }
70
- }
71
-
72
- /**
73
- * 获取当前 commit hash
74
- */
75
- function getCommitHash(repoDir: string): string {
76
- return exec('git rev-parse HEAD', repoDir);
77
- }
78
-
79
- /**
80
- * 生成 MIT License NOTICE 文件
81
- */
82
- function generateNotice(commitHash: string, syncedAt: string): string {
83
- return `This directory contains skills from addyosmani/agent-skills
84
- Repository: https://github.com/addyosmani/agent-skills
85
- License: MIT
86
- Upstream commit: ${commitHash}
87
- Synced at: ${syncedAt}
88
-
89
- Original work Copyright (c) Addy Osmani
90
- Modifications (if any) Copyright (c) claude-forge contributors
91
-
92
- MIT License
93
-
94
- Permission is hereby granted, free of charge, to any person obtaining a copy
95
- of this software and associated documentation files (the "Software"), to deal
96
- in the Software without restriction, including without limitation the rights
97
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
98
- copies of the Software, and to permit persons to whom the Software is
99
- furnished to do so, subject to the following conditions:
100
-
101
- The above copyright notice and this permission notice shall be included in all
102
- copies or substantial portions of the Software.
103
-
104
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
105
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
106
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
107
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
108
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
109
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
110
- SOFTWARE.
111
- `;
112
- }
113
-
114
- /**
115
- * 同步 agent-skills 仓库
116
- */
117
- async function syncAgentSkills(): Promise<void> {
118
- console.log('🔄 开始同步 agent-skills...\n');
119
-
120
- // 1. 检查 git 可用性
121
- checkGitAvailable();
122
-
123
- // 2. 确保基础目录存在
124
- ensureDir(SKILLS_BASE_DIR);
125
-
126
- let isNewClone = false;
127
-
128
- // 3. Clone 或 Pull
129
- if (!fs.existsSync(TARGET_DIR)) {
130
- console.log(`📦 克隆仓库: ${UPSTREAM_REPO}`);
131
- try {
132
- exec(`git clone ${UPSTREAM_REPO} "${TARGET_DIR}"`);
133
- isNewClone = true;
134
- console.log('✓ 克隆成功\n');
135
- } catch (error) {
136
- console.error('❌ 克隆失败');
137
- console.error('可能原因:网络问题、仓库不存在、权限不足');
138
- throw error;
139
- }
140
- } else {
141
- console.log('📂 目录已存在,执行 git pull 更新...');
142
- try {
143
- const output = exec('git pull', TARGET_DIR);
144
- console.log(`✓ ${output}\n`);
145
- } catch (error) {
146
- console.error('❌ 更新失败');
147
- console.error('可能原因:本地有未提交的修改、网络问题');
148
- throw error;
149
- }
150
- }
151
-
152
- // 4. 获取 commit hash
153
- const commitHash = getCommitHash(TARGET_DIR);
154
- const syncedAt = new Date().toISOString();
155
-
156
- console.log(`📌 Upstream commit: ${commitHash}`);
157
- console.log(`🕐 同步时间: ${syncedAt}\n`);
158
-
159
- // 5. 写入 metadata
160
- const metadata: SyncMetadata = {
161
- upstream_repo: UPSTREAM_REPO,
162
- commit_hash: commitHash,
163
- synced_at: syncedAt,
164
- };
165
-
166
- fs.writeFileSync(METADATA_FILE, JSON.stringify(metadata, null, 2), 'utf-8');
167
- console.log(`✓ 元数据已保存: ${METADATA_FILE}`);
168
-
169
- // 6. 生成 NOTICE 文件
170
- const noticeContent = generateNotice(commitHash, syncedAt);
171
- fs.writeFileSync(NOTICE_FILE, noticeContent, 'utf-8');
172
- console.log(`✓ NOTICE 文件已生成: ${NOTICE_FILE}\n`);
173
-
174
- // 7. 统计 skills 数量
175
- const skillsDir = path.join(TARGET_DIR, 'skills');
176
- if (fs.existsSync(skillsDir)) {
177
- const skills = fs.readdirSync(skillsDir).filter((name) => {
178
- const fullPath = path.join(skillsDir, name);
179
- return fs.statSync(fullPath).isDirectory();
180
- });
181
- console.log(`📊 共同步 ${skills.length} 个 skills`);
182
- }
183
-
184
- console.log('\n✅ 同步完成!');
185
- console.log(`\n目标目录: ${TARGET_DIR}`);
186
- }
187
-
188
- // 执行同步
189
- syncAgentSkills().catch((error) => {
190
- console.error('\n❌ 同步失败:', error.message);
191
- process.exit(1);
192
- });
193
-
@@ -1,71 +0,0 @@
1
- #!/bin/bash
2
- # 测试 Hook 脚本是否能正常与守护进程通信
3
-
4
- SOCKET_PATH="$HOME/.claude-forge/daemon.sock"
5
-
6
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
7
- echo " 测试 Claude Forge Hook 通信"
8
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
9
- echo ""
10
-
11
- # 1. 检查守护进程是否运行
12
- echo "1. 检查守护进程状态..."
13
- if [ -f "$HOME/.claude-forge/daemon.pid" ]; then
14
- PID=$(cat "$HOME/.claude-forge/daemon.pid")
15
- if kill -0 "$PID" 2>/dev/null; then
16
- echo " ✓ 守护进程运行中 (PID: $PID)"
17
- else
18
- echo " ✗ 守护进程未运行"
19
- exit 1
20
- fi
21
- else
22
- echo " ✗ PID 文件不存在"
23
- exit 1
24
- fi
25
-
26
- # 2. 检查 Socket 文件
27
- echo ""
28
- echo "2. 检查 Socket 文件..."
29
- if [ -S "$SOCKET_PATH" ]; then
30
- echo " ✓ Socket 文件存在: $SOCKET_PATH"
31
- else
32
- echo " ✗ Socket 文件不存在"
33
- exit 1
34
- fi
35
-
36
- # 3. 发送测试事件
37
- echo ""
38
- echo "3. 发送测试事件..."
39
-
40
- # PreToolUse 事件
41
- echo " 发送 PreToolUse 事件..."
42
- echo '{"hook_type":"PreToolUse","timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","session_id":"test-session-123","project_path":"'$PWD'","tool_name":"Read","tool_input":"{\"file_path\":\"/test/file.txt\"}"}' | nc -U "$SOCKET_PATH" 2>/dev/null
43
- sleep 0.5
44
-
45
- # PostToolUse 事件
46
- echo " 发送 PostToolUse 事件..."
47
- echo '{"hook_type":"PostToolUse","timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","session_id":"test-session-123","project_path":"'$PWD'","tool_name":"Read","success":true}' | nc -U "$SOCKET_PATH" 2>/dev/null
48
- sleep 0.5
49
-
50
- # Notification 事件
51
- echo " 发送 Notification 事件..."
52
- echo '{"hook_type":"Notification","timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","session_id":"test-session-123","project_path":"'$PWD'","message":"Test notification"}' | nc -U "$SOCKET_PATH" 2>/dev/null
53
- sleep 0.5
54
-
55
- echo " ✓ 测试事件已发送"
56
-
57
- # 4. 查询数据库
58
- echo ""
59
- echo "4. 查询数据库中的事件..."
60
- sleep 1
61
- cd "$(dirname "$0")/.."
62
- npx tsx src/cli/index.ts query stats
63
-
64
- echo ""
65
- echo "5. 查看最近的事件..."
66
- npx tsx src/cli/index.ts query events --limit 5
67
-
68
- echo ""
69
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
70
- echo " 测试完成"
71
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /**
3
- * Verification script to test skill loading from both formats
4
- */
5
-
6
- import { SkillRegistry } from '../src/skills/registry.js';
7
-
8
- console.log('=== Verifying Skill Loading ===\n');
9
-
10
- const registry = new SkillRegistry();
11
- const skills = registry.getAll();
12
-
13
- console.log(`Total skills loaded: ${skills.length}\n`);
14
-
15
- // Check for official skills
16
- const officialSkills = skills.filter(s => s.isOfficial);
17
- console.log(`Official skills: ${officialSkills.length}`);
18
-
19
- // Check for user skills
20
- const userSkills = skills.filter(s => !s.isOfficial);
21
- console.log(`User skills: ${userSkills.length}\n`);
22
-
23
- // Check for directory format skills (path contains SKILL.md)
24
- const dirFormatSkills = userSkills.filter(s => s.path.includes('SKILL.md'));
25
- console.log(`Directory format skills: ${dirFormatSkills.length}`);
26
- if (dirFormatSkills.length > 0) {
27
- console.log('Examples:');
28
- dirFormatSkills.slice(0, 3).forEach(s => {
29
- console.log(` - ${s.id} (${s.path})`);
30
- console.log(` description: ${s.description || 'N/A'}`);
31
- console.log(` keywords: ${s.keywords.join(', ') || 'N/A'}`);
32
- });
33
- }
34
-
35
- // Check for flat format skills (path ends with .md but not SKILL.md)
36
- const flatFormatSkills = userSkills.filter(s => s.path.endsWith('.md') && !s.path.includes('SKILL.md'));
37
- console.log(`\nFlat format skills: ${flatFormatSkills.length}`);
38
- if (flatFormatSkills.length > 0) {
39
- console.log('Examples:');
40
- flatFormatSkills.slice(0, 3).forEach(s => {
41
- console.log(` - ${s.id} (${s.path})`);
42
- console.log(` description: ${s.description || 'N/A'}`);
43
- console.log(` keywords: ${s.keywords.join(', ') || 'N/A'}`);
44
- });
45
- }
46
-
47
- // Check for skills with description field
48
- const skillsWithDesc = skills.filter(s => s.description);
49
- console.log(`\nSkills with description field: ${skillsWithDesc.length}`);
50
-
51
- // Check for skills without keywords (should use description fallback)
52
- const skillsWithoutKeywords = skills.filter(s => s.keywords.length === 0);
53
- console.log(`Skills without keywords: ${skillsWithoutKeywords.length}`);
54
- if (skillsWithoutKeywords.length > 0) {
55
- console.log('Examples:');
56
- skillsWithoutKeywords.slice(0, 3).forEach(s => {
57
- console.log(` - ${s.id}`);
58
- console.log(` description: ${s.description || 'N/A'}`);
59
- });
60
- }
61
-
62
- console.log('\n=== Verification Complete ===');