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.
Files changed (398) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +8 -0
  2. package/.claude/skills/sillyspec-quick/SKILL.md +2 -1
  3. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  4. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  5. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  6. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  7. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  8. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  9. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  10. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  11. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +57 -0
  12. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +177 -0
  13. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  14. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  15. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  16. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  17. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  18. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +64 -0
  19. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +54 -0
  20. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  21. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  22. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +2 -0
  23. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +20 -0
  24. package/.claude/worktrees/sillyspec-data-model-research/README.md +203 -0
  25. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +91 -0
  26. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +2 -0
  27. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  28. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +977 -0
  29. package/.claude/worktrees/sillyspec-data-model-research/package.json +39 -0
  30. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  31. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  32. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  33. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +16 -0
  34. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  35. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +836 -0
  36. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +256 -0
  37. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +25 -0
  38. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +95 -0
  39. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +679 -0
  40. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +526 -0
  41. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +357 -0
  42. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +803 -0
  43. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +290 -0
  44. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +270 -0
  45. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +65 -0
  46. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +109 -0
  47. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +202 -0
  48. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +88 -0
  49. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +328 -0
  50. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +97 -0
  51. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +480 -0
  52. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +20 -0
  53. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +55 -0
  54. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +381 -0
  55. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +517 -0
  56. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +155 -0
  57. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +245 -0
  58. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +246 -0
  59. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +121 -0
  60. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +825 -0
  61. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +393 -0
  62. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +107 -0
  63. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +1099 -0
  64. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +420 -0
  65. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +78 -0
  66. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +73 -0
  67. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +150 -0
  68. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +130 -0
  69. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +892 -0
  70. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +2798 -0
  71. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +626 -0
  72. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +231 -0
  73. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +128 -0
  74. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +104 -0
  75. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +543 -0
  76. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +127 -0
  77. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +166 -0
  78. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +222 -0
  79. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +580 -0
  80. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +336 -0
  81. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +355 -0
  82. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +36 -0
  83. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +594 -0
  84. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +265 -0
  85. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +1304 -0
  86. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +115 -0
  87. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +852 -0
  88. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +77 -0
  89. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +1595 -0
  90. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +1552 -0
  91. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +1259 -0
  92. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +156 -0
  93. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +1084 -0
  94. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +208 -0
  95. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +128 -0
  96. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +843 -0
  97. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +186 -0
  98. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +269 -0
  99. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +1562 -0
  100. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +584 -0
  101. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +23 -0
  102. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +388 -0
  103. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +512 -0
  104. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +95 -0
  105. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +414 -0
  106. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +597 -0
  107. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +62 -0
  108. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +50 -0
  109. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +358 -0
  110. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +171 -0
  111. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +550 -0
  112. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +889 -0
  113. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +597 -0
  114. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +199 -0
  115. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +236 -0
  116. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +617 -0
  117. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +145 -0
  118. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +540 -0
  119. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +1275 -0
  120. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +43 -0
  121. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +29 -0
  122. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +514 -0
  123. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +1344 -0
  124. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +650 -0
  125. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +167 -0
  126. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +608 -0
  127. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +64 -0
  128. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +246 -0
  129. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +1470 -0
  130. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +1498 -0
  131. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +210 -0
  132. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +1718 -0
  133. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +277 -0
  134. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +19 -0
  135. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +600 -0
  136. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +125 -0
  137. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +1446 -0
  138. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +576 -0
  139. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +1715 -0
  140. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +23 -0
  141. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +28 -0
  142. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +12 -0
  143. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +32 -0
  144. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +79 -0
  145. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +132 -0
  146. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  147. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  148. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  149. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  150. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  151. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  152. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  153. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  154. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +57 -0
  155. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +177 -0
  156. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  157. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  158. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  159. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  160. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  161. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  162. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +64 -0
  163. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +54 -0
  164. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  165. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  166. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +6 -0
  167. package/.worktrees/8d2d0392/.gitattributes +2 -0
  168. package/.worktrees/8d2d0392/.husky/pre-push +20 -0
  169. package/.worktrees/8d2d0392/README.md +203 -0
  170. package/.worktrees/8d2d0392/SKILL.md +91 -0
  171. package/.worktrees/8d2d0392/architecture-analysis.md +448 -0
  172. package/.worktrees/8d2d0392/bin/sillyspec.js +2 -0
  173. package/.worktrees/8d2d0392/eval/README.md +86 -0
  174. package/.worktrees/8d2d0392/eval/eval.config.json +28 -0
  175. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +63 -0
  176. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +27 -0
  177. package/.worktrees/8d2d0392/eval/lib/config.mjs +82 -0
  178. package/.worktrees/8d2d0392/eval/lib/db.mjs +76 -0
  179. package/.worktrees/8d2d0392/eval/lib/report.mjs +120 -0
  180. package/.worktrees/8d2d0392/eval/lib/runner.mjs +157 -0
  181. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +73 -0
  182. package/.worktrees/8d2d0392/eval/lib/util.mjs +107 -0
  183. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +30 -0
  184. package/.worktrees/8d2d0392/eval/run.mjs +83 -0
  185. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +6 -0
  186. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  187. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +6 -0
  188. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +28 -0
  189. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +6 -0
  190. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  191. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  192. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +6 -0
  193. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +31 -0
  194. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  195. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +6 -0
  196. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  197. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +6 -0
  198. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +38 -0
  199. package/.worktrees/8d2d0392/logo.jpg +0 -0
  200. package/.worktrees/8d2d0392/package-lock.json +977 -0
  201. package/.worktrees/8d2d0392/package.json +41 -0
  202. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  203. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  204. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  205. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +16 -0
  206. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  207. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +836 -0
  208. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +256 -0
  209. package/.worktrees/8d2d0392/packages/dashboard/package.json +25 -0
  210. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +95 -0
  211. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +679 -0
  212. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +526 -0
  213. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +357 -0
  214. package/.worktrees/8d2d0392/src/agent-session-log.js +803 -0
  215. package/.worktrees/8d2d0392/src/change-list.js +290 -0
  216. package/.worktrees/8d2d0392/src/change-risk-profile.js +339 -0
  217. package/.worktrees/8d2d0392/src/check-primitives.js +65 -0
  218. package/.worktrees/8d2d0392/src/classify-change.js +109 -0
  219. package/.worktrees/8d2d0392/src/commit-suggest.js +202 -0
  220. package/.worktrees/8d2d0392/src/config-cat.js +88 -0
  221. package/.worktrees/8d2d0392/src/config-schema.js +328 -0
  222. package/.worktrees/8d2d0392/src/constants.js +97 -0
  223. package/.worktrees/8d2d0392/src/contract-matrix.js +533 -0
  224. package/.worktrees/8d2d0392/src/datetime.js +20 -0
  225. package/.worktrees/8d2d0392/src/db-engine.js +55 -0
  226. package/.worktrees/8d2d0392/src/db.js +381 -0
  227. package/.worktrees/8d2d0392/src/decision-distill.js +517 -0
  228. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +155 -0
  229. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +245 -0
  230. package/.worktrees/8d2d0392/src/dispatch/probe.js +246 -0
  231. package/.worktrees/8d2d0392/src/dispatch/strategy.js +121 -0
  232. package/.worktrees/8d2d0392/src/docs-check.js +825 -0
  233. package/.worktrees/8d2d0392/src/docs-debt.js +393 -0
  234. package/.worktrees/8d2d0392/src/docs-gate.js +107 -0
  235. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +1099 -0
  236. package/.worktrees/8d2d0392/src/endpoint-extractor.js +409 -0
  237. package/.worktrees/8d2d0392/src/foreign-declared.js +78 -0
  238. package/.worktrees/8d2d0392/src/fs-atomic.js +73 -0
  239. package/.worktrees/8d2d0392/src/git-helper.js +150 -0
  240. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +130 -0
  241. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +892 -0
  242. package/.worktrees/8d2d0392/src/index.js +2854 -0
  243. package/.worktrees/8d2d0392/src/init.js +626 -0
  244. package/.worktrees/8d2d0392/src/knowledge-match.js +231 -0
  245. package/.worktrees/8d2d0392/src/local-detect.js +128 -0
  246. package/.worktrees/8d2d0392/src/local-register.js +104 -0
  247. package/.worktrees/8d2d0392/src/machine-interface.js +543 -0
  248. package/.worktrees/8d2d0392/src/migrate.js +127 -0
  249. package/.worktrees/8d2d0392/src/module-impact.js +166 -0
  250. package/.worktrees/8d2d0392/src/module-resolve.js +222 -0
  251. package/.worktrees/8d2d0392/src/modules.js +580 -0
  252. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +126 -0
  253. package/.worktrees/8d2d0392/src/progress/change-registry.js +336 -0
  254. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +355 -0
  255. package/.worktrees/8d2d0392/src/progress/shared.js +36 -0
  256. package/.worktrees/8d2d0392/src/progress/stage-machine.js +594 -0
  257. package/.worktrees/8d2d0392/src/progress/step-store.js +265 -0
  258. package/.worktrees/8d2d0392/src/progress.js +1304 -0
  259. package/.worktrees/8d2d0392/src/quick-recommend.js +115 -0
  260. package/.worktrees/8d2d0392/src/quicklog.js +883 -0
  261. package/.worktrees/8d2d0392/src/review-tier.js +77 -0
  262. package/.worktrees/8d2d0392/src/run/command.js +1641 -0
  263. package/.worktrees/8d2d0392/src/run/complete-handlers.js +1552 -0
  264. package/.worktrees/8d2d0392/src/run/complete.js +1259 -0
  265. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +156 -0
  266. package/.worktrees/8d2d0392/src/run/gates.js +1094 -0
  267. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +208 -0
  268. package/.worktrees/8d2d0392/src/run/next.js +128 -0
  269. package/.worktrees/8d2d0392/src/run/prompt.js +843 -0
  270. package/.worktrees/8d2d0392/src/run/quick-audit.js +186 -0
  271. package/.worktrees/8d2d0392/src/run/scan-profile.js +269 -0
  272. package/.worktrees/8d2d0392/src/run/shared.js +1562 -0
  273. package/.worktrees/8d2d0392/src/run/stage.js +587 -0
  274. package/.worktrees/8d2d0392/src/run.js +23 -0
  275. package/.worktrees/8d2d0392/src/scan-diff.js +388 -0
  276. package/.worktrees/8d2d0392/src/scan-postcheck.js +524 -0
  277. package/.worktrees/8d2d0392/src/scan-staleness.js +95 -0
  278. package/.worktrees/8d2d0392/src/setup.js +414 -0
  279. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +597 -0
  280. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +62 -0
  281. package/.worktrees/8d2d0392/src/spec-dir-typo.js +50 -0
  282. package/.worktrees/8d2d0392/src/spec-sync.js +358 -0
  283. package/.worktrees/8d2d0392/src/stage-contract-engine.js +171 -0
  284. package/.worktrees/8d2d0392/src/stage-contract-spec.js +551 -0
  285. package/.worktrees/8d2d0392/src/stage-contract.js +948 -0
  286. package/.worktrees/8d2d0392/src/stage-review.js +597 -0
  287. package/.worktrees/8d2d0392/src/stages/archive.js +199 -0
  288. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +285 -0
  289. package/.worktrees/8d2d0392/src/stages/brainstorm.js +624 -0
  290. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +145 -0
  291. package/.worktrees/8d2d0392/src/stages/doctor.js +540 -0
  292. package/.worktrees/8d2d0392/src/stages/execute.js +1277 -0
  293. package/.worktrees/8d2d0392/src/stages/explore.js +43 -0
  294. package/.worktrees/8d2d0392/src/stages/index.js +29 -0
  295. package/.worktrees/8d2d0392/src/stages/knowledge.js +514 -0
  296. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +1398 -0
  297. package/.worktrees/8d2d0392/src/stages/plan.js +651 -0
  298. package/.worktrees/8d2d0392/src/stages/quick.js +167 -0
  299. package/.worktrees/8d2d0392/src/stages/scan.js +608 -0
  300. package/.worktrees/8d2d0392/src/stages/status.js +64 -0
  301. package/.worktrees/8d2d0392/src/stages/verify.js +246 -0
  302. package/.worktrees/8d2d0392/src/sync.js +1470 -0
  303. package/.worktrees/8d2d0392/src/task-review.js +1498 -0
  304. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +21 -0
  305. package/.worktrees/8d2d0392/src/taskcard.js +217 -0
  306. package/.worktrees/8d2d0392/src/verify-postcheck.js +1718 -0
  307. package/.worktrees/8d2d0392/src/verify-probes.js +327 -0
  308. package/.worktrees/8d2d0392/src/version.js +19 -0
  309. package/.worktrees/8d2d0392/src/workflow.js +600 -0
  310. package/.worktrees/8d2d0392/src/workspace.js +125 -0
  311. package/.worktrees/8d2d0392/src/worktree-apply.js +1611 -0
  312. package/.worktrees/8d2d0392/src/worktree-deps.js +576 -0
  313. package/.worktrees/8d2d0392/src/worktree.js +1838 -0
  314. package/.worktrees/8d2d0392/templates/claude-instruction.md +23 -0
  315. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +29 -0
  316. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +12 -0
  317. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +32 -0
  318. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +79 -0
  319. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +132 -0
  320. package/architecture-analysis.md +448 -0
  321. package/eval/README.md +86 -0
  322. package/eval/eval.config.json +28 -0
  323. package/eval/lib/adapters/cli.mjs +63 -0
  324. package/eval/lib/adapters/dryrun.mjs +27 -0
  325. package/eval/lib/config.mjs +82 -0
  326. package/eval/lib/db.mjs +76 -0
  327. package/eval/lib/report.mjs +120 -0
  328. package/eval/lib/runner.mjs +157 -0
  329. package/eval/lib/tasks.mjs +73 -0
  330. package/eval/lib/util.mjs +107 -0
  331. package/eval/lib/workdir.mjs +30 -0
  332. package/eval/run.mjs +83 -0
  333. package/eval/tasks/001-slugify/files/package.json +6 -0
  334. package/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  335. package/eval/tasks/001-slugify/task.json +6 -0
  336. package/eval/tasks/001-slugify/verify.mjs +28 -0
  337. package/eval/tasks/002-each-day/files/package.json +6 -0
  338. package/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  339. package/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  340. package/eval/tasks/002-each-day/task.json +6 -0
  341. package/eval/tasks/002-each-day/verify.mjs +31 -0
  342. package/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  343. package/eval/tasks/003-word-report/files/package.json +6 -0
  344. package/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  345. package/eval/tasks/003-word-report/task.json +6 -0
  346. package/eval/tasks/003-word-report/verify.mjs +38 -0
  347. package/package.json +4 -2
  348. package/src/agent-session-log.js +45 -5
  349. package/src/change-risk-profile.js +83 -14
  350. package/src/config-schema.js +18 -3
  351. package/src/contract-matrix.js +90 -29
  352. package/src/datetime.js +20 -0
  353. package/src/decision-distill.js +517 -0
  354. package/src/dispatch/backends/local-agent.js +4 -4
  355. package/src/docs-check.js +227 -0
  356. package/src/docs-debt.js +187 -24
  357. package/src/doctor-diagnostics.js +102 -2
  358. package/src/endpoint-extractor.js +41 -52
  359. package/src/foreign-declared.js +155 -0
  360. package/src/index.js +95 -13
  361. package/src/init.js +9 -7
  362. package/src/knowledge-match.js +107 -6
  363. package/src/local-register.js +7 -1
  364. package/src/module-resolve.js +12 -1
  365. package/src/modules.js +2 -1
  366. package/src/plan-adopt-waves.js +126 -0
  367. package/src/quicklog.js +50 -4
  368. package/src/run/command.js +124 -44
  369. package/src/run/complete-handlers.js +48 -19
  370. package/src/run/complete.js +5 -2
  371. package/src/run/gates.js +104 -22
  372. package/src/run/prompt.js +84 -42
  373. package/src/run/quick-audit.js +11 -0
  374. package/src/run/shared.js +152 -10
  375. package/src/run/stage.js +8 -5
  376. package/src/run.js +2 -2
  377. package/src/scan-postcheck.js +30 -17
  378. package/src/stage-contract-spec.js +3 -2
  379. package/src/stage-contract.js +68 -4
  380. package/src/stages/archive.js +53 -12
  381. package/src/stages/brainstorm-auto.js +50 -1
  382. package/src/stages/brainstorm.js +13 -0
  383. package/src/stages/doctor.js +157 -1
  384. package/src/stages/execute.js +32 -6
  385. package/src/stages/plan-postcheck.js +76 -17
  386. package/src/stages/plan.js +9 -4
  387. package/src/stages/quick.js +6 -1
  388. package/src/stages/verify.js +32 -15
  389. package/src/sync.js +41 -3
  390. package/src/task-review.js +2 -2
  391. package/src/taskcard-placeholders.js +21 -0
  392. package/src/taskcard.js +43 -1
  393. package/src/verify-postcheck.js +315 -13
  394. package/src/verify-probes.js +73 -10
  395. package/src/worktree-apply.js +569 -227
  396. package/src/worktree-deps.js +150 -1
  397. package/src/worktree.js +285 -77
  398. package/templates/prompts/taskcard-rules.md +2 -1
package/src/worktree.js CHANGED
@@ -9,10 +9,10 @@
9
9
  */
10
10
 
11
11
  import { execFileSync } from 'child_process';
12
- import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync, readdirSync, statSync, lstatSync, readlinkSync, unlinkSync } from 'fs';
12
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync, readdirSync, statSync, lstatSync, readlinkSync, unlinkSync, copyFileSync } from 'fs';
13
13
  import { join, resolve, dirname, relative, isAbsolute } from 'path';
14
14
  import { createHash } from 'crypto';
15
- import { provisionDeps, checkDepsFreshness } from './worktree-deps.js';
15
+ import { provisionDeps, checkDepsFreshness, detectEditableInstallEscape } from './worktree-deps.js';
16
16
  import { writeAtomicSync } from './fs-atomic.js';
17
17
  import { git, gitQuiet } from './git-helper.js';
18
18
 
@@ -24,6 +24,65 @@ const WORKTREES_REL = '.sillyspec/.runtime/worktrees';
24
24
  const BRANCH_PREFIX = 'sillyspec/';
25
25
  const META_FILE = 'meta.json';
26
26
 
27
+ /**
28
+ * 解除 worktree 内全部 node_modules junction/symlink(根 + meta.depsModules 各子模块)。
29
+ *
30
+ * 坑 ghost-dir-junction-pierce(2026-08-23 实证:worktree apply 后目录残留,人工 rm -rf 经
31
+ * junction 穿透删主仓 node_modules——user-inputs 两次事故实录;npm ci / git worktree remove
32
+ * 同样跟随 junction)。任何删除 worktree 目录的路径(cleanup / create 幽灵强删 / doctor 修复)
33
+ * 必须先解链;此前解链逻辑三处复制粘贴且**不覆盖 modules 子模块 junction**
34
+ * (meta.depsModules 记录的 wt/<module>/node_modules)。
35
+ *
36
+ * lstat/rmdir 失败 fail-loud(D-001@v1:静默跳过解链的后果是穿透删主仓,宁可阻断)。
37
+ *
38
+ * @param {string} worktreePath worktree 根目录
39
+ * @param {object} [meta] 可含 depsModules([{path}] 子模块清单);null 时只解根
40
+ * @param {string[]} [details] 可选,记录解链明细(cleanup details 兼容)
41
+ * @returns {number} 实际解除的链接数
42
+ */
43
+ export function unlinkNodeModulesLinks(worktreePath, meta = null, details = null) {
44
+ let removed = 0;
45
+ const targets = [join(worktreePath, 'node_modules')];
46
+ for (const m of Array.isArray(meta && meta.depsModules) ? meta.depsModules : []) {
47
+ // 子模块 path 安全校验(与 worktree-deps isSafeModulePath 同口径):拒绝绝对路径与 .. 段
48
+ if (m && typeof m.path === 'string' && m.path && !isAbsolute(m.path) && !m.path.split(/[\\/]+/).includes('..')) {
49
+ targets.push(join(worktreePath, m.path, 'node_modules'));
50
+ }
51
+ }
52
+ for (const nm of targets) {
53
+ if (!existsSync(nm)) continue;
54
+ let isLink;
55
+ try {
56
+ isLink = lstatSync(nm).isSymbolicLink();
57
+ } catch (e) {
58
+ throw new Error(`worktree node_modules junction 检测失败(疑似 EPERM:杀毒/索引锁 junction),阻断删除以保护主仓 node_modules:${e.message}。请关闭占用进程或手动 rmdir "${nm}" 后重试`);
59
+ }
60
+ if (!isLink) continue;
61
+ try {
62
+ if (process.platform === 'win32') {
63
+ // Windows rmdir 删 junction(reparse point)不跟随目标;execFileSync 数组形式不经 shell
64
+ execFileSync('cmd.exe', ['/c', 'rmdir', nm]);
65
+ } else {
66
+ unlinkSync(nm);
67
+ }
68
+ removed++;
69
+ if (details) details.push(`worktree node_modules junction/symlink removed: ${relative(worktreePath, nm) || '(root)'} (protect main checkout)`);
70
+ } catch (e) {
71
+ throw new Error(`worktree node_modules junction 解链失败,阻断删除以保护主仓 node_modules:${e.message}。请手动 rmdir "${nm}" 后重试`);
72
+ }
73
+ }
74
+ return removed;
75
+ }
76
+
77
+ /**
78
+ * 安全删除 worktree 目录:先解链全部 node_modules junction 再 rmSync。
79
+ * 幽灵目录清理(create 强删 / doctor ghost 修复)的统一出口——不再裸 rmSync。
80
+ */
81
+ export function safeRemoveWorktreeDir(worktreePath, meta = null) {
82
+ unlinkNodeModulesLinks(worktreePath, meta);
83
+ rmSync(worktreePath, { recursive: true, force: true });
84
+ }
85
+
27
86
  // 进程级缓存:cwd → 主仓库根目录。避免每次 new WorktreeManager 都 spawn 一次
28
87
  // `git rev-parse --git-common-dir`(Windows 上每次 spawn 约 30-100ms,execute 一次命令
29
88
  // 会 new 多个 WorktreeManager)。git-common-dir 在进程内对同一 cwd 稳定,缓存安全。
@@ -357,7 +416,7 @@ export class WorktreeManager {
357
416
  * @returns {{ branch: string, worktreePath: string, baseHash: string }}
358
417
  * @throws {Error} worktree 已存在、git 不可用、changeName 为空
359
418
  */
360
- create(changeName, { base } = {}) {
419
+ create(changeName, { base, adoptBranch = false } = {}) {
361
420
  const name = validateChangeName(changeName);
362
421
  const worktreePath = this.getWorktreePath(name);
363
422
  const branch = BRANCH_PREFIX + name;
@@ -416,19 +475,35 @@ export class WorktreeManager {
416
475
  );
417
476
  }
418
477
  console.log(`⚠️ 检测到幽灵 worktree 目录(无 meta.json,无未提交改动),自动清理...`);
419
- try { rmSync(worktreePath, { recursive: true, force: true }); } catch {}
420
- // 同步清理 git worktree 注册 + 残留分支,否则目录虽删但 git 内部状态未清,
421
- // 后续 git worktree add 会因「worktree 已注册」或「分支已存在」失败
478
+ // 安全删除(坑 ghost-dir-junction-pierce):git status 拦不住 junction(gitignored 的
479
+ // node_modules 不进 status,junction 目标内容更非「未提交改动」),裸 rmSync/人工 rm -rf
480
+ // 会穿透 junction 删主仓 node_modules——先解链再删。
481
+ try { safeRemoveWorktreeDir(worktreePath); } catch (unlinkErr) {
482
+ throw new Error(`幽灵 worktree 安全清理失败(已阻断,主仓 node_modules 未受影响):${unlinkErr.message}`)
483
+ }
484
+ // 同步清理 git worktree 注册(git 内部状态),否则后续 worktree add 会因「已注册」失败。
485
+ // 不再盲删同名分支(坑 worktree-user-branch-conflict,2026-08-24 用户反馈五期①:该分支
486
+ // 可能是用户有意创建的,无凭据区分遗留 vs 自建——统一交由下方分支决策菜单处置)。
422
487
  try { gitQuiet(this.cwd, ['worktree', 'prune'], { timeout: 30000 }); } catch {}
423
- try { gitQuiet(this.cwd, ['branch', '-D', branch]); } catch {}
424
488
  } else {
425
489
  throw new Error(`worktree already exists: ${name}. Run cleanup first.`);
426
490
  }
427
491
  }
428
492
 
429
- // 2. 检查分支是否已存在
430
- if (gitQuiet(this.cwd, ['rev-parse', '--verify', `refs/heads/${branch}`])) {
431
- throw new Error(`branch already exists: ${branch}. Run cleanup first.`);
493
+ // 2. 检查分支是否已存在(坑 worktree-user-branch-conflict,2026-08-24 用户反馈五期①:
494
+ // 「用户要求在指定分支上做」时既有同名分支让 execute 直接死锁,旧报错只说 Run cleanup
495
+ // first、修复建议无条件推荐删分支——用户自建分支被引导误删。现给决策菜单;--adopt-branch
496
+ // 显式收编:检出该分支为 worktree 工作分支,分支现状作 baseline,仅后续新改动计入交付。)
497
+ const branchExists = !!gitQuiet(this.cwd, ['rev-parse', '--verify', `refs/heads/${branch}`]);
498
+ let adoptedBranch = false;
499
+ if (branchExists && !adoptBranch) {
500
+ throw new Error(
501
+ `分支已存在:${branch}(worktree create 需新建同名分支,直接冲突)。按实际情况三选一:\n` +
502
+ ` ① 本变更的遗留分支(上次 execute 残留、内容已落地或作废):确认后 git branch -D ${branch} 再重跑;\n` +
503
+ ` ② 该分支是你有意让本变更在其上做的(用户指定分支):sillyspec run execute --change ${name} --adopt-branch\n` +
504
+ ` —— 收编为 worktree 工作分支,分支既有内容计入 baseline(仅后续新改动算交付 diff);\n` +
505
+ ` ③ 换变更名重跑。`
506
+ );
432
507
  }
433
508
 
434
509
  // 3. 解析 base 分支
@@ -457,7 +532,17 @@ export class WorktreeManager {
457
532
 
458
533
  // 5. 创建 worktree(含版本检测 + sandbox fallback)
459
534
  try {
460
- git(this.cwd, ['worktree', 'add', worktreePath, '-b', branch, baseHash], { timeout: 120000 });
535
+ if (branchExists && adoptBranch) {
536
+ // --adopt-branch 收编(坑 worktree-user-branch-conflict):检出既有分支为工作分支(不 -b),
537
+ // 分支当前 HEAD 作 baseHash——分支存量内容归 baseline,仅子代理新改动计入交付 diff
538
+ // (与 dirty baseline overlay 同哲学)。baseBranch 仍记主仓侧锚(sync 诊断用)。
539
+ git(this.cwd, ['worktree', 'add', worktreePath, branch], { timeout: 120000 });
540
+ baseHash = git(this.cwd, ['rev-parse', branch]);
541
+ adoptedBranch = true;
542
+ console.log(`📌 已收编既有分支 ${branch} 为 worktree 工作分支(--adopt-branch):baseline = 分支 HEAD ${String(baseHash).slice(0, 8)},分支既有内容不计交付 diff`);
543
+ } else {
544
+ git(this.cwd, ['worktree', 'add', worktreePath, '-b', branch, baseHash], { timeout: 120000 });
545
+ }
461
546
  } catch (e) {
462
547
  const check = isGitWorktreeSupported(this.cwd);
463
548
  if (!check.supported) {
@@ -518,8 +603,9 @@ export class WorktreeManager {
518
603
 
519
604
  // 5.7 创建 baseline checkpoint(有 dirty baseline 时才创建)
520
605
  let baselineCommit = null;
606
+ if (adoptedBranch) baselineCommit = baseHash; // adopt:分支 HEAD 恒作交付 diff 锚(无 dirty overlay 也要锚定)
521
607
  if (baselineFiles.length > 0) {
522
- baselineCommit = this._createBaselineCheckpoint(worktreePath, name);
608
+ baselineCommit = this._createBaselineCheckpoint(worktreePath, name, baselineFiles);
523
609
  }
524
610
 
525
611
  // 5.8 依赖供给(change 2026-06-28-worktree-deps-provision)
@@ -552,12 +638,13 @@ export class WorktreeManager {
552
638
  depsLockHash: deps.depsLockHash || null,
553
639
  depsCheckedAt: deps.depsCheckedAt || null,
554
640
  ...(deps.depsError ? { depsError: deps.depsError } : {}),
641
+ ...(adoptedBranch ? { adoptedBranch: true } : {}),
555
642
  };
556
643
 
557
644
  const metaPath = join(worktreePath, META_FILE);
558
645
  writeMetaAtomic(metaPath, meta);
559
646
 
560
- return { branch, worktreePath, baseHash, mode: meta.mode, syncDiagnostic };
647
+ return { branch, worktreePath, baseHash, mode: meta.mode, syncDiagnostic, ...(adoptedBranch ? { adoptedBranch: true } : {}) };
561
648
  }
562
649
 
563
650
  /**
@@ -655,7 +742,7 @@ export class WorktreeManager {
655
742
 
656
743
  let baselineCommit = null;
657
744
  if (baselineFiles.length > 0) {
658
- baselineCommit = this._createBaselineCheckpoint(this.cwd, name);
745
+ baselineCommit = this._createBaselineCheckpoint(this.cwd, name, baselineFiles);
659
746
  }
660
747
 
661
748
  const meta = {
@@ -800,6 +887,69 @@ export class WorktreeManager {
800
887
  return refs;
801
888
  }
802
889
 
890
+ /**
891
+ * 清理前打捞 spec 流程产物(坑 worktree-spec-artifact-misplace,2026-08-24 用户实证)。
892
+ *
893
+ * 子代理 cwd=worktree 时会把流程产物(verify-result.md / module-impact.md / 任务卡 / 模块文档)
894
+ * 写进 worktree 内的 .sillyspec——而 apply 的 filterDeliverableFiles 把 .sillyspec/changes/ 排除在
895
+ * 交付外(spec 文档不进代码 patch),cleanup 删除 worktree 这些产物即蒸发、主仓流程看不到。
896
+ * 删除前扫 worktree 内两棵子树做最后打捞:
897
+ * changes/<name>/** → 主仓缺失则 copy 回(verify-result.md 等核心场景);同名不同内容仅列
898
+ * 清单 warn 不覆盖(主仓版本可能是更新的,覆盖会倒退)
899
+ * docs/** → 主仓缺失则 copy 回(模块文档卡片;同名差异不提示——tracked checkout 副本常态)
900
+ * 只扫本变更子树(其它 change 的副本文件不越权搬运)。异常只 warn 不阻断清理。
901
+ * @private
902
+ */
903
+ _salvageSpecArtifacts(name, worktreePath, details) {
904
+ try {
905
+ const mainSpec = join(this._resolveMainRepoRoot(), '.sillyspec');
906
+ const wtSpec = join(worktreePath, '.sillyspec');
907
+ if (!existsSync(wtSpec)) return;
908
+ if (resolve(wtSpec) === resolve(mainSpec)) return; // in-place:同一目录,无需打捞
909
+ const salvaged = [];
910
+ const conflicts = [];
911
+ const salvageTree = (subDir, reportConflict) => {
912
+ const srcRoot = join(wtSpec, subDir);
913
+ if (!existsSync(srcRoot)) return;
914
+ const walk = (dir) => {
915
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
916
+ const src = join(dir, entry.name);
917
+ if (entry.isDirectory()) { walk(src); continue; }
918
+ if (!entry.isFile()) continue;
919
+ const rel = relative(wtSpec, src);
920
+ const dst = join(mainSpec, rel);
921
+ try {
922
+ if (!existsSync(dst)) {
923
+ mkdirSync(dirname(dst), { recursive: true });
924
+ copyFileSync(src, dst);
925
+ salvaged.push(rel);
926
+ } else if (reportConflict && readFileSync(src, 'utf8') !== readFileSync(dst, 'utf8')) {
927
+ conflicts.push(rel);
928
+ }
929
+ } catch { /* 单文件失败不拖垮整体打捞 */ }
930
+ }
931
+ };
932
+ walk(srcRoot);
933
+ };
934
+ salvageTree(join('changes', name), true);
935
+ salvageTree('docs', false);
936
+ if (salvaged.length > 0) {
937
+ console.warn(`⚠️ worktree 清理前打捞:${salvaged.length} 个 spec 流程产物只存在于 worktree 副本,已复制回主仓(apply 不搬运 .sillyspec/changes,不捞即随清理蒸发):`);
938
+ for (const f of salvaged.slice(0, 20)) console.warn(` ${join(mainSpec, f)}`);
939
+ if (salvaged.length > 20) console.warn(` …等共 ${salvaged.length} 个`);
940
+ details.push(`salvaged ${salvaged.length} spec artifacts to main repo`);
941
+ }
942
+ if (conflicts.length > 0) {
943
+ console.warn(`⚠️ worktree 与主仓存在同名但内容不同的流程产物(不覆盖,请人工确认是否需要合并):`);
944
+ for (const f of conflicts.slice(0, 20)) console.warn(` ${join(mainSpec, f)}`);
945
+ if (conflicts.length > 20) console.warn(` …等共 ${conflicts.length} 个`);
946
+ details.push(`conflicting spec artifacts: ${conflicts.length}`);
947
+ }
948
+ } catch (e) {
949
+ console.warn(`⚠️ spec 产物打捞跳过(不阻断清理): ${e?.message || e}`);
950
+ }
951
+ }
952
+
803
953
  cleanup(changeName, { force = false, maxRetries = 3 } = {}) {
804
954
  const name = validateChangeName(changeName);
805
955
  const meta = this.getMeta(name);
@@ -839,34 +989,17 @@ export class WorktreeManager {
839
989
 
840
990
  const branch = (meta && meta.branch) || BRANCH_PREFIX + name;
841
991
 
842
- // Windows 保护:先解链接 worktree/node_modules(junction 指向主 checkout),
843
- // 否则后续 git worktree remove / rmSync recursive 会跟随 junction 误删主 node_modules 内容。
992
+ // 打捞 spec 流程产物(坑 worktree-spec-artifact-misplace,2026-08-24 用户实证):必须在任何
993
+ // 删除动作之前。in-place(worktree 即主工作区)与 native-worktree(外部隔离环境)跳过。
994
+ if (!isInPlace && mode !== 'native-worktree' && existsSync(worktreePath)) {
995
+ this._salvageSpecArtifacts(name, worktreePath, details);
996
+ }
997
+
998
+ // Windows 保护:先解链接 worktree 内全部 node_modules junction(根 + modules 子模块,
999
+ // 坑 ghost-dir-junction-pierce:子模块 junction 此前不覆盖——npm ci / rm -rf / git worktree
1000
+ // remove 跟随任一 junction 都会穿透删主仓对应 node_modules)。
844
1001
  if (!isInPlace && existsSync(worktreePath)) {
845
- const wtNodeModules = join(worktreePath, 'node_modules');
846
- if (existsSync(wtNodeModules)) {
847
- // lstat 失败 fail-loud(D-001@v1 / review-2026-08-09 #4):EPERM(杀毒/索引锁 junction)若静默跳过解链,
848
- // 后续 git worktree remove / rmSync recursive 会跟随 junction 误删主仓 node_modules
849
- let isLink;
850
- try {
851
- isLink = lstatSync(wtNodeModules).isSymbolicLink();
852
- } catch (e) {
853
- throw new Error(`worktree node_modules junction 检测失败(疑似 EPERM:杀毒/索引占用),阻断 cleanup 保护主仓 node_modules:${e.message}。请关闭占用进程或手动 rmdir "${wtNodeModules}" 后重试 sillyspec worktree cleanup`);
854
- }
855
- if (isLink) {
856
- try {
857
- if (process.platform === 'win32') {
858
- // Windows rmdir 删 junction(reparse point)不跟随目标,保护主 checkout
859
- // execFileSync 数组形式:路径含引号/特殊字符时不会经 shell 解析(安全收敛,与 git-helper 同范式)
860
- execFileSync('cmd.exe', ['/c', 'rmdir', wtNodeModules]);
861
- } else {
862
- unlinkSync(wtNodeModules);
863
- }
864
- details.push('worktree node_modules junction/symlink removed (protect main checkout)');
865
- } catch (e) {
866
- throw new Error(`worktree node_modules junction 解链失败,阻断 cleanup 保护主仓 node_modules:${e.message}。请手动 rmdir "${wtNodeModules}" 后重试`);
867
- }
868
- }
869
- }
1002
+ unlinkNodeModulesLinks(worktreePath, meta, details)
870
1003
  }
871
1004
 
872
1005
  // 1. git worktree remove(带 retry)—— in-place 跳过:无 git worktree 注册,且 worktreePath 即主工作区
@@ -907,6 +1040,11 @@ export class WorktreeManager {
907
1040
 
908
1041
  // 4. 删除分支(fail-closed:task review 引用可达性校验。force 也不绕过——force 语义 =
909
1042
  // 丢弃内容,不含丢弃审计链;确要删用 git branch -D 手动执行)
1043
+ // native-worktree 豁免(坑 worktree-user-branch-conflict,2026-08-24):该模式 meta.branch
1044
+ // 记的是用户自己的检出分支(非 sillyspec 所建),force 也不删——只清 sillyspec 侧注册。
1045
+ if (mode === 'native-worktree') {
1046
+ details.push(`branch kept: native-worktree 模式的 branch(${branch})是用户自己的检出分支,不删除`);
1047
+ } else
910
1048
  // 升级(坑 cleanup-branch-review-anchor-tag,2026-08-21 实证):分支被 review.json 引用
911
1049
  // 时不再只能手动保留——打 `sillyspec-audit/<branch>` 轻量 tag 锚定分支 tip(ref 前缀独立
912
1050
  // 于 sillyspec/* 分支族,doctor 孤儿分支扫描不误伤),commit 经 tag 保持可达(gc 安全),
@@ -1007,31 +1145,11 @@ export class WorktreeManager {
1007
1145
  try {
1008
1146
  const meta = this.getMeta(name) || {};
1009
1147
  const isInPlace = meta.mode === 'in-place-fallback';
1010
- // 先解 junction(非 in-place):lstatSync 判 link → Windows rmdir junction / Unix unlinkSync
1148
+ // 先解 junction(非 in-place):统一走共享解链(坑 ghost-dir-junction-pierce:覆盖根 +
1149
+ // depsModules 子模块;lstat/rmdir 失败 fail-loud,D-001@v1 / review-2026-08-09 #4——
1150
+ // 静默跳过解链会让 install 经 junction 误改主仓 node_modules)
1011
1151
  if (!isInPlace && existsSync(wtPath)) {
1012
- const wtNodeModules = join(wtPath, 'node_modules');
1013
- if (existsSync(wtNodeModules)) {
1014
- // lstat 失败 fail-loud(D-001@v1)+ 解链失败 fail-loud(D-002@v1 / review-2026-08-09 #4):
1015
- // 原 best-effort「交 provisionDeps install」会经 junction 误改主仓 node_modules,正是 #4 坑
1016
- let isLink;
1017
- try {
1018
- isLink = lstatSync(wtNodeModules).isSymbolicLink();
1019
- } catch (e) {
1020
- throw new Error(`worktree node_modules junction 检测失败(疑似 EPERM:杀毒/索引占用),阻断 doctor reprovision 保护主仓 node_modules:${e.message}。请关闭占用进程或手动 rmdir "${wtNodeModules}" 后重试`);
1021
- }
1022
- if (isLink) {
1023
- try {
1024
- if (process.platform === 'win32') {
1025
- // execFileSync 数组形式:不经 shell,防 meta.worktreePath 注入(安全收敛)
1026
- execFileSync('cmd.exe', ['/c', 'rmdir', wtNodeModules]);
1027
- } else {
1028
- unlinkSync(wtNodeModules);
1029
- }
1030
- } catch (e) {
1031
- throw new Error(`worktree node_modules junction 解链失败,阻断 doctor reprovision(不调 provisionDeps 避免经 junction 误改主仓):${e.message}。请手动 rmdir "${wtNodeModules}" 后重试`);
1032
- }
1033
- }
1034
- }
1152
+ unlinkNodeModulesLinks(wtPath, meta)
1035
1153
  }
1036
1154
  // 触发分流(坑 doctor-reprovision-junction-missing,2026-08-22 实证:junction 未建的
1037
1155
  // missing/failed 场景被 force install 强制重装——install 静默失败面大且慢;lockfile 一致时
@@ -1043,11 +1161,18 @@ export class WorktreeManager {
1043
1161
  force: !opts.relinkFirst,
1044
1162
  }) || {};
1045
1163
  const metaPath = join(this.getWorktreePath(name), META_FILE);
1046
- // 成功重供时清掉旧 depsError(provisionDeps 成功结果不含该键,{...meta,...deps} 会残留旧值)
1164
+ // 错误保真(坑 doctor-reprovision-error-erased,2026-08-23 实证:provisionDeps 的子模块
1165
+ // 后验证/mismatch 摘要追加 depsError 但不降级 depsStatus——原「depsStatus!=='failed' 即删
1166
+ // depsError」把失败证据从 meta 抹掉,msg 也不含 → doctor 报 re-provisioned 成功而子模块
1167
+ // 实际无链接无提示)。三改:①本次供给全量干净(无 depsError 且非 failed)才清旧值;
1168
+ // ②msg 拼上 depsError;③failed/有错误 → ok:false 落 unfixable(原无条件 ok:true 把失败
1169
+ // 也进 fixed 数组,CLI 打 ✅ 误导「已修好」)。
1170
+ const hasDepError = deps.depsStatus === 'failed' || !!deps.depsError;
1047
1171
  const merged = { ...meta, ...deps };
1048
- if (deps.depsStatus !== 'failed') delete merged.depsError;
1172
+ if (!hasDepError) delete merged.depsError;
1049
1173
  writeMetaAtomic(metaPath, merged);
1050
- return { ok: true, msg: `re-provisioned ${name}: depsStatus=${deps.depsStatus}` };
1174
+ const msg = `re-provisioned ${name}: depsStatus=${deps.depsStatus}` + (deps.depsError ? `;⚠️ ${deps.depsError}` : '');
1175
+ return hasDepError ? { ok: false, msg } : { ok: true, msg };
1051
1176
  } catch (e) {
1052
1177
  return { ok: false, msg: `re-provision failed for ${name}: ${e.message}` };
1053
1178
  }
@@ -1079,16 +1204,19 @@ export class WorktreeManager {
1079
1204
  // 数据源不一致——并行会话的活跃变更(meta 已清/in-place/平台模式 meta 在别处)分支会被全局
1080
1205
  // doctor --fix 误删。删分支前交叉核对:分支名 ∈ 活跃变更 → 保留(fixable:false 提示人工确认)。
1081
1206
  // 先探 DB 文件存在再实例化 ProgressManager(坑7 读路径建库:_ensureDB 不存在会建库污染)。
1082
- // null = 进度库存在但读失败(无法判定活跃态,保守不自动删);空 Set = 无库/无活跃变更
1083
- // (git-only 工作流零回归,孤儿分支照删)。
1207
+ // null = 无法核对(读失败 或 无进度库——坑 worktree-user-branch-conflict 2026-08-24 收紧:
1208
+ // 无库时无法区分孤儿与用户自建分支,从「照删」改保守保留,git-only 便利让位于不误删);
1209
+ // Set = 进度库可读(空集=无活跃变更,非活跃孤儿仍可删)。
1084
1210
  let activeChanges = null;
1211
+ let dbMissing = false;
1085
1212
  try {
1086
1213
  const specBaseOfWt = dirname(dirname(this.worktreeBase)); // <specBase>(.runtime/worktrees 上两级)
1087
1214
  if (existsSync(join(specBaseOfWt, '.runtime', 'sillyspec.db'))) {
1088
1215
  const { ProgressManager } = await import('./progress.js');
1089
1216
  activeChanges = new Set(new ProgressManager({ specDir: specBaseOfWt }).listChanges(this.cwd));
1090
1217
  } else {
1091
- activeChanges = new Set();
1218
+ activeChanges = null;
1219
+ dbMissing = true;
1092
1220
  }
1093
1221
  } catch (e) {
1094
1222
  console.warn(`⚠️ doctor 进度库读取失败,孤儿分支的活跃态交叉核对不可用(保守不自动删): ${e.message}`);
@@ -1199,6 +1327,17 @@ export class WorktreeManager {
1199
1327
  (r.ok ? fixed : unfixable).push(r.msg);
1200
1328
  }
1201
1329
  }
1330
+ // editable install 越界检查(坑 worktree-editable-install-escape,2026-08-25 实证
1331
+ // gen:types 坑):worktree venv 的 editable install 指向 worktree 外(主仓)时,
1332
+ // gen:types/后端命令/pytest 静默加载旧代码零报错——此前靠模块文档人工记忆,内建检查化。
1333
+ // fixable:false(重装决策留给用户:uv sync / pip install -e . 需按项目方式选)。
1334
+ try {
1335
+ const escapes = detectEditableInstallEscape(wtPath);
1336
+ if (escapes.length > 0) {
1337
+ issues.push({ type: 'editable-install-escape', name, fixable: false,
1338
+ detail: `worktree venv 含 ${escapes.length} 个 editable install 指向 worktree 外(${escapes.slice(0, 5).map(e => `${e.pkg}→${e.target}`).join(', ')}${escapes.length > 5 ? ' 等' : ''})——gen:types/后端命令会静默加载 worktree 外旧代码。修复:在 worktree 内重装(uv sync / uv pip install -e .)后重跑生成命令` });
1339
+ }
1340
+ } catch { /* 探测失败不阻断 doctor */ }
1202
1341
  }
1203
1342
  }
1204
1343
 
@@ -1217,10 +1356,21 @@ export class WorktreeManager {
1217
1356
  if (files.length === 0 || (files.length === 1 && files[0] === META_FILE)) {
1218
1357
  issues.push({ type: 'ghost-dir', name, detail: `空目录/幽灵目录: ${dirPath}`, fixable: true });
1219
1358
  if (fix) {
1220
- try { rmSync(dirPath, { recursive: true, force: true }); fixed.push(`removed ghost dir: ${name}`); } catch { unfixable.push(`remove failed for: ${name}`); }
1359
+ // 安全删除(坑 ghost-dir-junction-pierce):统一先解 node_modules junction 再删
1360
+ try { safeRemoveWorktreeDir(dirPath); fixed.push(`removed ghost dir: ${name}`); } catch (e) { unfixable.push(`remove failed for: ${name} (${e.message.slice(0, 120)})`); }
1221
1361
  }
1222
1362
  } else {
1223
- issues.push({ type: 'ghost-dir-with-files', name, detail: `目录存在但无 meta.json: ${dirPath} (含 ${files.length} 文件)`, fixable: false });
1363
+ // junction 侦测(坑 ghost-dir-junction-pierce):无 meta 的含文件目录不自动删(内容
1364
+ // 不明,fixable:false 交人工裁决),但必须警示穿透风险 + 给安全手动指引——人工
1365
+ // rm -rf(Git Bash coreutils 跟随 junction)会删主仓 node_modules。
1366
+ const junctionHits = [];
1367
+ for (const cand of [join(dirPath, 'node_modules'), ...files.filter(f => !f.startsWith('.')).slice(0, 20).map(f => join(dirPath, f, 'node_modules'))]) {
1368
+ try { if (lstatSync(cand).isSymbolicLink()) junctionHits.push(relative(dirPath, cand) || '(root)') } catch {}
1369
+ }
1370
+ const junctionNote = junctionHits.length > 0
1371
+ ? ` ⚠️ 含 node_modules junction(${junctionHits.join(', ')})——手动删除前必须先解链(cmd /c rmdir "<目录>\\<相对路径>"),直接 rm -rf 会穿透删除主仓 node_modules;解链后删除目录或跑 sillyspec worktree doctor --fix`
1372
+ : '';
1373
+ issues.push({ type: 'ghost-dir-with-files', name, detail: `目录存在但无 meta.json: ${dirPath} (含 ${files.length} 文件)${junctionNote}`, fixable: false });
1224
1374
  }
1225
1375
  }
1226
1376
 
@@ -1267,9 +1417,20 @@ export class WorktreeManager {
1267
1417
  continue;
1268
1418
  }
1269
1419
  if (activeChanges === null) {
1270
- // 进度库读失败:无法判定活跃态,保守不自动删(宁可漏删不可误删并行会话分支)
1420
+ // 无法核对活跃态(读失败 或 无进度库):保守不自动删(宁可漏删不可误删——
1421
+ // 坑 worktree-user-branch-conflict:无库时该分支可能是用户自建的,无凭据区分)
1422
+ const why = dbMissing ? '无进度库,无法区分孤儿与用户自建分支' : '进度库不可读,无法交叉核对活跃态'
1423
+ issues.push({ type: 'orphan-branch', name, fixable: false,
1424
+ detail: `分支疑似残留(无对应 meta,且${why}): ${branch}——保守不自动删,人工确认后 git branch -D ${branch}` });
1425
+ continue;
1426
+ }
1427
+ // review 锚点复核(坑 worktree-user-branch-conflict):分支上有 task review base/head
1428
+ // 引用的 commit → 审计链在用,不自动删(与 cleanup 的分支删除审计保护同口径)
1429
+ let reviewRefs = [];
1430
+ try { reviewRefs = this._branchReviewReferences(branch); } catch { reviewRefs = [] }
1431
+ if (reviewRefs.length > 0) {
1271
1432
  issues.push({ type: 'orphan-branch', name, fixable: false,
1272
- detail: `分支疑似残留(无对应 meta,且进度库不可读无法交叉核对活跃态): ${branch}——保守不自动删,人工确认后 git branch -D ${branch}` });
1433
+ detail: `分支无对应 meta 但被 ${reviewRefs.length} 个 task review.json 的 base/head 引用(审计锚点)——保留。确要删除:先归档/迁移审计引用,或手动 git branch -D ${branch}` });
1273
1434
  continue;
1274
1435
  }
1275
1436
  issues.push({ type: 'orphan-branch', name, detail: `分支残留(无对应 meta,且非活跃变更): ${branch}`, fixable: true });
@@ -1323,6 +1484,41 @@ export class WorktreeManager {
1323
1484
  }
1324
1485
 
1325
1486
  const isDeliverable = f => f && !f.startsWith('.sillyspec/') && f !== 'meta.json';
1487
+ const isDeliverablePath = isDeliverable;
1488
+
1489
+ // 合并可达性短路(坑 cleanup-merged-branch-byte-false-positive,2026-08-23 实证:分支已
1490
+ // merge 进主仓后主仓后续提交又改了同一批文件——下方逐字节判定必然不等 → 误报「未落地」
1491
+ // 拦 cleanup 要 --force,用户只能 git branch --merged 自证。历史可达性才是「交付已进主仓」
1492
+ // 的权威口径:分支 tip 是主仓 HEAD 的祖先 ⟺ diffBase..tip 的全部交付已在主仓历史里,后续
1493
+ // 演进不改写这一事实)。四条件全真才短路,任一拿不准(ref 已删/漂移/git 失败)落回原逐字节
1494
+ // 逻辑 fail-open,cherry-pick 落地(tip 非祖先)同样走原路径——零回归。
1495
+ try {
1496
+ const branch = meta.branch;
1497
+ if (branch) {
1498
+ const tip = gitQuiet(this.cwd, ['rev-parse', '--verify', branch]);
1499
+ const wtHead = gitQuiet(worktreePath, ['rev-parse', 'HEAD']);
1500
+ // 条件②③:worktree HEAD 就是分支 tip(无漂移/未删),且工作区无未 commit/未 track 的
1501
+ // 交付改动(那些不在祖先可达性内,须走逐字节路径逐个核对)
1502
+ if (tip && wtHead && tip === wtHead) {
1503
+ const wtStatus = gitQuiet(worktreePath, ['status', '--porcelain'], { timeout: 30000 });
1504
+ if (wtStatus !== null) {
1505
+ const deliverableDirty = wtStatus.split('\n').filter(Boolean)
1506
+ .map(l => l.slice(3).split(' -> ').pop())
1507
+ .some(isDeliverablePath);
1508
+ if (!deliverableDirty) {
1509
+ // 条件④:merge-base(branch, HEAD) === tip ⟺ tip 是 HEAD 祖先(不用 --is-ancestor:
1510
+ // gitQuiet 把 exit 1「非祖先」与真失败都归 null 无法区分;merge-base 恒 exit 0,
1511
+ // 输出等于 tip 即祖先,ref 失败返回 null 自然落回原逻辑)
1512
+ const mb = gitQuiet(this.cwd, ['merge-base', branch, 'HEAD']);
1513
+ if (mb === tip) {
1514
+ return { hasChanges: false, changedFiles: [], reason: `branch fully merged into main HEAD (tip ${tip.slice(0, 8)} is ancestor; post-merge main edits are later history)` };
1515
+ }
1516
+ }
1517
+ }
1518
+ }
1519
+ }
1520
+ } catch { /* 可达性判定异常 → 落回原逐字节逻辑(fail-open) */ }
1521
+
1326
1522
  try {
1327
1523
  // 1) 候选交付变更(worktree 工作区相对 diffBase)。--no-renames:rename 退化成 D+A,两侧文件都进集
1328
1524
  const trackedRaw = gitQuiet(worktreePath, ['diff', '--no-renames', '--name-only', diffBase], { timeout: 30000 });
@@ -1605,9 +1801,13 @@ export class WorktreeManager {
1605
1801
  * 用于区分 "前置 dirty baseline" 和 "子代理新增改动"
1606
1802
  * @param {string} worktreePath
1607
1803
  * @param {string} changeName
1804
+ * @param {string[]} [baselineFiles] 主仓并行在途文件清单(_overlayBaseline 返回的 files,
1805
+ * 已排除 .sillyspec)——写入提交信息正文(坑 baseline-checkpoint-opaque-carriage,
1806
+ * 2026-08-24 用户反馈三期③:checkpoint 把主仓并行脏文件带进分支 diff,逐任务归因要靠
1807
+ * 人肉区分;清单入 message 后 `git log` 一眼可辨、可机械排除)
1608
1808
  * @returns {string} commit hash
1609
1809
  */
1610
- _createBaselineCheckpoint(worktreePath, changeName) {
1810
+ _createBaselineCheckpoint(worktreePath, changeName, baselineFiles = []) {
1611
1811
  // 使用临时 git identity,避免用户未配置 user.name/user.email 导致失败
1612
1812
  const env = {
1613
1813
  GIT_AUTHOR_NAME: 'sillyspec',
@@ -1622,13 +1822,21 @@ export class WorktreeManager {
1622
1822
  if (!status) {
1623
1823
  return gitQuiet(worktreePath, ['rev-parse', 'HEAD']);
1624
1824
  }
1825
+ // 提交信息正文列夹带文件(封顶 30 行,超出记总数)——清单与 meta.baselineFiles 同源
1826
+ const CAP = 30
1827
+ const files = Array.isArray(baselineFiles) ? baselineFiles.filter(Boolean) : []
1828
+ const body = files.length > 0
1829
+ ? ['\n主仓并行在途文件(非本变更改动,逐任务归因时排除):',
1830
+ ...files.slice(0, CAP).map(f => `- ${f}`),
1831
+ ...(files.length > CAP ? [`…等共 ${files.length} 个`] : [])].join('\n')
1832
+ : ''
1625
1833
  // --no-verify:baseline 是锚点不是交付物,只是把主仓库 dirty 文件快照到 worktree
1626
1834
  // 分支上以便区分「前置 baseline」与「子代理新增改动」。它不该触发项目 pre-commit
1627
1835
  // hook(如 ruff format),否则主仓库 dirty 文件中任一不达标的会被 hook reformat
1628
1836
  // 致 commit 失败 → worktree 创建失败 → execute 无法启动。
1629
1837
  execFileSync(
1630
1838
  'git',
1631
- ['commit', '--no-verify', '-m', `sillyspec: baseline checkpoint for ${changeName}`],
1839
+ ['commit', '--no-verify', '-m', `sillyspec: baseline checkpoint for ${changeName}${body}`],
1632
1840
  { cwd: worktreePath, encoding: 'utf8', stdio: ['pipe','pipe','pipe'], env }
1633
1841
  );
1634
1842
  const hash = git(worktreePath, ['rev-parse', 'HEAD']);
@@ -22,7 +22,8 @@ TaskCard 格式规则(必须严格遵守):
22
22
  - 如果存在 decisions.md,无法覆盖的 D-xxx@vN 在 constraints 中标注
23
23
  - **保存前格式自检**(plan-postcheck 会硬校验,不通过到 Step 4 会批量报错,先在这里逐条自查):
24
24
  - **硬校验字段**(缺失 plan-postcheck 直接报错阻断,必须齐全):id、title、title_zh、allowed_paths、goal、implementation、acceptance、verify、constraints
25
+ - **占位符硬拦**(未替换视同缺字段,plan --done 直接报错阻断):FR-XX(requirement_ids)、D-XXX(decision_ids)、src/example/file.ts(allowed_paths)、一句话说明这个 task(goal)、具体步骤 1(implementation)、可验证的验收条件 1(acceptance)、边界约束 1(constraints)——骨架带出来的占位值必须逐个替换成真实内容
25
26
  - **规范约定字段**(应填但不硬校验,缺失不阻断完成、只影响规范性):author、created_at、priority、depends_on、blocks
26
27
  - allowed_paths 非空(至少一个真实源文件路径;回归类 task 无源码改动时填被验证的关键入口文件)
27
28
  - acceptance 与 verify 都在 frontmatter 内(漏写会被 plan-postcheck 报「缺少验收标准」/「缺少验证步骤」)
28
- - **生成方式**:用 `sillyspec taskcard <change-name> --task task-NN [--all]` 生成安全骨架(LF 行尾 + frontmatter 必闭合 + 九个硬校验字段齐全 + author/created_at 自动填),再往骨架里填语义内容——**勿用 Write tool 整文件手写**(CRLF / 漏闭合 `---` / 漏字段的根源,postcheck 报错大多由此来);已存在的卡命令会跳过不覆盖,局部修改用 Edit 定点改
29
+ - **生成方式**:由主 agent 一次性 `sillyspec taskcard <change-name> --all` 预生成全部安全骨架(LF 行尾 + frontmatter 必闭合 + 九个硬校验字段齐全 + author/created_at 自动填;幂等,已存在跳过)。**子代理不要并行跑 taskcard CLI**(2026-08-25 实证撞进度库 SQLite 锁),只往骨架里填语义内容(LF 行尾 + frontmatter 必闭合 + 九个硬校验字段齐全 + author/created_at 自动填),再往骨架里填语义内容——**勿用 Write tool 整文件手写**(CRLF / 漏闭合 `---` / 漏字段的根源,postcheck 报错大多由此来);已存在的卡命令会跳过不覆盖,局部修改用 Edit 定点改