@winspan/claude-forge 8.51.1 → 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 (409) 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 +121 -2
  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/constants.d.ts +2 -0
  11. package/dist/core/constants.d.ts.map +1 -1
  12. package/dist/core/constants.js +4 -0
  13. package/dist/core/constants.js.map +1 -1
  14. package/dist/core/storage/events.d.ts.map +1 -1
  15. package/dist/core/storage/events.js +0 -1
  16. package/dist/core/storage/events.js.map +1 -1
  17. package/dist/core/storage/maintenance.d.ts +25 -3
  18. package/dist/core/storage/maintenance.d.ts.map +1 -1
  19. package/dist/core/storage/maintenance.js +33 -4
  20. package/dist/core/storage/maintenance.js.map +1 -1
  21. package/dist/core/storage/routing.d.ts +4 -0
  22. package/dist/core/storage/routing.d.ts.map +1 -1
  23. package/dist/core/storage/routing.js +10 -4
  24. package/dist/core/storage/routing.js.map +1 -1
  25. package/dist/core/storage/sessions.d.ts +17 -0
  26. package/dist/core/storage/sessions.d.ts.map +1 -1
  27. package/dist/core/storage/sessions.js +64 -0
  28. package/dist/core/storage/sessions.js.map +1 -1
  29. package/dist/core/storage/skills.d.ts +4 -0
  30. package/dist/core/storage/skills.d.ts.map +1 -1
  31. package/dist/core/storage/skills.js +10 -2
  32. package/dist/core/storage/skills.js.map +1 -1
  33. package/dist/core/storage/sqlite.d.ts +5 -0
  34. package/dist/core/storage/sqlite.d.ts.map +1 -1
  35. package/dist/core/storage/sqlite.js +6 -0
  36. package/dist/core/storage/sqlite.js.map +1 -1
  37. package/dist/core/storage/tasks.d.ts.map +1 -1
  38. package/dist/core/storage/tasks.js +2 -0
  39. package/dist/core/storage/tasks.js.map +1 -1
  40. package/dist/core/types.d.ts +7 -0
  41. package/dist/core/types.d.ts.map +1 -1
  42. package/dist/daemon/index.d.ts.map +1 -1
  43. package/dist/daemon/index.js +30 -5
  44. package/dist/daemon/index.js.map +1 -1
  45. package/dist/daemon/skill-sync.d.ts +21 -0
  46. package/dist/daemon/skill-sync.d.ts.map +1 -0
  47. package/dist/daemon/skill-sync.js +75 -0
  48. package/dist/daemon/skill-sync.js.map +1 -0
  49. package/dist/hooks/notification.sh +1 -1
  50. package/dist/hooks/post-tool-use.sh +1 -1
  51. package/dist/hooks/pre-tool-use.sh +1 -1
  52. package/dist/hooks/stop.sh +1 -1
  53. package/dist/hooks/user-prompt-submit.sh +1 -1
  54. package/dist/skills/official/code-simplifier.md +37 -1
  55. package/dist/skills/official/find-skills.md +120 -1
  56. package/dist/skills/official/official-api-design.md +14 -1
  57. package/dist/skills/official/official-architecture-decision.md +22 -1
  58. package/dist/skills/official/official-db-schema-design.md +19 -1
  59. package/dist/skills/official/official-debug.md +9 -1
  60. package/dist/skills/official/official-pr-review.md +1 -1
  61. package/dist/skills/official/official-security-hardening.md +7 -1
  62. package/dist/skills/official/planning-with-files.md +206 -2
  63. package/dist/skills/official/ui-ux-pro-max.md +88 -1
  64. package/dist/skills/official/webapp-testing.md +85 -1
  65. package/dist/skills/registry.d.ts +1 -1
  66. package/dist/skills/registry.d.ts.map +1 -1
  67. package/dist/skills/registry.js +15 -4
  68. package/dist/skills/registry.js.map +1 -1
  69. package/dist/skills/semantic-matcher.d.ts +4 -3
  70. package/dist/skills/semantic-matcher.d.ts.map +1 -1
  71. package/dist/skills/semantic-matcher.js +20 -22
  72. package/dist/skills/semantic-matcher.js.map +1 -1
  73. package/dist/skills/upgrade-engine.d.ts +93 -0
  74. package/dist/skills/upgrade-engine.d.ts.map +1 -0
  75. package/dist/skills/upgrade-engine.js +447 -0
  76. package/dist/skills/upgrade-engine.js.map +1 -0
  77. package/dist/skills/upgrade-prompt.d.ts +20 -0
  78. package/dist/skills/upgrade-prompt.d.ts.map +1 -0
  79. package/dist/skills/upgrade-prompt.js +75 -0
  80. package/dist/skills/upgrade-prompt.js.map +1 -0
  81. package/dist/web/analytics/weekly-report.d.ts.map +1 -1
  82. package/dist/web/analytics/weekly-report.js +21 -29
  83. package/dist/web/analytics/weekly-report.js.map +1 -1
  84. package/dist/web/routes/patch.d.ts.map +1 -1
  85. package/dist/web/routes/patch.js +32 -2
  86. package/dist/web/routes/patch.js.map +1 -1
  87. package/dist/web/routes/sessions.d.ts.map +1 -1
  88. package/dist/web/routes/sessions.js +9 -7
  89. package/dist/web/routes/sessions.js.map +1 -1
  90. package/dist/web/routes/trace.d.ts.map +1 -1
  91. package/dist/web/routes/trace.js +2 -3
  92. package/dist/web/routes/trace.js.map +1 -1
  93. package/dist/web/server.d.ts.map +1 -1
  94. package/dist/web/server.js +3 -2
  95. package/dist/web/server.js.map +1 -1
  96. package/package.json +12 -2
  97. package/scripts/postinstall.cjs +21 -0
  98. package/.claude/CLAUDE.md +0 -17
  99. package/.eslintrc.js +0 -23
  100. package/.prettierrc +0 -8
  101. package/ARCHITECTURE_ISSUES.md +0 -249
  102. package/CLAUDE.md +0 -265
  103. package/CLAUDE.md.backup +0 -488
  104. package/docs/concurrent-agents.md +0 -129
  105. package/docs/design/architecture-review-20260516.md +0 -232
  106. package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +0 -219
  107. package/docs/design/h1-storage-aggregation-spec-20260518-1121.md +0 -299
  108. package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +0 -191
  109. package/docs/design/h3-fallback-removal-spec-20260518-1245.md +0 -76
  110. package/docs/design/h4-index-dedup-spec-20260518-1230.md +0 -109
  111. package/docs/design/h6-services-migration-spec-20260518-1355.md +0 -82
  112. package/docs/design/hook-failure-queue-spec-20260516-1530.md +0 -204
  113. package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +0 -106
  114. package/docs/design/m10-forge-paths-spec-20260518-1320.md +0 -121
  115. package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +0 -131
  116. package/docs/design/m7-routing-event-association-spec-20260518-1545.md +0 -103
  117. package/docs/design/project-path-gitroot-spec-20260518-1715.md +0 -134
  118. package/docs/design/refactor-phase1-spec-20260515-1600.md +0 -543
  119. package/docs/design/refactor-phase2-spec-20260515-1700.md +0 -424
  120. package/docs/design/task-active-gc-spec-20260518-1745.md +0 -146
  121. package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +0 -208
  122. package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +0 -104
  123. package/docs/implementation/h1-storage-aggregation-changelog-20260518-1121.md +0 -82
  124. package/docs/implementation/h2-final-changelog-20260518-1530.md +0 -61
  125. package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +0 -70
  126. package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +0 -120
  127. package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +0 -71
  128. package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +0 -71
  129. package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +0 -60
  130. package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +0 -46
  131. package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +0 -46
  132. package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +0 -196
  133. package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +0 -56
  134. package/docs/implementation/l1-swarm-protocol-extract-changelog-20260518-1605.md +0 -45
  135. package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +0 -63
  136. package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +0 -38
  137. package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +0 -58
  138. package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +0 -60
  139. package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +0 -43
  140. package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +0 -56
  141. package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +0 -69
  142. package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +0 -63
  143. package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +0 -354
  144. package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +0 -421
  145. package/docs/implementation/task-active-gc-changelog-20260518-1745.md +0 -35
  146. package/docs/implementation/task-title-summary-changelog-20260518-1130.md +0 -39
  147. package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +0 -22
  148. package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +0 -72
  149. package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +0 -56
  150. package/docs/reviews/claudemd-template-sync.md +0 -54
  151. package/docs/reviews/task-title-summary.md +0 -92
  152. package/docs/reviews/tasks-detail-back-loses-filters.md +0 -58
  153. package/docs/reviews/tasks-filter-pagination.md +0 -80
  154. package/docs/reviews/tasks-page-white-screen-hotfix.md +0 -126
  155. package/docs/ruflo-learning-strategy.md +0 -322
  156. package/docs/skills-deduplication-analysis.md +0 -83
  157. package/docs/skills-multiformat-support.md +0 -177
  158. package/docs/skills-third-party.md +0 -183
  159. package/docs/testing/tasks-filter-pagination-test-report.md +0 -86
  160. package/forge +0 -321
  161. package/playwright.config.ts +0 -40
  162. package/scripts/demo-v2.ts +0 -91
  163. package/scripts/dev-daemon.sh +0 -232
  164. package/scripts/dev-web.ts +0 -109
  165. package/scripts/e2e-mcp-link.ts +0 -423
  166. package/scripts/e2e-methodology-quality.ts +0 -253
  167. package/scripts/e2e-routing.ts +0 -456
  168. package/scripts/e2e-user-methodology.ts +0 -326
  169. package/scripts/e2e-web-workflows.ts +0 -299
  170. package/scripts/migrate-legacy-to-dynamic.sql +0 -108
  171. package/scripts/regenerate-execution-docs.ts +0 -116
  172. package/scripts/sync-agent-skills.ts +0 -193
  173. package/scripts/test-hook.sh +0 -71
  174. package/scripts/verify-skill-loading.ts +0 -62
  175. package/src/claudemd/claudemd-generator.ts +0 -568
  176. package/src/claudemd/convention-extractor.ts +0 -69
  177. package/src/claudemd/index.ts +0 -35
  178. package/src/claudemd/persona-manager.ts +0 -88
  179. package/src/claudemd/resume-manager.ts +0 -236
  180. package/src/claudemd/tech-detector.ts +0 -220
  181. package/src/claudemd/templates/swarm-protocol.md +0 -222
  182. package/src/cli/commands/claudemd.ts +0 -84
  183. package/src/cli/commands/config.ts +0 -46
  184. package/src/cli/commands/daemon.ts +0 -310
  185. package/src/cli/commands/executions.ts +0 -115
  186. package/src/cli/commands/init.ts +0 -204
  187. package/src/cli/commands/logs.ts +0 -181
  188. package/src/cli/commands/mcp.ts +0 -242
  189. package/src/cli/commands/menu.ts +0 -357
  190. package/src/cli/commands/skills.ts +0 -185
  191. package/src/cli/commands/stats.ts +0 -73
  192. package/src/cli/commands/status.ts +0 -69
  193. package/src/cli/commands/template.ts +0 -77
  194. package/src/cli/commands/trace.ts +0 -148
  195. package/src/cli/index.ts +0 -42
  196. package/src/cli/init/hook-manager.ts +0 -132
  197. package/src/core/ai/provider.ts +0 -308
  198. package/src/core/ai/types.ts +0 -51
  199. package/src/core/config.ts +0 -124
  200. package/src/core/constants.ts +0 -62
  201. package/src/core/event-fields.ts +0 -32
  202. package/src/core/queue/index.ts +0 -192
  203. package/src/core/storage/base.ts +0 -302
  204. package/src/core/storage/events.ts +0 -434
  205. package/src/core/storage/injections.ts +0 -78
  206. package/src/core/storage/maintenance.ts +0 -59
  207. package/src/core/storage/migrations/002_add_skill_tracking.sql +0 -6
  208. package/src/core/storage/migrations/003_add_skill_invocations.sql +0 -23
  209. package/src/core/storage/performance-indexes.sql +0 -23
  210. package/src/core/storage/routing.ts +0 -322
  211. package/src/core/storage/rows.ts +0 -112
  212. package/src/core/storage/schema.sql +0 -224
  213. package/src/core/storage/sessions.ts +0 -168
  214. package/src/core/storage/skills.ts +0 -233
  215. package/src/core/storage/sqlite.ts +0 -293
  216. package/src/core/storage/tasks.ts +0 -318
  217. package/src/core/storage/token-usage.ts +0 -93
  218. package/src/core/types.ts +0 -181
  219. package/src/core/utils/error-handler.ts +0 -257
  220. package/src/core/utils/forge-resume-block.ts +0 -74
  221. package/src/core/utils/format.ts +0 -69
  222. package/src/core/utils/git.ts +0 -23
  223. package/src/core/utils/logger.ts +0 -134
  224. package/src/core/utils/lru-cache.ts +0 -54
  225. package/src/core/utils/path.ts +0 -19
  226. package/src/core/utils/session.ts +0 -26
  227. package/src/core/utils/time.ts +0 -37
  228. package/src/core/utils/token-tracker.ts +0 -97
  229. package/src/daemon/event-parser.ts +0 -36
  230. package/src/daemon/handlers/history-exporter.ts +0 -117
  231. package/src/daemon/handlers/post-tool-use.ts +0 -54
  232. package/src/daemon/handlers/stop.ts +0 -208
  233. package/src/daemon/handlers/user-prompt.ts +0 -178
  234. package/src/daemon/hook-sync.ts +0 -91
  235. package/src/daemon/index.ts +0 -302
  236. package/src/daemon/launchd/com.claude-forge.daemon.plist.template +0 -47
  237. package/src/daemon/launchd-installer.ts +0 -260
  238. package/src/daemon/lifecycle.ts +0 -128
  239. package/src/daemon/router.ts +0 -40
  240. package/src/daemon/server.ts +0 -196
  241. package/src/daemon/services/task-segmenter.ts +0 -112
  242. package/src/hooks/hook-lib.sh +0 -118
  243. package/src/hooks/notification.sh +0 -35
  244. package/src/hooks/post-tool-use.sh +0 -61
  245. package/src/hooks/pre-tool-use.sh +0 -63
  246. package/src/hooks/stop.sh +0 -43
  247. package/src/hooks/user-prompt-submit.sh +0 -69
  248. package/src/mcp/server.ts +0 -322
  249. package/src/skills/index.ts +0 -2
  250. package/src/skills/invocation-guard.ts +0 -177
  251. package/src/skills/matcher.ts +0 -148
  252. package/src/skills/official/code-simplifier.md +0 -16
  253. package/src/skills/official/find-skills.md +0 -23
  254. package/src/skills/official/official-api-design.md +0 -17
  255. package/src/skills/official/official-architecture-decision.md +0 -20
  256. package/src/skills/official/official-bmad.md +0 -118
  257. package/src/skills/official/official-db-schema-design.md +0 -16
  258. package/src/skills/official/official-debug.md +0 -17
  259. package/src/skills/official/official-doc-driven.md +0 -31
  260. package/src/skills/official/official-harness-engineering.md +0 -108
  261. package/src/skills/official/official-performance-optimization.md +0 -30
  262. package/src/skills/official/official-pr-review.md +0 -35
  263. package/src/skills/official/official-release-checklist.md +0 -30
  264. package/src/skills/official/official-security-hardening.md +0 -26
  265. package/src/skills/official/official-spec-driven-design.md +0 -31
  266. package/src/skills/official/planning-with-files.md +0 -37
  267. package/src/skills/official/ui-ux-pro-max.md +0 -18
  268. package/src/skills/official/webapp-testing.md +0 -12
  269. package/src/skills/official-skills.ts +0 -89
  270. package/src/skills/registry.ts +0 -355
  271. package/src/skills/semantic-matcher.ts +0 -231
  272. package/src/skills/tools/pipeline-suggest.ts +0 -226
  273. package/src/skills/tools/skill-invoke.ts +0 -168
  274. package/src/skills/tools/skill-list.ts +0 -59
  275. package/src/templates/go.yaml +0 -53
  276. package/src/templates/python.yaml +0 -59
  277. package/src/templates/react.yaml +0 -55
  278. package/src/templates/template-manager.ts +0 -170
  279. package/src/web/analytics/anti-pattern-detector.ts +0 -367
  280. package/src/web/analytics/drift-detector.ts +0 -219
  281. package/src/web/analytics/weekly-report.ts +0 -431
  282. package/src/web/auth-middleware.ts +0 -54
  283. package/src/web/routes/_helpers.ts +0 -34
  284. package/src/web/routes/ai.ts +0 -204
  285. package/src/web/routes/auth.ts +0 -22
  286. package/src/web/routes/drift.ts +0 -25
  287. package/src/web/routes/error-handler.ts +0 -120
  288. package/src/web/routes/events.ts +0 -47
  289. package/src/web/routes/insights.ts +0 -43
  290. package/src/web/routes/patch.ts +0 -117
  291. package/src/web/routes/reports.ts +0 -34
  292. package/src/web/routes/rules.ts +0 -76
  293. package/src/web/routes/sessions.ts +0 -250
  294. package/src/web/routes/skill-stats.ts +0 -92
  295. package/src/web/routes/skills.ts +0 -350
  296. package/src/web/routes/static.ts +0 -67
  297. package/src/web/routes/stats.ts +0 -50
  298. package/src/web/routes/status.ts +0 -30
  299. package/src/web/routes/tasks.ts +0 -193
  300. package/src/web/routes/token-usage.ts +0 -20
  301. package/src/web/routes/trace.ts +0 -126
  302. package/src/web/routes/types.ts +0 -57
  303. package/src/web/server.ts +0 -134
  304. package/src/web/ssrf-guard.ts +0 -112
  305. package/src/web/static/index.html +0 -3251
  306. package/src/web/static/vendor/chart.umd.min.js +0 -20
  307. package/tests/e2e/dashboard.spec.ts +0 -205
  308. package/tests/e2e/routing-skill-e2e.test.ts +0 -39
  309. package/tests/helpers/mock-ai.ts +0 -92
  310. package/tests/helpers/mock-storage.ts +0 -159
  311. package/tests/integration/claudemd-generator.test.ts +0 -90
  312. package/tests/integration/queue-replay.integration.test.ts +0 -193
  313. package/tests/integration/tasks-filter.integration.test.ts +0 -154
  314. package/tests/integration/web-analytics.integration.test.ts +0 -133
  315. package/tests/integration/web-stats.integration.test.ts +0 -135
  316. package/tests/integration/web-trace.integration.test.ts +0 -175
  317. package/tests/performance/database.benchmark.ts +0 -161
  318. package/tests/semantic-matcher.test.ts +0 -99
  319. package/tests/skill-matcher.test.ts +0 -110
  320. package/tests/unit/ai-provider-retry.test.ts +0 -194
  321. package/tests/unit/ai-provider-vision.test.ts +0 -224
  322. package/tests/unit/claudemd-generator.test.ts +0 -68
  323. package/tests/unit/cli-mcp.test.ts +0 -141
  324. package/tests/unit/core/forge-paths.test.ts +0 -99
  325. package/tests/unit/daemon/hook-sync.test.ts +0 -71
  326. package/tests/unit/daemon/post-tool-use.test.ts +0 -121
  327. package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +0 -202
  328. package/tests/unit/daemon/task-segmenter-recover.test.ts +0 -84
  329. package/tests/unit/event-fields.test.ts +0 -88
  330. package/tests/unit/event-parser.test.ts +0 -55
  331. package/tests/unit/handlers.test.ts +0 -171
  332. package/tests/unit/hooks/resolve-project-path.test.ts +0 -122
  333. package/tests/unit/invocation-guard.test.ts +0 -125
  334. package/tests/unit/queue.test.ts +0 -272
  335. package/tests/unit/router.test.ts +0 -138
  336. package/tests/unit/security.test.ts +0 -128
  337. package/tests/unit/skill-invocations-workflow.test.ts +0 -495
  338. package/tests/unit/skill-registry.test.ts +0 -94
  339. package/tests/unit/skills/invocation-guard-ttl.test.ts +0 -211
  340. package/tests/unit/skills/official-skills-loader.test.ts +0 -126
  341. package/tests/unit/skills/registry-multiformat.test.ts +0 -92
  342. package/tests/unit/socket-server.test.ts +0 -183
  343. package/tests/unit/storage/event-operations-aggregates.test.ts +0 -342
  344. package/tests/unit/storage/migration-idempotent.test.ts +0 -304
  345. package/tests/unit/storage/routing-aggregates.test.ts +0 -276
  346. package/tests/unit/storage/routing.test.ts +0 -117
  347. package/tests/unit/storage/schema-missing.test.ts +0 -81
  348. package/tests/unit/storage/session-operations-aggregates.test.ts +0 -120
  349. package/tests/unit/storage/sessions-aggregate.test.ts +0 -435
  350. package/tests/unit/storage/skill-operations-counts.test.ts +0 -106
  351. package/tests/unit/storage/skills-aggregates.test.ts +0 -104
  352. package/tests/unit/storage/sqlite-refactor-harness.test.ts +0 -314
  353. package/tests/unit/storage/task-operations-counts.test.ts +0 -46
  354. package/tests/unit/storage/tasks-getById.test.ts +0 -343
  355. package/tests/unit/storage/tasks-stale-gc.test.ts +0 -86
  356. package/tests/unit/storage.test.ts +0 -172
  357. package/tests/unit/token-usage.test.ts +0 -144
  358. package/tests/unit/type-guards.test.ts +0 -201
  359. package/tests/unit/utils/format.test.ts +0 -189
  360. package/tests/unit/utils/session.test.ts +0 -89
  361. package/tests/unit/utils/time.test.ts +0 -112
  362. package/tests/unit/web/navigation-back-contract.test.ts +0 -134
  363. package/tests/unit/web/routes-auth.test.ts +0 -93
  364. package/tests/unit/web/routes-events.test.ts +0 -101
  365. package/tests/unit/web/routes-rules.test.ts +0 -182
  366. package/tests/unit/web/routes-sessions.test.ts +0 -181
  367. package/tests/unit/web/routes-skill-stats.test.ts +0 -179
  368. package/tests/unit/web/routes-stats.test.ts +0 -92
  369. package/tests/unit/web/routes-tasks.test.ts +0 -385
  370. package/tests/unit/web/task-title-contract.test.ts +0 -210
  371. package/tests/unit/web/tasks-component-contract.test.ts +0 -179
  372. package/tsconfig.json +0 -22
  373. package/vitest.config.ts +0 -21
  374. package/vitest.integration.config.ts +0 -16
  375. package/web/CLAUDE.md +0 -20
  376. package/web/index.html +0 -13
  377. package/web/package-lock.json +0 -4854
  378. package/web/package.json +0 -35
  379. package/web/postcss.config.js +0 -6
  380. package/web/src/App.tsx +0 -110
  381. package/web/src/components/CodeBlock.tsx +0 -31
  382. package/web/src/components/Confirm.tsx +0 -96
  383. package/web/src/components/Drawer.tsx +0 -60
  384. package/web/src/components/Layout.tsx +0 -145
  385. package/web/src/components/MarkdownRenderer.tsx +0 -77
  386. package/web/src/components/SearchInput.tsx +0 -31
  387. package/web/src/components/SessionDetailContent.tsx +0 -157
  388. package/web/src/components/Toast.tsx +0 -92
  389. package/web/src/index.css +0 -19
  390. package/web/src/main.tsx +0 -31
  391. package/web/src/pages/AIConfig.tsx +0 -233
  392. package/web/src/pages/Dashboard.tsx +0 -572
  393. package/web/src/pages/Events.tsx +0 -271
  394. package/web/src/pages/Reports.tsx +0 -428
  395. package/web/src/pages/SessionDetail.tsx +0 -162
  396. package/web/src/pages/Sessions.tsx +0 -205
  397. package/web/src/pages/Skills.tsx +0 -180
  398. package/web/src/pages/TaskDetail.tsx +0 -515
  399. package/web/src/pages/Tasks.tsx +0 -415
  400. package/web/src/utils/auth.ts +0 -59
  401. package/web/src/utils/export.ts +0 -54
  402. package/web/src/utils/navigation.ts +0 -25
  403. package/web/src/utils/task-title.ts +0 -49
  404. package/web/src/utils/time.ts +0 -13
  405. package/web/tailwind.config.js +0 -11
  406. package/web/tsconfig.json +0 -21
  407. package/web/tsconfig.node.json +0 -10
  408. package/web/vite.config.ts +0 -76
  409. package/winspan-claude-forge-8.43.0.tgz +0 -0
@@ -1,131 +0,0 @@
1
- # M2 + M3: event tool_input 类型契约 Spec
2
-
3
- ## 目标
4
- 为 `ForgeEvent.tool_input` 建立可选字段类型契约消除 `as any` 泛滥;同时让 `event_id` 在 parser 层尊重外部传入,为 hook 端端到端去重铺路。
5
-
6
- ## 调研结果
7
-
8
- ### M2 使用统计(30 处含 `as any` 与 `as Record<string,unknown>`)
9
-
10
- | 工具 | 字段 | 使用点 |
11
- |---|---|---|
12
- | Bash | `command` | `web/routes/sessions.ts:95,97,223,225`; `anti-pattern-detector.ts:256,363`; `cli/commands/logs.ts:44`; `history-exporter.ts:103` |
13
- | Edit/Write | `file_path` | `sessions.ts:90,91,232,233`; `tasks.ts:161,163`; `anti-pattern-detector.ts:140,356`; `resume-manager.ts:118`; `cli/commands/logs.ts:45`; `weekly-report.ts:274` |
14
- | UserPromptSubmit fallback | `user_prompt` | `sessions.ts:82,83,159,164`; `tasks.ts:168,171`; `daemon/index.ts:161`; `storage/base.ts:253,257` |
15
- | Agent/Task | `subagent_type`, `name`, `prompt` | `web/routes/tasks.ts:125–129`; `daemon/handlers/post-tool-use.ts:29` |
16
- | Notebook | `notebook_path` | `weekly-report.ts:274` |
17
-
18
- ### 使用模式
19
- **几乎全部是防御访问**:`(e.tool_input as any)?.command || ''`、`?.file_path`、`?? input?.command`。零处做 strict assert。
20
- 真正窄化的两处(`post-tool-use.ts:29`、`web/routes/tasks.ts:111-131`)也是 `?` 容忍。
21
-
22
- ### M3 event_id 流向
23
- - **Hook 端**:`pre-tool-use.sh`、`post-tool-use.sh` 等当前**不产生** `event_id`;payload 里无该字段。
24
- - **Queue 层**:`core/queue/index.ts:83` 已经写了 `event.event_id ?? randomUUID()`,文件名也依赖之。
25
- - **Storage 层**:`core/storage/events.ts:21` schema 已 `event_id: z.string().uuid().optional()`,`writeEvent` 也是 `event.event_id || randomUUID()`。**唯一断点**:`daemon/event-parser.ts:23` 无条件 `randomUUID()`,先于 storage,外部传入永远被覆盖。
26
-
27
- ## 方案选择
28
-
29
- ### M2:方案 B(lenient bag)+ 辅助 getter
30
- 理由:
31
- 1. 30+ 处使用全是 undefined-friendly,方案 A 需要给每个站点加 type guard,改动大且收益低(hook event 名不等于 tool 名,`Edit`/`Write`/`Bash` 都来自 `event.tool_name`,不是 `hook_type` discriminator)。
32
- 2. Claude Code 的 tool 集合是开放的(未来还可能新增),union 难以穷举;bag + index signature 兼容前向。
33
- 3. 已有 `anti-pattern-detector.ts:354-365` 的 `extractFilePath`/`extractBashCommand` 范式,扩展即可。
34
-
35
- ### M3:保留 `event_id` 可选透传
36
- `event-parser.ts` 改为 `event_id: validated.event_id ?? randomUUID()`,schema 加 `event_id: z.string().uuid().optional()`。**不强制 hook 端立即生成**。
37
-
38
- ## 类型设计
39
-
40
- ```ts
41
- // core/types.ts 追加
42
- export interface ToolInputFields {
43
- // Bash
44
- command?: string;
45
- description?: string;
46
- // Edit / Write / Read / NotebookEdit
47
- file_path?: string;
48
- notebook_path?: string;
49
- old_string?: string;
50
- new_string?: string;
51
- content?: string;
52
- // Agent / Task
53
- subagent_type?: string;
54
- name?: string;
55
- prompt?: string;
56
- // UserPromptSubmit fallback envelope
57
- user_prompt?: string;
58
- // 兼容未来未知字段
59
- [key: string]: unknown;
60
- }
61
-
62
- export interface ForgeEvent {
63
- // ...
64
- tool_input?: ToolInputFields;
65
- tool_output?: Record<string, unknown>;
66
- event_id?: string;
67
- }
68
-
69
- // helpers(放 core/event-fields.ts)
70
- export function getCommand(e: ForgeEvent): string | undefined {
71
- const c = e.tool_input?.command;
72
- return typeof c === 'string' ? c : undefined;
73
- }
74
- export function getFilePath(e: ForgeEvent): string | undefined {
75
- const fp = e.tool_input?.file_path ?? e.tool_input?.notebook_path;
76
- return typeof fp === 'string' && fp.length > 0 ? fp : undefined;
77
- }
78
- export function getUserPrompt(e: ForgeEvent): string | undefined {
79
- return e.user_prompt ?? (typeof e.tool_input?.user_prompt === 'string' ? e.tool_input.user_prompt : undefined);
80
- }
81
- export function getSubagentType(e: ForgeEvent): string | undefined {
82
- const s = e.tool_input?.subagent_type;
83
- return typeof s === 'string' ? s : undefined;
84
- }
85
- ```
86
-
87
- ## 改造范围
88
-
89
- | 文件 | 改动点 | 行数 |
90
- |---|---|---|
91
- | `src/core/types.ts` | 加 `ToolInputFields`;改 `ForgeEvent.tool_input` 类型 | +25 |
92
- | `src/core/event-fields.ts`(新建)| 4 个 getter | +30 |
93
- | `src/daemon/event-parser.ts` | schema 加 `event_id.optional()`;`event_id ?? randomUUID()`;`tool_input as ToolInputFields` | ~4 |
94
- | `src/daemon/index.ts:161` | 改 `getUserPrompt(event)` | 1 |
95
- | `src/web/routes/sessions.ts` | 8 处 `(tool_input as any)?.X` → getter | ~10 |
96
- | `src/web/routes/tasks.ts` | 5 处 | ~6 |
97
- | `src/cli/commands/logs.ts:42-46` | 直接用 `e.tool_input?.command` 等 | 4 |
98
- | `src/web/analytics/anti-pattern-detector.ts` | `extractFilePath/Command` 内联或调 getter | 2 |
99
- | `src/daemon/handlers/post-tool-use.ts:29` | `getSubagentType(event)` | 1 |
100
- | `src/daemon/handlers/history-exporter.ts:102-103` | 直接 `.file_path / .command` | 2 |
101
- | `src/claudemd/resume-manager.ts:118` | 已经接近规范,去 `as string` | 1 |
102
- | `src/core/storage/events.ts` | `tool_input` 反序列化 cast 调整 | 1 |
103
- | `src/core/storage/tasks.ts:233` | 同上 | 1 |
104
- | `src/core/storage/base.ts:253,257` | SQL 不变(已用 json_extract);无代码改动 | 0 |
105
-
106
- ## 测试策略
107
- - **新增** `src/tests/event-fields.test.ts`:4 个 getter × {undefined, wrong type, valid} 共约 12 case。
108
- - **新增** `src/tests/event-parser.test.ts`:
109
- - 无 `event_id` → 自动生成 UUID
110
- - 传入 `event_id` (合法 UUID) → 透传
111
- - `tool_input` 含 `command/file_path` → 落到 `ToolInputFields`
112
- - **回归**:`src/tests/events.test.ts`(若存在)补一条 `writeEvent` + parser 端到端 event_id 透传 + 重放 UNIQUE 拒收。
113
- - **集成**:现有 `tests/integration/*` 跑完无回归。
114
-
115
- ## 风险与回滚
116
- - **风险 1**:`ToolInputFields` 加 `[key:string]: unknown` 等于半放弃严格性 — 接受,因为目标是消 `as any` 与统一访问入口,而非全量窄化。
117
- - **风险 2**:M3 让外部 event_id 入库后,若 hook 端误用非 UUID 字符串,zod `.uuid()` 会抛 → 由 parser 抛错入 daemon error 路径,与现有 schema 失败同语义。回滚:parser 单行还原 `randomUUID()`。
118
- - **回滚成本**:M2 是纯类型 + getter 替换,git revert 即可;M3 仅 2 行。
119
-
120
- ## 实施顺序
121
- 1. 新增 `core/types.ts` 类型 + `core/event-fields.ts` getter,先跑 `tsc --noEmit`(此时旧 `as any` 仍有效,无破坏)。
122
- 2. 改 `daemon/event-parser.ts`(M3 + tool_input cast);加 parser 测试。
123
- 3. 逐文件替换 `as any`:`daemon/index.ts` → `cli/logs.ts` → `daemon/handlers/*` → `web/routes/sessions.ts` → `web/routes/tasks.ts` → `web/analytics/*` → `claudemd/resume-manager.ts`。每改一个跑 `tsc --noEmit`。
124
- 4. 跑 `npm test`,确认 0 回归。
125
- 5. 抓 hook 端 event_id 预生成作为后续 follow-up(**本 spec 不实施**)。
126
-
127
- ## 命名遵循
128
- - Getter 用 `get*` 前缀(符合「获取单个资源用 `get`」约定)。
129
- - 类型用 PascalCase:`ToolInputFields`。
130
- - 文件 kebab-case:`event-fields.ts`。
131
- - 字段名沿用 hook 原始命名 (`file_path` / `command` / `subagent_type`),不改 snake_case。
@@ -1,103 +0,0 @@
1
- # M7: post-tool-use routing_event 关联修复 Spec
2
-
3
- ## 目标
4
-
5
- 修复 `PostToolUseHandler` 将 Agent 调用错误关联到已完成(`obeyed` 已填)的 routing_event 的时序错配 bug:把"最近一条"语义收紧为"最近一条 pending(`obeyed IS NULL`)"。
6
-
7
- ## 数据流分析
8
-
9
- ### routing_event 生命周期
10
-
11
- | T | 触发 | 操作 | 状态 |
12
- |---|---|---|---|
13
- | T0 | user prompt P1 | `UserPromptHandler` 写 routing_event#1 | `obeyed=NULL` |
14
- | T1 | Agent 调用 | `PostToolUseHandler` 取 most-recent → #1,update | `#1.obeyed=1` |
15
- | T2 | 普通工具(Read/Bash)| 不写 routing_event | `#1.obeyed=1` |
16
- | T3 | user prompt P2 | 写 routing_event#2 | `#2.obeyed=NULL`,#1 仍 obeyed=1 |
17
- | T4 | Agent 调用 | 取 most-recent → #2 | 正常 |
18
-
19
- ### 现有读写点(routing_events)
20
-
21
- | 调用方 | 操作 | 方法 |
22
- |---|---|---|
23
- | `user-prompt.ts:120` | 每次 prompt insert,`obeyed=null` | `writeRoutingEvent` |
24
- | `post-tool-use.ts:33` | 取最近一条 | `getRecentRoutingEvent(sessionId)` |
25
- | `post-tool-use.ts:35` | 更新 obeyed/routed_to_* | `updateRoutingEvent(id, patch)` |
26
- | daemon 恢复 | 拉 pending(项目级) | `queryPendingRoutingEvents(ageMs)` |
27
- | 统计/聚合 | 只读 | `queryRoutingEvents`、`aggregate*` |
28
-
29
- ## Bug 复现路径
30
-
31
- **真实错配场景**:同一 user prompt 内连续 2+ 个 Agent 调用。
32
-
33
- ```
34
- T0 prompt P1 → write #1 (obeyed=NULL)
35
- T1 Agent#a 完成 → PostToolUse → getRecent → #1 → update {obeyed=1, routed_to_name='a'}
36
- T2 Agent#b 完成 → PostToolUse → getRecent → 仍是 #1 → update {obeyed=1, routed_to_name='b'}
37
- ```
38
-
39
- 后果:#1 的 `routed_to_name`、`first_tool_ts` 被第二个 Agent **覆盖**;第二个 Agent 调用**没有自己的归属 routing_event**,统计层缺数。
40
-
41
- **第二种错配**:跨 prompt 但中间 prompt 未走 UserPromptHandler(如 hook 失败 / daemon 重启后 buffer 丢失),下一个 Agent 仍会误关联到旧的 obeyed=1 的事件并把它再次覆盖。
42
-
43
- > review 描述的"覆盖未来不相关"其实是"覆盖过去已完成"语义,效果一致——丢失上次填充结果且当前调用无新行。
44
-
45
- ## 方案对比
46
-
47
- | 维度 | A: `obeyed IS NULL` 过滤 | B: sessionKey in-mem cache | C: A + B 组合 |
48
- |---|---|---|---|
49
- | 实现复杂度 | 低(1 个 SQL 改/加方法)| 中(cache + 失效)| 中高 |
50
- | 跨进程/重启鲁棒 | 强(DB 真源)| 弱(cache 丢)| 强 |
51
- | 同 prompt 多 Agent 行为 | 第 2 个 Agent 找不到 pending → 跳过更新(数据丢失)| 同上,cache 也指向同一 id | 同上 |
52
- | 时序正确性 | 强 | 强(cache 命中时)| 强 |
53
- | 风险 | 同 prompt 多 Agent 漏记需另案 | daemon crash 丢 cache | 复杂度高于必要 |
54
-
55
- **推荐:方案 A**。理由:
56
- 1. DB 是单一真源,无 cache 一致性问题。
57
- 2. 同 prompt 多 Agent 场景下,方案 A 与 B 行为一致(都只命中一次),不构成 B 的优势。
58
- 3. "同 prompt 多 Agent 都要记录"是 M7 范围外的功能扩展(应该在 PostToolUse 里 **insert** 新 routing_event 而非 update),不在此次修复内。
59
-
60
- ## 改造点
61
-
62
- | 文件 | 改动 |
63
- |---|---|
64
- | `src/core/storage/routing.ts` | `getRecentRoutingEvent(sessionId)` SQL 加 `AND obeyed IS NULL`;或保留旧方法 + 新增 `getRecentPendingRoutingEvent(sessionId)`(推荐后者,向后兼容) |
65
- | `src/daemon/handlers/post-tool-use.ts:33` | 调用新方法 `getRecentPendingRoutingEvent` |
66
- | `src/core/storage/sqlite.ts` | facade 透传新方法 |
67
- | `tests/unit/storage/routing.test.ts`(如缺则新建)| 单测:3 个时序 case |
68
- | `tests/unit/daemon/post-tool-use.test.ts`(如缺则新建)| handler 行为测试 |
69
-
70
- ## 测试策略
71
-
72
- **Storage 单测**(routing.test.ts):
73
- - `getRecentPendingRoutingEvent` 返回最近 `obeyed IS NULL` 的行
74
- - 已存在 obeyed=1 在前 + 新 pending 在后 → 返回新 pending
75
- - 全部 obeyed 已填 → 返回 null(不误返)
76
- - 不同 session 隔离
77
-
78
- **Handler 单测**(post-tool-use.test.ts,新增):
79
- - 时序 case 1(同 prompt 第 2 个 Agent):第 1 个 update 成功,第 2 个找不到 pending → silently skip(assert:原 routing_event 不被二次覆盖)
80
- - 时序 case 2(跨 prompt):每个 prompt 的 Agent 关联到自己的 event
81
- - 时序 case 3(无 routing_event):handler 不抛错
82
-
83
- 不需要集成测试(daemon 端到端已被 daemon 集成测试覆盖)。
84
-
85
- ## 风险与回滚
86
-
87
- - **风险 1**:同 prompt 多 Agent 漏记 → 文档化为已知限制(M7 范围外);后续可改为 PostToolUse insert 新行。
88
- - **风险 2**:旧库残留 obeyed=NULL 的 stale 行可能被新 prompt 的 Agent 错关 → 因为 ORDER BY ts DESC 限制 + session_id 过滤,最多影响"在该 session 内有非常老的孤儿 pending"的极端情况;可接受。
89
- - **回滚**:单 commit revert;新方法可保留无害。
90
-
91
- ## 实施顺序
92
-
93
- 1. routing.ts 新增 `getRecentPendingRoutingEvent`(SQL 加 `AND obeyed IS NULL`)
94
- 2. sqlite.ts facade 透传
95
- 3. routing.test.ts 加单测
96
- 4. post-tool-use.ts 切换调用
97
- 5. post-tool-use.test.ts 加 handler 单测
98
- 6. `npx tsc --noEmit` + 相关 vitest
99
-
100
- ## 命名遵循
101
-
102
- - `getRecentPendingRoutingEvent`(get 前缀,单个资源;与现有 `getRecentRoutingEvent`、`getExperimentAssignment` 对齐)
103
- - 不用 `queryRecentPending*`(query 前缀留给返回行集合的方法)
@@ -1,134 +0,0 @@
1
- # project-path git root 修复 Spec
2
-
3
- ## 目标
4
- 让 5 个 hook 在 IDE 调用时把 `cwd`(可能是任意子目录)上溯为 git 仓库根目录后再发给 daemon,从根上阻止子目录被生成 `.claude-forge/`。
5
-
6
- ## 调研结果
7
-
8
- | 位置 | 现状 | 改造需求 |
9
- |---|---|---|
10
- | `src/hooks/pre-tool-use.sh:15-16` | `PROJECT_PATH=$(jq -r '.cwd'); fallback $PWD` | 套上 `resolve_project_path` |
11
- | `src/hooks/post-tool-use.sh:17-18` | 同上 | 同上 |
12
- | `src/hooks/user-prompt-submit.sh:15-16` | 同上 | 同上 |
13
- | `src/hooks/stop.sh:11-12` | 同上 + 未引用 hook-lib.sh | 先 source hook-lib.sh 再用函数 |
14
- | `src/hooks/notification.sh:13-14` | 同上 | 同上 |
15
- | `src/hooks/hook-lib.sh` | 已有 `send_event_or_enqueue` 公共函数 | **新增 `resolve_project_path`** |
16
- | `src/daemon/handlers/history-exporter.ts:24` | `path.join(project_path,'.claude-forge','history')` | 不动(hook 端已传 git root) |
17
- | `src/cli/commands/executions.ts:16,53,85` | `process.cwd()` 拼 `.claude-forge` | 新增 `resolveGitRoot()` helper |
18
- | `src/templates/template-manager.ts:82,89` | `initProject(_, projectPath)` 由调用方传入 | 调用方传 git root 即可(init CLI 自身改) |
19
-
20
- 观察:`hook-lib.sh` 已存在公共函数集,`stop.sh` 是唯一未 source 它的 hook(手写 nc + socket),改造时顺手补齐一致性。
21
-
22
- ## 方案选择
23
-
24
- | | A. Hook 端解析 git root | B. Daemon 端解析 | C. 完全消除目录 | D. 混合 hash |
25
- |---|---|---|---|---|
26
- | 改动面 | 5 hook + lib + CLI | 1 处 | 涉及多模块迁移 | A+ 存储改造 |
27
- | 性能 | bash 上溯(O(深度),无子进程)| 每次 spawn `git` | 同 A | 同 A |
28
- | 下游受益 | 全部 | 仅 history-exporter | 全部但破坏可见性 | 全部 |
29
- | 老数据 | 兼容(新数据用新值)| 兼容 | 需迁移 | 需迁移 |
30
- | 风险 | 0 测试 hook 改动 | 子进程开销 | discoverability 破坏 | 引入新维度 |
31
-
32
- **推荐 A**:根因解决 + 保留用户在项目根 `ls` 即可看到 history 的可见性 + 不引入子进程开销。bash `while` 上溯零依赖,daemon / CLI 自动受益。
33
-
34
- ## 改造范围(约 70 行)
35
-
36
- | 文件 | 行数 | 说明 |
37
- |---|---|---|
38
- | `src/hooks/hook-lib.sh` | +25 | 新增 `resolve_project_path` |
39
- | `src/hooks/pre-tool-use.sh` | -2 +1 | 替换两行 |
40
- | `src/hooks/post-tool-use.sh` | -2 +1 | 同上 |
41
- | `src/hooks/user-prompt-submit.sh` | -2 +1 | 同上 |
42
- | `src/hooks/stop.sh` | -2 +2 | 先 source hook-lib.sh,再用函数 |
43
- | `src/hooks/notification.sh` | -2 +1 | 同上 |
44
- | `src/cli/commands/executions.ts` | +8 | 新增 `resolveGitRoot()` 替换 3 处 `process.cwd()` |
45
- | `src/cli/commands/init.ts`(调用 template-manager 处,需 grep 确认)| +2 | 把传给 `initProject` 的 `projectPath` 改成 git root |
46
- | 新增 `tests/unit/hooks/resolve-project-path.test.sh`(或 vitest 调 bash)| ~40 | safety-net |
47
- | 新增 `tests/integration/hook-gitroot.integration.test.ts` | ~50 | 端到端 |
48
-
49
- ## hook-lib.sh 公共函数设计
50
-
51
- ```bash
52
- # resolve_project_path <input_cwd>
53
- # 从 input_cwd 上溯查找最近的 .git 目录,输出 git root。
54
- # 非 git 项目 / 上溯到根 / 输入为空 → 回退到 input_cwd(再回退到 $PWD)。
55
- # 防御:最多上溯 64 层,避免符号链接环。
56
- resolve_project_path() {
57
- local dir="${1:-$PWD}"
58
- [ -z "$dir" ] && dir="$PWD"
59
-
60
- # 规整为绝对路径(不依赖 realpath)
61
- case "$dir" in
62
- /*) ;;
63
- *) dir="$PWD/$dir" ;;
64
- esac
65
-
66
- local guard=0
67
- while [ "$dir" != "/" ] && [ "$dir" != "." ] && [ $guard -lt 64 ]; do
68
- if [ -d "$dir/.git" ] || [ -f "$dir/.git" ]; then # 后者兼容 git worktree
69
- printf '%s' "$dir"
70
- return 0
71
- fi
72
- dir=$(dirname "$dir")
73
- guard=$((guard + 1))
74
- done
75
-
76
- # 未找到 → 回退到原 cwd
77
- printf '%s' "${1:-$PWD}"
78
- }
79
- ```
80
-
81
- 调用方一行替换:
82
- ```bash
83
- RAW_CWD=$(echo "$INPUT" | jq -r '.cwd // ""')
84
- PROJECT_PATH=$(resolve_project_path "${RAW_CWD:-$PWD}")
85
- ```
86
-
87
- ## CLI / daemon 端兼容
88
-
89
- **daemon 端**:不改。`history-exporter.ts:24` 信任传入的 `event.project_path`(hook 端已是 git root)。
90
-
91
- **CLI 端 `executions.ts`**:新增 helper(放 `src/core/utils/git.ts`):
92
- ```typescript
93
- export function resolveGitRoot(start = process.cwd()): string {
94
- try {
95
- return execSync('git rev-parse --show-toplevel', { cwd: start, stdio: ['ignore', 'pipe', 'ignore'] })
96
- .toString().trim() || start;
97
- } catch { return start; }
98
- }
99
- ```
100
- 三处 `path.join(process.cwd(), '.claude-forge', ...)` → `path.join(resolveGitRoot(), '.claude-forge', ...)`。
101
-
102
- **template-manager.ts**:函数本身签名不变(接收 `projectPath`),改 init 命令调用侧。
103
-
104
- ## 测试策略
105
-
106
- - **safety-net (单测 bash 函数)**:构造 fixture `/tmp/forge-test/repo/.git/`,对 `resolve_project_path /tmp/forge-test/repo/a/b/c` 断言返回 git root;非 git 目录断言回退;空输入断言回退到 `$PWD`。
107
- - **集成**:vitest 起一个 daemon,构造 `cwd=fixture/sub/dir` 的 INPUT,跑 `pre-tool-use.sh`,从 daemon storage queryEvents 断言 `project_path === fixture` 而非子目录。
108
- - **回归**:现有 daemon 集成测试不需要改(hook 端透明改造)。
109
- - **CLI 端**:单测 `resolveGitRoot()` 在 git 仓 / 非 git 仓两种 cwd 下的返回值。
110
-
111
- ## 风险与回滚
112
-
113
- - **`.git` 是文件(worktree)场景**:`[ -f "$dir/.git" ]` 已兼容。
114
- - **非 git 项目**:fallback 原 cwd,行为不变。
115
- - **monorepo 子模块各自 .git**:返回最近的 git root,符合预期。
116
- - **历史数据**:旧 sessions.project_path 仍是子目录路径,不做迁移;可选清单:列出 sessions 表去重 project_path,提供 `cf admin remap-project-path` 工具(非本次范围)。
117
- - **bash on Linux/macOS 差异**:用 POSIX 内建(`dirname` / `case`),不依赖 `realpath`。
118
- - **回滚**:还原 6 个文件即可,无 schema 变更。
119
-
120
- ## 实施顺序(refactor-safe)
121
-
122
- 1. **safety-net 阶段**:先写 `tests/unit/hooks/resolve-project-path.test.sh`(或 vitest 用 `child_process.execSync('bash -c "source hook-lib.sh && resolve_project_path ..."')`)和 `tests/integration/hook-gitroot.integration.test.ts`(先红)
123
- 2. **lib 阶段**:在 `hook-lib.sh` 新增 `resolve_project_path` → 单测转绿
124
- 3. **hook 改造**:5 个 hook 替换两行;`stop.sh` 同时改为 `source hook-lib.sh`(顺手补一致性)→ 集成测试转绿
125
- 4. **CLI 阶段**:新增 `src/core/utils/git.ts::resolveGitRoot`,改 `executions.ts` 3 处 + `init` 调用侧
126
- 5. **验证**:`npx tsc --noEmit` + `npm test` + 手工到 fixture 子目录跑 `cf executions list` 确认走 git root
127
- 6. **release**:bump patch 版本,changelog 注明"hooks 解析 git root,不再在子目录生成 .claude-forge"
128
-
129
- ## 命名遵循
130
-
131
- - bash 函数:`resolve_project_path`(snake_case,与 hook-lib 现有 `send_event_or_enqueue` / `_enqueue_event_bg` 一致)
132
- - TS 工具函数:`resolveGitRoot`(camelCase,`get` 前缀不适用因为这是计算非查询)
133
- - 新文件:`src/core/utils/git.ts`(kebab 化已为单词,遵循现有 `time.ts` / `session.ts`)
134
- - 测试文件:`tests/unit/hooks/resolve-project-path.test.sh` 或 `.test.ts`、`tests/integration/hook-gitroot.integration.test.ts`