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,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MultiRepoContext — 跨仓 task 运行时多仓执行上下文(W1 task-01)。
|
|
3
|
+
*
|
|
4
|
+
* 设计依据:design §7.1(接口权威定义)+ 决策 D-005/D-006/D-007/D-013。
|
|
5
|
+
*
|
|
6
|
+
* 收口 execute 链路 7 个单仓假设点(applyWorktree / validateTaskReviews /
|
|
7
|
+
* runVerifyTestCheck / generateTaskReviewDrafts 等)——把"主仓=唯一仓库"假设
|
|
8
|
+
* 抽成 Map<repoKey, RepoEntry>,单仓 change 退化为 {main:{...}} 单值 map 零回归
|
|
9
|
+
* (GOAL-2),跨仓 change 实时反映各仓 HEAD(约束①)+ 配置错误 fail-closed(约束②)。
|
|
10
|
+
*
|
|
11
|
+
* 关键约束:
|
|
12
|
+
* - 约束①(D-006):跨仓仓无 meta.json,base/head 不读 meta。resolveHead 实时
|
|
13
|
+
* `git -C <crossRepo> rev-parse HEAD`(不缓存,task 推进后过期);resolveBase
|
|
14
|
+
* 用 taskBaseCommit(task 卡 base_commit 锡点,跨仓必传)。
|
|
15
|
+
* - 约束②(D-007):declaredRepos 有 key 不在 repoRegistry → throw;跨仓仓
|
|
16
|
+
* `git -C <crossRepo> rev-parse HEAD` 失败 → throw。配置错误不降级,不沿用
|
|
17
|
+
* 主仓 verifyReviewGitEvidence 的 unavailable 降级(那是环境缺失容错;跨仓
|
|
18
|
+
* 不可用是用户 local.yaml 配错,性质不同,必须阻断)。
|
|
19
|
+
* - D-013:execute 启动时构造一次,进程级缓存贯穿 execute/apply/verify(本模块
|
|
20
|
+
* 不持有进程级缓存——ctx 实例本身就是进程级单例,由 execute 入口持有)。
|
|
21
|
+
*
|
|
22
|
+
* 不涉及生命周期契约(design §7.5):纯内存对象,不跨进程、不持久化、不入库。
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { git, gitQuiet } from '../git-helper.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {Object} RepoEntry
|
|
29
|
+
* @property {string} repoKey - repo 标识('main' 或 local.yaml repos: 的键名)
|
|
30
|
+
* @property {string} gitDir - git 工作目录(rev-parse/diff/apply 的 cwd)
|
|
31
|
+
* @property {string} worktreePath - 子代理工作目录(主仓=worktreePath 或 in-place-fallback 时=cwd;跨仓=跨仓仓根)
|
|
32
|
+
* @property {string} projectRoot - apply 目标根(主仓=主仓根;跨仓=跨仓仓根,但跨仓 apply=no-op 不用)
|
|
33
|
+
* @property {boolean} isMain - 是否主仓
|
|
34
|
+
* @property {function} resolveHead - () => string,实时 git rev-parse HEAD(跨仓不缓存)
|
|
35
|
+
* @property {function} resolveBase - (taskBaseCommit?) => string,base 锚点(主仓→meta.baseHash;跨仓→taskBaseCommit 必传)
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
export class MultiRepoContext {
|
|
39
|
+
/**
|
|
40
|
+
* @param {Object} opts
|
|
41
|
+
* @param {string} opts.cwd - 主仓 cwd
|
|
42
|
+
* @param {string} opts.changeName - 当前 change 名(读 worktreeManager.getMeta)
|
|
43
|
+
* @param {Object} [opts.platformOpts] - 平台选项(specRoot 等,预留,本模块不消费)
|
|
44
|
+
* @param {string[]} opts.declaredRepos - 所有 task 卡片声明的 repo: 值(含 'main')
|
|
45
|
+
* @param {Map<string,string>} opts.repoRegistry - local.yaml repos: 段解析结果 Map<key, path>
|
|
46
|
+
* @param {Object} opts.worktreeManager - WorktreeManager 实例(主仓 meta 读取;in-place-fallback 兜底 cwd)
|
|
47
|
+
* @throws {Error} 约束②: declaredRepos 中有 repoKey 不在 repoRegistry → 抛错列已注册 repo,阻断 execute
|
|
48
|
+
* 约束②: 跨仓仓 git rev-parse 失败(路径不存在/非 git 仓)→ 抛错阻断 execute
|
|
49
|
+
*/
|
|
50
|
+
constructor({ cwd, changeName, platformOpts, declaredRepos, repoRegistry, worktreeManager }) {
|
|
51
|
+
if (!cwd) throw new Error('MultiRepoContext: cwd 必传');
|
|
52
|
+
if (!Array.isArray(declaredRepos)) throw new Error('MultiRepoContext: declaredRepos 必传为数组');
|
|
53
|
+
if (!(repoRegistry instanceof Map)) throw new Error('MultiRepoContext: repoRegistry 必传为 Map<key,path>');
|
|
54
|
+
if (!worktreeManager || typeof worktreeManager.getMeta !== 'function') {
|
|
55
|
+
throw new Error('MultiRepoContext: worktreeManager 必传(需 getMeta 方法)');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.cwd = cwd;
|
|
59
|
+
this.changeName = changeName;
|
|
60
|
+
this.platformOpts = platformOpts || {};
|
|
61
|
+
this.repoRegistry = repoRegistry;
|
|
62
|
+
this.worktreeManager = worktreeManager;
|
|
63
|
+
|
|
64
|
+
// dedupe + 保留声明顺序(同一 repo 多 task 声明只建一项)
|
|
65
|
+
const seen = new Set();
|
|
66
|
+
const orderedKeys = [];
|
|
67
|
+
for (const key of declaredRepos) {
|
|
68
|
+
if (!seen.has(key)) {
|
|
69
|
+
seen.add(key);
|
|
70
|
+
orderedKeys.push(key);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 约束② fail-closed 预检:declaredRepos ⊆ repoRegistry ∪ {'main'}
|
|
75
|
+
// main 隐式 = cwd,不要求注册;其余 key 必须在 repoRegistry 命中。
|
|
76
|
+
const unregistered = orderedKeys.filter(k => k !== 'main' && !repoRegistry.has(k));
|
|
77
|
+
if (unregistered.length > 0) {
|
|
78
|
+
const registered = ['main (隐式)', ...repoRegistry.keys()];
|
|
79
|
+
throw new Error(
|
|
80
|
+
`MultiRepoContext: 以下 repo 未在 local.yaml repos: 段注册:[${unregistered.join(', ')}]。` +
|
|
81
|
+
`当前已注册 repo:[${registered.join(', ')}]。` +
|
|
82
|
+
`一键注册(每个缺的 key 各跑一次,勿手编 YAML):` +
|
|
83
|
+
unregistered.map(k => `sillyspec local register-repo ${k} <${k} 仓根路径>`).join(';') +
|
|
84
|
+
`。补注册后再启动 execute(约束② fail-closed,跨仓 apply 走错仓=数据所有权事故)。`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const map = new Map();
|
|
89
|
+
for (const repoKey of orderedKeys) {
|
|
90
|
+
map.set(repoKey, repoKey === 'main'
|
|
91
|
+
? this._buildMainEntry()
|
|
92
|
+
: this._buildCrossRepoEntry(repoKey, repoRegistry.get(repoKey)));
|
|
93
|
+
}
|
|
94
|
+
this.map = map;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 主仓 RepoEntry:isMain=true,读 worktreeManager.getMeta 的 baseHash + worktreePath。
|
|
99
|
+
* in-place-fallback 模式(meta.mode==='in-place-fallback' 或 meta 缺失)worktreePath 兜底为 cwd。
|
|
100
|
+
* @returns {RepoEntry}
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
_buildMainEntry() {
|
|
104
|
+
const meta = this.changeName ? this.worktreeManager.getMeta(this.changeName) : null;
|
|
105
|
+
const isInPlace = !meta || meta.mode === 'in-place-fallback';
|
|
106
|
+
const worktreePath = isInPlace ? this.cwd : (meta.worktreePath || this.cwd);
|
|
107
|
+
const baseHash = meta?.baseHash || null;
|
|
108
|
+
const gitDir = worktreePath; // 主仓 git 操作 cwd = worktree(或 in-place 的 cwd)
|
|
109
|
+
const projectRoot = this.cwd;
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
repoKey: 'main',
|
|
113
|
+
gitDir,
|
|
114
|
+
worktreePath,
|
|
115
|
+
projectRoot,
|
|
116
|
+
isMain: true,
|
|
117
|
+
// 主仓 HEAD:从 worktree/cwd 实时取(不缓存)。主仓单仓不变式下也可用 meta.baseHash 作 base,
|
|
118
|
+
// 但 HEAD 反映 worktree 当前态(子代理可能 commit 推进),故实时取与跨仓一致语义。
|
|
119
|
+
resolveHead: () => git(gitDir, ['rev-parse', 'HEAD']),
|
|
120
|
+
// 主仓 base:meta.baseHash(单仓不变式,CLI 创建 worktree 时锡点)。
|
|
121
|
+
// 跨仓 base 不走这里(resolveBase 必传 taskBaseCommit,由 _buildCrossRepoEntry 闭包消费)。
|
|
122
|
+
// 主仓忽略 taskBaseCommit 参数——主仓 base 永远锚 meta.baseHash,与单仓行为一致(零回归)。
|
|
123
|
+
resolveBase: (_taskBaseCommit) => {
|
|
124
|
+
if (!baseHash) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
'MultiRepoContext: 主仓 meta.baseHash 缺失,无法解析 base。' +
|
|
127
|
+
'可能 worktree 未创建或 meta.json 损坏——请先 sillyspec worktree doctor 检查。'
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return baseHash;
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 跨仓 RepoEntry:isMain=false,gitDir=projectRoot=worktreePath=跨仓仓根。
|
|
137
|
+
* 构造时 `git -C <crossRepo> rev-parse HEAD` 必须 succeed(约束② fail-closed),
|
|
138
|
+
* 路径不存在/非 git 仓 → throw 阻断 execute。
|
|
139
|
+
* @param {string} repoKey
|
|
140
|
+
* @param {string} crossRepoPath - repoRegistry 解析出的跨仓仓绝对路径
|
|
141
|
+
* @returns {RepoEntry}
|
|
142
|
+
* @private
|
|
143
|
+
*/
|
|
144
|
+
_buildCrossRepoEntry(repoKey, crossRepoPath) {
|
|
145
|
+
if (!crossRepoPath) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
`MultiRepoContext: repo "${repoKey}" 在 local.yaml repos: 段注册但路径为空。` +
|
|
148
|
+
`请补全路径(约束② fail-closed)。`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
// 约束②:跨仓 git 必须可达。失败 = 路径不存在 / 非 git 仓 / git 异常,一律阻断。
|
|
152
|
+
// 不沿用主仓 verifyReviewGitEvidence unavailable 降级(design §9 兼容策略表)。
|
|
153
|
+
let headVerify;
|
|
154
|
+
try {
|
|
155
|
+
headVerify = git(crossRepoPath, ['rev-parse', 'HEAD']);
|
|
156
|
+
} catch (e) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`MultiRepoContext: 跨仓 repo "${repoKey}" git 不可达(路径:${crossRepoPath})。` +
|
|
159
|
+
`rev-parse HEAD 失败:${e.message}。` +
|
|
160
|
+
`请检查 local.yaml repos: 段路径是否正确、目录是否存在且为 git 仓(约束② fail-closed,配置错误不降级)。`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (!headVerify) {
|
|
164
|
+
// git() 返回空串属异常态(无 commit 的空仓 rev-parse HEAD 会非零退出,已被 catch 兜底),
|
|
165
|
+
// 此处仅作防御性双保险,触发同样走 fail-closed。
|
|
166
|
+
throw new Error(
|
|
167
|
+
`MultiRepoContext: 跨仓 repo "${repoKey}"(${crossRepoPath})rev-parse HEAD 返回空——` +
|
|
168
|
+
`疑似空 git 仓(无 commit)。跨仓 task 需仓库已有至少一个 commit(约束② fail-closed)。`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
repoKey,
|
|
174
|
+
gitDir: crossRepoPath,
|
|
175
|
+
worktreePath: crossRepoPath,
|
|
176
|
+
projectRoot: crossRepoPath,
|
|
177
|
+
isMain: false,
|
|
178
|
+
// 约束①:跨仓 HEAD 实时取,不缓存(task 推进后过期,每次 resolveHead 反映最新 HEAD)。
|
|
179
|
+
resolveHead: () => git(crossRepoPath, ['rev-parse', 'HEAD']),
|
|
180
|
+
// 约束①:跨仓 base = task 卡 base_commit 锡点(必传)。跨仓仓无 meta.json,
|
|
181
|
+
// 不读 meta;taskBaseCommit 由 task-02 DeclaredRepos 之外的 task 卡 frontmatter 提供。
|
|
182
|
+
resolveBase: (taskBaseCommit) => {
|
|
183
|
+
if (!taskBaseCommit) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`MultiRepoContext: 跨仓 repo "${repoKey}" resolveBase 必传 taskBaseCommit(task 卡 base_commit 锡点)。` +
|
|
186
|
+
`跨仓仓无 meta.json,base 只能由 task 卡片锡点提供(约束①)。`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
return taskBaseCommit;
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** @returns {RepoEntry|null} */
|
|
195
|
+
resolve(repoKey) {
|
|
196
|
+
return this.map.get(repoKey) || null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** @returns {Map<string, RepoEntry>} */
|
|
200
|
+
get repos() {
|
|
201
|
+
return this.map;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** @returns {boolean} 是否含跨仓 task(map.size>1,execute prompt 分叉用) */
|
|
205
|
+
hasCrossRepo() {
|
|
206
|
+
return this.map.size > 1;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* next.js — `sillyspec next` 项目状态探测(吸收 continue/resume 两个 skill 的手工探测表,
|
|
3
|
+
* 2026-08-21 agent-手工产出审计第二批 G7/G8)。
|
|
4
|
+
*
|
|
5
|
+
* 两个 skill 各自维护一套「文件存在性状态机」推断表且内容重复,agent 每次手工跑
|
|
6
|
+
* ls/cat 探测再查表——纯机械探测是 CLI 的本职。本模块输出「状态描述 + 下一步命令 +
|
|
7
|
+
* 依据文件」,agent 按输出执行即可;skill 保留作兜底(CLI 不可用/输出异常时)。
|
|
8
|
+
*
|
|
9
|
+
* 纯 fs 探测(零 DB 依赖、零 token、快):进度库的权威状态归 `sillyspec progress show`,
|
|
10
|
+
* 本命令管「没有活跃进度时从产物文件反推该干什么」。决策表(两个 skill 合并):
|
|
11
|
+
*
|
|
12
|
+
* 1. HANDOFF.json 存在 → 交接恢复
|
|
13
|
+
* 2. 活跃变更(changes/ 非 archive)逐个推断:
|
|
14
|
+
* 无文件→补 proposal / 无 design.md→brainstorm / 无 tasks.md→brainstorm 末步 /
|
|
15
|
+
* 无 plan.md→plan / tasks.md 有未勾→execute / 全勾无 verify-result.md→verify /
|
|
16
|
+
* 有 verify-result.md→archive
|
|
17
|
+
* 3. 有 docs/<p>/scan/ 无活跃变更 → brainstorm(已扫描待开变更)
|
|
18
|
+
* 4. 有 REQUIREMENTS.md/ROADMAP.md 无变更 → brainstorm(绿地已有需求)
|
|
19
|
+
* 5. 什么都没有 → init(新项目)或 scan(棕地)
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync, readdirSync, readFileSync } from 'fs'
|
|
22
|
+
import { join } from 'path'
|
|
23
|
+
import { resolveSpecDir } from './shared.js'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 数 tasks.md checkbox:返回 { checked, total }(无文件 → {checked:0,total:0})
|
|
27
|
+
*/
|
|
28
|
+
function countTasks(tasksPath) {
|
|
29
|
+
if (!existsSync(tasksPath)) return { checked: 0, total: 0 }
|
|
30
|
+
let checked = 0
|
|
31
|
+
let total = 0
|
|
32
|
+
for (const line of readFileSync(tasksPath, 'utf8').split('\n')) {
|
|
33
|
+
const m = line.match(/^[-*]\s*\[([ xX])\]\s*task-\d+\b/)
|
|
34
|
+
if (!m) continue
|
|
35
|
+
total++
|
|
36
|
+
if (m[1] !== ' ') checked++
|
|
37
|
+
}
|
|
38
|
+
return { checked, total }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 单个活跃变更的产物推断:返回 { state, next, evidence }
|
|
43
|
+
*/
|
|
44
|
+
function inferChange(changeDir, name) {
|
|
45
|
+
const has = (f) => existsSync(join(changeDir, f))
|
|
46
|
+
const ev = (f) => join('.sillyspec', 'changes', name, f)
|
|
47
|
+
const t = countTasks(join(changeDir, 'tasks.md'))
|
|
48
|
+
|
|
49
|
+
if (!has('proposal.md') && !has('design.md') && !has('tasks.md') && !has('plan.md')) {
|
|
50
|
+
return { state: `${name}:变更目录为空`, next: 'sillyspec run brainstorm(完善 proposal)或清理该空目录', evidence: [ev('(无产物)')] }
|
|
51
|
+
}
|
|
52
|
+
if (!has('design.md')) {
|
|
53
|
+
return { state: `${name}:有 proposal 缺 design.md`, next: `sillyspec run brainstorm --change ${name}(推进到设计产物)`, evidence: [ev('proposal.md')] }
|
|
54
|
+
}
|
|
55
|
+
if (!has('tasks.md')) {
|
|
56
|
+
return { state: `${name}:有 design 缺 tasks.md`, next: `sillyspec run brainstorm --change ${name}(末步生成规范文件)`, evidence: [ev('design.md')] }
|
|
57
|
+
}
|
|
58
|
+
if (!has('plan.md')) {
|
|
59
|
+
return { state: `${name}:有 tasks.md 缺 plan.md`, next: `sillyspec run plan --change ${name}`, evidence: [ev('tasks.md')] }
|
|
60
|
+
}
|
|
61
|
+
if (t.total > 0 && t.checked < t.total) {
|
|
62
|
+
return {
|
|
63
|
+
state: `${name}:执行中(task ${t.checked}/${t.total})`,
|
|
64
|
+
next: `sillyspec run execute --change ${name}`,
|
|
65
|
+
evidence: [ev('plan.md'), ev('tasks.md')],
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!has('verify-result.md')) {
|
|
69
|
+
return { state: `${name}:task 全勾,待验证`, next: `sillyspec run verify --change ${name}`, evidence: [ev('tasks.md'), ev('plan.md')] }
|
|
70
|
+
}
|
|
71
|
+
return { state: `${name}:已验证,待归档`, next: `sillyspec run archive --change ${name}`, evidence: [ev('verify-result.md')] }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 探测当前项目状态与下一步命令。
|
|
76
|
+
* @param {{ cwd: string, specDir?: string|null }} opts
|
|
77
|
+
* @returns {{ state: string, next: string, evidence: string[], activeChanges: Array<{name,checked,total}> }}
|
|
78
|
+
* activeChanges 附带各变更 task 勾选进度(供 --json 消费);evidence 为相对 spec 根的路径
|
|
79
|
+
*/
|
|
80
|
+
export function detectNextStep({ cwd, specDir = null }) {
|
|
81
|
+
const specBase = resolveSpecDir(cwd, { specDir })
|
|
82
|
+
const changesRoot = join(specBase, 'changes')
|
|
83
|
+
|
|
84
|
+
// 1. HANDOFF 交接
|
|
85
|
+
for (const handoff of [join(cwd, 'HANDOFF.json'), join(specBase, 'HANDOFF.json')]) {
|
|
86
|
+
if (existsSync(handoff)) {
|
|
87
|
+
return { state: '存在 HANDOFF.json(上次会话交接)', next: '读 HANDOFF.json 后从交接点继续(sillyspec progress show 看活跃进度)', evidence: [handoff], activeChanges: [] }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 2. 活跃变更(排除 archive)
|
|
92
|
+
let active = []
|
|
93
|
+
try {
|
|
94
|
+
active = readdirSync(changesRoot, { withFileTypes: true })
|
|
95
|
+
.filter(e => e.isDirectory() && e.name !== 'archive')
|
|
96
|
+
.map(e => e.name)
|
|
97
|
+
.sort()
|
|
98
|
+
} catch { /* 无 changes/ 目录 */ }
|
|
99
|
+
if (active.length > 0) {
|
|
100
|
+
// 多活跃时逐个推断全报告,next 取第一个(字典序最前)的;调用方输出含全部状态行
|
|
101
|
+
const inferences = active.map(name => inferChange(join(changesRoot, name), name))
|
|
102
|
+
const progress = active.map((name, i) => {
|
|
103
|
+
const t = countTasks(join(changesRoot, name, 'tasks.md'))
|
|
104
|
+
return { name, checked: t.checked, total: t.total, state: inferences[i].state }
|
|
105
|
+
})
|
|
106
|
+
return { state: inferences.map(i => i.state).join(';'), next: inferences[0].next, evidence: inferences[0].evidence, activeChanges: progress }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 3. 已扫描无变更
|
|
110
|
+
const docsDir = join(specBase, 'docs')
|
|
111
|
+
try {
|
|
112
|
+
const scanned = readdirSync(docsDir, { withFileTypes: true })
|
|
113
|
+
.filter(e => e.isDirectory() && existsSync(join(docsDir, e.name, 'scan')))
|
|
114
|
+
if (scanned.length > 0) {
|
|
115
|
+
return { state: `已扫描(${scanned.length} 个项目文档),无活跃变更`, next: 'sillyspec run brainstorm "你的想法"', evidence: [join('.sillyspec', 'docs', scanned[0].name, 'scan')], activeChanges: [] }
|
|
116
|
+
}
|
|
117
|
+
} catch { /* 无 docs/ */ }
|
|
118
|
+
|
|
119
|
+
// 4. 绿地已有需求
|
|
120
|
+
for (const f of ['REQUIREMENTS.md', 'ROADMAP.md']) {
|
|
121
|
+
if (existsSync(join(specBase, f))) {
|
|
122
|
+
return { state: `绿地项目已有 ${f},无活跃变更`, next: 'sillyspec run brainstorm "你的想法"', evidence: [join('.sillyspec', f)], activeChanges: [] }
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 5. 什么都没有
|
|
127
|
+
return { state: '未初始化(无 .sillyspec 产物)', next: 'sillyspec init(新项目)或 sillyspec scan(棕地项目)', evidence: [], activeChanges: [] }
|
|
128
|
+
}
|