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
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { openDatabase, applyPragmas, runTransaction } from './db-engine.js';
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
|
|
5
|
+
// DB schema 版本(与 project.schema_version DEFAULT 对齐)。_createSchema 改动(加表/列/migration)时 bump,
|
|
6
|
+
// 触发 .schema-version 戳失效 → 下次 init 重跑 _createSchema(W4-H:高频读路径 gate/derive/status
|
|
7
|
+
// 每次 new ProgressManager 都过 init,靠版本戳跳过建表省开销)。
|
|
8
|
+
// node:sqlite(DatabaseSync)是原生 SQLite 引擎,打开即持久化(不像 sql.js 纯内存需整库 export 落盘),
|
|
9
|
+
// _createSchema 内 DDL 直接落盘,无需额外 _save。
|
|
10
|
+
const DB_SCHEMA_VERSION = 5;
|
|
11
|
+
|
|
12
|
+
// SQLITE_BUSY 应用层有限重试(R-08 / NFR-03):WAL 单写者模型,并发写第二者在
|
|
13
|
+
// busy_timeout=5000(init PRAGMA)后抛 SQLITE_BUSY。busy_timeout 已在引擎层处理大部分等待;
|
|
14
|
+
// 此处常量给 transaction() 做超时后的应用层兜底重试。
|
|
15
|
+
// 仅 SQLITE_BUSY 重试(其它异常直接上抛);MAX_BUSY_RETRIES 有限次防死循环,达上限 fail-loud
|
|
16
|
+
// 不静默吞错。BUSY_BACKOFF_MS 递增退避(50→100→200ms),总等待上限 350ms。
|
|
17
|
+
// busy_timeout=5000 保持不变(design §7):引擎层 5s 等待已覆盖大部分锁竞争,应用层 3 次退避
|
|
18
|
+
// 足够消化极端并发超时尖刺,无需抬高 busy_timeout(过长会让单次写阻塞拖慢整体吞吐)。
|
|
19
|
+
const MAX_BUSY_RETRIES = 3;
|
|
20
|
+
const BUSY_BACKOFF_MS = [50, 100, 200];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 同步阻塞 sleep(node:sqlite 同步 API,BUSY 退避不能用 await)。
|
|
24
|
+
* Atomics.wait 阻塞当前线程不占 CPU;SharedArrayBuffer 不可用的环境(受限 CSP / 旧 Node)
|
|
25
|
+
* 退化为 busy-wait(退避时长 50-200ms 短,CPU 占用可接受)。仅在 transaction() 的 BUSY
|
|
26
|
+
* 重试路径调用。
|
|
27
|
+
*/
|
|
28
|
+
function _sleepSync(ms) {
|
|
29
|
+
try {
|
|
30
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
31
|
+
} catch {
|
|
32
|
+
const end = Date.now() + ms;
|
|
33
|
+
while (Date.now() < end) { /* busy-wait fallback */ }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class DB {
|
|
38
|
+
constructor(dbPath) {
|
|
39
|
+
this.dbPath = dbPath;
|
|
40
|
+
this.db = null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 同步初始化(node:sqlite DatabaseSync 是同步 API,无 async/await,与 sql.js 的 initSqlJs() 异步加载不同):
|
|
45
|
+
* - openDatabase(path) 同步打开/创建库文件(node:sqlite 原生绑定,非 WASM)
|
|
46
|
+
* - PRAGMA:journal_mode=WAL 真生效(node:sqlite 直连原生 SQLite,WAL 落地;
|
|
47
|
+
* sql.js 是纯内存库,WAL 对它无意义),busy_timeout=5000 让写锁竞争时自动等待,
|
|
48
|
+
* foreign_keys=ON 启用外键级联,synchronous=NORMAL 在 WAL 下兼顾安全与性能
|
|
49
|
+
* - schema 戳检查:内容匹配 DB_SCHEMA_VERSION 则跳过 _createSchema,省建表开销
|
|
50
|
+
* - node:sqlite 打开即持久化,DDL/事务提交直接落盘,不需要 sql.js 时代的 _save()
|
|
51
|
+
*
|
|
52
|
+
* .bak 损坏回退由 _openWithFallback() 承担(task-04):主库 → .bak → 全新/报错 逐级回退,
|
|
53
|
+
* 语义对齐原 sql.js 的 _loadDatabase。
|
|
54
|
+
*/
|
|
55
|
+
init() {
|
|
56
|
+
// 1. 确保父目录存在
|
|
57
|
+
const dir = dirname(this.dbPath);
|
|
58
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
59
|
+
|
|
60
|
+
// 2. 同步打开/创建数据库(主库 → .bak → 全新/报错 逐级回退,归 task-04)
|
|
61
|
+
this.db = this._openWithFallback();
|
|
62
|
+
|
|
63
|
+
// 3. 设置 PRAGMA(node:sqlite 走真 SQLite,journal_mode=WAL 真生效;经 applyPragmas 逐条 exec)
|
|
64
|
+
applyPragmas(this.db, [
|
|
65
|
+
['journal_mode', 'WAL'],
|
|
66
|
+
['busy_timeout', '5000'],
|
|
67
|
+
['foreign_keys', 'ON'],
|
|
68
|
+
['synchronous', 'NORMAL'],
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
// 4. 创建表结构(仅当 schema 版本戳不匹配时——W4-H):
|
|
72
|
+
// schema 已最新则跳过建表,省 DDL 开销。node:sqlite 打开即持久化,
|
|
73
|
+
// _createSchema 内 DDL 直接落盘,无需 _save。
|
|
74
|
+
// 戳在但 db 缺表属"手动改 db"边角(SillySpec 不支持),不在本层兜底。
|
|
75
|
+
const versionPath = `${this.dbPath}.schema-version`;
|
|
76
|
+
let schemaCurrent = false;
|
|
77
|
+
try {
|
|
78
|
+
schemaCurrent = existsSync(versionPath)
|
|
79
|
+
&& readFileSync(versionPath, 'utf8').trim() === String(DB_SCHEMA_VERSION);
|
|
80
|
+
} catch { /* 戳读取失败保守重跑 schema */ }
|
|
81
|
+
|
|
82
|
+
if (!schemaCurrent) {
|
|
83
|
+
this._createSchema();
|
|
84
|
+
try { writeFileSync(versionPath, String(DB_SCHEMA_VERSION)); } catch { /* 戳写入失败不阻断,下次重跑 */ }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 打开数据库(主库 → .bak → 全新/报错 逐级回退)。
|
|
90
|
+
* 语义对齐原 sql.js 的 _loadDatabase,但 node:sqlite 绑定文件路径无 _save,
|
|
91
|
+
* .bak 回退时 copyFileSync 把 .bak 内容恢复到主库路径,统一用 dbPath。
|
|
92
|
+
* - 主库存在且有内容且可打开:直接用。
|
|
93
|
+
* - 主库缺失/为空/损坏:尝试 .bak;成功则 warn 原因后 copy 回主库使用。
|
|
94
|
+
* - 都不可用:主库不存在→建全新空库;主库曾存在(空/损坏)→fail-loud 抛错(不静默建空库吞进度)。
|
|
95
|
+
* node:sqlite 打开 0 字节文件不抛错:主库须 statSync 显式判空(截断信号→走回退,防静默吞进度);
|
|
96
|
+
* .bak 作为恢复源只要存在且能打开即用(含 0 字节空库——node:sqlite 视其为合法空库)。
|
|
97
|
+
* 注:node:sqlite 提交即持久化,不再写前备份主 .bak(sql.js 时代 _save/_atomicWriteSync 已随
|
|
98
|
+
* 2026-08-11 迁移移除);此恢复分支是向后兼容兜底,仅对 sql.js 时代遗留的 .bak 生效,
|
|
99
|
+
* 全新 node:sqlite 项目不产生主 .bak)。
|
|
100
|
+
*/
|
|
101
|
+
_openWithFallback() {
|
|
102
|
+
const bakPath = `${this.dbPath}.bak`;
|
|
103
|
+
// readValid: null=文件不存在;'empty'=存在但 0 字节;'ok'=有内容
|
|
104
|
+
const readValid = (p) => {
|
|
105
|
+
if (!existsSync(p)) return null;
|
|
106
|
+
return statSync(p).size === 0 ? 'empty' : 'ok';
|
|
107
|
+
};
|
|
108
|
+
// tryOpen: openDatabase(path) + prepare 探测双保险(防打开成功但内容非 SQLite)。
|
|
109
|
+
// 探测前先设 busy_timeout(2026-08-21 审查 BUG-7):init() 的 applyPragmas 在 _openWithFallback
|
|
110
|
+
// 之后才跑,探测 SELECT 此前以 busy_timeout=0(SQLite 默认)执行——他者进程 CHECKPOINT 改写
|
|
111
|
+
// 主库时探测立即 SQLITE_BUSY,3 次重试总窗口仅 350ms,大 WAL 下 checkpoint 秒级 → 健康库
|
|
112
|
+
// 被误判"损坏"硬抛错。先设 busy_timeout 让探测自身等待锁,重试只剩消化瞬时抖动。
|
|
113
|
+
const tryOpen = (p) => {
|
|
114
|
+
let db;
|
|
115
|
+
try { db = openDatabase(p); }
|
|
116
|
+
catch { return null; }
|
|
117
|
+
try {
|
|
118
|
+
db.exec('PRAGMA busy_timeout = 5000');
|
|
119
|
+
db.prepare('SELECT count(*) FROM sqlite_master').get(); return db;
|
|
120
|
+
} catch { try { db.close(); } catch { /* 关闭失败忽略 */ } return null; }
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// 1. 主库(0 字节=截断信号,必须走回退,故门禁要求 'ok' 有内容)
|
|
124
|
+
if (readValid(this.dbPath) === 'ok') {
|
|
125
|
+
const primaryDb = tryOpen(this.dbPath);
|
|
126
|
+
if (primaryDb) return primaryDb;
|
|
127
|
+
// 并发首开竞争(2026-08-12 db-concurrency flaky 根因实证):多进程近乎同时
|
|
128
|
+
// new DB().init() 打开同一新建库时,tryOpen 的 prepare(SELECT count(*)) 可能撞上
|
|
129
|
+
// 他者进程的 CHECKPOINT 改写主库 → 瞬时失败返 null。此时主库存在且有内容,
|
|
130
|
+
// 非真损坏——有限重试消化锁竞争(复用 MAX_BUSY_RETRIES 退避,与 transaction 的
|
|
131
|
+
// SQLITE_BUSY 重试同基建)。真损坏重试也不会过,最终仍走 .bak 回退 / fail-loud,
|
|
132
|
+
// 防吞进度语义零回归。
|
|
133
|
+
for (let attempt = 0; attempt < MAX_BUSY_RETRIES; attempt++) {
|
|
134
|
+
_sleepSync(BUSY_BACKOFF_MS[attempt]);
|
|
135
|
+
const retryDb = tryOpen(this.dbPath);
|
|
136
|
+
if (retryDb) return retryDb;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 2. .bak 回退(.bak 是恢复源:存在且能打开即用,含 0 字节空库;门禁只挡"不存在",
|
|
141
|
+
// 避免 tryOpen 对不存在的路径触发 openDatabase 的副作用——会凭空创建文件)
|
|
142
|
+
if (readValid(bakPath) !== null) {
|
|
143
|
+
const bakDb = tryOpen(bakPath);
|
|
144
|
+
if (bakDb) {
|
|
145
|
+
const primaryRaw = readValid(this.dbPath);
|
|
146
|
+
const reason = primaryRaw === 'empty'
|
|
147
|
+
? 'sillyspec.db 为空(可能被截断)'
|
|
148
|
+
: primaryRaw === null
|
|
149
|
+
? 'sillyspec.db 不存在'
|
|
150
|
+
: 'sillyspec.db 损坏';
|
|
151
|
+
console.warn(`⚠️ ${reason},已从 .bak 备份恢复。`);
|
|
152
|
+
bakDb.close();
|
|
153
|
+
// 覆盖前救援快照(2026-08-21 审查 BUG-7):主库有内容但打不开("损坏")时,其中可能
|
|
154
|
+
// 含比 .bak 更新的数据——静默覆盖即静默丢。best-effort 留一份 .corrupt-<ts> 副本供人工恢复。
|
|
155
|
+
if (primaryRaw === 'ok') {
|
|
156
|
+
try { copyFileSync(this.dbPath, `${this.dbPath}.corrupt-${Date.now()}`); } catch { /* 救援失败不阻断恢复 */ }
|
|
157
|
+
}
|
|
158
|
+
// node:sqlite 绑定路径,无 _save:把 .bak 内容 copy 回主库,统一用 dbPath。
|
|
159
|
+
// 体检 BUG-18:主库可能正被其他进程(daemon/另一 CLI)打开——Windows 覆盖他人
|
|
160
|
+
// 打开的文件抛 EPERM/EBUSY,短暂退避重试(持有者通常是瞬时句柄),仍失败 fail-loud
|
|
161
|
+
let copied = false;
|
|
162
|
+
let lastErr = null;
|
|
163
|
+
for (let attempt = 0; attempt < 5 && !copied; attempt++) {
|
|
164
|
+
try {
|
|
165
|
+
copyFileSync(bakPath, this.dbPath);
|
|
166
|
+
copied = true;
|
|
167
|
+
} catch (e) {
|
|
168
|
+
if (!['EPERM', 'EBUSY', 'EACCES'].includes(e.code)) throw e;
|
|
169
|
+
lastErr = e;
|
|
170
|
+
_sleepSync(50 * (attempt + 1));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (!copied) throw lastErr;
|
|
174
|
+
return openDatabase(this.dbPath);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// 3. 都不可用
|
|
179
|
+
if (readValid(this.dbPath) === null) {
|
|
180
|
+
// 主库与备份都不存在 → 全新项目,建空库
|
|
181
|
+
return openDatabase(this.dbPath);
|
|
182
|
+
}
|
|
183
|
+
// 主库曾存在(空/损坏)但无法恢复 → 数据丢失,必须 fail-loud(不静默建空库吞进度)
|
|
184
|
+
throw new Error('sillyspec.db 损坏且 .bak 备份不可用,无法恢复。请从版本控制或其他备份恢复 .sillyspec/.runtime/ 后重试。');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* 关闭数据库。node:sqlite 的 close() 自动做 WAL checkpoint(把 -wal/-shm 日志合并回主库),
|
|
189
|
+
* 不需要 sql.js 时代的 _save() 整库 export 落盘。
|
|
190
|
+
*/
|
|
191
|
+
close() {
|
|
192
|
+
if (this.db) {
|
|
193
|
+
try {
|
|
194
|
+
this.db.close();
|
|
195
|
+
} catch (err) {
|
|
196
|
+
// close 自身失败(如 WAL checkpoint 磁盘满):仍置 null 防后续操作已损坏句柄,warn 留痕不吞
|
|
197
|
+
console.warn(`[db] close 失败(句柄已废弃): ${err && err.message ? err.message : err}`);
|
|
198
|
+
} finally {
|
|
199
|
+
this.db = null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 原生事务 + SQLITE_BUSY 应用层有限重试(R-08 / NFR-03)。
|
|
206
|
+
*
|
|
207
|
+
* node:sqlite 无 .transaction(),runTransaction(fn)(db-engine)用 SAVEPOINT/RELEASE/
|
|
208
|
+
* ROLLBACK TO 手写事务:fn 抛错自动回滚且不吞错,嵌套调用自动形成 savepoint 栈
|
|
209
|
+
* (对齐旧引擎嵌套自动 SAVEPOINT 的兼容实现)。无需手动 BEGIN/COMMIT/ROLLBACK,
|
|
210
|
+
* 也无需 _save(node:sqlite 提交即持久化)。
|
|
211
|
+
*
|
|
212
|
+
* SQLITE_BUSY 重试:WAL 单写者模型,并发写第二者在 busy_timeout=5000 后抛 BUSY。此处对
|
|
213
|
+
* BUSY 加 MAX_BUSY_RETRIES 次递增退避(BUSY_BACKOFF_MS);仅 BUSY 重试(其它异常直接上抛),
|
|
214
|
+
* 达上限 fail-loud 抛错不静默吞(防死循环)。BUSY 重试收敛在 DB 层 transaction 封装,
|
|
215
|
+
* 所有写者(progress.js _write / initChange / setStage 等)统一受益,不散落调用点。
|
|
216
|
+
*/
|
|
217
|
+
transaction(fn) {
|
|
218
|
+
if (!this.db) throw new Error('DB not initialized');
|
|
219
|
+
let attempt = 0;
|
|
220
|
+
while (true) {
|
|
221
|
+
try {
|
|
222
|
+
return runTransaction(this.db, fn);
|
|
223
|
+
} catch (err) {
|
|
224
|
+
// 仅 SQLITE_BUSY 重试(node:sqlite err.errcode 为 5 / err.code 为 'ERR_SQLITE_ERROR',message 含 'database is locked')
|
|
225
|
+
const isBusy = err && (err.code === 'SQLITE_BUSY' || err.code === 5 || err.errcode === 5
|
|
226
|
+
|| (typeof err.message === 'string' && /database is locked|SQLITE_BUSY/i.test(err.message)));
|
|
227
|
+
if (!isBusy) throw err;
|
|
228
|
+
if (attempt >= MAX_BUSY_RETRIES) throw err; // 达上限 fail-loud(不静默吞,防死循环)
|
|
229
|
+
_sleepSync(BUSY_BACKOFF_MS[attempt]);
|
|
230
|
+
attempt++;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** 获取底层 db 对象(node:sqlite DatabaseSync 实例,供 progress.js 直接使用) */
|
|
236
|
+
getDb() {
|
|
237
|
+
return this.db;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
_createSchema() {
|
|
241
|
+
// node:sqlite:exec() 执行多条 SQL/DDL(无返回);prepare().run/get/all 用于 DML。
|
|
242
|
+
// sql.js 的 .run(sql) 在此换为 .exec(sql)。
|
|
243
|
+
|
|
244
|
+
// project 表
|
|
245
|
+
this.db.exec(`
|
|
246
|
+
CREATE TABLE IF NOT EXISTS project (
|
|
247
|
+
id INTEGER PRIMARY KEY DEFAULT 1,
|
|
248
|
+
name TEXT NOT NULL,
|
|
249
|
+
schema_version INTEGER DEFAULT 5,
|
|
250
|
+
created_at TEXT NOT NULL,
|
|
251
|
+
updated_at TEXT NOT NULL
|
|
252
|
+
)
|
|
253
|
+
`);
|
|
254
|
+
|
|
255
|
+
// changes 表
|
|
256
|
+
this.db.exec(`
|
|
257
|
+
CREATE TABLE IF NOT EXISTS changes (
|
|
258
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
259
|
+
name TEXT UNIQUE NOT NULL,
|
|
260
|
+
current_stage TEXT DEFAULT 'scan',
|
|
261
|
+
status TEXT DEFAULT 'active',
|
|
262
|
+
no_worktree INTEGER DEFAULT 0,
|
|
263
|
+
created_at TEXT NOT NULL,
|
|
264
|
+
last_active TEXT NOT NULL,
|
|
265
|
+
platform_change_id INTEGER,
|
|
266
|
+
platform_workspace_id INTEGER,
|
|
267
|
+
platform_last_sync TEXT,
|
|
268
|
+
platform_sync_enabled INTEGER DEFAULT 0
|
|
269
|
+
)
|
|
270
|
+
`);
|
|
271
|
+
|
|
272
|
+
// stages 表
|
|
273
|
+
this.db.exec(`
|
|
274
|
+
CREATE TABLE IF NOT EXISTS stages (
|
|
275
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
276
|
+
change_id INTEGER NOT NULL REFERENCES changes(id) ON DELETE CASCADE,
|
|
277
|
+
stage TEXT NOT NULL,
|
|
278
|
+
status TEXT DEFAULT 'pending',
|
|
279
|
+
started_at TEXT,
|
|
280
|
+
completed_at TEXT,
|
|
281
|
+
UNIQUE(change_id, stage)
|
|
282
|
+
)
|
|
283
|
+
`);
|
|
284
|
+
|
|
285
|
+
// steps 表
|
|
286
|
+
this.db.exec(`
|
|
287
|
+
CREATE TABLE IF NOT EXISTS steps (
|
|
288
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
289
|
+
stage_id INTEGER NOT NULL REFERENCES stages(id) ON DELETE CASCADE,
|
|
290
|
+
name TEXT NOT NULL,
|
|
291
|
+
status TEXT DEFAULT 'pending',
|
|
292
|
+
output TEXT,
|
|
293
|
+
completed_at TEXT,
|
|
294
|
+
ordering INTEGER NOT NULL DEFAULT 0
|
|
295
|
+
)
|
|
296
|
+
`);
|
|
297
|
+
|
|
298
|
+
// batch_progress 表
|
|
299
|
+
this.db.exec(`
|
|
300
|
+
CREATE TABLE IF NOT EXISTS batch_progress (
|
|
301
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
302
|
+
change_id INTEGER NOT NULL REFERENCES changes(id) ON DELETE CASCADE,
|
|
303
|
+
total INTEGER DEFAULT 0,
|
|
304
|
+
completed INTEGER DEFAULT 0,
|
|
305
|
+
failed INTEGER DEFAULT 0,
|
|
306
|
+
skipped INTEGER DEFAULT 0,
|
|
307
|
+
UNIQUE(change_id)
|
|
308
|
+
)
|
|
309
|
+
`);
|
|
310
|
+
|
|
311
|
+
// approvals 表
|
|
312
|
+
this.db.exec(`
|
|
313
|
+
CREATE TABLE IF NOT EXISTS approvals (
|
|
314
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
315
|
+
change_id INTEGER NOT NULL REFERENCES changes(id) ON DELETE CASCADE,
|
|
316
|
+
status TEXT DEFAULT 'not_required',
|
|
317
|
+
requested_at TEXT,
|
|
318
|
+
approved_by TEXT,
|
|
319
|
+
approved_at TEXT,
|
|
320
|
+
rejection_reason TEXT,
|
|
321
|
+
UNIQUE(change_id)
|
|
322
|
+
)
|
|
323
|
+
`);
|
|
324
|
+
|
|
325
|
+
// 索引
|
|
326
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_changes_current_stage ON changes(current_stage)');
|
|
327
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_changes_status ON changes(status)');
|
|
328
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_stages_change ON stages(change_id)');
|
|
329
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_steps_stage ON steps(stage_id)');
|
|
330
|
+
|
|
331
|
+
// Migration: add isolation columns to changes table (idempotent)
|
|
332
|
+
this._migrateAddColumn('changes', 'isolation_status', 'TEXT');
|
|
333
|
+
this._migrateAddColumn('changes', 'isolation_mode', 'TEXT');
|
|
334
|
+
this._migrateAddColumn('changes', 'isolation_reason', 'TEXT');
|
|
335
|
+
|
|
336
|
+
// Migration: add waiting support columns to steps table (idempotent)
|
|
337
|
+
this._migrateAddColumn('steps', 'wait_reason', 'TEXT');
|
|
338
|
+
this._migrateAddColumn('steps', 'wait_options', 'TEXT');
|
|
339
|
+
this._migrateAddColumn('steps', 'wait_answer', 'TEXT');
|
|
340
|
+
this._migrateAddColumn('steps', 'waited_at', 'TEXT');
|
|
341
|
+
// repeatableWait support
|
|
342
|
+
this._migrateAddColumn('steps', 'wait_answers', 'TEXT'); // JSON array
|
|
343
|
+
this._migrateAddColumn('steps', 'wait_round', 'INTEGER');
|
|
344
|
+
this._migrateAddColumn('steps', 'max_wait_rounds', 'INTEGER');
|
|
345
|
+
|
|
346
|
+
// Revision v1 support
|
|
347
|
+
this._migrateAddColumn('stages', 'revision', 'INTEGER DEFAULT 0');
|
|
348
|
+
this._migrateAddColumn('stages', 'reopened_from_step', 'TEXT');
|
|
349
|
+
this._migrateAddColumn('stages', 'reopened_at', 'TEXT');
|
|
350
|
+
this._migrateAddColumn('stages', 'stale_reason', 'TEXT');
|
|
351
|
+
|
|
352
|
+
// Platform sync support(2026-08-10-platform-progress-sync §8 / D-012):
|
|
353
|
+
// changes 表加 base_ts(last_synced_platform_ts)与本地脏度(last_local_modified_ts)两列,
|
|
354
|
+
// 为 serializeForSync()/import() 序列化与 base_ts 乐观锁冲突检测提供数据载体。
|
|
355
|
+
// NULL 语义(gap8):last_local_modified_ts NULL=本地无脏度(pull 不判冲突直接 import);
|
|
356
|
+
// last_synced_platform_ts NULL=首次同步(base_ts NULL 平台接受首次 push)。
|
|
357
|
+
this._migrateAddColumn('changes', 'last_synced_platform_ts', 'TEXT');
|
|
358
|
+
this._migrateAddColumn('changes', 'last_local_modified_ts', 'TEXT');
|
|
359
|
+
|
|
360
|
+
// changes 表加 title(人类可读中文标题)+ quicklog_id(关联 QUICKLOG ql-ID)两列:
|
|
361
|
+
// 让 quick-<hex> 这种机器 hash sessionId 命名的 change 行可读,DB↔QUICKLOG 可对账。
|
|
362
|
+
// quick 启动时回填(stage.js:title 从任务描述提取、quicklog_id 用分配的 qlId),
|
|
363
|
+
// --done 时从 step3「需求:」刷新 title(agent 可改)。完整流程 change 的 name 本身
|
|
364
|
+
// 已语义化,title/quicklog_id 留空。不纳入平台同步脏度(本地展示用元信息)。
|
|
365
|
+
this._migrateAddColumn('changes', 'title', 'TEXT');
|
|
366
|
+
this._migrateAddColumn('changes', 'quicklog_id', 'TEXT');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* 幂等地给表添加列(列已存在则跳过)。
|
|
371
|
+
* node:sqlite:exec() 执行 ALTER TABLE DDL;列已存在抛错被 catch 静默跳过。
|
|
372
|
+
* @private
|
|
373
|
+
*/
|
|
374
|
+
_migrateAddColumn(table, column, type) {
|
|
375
|
+
try {
|
|
376
|
+
this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${type}`);
|
|
377
|
+
} catch {
|
|
378
|
+
// 列已存在,静默跳过
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|