sillyspec 3.27.2 → 3.27.6
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/.claude/skills/sillyspec-execute/SKILL.md +8 -0
- package/.claude/skills/sillyspec-quick/SKILL.md +2 -1
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +87 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +93 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +67 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +47 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +214 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +102 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +57 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +177 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +156 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +116 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +70 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +79 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +64 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +54 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +87 -0
- package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
- package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +2 -0
- package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +20 -0
- package/.claude/worktrees/sillyspec-data-model-research/README.md +203 -0
- package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +91 -0
- package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +2 -0
- package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
- package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +977 -0
- package/.claude/worktrees/sillyspec-data-model-research/package.json +39 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +16 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +836 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +256 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +25 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +95 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +679 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +526 -0
- package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +357 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +803 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +290 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +270 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +65 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +109 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +202 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +88 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +328 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +97 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +480 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +20 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +55 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/db.js +381 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +517 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +155 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +245 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +246 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +121 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +825 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +393 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +107 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +1099 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +420 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +78 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +73 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +150 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +130 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +892 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/index.js +2798 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/init.js +626 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +231 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +128 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +104 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +543 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +127 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +166 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +222 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +580 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +336 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +355 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +36 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +594 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +265 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +1304 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +115 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +852 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +77 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +1595 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +1552 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +1259 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +156 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +1084 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +208 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +128 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +843 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +186 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +269 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +1562 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +584 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/run.js +23 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +388 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +512 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +95 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +414 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +597 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +62 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +50 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +358 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +171 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +550 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +889 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +597 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +199 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +236 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +617 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +145 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +540 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +1275 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +43 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +29 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +514 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +1344 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +650 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +167 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +608 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +64 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +246 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +1470 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +1498 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +210 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +1718 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +277 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/version.js +19 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +600 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +125 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +1446 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +576 -0
- package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +1715 -0
- package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +23 -0
- package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +28 -0
- package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +12 -0
- package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +32 -0
- package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +79 -0
- package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +132 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +87 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +93 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +67 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +47 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +214 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +102 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +57 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +177 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +156 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +87 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +116 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +70 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +79 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +64 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +54 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +87 -0
- package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
- package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +6 -0
- package/.worktrees/8d2d0392/.gitattributes +2 -0
- package/.worktrees/8d2d0392/.husky/pre-push +20 -0
- package/.worktrees/8d2d0392/README.md +203 -0
- package/.worktrees/8d2d0392/SKILL.md +91 -0
- package/.worktrees/8d2d0392/architecture-analysis.md +448 -0
- package/.worktrees/8d2d0392/bin/sillyspec.js +2 -0
- package/.worktrees/8d2d0392/eval/README.md +86 -0
- package/.worktrees/8d2d0392/eval/eval.config.json +28 -0
- package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +63 -0
- package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +27 -0
- package/.worktrees/8d2d0392/eval/lib/config.mjs +82 -0
- package/.worktrees/8d2d0392/eval/lib/db.mjs +76 -0
- package/.worktrees/8d2d0392/eval/lib/report.mjs +120 -0
- package/.worktrees/8d2d0392/eval/lib/runner.mjs +157 -0
- package/.worktrees/8d2d0392/eval/lib/tasks.mjs +73 -0
- package/.worktrees/8d2d0392/eval/lib/util.mjs +107 -0
- package/.worktrees/8d2d0392/eval/lib/workdir.mjs +30 -0
- package/.worktrees/8d2d0392/eval/run.mjs +83 -0
- package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +6 -0
- package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
- package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +6 -0
- package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +28 -0
- package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +6 -0
- package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
- package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
- package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +6 -0
- package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +31 -0
- package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +5 -0
- package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +6 -0
- package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
- package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +6 -0
- package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +38 -0
- package/.worktrees/8d2d0392/logo.jpg +0 -0
- package/.worktrees/8d2d0392/package-lock.json +977 -0
- package/.worktrees/8d2d0392/package.json +41 -0
- package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
- package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
- package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
- package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +16 -0
- package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
- package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +836 -0
- package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +256 -0
- package/.worktrees/8d2d0392/packages/dashboard/package.json +25 -0
- package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +95 -0
- package/.worktrees/8d2d0392/packages/dashboard/server/index.js +679 -0
- package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +526 -0
- package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +357 -0
- package/.worktrees/8d2d0392/src/agent-session-log.js +803 -0
- package/.worktrees/8d2d0392/src/change-list.js +290 -0
- package/.worktrees/8d2d0392/src/change-risk-profile.js +339 -0
- package/.worktrees/8d2d0392/src/check-primitives.js +65 -0
- package/.worktrees/8d2d0392/src/classify-change.js +109 -0
- package/.worktrees/8d2d0392/src/commit-suggest.js +202 -0
- package/.worktrees/8d2d0392/src/config-cat.js +88 -0
- package/.worktrees/8d2d0392/src/config-schema.js +328 -0
- package/.worktrees/8d2d0392/src/constants.js +97 -0
- package/.worktrees/8d2d0392/src/contract-matrix.js +533 -0
- package/.worktrees/8d2d0392/src/datetime.js +20 -0
- package/.worktrees/8d2d0392/src/db-engine.js +55 -0
- package/.worktrees/8d2d0392/src/db.js +381 -0
- package/.worktrees/8d2d0392/src/decision-distill.js +517 -0
- package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +155 -0
- package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +245 -0
- package/.worktrees/8d2d0392/src/dispatch/probe.js +246 -0
- package/.worktrees/8d2d0392/src/dispatch/strategy.js +121 -0
- package/.worktrees/8d2d0392/src/docs-check.js +825 -0
- package/.worktrees/8d2d0392/src/docs-debt.js +393 -0
- package/.worktrees/8d2d0392/src/docs-gate.js +107 -0
- package/.worktrees/8d2d0392/src/doctor-diagnostics.js +1099 -0
- package/.worktrees/8d2d0392/src/endpoint-extractor.js +409 -0
- package/.worktrees/8d2d0392/src/foreign-declared.js +78 -0
- package/.worktrees/8d2d0392/src/fs-atomic.js +73 -0
- package/.worktrees/8d2d0392/src/git-helper.js +150 -0
- package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +130 -0
- package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +892 -0
- package/.worktrees/8d2d0392/src/index.js +2854 -0
- package/.worktrees/8d2d0392/src/init.js +626 -0
- package/.worktrees/8d2d0392/src/knowledge-match.js +231 -0
- package/.worktrees/8d2d0392/src/local-detect.js +128 -0
- package/.worktrees/8d2d0392/src/local-register.js +104 -0
- package/.worktrees/8d2d0392/src/machine-interface.js +543 -0
- package/.worktrees/8d2d0392/src/migrate.js +127 -0
- package/.worktrees/8d2d0392/src/module-impact.js +166 -0
- package/.worktrees/8d2d0392/src/module-resolve.js +222 -0
- package/.worktrees/8d2d0392/src/modules.js +580 -0
- package/.worktrees/8d2d0392/src/plan-adopt-waves.js +126 -0
- package/.worktrees/8d2d0392/src/progress/change-registry.js +336 -0
- package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +355 -0
- package/.worktrees/8d2d0392/src/progress/shared.js +36 -0
- package/.worktrees/8d2d0392/src/progress/stage-machine.js +594 -0
- package/.worktrees/8d2d0392/src/progress/step-store.js +265 -0
- package/.worktrees/8d2d0392/src/progress.js +1304 -0
- package/.worktrees/8d2d0392/src/quick-recommend.js +115 -0
- package/.worktrees/8d2d0392/src/quicklog.js +883 -0
- package/.worktrees/8d2d0392/src/review-tier.js +77 -0
- package/.worktrees/8d2d0392/src/run/command.js +1641 -0
- package/.worktrees/8d2d0392/src/run/complete-handlers.js +1552 -0
- package/.worktrees/8d2d0392/src/run/complete.js +1259 -0
- package/.worktrees/8d2d0392/src/run/concurrent-detect.js +156 -0
- package/.worktrees/8d2d0392/src/run/gates.js +1094 -0
- package/.worktrees/8d2d0392/src/run/multi-repo-context.js +208 -0
- package/.worktrees/8d2d0392/src/run/next.js +128 -0
- package/.worktrees/8d2d0392/src/run/prompt.js +843 -0
- package/.worktrees/8d2d0392/src/run/quick-audit.js +186 -0
- package/.worktrees/8d2d0392/src/run/scan-profile.js +269 -0
- package/.worktrees/8d2d0392/src/run/shared.js +1562 -0
- package/.worktrees/8d2d0392/src/run/stage.js +587 -0
- package/.worktrees/8d2d0392/src/run.js +23 -0
- package/.worktrees/8d2d0392/src/scan-diff.js +388 -0
- package/.worktrees/8d2d0392/src/scan-postcheck.js +524 -0
- package/.worktrees/8d2d0392/src/scan-staleness.js +95 -0
- package/.worktrees/8d2d0392/src/setup.js +414 -0
- package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +597 -0
- package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +62 -0
- package/.worktrees/8d2d0392/src/spec-dir-typo.js +50 -0
- package/.worktrees/8d2d0392/src/spec-sync.js +358 -0
- package/.worktrees/8d2d0392/src/stage-contract-engine.js +171 -0
- package/.worktrees/8d2d0392/src/stage-contract-spec.js +551 -0
- package/.worktrees/8d2d0392/src/stage-contract.js +948 -0
- package/.worktrees/8d2d0392/src/stage-review.js +597 -0
- package/.worktrees/8d2d0392/src/stages/archive.js +199 -0
- package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +285 -0
- package/.worktrees/8d2d0392/src/stages/brainstorm.js +624 -0
- package/.worktrees/8d2d0392/src/stages/cmd-existence.js +145 -0
- package/.worktrees/8d2d0392/src/stages/doctor.js +540 -0
- package/.worktrees/8d2d0392/src/stages/execute.js +1277 -0
- package/.worktrees/8d2d0392/src/stages/explore.js +43 -0
- package/.worktrees/8d2d0392/src/stages/index.js +29 -0
- package/.worktrees/8d2d0392/src/stages/knowledge.js +514 -0
- package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +1398 -0
- package/.worktrees/8d2d0392/src/stages/plan.js +651 -0
- package/.worktrees/8d2d0392/src/stages/quick.js +167 -0
- package/.worktrees/8d2d0392/src/stages/scan.js +608 -0
- package/.worktrees/8d2d0392/src/stages/status.js +64 -0
- package/.worktrees/8d2d0392/src/stages/verify.js +246 -0
- package/.worktrees/8d2d0392/src/sync.js +1470 -0
- package/.worktrees/8d2d0392/src/task-review.js +1498 -0
- package/.worktrees/8d2d0392/src/taskcard-placeholders.js +21 -0
- package/.worktrees/8d2d0392/src/taskcard.js +217 -0
- package/.worktrees/8d2d0392/src/verify-postcheck.js +1718 -0
- package/.worktrees/8d2d0392/src/verify-probes.js +327 -0
- package/.worktrees/8d2d0392/src/version.js +19 -0
- package/.worktrees/8d2d0392/src/workflow.js +600 -0
- package/.worktrees/8d2d0392/src/workspace.js +125 -0
- package/.worktrees/8d2d0392/src/worktree-apply.js +1611 -0
- package/.worktrees/8d2d0392/src/worktree-deps.js +576 -0
- package/.worktrees/8d2d0392/src/worktree.js +1838 -0
- package/.worktrees/8d2d0392/templates/claude-instruction.md +23 -0
- package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +29 -0
- package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +12 -0
- package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +32 -0
- package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +79 -0
- package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +132 -0
- package/architecture-analysis.md +448 -0
- package/eval/README.md +86 -0
- package/eval/eval.config.json +28 -0
- package/eval/lib/adapters/cli.mjs +63 -0
- package/eval/lib/adapters/dryrun.mjs +27 -0
- package/eval/lib/config.mjs +82 -0
- package/eval/lib/db.mjs +76 -0
- package/eval/lib/report.mjs +120 -0
- package/eval/lib/runner.mjs +157 -0
- package/eval/lib/tasks.mjs +73 -0
- package/eval/lib/util.mjs +107 -0
- package/eval/lib/workdir.mjs +30 -0
- package/eval/run.mjs +83 -0
- package/eval/tasks/001-slugify/files/package.json +6 -0
- package/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
- package/eval/tasks/001-slugify/task.json +6 -0
- package/eval/tasks/001-slugify/verify.mjs +28 -0
- package/eval/tasks/002-each-day/files/package.json +6 -0
- package/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
- package/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
- package/eval/tasks/002-each-day/task.json +6 -0
- package/eval/tasks/002-each-day/verify.mjs +31 -0
- package/eval/tasks/003-word-report/files/data/notes.txt +5 -0
- package/eval/tasks/003-word-report/files/package.json +6 -0
- package/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
- package/eval/tasks/003-word-report/task.json +6 -0
- package/eval/tasks/003-word-report/verify.mjs +38 -0
- package/package.json +4 -2
- package/src/agent-session-log.js +45 -5
- package/src/change-risk-profile.js +83 -14
- package/src/config-schema.js +18 -3
- package/src/contract-matrix.js +90 -29
- package/src/datetime.js +20 -0
- package/src/decision-distill.js +517 -0
- package/src/dispatch/backends/local-agent.js +4 -4
- package/src/docs-check.js +227 -0
- package/src/docs-debt.js +187 -24
- package/src/doctor-diagnostics.js +102 -2
- package/src/endpoint-extractor.js +41 -52
- package/src/foreign-declared.js +155 -0
- package/src/index.js +95 -13
- package/src/init.js +9 -7
- package/src/knowledge-match.js +107 -6
- package/src/local-register.js +7 -1
- package/src/module-resolve.js +12 -1
- package/src/modules.js +2 -1
- package/src/plan-adopt-waves.js +126 -0
- package/src/quicklog.js +50 -4
- package/src/run/command.js +124 -44
- package/src/run/complete-handlers.js +48 -19
- package/src/run/complete.js +5 -2
- package/src/run/gates.js +104 -22
- package/src/run/prompt.js +84 -42
- package/src/run/quick-audit.js +11 -0
- package/src/run/shared.js +152 -10
- package/src/run/stage.js +8 -5
- package/src/run.js +2 -2
- package/src/scan-postcheck.js +30 -17
- package/src/stage-contract-spec.js +3 -2
- package/src/stage-contract.js +68 -4
- package/src/stages/archive.js +53 -12
- package/src/stages/brainstorm-auto.js +50 -1
- package/src/stages/brainstorm.js +13 -0
- package/src/stages/doctor.js +157 -1
- package/src/stages/execute.js +32 -6
- package/src/stages/plan-postcheck.js +76 -17
- package/src/stages/plan.js +9 -4
- package/src/stages/quick.js +6 -1
- package/src/stages/verify.js +32 -15
- package/src/sync.js +41 -3
- package/src/task-review.js +2 -2
- package/src/taskcard-placeholders.js +21 -0
- package/src/taskcard.js +43 -1
- package/src/verify-postcheck.js +315 -13
- package/src/verify-probes.js +73 -10
- package/src/worktree-apply.js +569 -227
- package/src/worktree-deps.js +150 -1
- package/src/worktree.js +285 -77
- package/templates/prompts/taskcard-rules.md +2 -1
|
@@ -13,6 +13,17 @@ import { execSync } from 'child_process'
|
|
|
13
13
|
|
|
14
14
|
// ─── Provider: 扫描后端 router 注册的端点 ───────────────────────────────
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* matchIndex → 装饰器/路由起始行号(全文匹配配套;1-based)。
|
|
18
|
+
* 坑 endpoint-multiline-decorator-miss(2026-08-24 用户实证):三框架提取器原为逐行匹配,
|
|
19
|
+
* 多行装饰器(`@router.get(\n "/path",\n response_model=…)` 等)路径不在装饰器行 → 端点
|
|
20
|
+
* 静默漏 → endpoints.json artifact 与 live 扫描双失真 → probe5 missingBackend 误报(11 个
|
|
21
|
+
* 存量端点)。装饰器匹配改为全文正则(`\s*` 天然跨换行),行号取起始行。
|
|
22
|
+
*/
|
|
23
|
+
function lineOfIndex(content, index) {
|
|
24
|
+
return content.slice(0, index).split('\n').length
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
/**
|
|
17
28
|
* 从单个文件提取 FastAPI router 端点
|
|
18
29
|
* 支持 APIRouter(prefix=...) 和 @router.get/post/put/delete/patch("/path")
|
|
@@ -25,7 +36,7 @@ export function extractFastApiEndpoints(filePath) {
|
|
|
25
36
|
const lines = content.split('\n')
|
|
26
37
|
const endpoints = []
|
|
27
38
|
|
|
28
|
-
// 1. 提取 router prefix
|
|
39
|
+
// 1. 提取 router prefix(逐行,同文件近似——维持原行为)
|
|
29
40
|
let routerPrefix = ''
|
|
30
41
|
for (const line of lines) {
|
|
31
42
|
const prefixMatch = line.match(/(?:APIRouter|router)\s*\(\s*(?:prefix\s*=\s*)?["'`]([^"'`]+)["'`]/)
|
|
@@ -35,40 +46,17 @@ export function extractFastApiEndpoints(filePath) {
|
|
|
35
46
|
}
|
|
36
47
|
}
|
|
37
48
|
|
|
38
|
-
// 2.
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const rawPath = decoratorMatch[2]
|
|
50
|
-
endpoints.push({
|
|
51
|
-
method,
|
|
52
|
-
path: routerPrefix + rawPath,
|
|
53
|
-
source: filePath,
|
|
54
|
-
line: i + 1,
|
|
55
|
-
})
|
|
56
|
-
continue
|
|
57
|
-
}
|
|
58
|
-
// 分散式: @router.get\n ("/path",
|
|
59
|
-
const splitMatch = line.match(/@(?:router|api_router)\.(get|post|put|delete|patch)\s*$/)
|
|
60
|
-
if (splitMatch && i + 1 < lines.length) {
|
|
61
|
-
const nextLine = lines[i + 1]
|
|
62
|
-
const pathMatch = nextLine.match(/\(\s*["'`]([^"'`]+)["'`]/)
|
|
63
|
-
if (pathMatch) {
|
|
64
|
-
endpoints.push({
|
|
65
|
-
method: splitMatch[1].toUpperCase(),
|
|
66
|
-
path: routerPrefix + pathMatch[1],
|
|
67
|
-
source: filePath,
|
|
68
|
-
line: i + 1,
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
}
|
|
49
|
+
// 2. 装饰器全文匹配:单行 `@router.get("/path")`、分散式 `@router.get\n("/path")`、
|
|
50
|
+
// 多行参数 `@router.get(\n "/path",\n response_model=…)` 三态合一(\s* 跨换行)
|
|
51
|
+
const decoratorRe = /@(?:router|api_router)\.(get|post|put|delete|patch)\s*\(\s*["'`]([^"'`]+)["'`]/g
|
|
52
|
+
let m
|
|
53
|
+
while ((m = decoratorRe.exec(content)) !== null) {
|
|
54
|
+
endpoints.push({
|
|
55
|
+
method: m[1].toUpperCase(),
|
|
56
|
+
path: routerPrefix + m[2],
|
|
57
|
+
source: filePath,
|
|
58
|
+
line: lineOfIndex(content, m.index),
|
|
59
|
+
})
|
|
72
60
|
}
|
|
73
61
|
|
|
74
62
|
return endpoints
|
|
@@ -94,16 +82,18 @@ export function extractExpressEndpoints(filePath) {
|
|
|
94
82
|
if (useMatch) routerPrefix = useMatch[1]
|
|
95
83
|
}
|
|
96
84
|
|
|
85
|
+
// 路由全文匹配(坑 endpoint-multiline-decorator-miss:`router.get(\n "/path",\n handler)` 同病)
|
|
86
|
+
const routeRe = /\b(?:app|router)\.(get|post|put|delete|patch)\s*\(\s*["'`]([^"'`]+)["'`]/gi
|
|
87
|
+
let m
|
|
88
|
+
while ((m = routeRe.exec(content)) !== null) {
|
|
89
|
+
endpoints.push({ method: m[1].toUpperCase(), path: routerPrefix + m[2], source: filePath, line: lineOfIndex(content, m.index) })
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 链式 .route(path).get(h).put(h) —— 同行所有 method 配上 path(跨行链式不扩面,维持逐行)
|
|
97
93
|
for (let i = 0; i < lines.length; i++) {
|
|
98
94
|
const line = lines[i]
|
|
99
|
-
const m = line.match(/\b(?:app|router)\.(get|post|put|delete|patch)\s*\(\s*["'`]([^"'`]+)["'`]/i)
|
|
100
|
-
if (m) {
|
|
101
|
-
endpoints.push({ method: m[1].toUpperCase(), path: routerPrefix + m[2], source: filePath, line: i + 1 })
|
|
102
|
-
continue
|
|
103
|
-
}
|
|
104
95
|
const routeChain = line.match(/\.route\s*\(\s*["'`]([^"'`]+)["'`]/)
|
|
105
96
|
if (routeChain) {
|
|
106
|
-
// 链式 .route(path).get(h).put(h) —— 同行所有 method 配上 path
|
|
107
97
|
const chainPath = routerPrefix + routeChain[1]
|
|
108
98
|
for (const mm of line.matchAll(/\.(get|post|put|delete|patch)\s*\(/gi)) {
|
|
109
99
|
endpoints.push({ method: mm[1].toUpperCase(), path: chainPath, source: filePath, line: i + 1 })
|
|
@@ -135,17 +125,16 @@ export function extractSpringEndpoints(filePath) {
|
|
|
135
125
|
|
|
136
126
|
const methodMap = { get: 'GET', post: 'POST', put: 'PUT', delete: 'DELETE', patch: 'PATCH' }
|
|
137
127
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
128
|
+
// 短形式全文匹配(坑 endpoint-multiline-decorator-miss:`@GetMapping(\n "/path"\n)` 同病)
|
|
129
|
+
const shortRe = /@(Get|Post|Put|Delete|Patch)Mapping\s*\(\s*(?:value\s*=\s*)?["'`]([^"'`]+)["'`]/gi
|
|
130
|
+
let m
|
|
131
|
+
while ((m = shortRe.exec(content)) !== null) {
|
|
132
|
+
endpoints.push({ method: methodMap[m[1].toLowerCase()], path: classPrefix + m[2], source: filePath, line: lineOfIndex(content, m.index) })
|
|
133
|
+
}
|
|
134
|
+
// 旧形式全文匹配([^)]*? 字符类可跨行,`@RequestMapping(\n value="/p",\n method=…)` 随全文化一并覆盖)
|
|
135
|
+
const oldRe = /@RequestMapping\s*\(\s*(?:value\s*=\s*)?["'`]([^"'`]+)["'`][^)]*?method\s*=\s*RequestMethod\.(\w+)/gi
|
|
136
|
+
while ((m = oldRe.exec(content)) !== null) {
|
|
137
|
+
endpoints.push({ method: m[2].toUpperCase(), path: classPrefix + m[1], source: filePath, line: lineOfIndex(content, m.index) })
|
|
149
138
|
}
|
|
150
139
|
|
|
151
140
|
return endpoints
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 他者会话显式声明文件集(坑 verify-reconcile-foreign-wip,2026-08-23 实证:verify 实测
|
|
3
|
+
* 对账在主仓共享工作区取 git diff,无 meta 回退时把并行会话在途 WIP 全量算进本变更——误
|
|
4
|
+
* 命中他者模块跑他者测试 / 他者删除进本变更删除对账误报)。
|
|
5
|
+
*
|
|
6
|
+
* 归属口径与坑 35(quick 审计豁免,run/shared 的 collectOtherQuickSessionDeclarations)
|
|
7
|
+
* 同款:只认**显式声明**——其他 quick 会话 guard.allowedFiles + 其他变更 design §6 清单;
|
|
8
|
+
* 无主文件保留参与判定(fail-closed,不放松「未声明删除/越界」的抓取底线)。
|
|
9
|
+
*
|
|
10
|
+
* 独立零环模块:被 verify-postcheck / verify-probes / contract-matrix 共用(verify-
|
|
11
|
+
* postcheck import contract-matrix,parity 侧不能反向 import verify-postcheck)。
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync, readdirSync } from 'fs'
|
|
14
|
+
import { join } from 'path'
|
|
15
|
+
import { parseFileChangeListDetailed } from './change-list.js'
|
|
16
|
+
import { safeGit, unquoteGitPath } from './git-helper.js'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 主仓未提交文件集(staged + unstaged + untracked,rename 取新路径)。
|
|
20
|
+
* 活性判定的事实源:他者声明的文件若已不在未提交集,说明其工作已 apply+commit(或从未发生),
|
|
21
|
+
* 声明随之失效(坑 foreign-declared-stale-noise,2026-08-25 实证:并行会话 pathspec 重叠期
|
|
22
|
+
* execute/verify 每轮重复刷「已排除 N 个并行会话声明的文件」,其中大量是对方早已 apply+commit
|
|
23
|
+
* 的存量声明——design §6 清单与残留 quick guard 不随 commit 自动失效,纯噪音)。
|
|
24
|
+
* @param {string} cwd 项目根
|
|
25
|
+
* @returns {Set<string>|null} null = git 调用失败(调用方 fail-closed 不过滤)
|
|
26
|
+
*/
|
|
27
|
+
function getMainDirtySet(cwd) {
|
|
28
|
+
const r = safeGit(cwd, ['status', '--porcelain', '--untracked-files=all'], { trim: false })
|
|
29
|
+
if (r.value === null) return null
|
|
30
|
+
const set = new Set()
|
|
31
|
+
for (const line of r.value.split('\n')) {
|
|
32
|
+
if (!line.trim()) continue
|
|
33
|
+
let p = line.slice(3).trim()
|
|
34
|
+
const arrow = p.lastIndexOf(' -> ')
|
|
35
|
+
if (arrow !== -1) p = p.slice(arrow + 4)
|
|
36
|
+
if (p.startsWith('"') && p.endsWith('"')) p = unquoteGitPath(p.slice(1, -1))
|
|
37
|
+
p = p.replace(/\\/g, '/')
|
|
38
|
+
if (p) set.add(p)
|
|
39
|
+
}
|
|
40
|
+
return set
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 变更 worktree 活性速查(.runtime/worktrees/<change>/meta.json)。
|
|
45
|
+
* isolated=true:有存活隔离 worktree(meta 在、非 in-place、worktreePath 目录在)——
|
|
46
|
+
* 其 WIP 在 worktree 内主仓 porcelain 不可见,整份 design 声明按在途处理。
|
|
47
|
+
* @returns {Map<string, { isolated: boolean }>|null} null = 读取失败(fail-closed)
|
|
48
|
+
*/
|
|
49
|
+
function loadWorktreeLiveness(specBase) {
|
|
50
|
+
const map = new Map()
|
|
51
|
+
try {
|
|
52
|
+
const dir = join(specBase, '.runtime', 'worktrees')
|
|
53
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
54
|
+
if (!e.isDirectory()) continue
|
|
55
|
+
try {
|
|
56
|
+
const meta = JSON.parse(readFileSync(join(dir, e.name, 'meta.json'), 'utf8'))
|
|
57
|
+
const isolated = Boolean(meta && meta.mode !== 'in-place-fallback'
|
|
58
|
+
&& meta.worktreePath && existsSync(meta.worktreePath))
|
|
59
|
+
map.set(meta.changeName || e.name, { isolated })
|
|
60
|
+
} catch { /* 单条损坏跳过(该变更走主仓 dirty 判定) */ }
|
|
61
|
+
}
|
|
62
|
+
} catch { return null }
|
|
63
|
+
return map
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 他者声明活性收敛:声明只在「工作仍在途」时有效,已 apply+commit 的存量声明自动失效。
|
|
68
|
+
* - quick 会话(主仓直接改):文件仍在主仓未提交集才算在途
|
|
69
|
+
* - 变更:有存活隔离 worktree → 整份声明在途;否则与 quick 同口径看主仓未提交集
|
|
70
|
+
* 判定所需事实读不出来(git/meta 失败)→ 一律保留(fail-closed,不放大放行面)。
|
|
71
|
+
* @param {Map<string, string[]>} foreign collectForeignDeclaredFiles 的原始结果(原地收敛)
|
|
72
|
+
*/
|
|
73
|
+
function filterStaleForeignDeclarations(foreign, cwd, specBase) {
|
|
74
|
+
if (foreign.size === 0) return
|
|
75
|
+
const dirty = getMainDirtySet(cwd)
|
|
76
|
+
const worktrees = loadWorktreeLiveness(specBase)
|
|
77
|
+
if (dirty === null && worktrees === null) return // 两个事实源全失败 → 原样保留
|
|
78
|
+
for (const [file, owners] of [...foreign.entries()]) {
|
|
79
|
+
const live = owners.filter(owner => {
|
|
80
|
+
if (!owner.startsWith('quick-')) {
|
|
81
|
+
const wt = worktrees ? worktrees.get(owner) : undefined
|
|
82
|
+
if (wt && wt.isolated) return true // 隔离 worktree 在途,声明整份有效
|
|
83
|
+
}
|
|
84
|
+
// quick 会话 / 无存活 worktree 的变更:看主仓未提交集;dirty 集不可用则保守保留
|
|
85
|
+
return dirty === null ? true : dirty.has(file)
|
|
86
|
+
})
|
|
87
|
+
if (live.length === 0) foreign.delete(file)
|
|
88
|
+
else if (live.length < owners.length) foreign.set(file, live)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param {string} cwd 项目根
|
|
94
|
+
* @param {string|null} currentChangeName 本变更名(quick 会话名或 change 名,排除自身)
|
|
95
|
+
* @returns {Map<string, string[]>} file → 声明者列表(quick-<hex> 或变更名)
|
|
96
|
+
*/
|
|
97
|
+
export function collectForeignDeclaredFiles(cwd, currentChangeName) {
|
|
98
|
+
const foreign = new Map()
|
|
99
|
+
const add = (file, owner) => {
|
|
100
|
+
const f = String(file || '').replace(/\\/g, '/')
|
|
101
|
+
if (!f) return
|
|
102
|
+
if (!foreign.has(f)) foreign.set(f, [])
|
|
103
|
+
if (!foreign.get(f).includes(owner)) foreign.get(f).push(owner)
|
|
104
|
+
}
|
|
105
|
+
const specBase = join(cwd, '.sillyspec')
|
|
106
|
+
try {
|
|
107
|
+
// ① 其他 quick 会话的 --files 显式声明(guard.json)
|
|
108
|
+
const sessionsDir = join(specBase, '.runtime', 'quick-sessions')
|
|
109
|
+
let sessionDirs = []
|
|
110
|
+
try { sessionDirs = readdirSync(sessionsDir, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name) } catch {}
|
|
111
|
+
for (const sid of sessionDirs) {
|
|
112
|
+
if (sid === currentChangeName) continue
|
|
113
|
+
try {
|
|
114
|
+
const guard = JSON.parse(readFileSync(join(sessionsDir, sid, 'guard.json'), 'utf8'))
|
|
115
|
+
for (const f of Array.isArray(guard.allowedFiles) ? guard.allowedFiles : []) add(f, sid)
|
|
116
|
+
} catch { /* 损坏/缺失跳过 */ }
|
|
117
|
+
}
|
|
118
|
+
// ② 其他变更的 design §6 清单(目录在即视为在途变更;archive/ 下不算)
|
|
119
|
+
const changesDir = join(specBase, 'changes')
|
|
120
|
+
let changeDirs = []
|
|
121
|
+
try { changeDirs = readdirSync(changesDir, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name) } catch {}
|
|
122
|
+
for (const cn of changeDirs) {
|
|
123
|
+
if (cn === currentChangeName || cn === 'archive') continue
|
|
124
|
+
const designPath = join(changesDir, cn, 'design.md')
|
|
125
|
+
if (!existsSync(designPath)) continue
|
|
126
|
+
try {
|
|
127
|
+
for (const e of parseFileChangeListDetailed(designPath)) add(e.path, cn)
|
|
128
|
+
} catch { /* 清单解析失败跳过该变更 */ }
|
|
129
|
+
}
|
|
130
|
+
} catch { /* 整体异常 → 空集(等价不过滤,回到原行为) */ }
|
|
131
|
+
// 活性收敛(坑 foreign-declared-stale-noise):已 apply+commit 的他者声明不再产生排除噪音
|
|
132
|
+
try { filterStaleForeignDeclarations(foreign, cwd, specBase) } catch { /* 收敛失败 → 原样保留(fail-closed) */ }
|
|
133
|
+
return foreign
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 按他者声明集切分 diff 文件(collectForeignDeclaredFiles 的消费端快捷封装)。
|
|
138
|
+
* @param {string} cwd 项目根
|
|
139
|
+
* @param {string|null} currentChangeName 本变更名
|
|
140
|
+
* @param {string[]|null} diffFiles 待切分文件列表(null 透传,保持调用方 null 语义)
|
|
141
|
+
* @returns {{ own: string[]|null, foreign: Array<{file: string, owners: string[]}> }}
|
|
142
|
+
*/
|
|
143
|
+
export function splitOwnVsForeignDiffFiles(cwd, currentChangeName, diffFiles) {
|
|
144
|
+
if (!Array.isArray(diffFiles)) return { own: diffFiles, foreign: [] }
|
|
145
|
+
const foreignMap = collectForeignDeclaredFiles(cwd, currentChangeName)
|
|
146
|
+
if (foreignMap.size === 0) return { own: diffFiles, foreign: [] }
|
|
147
|
+
const own = []
|
|
148
|
+
const foreign = []
|
|
149
|
+
for (const f of diffFiles) {
|
|
150
|
+
const owners = foreignMap.get(String(f).replace(/\\/g, '/'))
|
|
151
|
+
if (owners) foreign.push({ file: f, owners })
|
|
152
|
+
else own.push(f)
|
|
153
|
+
}
|
|
154
|
+
return { own, foreign }
|
|
155
|
+
}
|
package/src/index.js
CHANGED
|
@@ -100,6 +100,7 @@ SillySpec CLI — 规范驱动开发工具包
|
|
|
100
100
|
sillyspec module-impact --change <name> 生成 module-impact.md 骨架(文件×模块归属按 module-map 预填 + 未匹配清单)
|
|
101
101
|
sillyspec endpoints extract --change <name> [--task task-NN] [--dir <dir>|--files <a.py,b.js>] 静态扫描路由装饰器生成 endpoints.json
|
|
102
102
|
sillyspec scan-fix-headers [--project <名>] scan 文档补 author/created_at header(幂等)
|
|
103
|
+
sillyspec plan-adopt-waves --change <名> [--dry-run] plan.md Wave 段一键重排为 depends_on 拓扑分组(同步任务总表 W 列,幂等)
|
|
103
104
|
sillyspec workspace add <名> <路径> [--role] [--repo] | remove <名> | status 多项目工作区登记与状态探测
|
|
104
105
|
sillyspec scan-fix-leak --spec-dir <specRoot> source_root 误写产物搬到平台 specRoot(污染一键修复)
|
|
105
106
|
sillyspec run quick --cancel --change <会话ID> [--ql <ql-id>] 取消误启动的 quick 会话(QUICKLOG 翻已取消 + 挂载行移除)
|
|
@@ -778,15 +779,22 @@ async function main() {
|
|
|
778
779
|
process.exit(2);
|
|
779
780
|
}
|
|
780
781
|
assertSafeChangeName(vpChange, '--change 变更名');
|
|
781
|
-
const { runVerifyProbes, renderVerifyProbesReport, generateVerifyResultSkeleton } = await import('./verify-probes.js');
|
|
782
|
-
|
|
782
|
+
const { runVerifyProbes, renderVerifyProbesReport, generateVerifyResultSkeleton, resolveVerifyProbesSpecBase } = await import('./verify-probes.js');
|
|
783
|
+
// spec 根统一走漂移锚定(坑 worktree-spec-artifact-misplace):在 worktree 内跑时锚回主仓,
|
|
784
|
+
// 探针读取与 --init 骨架都落主仓——与 plan/execute/verify/archive 的 command.js 守卫同口径。
|
|
785
|
+
// resolvePlatformSpecDir 仍先调(保留平台接管 fail-closed 检查副作用),但仅 pointer 存在时
|
|
786
|
+
// 才把它的返回值当平台根——无 pointer 时它回退 resolveSpecDir(cwd),会返回 worktree 副本
|
|
787
|
+
// 根,当作 platformBase 传入会让锚定被跳过(骨架落回副本)。
|
|
788
|
+
const vpResolved = resolvePlatformSpecDir(dir, specDir);
|
|
789
|
+
const vpPlatformBase = existsSync(join(dir, '.sillyspec-platform.json')) ? vpResolved : null;
|
|
790
|
+
const vpSpecBase = resolveVerifyProbesSpecBase(dir, specDir, vpPlatformBase);
|
|
791
|
+
const vpResult = runVerifyProbes({ cwd: dir, changeName: vpChange, specDir: vpSpecBase });
|
|
783
792
|
if (json) {
|
|
784
793
|
console.log(JSON.stringify({ command: 'verify-probes', change: vpChange, ...vpResult }, null, 2));
|
|
785
794
|
break;
|
|
786
795
|
}
|
|
787
796
|
console.log(renderVerifyProbesReport(vpResult));
|
|
788
797
|
if (vpInit) {
|
|
789
|
-
const vpSpecBase = resolvePlatformSpecDir(dir, specDir) || join(dir, '.sillyspec');
|
|
790
798
|
const vpReportPath = join(vpSpecBase, 'changes', vpChange, 'verify-result.md');
|
|
791
799
|
if (existsSync(vpReportPath)) {
|
|
792
800
|
console.log(`\nℹ️ verify-result.md 已存在,不覆盖: ${vpReportPath}`);
|
|
@@ -797,6 +805,52 @@ async function main() {
|
|
|
797
805
|
}
|
|
798
806
|
break;
|
|
799
807
|
}
|
|
808
|
+
case 'plan-adopt-waves': {
|
|
809
|
+
// plan.md Wave 段一键重排(坑 wave-manual-mismatch-noise,2026-08-24 用户反馈二期):
|
|
810
|
+
// 手排 Wave 与拓扑比对不一致需手改;依赖方向硬拦(plan-postcheck)落地后给一条零手写出路。
|
|
811
|
+
// depMap 与 postcheck 同源(collectTaskDepMap)→ topoSortWaves → 重写 Wave 段 + 同步任务总表 W 列。
|
|
812
|
+
const pawChangeIdx = args.indexOf('--change');
|
|
813
|
+
const pawChange = pawChangeIdx >= 0 && args[pawChangeIdx + 1] ? args[pawChangeIdx + 1] : null;
|
|
814
|
+
const pawDryRun = args.includes('--dry-run');
|
|
815
|
+
if (!pawChange) {
|
|
816
|
+
console.error('用法: sillyspec plan-adopt-waves --change <name> [--dry-run] [--json] [--spec-dir <path>]\n 把 plan.md 的 Wave 段一键重排为 depends_on 拓扑分组(同步任务总表 W 列;--dry-run 只看不写)');
|
|
817
|
+
process.exit(2);
|
|
818
|
+
}
|
|
819
|
+
assertSafeChangeName(pawChange, '--change 变更名');
|
|
820
|
+
const { adoptPlanWaves } = await import('./plan-adopt-waves.js');
|
|
821
|
+
const pawSpecBase = resolvePlatformSpecDir(dir, specDir) || join(dir, '.sillyspec');
|
|
822
|
+
const pawResult = adoptPlanWaves({ changeDir: join(pawSpecBase, 'changes', pawChange), dryRun: pawDryRun });
|
|
823
|
+
if (json) {
|
|
824
|
+
console.log(JSON.stringify({ command: 'plan-adopt-waves', change: pawChange, ...pawResult }, null, 2));
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
827
|
+
if (!pawResult.ok) {
|
|
828
|
+
console.error(`❌ ${pawResult.error}`);
|
|
829
|
+
process.exit(1);
|
|
830
|
+
}
|
|
831
|
+
console.log('📊 拓扑分组(depends_on):');
|
|
832
|
+
pawResult.waves.forEach((wave, i) => {
|
|
833
|
+
console.log(` Wave ${i + 1}: ${wave.join(', ')}`);
|
|
834
|
+
});
|
|
835
|
+
if (pawDryRun) {
|
|
836
|
+
console.log(`\n👁️ dry-run——将写入 ${pawResult.planPath} 的 Wave 段预览:`);
|
|
837
|
+
for (const l of pawResult.waveBlock) console.log(` ${l}`);
|
|
838
|
+
} else {
|
|
839
|
+
console.log(`\n✅ plan.md Wave 段已重排: ${pawResult.planPath}(任务总表 W 列更新 ${pawResult.tableRowsUpdated} 行${pawResult.tableRowsSkipped > 0 ? `,${pawResult.tableRowsSkipped} 行非模板格式未改` : ''};行尾统一 LF)`);
|
|
840
|
+
}
|
|
841
|
+
if (pawResult.postcheck) {
|
|
842
|
+
const pc = pawResult.postcheck;
|
|
843
|
+
if ((pc.errors || []).length > 0) {
|
|
844
|
+
console.warn(`⚠️ 重排后 blueprint 一致性问题(topo 只看依赖不看文件重叠——同 Wave 共享路径需手动拆分或补 depends_on):`);
|
|
845
|
+
for (const e of pc.errors.slice(0, 10)) console.warn(` ${e}`);
|
|
846
|
+
if (pc.errors.length > 10) console.warn(` …等共 ${pc.errors.length} 条`);
|
|
847
|
+
} else {
|
|
848
|
+
console.log('✅ 重排后 blueprint 一致性校验通过(无同 Wave 共享路径冲突)');
|
|
849
|
+
}
|
|
850
|
+
for (const w of (pc.warnings || []).slice(0, 5)) console.warn(`⚠️ ${w}`);
|
|
851
|
+
}
|
|
852
|
+
break;
|
|
853
|
+
}
|
|
800
854
|
case 'module-impact': {
|
|
801
855
|
// archive 模块影响矩阵骨架(2026-08-21 审计第三批 D3):文件×模块归属按 _module-map.yaml
|
|
802
856
|
// paths 前缀匹配预填(机械),影响类型/review 标记留 <!--TODO-->(语义)。已存在不覆盖。
|
|
@@ -1499,8 +1553,8 @@ async function main() {
|
|
|
1499
1553
|
SillySpec worktree — git worktree 隔离管理
|
|
1500
1554
|
|
|
1501
1555
|
用法:
|
|
1502
|
-
sillyspec worktree create <change-name> [--base <branch>] 创建隔离 worktree
|
|
1503
|
-
sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge]
|
|
1556
|
+
sillyspec worktree create <change-name> [--base <branch>] [--adopt-branch] 创建隔离 worktree(--adopt-branch:收编既有同名分支为工作分支,分支现状作 baseline)
|
|
1557
|
+
sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge] [--skip-overlap] [--stash-dirty] 校验并应用变更到主工作区(--stash-dirty:主仓在途改动自动 stash→apply→恢复,SHA 兜底可审计)
|
|
1504
1558
|
sillyspec worktree assess <change-name> 风险审计 + 自动 apply
|
|
1505
1559
|
sillyspec worktree diff <change-name> [--base <commit>] 查看 worktree 相对 base 的变更
|
|
1506
1560
|
sillyspec worktree list 列出所有活跃 worktree
|
|
@@ -1518,7 +1572,7 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1518
1572
|
switch (wtSubCmd) {
|
|
1519
1573
|
case 'create': {
|
|
1520
1574
|
if (!wtName) {
|
|
1521
|
-
console.error('❌ 用法: sillyspec worktree create <change-name> [--base <branch>]');
|
|
1575
|
+
console.error('❌ 用法: sillyspec worktree create <change-name> [--base <branch>] [--adopt-branch]');
|
|
1522
1576
|
process.exit(1);
|
|
1523
1577
|
}
|
|
1524
1578
|
// F6 路径穿越消毒:worktree 名用于分支名 + worktree 目录,含 ../ 会逃出 .sillyspec/worktrees/。
|
|
@@ -1526,8 +1580,9 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1526
1580
|
catch (e) { console.error(`❌ ${e.message}`); process.exit(2); }
|
|
1527
1581
|
const baseIdx = args.indexOf('--base');
|
|
1528
1582
|
const base = baseIdx >= 0 && args[baseIdx + 1] ? args[baseIdx + 1] : undefined;
|
|
1583
|
+
const adoptBranch = args.includes('--adopt-branch'); // 收编既有同名分支为工作分支(坑 worktree-user-branch-conflict)
|
|
1529
1584
|
try {
|
|
1530
|
-
const info = wm.create(wtName, { base });
|
|
1585
|
+
const info = wm.create(wtName, { base, adoptBranch });
|
|
1531
1586
|
console.log(`✅ worktree 已创建`);
|
|
1532
1587
|
console.log(` 分支: ${info.branch}`);
|
|
1533
1588
|
console.log(` 路径: ${info.worktreePath}`);
|
|
@@ -1547,11 +1602,13 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1547
1602
|
}
|
|
1548
1603
|
case 'apply': {
|
|
1549
1604
|
if (!wtName) {
|
|
1550
|
-
console.error('❌ 用法: sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge]');
|
|
1605
|
+
console.error('❌ 用法: sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge] [--skip-overlap] [--stash-dirty]');
|
|
1551
1606
|
process.exit(1);
|
|
1552
1607
|
}
|
|
1553
1608
|
const checkOnly = args.includes('--check-only');
|
|
1554
1609
|
const merge = args.includes('--merge');
|
|
1610
|
+
const skipOverlap = args.includes('--skip-overlap');
|
|
1611
|
+
const stashDirty = args.includes('--stash-dirty');
|
|
1555
1612
|
|
|
1556
1613
|
// 解析 --base 参数(默认 merge-base)
|
|
1557
1614
|
let base = 'merge-base';
|
|
@@ -1565,7 +1622,7 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1565
1622
|
base = baseVal;
|
|
1566
1623
|
}
|
|
1567
1624
|
|
|
1568
|
-
const { applyWorktree } = await import('./worktree-apply.js');
|
|
1625
|
+
const { applyWorktree, withMainRepoLock } = await import('./worktree-apply.js');
|
|
1569
1626
|
// W3 task-09:apply 链路构造 ctx(D-013),让 task-05 applyWorktree 按 ctx 区分主仓 A5 / 跨仓 no-op。
|
|
1570
1627
|
// 跨仓 apply=no-op(G1 D-009):校验 review.head 是跨仓真实 commit + 跳过 wm.cleanup。
|
|
1571
1628
|
// ctx 构造 fail-closed(约束②)——跨仓配置错时 apply 必须阻断(走错仓=数据所有权事故),不降级。
|
|
@@ -1577,7 +1634,17 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1577
1634
|
console.error(`❌ apply 失败:跨仓 MultiRepoContext 构造失败(${e.message})`);
|
|
1578
1635
|
process.exit(1);
|
|
1579
1636
|
}
|
|
1580
|
-
|
|
1637
|
+
// 主仓 apply 互斥锁(坑 main-apply-no-mutex):真 apply(非 checkOnly)在锁内跑——
|
|
1638
|
+
// apply 链(rollback/merge/cleanup)直接改主仓工作区,两会话并发互踩会互相清文件。
|
|
1639
|
+
let result;
|
|
1640
|
+
try {
|
|
1641
|
+
result = checkOnly
|
|
1642
|
+
? applyWorktree(wtName, { cwd: dir, checkOnly, merge, base, ctx: _applyCtx, skipOverlap, stashDirty })
|
|
1643
|
+
: await withMainRepoLock(dir, wtName, 'apply', () => applyWorktree(wtName, { cwd: dir, checkOnly, merge, base, ctx: _applyCtx, skipOverlap, stashDirty }));
|
|
1644
|
+
} catch (lockErr) {
|
|
1645
|
+
console.error(`❌ ${lockErr.message}`);
|
|
1646
|
+
process.exit(1);
|
|
1647
|
+
}
|
|
1581
1648
|
|
|
1582
1649
|
if (result.errors.length > 0) {
|
|
1583
1650
|
console.error(`❌ 校验失败:`);
|
|
@@ -1685,8 +1752,15 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1685
1752
|
console.log('');
|
|
1686
1753
|
if (assessment.decision === 'SAFE' || assessment.decision === 'WARNING') {
|
|
1687
1754
|
console.log('Action: auto-applying...');
|
|
1688
|
-
const { applyWorktree } = await import('./worktree-apply.js');
|
|
1689
|
-
|
|
1755
|
+
const { applyWorktree, withMainRepoLock } = await import('./worktree-apply.js');
|
|
1756
|
+
// 主仓互斥锁(与手动 apply 同款):自动 apply 同样改主仓工作区,必须互斥
|
|
1757
|
+
let applyResult;
|
|
1758
|
+
try {
|
|
1759
|
+
applyResult = await withMainRepoLock(dir, wtName, 'assess-auto-apply', () => applyWorktree(wtName, { cwd: dir, ctx: _assessCtx }));
|
|
1760
|
+
} catch (lockErr) {
|
|
1761
|
+
console.error(`❌ 自动 apply 未执行:${lockErr.message}`);
|
|
1762
|
+
break;
|
|
1763
|
+
}
|
|
1690
1764
|
if (applyResult.errors.length > 0) {
|
|
1691
1765
|
console.error('❌ apply 失败:', applyResult.errors.join('; '));
|
|
1692
1766
|
} else {
|
|
@@ -1785,7 +1859,10 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1785
1859
|
}
|
|
1786
1860
|
const forceFlag = args.includes('--force');
|
|
1787
1861
|
try {
|
|
1788
|
-
|
|
1862
|
+
// 主仓互斥锁(坑 main-repo-no-mutex 二批):cleanup 删 worktree 注册表/分支/目录,
|
|
1863
|
+
// 与并行会话的 apply/cleanup 互踩会互相清——与其他写主仓操作共用一把 main-repo.lock
|
|
1864
|
+
const { withMainRepoLock } = await import('./worktree-apply.js');
|
|
1865
|
+
const result = await withMainRepoLock(dir, wtName, 'worktree-cleanup', () => wm.cleanup(wtName, { force: forceFlag }));
|
|
1789
1866
|
if (result.result === 'cleaned' || result.result === 'force-cleaned') {
|
|
1790
1867
|
console.log(`✅ worktree 已清理: ${wtName} (mode: ${result.mode})`);
|
|
1791
1868
|
if (result.details?.length > 0) {
|
|
@@ -1798,6 +1875,11 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
1798
1875
|
console.log(` 原因: in-place 模式没有隔离目录需要清理`);
|
|
1799
1876
|
} else if (result.result === 'blocked') {
|
|
1800
1877
|
console.error(`🚫 拒绝清理:有未落主仓交付变更,请先 sillyspec worktree apply ${wtName} 或 --force`);
|
|
1878
|
+
} else if (result.result === 'partial') {
|
|
1879
|
+
// 坑 ghost-dir-junction-pierce:partial 残留此前落进 else 打成「未找到」,用户误以为
|
|
1880
|
+
// 干净、人工 rm -rf 穿透 junction——必须明示残留 + 安全清理指引
|
|
1881
|
+
console.warn(`⚠️ 部分清理(残留:${(result.residual || []).join('; ') || 'worktree 目录'})`);
|
|
1882
|
+
console.warn(` Windows 手动清理勿 rm -rf(穿透 node_modules junction 删主仓依赖):先 cmd /c rmdir "<worktree>\\node_modules" 解链再删,或 sillyspec worktree doctor --fix`);
|
|
1801
1883
|
} else {
|
|
1802
1884
|
console.log(`ℹ️ worktree 未找到: ${wtName}`);
|
|
1803
1885
|
}
|
package/src/init.js
CHANGED
|
@@ -23,6 +23,9 @@ const __dirname = dirname(__filename);
|
|
|
23
23
|
// 详见 docs/sillyspec/runtime-cleanup-destroys-worktree-meta.md
|
|
24
24
|
//
|
|
25
25
|
// 策略:白名单保留权威状态,逐项删除可重建的缓存子项;未知子项默认保留(安全侧倾斜)。
|
|
26
|
+
// local.yaml 同样保留:gitignored 凭据文件(平台 init lease 第 5 步下发 / local detect /
|
|
27
|
+
// platform connect 写入,含用户手调 mcp 段),删除即永久丢失无法从 git 找回。本函数曾把它
|
|
28
|
+
// 当非权威残留整删,与 platformMode 跳过清理的保护语义自相矛盾,2026-08-23 起不再删。
|
|
26
29
|
const RUNTIME_KEEP = new Set([
|
|
27
30
|
'worktrees', // worktree 目录 + meta.json(worktree.js:17)
|
|
28
31
|
'sillyspec.db', // SQLite 进度库(权威状态源,progress.js:7)
|
|
@@ -33,15 +36,14 @@ const RUNTIME_KEEP = new Set([
|
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
38
|
* 清理 .sillyspec/ 下的运行时残留,保留权威状态。
|
|
36
|
-
* 同时清理 local.yaml
|
|
39
|
+
* 同时清理 codebase/(非权威,整删安全)。local.yaml 受保护不删——
|
|
40
|
+
* 平台 init 下发的凭据配置,见上方策略注释。
|
|
37
41
|
* @param {string} legacyDir - 源码目录的 .sillyspec/ 路径
|
|
38
42
|
*/
|
|
39
43
|
export function cleanupRuntimeResidue(legacyDir) {
|
|
40
|
-
// local.yaml
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (existsSync(p)) { try { rmSync(p, { recursive: true, force: true }) } catch {} }
|
|
44
|
-
}
|
|
44
|
+
// codebase/ 非权威,整删;local.yaml 是凭据配置,保留
|
|
45
|
+
const codebasePath = join(legacyDir, 'codebase');
|
|
46
|
+
if (existsSync(codebasePath)) { try { rmSync(codebasePath, { recursive: true, force: true }) } catch {} }
|
|
45
47
|
// .runtime/ 逐项清理,白名单保留
|
|
46
48
|
const runtimeDir = join(legacyDir, '.runtime');
|
|
47
49
|
if (existsSync(runtimeDir)) {
|
|
@@ -251,7 +253,7 @@ function doInstall(projectDir, tools, subprojects = [], specDir = null, options
|
|
|
251
253
|
// 真实资产存在:拒绝整体删除,仅清理运行时残留
|
|
252
254
|
console.error('❌ [sillyspec] 拒绝删除源码目录的 .sillyspec/:检测到真实资产(changes/、projects/ 或 sillyspec.db)。');
|
|
253
255
|
console.error(' 该项目似乎本身就用 SillySpec 管理。如需改用外部 spec 目录,请先手动迁移/备份。');
|
|
254
|
-
console.error(' 本次仅清理运行时残留(.runtime/ 缓存、local.yaml、
|
|
256
|
+
console.error(' 本次仅清理运行时残留(.runtime/ 缓存、codebase/),保留 local.yaml、worktrees 与进度状态。');
|
|
255
257
|
cleanupRuntimeResidue(legacyDir);
|
|
256
258
|
} else {
|
|
257
259
|
// 无真实资产:确属旧版本残留,安全删除
|