@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.
- package/DEVELOPMENT.md +290 -221
- package/README.md +50 -8
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +121 -2
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/init/hook-manager.d.ts +1 -1
- package/dist/cli/init/hook-manager.d.ts.map +1 -1
- package/dist/cli/init/hook-manager.js +1 -0
- package/dist/cli/init/hook-manager.js.map +1 -1
- package/dist/core/constants.d.ts +2 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +4 -0
- package/dist/core/constants.js.map +1 -1
- package/dist/core/storage/events.d.ts.map +1 -1
- package/dist/core/storage/events.js +0 -1
- package/dist/core/storage/events.js.map +1 -1
- package/dist/core/storage/maintenance.d.ts +25 -3
- package/dist/core/storage/maintenance.d.ts.map +1 -1
- package/dist/core/storage/maintenance.js +33 -4
- package/dist/core/storage/maintenance.js.map +1 -1
- package/dist/core/storage/routing.d.ts +4 -0
- package/dist/core/storage/routing.d.ts.map +1 -1
- package/dist/core/storage/routing.js +10 -4
- package/dist/core/storage/routing.js.map +1 -1
- package/dist/core/storage/sessions.d.ts +17 -0
- package/dist/core/storage/sessions.d.ts.map +1 -1
- package/dist/core/storage/sessions.js +64 -0
- package/dist/core/storage/sessions.js.map +1 -1
- package/dist/core/storage/skills.d.ts +4 -0
- package/dist/core/storage/skills.d.ts.map +1 -1
- package/dist/core/storage/skills.js +10 -2
- package/dist/core/storage/skills.js.map +1 -1
- package/dist/core/storage/sqlite.d.ts +5 -0
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +6 -0
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts.map +1 -1
- package/dist/core/storage/tasks.js +2 -0
- package/dist/core/storage/tasks.js.map +1 -1
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +30 -5
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/skill-sync.d.ts +21 -0
- package/dist/daemon/skill-sync.d.ts.map +1 -0
- package/dist/daemon/skill-sync.js +75 -0
- package/dist/daemon/skill-sync.js.map +1 -0
- package/dist/hooks/notification.sh +1 -1
- package/dist/hooks/post-tool-use.sh +1 -1
- package/dist/hooks/pre-tool-use.sh +1 -1
- package/dist/hooks/stop.sh +1 -1
- package/dist/hooks/user-prompt-submit.sh +1 -1
- package/dist/skills/official/code-simplifier.md +37 -1
- package/dist/skills/official/find-skills.md +120 -1
- package/dist/skills/official/official-api-design.md +14 -1
- package/dist/skills/official/official-architecture-decision.md +22 -1
- package/dist/skills/official/official-db-schema-design.md +19 -1
- package/dist/skills/official/official-debug.md +9 -1
- package/dist/skills/official/official-pr-review.md +1 -1
- package/dist/skills/official/official-security-hardening.md +7 -1
- package/dist/skills/official/planning-with-files.md +206 -2
- package/dist/skills/official/ui-ux-pro-max.md +88 -1
- package/dist/skills/official/webapp-testing.md +85 -1
- package/dist/skills/registry.d.ts +1 -1
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +15 -4
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/semantic-matcher.d.ts +4 -3
- package/dist/skills/semantic-matcher.d.ts.map +1 -1
- package/dist/skills/semantic-matcher.js +20 -22
- package/dist/skills/semantic-matcher.js.map +1 -1
- package/dist/skills/upgrade-engine.d.ts +93 -0
- package/dist/skills/upgrade-engine.d.ts.map +1 -0
- package/dist/skills/upgrade-engine.js +447 -0
- package/dist/skills/upgrade-engine.js.map +1 -0
- package/dist/skills/upgrade-prompt.d.ts +20 -0
- package/dist/skills/upgrade-prompt.d.ts.map +1 -0
- package/dist/skills/upgrade-prompt.js +75 -0
- package/dist/skills/upgrade-prompt.js.map +1 -0
- package/dist/web/analytics/weekly-report.d.ts.map +1 -1
- package/dist/web/analytics/weekly-report.js +21 -29
- package/dist/web/analytics/weekly-report.js.map +1 -1
- package/dist/web/routes/patch.d.ts.map +1 -1
- package/dist/web/routes/patch.js +32 -2
- package/dist/web/routes/patch.js.map +1 -1
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +9 -7
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/trace.d.ts.map +1 -1
- package/dist/web/routes/trace.js +2 -3
- package/dist/web/routes/trace.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +3 -2
- package/dist/web/server.js.map +1 -1
- package/package.json +12 -2
- package/scripts/postinstall.cjs +21 -0
- package/.claude/CLAUDE.md +0 -17
- package/.eslintrc.js +0 -23
- package/.prettierrc +0 -8
- package/ARCHITECTURE_ISSUES.md +0 -249
- package/CLAUDE.md +0 -265
- package/CLAUDE.md.backup +0 -488
- package/docs/concurrent-agents.md +0 -129
- package/docs/design/architecture-review-20260516.md +0 -232
- package/docs/design/fix-skills-data-and-set-leak-spec-20260516-1300.md +0 -219
- package/docs/design/h1-storage-aggregation-spec-20260518-1121.md +0 -299
- package/docs/design/h2-getdatabase-encapsulation-spec-20260518-1450.md +0 -191
- package/docs/design/h3-fallback-removal-spec-20260518-1245.md +0 -76
- package/docs/design/h4-index-dedup-spec-20260518-1230.md +0 -109
- package/docs/design/h6-services-migration-spec-20260518-1355.md +0 -82
- package/docs/design/hook-failure-queue-spec-20260516-1530.md +0 -204
- package/docs/design/l1-swarm-protocol-extract-spec-20260518-1605.md +0 -106
- package/docs/design/m10-forge-paths-spec-20260518-1320.md +0 -121
- package/docs/design/m2-m3-tool-input-spec-20260518-1425.md +0 -131
- package/docs/design/m7-routing-event-association-spec-20260518-1545.md +0 -103
- package/docs/design/project-path-gitroot-spec-20260518-1715.md +0 -134
- package/docs/design/refactor-phase1-spec-20260515-1600.md +0 -543
- package/docs/design/refactor-phase2-spec-20260515-1700.md +0 -424
- package/docs/design/task-active-gc-spec-20260518-1745.md +0 -146
- package/docs/design/tasks-list-filter-pagination-spec-20260518-0930.md +0 -208
- package/docs/implementation/fix-skills-data-and-set-leak-changelog-20260516-1300.md +0 -104
- package/docs/implementation/h1-storage-aggregation-changelog-20260518-1121.md +0 -82
- package/docs/implementation/h2-final-changelog-20260518-1530.md +0 -61
- package/docs/implementation/h2-phase1-safety-net-changelog-20260518-1450.md +0 -70
- package/docs/implementation/h2-phase2-operations-changelog-20260518-1450.md +0 -120
- package/docs/implementation/h2-phase3-callsites-changelog-20260518-1450.md +0 -71
- package/docs/implementation/h3-fallback-removal-changelog-20260518-1245.md +0 -71
- package/docs/implementation/h4-index-dedup-changelog-20260518-1230.md +0 -60
- package/docs/implementation/h6-services-migration-changelog-20260518-1355.md +0 -46
- package/docs/implementation/h7-m9-defaults-changelog-20260518-1300.md +0 -46
- package/docs/implementation/hook-failure-queue-changelog-20260516-1530.md +0 -196
- package/docs/implementation/hotfix-daemon-event-reject-20260516-1430.md +0 -56
- package/docs/implementation/l1-swarm-protocol-extract-changelog-20260518-1605.md +0 -45
- package/docs/implementation/l3-l4-daemon-perf-changelog-20260518-1410.md +0 -63
- package/docs/implementation/l6-l8-final-cleanup-changelog-20260518-1640.md +0 -38
- package/docs/implementation/m1-m4-m5-l7-cleanup-changelog-20260518-1310.md +0 -58
- package/docs/implementation/m10-forge-paths-changelog-20260518-1320.md +0 -60
- package/docs/implementation/m2-m3-tool-input-changelog-20260518-1425.md +0 -43
- package/docs/implementation/m6-m8-naming-shutdown-changelog-20260518-1340.md +0 -56
- package/docs/implementation/m7-routing-association-changelog-20260518-1545.md +0 -69
- package/docs/implementation/project-path-gitroot-changelog-20260518-1715.md +0 -63
- package/docs/implementation/refactor-phase1-changelog-20260515-1630.md +0 -354
- package/docs/implementation/refactor-phase2-changelog-20260515-1705.md +0 -421
- package/docs/implementation/task-active-gc-changelog-20260518-1745.md +0 -35
- package/docs/implementation/task-title-summary-changelog-20260518-1130.md +0 -39
- package/docs/implementation/tasks-detail-back-loses-filters-changelog-20260518-1100.md +0 -22
- package/docs/implementation/tasks-list-filter-pagination-changelog-20260518-0930.md +0 -72
- package/docs/implementation/tasks-page-white-screen-hotfix-changelog-20260518-1015.md +0 -56
- package/docs/reviews/claudemd-template-sync.md +0 -54
- package/docs/reviews/task-title-summary.md +0 -92
- package/docs/reviews/tasks-detail-back-loses-filters.md +0 -58
- package/docs/reviews/tasks-filter-pagination.md +0 -80
- package/docs/reviews/tasks-page-white-screen-hotfix.md +0 -126
- package/docs/ruflo-learning-strategy.md +0 -322
- package/docs/skills-deduplication-analysis.md +0 -83
- package/docs/skills-multiformat-support.md +0 -177
- package/docs/skills-third-party.md +0 -183
- package/docs/testing/tasks-filter-pagination-test-report.md +0 -86
- package/forge +0 -321
- package/playwright.config.ts +0 -40
- package/scripts/demo-v2.ts +0 -91
- package/scripts/dev-daemon.sh +0 -232
- package/scripts/dev-web.ts +0 -109
- package/scripts/e2e-mcp-link.ts +0 -423
- package/scripts/e2e-methodology-quality.ts +0 -253
- package/scripts/e2e-routing.ts +0 -456
- package/scripts/e2e-user-methodology.ts +0 -326
- package/scripts/e2e-web-workflows.ts +0 -299
- package/scripts/migrate-legacy-to-dynamic.sql +0 -108
- package/scripts/regenerate-execution-docs.ts +0 -116
- package/scripts/sync-agent-skills.ts +0 -193
- package/scripts/test-hook.sh +0 -71
- package/scripts/verify-skill-loading.ts +0 -62
- package/src/claudemd/claudemd-generator.ts +0 -568
- package/src/claudemd/convention-extractor.ts +0 -69
- package/src/claudemd/index.ts +0 -35
- package/src/claudemd/persona-manager.ts +0 -88
- package/src/claudemd/resume-manager.ts +0 -236
- package/src/claudemd/tech-detector.ts +0 -220
- package/src/claudemd/templates/swarm-protocol.md +0 -222
- package/src/cli/commands/claudemd.ts +0 -84
- package/src/cli/commands/config.ts +0 -46
- package/src/cli/commands/daemon.ts +0 -310
- package/src/cli/commands/executions.ts +0 -115
- package/src/cli/commands/init.ts +0 -204
- package/src/cli/commands/logs.ts +0 -181
- package/src/cli/commands/mcp.ts +0 -242
- package/src/cli/commands/menu.ts +0 -357
- package/src/cli/commands/skills.ts +0 -185
- package/src/cli/commands/stats.ts +0 -73
- package/src/cli/commands/status.ts +0 -69
- package/src/cli/commands/template.ts +0 -77
- package/src/cli/commands/trace.ts +0 -148
- package/src/cli/index.ts +0 -42
- package/src/cli/init/hook-manager.ts +0 -132
- package/src/core/ai/provider.ts +0 -308
- package/src/core/ai/types.ts +0 -51
- package/src/core/config.ts +0 -124
- package/src/core/constants.ts +0 -62
- package/src/core/event-fields.ts +0 -32
- package/src/core/queue/index.ts +0 -192
- package/src/core/storage/base.ts +0 -302
- package/src/core/storage/events.ts +0 -434
- package/src/core/storage/injections.ts +0 -78
- package/src/core/storage/maintenance.ts +0 -59
- package/src/core/storage/migrations/002_add_skill_tracking.sql +0 -6
- package/src/core/storage/migrations/003_add_skill_invocations.sql +0 -23
- package/src/core/storage/performance-indexes.sql +0 -23
- package/src/core/storage/routing.ts +0 -322
- package/src/core/storage/rows.ts +0 -112
- package/src/core/storage/schema.sql +0 -224
- package/src/core/storage/sessions.ts +0 -168
- package/src/core/storage/skills.ts +0 -233
- package/src/core/storage/sqlite.ts +0 -293
- package/src/core/storage/tasks.ts +0 -318
- package/src/core/storage/token-usage.ts +0 -93
- package/src/core/types.ts +0 -181
- package/src/core/utils/error-handler.ts +0 -257
- package/src/core/utils/forge-resume-block.ts +0 -74
- package/src/core/utils/format.ts +0 -69
- package/src/core/utils/git.ts +0 -23
- package/src/core/utils/logger.ts +0 -134
- package/src/core/utils/lru-cache.ts +0 -54
- package/src/core/utils/path.ts +0 -19
- package/src/core/utils/session.ts +0 -26
- package/src/core/utils/time.ts +0 -37
- package/src/core/utils/token-tracker.ts +0 -97
- package/src/daemon/event-parser.ts +0 -36
- package/src/daemon/handlers/history-exporter.ts +0 -117
- package/src/daemon/handlers/post-tool-use.ts +0 -54
- package/src/daemon/handlers/stop.ts +0 -208
- package/src/daemon/handlers/user-prompt.ts +0 -178
- package/src/daemon/hook-sync.ts +0 -91
- package/src/daemon/index.ts +0 -302
- package/src/daemon/launchd/com.claude-forge.daemon.plist.template +0 -47
- package/src/daemon/launchd-installer.ts +0 -260
- package/src/daemon/lifecycle.ts +0 -128
- package/src/daemon/router.ts +0 -40
- package/src/daemon/server.ts +0 -196
- package/src/daemon/services/task-segmenter.ts +0 -112
- package/src/hooks/hook-lib.sh +0 -118
- package/src/hooks/notification.sh +0 -35
- package/src/hooks/post-tool-use.sh +0 -61
- package/src/hooks/pre-tool-use.sh +0 -63
- package/src/hooks/stop.sh +0 -43
- package/src/hooks/user-prompt-submit.sh +0 -69
- package/src/mcp/server.ts +0 -322
- package/src/skills/index.ts +0 -2
- package/src/skills/invocation-guard.ts +0 -177
- package/src/skills/matcher.ts +0 -148
- package/src/skills/official/code-simplifier.md +0 -16
- package/src/skills/official/find-skills.md +0 -23
- package/src/skills/official/official-api-design.md +0 -17
- package/src/skills/official/official-architecture-decision.md +0 -20
- package/src/skills/official/official-bmad.md +0 -118
- package/src/skills/official/official-db-schema-design.md +0 -16
- package/src/skills/official/official-debug.md +0 -17
- package/src/skills/official/official-doc-driven.md +0 -31
- package/src/skills/official/official-harness-engineering.md +0 -108
- package/src/skills/official/official-performance-optimization.md +0 -30
- package/src/skills/official/official-pr-review.md +0 -35
- package/src/skills/official/official-release-checklist.md +0 -30
- package/src/skills/official/official-security-hardening.md +0 -26
- package/src/skills/official/official-spec-driven-design.md +0 -31
- package/src/skills/official/planning-with-files.md +0 -37
- package/src/skills/official/ui-ux-pro-max.md +0 -18
- package/src/skills/official/webapp-testing.md +0 -12
- package/src/skills/official-skills.ts +0 -89
- package/src/skills/registry.ts +0 -355
- package/src/skills/semantic-matcher.ts +0 -231
- package/src/skills/tools/pipeline-suggest.ts +0 -226
- package/src/skills/tools/skill-invoke.ts +0 -168
- package/src/skills/tools/skill-list.ts +0 -59
- package/src/templates/go.yaml +0 -53
- package/src/templates/python.yaml +0 -59
- package/src/templates/react.yaml +0 -55
- package/src/templates/template-manager.ts +0 -170
- package/src/web/analytics/anti-pattern-detector.ts +0 -367
- package/src/web/analytics/drift-detector.ts +0 -219
- package/src/web/analytics/weekly-report.ts +0 -431
- package/src/web/auth-middleware.ts +0 -54
- package/src/web/routes/_helpers.ts +0 -34
- package/src/web/routes/ai.ts +0 -204
- package/src/web/routes/auth.ts +0 -22
- package/src/web/routes/drift.ts +0 -25
- package/src/web/routes/error-handler.ts +0 -120
- package/src/web/routes/events.ts +0 -47
- package/src/web/routes/insights.ts +0 -43
- package/src/web/routes/patch.ts +0 -117
- package/src/web/routes/reports.ts +0 -34
- package/src/web/routes/rules.ts +0 -76
- package/src/web/routes/sessions.ts +0 -250
- package/src/web/routes/skill-stats.ts +0 -92
- package/src/web/routes/skills.ts +0 -350
- package/src/web/routes/static.ts +0 -67
- package/src/web/routes/stats.ts +0 -50
- package/src/web/routes/status.ts +0 -30
- package/src/web/routes/tasks.ts +0 -193
- package/src/web/routes/token-usage.ts +0 -20
- package/src/web/routes/trace.ts +0 -126
- package/src/web/routes/types.ts +0 -57
- package/src/web/server.ts +0 -134
- package/src/web/ssrf-guard.ts +0 -112
- package/src/web/static/index.html +0 -3251
- package/src/web/static/vendor/chart.umd.min.js +0 -20
- package/tests/e2e/dashboard.spec.ts +0 -205
- package/tests/e2e/routing-skill-e2e.test.ts +0 -39
- package/tests/helpers/mock-ai.ts +0 -92
- package/tests/helpers/mock-storage.ts +0 -159
- package/tests/integration/claudemd-generator.test.ts +0 -90
- package/tests/integration/queue-replay.integration.test.ts +0 -193
- package/tests/integration/tasks-filter.integration.test.ts +0 -154
- package/tests/integration/web-analytics.integration.test.ts +0 -133
- package/tests/integration/web-stats.integration.test.ts +0 -135
- package/tests/integration/web-trace.integration.test.ts +0 -175
- package/tests/performance/database.benchmark.ts +0 -161
- package/tests/semantic-matcher.test.ts +0 -99
- package/tests/skill-matcher.test.ts +0 -110
- package/tests/unit/ai-provider-retry.test.ts +0 -194
- package/tests/unit/ai-provider-vision.test.ts +0 -224
- package/tests/unit/claudemd-generator.test.ts +0 -68
- package/tests/unit/cli-mcp.test.ts +0 -141
- package/tests/unit/core/forge-paths.test.ts +0 -99
- package/tests/unit/daemon/hook-sync.test.ts +0 -71
- package/tests/unit/daemon/post-tool-use.test.ts +0 -121
- package/tests/unit/daemon/stop-handler-behavior-summary.test.ts +0 -202
- package/tests/unit/daemon/task-segmenter-recover.test.ts +0 -84
- package/tests/unit/event-fields.test.ts +0 -88
- package/tests/unit/event-parser.test.ts +0 -55
- package/tests/unit/handlers.test.ts +0 -171
- package/tests/unit/hooks/resolve-project-path.test.ts +0 -122
- package/tests/unit/invocation-guard.test.ts +0 -125
- package/tests/unit/queue.test.ts +0 -272
- package/tests/unit/router.test.ts +0 -138
- package/tests/unit/security.test.ts +0 -128
- package/tests/unit/skill-invocations-workflow.test.ts +0 -495
- package/tests/unit/skill-registry.test.ts +0 -94
- package/tests/unit/skills/invocation-guard-ttl.test.ts +0 -211
- package/tests/unit/skills/official-skills-loader.test.ts +0 -126
- package/tests/unit/skills/registry-multiformat.test.ts +0 -92
- package/tests/unit/socket-server.test.ts +0 -183
- package/tests/unit/storage/event-operations-aggregates.test.ts +0 -342
- package/tests/unit/storage/migration-idempotent.test.ts +0 -304
- package/tests/unit/storage/routing-aggregates.test.ts +0 -276
- package/tests/unit/storage/routing.test.ts +0 -117
- package/tests/unit/storage/schema-missing.test.ts +0 -81
- package/tests/unit/storage/session-operations-aggregates.test.ts +0 -120
- package/tests/unit/storage/sessions-aggregate.test.ts +0 -435
- package/tests/unit/storage/skill-operations-counts.test.ts +0 -106
- package/tests/unit/storage/skills-aggregates.test.ts +0 -104
- package/tests/unit/storage/sqlite-refactor-harness.test.ts +0 -314
- package/tests/unit/storage/task-operations-counts.test.ts +0 -46
- package/tests/unit/storage/tasks-getById.test.ts +0 -343
- package/tests/unit/storage/tasks-stale-gc.test.ts +0 -86
- package/tests/unit/storage.test.ts +0 -172
- package/tests/unit/token-usage.test.ts +0 -144
- package/tests/unit/type-guards.test.ts +0 -201
- package/tests/unit/utils/format.test.ts +0 -189
- package/tests/unit/utils/session.test.ts +0 -89
- package/tests/unit/utils/time.test.ts +0 -112
- package/tests/unit/web/navigation-back-contract.test.ts +0 -134
- package/tests/unit/web/routes-auth.test.ts +0 -93
- package/tests/unit/web/routes-events.test.ts +0 -101
- package/tests/unit/web/routes-rules.test.ts +0 -182
- package/tests/unit/web/routes-sessions.test.ts +0 -181
- package/tests/unit/web/routes-skill-stats.test.ts +0 -179
- package/tests/unit/web/routes-stats.test.ts +0 -92
- package/tests/unit/web/routes-tasks.test.ts +0 -385
- package/tests/unit/web/task-title-contract.test.ts +0 -210
- package/tests/unit/web/tasks-component-contract.test.ts +0 -179
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -21
- package/vitest.integration.config.ts +0 -16
- package/web/CLAUDE.md +0 -20
- package/web/index.html +0 -13
- package/web/package-lock.json +0 -4854
- package/web/package.json +0 -35
- package/web/postcss.config.js +0 -6
- package/web/src/App.tsx +0 -110
- package/web/src/components/CodeBlock.tsx +0 -31
- package/web/src/components/Confirm.tsx +0 -96
- package/web/src/components/Drawer.tsx +0 -60
- package/web/src/components/Layout.tsx +0 -145
- package/web/src/components/MarkdownRenderer.tsx +0 -77
- package/web/src/components/SearchInput.tsx +0 -31
- package/web/src/components/SessionDetailContent.tsx +0 -157
- package/web/src/components/Toast.tsx +0 -92
- package/web/src/index.css +0 -19
- package/web/src/main.tsx +0 -31
- package/web/src/pages/AIConfig.tsx +0 -233
- package/web/src/pages/Dashboard.tsx +0 -572
- package/web/src/pages/Events.tsx +0 -271
- package/web/src/pages/Reports.tsx +0 -428
- package/web/src/pages/SessionDetail.tsx +0 -162
- package/web/src/pages/Sessions.tsx +0 -205
- package/web/src/pages/Skills.tsx +0 -180
- package/web/src/pages/TaskDetail.tsx +0 -515
- package/web/src/pages/Tasks.tsx +0 -415
- package/web/src/utils/auth.ts +0 -59
- package/web/src/utils/export.ts +0 -54
- package/web/src/utils/navigation.ts +0 -25
- package/web/src/utils/task-title.ts +0 -49
- package/web/src/utils/time.ts +0 -13
- package/web/tailwind.config.js +0 -11
- package/web/tsconfig.json +0 -21
- package/web/tsconfig.node.json +0 -10
- package/web/vite.config.ts +0 -76
- 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`
|