@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,424 +0,0 @@
|
|
|
1
|
-
# claude-forge 渐进式重构 - 第 2 迭代实施方案
|
|
2
|
-
|
|
3
|
-
**版本**: v1.0
|
|
4
|
-
**创建时间**: 2026-05-15 17:00
|
|
5
|
-
**迭代周期**: 2 周(10 个工作日)
|
|
6
|
-
**前置条件**: 第 1 迭代已完成(P0 安全漏洞修复 + P1 基础设施改进 + 测试覆盖率 40%)
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 1. 目标与范围
|
|
11
|
-
|
|
12
|
-
### 1.1 迭代目标
|
|
13
|
-
|
|
14
|
-
**主要目标**:
|
|
15
|
-
1. 消除代码重复,提升可维护性(P1-3, P1-4, P1-5)
|
|
16
|
-
2. 统一命名风格,提升代码可读性(P1-6, P1-7)
|
|
17
|
-
3. 优化数据库查询性能(P2-6, P2-7)
|
|
18
|
-
4. 防护内存泄漏风险(P2-8)
|
|
19
|
-
5. 提升测试覆盖率至 60%
|
|
20
|
-
|
|
21
|
-
**量化指标**:
|
|
22
|
-
- 代码重复率:从 ~15% 降至 <8%
|
|
23
|
-
- 测试覆盖率:从 40% 提升至 60%
|
|
24
|
-
- 数据库查询性能:N+1 查询减少 80%
|
|
25
|
-
- 内存泄漏风险:InvocationGuard 增加 TTL 机制
|
|
26
|
-
|
|
27
|
-
### 1.2 包含的问题
|
|
28
|
-
|
|
29
|
-
**P1 级问题**(必须完成):
|
|
30
|
-
- ✅ P1-3: 时间戳归一化逻辑重复(3 处)
|
|
31
|
-
- ✅ P1-4: 错误日志模式重复(5 处)
|
|
32
|
-
- ✅ P1-5: Session ID 截断逻辑重复(4 处)
|
|
33
|
-
- ✅ P1-6: 文件命名风格混乱(kebab-case vs camelCase)
|
|
34
|
-
- ✅ P1-7: 函数命名不一致(get vs query vs list)
|
|
35
|
-
|
|
36
|
-
**P2 级问题**(部分完成):
|
|
37
|
-
- ✅ P2-6: 数据库查询未使用预编译语句(部分文件)
|
|
38
|
-
- ✅ P2-7: 缺少连接池(SQLite WAL 模式优化)
|
|
39
|
-
- ✅ P2-8: 内存泄漏风险(InvocationGuard 无 TTL)
|
|
40
|
-
|
|
41
|
-
### 1.3 不包含的问题
|
|
42
|
-
|
|
43
|
-
**留到第 3 迭代**:
|
|
44
|
-
- P2-1: 类型断言滥用(需要更大范围的类型系统重构)
|
|
45
|
-
- P2-2: 错误处理不一致(需要统一错误处理策略)
|
|
46
|
-
- P2-3: 配置验证缺失(需要 Zod schema 设计)
|
|
47
|
-
- P2-4: 日志级别混乱(需要日志策略重新设计)
|
|
48
|
-
- P2-5: 魔法数字(需要常量提取策略)
|
|
49
|
-
- P2-9: 事件监听器泄漏(需要生命周期管理重构)
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## 2. 改动文件清单
|
|
54
|
-
|
|
55
|
-
### 2.1 新增文件(6 个)
|
|
56
|
-
|
|
57
|
-
| 文件路径 | 用途 | 预计行数 |
|
|
58
|
-
|---------|------|---------|
|
|
59
|
-
| `src/core/utils/time.ts` | 时间戳归一化工具 | 50 |
|
|
60
|
-
| `src/core/utils/session.ts` | Session ID 处理工具 | 40 |
|
|
61
|
-
| `src/core/utils/format.ts` | 通用格式化工具(日志、错误) | 80 |
|
|
62
|
-
| `tests/unit/utils/time.test.ts` | 时间工具测试 | 100 |
|
|
63
|
-
| `tests/unit/utils/session.test.ts` | Session 工具测试 | 80 |
|
|
64
|
-
| `tests/unit/utils/format.test.ts` | 格式化工具测试 | 120 |
|
|
65
|
-
|
|
66
|
-
### 2.2 修改文件(18 个)
|
|
67
|
-
|
|
68
|
-
| 文件路径 | 改动类型 | 预计改动行数 | 改动原因 |
|
|
69
|
-
|---------|---------|-------------|---------|
|
|
70
|
-
| `src/daemon/event-parser.ts` | 重构 | 20 | 使用 `normalizeTimestamp` |
|
|
71
|
-
| `src/daemon/handlers/stop.ts` | 重构 | 30 | 使用 `truncateSessionId` + `formatError` |
|
|
72
|
-
| `src/daemon/handlers/user-prompt.ts` | 重构 | 25 | 使用 `truncateSessionId` |
|
|
73
|
-
| `src/daemon/handlers/history-exporter.ts` | 重构 | 20 | 使用 `normalizeTimestamp` |
|
|
74
|
-
| `src/daemon/services/task-segmenter.ts` | 重构 | 30 | 使用 `normalizeTimestamp` |
|
|
75
|
-
| `src/claudemd/resume-manager.ts` | 重构 | 25 | 使用 `normalizeTimestamp` + `truncateSessionId` |
|
|
76
|
-
| `src/core/storage/events.ts` | 优化 | 40 | 预编译语句 + 批量插入 |
|
|
77
|
-
| `src/core/storage/sessions.ts` | 优化 | 30 | 预编译语句优化 |
|
|
78
|
-
| `src/core/storage/routing.ts` | 优化 | 35 | 预编译语句 + 索引优化 |
|
|
79
|
-
| `src/core/storage/tasks.ts` | 优化 | 25 | 预编译语句优化 |
|
|
80
|
-
| `src/core/storage/injections.ts` | 优化 | 20 | 预编译语句优化 |
|
|
81
|
-
| `src/core/storage/token-usage.ts` | 优化 | 20 | 预编译语句优化 |
|
|
82
|
-
| `src/core/storage/skills.ts` | 优化 | 30 | 预编译语句 + N+1 查询优化 |
|
|
83
|
-
| `src/core/storage/base.ts` | 优化 | 40 | WAL 模式优化 + 连接池配置 |
|
|
84
|
-
| `src/skills/invocation-guard.ts` | 增强 | 50 | 增加 TTL 机制 + 自动清理 |
|
|
85
|
-
| `src/daemon/router.ts` | 重构 | 15 | 使用 `formatError` |
|
|
86
|
-
| `src/daemon/server.ts` | 重构 | 20 | 使用 `formatError` |
|
|
87
|
-
| `src/web/server.ts` | 重构 | 15 | 使用 `formatError` |
|
|
88
|
-
|
|
89
|
-
### 2.3 重命名文件(0 个)
|
|
90
|
-
|
|
91
|
-
**说明**:文件命名风格混乱问题(P1-6)通过代码审查和新文件命名规范解决,不涉及现有文件重命名(避免 git 历史混乱)。
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## 3. 实施步骤
|
|
96
|
-
|
|
97
|
-
### Step 1: 抽取重复逻辑(3 天)
|
|
98
|
-
|
|
99
|
-
**目标**:消除时间戳、日志、ID 截断的重复代码。
|
|
100
|
-
|
|
101
|
-
#### 3.1.1 创建工具函数
|
|
102
|
-
|
|
103
|
-
**文件**: `src/core/utils/time.ts`
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
/**
|
|
107
|
-
* 时间戳归一化工具
|
|
108
|
-
*
|
|
109
|
-
* 统一处理 ISO 8601 时间戳的 Z 后缀问题,确保所有时间戳都带 Z。
|
|
110
|
-
*/
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* 归一化时间戳,确保带 Z 后缀
|
|
114
|
-
*/
|
|
115
|
-
export function normalizeTimestamp(timestamp: string): string {
|
|
116
|
-
if (!timestamp) return new Date().toISOString();
|
|
117
|
-
return timestamp.endsWith('Z') ? timestamp : timestamp + 'Z';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* 将时间戳转换为 Unix 毫秒数
|
|
122
|
-
*/
|
|
123
|
-
export function timestampToMs(timestamp: string): number {
|
|
124
|
-
return new Date(normalizeTimestamp(timestamp)).getTime();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* 计算两个时间戳之间的毫秒差
|
|
129
|
-
*/
|
|
130
|
-
export function timeDiff(start: string, end: string): number {
|
|
131
|
-
return timestampToMs(end) - timestampToMs(start);
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**文件**: `src/core/utils/session.ts`
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
/**
|
|
139
|
-
* Session ID 处理工具
|
|
140
|
-
*/
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* 截断 Session ID 到指定长度(用于日志显示)
|
|
144
|
-
*/
|
|
145
|
-
export function truncateSessionId(sessionId: string, length: number = 8): string {
|
|
146
|
-
if (!sessionId) return 'unknown';
|
|
147
|
-
return sessionId.slice(0, length);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* 验证 Session ID 格式(UUID v4)
|
|
152
|
-
*/
|
|
153
|
-
export function isValidSessionId(sessionId: string): boolean {
|
|
154
|
-
const uuidV4Regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
155
|
-
return uuidV4Regex.test(sessionId);
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
**文件**: `src/core/utils/format.ts`
|
|
160
|
-
|
|
161
|
-
```typescript
|
|
162
|
-
/**
|
|
163
|
-
* 通用格式化工具
|
|
164
|
-
*/
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* 格式化错误信息(用于日志)
|
|
168
|
-
*/
|
|
169
|
-
export function formatError(context: string, error: unknown): string {
|
|
170
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
171
|
-
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
172
|
-
return `${context}: ${errorMessage}${errorStack ? `\n${errorStack}` : ''}`;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* 格式化文件大小(字节 → 人类可读)
|
|
177
|
-
*/
|
|
178
|
-
export function formatFileSize(bytes: number): string {
|
|
179
|
-
if (bytes === 0) return '0 B';
|
|
180
|
-
const k = 1024;
|
|
181
|
-
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
182
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
183
|
-
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
|
|
184
|
-
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
#### 3.1.2 替换重复代码
|
|
188
|
-
|
|
189
|
-
**改动文件**:
|
|
190
|
-
- `src/daemon/event-parser.ts`:使用 `normalizeTimestamp`
|
|
191
|
-
- `src/daemon/handlers/stop.ts`:使用 `truncateSessionId` + `formatError`
|
|
192
|
-
- `src/daemon/handlers/user-prompt.ts`:使用 `truncateSessionId`
|
|
193
|
-
- `src/daemon/handlers/history-exporter.ts`:使用 `normalizeTimestamp`
|
|
194
|
-
- `src/daemon/services/task-segmenter.ts`:使用 `normalizeTimestamp`
|
|
195
|
-
- `src/claudemd/resume-manager.ts`:使用 `normalizeTimestamp` + `truncateSessionId`
|
|
196
|
-
|
|
197
|
-
**验证方法**:
|
|
198
|
-
1. 运行单元测试:`npx vitest run tests/unit/utils/`
|
|
199
|
-
2. 运行集成测试:`npx vitest run tests/integration/`
|
|
200
|
-
3. 手动测试:启动 daemon,触发各类事件,检查日志格式
|
|
201
|
-
|
|
202
|
-
**回滚方案**:
|
|
203
|
-
- Git revert 到 Step 1 开始前的 commit
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
### Step 2: 统一命名风格(2 天)
|
|
208
|
-
|
|
209
|
-
**目标**:统一文件命名和函数命名风格。
|
|
210
|
-
|
|
211
|
-
#### 3.2.1 文件命名规范
|
|
212
|
-
|
|
213
|
-
**规范**:
|
|
214
|
-
- 所有新文件使用 `kebab-case.ts`(如 `time-utils.ts`)
|
|
215
|
-
- 现有文件保持不变(避免 git 历史混乱)
|
|
216
|
-
- 在 `CLAUDE.md` 中明确规范
|
|
217
|
-
|
|
218
|
-
**改动**:
|
|
219
|
-
- 更新 `CLAUDE.md`,添加文件命名规范章节
|
|
220
|
-
|
|
221
|
-
#### 3.2.2 函数命名规范
|
|
222
|
-
|
|
223
|
-
**规范**:
|
|
224
|
-
- 查询单条记录:`get*`(如 `getSession`)
|
|
225
|
-
- 查询多条记录:`query*`(如 `querySessions`)
|
|
226
|
-
- 列出所有记录:`list*`(如 `listSkills`)
|
|
227
|
-
- 写入记录:`write*`(如 `writeEvent`)
|
|
228
|
-
- 更新记录:`update*`(如 `updateTask`)
|
|
229
|
-
|
|
230
|
-
**说明**:经过检查,现有函数命名已基本符合规范,无需大规模重命名。
|
|
231
|
-
|
|
232
|
-
**验证方法**:
|
|
233
|
-
1. 代码审查:检查所有新增函数是否符合规范
|
|
234
|
-
2. 文档审查:检查 `CLAUDE.md` 是否明确规范
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
### Step 3: 优化数据库查询(3 天)
|
|
239
|
-
|
|
240
|
-
**目标**:使用预编译语句,消除 N+1 查询,优化连接池。
|
|
241
|
-
|
|
242
|
-
#### 3.3.1 预编译语句优化
|
|
243
|
-
|
|
244
|
-
**改动示例**(`src/core/storage/events.ts`):
|
|
245
|
-
|
|
246
|
-
**Before**:
|
|
247
|
-
```typescript
|
|
248
|
-
const sql = `SELECT * FROM events ${where} ORDER BY timestamp DESC LIMIT ${limit} OFFSET ${offset}`;
|
|
249
|
-
const rows = this.db.prepare(sql).all(...params);
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
**After**:
|
|
253
|
-
```typescript
|
|
254
|
-
const sql = `SELECT * FROM events ${where} ORDER BY timestamp DESC LIMIT ? OFFSET ?`;
|
|
255
|
-
params.push(limit, offset);
|
|
256
|
-
const rows = this.db.prepare(sql).all(...params);
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
#### 3.3.2 连接池优化
|
|
260
|
-
|
|
261
|
-
**改动文件**:`src/core/storage/base.ts`
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
// Before
|
|
265
|
-
this.db.pragma('busy_timeout = 5000');
|
|
266
|
-
this.db.pragma('cache_size = -2000'); // 2MB
|
|
267
|
-
|
|
268
|
-
// After
|
|
269
|
-
this.db.pragma('busy_timeout = 10000'); // 增加到 10 秒
|
|
270
|
-
this.db.pragma('cache_size = -8000'); // 增加到 8MB
|
|
271
|
-
this.db.pragma('temp_store = MEMORY'); // 临时表使用内存
|
|
272
|
-
this.db.pragma('mmap_size = 30000000000'); // 启用 mmap(30GB)
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
**验证方法**:
|
|
276
|
-
1. 性能测试:并发写入 1000 条事件,测量延迟
|
|
277
|
-
2. 内存测试:监控 daemon 内存占用(应 <100MB)
|
|
278
|
-
|
|
279
|
-
---
|
|
280
|
-
|
|
281
|
-
### Step 4: 内存泄漏防护(1 天)
|
|
282
|
-
|
|
283
|
-
**目标**:为 `InvocationGuard` 增加 TTL 机制。
|
|
284
|
-
|
|
285
|
-
**改动文件**:`src/skills/invocation-guard.ts`
|
|
286
|
-
|
|
287
|
-
**改动方案**:
|
|
288
|
-
|
|
289
|
-
```typescript
|
|
290
|
-
export interface SessionInvocations {
|
|
291
|
-
total: number;
|
|
292
|
-
depth: number;
|
|
293
|
-
calledSkills: Set<string>;
|
|
294
|
-
lastAccessTime: number; // 新增:最后访问时间
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
export class InvocationGuard {
|
|
298
|
-
private sessions = new Map<string, SessionInvocations>();
|
|
299
|
-
private readonly TTL_MS = 30 * 60 * 1000; // 30 分钟
|
|
300
|
-
private cleanupInterval: NodeJS.Timeout | null = null;
|
|
301
|
-
|
|
302
|
-
constructor() {
|
|
303
|
-
// 启动定时清理任务(每 5 分钟)
|
|
304
|
-
this.cleanupInterval = setInterval(() => {
|
|
305
|
-
this.cleanupExpiredSessions();
|
|
306
|
-
}, 5 * 60 * 1000);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
private cleanupExpiredSessions(): void {
|
|
310
|
-
const now = Date.now();
|
|
311
|
-
const expired: string[] = [];
|
|
312
|
-
|
|
313
|
-
for (const [sessionId, session] of this.sessions.entries()) {
|
|
314
|
-
if (now - session.lastAccessTime > this.TTL_MS) {
|
|
315
|
-
expired.push(sessionId);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
for (const sessionId of expired) {
|
|
320
|
-
this.sessions.delete(sessionId);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
destroy(): void {
|
|
325
|
-
if (this.cleanupInterval) {
|
|
326
|
-
clearInterval(this.cleanupInterval);
|
|
327
|
-
this.cleanupInterval = null;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
**验证方法**:
|
|
334
|
-
1. 单元测试:模拟 30 分钟后清理过期 session
|
|
335
|
-
2. 内存测试:运行 daemon 24 小时,监控内存占用
|
|
336
|
-
|
|
337
|
-
---
|
|
338
|
-
|
|
339
|
-
### Step 5: 提升测试覆盖率(1 天)
|
|
340
|
-
|
|
341
|
-
**目标**:将测试覆盖率从 40% 提升至 60%。
|
|
342
|
-
|
|
343
|
-
**新增测试文件**:
|
|
344
|
-
- `tests/unit/utils/time.test.ts`(100 行)
|
|
345
|
-
- `tests/unit/utils/session.test.ts`(80 行)
|
|
346
|
-
- `tests/unit/utils/format.test.ts`(120 行)
|
|
347
|
-
- `tests/unit/skills/invocation-guard-ttl.test.ts`(150 行)
|
|
348
|
-
|
|
349
|
-
**验证方法**:
|
|
350
|
-
1. 运行覆盖率报告:`npx vitest run --coverage`
|
|
351
|
-
2. 确保覆盖率 ≥ 60%
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
## 4. 风险点
|
|
356
|
-
|
|
357
|
-
### 4.1 高风险改动
|
|
358
|
-
|
|
359
|
-
| 风险点 | 影响范围 | 降低措施 |
|
|
360
|
-
|-------|---------|---------|
|
|
361
|
-
| 数据库查询优化 | 所有存储操作 | 1. 保留原查询作为备份<br>2. 性能测试验证<br>3. 灰度发布 |
|
|
362
|
-
| InvocationGuard TTL | Skill 调用链路 | 1. TTL 设置为 30 分钟<br>2. 单元测试覆盖<br>3. 监控内存占用 |
|
|
363
|
-
| 时间戳归一化 | 所有时间相关逻辑 | 1. 单元测试覆盖<br>2. 集成测试验证<br>3. 保留原逻辑备份 |
|
|
364
|
-
|
|
365
|
-
---
|
|
366
|
-
|
|
367
|
-
## 5. 验收标准
|
|
368
|
-
|
|
369
|
-
### 5.1 功能验收
|
|
370
|
-
|
|
371
|
-
- ✅ 所有现有功能正常
|
|
372
|
-
- ✅ daemon 启动正常
|
|
373
|
-
- ✅ Web 仪表盘正常访问
|
|
374
|
-
- ✅ CLI 命令正常执行
|
|
375
|
-
|
|
376
|
-
### 5.2 性能验收
|
|
377
|
-
|
|
378
|
-
- ✅ 数据库查询性能提升(对比修改前后)
|
|
379
|
-
- ✅ 内存占用稳定(<100MB)
|
|
380
|
-
- ✅ N+1 查询消除
|
|
381
|
-
|
|
382
|
-
### 5.3 测试验收
|
|
383
|
-
|
|
384
|
-
- ✅ 单元测试覆盖率 ≥ 60%
|
|
385
|
-
- ✅ 所有测试通过
|
|
386
|
-
- ✅ 代码重复率 <8%
|
|
387
|
-
|
|
388
|
-
---
|
|
389
|
-
|
|
390
|
-
## 6. 时间估算
|
|
391
|
-
|
|
392
|
-
| 步骤 | 工作量(天) | 依赖 |
|
|
393
|
-
|---|---|---|
|
|
394
|
-
| Step 1: 抽取重复逻辑 | 3 | 无 |
|
|
395
|
-
| Step 2: 统一命名风格 | 2 | 无 |
|
|
396
|
-
| Step 3: 优化数据库查询 | 3 | 无 |
|
|
397
|
-
| Step 4: 内存泄漏防护 | 1 | 无 |
|
|
398
|
-
| Step 5: 提升测试覆盖率 | 1 | Step 1-4 完成后 |
|
|
399
|
-
| **总计** | **10 天** | - |
|
|
400
|
-
|
|
401
|
-
**总工作量**:10 天(2 周)
|
|
402
|
-
|
|
403
|
-
---
|
|
404
|
-
|
|
405
|
-
## 7. 里程碑
|
|
406
|
-
|
|
407
|
-
| 日期 | 里程碑 | 交付物 |
|
|
408
|
-
|---|---|---|
|
|
409
|
-
| 2026-05-20 | 重复逻辑抽取完成 | 3 个工具模块 + 测试 |
|
|
410
|
-
| 2026-05-22 | 命名风格统一完成 | 更新 CLAUDE.md |
|
|
411
|
-
| 2026-05-27 | 数据库优化完成 | 性能测试报告 |
|
|
412
|
-
| 2026-05-28 | 内存泄漏防护完成 | TTL 机制 + 测试 |
|
|
413
|
-
| 2026-05-29 | 第 2 迭代验收 | 覆盖率 ≥ 60% |
|
|
414
|
-
|
|
415
|
-
---
|
|
416
|
-
|
|
417
|
-
## 8. 下一步
|
|
418
|
-
|
|
419
|
-
**Phase 2.5: User Review**
|
|
420
|
-
|
|
421
|
-
请 review 本方案后回复:
|
|
422
|
-
- **"批准"** / **"approve"** → spawn coder 开始实施
|
|
423
|
-
- **"修改 [意见]"** → 调整 spec
|
|
424
|
-
- **"取消"** → 停止任务
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# task active GC 修复 Spec
|
|
2
|
-
|
|
3
|
-
## 目标
|
|
4
|
-
|
|
5
|
-
通过周期 GC + completeCurrentTask recover fallback,消除因 ESC 中断、Stop hook 未触发、daemon 重启等场景导致的 task 永久滞留 `active` 状态。
|
|
6
|
-
|
|
7
|
-
## Bug 复现路径
|
|
8
|
-
|
|
9
|
-
| 场景 | 触发条件 | 为何漏掉 |
|
|
10
|
-
|------|---------|---------|
|
|
11
|
-
| A | 用户 ESC 中断 Claude Code,Stop hook 不触发 | completeCurrentTask 永远不被调用 |
|
|
12
|
-
| B | daemon 重启后用户 ESC,Stop hook 触发但 `currentTasks` Map 为空 | completeCurrentTask 第 78 行:`const current = this.currentTasks.get(sessionId)` — Map 空直接 return |
|
|
13
|
-
| C | 用户切到别的 session 后永不再 prompt 旧 session | shouldStartNewTask 从不被触发,task 无人收尾 |
|
|
14
|
-
|
|
15
|
-
## 方案对比
|
|
16
|
-
|
|
17
|
-
| 方案 | 修复场景 | 改动文件数 | 风险 |
|
|
18
|
-
|------|---------|-----------|------|
|
|
19
|
-
| A:周期 GC | A / C(idle 超阈值后兜底) | 3 | idle 阈值设太短可能误杀长任务 |
|
|
20
|
-
| B:completeCurrentTask recover fallback | B | 1 | 仅修场景 B,A/C 仍漏 |
|
|
21
|
-
| C:A + B 组合 | A / B / C 全覆盖 | 3 | 最全面,改动仍可控 |
|
|
22
|
-
| D:新增 `auto_closed` 状态 | A / B / C + UI 语义区分 | 5+ | 改动大,可作后续优化 |
|
|
23
|
-
|
|
24
|
-
**推荐:方案 C**。
|
|
25
|
-
|
|
26
|
-
## 详细设计
|
|
27
|
-
|
|
28
|
-
### 1. storage 新方法:`completeStaleActiveTasks`
|
|
29
|
-
|
|
30
|
-
**位置**:`src/core/storage/tasks.ts`(TaskOperations 类内)
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
/**
|
|
34
|
-
* 将 idle 超过阈值的 active task 批量转为 completed。
|
|
35
|
-
* 条件:status='active' AND end_time IS NOT NULL
|
|
36
|
-
* AND (now - end_time) > idleMinutes 分钟。
|
|
37
|
-
* 返回:受影响行数。
|
|
38
|
-
*/
|
|
39
|
-
completeStaleActiveTasks(idleMinutes: number): number {
|
|
40
|
-
const result = this.db.prepare(`
|
|
41
|
-
UPDATE tasks
|
|
42
|
-
SET status = 'completed'
|
|
43
|
-
WHERE status = 'active'
|
|
44
|
-
AND end_time IS NOT NULL
|
|
45
|
-
AND (julianday('now') - julianday(end_time)) * 24 * 60 > ?
|
|
46
|
-
`).run(idleMinutes);
|
|
47
|
-
return result.changes;
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
同步在 `SQLiteStorage` facade(`sqlite.ts`)暴露同名代理方法。
|
|
52
|
-
|
|
53
|
-
注意:`end_time` 由 `linkEventToTask` 持续更新,作为 idle 判定基准合理。没有 `end_time` 的 task(从未 link 过事件)不纳入 GC,避免误杀刚创建的 task。
|
|
54
|
-
|
|
55
|
-
### 2. TaskSegmenter.completeCurrentTask 加 recover fallback
|
|
56
|
-
|
|
57
|
-
**位置**:`src/daemon/services/task-segmenter.ts:77`
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
completeCurrentTask(sessionId: string, timestamp: string): void {
|
|
61
|
-
const current = this.currentTasks.get(sessionId) ?? this.recoverActiveTask(sessionId);
|
|
62
|
-
if (!current) return;
|
|
63
|
-
...
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
一行改动,与 `processPrompt` / `linkEvent` 模式一致。
|
|
68
|
-
|
|
69
|
-
### 3. maintenanceInterval 加 GC 调度
|
|
70
|
-
|
|
71
|
-
**位置**:`src/daemon/index.ts:105-116`
|
|
72
|
-
|
|
73
|
-
现有 `maintenanceInterval` 是 **24 小时**,仅清理旧 events。需新增独立的**短周期 GC interval**:
|
|
74
|
-
|
|
75
|
-
```ts
|
|
76
|
-
// ── 5.6. Stale task GC (every 5 minutes) ──────────────────────────
|
|
77
|
-
const STALE_TASK_GC_INTERVAL = 5 * 60 * 1000; // 5 分钟
|
|
78
|
-
const STALE_TASK_IDLE_MINUTES = 10; // idle 超 10 分钟视为滞留
|
|
79
|
-
|
|
80
|
-
const staleTaskGcInterval = setInterval(() => {
|
|
81
|
-
try {
|
|
82
|
-
const closed = storage.completeStaleActiveTasks(STALE_TASK_IDLE_MINUTES);
|
|
83
|
-
if (closed > 0) {
|
|
84
|
-
logger.info(`[Maintenance] Auto-completed ${closed} stale active task(s)`);
|
|
85
|
-
}
|
|
86
|
-
} catch (err) {
|
|
87
|
-
logger.error(`[Maintenance] Stale task GC failed: ${err}`);
|
|
88
|
-
}
|
|
89
|
-
}, STALE_TASK_GC_INTERVAL);
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
关闭时需调用 `clearInterval(staleTaskGcInterval)`(在现有 graceful shutdown 段追加)。
|
|
93
|
-
|
|
94
|
-
## 改造范围
|
|
95
|
-
|
|
96
|
-
| 文件 | 改动内容 | 估算行数 |
|
|
97
|
-
|------|---------|---------|
|
|
98
|
-
| `src/core/storage/tasks.ts` | 新增 `completeStaleActiveTasks` 方法 | +12 |
|
|
99
|
-
| `src/core/storage/sqlite.ts` | facade 代理方法 | +3 |
|
|
100
|
-
| `src/daemon/services/task-segmenter.ts` | completeCurrentTask recover fallback(1 行) | +1 |
|
|
101
|
-
| `src/daemon/index.ts` | 新增 GC interval + clearInterval | +12 |
|
|
102
|
-
|
|
103
|
-
共 4 文件,约 28 行净增。
|
|
104
|
-
|
|
105
|
-
## 配置
|
|
106
|
-
|
|
107
|
-
| 参数 | 值 | 说明 |
|
|
108
|
-
|------|----|------|
|
|
109
|
-
| `STALE_TASK_IDLE_MINUTES` | 10 | idle 超 10 分钟视为放弃,不可配置(硬编码常量) |
|
|
110
|
-
| `STALE_TASK_GC_INTERVAL` | 5 分钟 | GC 轮询间隔,独立于 24h 维护周期 |
|
|
111
|
-
|
|
112
|
-
如未来需要可迁移到 `config.yaml` 的 `tasks.stale_gc_minutes` 字段。
|
|
113
|
-
|
|
114
|
-
## 测试策略
|
|
115
|
-
|
|
116
|
-
| 测试类型 | 测试用例 | 文件位置 |
|
|
117
|
-
|---------|---------|---------|
|
|
118
|
-
| 单测:`completeStaleActiveTasks` | 空表返回 0 | 新增 `tests/unit/storage/tasks-stale-gc.test.ts` |
|
|
119
|
-
| | 1 idle 超阈值 + 1 未超:只关超的 | 同上 |
|
|
120
|
-
| | `status='completed'` 的 task 不被改动 | 同上 |
|
|
121
|
-
| | `end_time IS NULL` 的 task 不被纳入 | 同上 |
|
|
122
|
-
| 单测:recover fallback | Map 为空时仍能 complete DB 中 active task | 扩展现有 task-segmenter 测试 |
|
|
123
|
-
|
|
124
|
-
## 风险与回滚
|
|
125
|
-
|
|
126
|
-
| 风险 | 概率 | 缓解措施 |
|
|
127
|
-
|------|------|---------|
|
|
128
|
-
| 误杀正在进行的长任务 | 低(idle 阈值 10 分钟,linkEvent 持续刷新 end_time) | 阈值可调大;日志可审计 |
|
|
129
|
-
| 旧库一次性批量 GC | 必然发生,且是预期行为 | 无需回滚,这正是修 bug 的目的 |
|
|
130
|
-
| GC interval 异常退出 | 极低(try-catch 包裹) | 日志记录,不影响主流程 |
|
|
131
|
-
|
|
132
|
-
**回滚**:删除 daemon/index.ts 中的 `staleTaskGcInterval` 代码块即可完全禁用 GC,其他改动无副作用。
|
|
133
|
-
|
|
134
|
-
## 实施顺序
|
|
135
|
-
|
|
136
|
-
1. `tasks.ts` — 新增 `completeStaleActiveTasks` + 单测
|
|
137
|
-
2. `sqlite.ts` — facade 代理方法
|
|
138
|
-
3. `task-segmenter.ts` — recover fallback 单行 + 单测
|
|
139
|
-
4. `daemon/index.ts` — GC interval 注册 + clearInterval
|
|
140
|
-
5. 全量测试 `npm test`
|
|
141
|
-
|
|
142
|
-
## 命名遵循
|
|
143
|
-
|
|
144
|
-
- `completeStaleActiveTasks`:`complete` 前缀(语义清晰,优于 `write`)
|
|
145
|
-
- `STALE_TASK_GC_INTERVAL` / `STALE_TASK_IDLE_MINUTES`:全大写常量
|
|
146
|
-
- `staleTaskGcInterval`:camelCase 变量,与 `maintenanceInterval` 风格一致
|