@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,112 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import type { SQLiteStorage } from '../../core/storage/sqlite.js';
3
- import { logger } from '../../core/utils/logger.js';
4
- import { normalizeTimestamp, timestampToMs } from '../../core/utils/time.js';
5
- import { truncateSessionId } from '../../core/utils/session.js';
6
- import { truncateString } from '../../core/utils/format.js';
7
-
8
- const NEW_TASK_KEYWORDS = [
9
- '帮我', '实现', '修复', '添加', '重构', '优化', '创建', '删除',
10
- '升级', '迁移', '部署', '配置', '设计', '提交', '推送',
11
- 'fix', 'add', 'implement', 'refactor', 'create', 'delete', 'deploy',
12
- ];
13
-
14
- const CONTINUE_KEYWORDS = [
15
- '继续', '然后', '还有', '另外', '这个', '那个', '它',
16
- '对', '好的', '可以', '是的', '不是', '不对', '改一下',
17
- ];
18
-
19
- const TASK_SWITCH_MINUTES = 10;
20
-
21
- export class TaskSegmenter {
22
- private currentTasks = new Map<string, { id: string; lastTime: number }>();
23
-
24
- constructor(private storage: SQLiteStorage) {}
25
-
26
- processPrompt(sessionId: string, prompt: string, timestamp: string, eventId?: string): string {
27
- const key = sessionId;
28
- const current = this.currentTasks.get(key) ?? this.recoverActiveTask(key);
29
- const now = timestampToMs(timestamp);
30
-
31
- if (!current || this.shouldStartNewTask(prompt, now, current)) {
32
- if (current) {
33
- this.storage.updateTask(current.id, { status: 'completed', end_time: timestamp });
34
- }
35
- const taskId = this.createTask(sessionId, prompt, timestamp);
36
- this.currentTasks.set(key, { id: taskId, lastTime: now });
37
- if (eventId) this.storage.linkEventToTask(taskId, eventId);
38
- return taskId;
39
- }
40
-
41
- current.lastTime = now;
42
- if (eventId) this.storage.linkEventToTask(current.id, eventId);
43
- return current.id;
44
- }
45
-
46
- linkEvent(sessionId: string, eventId: string): void {
47
- const current = this.currentTasks.get(sessionId) ?? this.recoverActiveTask(sessionId);
48
- if (current) {
49
- this.storage.linkEventToTask(current.id, eventId);
50
- }
51
- }
52
-
53
- /**
54
- * 从数据库恢复 session 的 active 任务到内存 Map。
55
- * 用于 daemon 重启后内存丢失场景的 lazy 恢复。
56
- * 找不到 active 任务时返回 null(不报错)。
57
- */
58
- private recoverActiveTask(sessionId: string): { id: string; lastTime: number } | null {
59
- const tasks = this.storage.queryTasks({ session_id: sessionId, limit: 5 });
60
- const activeTask = tasks.find(t => t.status === 'active');
61
- if (!activeTask) return null;
62
-
63
- const anchor = activeTask.end_time ?? activeTask.start_time;
64
- const lastTime = timestampToMs(anchor);
65
- const entry = { id: activeTask.id, lastTime };
66
- this.currentTasks.set(sessionId, entry);
67
- logger.info(
68
- `[TaskSegmenter] Recovered active task ${truncateString(activeTask.id, 8)} for session ${truncateSessionId(sessionId)} from DB`,
69
- );
70
- return entry;
71
- }
72
-
73
- getCurrentTaskId(sessionId: string): string | null {
74
- return this.currentTasks.get(sessionId)?.id ?? null;
75
- }
76
-
77
- completeCurrentTask(sessionId: string, timestamp: string): void {
78
- const current = this.currentTasks.get(sessionId) ?? this.recoverActiveTask(sessionId);
79
- if (!current) return;
80
- this.storage.updateTask(current.id, {
81
- status: 'completed',
82
- end_time: timestamp,
83
- });
84
- this.currentTasks.delete(sessionId);
85
- }
86
-
87
- private shouldStartNewTask(prompt: string, now: number, current: { lastTime: number }): boolean {
88
- const minutesDiff = (now - current.lastTime) / 60000;
89
- if (minutesDiff > TASK_SWITCH_MINUTES) return true;
90
-
91
- const hasContinue = CONTINUE_KEYWORDS.some(kw => prompt.includes(kw));
92
- if (hasContinue) return false;
93
-
94
- const hasNewTask = NEW_TASK_KEYWORDS.some(kw => prompt.includes(kw));
95
- return hasNewTask;
96
- }
97
-
98
- private createTask(sessionId: string, prompt: string, timestamp: string): string {
99
- const taskId = randomUUID();
100
- const title = this.extractTitle(prompt);
101
- this.storage.writeTask({ id: taskId, session_id: sessionId, title, start_time: timestamp });
102
- logger.info(`[TaskSegmenter] New task: "${title}" (${truncateString(taskId, 8)})`);
103
- return taskId;
104
- }
105
-
106
- private extractTitle(prompt: string): string {
107
- const cleaned = prompt.replace(/\[Image #\d+\]/g, '').trim();
108
- const firstLine = cleaned.split('\n')[0].trim();
109
- if (firstLine.length <= 60) return firstLine || '(无标题)';
110
- return truncateString(firstLine, 60);
111
- }
112
- }
@@ -1,88 +0,0 @@
1
- import { existsSync, readFileSync, copyFileSync, mkdirSync, readdirSync } from 'node:fs';
2
- import { createHash } from 'node:crypto';
3
- import { join, dirname } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { homedir } from 'node:os';
6
- import { logger } from '../core/utils/logger.js';
7
-
8
- const USER_SKILLS_DIR = join(homedir(), '.claude', 'skills');
9
-
10
- function sha256(content: Buffer): string {
11
- return createHash('sha256').update(content).digest('hex');
12
- }
13
-
14
- function getSourceSkillsDir(): string {
15
- // Compiled: dist/daemon/skill-sync.js → dist/skills/official
16
- // Dev (vitest): src/daemon/skill-sync.ts → src/skills/official
17
- return join(dirname(fileURLToPath(import.meta.url)), '..', 'skills', 'official');
18
- }
19
-
20
- export interface SkillSyncResult {
21
- copied: number;
22
- checked: number;
23
- skipped_userOwned: number; // user skills not in source list — untouched
24
- }
25
-
26
- /**
27
- * Sync official skills from dist/skills/official to ~/.claude/skills/.
28
- *
29
- * Strategy:
30
- * - Only files present in the source dir (dist/skills/official) are candidates
31
- * - sha256 identical → skip; different → overwrite
32
- * - User-only skills (not in source list) are never touched
33
- * - Target dir is created if absent (first install)
34
- *
35
- * Failures are logged as warnings and never thrown — daemon startup must not be blocked.
36
- */
37
- export function syncSkills(opts?: { sourceDir?: string; targetDir?: string }): SkillSyncResult {
38
- const result: SkillSyncResult = { copied: 0, checked: 0, skipped_userOwned: 0 };
39
- const sourceDir = opts?.sourceDir ?? getSourceSkillsDir();
40
- const targetDir = opts?.targetDir ?? USER_SKILLS_DIR;
41
-
42
- if (!existsSync(sourceDir)) {
43
- logger.warn(`[SkillSync] source dir not found at ${sourceDir}, skipping`);
44
- return result;
45
- }
46
-
47
- // Ensure target dir exists (first install may not have ~/.claude/skills/)
48
- try {
49
- mkdirSync(targetDir, { recursive: true });
50
- } catch {
51
- /* ignore — if it already exists mkdirSync is a no-op */
52
- }
53
-
54
- let sourceFiles: string[];
55
- try {
56
- sourceFiles = readdirSync(sourceDir).filter((f) => f.endsWith('.md'));
57
- } catch (err) {
58
- logger.warn(`[SkillSync] failed to list ${sourceDir}: ${err}`);
59
- return result;
60
- }
61
-
62
- for (const file of sourceFiles) {
63
- result.checked++;
64
- const src = join(sourceDir, file);
65
- const dest = join(targetDir, file);
66
-
67
- try {
68
- const srcContent = readFileSync(src);
69
- if (existsSync(dest)) {
70
- const destContent = readFileSync(dest);
71
- if (sha256(srcContent) === sha256(destContent)) {
72
- continue; // identical — no copy needed
73
- }
74
- }
75
-
76
- copyFileSync(src, dest);
77
- result.copied++;
78
- logger.info(`[SkillSync] updated ${file}`);
79
- } catch (err) {
80
- logger.warn(`[SkillSync] failed to sync ${file}: ${err instanceof Error ? err.message : String(err)}`);
81
- }
82
- }
83
-
84
- if (result.copied > 0) {
85
- logger.info(`[SkillSync] synced ${result.copied}/${result.checked} skill files`);
86
- }
87
- return result;
88
- }
@@ -1,118 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - Hook shared library
3
- # Source this file at the top of each hook script:
4
- # source "$(dirname "$0")/hook-lib.sh"
5
- #
6
- # Provides:
7
- # - SOCKET_PATH, QUEUE_DIR shared variables
8
- # - send_event_or_enqueue() function
9
-
10
- SOCKET_PATH="${CLAUDE_FORGE_SOCKET:-$HOME/.claude-forge/daemon.sock}"
11
- QUEUE_DIR="$HOME/.claude-forge/queue"
12
-
13
- # resolve_project_path <input_cwd>
14
- #
15
- # Walk up the directory tree from <input_cwd> to find the nearest ancestor that
16
- # contains a `.git` entry (directory for normal clones, file for worktrees /
17
- # submodules). Print the resolved git-root path on stdout.
18
- #
19
- # Fallback rules:
20
- # - Empty input → start from $PWD
21
- # - Relative input → prefixed with $PWD to absolutise
22
- # - No .git found within 64 levels → print original input unchanged
23
- #
24
- # POSIX-only: uses `dirname` and `case`; does NOT depend on `realpath` or any
25
- # GNU coreutils extensions, so it works on macOS BSD and Linux alike.
26
- resolve_project_path() {
27
- local input="${1:-}"
28
- local dir="${input:-$PWD}"
29
-
30
- # Absolutise: prefix relative paths with $PWD (no realpath dependency)
31
- case "$dir" in
32
- /*) ;;
33
- *) dir="$PWD/$dir" ;;
34
- esac
35
-
36
- local guard=0
37
- while [ "$dir" != "/" ] && [ "$dir" != "." ] && [ $guard -lt 64 ]; do
38
- if [ -d "$dir/.git" ] || [ -f "$dir/.git" ]; then
39
- printf '%s' "$dir"
40
- return 0
41
- fi
42
- dir=$(dirname "$dir")
43
- guard=$((guard + 1))
44
- done
45
-
46
- # No git ancestor found → fall back to the caller's original cwd
47
- printf '%s' "${input:-$PWD}"
48
- }
49
-
50
- # send_event_or_enqueue <event_json> [timeout_seconds]
51
- #
52
- # 1. If socket file does not exist → enqueue in background → return empty string
53
- # 2. If socket exists → send via nc with timeout
54
- # - nc exit code != 0 → enqueue in background → return empty string
55
- # - nc exit code == 0 → return daemon response on stdout
56
- #
57
- # The caller reads REPLY_RESPONSE after calling this function:
58
- # send_event_or_enqueue "$EVENT" 10
59
- # RESPONSE="$HOOK_RESPONSE"
60
- #
61
- # macOS BSD nc notes:
62
- # - `nc -U` opens a Unix domain socket connection
63
- # - `-w N` sets idle timeout (seconds); on macOS this is the "connection timeout"
64
- # for UDP but for TCP/Unix it's inactivity timeout after connection
65
- # - Exit code: 0 = success (data sent + connection closed by remote), 1 = error
66
- # - An empty response (daemon returns nothing) still exits 0 if the connection
67
- # was established and closed cleanly → we check exit code, NOT response content
68
-
69
- HOOK_RESPONSE=""
70
-
71
- send_event_or_enqueue() {
72
- local event_json="$1"
73
- local timeout_secs="${2:-10}"
74
-
75
- HOOK_RESPONSE=""
76
-
77
- # Fast path: no socket file → daemon is not running
78
- if [ ! -S "$SOCKET_PATH" ]; then
79
- _enqueue_event_bg "$event_json"
80
- return 0
81
- fi
82
-
83
- # Socket exists: try to send; capture exit code separately from stdout
84
- local tmp_response
85
- tmp_response=$(echo "$event_json" | nc -U -w "$timeout_secs" "$SOCKET_PATH" 2>/dev/null)
86
- local nc_exit=$?
87
-
88
- if [ $nc_exit -ne 0 ]; then
89
- # nc failed (connection refused, socket disappeared between check and send, etc.)
90
- _enqueue_event_bg "$event_json"
91
- return 0
92
- fi
93
-
94
- # Success: pass response back to caller
95
- HOOK_RESPONSE="$tmp_response"
96
- }
97
-
98
- # _enqueue_event_bg <event_json>
99
- # Forks a background subshell to write the event JSON to the queue directory.
100
- # The main hook process is never blocked by this operation.
101
- _enqueue_event_bg() {
102
- local event_json="$1"
103
- (
104
- mkdir -p "$QUEUE_DIR"
105
- # Timestamp with second precision (BSD date has no %N nanoseconds)
106
- local ts
107
- ts=$(date -u +"%Y%m%dT%H%M%S")
108
- # UUID: prefer uuidgen (macOS), fall back to /proc on Linux
109
- local uuid
110
- uuid=$(uuidgen 2>/dev/null \
111
- || cat /proc/sys/kernel/random/uuid 2>/dev/null \
112
- || printf '%s-%s' "$$" "$RANDOM")
113
- local filename="${ts}-${uuid}.json"
114
- # Atomic write: write to temp file, then rename
115
- local tmp_file="$QUEUE_DIR/.tmp-${filename}"
116
- printf '%s' "$event_json" > "$tmp_file" && mv "$tmp_file" "$QUEUE_DIR/${filename}"
117
- ) &
118
- }
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - Notification Hook
3
-
4
- # shellcheck source=./hook-lib.sh
5
- source "$(dirname "$0")/hook-lib.sh"
6
-
7
- AUTH_TOKEN=$(cat "$HOME/.claude-forge/daemon.token" 2>/dev/null || echo '')
8
-
9
- # 读取 stdin
10
- INPUT=$(cat)
11
-
12
- # 提取 cwd(jq 替代 python3)
13
- RAW_CWD=$(echo "$INPUT" | jq -r '.cwd // ""')
14
- PROJECT_PATH=$(resolve_project_path "${RAW_CWD:-$PWD}")
15
- SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // .sessionId // ""')
16
- SESSION_ID="${SESSION_ID:-${CLAUDE_CODE_SESSION_ID:-cli}}"
17
-
18
- # 构造事件 JSON(原始 INPUT 作为 tool_input,保留完整通知内容)
19
- TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
20
- TOOL_INPUT=$(echo "$INPUT" | jq -c '.')
21
- EVENT=$(jq -nc \
22
- --arg hook_type "Notification" \
23
- --arg timestamp "$TIMESTAMP" \
24
- --arg session_id "$SESSION_ID" \
25
- --arg project_path "$PROJECT_PATH" \
26
- --argjson tool_input "$TOOL_INPUT" \
27
- --arg auth "$AUTH_TOKEN" \
28
- '{hook_type: $hook_type, timestamp: $timestamp, session_id: $session_id,
29
- project_path: $project_path, tool_name: "notification",
30
- tool_input: $tool_input, _auth: $auth}')
31
-
32
- # 发送到 daemon(1 秒超时;失败时入队)
33
- send_event_or_enqueue "$EVENT" 1
34
-
35
- exit 0
@@ -1,61 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - PostToolUse Hook
3
-
4
- # shellcheck source=./hook-lib.sh
5
- source "$(dirname "$0")/hook-lib.sh"
6
-
7
- AUTH_TOKEN=$(cat "$HOME/.claude-forge/daemon.token" 2>/dev/null || echo '')
8
-
9
- # 读取 stdin
10
- INPUT=$(cat)
11
-
12
- # 提取字段(单次 jq 调用,替代 4 个 python3 进程)
13
- # tool_response 是 Claude Code 的字段名
14
- TOOL_NAME="${CLAUDE_TOOL_NAME:-$(echo "$INPUT" | jq -r '.tool_name // ""')}"
15
- TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}')
16
- TOOL_OUTPUT=$(echo "$INPUT" | jq -c '.tool_response // {}')
17
- RAW_CWD=$(echo "$INPUT" | jq -r '.cwd // ""')
18
- PROJECT_PATH=$(resolve_project_path "${RAW_CWD:-$PWD}")
19
- SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // .sessionId // ""')
20
- SESSION_ID="${SESSION_ID:-${CLAUDE_CODE_SESSION_ID:-cli}}"
21
-
22
- # 构造事件 JSON
23
- TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
24
- EVENT=$(jq -nc \
25
- --arg hook_type "PostToolUse" \
26
- --arg timestamp "$TIMESTAMP" \
27
- --arg session_id "$SESSION_ID" \
28
- --arg project_path "$PROJECT_PATH" \
29
- --arg tool_name "$TOOL_NAME" \
30
- --argjson tool_input "$TOOL_INPUT" \
31
- --argjson tool_output "$TOOL_OUTPUT" \
32
- --arg auth "$AUTH_TOKEN" \
33
- '{hook_type: $hook_type, timestamp: $timestamp, session_id: $session_id,
34
- project_path: $project_path, tool_name: $tool_name, tool_input: $tool_input,
35
- tool_output: $tool_output, _auth: $auth}')
36
-
37
- # 发送到 daemon(PostToolUse 也需要等待响应以支持通知注入;失败时入队)
38
- send_event_or_enqueue "$EVENT" 5
39
- RESPONSE="$HOOK_RESPONSE"
40
-
41
- if [ -n "$RESPONSE" ]; then
42
- # 硬阻断:优先使用 hookSpecificOutput(Claude Code 官方格式)
43
- ALLOW=$(echo "$RESPONSE" | jq -r '.allow // true')
44
- if [ "$ALLOW" = "false" ]; then
45
- HAS_HOOK_OUTPUT=$(echo "$RESPONSE" | jq -r 'if .hookSpecificOutput then "yes" else "no" end')
46
- if [ "$HAS_HOOK_OUTPUT" = "yes" ]; then
47
- echo "$RESPONSE" | jq '{hookSpecificOutput: .hookSpecificOutput}'
48
- exit 0
49
- else
50
- REASON=$(echo "$RESPONSE" | jq -r '.reason // "Pipeline 已阻断"')
51
- echo "$REASON" >&2
52
- exit 2
53
- fi
54
- fi
55
-
56
- HAS_CONTEXT=$(echo "$RESPONSE" | jq -r 'if .additionalContext and (.additionalContext != "") then "yes" else "no" end')
57
- if [ "$HAS_CONTEXT" = "yes" ]; then
58
- echo "$RESPONSE"
59
- fi
60
- fi
61
- exit 0
@@ -1,63 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - PreToolUse Hook(双向通信)
3
-
4
- # shellcheck source=./hook-lib.sh
5
- source "$(dirname "$0")/hook-lib.sh"
6
-
7
- AUTH_TOKEN=$(cat "$HOME/.claude-forge/daemon.token" 2>/dev/null || echo '')
8
-
9
- # 读取 stdin(Claude Code 传入的 JSON)
10
- INPUT=$(cat)
11
-
12
- # 提取字段(单次 jq 调用,替代 3 个 python3 进程)
13
- TOOL_NAME="${CLAUDE_TOOL_NAME:-$(echo "$INPUT" | jq -r '.tool_name // ""')}"
14
- TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}')
15
- RAW_CWD=$(echo "$INPUT" | jq -r '.cwd // ""')
16
- PROJECT_PATH=$(resolve_project_path "${RAW_CWD:-$PWD}")
17
- SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // .sessionId // ""')
18
- SESSION_ID="${SESSION_ID:-${CLAUDE_CODE_SESSION_ID:-cli}}"
19
-
20
- # 构造事件 JSON(jq -n 替代 python3 heredoc)
21
- TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
22
- EVENT=$(jq -nc \
23
- --arg hook_type "PreToolUse" \
24
- --arg timestamp "$TIMESTAMP" \
25
- --arg session_id "$SESSION_ID" \
26
- --arg project_path "$PROJECT_PATH" \
27
- --arg tool_name "$TOOL_NAME" \
28
- --argjson tool_input "$TOOL_INPUT" \
29
- --arg auth "$AUTH_TOKEN" \
30
- '{hook_type: $hook_type, timestamp: $timestamp, session_id: $session_id,
31
- project_path: $project_path, tool_name: $tool_name, tool_input: $tool_input,
32
- _auth: $auth}')
33
-
34
- # 发送事件(5 秒超时;失败时入队)
35
- send_event_or_enqueue "$EVENT" 5
36
- RESPONSE="$HOOK_RESPONSE"
37
-
38
- if [ -n "$RESPONSE" ]; then
39
- ALLOW=$(echo "$RESPONSE" | jq -r '.allow // true')
40
-
41
- if [ "$ALLOW" = "false" ]; then
42
- # 优先使用 hookSpecificOutput(Claude Code 官方格式),否则降级到 stderr + exit 2
43
- HAS_HOOK_OUTPUT=$(echo "$RESPONSE" | jq -r 'if .hookSpecificOutput then "yes" else "no" end')
44
- if [ "$HAS_HOOK_OUTPUT" = "yes" ]; then
45
- # 输出 hookSpecificOutput 格式到 stdout,但必须 exit 非0 才能真正阻止工具执行
46
- echo "$RESPONSE" | jq '{hookSpecificOutput: .hookSpecificOutput}'
47
- exit 1
48
- else
49
- # 降级:输出原因到 stderr,exit 2 强制阻断
50
- REASON=$(echo "$RESPONSE" | jq -r '.reason // "操作被 Forge 阻断"')
51
- echo "$REASON" >&2
52
- exit 2
53
- fi
54
- fi
55
-
56
- # 有 additionalContext 时输出
57
- HAS_CONTEXT=$(echo "$RESPONSE" | jq -r 'if .additionalContext and (.additionalContext != "") then "yes" else "no" end')
58
- if [ "$HAS_CONTEXT" = "yes" ]; then
59
- echo "$RESPONSE"
60
- fi
61
- fi
62
-
63
- exit 0
package/src/hooks/stop.sh DELETED
@@ -1,43 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - Stop Hook
3
-
4
- # shellcheck source=./hook-lib.sh
5
- source "$(dirname "$0")/hook-lib.sh"
6
-
7
- AUTH_TOKEN=$(cat "$HOME/.claude-forge/daemon.token" 2>/dev/null || echo '')
8
-
9
- # 读取 stdin
10
- INPUT=$(cat 2>/dev/null || echo '{}')
11
-
12
- # 提取 cwd,上溯 git root
13
- RAW_CWD=$(echo "$INPUT" | jq -r '.cwd // ""')
14
- PROJECT_PATH=$(resolve_project_path "${RAW_CWD:-$PWD}")
15
- SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // .sessionId // ""')
16
- SESSION_ID="${SESSION_ID:-${CLAUDE_CODE_SESSION_ID:-cli}}"
17
-
18
- # 构造事件 JSON
19
- TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
20
- EVENT=$(jq -nc \
21
- --arg hook_type "Stop" \
22
- --arg timestamp "$TIMESTAMP" \
23
- --arg session_id "$SESSION_ID" \
24
- --arg project_path "$PROJECT_PATH" \
25
- --arg auth "$AUTH_TOKEN" \
26
- '{hook_type: $hook_type, timestamp: $timestamp, session_id: $session_id,
27
- project_path: $project_path, tool_name: "stop", tool_input: {}, _auth: $auth}')
28
-
29
- # 发送事件并读取响应(失败时入队)
30
- send_event_or_enqueue "$EVENT" 5
31
- RESPONSE="$HOOK_RESPONSE"
32
-
33
- # 解析响应:allow=false 时输出 reason 并以 exit 2 阻断
34
- if [ -n "$RESPONSE" ]; then
35
- ALLOW=$(echo "$RESPONSE" | jq -r '.allow // true' 2>/dev/null)
36
- if [ "$ALLOW" = "false" ]; then
37
- REASON=$(echo "$RESPONSE" | jq -r '.reason // "质量门禁阻断"' 2>/dev/null)
38
- echo "$REASON"
39
- exit 2
40
- fi
41
- fi
42
-
43
- exit 0
@@ -1,69 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Claude Forge - UserPromptSubmit Hook
3
- # 拦截用户输入,触发意图分析和自动 Pipeline 编排
4
-
5
- # shellcheck source=./hook-lib.sh
6
- source "$(dirname "$0")/hook-lib.sh"
7
-
8
- AUTH_TOKEN=$(cat "$HOME/.claude-forge/daemon.token" 2>/dev/null || echo '')
9
-
10
- # 读取 stdin(Claude Code 传入的 JSON)
11
- INPUT=$(cat)
12
-
13
- # 提取字段(jq 替代 python3)
14
- USER_PROMPT=$(echo "$INPUT" | jq -r '.prompt // ""')
15
- RAW_CWD=$(echo "$INPUT" | jq -r '.cwd // ""')
16
- PROJECT_PATH=$(resolve_project_path "${RAW_CWD:-$PWD}")
17
- SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // .sessionId // ""')
18
- SESSION_ID="${SESSION_ID:-${CLAUDE_CODE_SESSION_ID:-cli}}"
19
-
20
- # 空 prompt 跳过
21
- if [ -z "$USER_PROMPT" ]; then
22
- exit 0
23
- fi
24
-
25
- # 构造事件 JSON(jq -n 替代 python3 heredoc)
26
- TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
27
- EVENT=$(jq -nc \
28
- --arg hook_type "UserPromptSubmit" \
29
- --arg timestamp "$TIMESTAMP" \
30
- --arg session_id "$SESSION_ID" \
31
- --arg project_path "$PROJECT_PATH" \
32
- --arg user_prompt "$USER_PROMPT" \
33
- --arg auth "$AUTH_TOKEN" \
34
- '{hook_type: $hook_type, timestamp: $timestamp, session_id: $session_id,
35
- project_path: $project_path, tool_name: "UserPrompt",
36
- user_prompt: $user_prompt, tool_input: {user_prompt: $user_prompt}, _auth: $auth}')
37
-
38
- if [ -z "$EVENT" ]; then
39
- exit 0
40
- fi
41
-
42
- # 发送事件(10 秒超时,AI 分析可能需要更多时间)
43
- # 失败时自动入队(daemon 停机期间事件不丢失)
44
- send_event_or_enqueue "$EVENT" 10
45
- RESPONSE="$HOOK_RESPONSE"
46
-
47
- if [ -n "$RESPONSE" ]; then
48
- HAS_SYSTEM=$(echo "$RESPONSE" | jq -r 'if .systemMessage and (.systemMessage != "") then "yes" else "no" end')
49
- HAS_CONTEXT=$(echo "$RESPONSE" | jq -r 'if .additionalContext and (.additionalContext != "") then "yes" else "no" end')
50
-
51
- if [ "$HAS_SYSTEM" = "yes" ] || [ "$HAS_CONTEXT" = "yes" ]; then
52
- # stderr 输出摘要到终端
53
- if [ "$HAS_SYSTEM" = "yes" ]; then
54
- SM_LEN=$(echo "$RESPONSE" | jq -r '.systemMessage | length')
55
- printf '\033[36m💉 [Forge] 注入 systemMessage (%s chars)\033[0m\n' "$SM_LEN" >&2
56
- fi
57
- if [ "$HAS_CONTEXT" = "yes" ]; then
58
- CONTEXT=$(echo "$RESPONSE" | jq -r '.additionalContext // ""')
59
- DISPLAY_LINES=$(printf '%s' "$CONTEXT" | head -3)
60
- if [ -n "$DISPLAY_LINES" ]; then
61
- printf '\033[36m💉 [Forge] %s\033[0m\n' "$DISPLAY_LINES" >&2
62
- fi
63
- fi
64
- # stdout 返回给 Claude Code
65
- echo "$RESPONSE"
66
- fi
67
- fi
68
-
69
- exit 0