sillyspec 3.27.12 → 3.28.2

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 (1234) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +214 -214
  2. package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
  3. package/.claude/skills/sillyspec-quick/SKILL.md +116 -116
  4. package/package.json +1 -1
  5. package/src/agent-session-log.js +77 -10
  6. package/src/archive-delta.js +419 -0
  7. package/src/config-schema.js +2 -2
  8. package/src/contract-matrix.js +15 -2
  9. package/src/design-facts.js +354 -0
  10. package/src/docs-check.js +79 -8
  11. package/src/doctor-diagnostics.js +75 -3
  12. package/src/endpoint-baseline.js +109 -0
  13. package/src/endpoint-extractor.js +100 -24
  14. package/src/git-helper.js +31 -0
  15. package/src/index.js +248 -8
  16. package/src/machine-interface.js +63 -0
  17. package/src/modules.js +41 -12
  18. package/src/progress/change-registry.js +20 -0
  19. package/src/progress/consistency-doctor.js +124 -5
  20. package/src/progress/stage-machine.js +118 -2
  21. package/src/progress.js +6 -0
  22. package/src/quicklog.js +51 -0
  23. package/src/run/command.js +71 -2
  24. package/src/run/complete-handlers.js +84 -7
  25. package/src/run/complete.js +58 -5
  26. package/src/run/gates.js +333 -2
  27. package/src/run/prompt.js +70 -0
  28. package/src/run/quick-audit.js +98 -0
  29. package/src/run/scan-profile.js +98 -6
  30. package/src/run/shared.js +66 -1
  31. package/src/run/stage.js +25 -12
  32. package/src/scan-diff.js +54 -1
  33. package/src/scan-facts.js +173 -0
  34. package/src/scan-postcheck.js +110 -3
  35. package/src/spec-sync.js +210 -16
  36. package/src/stage-review.js +62 -3
  37. package/src/stages/archive.js +5 -5
  38. package/src/stages/brainstorm.js +10 -10
  39. package/src/stages/execute.js +21 -15
  40. package/src/stages/plan-postcheck.js +194 -1
  41. package/src/stages/plan.js +6 -2
  42. package/src/stages/scan.js +44 -102
  43. package/src/stages/verify.js +9 -7
  44. package/src/sync.js +122 -4
  45. package/src/task-review.js +51 -4
  46. package/src/taskcard.js +8 -1
  47. package/src/verify-postcheck.js +670 -10
  48. package/src/verify-probes.js +92 -10
  49. package/src/workflow.js +30 -0
  50. package/templates/agents-instruction.md +1 -1
  51. package/templates/prompts/taskcard-rules.md +5 -0
  52. package/templates/workflows/scan-docs.yaml +6 -0
  53. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  54. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  55. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  56. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  57. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  58. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  59. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  60. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  61. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +0 -57
  62. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +0 -177
  63. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  64. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  65. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  66. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  67. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  68. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +0 -64
  69. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +0 -54
  70. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  71. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  72. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +0 -2
  73. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +0 -20
  74. package/.claude/worktrees/sillyspec-data-model-research/README.md +0 -203
  75. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +0 -91
  76. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +0 -2
  77. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  78. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +0 -977
  79. package/.claude/worktrees/sillyspec-data-model-research/package.json +0 -39
  80. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  81. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  82. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  83. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +0 -16
  84. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  85. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +0 -836
  86. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +0 -256
  87. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +0 -25
  88. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +0 -95
  89. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +0 -679
  90. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +0 -526
  91. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +0 -357
  92. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +0 -803
  93. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +0 -290
  94. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +0 -270
  95. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +0 -65
  96. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +0 -109
  97. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +0 -202
  98. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +0 -88
  99. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +0 -328
  100. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +0 -97
  101. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +0 -480
  102. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +0 -20
  103. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +0 -55
  104. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +0 -381
  105. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +0 -517
  106. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +0 -155
  107. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +0 -245
  108. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +0 -246
  109. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +0 -121
  110. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +0 -825
  111. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +0 -393
  112. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +0 -107
  113. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +0 -1099
  114. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +0 -420
  115. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +0 -78
  116. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +0 -73
  117. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +0 -150
  118. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +0 -130
  119. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +0 -892
  120. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +0 -2798
  121. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +0 -626
  122. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +0 -231
  123. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +0 -128
  124. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +0 -104
  125. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +0 -543
  126. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +0 -127
  127. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +0 -166
  128. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +0 -222
  129. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +0 -580
  130. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +0 -336
  131. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +0 -355
  132. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +0 -36
  133. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +0 -594
  134. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +0 -265
  135. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +0 -1304
  136. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +0 -115
  137. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +0 -852
  138. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +0 -77
  139. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +0 -1595
  140. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +0 -1552
  141. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +0 -1259
  142. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +0 -156
  143. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +0 -1084
  144. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +0 -208
  145. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +0 -128
  146. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +0 -843
  147. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +0 -186
  148. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +0 -269
  149. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +0 -1562
  150. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +0 -584
  151. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +0 -23
  152. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +0 -388
  153. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +0 -512
  154. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +0 -95
  155. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +0 -414
  156. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +0 -597
  157. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +0 -62
  158. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +0 -50
  159. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +0 -358
  160. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +0 -171
  161. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +0 -550
  162. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +0 -889
  163. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +0 -597
  164. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +0 -199
  165. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +0 -236
  166. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +0 -617
  167. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +0 -145
  168. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +0 -540
  169. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +0 -1275
  170. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +0 -43
  171. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +0 -29
  172. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +0 -514
  173. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +0 -1344
  174. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +0 -650
  175. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +0 -167
  176. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +0 -608
  177. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +0 -64
  178. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +0 -246
  179. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +0 -1470
  180. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +0 -1498
  181. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +0 -210
  182. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +0 -1718
  183. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +0 -277
  184. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +0 -19
  185. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +0 -600
  186. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +0 -125
  187. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +0 -1446
  188. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +0 -576
  189. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +0 -1715
  190. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +0 -23
  191. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +0 -28
  192. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +0 -12
  193. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +0 -32
  194. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +0 -79
  195. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +0 -132
  196. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  197. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  198. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  199. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  200. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  201. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  202. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  203. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  204. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +0 -57
  205. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +0 -177
  206. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  207. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  208. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  209. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  210. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  211. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  212. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +0 -64
  213. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +0 -54
  214. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  215. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  216. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +0 -6
  217. package/.worktrees/2c37b1d7/.gitattributes +0 -2
  218. package/.worktrees/2c37b1d7/.husky/pre-push +0 -20
  219. package/.worktrees/2c37b1d7/README.md +0 -203
  220. package/.worktrees/2c37b1d7/SKILL.md +0 -91
  221. package/.worktrees/2c37b1d7/architecture-analysis.md +0 -448
  222. package/.worktrees/2c37b1d7/bin/sillyspec.js +0 -2
  223. package/.worktrees/2c37b1d7/eval/README.md +0 -86
  224. package/.worktrees/2c37b1d7/eval/eval.config.json +0 -28
  225. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +0 -63
  226. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +0 -27
  227. package/.worktrees/2c37b1d7/eval/lib/config.mjs +0 -82
  228. package/.worktrees/2c37b1d7/eval/lib/db.mjs +0 -76
  229. package/.worktrees/2c37b1d7/eval/lib/report.mjs +0 -120
  230. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +0 -157
  231. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +0 -73
  232. package/.worktrees/2c37b1d7/eval/lib/util.mjs +0 -107
  233. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +0 -30
  234. package/.worktrees/2c37b1d7/eval/run.mjs +0 -83
  235. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +0 -6
  236. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  237. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +0 -6
  238. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +0 -28
  239. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +0 -6
  240. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  241. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  242. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +0 -6
  243. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +0 -31
  244. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  245. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +0 -6
  246. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  247. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +0 -6
  248. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +0 -38
  249. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  250. package/.worktrees/2c37b1d7/package-lock.json +0 -977
  251. package/.worktrees/2c37b1d7/package.json +0 -41
  252. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  253. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  254. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  255. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +0 -16
  256. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  257. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +0 -836
  258. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +0 -256
  259. package/.worktrees/2c37b1d7/packages/dashboard/package.json +0 -25
  260. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +0 -95
  261. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +0 -679
  262. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +0 -526
  263. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +0 -357
  264. package/.worktrees/2c37b1d7/src/agent-session-log.js +0 -803
  265. package/.worktrees/2c37b1d7/src/change-list.js +0 -290
  266. package/.worktrees/2c37b1d7/src/change-risk-profile.js +0 -339
  267. package/.worktrees/2c37b1d7/src/check-primitives.js +0 -65
  268. package/.worktrees/2c37b1d7/src/classify-change.js +0 -109
  269. package/.worktrees/2c37b1d7/src/commit-suggest.js +0 -202
  270. package/.worktrees/2c37b1d7/src/config-cat.js +0 -88
  271. package/.worktrees/2c37b1d7/src/config-schema.js +0 -328
  272. package/.worktrees/2c37b1d7/src/constants.js +0 -97
  273. package/.worktrees/2c37b1d7/src/contract-matrix.js +0 -533
  274. package/.worktrees/2c37b1d7/src/datetime.js +0 -20
  275. package/.worktrees/2c37b1d7/src/db-engine.js +0 -55
  276. package/.worktrees/2c37b1d7/src/db.js +0 -381
  277. package/.worktrees/2c37b1d7/src/decision-distill.js +0 -517
  278. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +0 -155
  279. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +0 -245
  280. package/.worktrees/2c37b1d7/src/dispatch/probe.js +0 -246
  281. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +0 -121
  282. package/.worktrees/2c37b1d7/src/docs-check.js +0 -825
  283. package/.worktrees/2c37b1d7/src/docs-debt.js +0 -393
  284. package/.worktrees/2c37b1d7/src/docs-gate.js +0 -107
  285. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +0 -1099
  286. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +0 -409
  287. package/.worktrees/2c37b1d7/src/foreign-declared.js +0 -155
  288. package/.worktrees/2c37b1d7/src/fs-atomic.js +0 -73
  289. package/.worktrees/2c37b1d7/src/git-helper.js +0 -150
  290. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +0 -130
  291. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +0 -892
  292. package/.worktrees/2c37b1d7/src/index.js +0 -2854
  293. package/.worktrees/2c37b1d7/src/init.js +0 -626
  294. package/.worktrees/2c37b1d7/src/knowledge-match.js +0 -231
  295. package/.worktrees/2c37b1d7/src/local-detect.js +0 -128
  296. package/.worktrees/2c37b1d7/src/local-register.js +0 -104
  297. package/.worktrees/2c37b1d7/src/machine-interface.js +0 -543
  298. package/.worktrees/2c37b1d7/src/migrate.js +0 -127
  299. package/.worktrees/2c37b1d7/src/module-impact.js +0 -166
  300. package/.worktrees/2c37b1d7/src/module-resolve.js +0 -222
  301. package/.worktrees/2c37b1d7/src/modules.js +0 -580
  302. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +0 -126
  303. package/.worktrees/2c37b1d7/src/progress/change-registry.js +0 -336
  304. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +0 -355
  305. package/.worktrees/2c37b1d7/src/progress/shared.js +0 -36
  306. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +0 -594
  307. package/.worktrees/2c37b1d7/src/progress/step-store.js +0 -265
  308. package/.worktrees/2c37b1d7/src/progress.js +0 -1304
  309. package/.worktrees/2c37b1d7/src/quick-recommend.js +0 -115
  310. package/.worktrees/2c37b1d7/src/quicklog.js +0 -883
  311. package/.worktrees/2c37b1d7/src/review-tier.js +0 -77
  312. package/.worktrees/2c37b1d7/src/run/command.js +0 -1641
  313. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +0 -1552
  314. package/.worktrees/2c37b1d7/src/run/complete.js +0 -1259
  315. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +0 -156
  316. package/.worktrees/2c37b1d7/src/run/gates.js +0 -1111
  317. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +0 -208
  318. package/.worktrees/2c37b1d7/src/run/next.js +0 -128
  319. package/.worktrees/2c37b1d7/src/run/prompt.js +0 -843
  320. package/.worktrees/2c37b1d7/src/run/quick-audit.js +0 -186
  321. package/.worktrees/2c37b1d7/src/run/scan-profile.js +0 -269
  322. package/.worktrees/2c37b1d7/src/run/shared.js +0 -1562
  323. package/.worktrees/2c37b1d7/src/run/stage.js +0 -587
  324. package/.worktrees/2c37b1d7/src/run.js +0 -23
  325. package/.worktrees/2c37b1d7/src/scan-diff.js +0 -388
  326. package/.worktrees/2c37b1d7/src/scan-postcheck.js +0 -524
  327. package/.worktrees/2c37b1d7/src/scan-staleness.js +0 -95
  328. package/.worktrees/2c37b1d7/src/setup.js +0 -414
  329. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +0 -597
  330. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +0 -62
  331. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +0 -50
  332. package/.worktrees/2c37b1d7/src/spec-sync.js +0 -358
  333. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +0 -171
  334. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +0 -551
  335. package/.worktrees/2c37b1d7/src/stage-contract.js +0 -948
  336. package/.worktrees/2c37b1d7/src/stage-review.js +0 -597
  337. package/.worktrees/2c37b1d7/src/stages/archive.js +0 -199
  338. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +0 -285
  339. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +0 -624
  340. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +0 -145
  341. package/.worktrees/2c37b1d7/src/stages/doctor.js +0 -540
  342. package/.worktrees/2c37b1d7/src/stages/execute.js +0 -1277
  343. package/.worktrees/2c37b1d7/src/stages/explore.js +0 -43
  344. package/.worktrees/2c37b1d7/src/stages/index.js +0 -29
  345. package/.worktrees/2c37b1d7/src/stages/knowledge.js +0 -514
  346. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +0 -1398
  347. package/.worktrees/2c37b1d7/src/stages/plan.js +0 -655
  348. package/.worktrees/2c37b1d7/src/stages/quick.js +0 -167
  349. package/.worktrees/2c37b1d7/src/stages/scan.js +0 -608
  350. package/.worktrees/2c37b1d7/src/stages/status.js +0 -64
  351. package/.worktrees/2c37b1d7/src/stages/verify.js +0 -246
  352. package/.worktrees/2c37b1d7/src/sync.js +0 -1470
  353. package/.worktrees/2c37b1d7/src/task-review.js +0 -1498
  354. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +0 -21
  355. package/.worktrees/2c37b1d7/src/taskcard.js +0 -250
  356. package/.worktrees/2c37b1d7/src/verify-postcheck.js +0 -1718
  357. package/.worktrees/2c37b1d7/src/verify-probes.js +0 -327
  358. package/.worktrees/2c37b1d7/src/version.js +0 -19
  359. package/.worktrees/2c37b1d7/src/workflow.js +0 -600
  360. package/.worktrees/2c37b1d7/src/workspace.js +0 -125
  361. package/.worktrees/2c37b1d7/src/worktree-apply.js +0 -1611
  362. package/.worktrees/2c37b1d7/src/worktree-deps.js +0 -668
  363. package/.worktrees/2c37b1d7/src/worktree.js +0 -1849
  364. package/.worktrees/2c37b1d7/templates/claude-instruction.md +0 -23
  365. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +0 -29
  366. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +0 -12
  367. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +0 -32
  368. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +0 -79
  369. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +0 -132
  370. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  371. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  372. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  373. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  374. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  375. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  376. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  377. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  378. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +0 -57
  379. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +0 -177
  380. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  381. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  382. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  383. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  384. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  385. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +0 -64
  386. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +0 -54
  387. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  388. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  389. package/.worktrees/542c4415/.gitattributes +0 -2
  390. package/.worktrees/542c4415/.husky/pre-push +0 -20
  391. package/.worktrees/542c4415/README.md +0 -203
  392. package/.worktrees/542c4415/SKILL.md +0 -91
  393. package/.worktrees/542c4415/architecture-analysis.md +0 -448
  394. package/.worktrees/542c4415/bin/sillyspec.js +0 -2
  395. package/.worktrees/542c4415/eval/README.md +0 -86
  396. package/.worktrees/542c4415/eval/eval.config.json +0 -28
  397. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +0 -63
  398. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +0 -27
  399. package/.worktrees/542c4415/eval/lib/config.mjs +0 -82
  400. package/.worktrees/542c4415/eval/lib/db.mjs +0 -76
  401. package/.worktrees/542c4415/eval/lib/report.mjs +0 -120
  402. package/.worktrees/542c4415/eval/lib/runner.mjs +0 -157
  403. package/.worktrees/542c4415/eval/lib/tasks.mjs +0 -73
  404. package/.worktrees/542c4415/eval/lib/util.mjs +0 -107
  405. package/.worktrees/542c4415/eval/lib/workdir.mjs +0 -30
  406. package/.worktrees/542c4415/eval/run.mjs +0 -83
  407. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +0 -6
  408. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  409. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +0 -6
  410. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +0 -28
  411. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +0 -6
  412. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  413. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  414. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +0 -6
  415. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +0 -31
  416. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  417. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +0 -6
  418. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  419. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +0 -6
  420. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +0 -38
  421. package/.worktrees/542c4415/logo.jpg +0 -0
  422. package/.worktrees/542c4415/package-lock.json +0 -977
  423. package/.worktrees/542c4415/package.json +0 -41
  424. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  425. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  426. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  427. package/.worktrees/542c4415/packages/dashboard/dist/index.html +0 -16
  428. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  429. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +0 -836
  430. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +0 -256
  431. package/.worktrees/542c4415/packages/dashboard/package.json +0 -25
  432. package/.worktrees/542c4415/packages/dashboard/server/executor.js +0 -95
  433. package/.worktrees/542c4415/packages/dashboard/server/index.js +0 -679
  434. package/.worktrees/542c4415/packages/dashboard/server/parser.js +0 -526
  435. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +0 -357
  436. package/.worktrees/542c4415/src/agent-session-log.js +0 -803
  437. package/.worktrees/542c4415/src/change-list.js +0 -290
  438. package/.worktrees/542c4415/src/change-risk-profile.js +0 -339
  439. package/.worktrees/542c4415/src/check-primitives.js +0 -65
  440. package/.worktrees/542c4415/src/classify-change.js +0 -109
  441. package/.worktrees/542c4415/src/commit-suggest.js +0 -202
  442. package/.worktrees/542c4415/src/config-cat.js +0 -88
  443. package/.worktrees/542c4415/src/config-schema.js +0 -328
  444. package/.worktrees/542c4415/src/constants.js +0 -97
  445. package/.worktrees/542c4415/src/contract-matrix.js +0 -533
  446. package/.worktrees/542c4415/src/datetime.js +0 -20
  447. package/.worktrees/542c4415/src/db-engine.js +0 -55
  448. package/.worktrees/542c4415/src/db.js +0 -381
  449. package/.worktrees/542c4415/src/decision-distill.js +0 -517
  450. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +0 -155
  451. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +0 -245
  452. package/.worktrees/542c4415/src/dispatch/probe.js +0 -246
  453. package/.worktrees/542c4415/src/dispatch/strategy.js +0 -121
  454. package/.worktrees/542c4415/src/docs-check.js +0 -825
  455. package/.worktrees/542c4415/src/docs-debt.js +0 -393
  456. package/.worktrees/542c4415/src/docs-gate.js +0 -107
  457. package/.worktrees/542c4415/src/doctor-diagnostics.js +0 -1099
  458. package/.worktrees/542c4415/src/endpoint-extractor.js +0 -409
  459. package/.worktrees/542c4415/src/foreign-declared.js +0 -155
  460. package/.worktrees/542c4415/src/fs-atomic.js +0 -73
  461. package/.worktrees/542c4415/src/git-helper.js +0 -150
  462. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +0 -130
  463. package/.worktrees/542c4415/src/hooks/worktree-guard.js +0 -892
  464. package/.worktrees/542c4415/src/index.js +0 -2854
  465. package/.worktrees/542c4415/src/init.js +0 -626
  466. package/.worktrees/542c4415/src/knowledge-match.js +0 -231
  467. package/.worktrees/542c4415/src/local-detect.js +0 -128
  468. package/.worktrees/542c4415/src/local-register.js +0 -104
  469. package/.worktrees/542c4415/src/machine-interface.js +0 -543
  470. package/.worktrees/542c4415/src/migrate.js +0 -127
  471. package/.worktrees/542c4415/src/module-impact.js +0 -166
  472. package/.worktrees/542c4415/src/module-resolve.js +0 -222
  473. package/.worktrees/542c4415/src/modules.js +0 -580
  474. package/.worktrees/542c4415/src/plan-adopt-waves.js +0 -126
  475. package/.worktrees/542c4415/src/progress/change-registry.js +0 -336
  476. package/.worktrees/542c4415/src/progress/consistency-doctor.js +0 -355
  477. package/.worktrees/542c4415/src/progress/shared.js +0 -36
  478. package/.worktrees/542c4415/src/progress/stage-machine.js +0 -594
  479. package/.worktrees/542c4415/src/progress/step-store.js +0 -265
  480. package/.worktrees/542c4415/src/progress.js +0 -1304
  481. package/.worktrees/542c4415/src/quick-recommend.js +0 -115
  482. package/.worktrees/542c4415/src/quicklog.js +0 -883
  483. package/.worktrees/542c4415/src/review-tier.js +0 -77
  484. package/.worktrees/542c4415/src/run/command.js +0 -1641
  485. package/.worktrees/542c4415/src/run/complete-handlers.js +0 -1552
  486. package/.worktrees/542c4415/src/run/complete.js +0 -1259
  487. package/.worktrees/542c4415/src/run/concurrent-detect.js +0 -156
  488. package/.worktrees/542c4415/src/run/gates.js +0 -1111
  489. package/.worktrees/542c4415/src/run/multi-repo-context.js +0 -208
  490. package/.worktrees/542c4415/src/run/next.js +0 -128
  491. package/.worktrees/542c4415/src/run/prompt.js +0 -843
  492. package/.worktrees/542c4415/src/run/quick-audit.js +0 -186
  493. package/.worktrees/542c4415/src/run/scan-profile.js +0 -269
  494. package/.worktrees/542c4415/src/run/shared.js +0 -1562
  495. package/.worktrees/542c4415/src/run/stage.js +0 -587
  496. package/.worktrees/542c4415/src/run.js +0 -23
  497. package/.worktrees/542c4415/src/scan-diff.js +0 -388
  498. package/.worktrees/542c4415/src/scan-postcheck.js +0 -524
  499. package/.worktrees/542c4415/src/scan-staleness.js +0 -95
  500. package/.worktrees/542c4415/src/setup.js +0 -414
  501. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +0 -597
  502. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +0 -62
  503. package/.worktrees/542c4415/src/spec-dir-typo.js +0 -50
  504. package/.worktrees/542c4415/src/spec-sync.js +0 -358
  505. package/.worktrees/542c4415/src/stage-contract-engine.js +0 -171
  506. package/.worktrees/542c4415/src/stage-contract-spec.js +0 -551
  507. package/.worktrees/542c4415/src/stage-contract.js +0 -948
  508. package/.worktrees/542c4415/src/stage-review.js +0 -597
  509. package/.worktrees/542c4415/src/stages/archive.js +0 -199
  510. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +0 -285
  511. package/.worktrees/542c4415/src/stages/brainstorm.js +0 -624
  512. package/.worktrees/542c4415/src/stages/cmd-existence.js +0 -145
  513. package/.worktrees/542c4415/src/stages/doctor.js +0 -540
  514. package/.worktrees/542c4415/src/stages/execute.js +0 -1277
  515. package/.worktrees/542c4415/src/stages/explore.js +0 -43
  516. package/.worktrees/542c4415/src/stages/index.js +0 -29
  517. package/.worktrees/542c4415/src/stages/knowledge.js +0 -514
  518. package/.worktrees/542c4415/src/stages/plan-postcheck.js +0 -1398
  519. package/.worktrees/542c4415/src/stages/plan.js +0 -655
  520. package/.worktrees/542c4415/src/stages/quick.js +0 -167
  521. package/.worktrees/542c4415/src/stages/scan.js +0 -608
  522. package/.worktrees/542c4415/src/stages/status.js +0 -64
  523. package/.worktrees/542c4415/src/stages/verify.js +0 -246
  524. package/.worktrees/542c4415/src/sync.js +0 -1470
  525. package/.worktrees/542c4415/src/task-review.js +0 -1498
  526. package/.worktrees/542c4415/src/taskcard-placeholders.js +0 -21
  527. package/.worktrees/542c4415/src/taskcard.js +0 -250
  528. package/.worktrees/542c4415/src/verify-postcheck.js +0 -1718
  529. package/.worktrees/542c4415/src/verify-probes.js +0 -327
  530. package/.worktrees/542c4415/src/version.js +0 -19
  531. package/.worktrees/542c4415/src/workflow.js +0 -600
  532. package/.worktrees/542c4415/src/workspace.js +0 -125
  533. package/.worktrees/542c4415/src/worktree-apply.js +0 -1611
  534. package/.worktrees/542c4415/src/worktree-deps.js +0 -668
  535. package/.worktrees/542c4415/src/worktree.js +0 -1849
  536. package/.worktrees/542c4415/templates/claude-instruction.md +0 -23
  537. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +0 -29
  538. package/.worktrees/542c4415/templates/prompts/testcase-design.md +0 -12
  539. package/.worktrees/542c4415/templates/prompts/verify-probes.md +0 -32
  540. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +0 -79
  541. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +0 -132
  542. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  543. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  544. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  545. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  546. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  547. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  548. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  549. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  550. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +0 -57
  551. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +0 -177
  552. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  553. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  554. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  555. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  556. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  557. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  558. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +0 -64
  559. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +0 -54
  560. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  561. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  562. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +0 -6
  563. package/.worktrees/8d2d0392/.gitattributes +0 -2
  564. package/.worktrees/8d2d0392/.husky/pre-push +0 -20
  565. package/.worktrees/8d2d0392/README.md +0 -203
  566. package/.worktrees/8d2d0392/SKILL.md +0 -91
  567. package/.worktrees/8d2d0392/architecture-analysis.md +0 -448
  568. package/.worktrees/8d2d0392/bin/sillyspec.js +0 -2
  569. package/.worktrees/8d2d0392/eval/README.md +0 -86
  570. package/.worktrees/8d2d0392/eval/eval.config.json +0 -28
  571. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +0 -63
  572. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +0 -27
  573. package/.worktrees/8d2d0392/eval/lib/config.mjs +0 -82
  574. package/.worktrees/8d2d0392/eval/lib/db.mjs +0 -76
  575. package/.worktrees/8d2d0392/eval/lib/report.mjs +0 -120
  576. package/.worktrees/8d2d0392/eval/lib/runner.mjs +0 -157
  577. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +0 -73
  578. package/.worktrees/8d2d0392/eval/lib/util.mjs +0 -107
  579. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +0 -30
  580. package/.worktrees/8d2d0392/eval/run.mjs +0 -83
  581. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +0 -6
  582. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  583. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +0 -6
  584. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +0 -28
  585. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +0 -6
  586. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  587. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  588. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +0 -6
  589. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +0 -31
  590. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  591. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +0 -6
  592. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  593. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +0 -6
  594. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +0 -38
  595. package/.worktrees/8d2d0392/logo.jpg +0 -0
  596. package/.worktrees/8d2d0392/package-lock.json +0 -977
  597. package/.worktrees/8d2d0392/package.json +0 -41
  598. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  599. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  600. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  601. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +0 -16
  602. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  603. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +0 -836
  604. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +0 -256
  605. package/.worktrees/8d2d0392/packages/dashboard/package.json +0 -25
  606. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +0 -95
  607. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +0 -679
  608. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +0 -526
  609. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +0 -357
  610. package/.worktrees/8d2d0392/src/agent-session-log.js +0 -803
  611. package/.worktrees/8d2d0392/src/change-list.js +0 -290
  612. package/.worktrees/8d2d0392/src/change-risk-profile.js +0 -339
  613. package/.worktrees/8d2d0392/src/check-primitives.js +0 -65
  614. package/.worktrees/8d2d0392/src/classify-change.js +0 -109
  615. package/.worktrees/8d2d0392/src/commit-suggest.js +0 -202
  616. package/.worktrees/8d2d0392/src/config-cat.js +0 -88
  617. package/.worktrees/8d2d0392/src/config-schema.js +0 -328
  618. package/.worktrees/8d2d0392/src/constants.js +0 -97
  619. package/.worktrees/8d2d0392/src/contract-matrix.js +0 -533
  620. package/.worktrees/8d2d0392/src/datetime.js +0 -20
  621. package/.worktrees/8d2d0392/src/db-engine.js +0 -55
  622. package/.worktrees/8d2d0392/src/db.js +0 -381
  623. package/.worktrees/8d2d0392/src/decision-distill.js +0 -517
  624. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +0 -155
  625. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +0 -245
  626. package/.worktrees/8d2d0392/src/dispatch/probe.js +0 -246
  627. package/.worktrees/8d2d0392/src/dispatch/strategy.js +0 -121
  628. package/.worktrees/8d2d0392/src/docs-check.js +0 -825
  629. package/.worktrees/8d2d0392/src/docs-debt.js +0 -393
  630. package/.worktrees/8d2d0392/src/docs-gate.js +0 -107
  631. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +0 -1099
  632. package/.worktrees/8d2d0392/src/endpoint-extractor.js +0 -409
  633. package/.worktrees/8d2d0392/src/foreign-declared.js +0 -78
  634. package/.worktrees/8d2d0392/src/fs-atomic.js +0 -73
  635. package/.worktrees/8d2d0392/src/git-helper.js +0 -150
  636. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +0 -130
  637. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +0 -892
  638. package/.worktrees/8d2d0392/src/index.js +0 -2854
  639. package/.worktrees/8d2d0392/src/init.js +0 -626
  640. package/.worktrees/8d2d0392/src/knowledge-match.js +0 -231
  641. package/.worktrees/8d2d0392/src/local-detect.js +0 -128
  642. package/.worktrees/8d2d0392/src/local-register.js +0 -104
  643. package/.worktrees/8d2d0392/src/machine-interface.js +0 -543
  644. package/.worktrees/8d2d0392/src/migrate.js +0 -127
  645. package/.worktrees/8d2d0392/src/module-impact.js +0 -166
  646. package/.worktrees/8d2d0392/src/module-resolve.js +0 -222
  647. package/.worktrees/8d2d0392/src/modules.js +0 -580
  648. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +0 -126
  649. package/.worktrees/8d2d0392/src/progress/change-registry.js +0 -336
  650. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +0 -355
  651. package/.worktrees/8d2d0392/src/progress/shared.js +0 -36
  652. package/.worktrees/8d2d0392/src/progress/stage-machine.js +0 -594
  653. package/.worktrees/8d2d0392/src/progress/step-store.js +0 -265
  654. package/.worktrees/8d2d0392/src/progress.js +0 -1304
  655. package/.worktrees/8d2d0392/src/quick-recommend.js +0 -115
  656. package/.worktrees/8d2d0392/src/quicklog.js +0 -883
  657. package/.worktrees/8d2d0392/src/review-tier.js +0 -77
  658. package/.worktrees/8d2d0392/src/run/command.js +0 -1641
  659. package/.worktrees/8d2d0392/src/run/complete-handlers.js +0 -1552
  660. package/.worktrees/8d2d0392/src/run/complete.js +0 -1259
  661. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +0 -156
  662. package/.worktrees/8d2d0392/src/run/gates.js +0 -1094
  663. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +0 -208
  664. package/.worktrees/8d2d0392/src/run/next.js +0 -128
  665. package/.worktrees/8d2d0392/src/run/prompt.js +0 -843
  666. package/.worktrees/8d2d0392/src/run/quick-audit.js +0 -186
  667. package/.worktrees/8d2d0392/src/run/scan-profile.js +0 -269
  668. package/.worktrees/8d2d0392/src/run/shared.js +0 -1562
  669. package/.worktrees/8d2d0392/src/run/stage.js +0 -587
  670. package/.worktrees/8d2d0392/src/run.js +0 -23
  671. package/.worktrees/8d2d0392/src/scan-diff.js +0 -388
  672. package/.worktrees/8d2d0392/src/scan-postcheck.js +0 -524
  673. package/.worktrees/8d2d0392/src/scan-staleness.js +0 -95
  674. package/.worktrees/8d2d0392/src/setup.js +0 -414
  675. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +0 -597
  676. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +0 -62
  677. package/.worktrees/8d2d0392/src/spec-dir-typo.js +0 -50
  678. package/.worktrees/8d2d0392/src/spec-sync.js +0 -358
  679. package/.worktrees/8d2d0392/src/stage-contract-engine.js +0 -171
  680. package/.worktrees/8d2d0392/src/stage-contract-spec.js +0 -551
  681. package/.worktrees/8d2d0392/src/stage-contract.js +0 -948
  682. package/.worktrees/8d2d0392/src/stage-review.js +0 -597
  683. package/.worktrees/8d2d0392/src/stages/archive.js +0 -199
  684. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +0 -285
  685. package/.worktrees/8d2d0392/src/stages/brainstorm.js +0 -624
  686. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +0 -145
  687. package/.worktrees/8d2d0392/src/stages/doctor.js +0 -540
  688. package/.worktrees/8d2d0392/src/stages/execute.js +0 -1277
  689. package/.worktrees/8d2d0392/src/stages/explore.js +0 -43
  690. package/.worktrees/8d2d0392/src/stages/index.js +0 -29
  691. package/.worktrees/8d2d0392/src/stages/knowledge.js +0 -514
  692. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +0 -1398
  693. package/.worktrees/8d2d0392/src/stages/plan.js +0 -651
  694. package/.worktrees/8d2d0392/src/stages/quick.js +0 -167
  695. package/.worktrees/8d2d0392/src/stages/scan.js +0 -608
  696. package/.worktrees/8d2d0392/src/stages/status.js +0 -64
  697. package/.worktrees/8d2d0392/src/stages/verify.js +0 -246
  698. package/.worktrees/8d2d0392/src/sync.js +0 -1470
  699. package/.worktrees/8d2d0392/src/task-review.js +0 -1498
  700. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +0 -21
  701. package/.worktrees/8d2d0392/src/taskcard.js +0 -217
  702. package/.worktrees/8d2d0392/src/verify-postcheck.js +0 -1718
  703. package/.worktrees/8d2d0392/src/verify-probes.js +0 -327
  704. package/.worktrees/8d2d0392/src/version.js +0 -19
  705. package/.worktrees/8d2d0392/src/workflow.js +0 -600
  706. package/.worktrees/8d2d0392/src/workspace.js +0 -125
  707. package/.worktrees/8d2d0392/src/worktree-apply.js +0 -1611
  708. package/.worktrees/8d2d0392/src/worktree-deps.js +0 -576
  709. package/.worktrees/8d2d0392/src/worktree.js +0 -1838
  710. package/.worktrees/8d2d0392/templates/claude-instruction.md +0 -23
  711. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +0 -29
  712. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +0 -12
  713. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +0 -32
  714. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +0 -79
  715. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +0 -132
  716. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  717. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  718. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  719. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  720. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  721. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  722. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  723. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  724. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +0 -57
  725. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +0 -177
  726. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  727. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  728. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  729. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  730. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  731. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +0 -64
  732. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +0 -54
  733. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  734. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  735. package/.worktrees/c1eae35e/.gitattributes +0 -2
  736. package/.worktrees/c1eae35e/.husky/pre-push +0 -20
  737. package/.worktrees/c1eae35e/README.md +0 -203
  738. package/.worktrees/c1eae35e/SKILL.md +0 -91
  739. package/.worktrees/c1eae35e/architecture-analysis.md +0 -448
  740. package/.worktrees/c1eae35e/bin/sillyspec.js +0 -2
  741. package/.worktrees/c1eae35e/eval/README.md +0 -86
  742. package/.worktrees/c1eae35e/eval/eval.config.json +0 -28
  743. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +0 -63
  744. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +0 -27
  745. package/.worktrees/c1eae35e/eval/lib/config.mjs +0 -82
  746. package/.worktrees/c1eae35e/eval/lib/db.mjs +0 -76
  747. package/.worktrees/c1eae35e/eval/lib/report.mjs +0 -120
  748. package/.worktrees/c1eae35e/eval/lib/runner.mjs +0 -157
  749. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +0 -73
  750. package/.worktrees/c1eae35e/eval/lib/util.mjs +0 -107
  751. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +0 -30
  752. package/.worktrees/c1eae35e/eval/run.mjs +0 -83
  753. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +0 -6
  754. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  755. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +0 -6
  756. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +0 -28
  757. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +0 -6
  758. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  759. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  760. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +0 -6
  761. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +0 -31
  762. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  763. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +0 -6
  764. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  765. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +0 -6
  766. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +0 -38
  767. package/.worktrees/c1eae35e/logo.jpg +0 -0
  768. package/.worktrees/c1eae35e/package-lock.json +0 -977
  769. package/.worktrees/c1eae35e/package.json +0 -41
  770. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  771. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  772. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  773. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +0 -16
  774. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  775. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +0 -836
  776. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +0 -256
  777. package/.worktrees/c1eae35e/packages/dashboard/package.json +0 -25
  778. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +0 -95
  779. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +0 -679
  780. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +0 -526
  781. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +0 -357
  782. package/.worktrees/c1eae35e/src/agent-session-log.js +0 -803
  783. package/.worktrees/c1eae35e/src/change-list.js +0 -290
  784. package/.worktrees/c1eae35e/src/change-risk-profile.js +0 -339
  785. package/.worktrees/c1eae35e/src/check-primitives.js +0 -65
  786. package/.worktrees/c1eae35e/src/classify-change.js +0 -109
  787. package/.worktrees/c1eae35e/src/commit-suggest.js +0 -202
  788. package/.worktrees/c1eae35e/src/config-cat.js +0 -88
  789. package/.worktrees/c1eae35e/src/config-schema.js +0 -328
  790. package/.worktrees/c1eae35e/src/constants.js +0 -97
  791. package/.worktrees/c1eae35e/src/contract-matrix.js +0 -533
  792. package/.worktrees/c1eae35e/src/datetime.js +0 -20
  793. package/.worktrees/c1eae35e/src/db-engine.js +0 -55
  794. package/.worktrees/c1eae35e/src/db.js +0 -381
  795. package/.worktrees/c1eae35e/src/decision-distill.js +0 -517
  796. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +0 -155
  797. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +0 -245
  798. package/.worktrees/c1eae35e/src/dispatch/probe.js +0 -246
  799. package/.worktrees/c1eae35e/src/dispatch/strategy.js +0 -121
  800. package/.worktrees/c1eae35e/src/docs-check.js +0 -825
  801. package/.worktrees/c1eae35e/src/docs-debt.js +0 -393
  802. package/.worktrees/c1eae35e/src/docs-gate.js +0 -107
  803. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +0 -1099
  804. package/.worktrees/c1eae35e/src/endpoint-extractor.js +0 -409
  805. package/.worktrees/c1eae35e/src/foreign-declared.js +0 -155
  806. package/.worktrees/c1eae35e/src/fs-atomic.js +0 -73
  807. package/.worktrees/c1eae35e/src/git-helper.js +0 -150
  808. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +0 -130
  809. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +0 -892
  810. package/.worktrees/c1eae35e/src/index.js +0 -2854
  811. package/.worktrees/c1eae35e/src/init.js +0 -626
  812. package/.worktrees/c1eae35e/src/knowledge-match.js +0 -231
  813. package/.worktrees/c1eae35e/src/local-detect.js +0 -128
  814. package/.worktrees/c1eae35e/src/local-register.js +0 -104
  815. package/.worktrees/c1eae35e/src/machine-interface.js +0 -543
  816. package/.worktrees/c1eae35e/src/migrate.js +0 -127
  817. package/.worktrees/c1eae35e/src/module-impact.js +0 -166
  818. package/.worktrees/c1eae35e/src/module-resolve.js +0 -222
  819. package/.worktrees/c1eae35e/src/modules.js +0 -580
  820. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +0 -126
  821. package/.worktrees/c1eae35e/src/progress/change-registry.js +0 -336
  822. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +0 -355
  823. package/.worktrees/c1eae35e/src/progress/shared.js +0 -36
  824. package/.worktrees/c1eae35e/src/progress/stage-machine.js +0 -594
  825. package/.worktrees/c1eae35e/src/progress/step-store.js +0 -265
  826. package/.worktrees/c1eae35e/src/progress.js +0 -1304
  827. package/.worktrees/c1eae35e/src/quick-recommend.js +0 -115
  828. package/.worktrees/c1eae35e/src/quicklog.js +0 -883
  829. package/.worktrees/c1eae35e/src/review-tier.js +0 -77
  830. package/.worktrees/c1eae35e/src/run/command.js +0 -1641
  831. package/.worktrees/c1eae35e/src/run/complete-handlers.js +0 -1552
  832. package/.worktrees/c1eae35e/src/run/complete.js +0 -1259
  833. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +0 -156
  834. package/.worktrees/c1eae35e/src/run/gates.js +0 -1111
  835. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +0 -208
  836. package/.worktrees/c1eae35e/src/run/next.js +0 -128
  837. package/.worktrees/c1eae35e/src/run/prompt.js +0 -843
  838. package/.worktrees/c1eae35e/src/run/quick-audit.js +0 -186
  839. package/.worktrees/c1eae35e/src/run/scan-profile.js +0 -269
  840. package/.worktrees/c1eae35e/src/run/shared.js +0 -1562
  841. package/.worktrees/c1eae35e/src/run/stage.js +0 -587
  842. package/.worktrees/c1eae35e/src/run.js +0 -23
  843. package/.worktrees/c1eae35e/src/scan-diff.js +0 -388
  844. package/.worktrees/c1eae35e/src/scan-postcheck.js +0 -524
  845. package/.worktrees/c1eae35e/src/scan-staleness.js +0 -95
  846. package/.worktrees/c1eae35e/src/setup.js +0 -414
  847. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +0 -597
  848. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +0 -62
  849. package/.worktrees/c1eae35e/src/spec-dir-typo.js +0 -50
  850. package/.worktrees/c1eae35e/src/spec-sync.js +0 -358
  851. package/.worktrees/c1eae35e/src/stage-contract-engine.js +0 -171
  852. package/.worktrees/c1eae35e/src/stage-contract-spec.js +0 -551
  853. package/.worktrees/c1eae35e/src/stage-contract.js +0 -948
  854. package/.worktrees/c1eae35e/src/stage-review.js +0 -597
  855. package/.worktrees/c1eae35e/src/stages/archive.js +0 -199
  856. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +0 -285
  857. package/.worktrees/c1eae35e/src/stages/brainstorm.js +0 -624
  858. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +0 -145
  859. package/.worktrees/c1eae35e/src/stages/doctor.js +0 -540
  860. package/.worktrees/c1eae35e/src/stages/execute.js +0 -1277
  861. package/.worktrees/c1eae35e/src/stages/explore.js +0 -43
  862. package/.worktrees/c1eae35e/src/stages/index.js +0 -29
  863. package/.worktrees/c1eae35e/src/stages/knowledge.js +0 -514
  864. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +0 -1398
  865. package/.worktrees/c1eae35e/src/stages/plan.js +0 -655
  866. package/.worktrees/c1eae35e/src/stages/quick.js +0 -167
  867. package/.worktrees/c1eae35e/src/stages/scan.js +0 -608
  868. package/.worktrees/c1eae35e/src/stages/status.js +0 -64
  869. package/.worktrees/c1eae35e/src/stages/verify.js +0 -246
  870. package/.worktrees/c1eae35e/src/sync.js +0 -1470
  871. package/.worktrees/c1eae35e/src/task-review.js +0 -1498
  872. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +0 -21
  873. package/.worktrees/c1eae35e/src/taskcard.js +0 -250
  874. package/.worktrees/c1eae35e/src/verify-postcheck.js +0 -1718
  875. package/.worktrees/c1eae35e/src/verify-probes.js +0 -327
  876. package/.worktrees/c1eae35e/src/version.js +0 -19
  877. package/.worktrees/c1eae35e/src/workflow.js +0 -600
  878. package/.worktrees/c1eae35e/src/workspace.js +0 -125
  879. package/.worktrees/c1eae35e/src/worktree-apply.js +0 -1611
  880. package/.worktrees/c1eae35e/src/worktree-deps.js +0 -668
  881. package/.worktrees/c1eae35e/src/worktree.js +0 -1849
  882. package/.worktrees/c1eae35e/templates/claude-instruction.md +0 -23
  883. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +0 -29
  884. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +0 -12
  885. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +0 -32
  886. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +0 -79
  887. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +0 -132
  888. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  889. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  890. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  891. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  892. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  893. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  894. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  895. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  896. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +0 -57
  897. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +0 -177
  898. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  899. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  900. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  901. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  902. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  903. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  904. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +0 -64
  905. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +0 -54
  906. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  907. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  908. package/.worktrees/dafc71ad/.gitattributes +0 -2
  909. package/.worktrees/dafc71ad/.husky/pre-push +0 -20
  910. package/.worktrees/dafc71ad/README.md +0 -203
  911. package/.worktrees/dafc71ad/SKILL.md +0 -91
  912. package/.worktrees/dafc71ad/analysis.md +0 -366
  913. package/.worktrees/dafc71ad/architecture-analysis.md +0 -448
  914. package/.worktrees/dafc71ad/bin/sillyspec.js +0 -2
  915. package/.worktrees/dafc71ad/eval/README.md +0 -86
  916. package/.worktrees/dafc71ad/eval/eval.config.json +0 -28
  917. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +0 -63
  918. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +0 -27
  919. package/.worktrees/dafc71ad/eval/lib/config.mjs +0 -82
  920. package/.worktrees/dafc71ad/eval/lib/db.mjs +0 -76
  921. package/.worktrees/dafc71ad/eval/lib/report.mjs +0 -120
  922. package/.worktrees/dafc71ad/eval/lib/runner.mjs +0 -157
  923. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +0 -73
  924. package/.worktrees/dafc71ad/eval/lib/util.mjs +0 -107
  925. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +0 -30
  926. package/.worktrees/dafc71ad/eval/run.mjs +0 -83
  927. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +0 -6
  928. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  929. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +0 -6
  930. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +0 -28
  931. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +0 -6
  932. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  933. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  934. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +0 -6
  935. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +0 -31
  936. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  937. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +0 -6
  938. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  939. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +0 -6
  940. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +0 -38
  941. package/.worktrees/dafc71ad/logo.jpg +0 -0
  942. package/.worktrees/dafc71ad/package-lock.json +0 -977
  943. package/.worktrees/dafc71ad/package.json +0 -41
  944. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  945. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  946. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  947. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +0 -16
  948. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  949. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +0 -836
  950. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +0 -256
  951. package/.worktrees/dafc71ad/packages/dashboard/package.json +0 -25
  952. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +0 -95
  953. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +0 -679
  954. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +0 -526
  955. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +0 -357
  956. package/.worktrees/dafc71ad/src/agent-session-log.js +0 -803
  957. package/.worktrees/dafc71ad/src/change-list.js +0 -290
  958. package/.worktrees/dafc71ad/src/change-risk-profile.js +0 -339
  959. package/.worktrees/dafc71ad/src/check-primitives.js +0 -65
  960. package/.worktrees/dafc71ad/src/classify-change.js +0 -109
  961. package/.worktrees/dafc71ad/src/commit-suggest.js +0 -202
  962. package/.worktrees/dafc71ad/src/config-cat.js +0 -88
  963. package/.worktrees/dafc71ad/src/config-schema.js +0 -328
  964. package/.worktrees/dafc71ad/src/constants.js +0 -97
  965. package/.worktrees/dafc71ad/src/contract-matrix.js +0 -533
  966. package/.worktrees/dafc71ad/src/datetime.js +0 -20
  967. package/.worktrees/dafc71ad/src/db-engine.js +0 -55
  968. package/.worktrees/dafc71ad/src/db.js +0 -381
  969. package/.worktrees/dafc71ad/src/decision-distill.js +0 -517
  970. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +0 -155
  971. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +0 -245
  972. package/.worktrees/dafc71ad/src/dispatch/probe.js +0 -246
  973. package/.worktrees/dafc71ad/src/dispatch/strategy.js +0 -121
  974. package/.worktrees/dafc71ad/src/docs-check.js +0 -825
  975. package/.worktrees/dafc71ad/src/docs-debt.js +0 -393
  976. package/.worktrees/dafc71ad/src/docs-gate.js +0 -107
  977. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +0 -1099
  978. package/.worktrees/dafc71ad/src/endpoint-extractor.js +0 -409
  979. package/.worktrees/dafc71ad/src/foreign-declared.js +0 -155
  980. package/.worktrees/dafc71ad/src/fs-atomic.js +0 -73
  981. package/.worktrees/dafc71ad/src/git-helper.js +0 -150
  982. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +0 -130
  983. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +0 -892
  984. package/.worktrees/dafc71ad/src/index.js +0 -2854
  985. package/.worktrees/dafc71ad/src/init.js +0 -626
  986. package/.worktrees/dafc71ad/src/knowledge-match.js +0 -231
  987. package/.worktrees/dafc71ad/src/local-detect.js +0 -128
  988. package/.worktrees/dafc71ad/src/local-register.js +0 -104
  989. package/.worktrees/dafc71ad/src/machine-interface.js +0 -543
  990. package/.worktrees/dafc71ad/src/migrate.js +0 -127
  991. package/.worktrees/dafc71ad/src/module-impact.js +0 -166
  992. package/.worktrees/dafc71ad/src/module-resolve.js +0 -222
  993. package/.worktrees/dafc71ad/src/modules.js +0 -580
  994. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +0 -126
  995. package/.worktrees/dafc71ad/src/progress/change-registry.js +0 -336
  996. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +0 -355
  997. package/.worktrees/dafc71ad/src/progress/shared.js +0 -36
  998. package/.worktrees/dafc71ad/src/progress/stage-machine.js +0 -594
  999. package/.worktrees/dafc71ad/src/progress/step-store.js +0 -265
  1000. package/.worktrees/dafc71ad/src/progress.js +0 -1304
  1001. package/.worktrees/dafc71ad/src/quick-recommend.js +0 -115
  1002. package/.worktrees/dafc71ad/src/quicklog.js +0 -883
  1003. package/.worktrees/dafc71ad/src/review-tier.js +0 -77
  1004. package/.worktrees/dafc71ad/src/run/command.js +0 -1641
  1005. package/.worktrees/dafc71ad/src/run/complete-handlers.js +0 -1552
  1006. package/.worktrees/dafc71ad/src/run/complete.js +0 -1259
  1007. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +0 -156
  1008. package/.worktrees/dafc71ad/src/run/gates.js +0 -1111
  1009. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +0 -208
  1010. package/.worktrees/dafc71ad/src/run/next.js +0 -128
  1011. package/.worktrees/dafc71ad/src/run/prompt.js +0 -843
  1012. package/.worktrees/dafc71ad/src/run/quick-audit.js +0 -186
  1013. package/.worktrees/dafc71ad/src/run/scan-profile.js +0 -269
  1014. package/.worktrees/dafc71ad/src/run/shared.js +0 -1562
  1015. package/.worktrees/dafc71ad/src/run/stage.js +0 -587
  1016. package/.worktrees/dafc71ad/src/run.js +0 -23
  1017. package/.worktrees/dafc71ad/src/scan-diff.js +0 -388
  1018. package/.worktrees/dafc71ad/src/scan-postcheck.js +0 -524
  1019. package/.worktrees/dafc71ad/src/scan-staleness.js +0 -95
  1020. package/.worktrees/dafc71ad/src/setup.js +0 -414
  1021. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +0 -597
  1022. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +0 -62
  1023. package/.worktrees/dafc71ad/src/spec-dir-typo.js +0 -50
  1024. package/.worktrees/dafc71ad/src/spec-sync.js +0 -358
  1025. package/.worktrees/dafc71ad/src/stage-contract-engine.js +0 -171
  1026. package/.worktrees/dafc71ad/src/stage-contract-spec.js +0 -551
  1027. package/.worktrees/dafc71ad/src/stage-contract.js +0 -948
  1028. package/.worktrees/dafc71ad/src/stage-review.js +0 -597
  1029. package/.worktrees/dafc71ad/src/stages/archive.js +0 -199
  1030. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +0 -285
  1031. package/.worktrees/dafc71ad/src/stages/brainstorm.js +0 -624
  1032. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +0 -145
  1033. package/.worktrees/dafc71ad/src/stages/doctor.js +0 -540
  1034. package/.worktrees/dafc71ad/src/stages/execute.js +0 -1277
  1035. package/.worktrees/dafc71ad/src/stages/explore.js +0 -43
  1036. package/.worktrees/dafc71ad/src/stages/index.js +0 -29
  1037. package/.worktrees/dafc71ad/src/stages/knowledge.js +0 -514
  1038. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +0 -1398
  1039. package/.worktrees/dafc71ad/src/stages/plan.js +0 -655
  1040. package/.worktrees/dafc71ad/src/stages/quick.js +0 -167
  1041. package/.worktrees/dafc71ad/src/stages/scan.js +0 -608
  1042. package/.worktrees/dafc71ad/src/stages/status.js +0 -64
  1043. package/.worktrees/dafc71ad/src/stages/verify.js +0 -246
  1044. package/.worktrees/dafc71ad/src/sync.js +0 -1470
  1045. package/.worktrees/dafc71ad/src/task-review.js +0 -1498
  1046. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +0 -21
  1047. package/.worktrees/dafc71ad/src/taskcard.js +0 -250
  1048. package/.worktrees/dafc71ad/src/verify-postcheck.js +0 -1718
  1049. package/.worktrees/dafc71ad/src/verify-probes.js +0 -327
  1050. package/.worktrees/dafc71ad/src/version.js +0 -19
  1051. package/.worktrees/dafc71ad/src/workflow.js +0 -600
  1052. package/.worktrees/dafc71ad/src/workspace.js +0 -125
  1053. package/.worktrees/dafc71ad/src/worktree-apply.js +0 -1611
  1054. package/.worktrees/dafc71ad/src/worktree-deps.js +0 -668
  1055. package/.worktrees/dafc71ad/src/worktree.js +0 -1849
  1056. package/.worktrees/dafc71ad/templates/claude-instruction.md +0 -23
  1057. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +0 -29
  1058. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +0 -12
  1059. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +0 -32
  1060. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +0 -79
  1061. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +0 -132
  1062. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  1063. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  1064. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  1065. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  1066. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  1067. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  1068. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  1069. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  1070. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +0 -57
  1071. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +0 -177
  1072. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  1073. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  1074. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  1075. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  1076. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  1077. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  1078. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +0 -64
  1079. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +0 -54
  1080. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  1081. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  1082. package/.worktrees/e58fcc4c/.gitattributes +0 -2
  1083. package/.worktrees/e58fcc4c/.husky/pre-push +0 -20
  1084. package/.worktrees/e58fcc4c/README.md +0 -203
  1085. package/.worktrees/e58fcc4c/SKILL.md +0 -91
  1086. package/.worktrees/e58fcc4c/architecture-analysis.md +0 -503
  1087. package/.worktrees/e58fcc4c/bin/sillyspec.js +0 -2
  1088. package/.worktrees/e58fcc4c/eval/README.md +0 -86
  1089. package/.worktrees/e58fcc4c/eval/eval.config.json +0 -28
  1090. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +0 -63
  1091. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +0 -27
  1092. package/.worktrees/e58fcc4c/eval/lib/config.mjs +0 -82
  1093. package/.worktrees/e58fcc4c/eval/lib/db.mjs +0 -76
  1094. package/.worktrees/e58fcc4c/eval/lib/report.mjs +0 -120
  1095. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +0 -157
  1096. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +0 -73
  1097. package/.worktrees/e58fcc4c/eval/lib/util.mjs +0 -107
  1098. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +0 -30
  1099. package/.worktrees/e58fcc4c/eval/run.mjs +0 -83
  1100. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +0 -6
  1101. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  1102. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +0 -6
  1103. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +0 -28
  1104. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +0 -6
  1105. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  1106. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  1107. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +0 -6
  1108. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +0 -31
  1109. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  1110. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +0 -6
  1111. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  1112. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +0 -6
  1113. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +0 -38
  1114. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  1115. package/.worktrees/e58fcc4c/package-lock.json +0 -977
  1116. package/.worktrees/e58fcc4c/package.json +0 -41
  1117. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  1118. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  1119. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  1120. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +0 -16
  1121. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  1122. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +0 -836
  1123. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +0 -256
  1124. package/.worktrees/e58fcc4c/packages/dashboard/package.json +0 -25
  1125. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +0 -95
  1126. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +0 -679
  1127. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +0 -526
  1128. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +0 -357
  1129. package/.worktrees/e58fcc4c/src/agent-session-log.js +0 -803
  1130. package/.worktrees/e58fcc4c/src/change-list.js +0 -290
  1131. package/.worktrees/e58fcc4c/src/change-risk-profile.js +0 -339
  1132. package/.worktrees/e58fcc4c/src/check-primitives.js +0 -65
  1133. package/.worktrees/e58fcc4c/src/classify-change.js +0 -109
  1134. package/.worktrees/e58fcc4c/src/commit-suggest.js +0 -202
  1135. package/.worktrees/e58fcc4c/src/config-cat.js +0 -88
  1136. package/.worktrees/e58fcc4c/src/config-schema.js +0 -328
  1137. package/.worktrees/e58fcc4c/src/constants.js +0 -97
  1138. package/.worktrees/e58fcc4c/src/contract-matrix.js +0 -533
  1139. package/.worktrees/e58fcc4c/src/datetime.js +0 -20
  1140. package/.worktrees/e58fcc4c/src/db-engine.js +0 -55
  1141. package/.worktrees/e58fcc4c/src/db.js +0 -381
  1142. package/.worktrees/e58fcc4c/src/decision-distill.js +0 -517
  1143. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +0 -155
  1144. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +0 -245
  1145. package/.worktrees/e58fcc4c/src/dispatch/probe.js +0 -246
  1146. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +0 -121
  1147. package/.worktrees/e58fcc4c/src/docs-check.js +0 -825
  1148. package/.worktrees/e58fcc4c/src/docs-debt.js +0 -393
  1149. package/.worktrees/e58fcc4c/src/docs-gate.js +0 -107
  1150. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +0 -1099
  1151. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +0 -409
  1152. package/.worktrees/e58fcc4c/src/foreign-declared.js +0 -155
  1153. package/.worktrees/e58fcc4c/src/fs-atomic.js +0 -73
  1154. package/.worktrees/e58fcc4c/src/git-helper.js +0 -150
  1155. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +0 -130
  1156. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +0 -892
  1157. package/.worktrees/e58fcc4c/src/index.js +0 -2854
  1158. package/.worktrees/e58fcc4c/src/init.js +0 -626
  1159. package/.worktrees/e58fcc4c/src/knowledge-match.js +0 -231
  1160. package/.worktrees/e58fcc4c/src/local-detect.js +0 -128
  1161. package/.worktrees/e58fcc4c/src/local-register.js +0 -104
  1162. package/.worktrees/e58fcc4c/src/machine-interface.js +0 -543
  1163. package/.worktrees/e58fcc4c/src/migrate.js +0 -127
  1164. package/.worktrees/e58fcc4c/src/module-impact.js +0 -166
  1165. package/.worktrees/e58fcc4c/src/module-resolve.js +0 -222
  1166. package/.worktrees/e58fcc4c/src/modules.js +0 -580
  1167. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +0 -126
  1168. package/.worktrees/e58fcc4c/src/progress/change-registry.js +0 -336
  1169. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +0 -355
  1170. package/.worktrees/e58fcc4c/src/progress/shared.js +0 -36
  1171. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +0 -594
  1172. package/.worktrees/e58fcc4c/src/progress/step-store.js +0 -265
  1173. package/.worktrees/e58fcc4c/src/progress.js +0 -1304
  1174. package/.worktrees/e58fcc4c/src/quick-recommend.js +0 -115
  1175. package/.worktrees/e58fcc4c/src/quicklog.js +0 -883
  1176. package/.worktrees/e58fcc4c/src/review-tier.js +0 -77
  1177. package/.worktrees/e58fcc4c/src/run/command.js +0 -1641
  1178. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +0 -1552
  1179. package/.worktrees/e58fcc4c/src/run/complete.js +0 -1259
  1180. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +0 -156
  1181. package/.worktrees/e58fcc4c/src/run/gates.js +0 -1111
  1182. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +0 -208
  1183. package/.worktrees/e58fcc4c/src/run/next.js +0 -128
  1184. package/.worktrees/e58fcc4c/src/run/prompt.js +0 -843
  1185. package/.worktrees/e58fcc4c/src/run/quick-audit.js +0 -186
  1186. package/.worktrees/e58fcc4c/src/run/scan-profile.js +0 -269
  1187. package/.worktrees/e58fcc4c/src/run/shared.js +0 -1562
  1188. package/.worktrees/e58fcc4c/src/run/stage.js +0 -587
  1189. package/.worktrees/e58fcc4c/src/run.js +0 -23
  1190. package/.worktrees/e58fcc4c/src/scan-diff.js +0 -388
  1191. package/.worktrees/e58fcc4c/src/scan-postcheck.js +0 -524
  1192. package/.worktrees/e58fcc4c/src/scan-staleness.js +0 -95
  1193. package/.worktrees/e58fcc4c/src/setup.js +0 -414
  1194. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +0 -597
  1195. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +0 -62
  1196. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +0 -50
  1197. package/.worktrees/e58fcc4c/src/spec-sync.js +0 -358
  1198. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +0 -171
  1199. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +0 -551
  1200. package/.worktrees/e58fcc4c/src/stage-contract.js +0 -948
  1201. package/.worktrees/e58fcc4c/src/stage-review.js +0 -597
  1202. package/.worktrees/e58fcc4c/src/stages/archive.js +0 -199
  1203. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +0 -285
  1204. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +0 -624
  1205. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +0 -145
  1206. package/.worktrees/e58fcc4c/src/stages/doctor.js +0 -540
  1207. package/.worktrees/e58fcc4c/src/stages/execute.js +0 -1277
  1208. package/.worktrees/e58fcc4c/src/stages/explore.js +0 -43
  1209. package/.worktrees/e58fcc4c/src/stages/index.js +0 -29
  1210. package/.worktrees/e58fcc4c/src/stages/knowledge.js +0 -514
  1211. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +0 -1398
  1212. package/.worktrees/e58fcc4c/src/stages/plan.js +0 -655
  1213. package/.worktrees/e58fcc4c/src/stages/quick.js +0 -167
  1214. package/.worktrees/e58fcc4c/src/stages/scan.js +0 -608
  1215. package/.worktrees/e58fcc4c/src/stages/status.js +0 -64
  1216. package/.worktrees/e58fcc4c/src/stages/verify.js +0 -246
  1217. package/.worktrees/e58fcc4c/src/sync.js +0 -1470
  1218. package/.worktrees/e58fcc4c/src/task-review.js +0 -1498
  1219. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +0 -21
  1220. package/.worktrees/e58fcc4c/src/taskcard.js +0 -250
  1221. package/.worktrees/e58fcc4c/src/verify-postcheck.js +0 -1718
  1222. package/.worktrees/e58fcc4c/src/verify-probes.js +0 -327
  1223. package/.worktrees/e58fcc4c/src/version.js +0 -19
  1224. package/.worktrees/e58fcc4c/src/workflow.js +0 -600
  1225. package/.worktrees/e58fcc4c/src/workspace.js +0 -125
  1226. package/.worktrees/e58fcc4c/src/worktree-apply.js +0 -1611
  1227. package/.worktrees/e58fcc4c/src/worktree-deps.js +0 -668
  1228. package/.worktrees/e58fcc4c/src/worktree.js +0 -1849
  1229. package/.worktrees/e58fcc4c/templates/claude-instruction.md +0 -23
  1230. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +0 -29
  1231. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +0 -12
  1232. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +0 -32
  1233. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +0 -79
  1234. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +0 -132
@@ -1,1849 +0,0 @@
1
- /**
2
- * SillySpec WorktreeManager — git worktree 生命周期管理
3
- *
4
- * 封装 git worktree 的 create/list/cleanup/getMeta 操作,
5
- * 为 execute 阶段提供代码隔离环境。
6
- *
7
- * worktree 存储目录:.sillyspec/.runtime/worktrees/<change-name>/
8
- * 分支命名:sillyspec/<change-name>
9
- */
10
-
11
- import { execFileSync } from 'child_process';
12
- import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync, readdirSync, statSync, lstatSync, readlinkSync, unlinkSync, copyFileSync } from 'fs';
13
- import { join, resolve, dirname, relative, isAbsolute } from 'path';
14
- import { createHash } from 'crypto';
15
- import { provisionDeps, checkDepsFreshness, detectEditableInstallEscape } from './worktree-deps.js';
16
- import { writeAtomicSync } from './fs-atomic.js';
17
- import { git, gitQuiet } from './git-helper.js';
18
-
19
- // meta.json 会被 hook 进程与其它 CLI 进程并发读取(worktree-guard / getMeta / create 幽灵判定),
20
- // 必须原子写:半截 JSON 会让 getMeta 返回 null → 触发幽灵 worktree 强删(可能丢 gitignored 改动)。
21
- const writeMetaAtomic = (metaPath, meta) => writeAtomicSync(metaPath, JSON.stringify(meta, null, 2) + '\n');
22
-
23
- const WORKTREES_REL = '.sillyspec/.runtime/worktrees';
24
- const BRANCH_PREFIX = 'sillyspec/';
25
- const META_FILE = 'meta.json';
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
-
86
- // 进程级缓存:cwd → 主仓库根目录。避免每次 new WorktreeManager 都 spawn 一次
87
- // `git rev-parse --git-common-dir`(Windows 上每次 spawn 约 30-100ms,execute 一次命令
88
- // 会 new 多个 WorktreeManager)。git-common-dir 在进程内对同一 cwd 稳定,缓存安全。
89
- const _mainRepoRootByCwd = new Map();
90
-
91
- /**
92
- * 检测当前目录的隔离状态
93
- * 返回 { inWorktree: boolean, inSubmodule: boolean }
94
- *
95
- * 用 git rev-parse --git-dir 和 --git-common-dir 判断:
96
- * - GIT_DIR != GIT_COMMON 通常是 linked worktree
97
- * - 但在 git submodule 里也会出现这种情况
98
- * - 所以必须额外检查 --show-superproject-working-tree 排除 submodule
99
- */
100
- export function detectIsolation(cwd = process.cwd()) {
101
- try {
102
- const gitDir = git(cwd, ['rev-parse', '--git-dir']);
103
- const gitCommonDir = git(cwd, ['rev-parse', '--git-common-dir']);
104
- const superProject = gitQuiet(cwd, ['rev-parse', '--show-superproject-working-tree']);
105
-
106
- const inWorktree = gitDir !== gitCommonDir && !superProject;
107
- const inSubmodule = !!superProject;
108
-
109
- return { inWorktree, inSubmodule, gitDir, gitCommonDir };
110
- } catch {
111
- return { inWorktree: false, inSubmodule: false, gitDir: null, gitCommonDir: null };
112
- }
113
- }
114
-
115
- /**
116
- * 检查 worktree 存储目录是否被 .gitignore 忽略
117
- * @param {string} cwd - 项目根目录
118
- * @returns {{ ignored: boolean, path: string }}
119
- */
120
- function checkWorktreeDirIgnored(cwd = process.cwd()) {
121
- const relPath = WORKTREES_REL;
122
- try {
123
- git(cwd, ['check-ignore', '-q', relPath]);
124
- return { ignored: true, path: relPath };
125
- } catch {
126
- return { ignored: false, path: relPath };
127
- }
128
- }
129
-
130
- /**
131
- * 检测 worktree base(主仓库 HEAD)与 origin 默认分支的同步状态(只读:不 ff、不改 HEAD)。
132
- * 替代旧的 fetch + merge --ff-only:旧逻辑分叉时 ff 失败被静默吞(syncStatus=failed),
133
- * 成功时 baseHash 锚点又不更新(ff 引入的 main 内容污染 apply patch)。现改为只检测+报告,
134
- * 不阻断 create,对齐 origin 的动作留给用户/agent。
135
- *
136
- * @param {string} cwd 主仓库目录
137
- * @param {string} baseHash worktree base commit(= 主仓库 HEAD)
138
- * @returns {{ status: 'up-to-date'|'behind'|'diverged'|'ahead'|'unknown', defaultBranch: string|null, behind: number, ahead: number }}
139
- */
140
- export function computeBaseSync(cwd, baseHash) {
141
- const diag = { status: 'unknown', defaultBranch: null, behind: 0, ahead: 0 };
142
- // 推断默认分支:优先 origin/HEAD 指向的真实分支名(修复旧 339-342 的运算符优先级 bug
143
- // ——旧代码在 origin/HEAD 存在时恒返回 'main',丢弃 symbolic-ref 的真实结果)。
144
- const headRef = gitQuiet(cwd, ['symbolic-ref', 'refs/remotes/origin/HEAD', '--short']);
145
- let defaultBranch = headRef ? headRef.replace('origin/', '') : null;
146
- if (!defaultBranch) {
147
- // fallback:origin/HEAD 未设置时,探测常见默认分支是否存在
148
- for (const cand of ['main', 'master']) {
149
- if (gitQuiet(cwd, ['rev-parse', '--verify', '--quiet', `refs/remotes/origin/${cand}`])) {
150
- defaultBranch = cand;
151
- break;
152
- }
153
- }
154
- }
155
- if (!defaultBranch) return diag; // 无 origin 或推不出默认分支 → unknown
156
- diag.defaultBranch = defaultBranch;
157
-
158
- // best-effort fetch(只更新 remote-tracking,不改工作区/HEAD/分支;失败静默降级用缓存)
159
- gitQuiet(cwd, ['fetch', 'origin', '--quiet'], { timeout: 60000 });
160
- const remoteHead = gitQuiet(cwd, ['rev-parse', '--verify', '--quiet', `refs/remotes/origin/${defaultBranch}`]);
161
- if (!baseHash || !remoteHead) return diag;
162
- if (baseHash === remoteHead) {
163
- diag.status = 'up-to-date';
164
- return diag;
165
- }
166
- const behind = Number(gitQuiet(cwd, ['rev-list', '--count', `${baseHash}..${remoteHead}`]) || 0);
167
- const ahead = Number(gitQuiet(cwd, ['rev-list', '--count', `${remoteHead}..${baseHash}`]) || 0);
168
- diag.behind = behind;
169
- diag.ahead = ahead;
170
- diag.status = (behind > 0 && ahead > 0) ? 'diverged' : (behind > 0 ? 'behind' : 'ahead');
171
- return diag;
172
- }
173
-
174
- /**
175
- * 把 base 同步检测结果打印到 stdout(醒目但不阻断 create)。
176
- * up-to-date 静默不刷屏;其余给风险等级 + 对齐命令,由用户/agent 决定是否处理。
177
- */
178
- function printSyncReport(diag, baseHash, changeName) {
179
- const short = (baseHash || '').slice(0, 8);
180
- if (diag.status === 'up-to-date') return;
181
- if (diag.status === 'unknown') {
182
- console.log(`ℹ️ base 同步检测:无 origin 远端或未设置默认分支,跳过(base ${short})`);
183
- return;
184
- }
185
- const b = diag.defaultBranch;
186
- const ch = changeName || '<change>';
187
- if (diag.status === 'behind') {
188
- console.log(`⚠️ base 同步检测:落后 origin/${b} ${diag.behind} 个 commit(base ${short})`);
189
- console.log(` apply 时 git --3way 会自动三路合并主干已提交推进;只有同文件同区域重叠才冲突。`);
190
- console.log(` 建议先对齐以减小冲突面:`);
191
- console.log(` git merge --ff-only origin/${b}`);
192
- console.log(` sillyspec worktree cleanup ${ch} && sillyspec run execute --change ${ch}`);
193
- console.log(` 或继续,重叠冲突时用 --merge 兜底(会引入合并提交)。`);
194
- } else if (diag.status === 'diverged') {
195
- console.log(`⚠️ base 同步检测:与 origin/${b} 分叉(领先 ${diag.ahead} / 落后 ${diag.behind},base ${short})`);
196
- console.log(` apply 回 main 大概率冲突。建议先在主仓库对齐(rebase 或 merge origin/${b}),`);
197
- console.log(` 再 sillyspec worktree cleanup ${ch} + 重跑 execute。`);
198
- } else {
199
- // ahead:本地有未 push 的提交,无 apply 冲突风险
200
- console.log(`ℹ️ base 同步检测:领先 origin/${b} ${diag.ahead} 个 commit(本地有未 push 的提交,无冲突风险)`);
201
- }
202
- }
203
-
204
- function parseJSON(raw) {
205
- try { return JSON.parse(raw); } catch { return null; }
206
- }
207
-
208
- /**
209
- * 跨平台同步等待(cleanup 重试退避用)
210
- * 不依赖外部 sleep 命令——Windows cmd.exe 无 sleep;当 Git for Windows 未把 usr/bin 加入
211
- * PATH 时,execSync('sleep 0.5') 会抛错并从 catch 块冒泡,直接中断整个 cleanup()。
212
- * 改用 busy-wait 规避,保证 retry 之间真有间隔且不依赖环境。
213
- */
214
- function sleepMs(ms) {
215
- const end = Date.now() + ms;
216
- while (Date.now() < end) { /* spin */ }
217
- }
218
-
219
- export function computeBaselineHash(cwd) {
220
- // 排除非交付物的元数据/文档 churn,避免多操作者仓库里别人改这些 → 整树 hash 变 → apply 误阻断
221
- // (execute 自身也会改 .sillyspec/docs.sillyspec,否则每个 execute 收尾都因自身改动 BLOCKED)。
222
- // 安全:coarse hash 只挡「未提交」dirty(git apply --3way 危险区,实测必拦);真冲突由
223
- // applyWorktree step5a(未提交∩changedFiles 精确点名)+step7(--3way 冲突回滚)兜底,
224
- // 「已提交」推进不再拦(step5b 已放宽交 --3way 自动三路合并),不读这里的 exclude。
225
- // - .sillyspec/:brainstorm/plan 蓝图 + runtime 产物
226
- // - .claude/:agent 配置/skills/CLAUDE.md(多操作者 agent 指引 churn)
227
- // - docs/:文档(非代码交付物)
228
- // - CLAUDE.md:根 agent 指引(多操作者常改)
229
- // 必须和 applyWorktree step 4.5 (worktree-apply.js) 使用相同的排除规则。
230
- const exclude = ['--', '.', ':(exclude).sillyspec/', ':(exclude).claude/', ':(exclude)docs/', ':(exclude)CLAUDE.md'];
231
- const staged = gitQuiet(cwd, ['diff', '--cached', ...exclude], { timeout: 30000 }) || '';
232
- const unstaged = gitQuiet(cwd, ['diff', ...exclude], { timeout: 30000 }) || '';
233
- const untracked = gitQuiet(cwd, ['ls-files', '--others', '--exclude-standard', ...exclude], { timeout: 30000 }) || '';
234
- const raw = `staged:${staged}
235
- unstaged:${unstaged}
236
- untracked:${untracked}`;
237
- return createHash('sha256').update(raw).digest('hex').slice(0, 16);
238
- }
239
-
240
- function validateChangeName(changeName) {
241
- if (!changeName || typeof changeName !== 'string' || changeName.trim() === '') {
242
- throw new Error('changeName 不能为空');
243
- }
244
- const trimmed = changeName.trim();
245
- // 禁止路径穿越
246
- if (trimmed.includes('..') || trimmed.includes('/') || trimmed.includes('\\')) {
247
- throw new Error(`changeName 不合法: "${changeName}",不能包含 ..、/ 或 \\`);
248
- }
249
- return trimmed;
250
- }
251
-
252
- /**
253
- * 检测 git worktree 是否可用
254
- * @param {string} cwd
255
- * @returns {{ supported: boolean, version: string|null, reason?: string }}
256
- */
257
- function isGitWorktreeSupported(cwd = process.cwd()) {
258
- try {
259
- const raw = git(cwd, ['--version']);
260
- const match = raw.match(/git version (\d+)\.(\d+)/);
261
- if (!match) return { supported: false, version: raw, reason: 'cannot parse version' };
262
- const major = parseInt(match[1], 10);
263
- const minor = parseInt(match[2], 10);
264
- if (major > 2 || (major === 2 && minor >= 15)) {
265
- return { supported: true, version: raw };
266
- }
267
- return { supported: false, version: raw, reason: 'git version < 2.15' };
268
- } catch {
269
- return { supported: false, version: null, reason: 'git not found' };
270
- }
271
- }
272
-
273
- /**
274
- * 复制单个 untracked 条目到 worktree(baseline overlay 用)。
275
- *
276
- * 防御目录:untracked 项若是目录(如 Claude Code agent worktree 隔离目录 .worktrees/<hash>/),
277
- * readFileSync 会 EISDIR → 整个 overlay fail-fast。目录跳过(overlay 只同步文件层未提交改动,
278
- * 目录结构由后续文件写入的 mkdirSync 重建)。坑 execute-worktree-overlay-untracked-dir-eisdir。
279
- *
280
- * @param {string} src 主仓库源路径
281
- * @param {string} dst worktree 目标路径
282
- * @returns {{status:'copied'|'skipped-dir'|'missing'|'error', error?:string}}
283
- */
284
- export function copyUntrackedEntry(src, dst) {
285
- if (!existsSync(src)) return { status: 'missing' };
286
- let st;
287
- try { st = statSync(src); } catch { return { status: 'missing' }; }
288
- if (st.isDirectory()) return { status: 'skipped-dir' };
289
- try {
290
- mkdirSync(dirname(dst), { recursive: true });
291
- writeFileSync(dst, readFileSync(src));
292
- return { status: 'copied' };
293
- } catch (e) {
294
- return { status: 'error', error: e.message };
295
- }
296
- }
297
-
298
- /**
299
- * execute 阶段级核验(防空跑谎报,D-002@v1 / FR-04/05/06):聚合 review.changedFiles 的交付文件,
300
- * 逐个核验存在于 worktree 分支 tree 或 worktree 工作区。两处皆无 = 声称实现但从未落盘。
301
- *
302
- * - checked:false:worktreePath 不存在或 branch 不存在(git rev-parse --verify <branch> 失败)
303
- * → 无法核验(worktree 已丢 / 分支已删),调用方保守提示人工确认。
304
- * - 逐文件:`git rev-parse --verify --quiet <branch>:<file>` 成功(在分支 tree)或
305
- * existsSync(worktreePath/<file>)(在工作区)→ verified;两处皆无 → missing。
306
- * tree 探测用 rev-parse --verify --quiet 而非 `git cat-file -e`:语义等价(按 branch tree 解析
307
- * blob),但 cat-file 对不存在路径会往 stderr 打 `fatal: path ... does not exist` 噪音
308
- * (git-helper gitQuiet 只吞退出码不吞 stderr),--quiet 完全静默。
309
- *
310
- * git 调用走项目统一入口 gitQuiet(git-helper.js,数组形式 execFileSync 不经 shell,Windows 安全)。
311
- * 宽松非阻断:本函数只返回结果不 warn/exit,由调用方决定(design 为 warn 不 exit)。
312
- *
313
- * @param {object} p
314
- * @param {string} p.worktreePath - worktree 根目录(绝对路径,meta.worktreePath)
315
- * @param {string} p.branch - sillyspec/<change> 分支名(核验 tree)
316
- * @param {string[]} p.changedFiles - review 声称的交付文件(调用方已过滤主仓 repo、非 .sillyspec)
317
- * @returns {{ missing: string[], verified: string[], checked: boolean }}
318
- * checked=false 表示无法核验(worktree/分支不存在),调用方保守提示人工确认。
319
- */
320
- export function findMissingDeliverables({ worktreePath, branch, changedFiles }) {
321
- const files = Array.isArray(changedFiles)
322
- ? changedFiles.filter(f => typeof f === 'string' && f.trim() !== '')
323
- : []
324
- // worktree 目录不存在 → 无法核验(目录已丢,如 apply 后 cleanup / 并行 session 清过)
325
- if (!worktreePath || !existsSync(worktreePath)) {
326
- return { missing: [], verified: [], checked: false }
327
- }
328
- // branch 不存在(rev-parse --verify 失败)→ 无法核验分支 tree
329
- if (!branch || !gitQuiet(worktreePath, ['rev-parse', '--verify', '--quiet', branch])) {
330
- return { missing: [], verified: [], checked: false }
331
- }
332
- const missing = []
333
- const verified = []
334
- for (const raw of files) {
335
- // 统一正斜杠:review.json 可能落 Windows 反斜杠路径,rev-parse tree 路径一律 /
336
- const f = raw.replace(/\\/g, '/')
337
- const inBranch = gitQuiet(worktreePath, ['rev-parse', '--verify', '--quiet', `${branch}:${f}`]) !== null
338
- const inWorktree = existsSync(join(worktreePath, f))
339
- if (inBranch || inWorktree) verified.push(raw)
340
- else missing.push(raw)
341
- }
342
- return { missing, verified, checked: true }
343
- }
344
-
345
- export class WorktreeManager {
346
- constructor({ cwd, worktreeDir } = {}) {
347
- this.cwd = cwd || process.cwd();
348
-
349
- // worktreeBase 必须固定到主仓库路径,不能跟着 cwd 变化。
350
- // native-worktree 模式下 cwd 是 worktree 子目录,用 cwd 推导 worktreeBase
351
- // 会导致 meta 写入 worktree 内部路径,worktree 内再次执行时找不到。
352
- // 解决:用 git rev-parse --git-common-dir 反推主仓库路径。
353
- if (worktreeDir) {
354
- this.worktreeBase = worktreeDir;
355
- } else {
356
- this.worktreeBase = resolve(this._resolveMainRepoRoot(), WORKTREES_REL);
357
- }
358
- }
359
-
360
- /**
361
- * 解析当前 git 环境对应的主仓库根目录
362
- * 在主仓库内执行:返回 cwd 自身
363
- * 在 linked worktree 内执行:返回 git-common-dir 的父目录(即主仓库 .git 所在地)
364
- * @private
365
- */
366
- _resolveMainRepoRoot() {
367
- const cached = _mainRepoRootByCwd.get(this.cwd);
368
- if (cached !== undefined) return cached;
369
-
370
- let root = this.cwd;
371
- try {
372
- // git-common-dir 在主仓库内 = <main>/.git,在 linked worktree 内 = <main>/.git(git 共享 .git 目录)。
373
- // 但 git 可能返回**相对路径**(如 `.git`)。必须相对 this.cwd 绝对化,否则下面的
374
- // existsSync/statSync 会相对 process.cwd() 解析——当 process.cwd 是另一个 git 仓库
375
- // (未 chdir 的脚本、或 CLI 在别处跑)时,worktreeBase 会错解析到 process.cwd 仓库,
376
- // getMeta 读错位置返回 null。resolve() 对绝对参数原样返回、对相对参数相对 this.cwd 解析,两者皆稳。
377
- const commonDir = gitQuiet(this.cwd, ['rev-parse', '--git-common-dir']);
378
- if (commonDir) {
379
- const absCommonDir = resolve(this.cwd, commonDir);
380
- if (existsSync(absCommonDir) && statSync(absCommonDir).isDirectory()) {
381
- root = dirname(absCommonDir);
382
- }
383
- }
384
- } catch (e) {
385
- // 静默 fallback:主仓库内执行或 git 异常
386
- }
387
- _mainRepoRootByCwd.set(this.cwd, root);
388
- return root;
389
- }
390
-
391
- /**
392
- * 获取 worktree 目录绝对路径
393
- * @param {string} changeName
394
- * @returns {string}
395
- */
396
- getWorktreePath(changeName) {
397
- return resolve(this.worktreeBase, changeName);
398
- }
399
-
400
- /**
401
- * 读取 worktree 元数据
402
- * @param {string} changeName
403
- * @returns {object|null} meta.json 内容,不存在或损坏返回 null
404
- */
405
- getMeta(changeName) {
406
- const name = validateChangeName(changeName);
407
- const metaPath = join(this.getWorktreePath(name), META_FILE);
408
- if (!existsSync(metaPath)) return null;
409
- return parseJSON(readFileSync(metaPath, 'utf8'));
410
- }
411
-
412
- /**
413
- * 创建 worktree
414
- * @param {string} changeName - 变更名
415
- * @param {{ base?: string }} opts - base: 基础分支,默认当前 HEAD
416
- * @returns {{ branch: string, worktreePath: string, baseHash: string }}
417
- * @throws {Error} worktree 已存在、git 不可用、changeName 为空
418
- */
419
- create(changeName, { base, adoptBranch = false } = {}) {
420
- const name = validateChangeName(changeName);
421
- const worktreePath = this.getWorktreePath(name);
422
- const branch = BRANCH_PREFIX + name;
423
-
424
- // 0. 检测当前环境隔离状态(submodule guard)
425
- const isolation = detectIsolation(this.cwd);
426
- if (isolation.inSubmodule) {
427
- throw new Error(
428
- '当前目录在 git submodule 内,SillySpec worktree 不支持在 submodule 中创建。' +
429
- '\n请在主仓库根目录执行 execute。'
430
- );
431
- }
432
- if (isolation.inWorktree) {
433
- // 已在 linked worktree 中,复用当前目录作为 worktree 路径
434
- console.log(`ℹ️ 已在 linked worktree 中(git-dir: ${isolation.gitDir}),复用当前隔离环境。`);
435
-
436
- // 幂等守卫:meta 已存在时不重新 overlay baseline
437
- const existingMeta = this.getMeta(name)
438
- if (existingMeta) {
439
- return { branch: existingMeta.branch, worktreePath: existingMeta.worktreePath, baseHash: existingMeta.baseHash, mode: existingMeta.mode }
440
- }
441
-
442
- // meta 不存在但已在 worktree 内:可能是 meta 被损坏/误删。
443
- // 绝对禁止 overlay baseline(source === target 会冲突),
444
- // 只恢复 meta 引用,不触碰文件系统。
445
- return this._recoverNativeWorktreeMeta(name, {
446
- worktreePath: this.cwd,
447
- branch: gitQuiet(this.cwd, ['symbolic-ref', '--short', 'HEAD']) || 'detached',
448
- });
449
- }
450
-
451
- // 1. 检查 worktree 目录是否被 gitignore
452
- const ignoreStatus = checkWorktreeDirIgnored(this.cwd);
453
- if (!ignoreStatus.ignored) {
454
- throw new Error(
455
- `worktree 存储目录 ${ignoreStatus.path} 未被 .gitignore 忽略,` +
456
- `创建 worktree 可能导致内容被误提交。\n` +
457
- `请先在 .gitignore 中添加: ${ignoreStatus.path}/\n` +
458
- `或运行 sillyspec doctor 检查修复。`
459
- );
460
- }
461
-
462
- // 2. 检查 worktree 是否已存在
463
- if (existsSync(worktreePath)) {
464
- // 目录在但 meta.json 不存在(幽灵状态)—— 删之前必须确认无未提交改动,
465
- // 否则会丢失 execute 期间未 commit 的代码(不可恢复,3.22.4 修复)。
466
- if (!this.getMeta(name)) {
467
- let uncommitted = '';
468
- try { uncommitted = git(worktreePath, ['status', '--porcelain'], { timeout: 30000 }) } catch {}
469
- if (uncommitted.trim()) {
470
- throw new Error(
471
- `检测到幽灵 worktree(无 meta.json)但含未提交改动,拒绝自动清理(防丢代码)。\n` +
472
- ` 目录:${worktreePath}\n` +
473
- ` 请先检查/commit/备份该目录,再手动清理:sillyspec worktree cleanup ${name} --force\n` +
474
- ` (未提交文件数:${uncommitted.trim().split('\n').length})`
475
- );
476
- }
477
- console.log(`⚠️ 检测到幽灵 worktree 目录(无 meta.json,无未提交改动),自动清理...`);
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 自建——统一交由下方分支决策菜单处置)。
487
- try { gitQuiet(this.cwd, ['worktree', 'prune'], { timeout: 30000 }); } catch {}
488
- } else {
489
- throw new Error(`worktree already exists: ${name}. Run cleanup first.`);
490
- }
491
- }
492
-
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
- );
507
- }
508
-
509
- // 3. 解析 base 分支
510
- let baseBranch = base;
511
- let baseHash;
512
- if (baseBranch) {
513
- baseHash = git(this.cwd, ['rev-parse', baseBranch]);
514
- } else {
515
- // 默认用当前 HEAD
516
- baseBranch = gitQuiet(this.cwd, ['symbolic-ref', '--short', 'HEAD']) || git(this.cwd, ['rev-parse', 'HEAD']);
517
- baseHash = git(this.cwd, ['rev-parse', 'HEAD']);
518
- }
519
-
520
- // 4. 创建 worktree 根目录
521
- if (!existsSync(this.worktreeBase)) {
522
- mkdirSync(this.worktreeBase, { recursive: true });
523
- }
524
-
525
- // 4.5 Windows 长路径支持:archive/ 下嵌套的 .runtime/artifacts 超长文件名(>260 字符)
526
- // 会让 worktree add 的 checkout 报 "Filename too long" 失败 → 降级 in-place 且主工作区
527
- // 未切分支,直接写代码污染 main(见缺陷 execute-in-place-windows-pitfalls 坑1)。
528
- // core.longpaths=true 让 git 用 \\?\ 前缀绕过 MAX_PATH,幂等、Windows 推荐、低风险,失败不阻断。
529
- if (process.platform === 'win32') {
530
- try { gitQuiet(this.cwd, ['config', 'core.longpaths', 'true']); } catch {}
531
- }
532
-
533
- // 5. 创建 worktree(含版本检测 + sandbox fallback)
534
- try {
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
- }
546
- } catch (e) {
547
- const check = isGitWorktreeSupported(this.cwd);
548
- if (!check.supported) {
549
- throw new Error(`git worktree add 失败: ${e.stderr || e.message}\n\n${check.reason ? `原因: ${check.reason}` : ''}\n建议: 升级 git 到 >= 2.15;或运行 \`sillyspec worktree doctor --fix\` 检查 worktree 状态。`);
550
- }
551
- // 体检 BUG-16 并发竞态防御:多 agent 同时首建同名 change 时,败者的 add 失败可能只是
552
- // 「赢家刚建成目录/分支」。此时降级 in-place 会造成一个 worktree + 一个 in-place 的
553
- // 分裂状态(两 agent 各写各的基线)——先重查,并发赢家已建成则按 already exists 抛错。
554
- if (existsSync(worktreePath) || gitQuiet(this.cwd, ['rev-parse', '--verify', `refs/heads/${branch}`])) {
555
- throw new Error(`worktree already exists: ${name}(并发创建,另一进程已抢先建成,本进程不降级 in-place). Run cleanup first.`);
556
- }
557
- // sandbox/permission fallback: 降级为 in-place + baseline protection
558
- console.log(`⚠️ git worktree add 失败(可能是沙箱权限限制),降级为 in-place 模式 + baseline protection`);
559
- console.log(` 原因: ${e.stderr || e.message}`);
560
- return this._createInPlaceMeta(name, {
561
- worktreePath: this.cwd,
562
- branch,
563
- baseBranch,
564
- baseHash,
565
- mode: 'in-place-fallback',
566
- });
567
- }
568
-
569
- // 5.4b 立即写占位 meta(防 create 中断导致幽灵 worktree:目录在 + meta 没 →
570
- // 下次 create 误判幽灵强删)。后续 fetch/overlay/provision 步骤若抛错,占位
571
- // meta 让 getMeta 返回非 null,下次 create 走 "already exists" 分支(保护
572
- // worktree 内任何已写入的内容,不触发幽灵清理)。最终完整 meta 在 step 6 覆盖。
573
- try {
574
- const placeholderMeta = {
575
- name_zh: 'worktree 元数据',
576
- changeName: name,
577
- branch,
578
- baseBranch,
579
- baseHash,
580
- worktreePath,
581
- mode: 'worktree',
582
- createdAt: new Date().toISOString(),
583
- provisioning: true,
584
- };
585
- writeMetaAtomic(join(worktreePath, META_FILE), placeholderMeta);
586
- } catch (e) {
587
- // 占位 meta 是「防 create 中断 → 幽灵强删」的守卫。写失败不能静默:否则中断后
588
- // getMeta 仍返回 null,下次 create 会把含 gitignored 改动的 worktree 当幽灵删掉。
589
- console.warn(`⚠️ 占位 meta 写入失败: ${e.message}(若 create 中断,下次可能误判幽灵 worktree)`);
590
- }
591
-
592
- // 5.5 base 同步检测(只读:不 ff、不改 HEAD;best-effort fetch 失败降级用缓存)。
593
- // 旧逻辑 fetch + merge --ff-only:分叉时 ff 失败被静默吞(syncStatus=failed),成功时
594
- // baseHash 锚点又不更新(ff 引入的 main 内容污染 apply patch)。现改为只检测 + 报告,
595
- // 不阻断 create,对齐 origin 的动作留给用户/agent。
596
- const syncDiagnostic = computeBaseSync(this.cwd, baseHash);
597
- printSyncReport(syncDiagnostic, baseHash, name);
598
-
599
- // 5.6 Dirty baseline overlay:将主工作区未提交变更同步到 worktree
600
- const baselineResult = this._overlayBaseline(this.cwd, worktreePath);
601
- const baselineFiles = baselineResult.files;
602
- const baselineHash = baselineResult.baselineHash;
603
-
604
- // 5.7 创建 baseline checkpoint(有 dirty baseline 时才创建)
605
- let baselineCommit = null;
606
- if (adoptedBranch) baselineCommit = baseHash; // adopt:分支 HEAD 恒作交付 diff 锚(无 dirty overlay 也要锚定)
607
- if (baselineFiles.length > 0) {
608
- baselineCommit = this._createBaselineCheckpoint(worktreePath, name, baselineFiles);
609
- }
610
-
611
- // 5.8 依赖供给(change 2026-06-28-worktree-deps-provision)
612
- // baseline overlay 后让 worktree 立即可构建/测试;失败不阻断 create,只记 meta。
613
- let deps = {};
614
- try {
615
- deps = provisionDeps(worktreePath, this.cwd, { specBase: join(this.cwd, '.sillyspec') }) || {};
616
- } catch (e) {
617
- deps = { depsStatus: 'failed', depsError: `provisionDeps crashed: ${e.message}` };
618
- }
619
-
620
- // 6. 写入 meta.json
621
- const meta = {
622
- name_zh: 'worktree 元数据',
623
- changeName: name,
624
- branch,
625
- baseBranch,
626
- baseHash,
627
- actualBaseHash: gitQuiet(worktreePath, ['rev-parse', 'HEAD']) || baseHash,
628
- createdAt: new Date().toISOString(),
629
- worktreePath,
630
- mode: 'worktree',
631
- baselineFiles,
632
- baselineCommit,
633
- baselineHash,
634
- syncDiagnostic,
635
- depsStatus: deps.depsStatus,
636
- depsMethod: deps.depsMethod || null,
637
- depsSource: deps.depsSource || null,
638
- depsLockHash: deps.depsLockHash || null,
639
- depsCheckedAt: deps.depsCheckedAt || null,
640
- ...(deps.depsError ? { depsError: deps.depsError } : {}),
641
- ...(adoptedBranch ? { adoptedBranch: true } : {}),
642
- };
643
-
644
- const metaPath = join(worktreePath, META_FILE);
645
- writeMetaAtomic(metaPath, meta);
646
-
647
- return { branch, worktreePath, baseHash, mode: meta.mode, syncDiagnostic, ...(adoptedBranch ? { adoptedBranch: true } : {}) };
648
- }
649
-
650
- /**
651
- * native-worktree 模式下恢复 meta 引用
652
- * 当 meta.json 被损坏/误删时,只重建 meta 文件,不触碰文件系统(不 overlay)
653
- * @private
654
- */
655
- _recoverNativeWorktreeMeta(name, { worktreePath, branch }) {
656
- const baseHash = gitQuiet(worktreePath, ['rev-parse', 'HEAD']) || null
657
- const meta = {
658
- name_zh: 'worktree 元数据',
659
- changeName: name,
660
- branch: branch || BRANCH_PREFIX + name,
661
- baseBranch: branch,
662
- baseHash,
663
- actualBaseHash: baseHash,
664
- createdAt: new Date().toISOString(),
665
- worktreePath,
666
- mode: 'native-worktree',
667
- baselineFiles: [],
668
- baselineCommit: null,
669
- baselineHash: null,
670
- recoveredAt: new Date().toISOString(),
671
- recoveryNote: 'meta was missing in native-worktree; recovered without baseline overlay',
672
- }
673
- if (!existsSync(this.worktreeBase)) mkdirSync(this.worktreeBase, { recursive: true })
674
- const metaDir = join(this.worktreeBase, name)
675
- if (!existsSync(metaDir)) mkdirSync(metaDir, { recursive: true })
676
- writeMetaAtomic(join(metaDir, META_FILE), meta)
677
- console.log(`🔗 native-worktree meta 已恢复: ${metaDir}/meta.json`)
678
- return { branch: meta.branch, worktreePath, baseHash, mode: meta.mode }
679
- }
680
-
681
- /**
682
- * 创建 in-place 模式的 meta.json(降级路径)
683
- * 不创建 git worktree,直接在当前目录记录 baseline 并写入 meta
684
- * @private
685
- */
686
- _createInPlaceMeta(name, { worktreePath, branch, baseBranch, baseHash, mode } = {}) {
687
- // 幂等守卫:meta 已存在时不重新创建(避免 overlay baseline 和已有改动冲突)
688
- const existingMeta = this.getMeta(name)
689
- if (existingMeta) {
690
- return { branch: existingMeta.branch, worktreePath: existingMeta.worktreePath, baseHash: existingMeta.baseHash, mode: existingMeta.mode }
691
- }
692
-
693
- // 供给 deps(与 native worktree 路径一致)。in-place-fallback 模式漏写 depsStatus 会致
694
- // enforceDepsGate(run.js)把 undefined 当 unknown 阻断 execute --done,死锁无法推进。
695
- // 见 docs/sillyspec/execute-inplace-deps-gate.md(2026-07-08 发现)。
696
- let deps = {}
697
- try {
698
- deps = provisionDeps(worktreePath, this.cwd, { specBase: join(this.cwd, '.sillyspec') }) || {}
699
- } catch (e) {
700
- deps = { depsStatus: 'failed', depsError: `provisionDeps crashed: ${e.message}` }
701
- }
702
-
703
- // 硬规则:禁止 self-overlay(source 和 target 相同时 overlay 必然冲突)
704
- const resolvedSource = resolve(this.cwd)
705
- const resolvedTarget = resolve(worktreePath)
706
- if (resolvedSource === resolvedTarget) {
707
- console.warn('⚠️ 跳过 baseline overlay:当前目录与目标目录相同(native-worktree 或 in-place 模式)')
708
- // 写 meta 但不 overlay
709
- baseBranch = baseBranch || gitQuiet(this.cwd, ['symbolic-ref', '--short', 'HEAD']) || gitQuiet(this.cwd, ['rev-parse', 'HEAD'])
710
- baseHash = baseHash || git(this.cwd, ['rev-parse', 'HEAD'])
711
- const meta = {
712
- name_zh: 'worktree 元数据',
713
- changeName: name,
714
- branch: branch || BRANCH_PREFIX + name,
715
- baseBranch,
716
- baseHash,
717
- actualBaseHash: gitQuiet(worktreePath, ['rev-parse', 'HEAD']) || baseHash,
718
- createdAt: new Date().toISOString(),
719
- worktreePath,
720
- mode: mode || 'in-place-fallback',
721
- baselineFiles: [],
722
- baselineCommit: null,
723
- baselineHash: null,
724
- ...deps,
725
- }
726
- if (!existsSync(this.worktreeBase)) mkdirSync(this.worktreeBase, { recursive: true })
727
- const metaDir = join(this.worktreeBase, name)
728
- if (!existsSync(metaDir)) mkdirSync(metaDir, { recursive: true })
729
- writeMetaAtomic(join(metaDir, META_FILE), meta)
730
- return { branch: meta.branch, worktreePath, baseHash, mode: meta.mode }
731
- }
732
-
733
- // 解析 base
734
- if (!baseHash) {
735
- baseBranch = baseBranch || gitQuiet(this.cwd, ['symbolic-ref', '--short', 'HEAD']) || gitQuiet(this.cwd, ['rev-parse', 'HEAD']);
736
- baseHash = git(this.cwd, ['rev-parse', 'HEAD']);
737
- }
738
-
739
- const baselineResult = this._overlayBaseline(this.cwd, this.cwd);
740
- const baselineFiles = baselineResult.files;
741
- const baselineHash = baselineResult.baselineHash;
742
-
743
- let baselineCommit = null;
744
- if (baselineFiles.length > 0) {
745
- baselineCommit = this._createBaselineCheckpoint(this.cwd, name, baselineFiles);
746
- }
747
-
748
- const meta = {
749
- name_zh: 'worktree 元数据',
750
- changeName: name,
751
- branch: branch || BRANCH_PREFIX + name,
752
- baseBranch,
753
- baseHash,
754
- actualBaseHash: gitQuiet(worktreePath, ['rev-parse', 'HEAD']) || baseHash,
755
- createdAt: new Date().toISOString(),
756
- worktreePath,
757
- mode: mode || 'in-place-fallback',
758
- baselineFiles,
759
- baselineCommit,
760
- baselineHash,
761
- ...deps,
762
- };
763
-
764
- // in-place 模式下 meta 写入 worktreeBase(避免污染主工作区)
765
- if (!existsSync(this.worktreeBase)) {
766
- mkdirSync(this.worktreeBase, { recursive: true });
767
- }
768
- const metaPath = join(this.worktreeBase, name, META_FILE);
769
- const metaDir = join(this.worktreeBase, name);
770
- if (!existsSync(metaDir)) {
771
- mkdirSync(metaDir, { recursive: true });
772
- }
773
- writeMetaAtomic(metaPath, meta);
774
-
775
- return { branch: meta.branch, worktreePath, baseHash, mode: meta.mode };
776
- }
777
-
778
- /**
779
- * 构建 isolation 信息对象,用于写入 sillyspec.db(_writeIsolationToDB,isolation_status 列)
780
- * @param {string} changeName
781
- * @returns {{ status: string, mode: string, path: string } | null}
782
- */
783
- getIsolationInfo(changeName) {
784
- const meta = this.getMeta(changeName);
785
- if (!meta) return null;
786
-
787
- const mode = meta.mode || 'worktree';
788
- const statusMap = {
789
- 'worktree': 'verified',
790
- 'native-worktree': 'verified',
791
- 'in-place-fallback': 'degraded',
792
- };
793
-
794
- return {
795
- status: statusMap[mode] || 'verified',
796
- mode,
797
- path: meta.worktreePath,
798
- branch: meta.branch,
799
- };
800
- }
801
-
802
- /**
803
- * 获取 worktree 的运行模式
804
- * @param {string} changeName
805
- * @returns {'worktree'|'native-worktree'|'in-place-fallback'|null}
806
- */
807
- getMode(changeName) {
808
- const meta = this.getMeta(changeName);
809
- return meta?.mode || null;
810
- }
811
-
812
- /**
813
- * 列出所有活跃 worktree
814
- * @returns {Array<{ changeName: string, branch: string, baseHash: string, createdAt: string, worktreePath: string }>}
815
- */
816
- list() {
817
- const results = [];
818
- if (!existsSync(this.worktreeBase)) return results;
819
-
820
- const entries = readdirSync(this.worktreeBase, { withFileTypes: true });
821
- for (const entry of entries) {
822
- if (!entry.isDirectory()) continue;
823
- const metaPath = join(this.worktreeBase, entry.name, META_FILE);
824
- if (!existsSync(metaPath)) continue;
825
- const meta = parseJSON(readFileSync(metaPath, 'utf8'));
826
- if (!meta) continue;
827
- results.push({
828
- changeName: meta.changeName,
829
- branch: meta.branch,
830
- baseHash: meta.baseHash,
831
- baseBranch: meta.baseBranch,
832
- createdAt: meta.createdAt,
833
- worktreePath: meta.worktreePath,
834
- mode: meta.mode || 'worktree',
835
- });
836
- }
837
-
838
- return results;
839
- }
840
-
841
- /**
842
- * 清理 worktree(仅限 SillySpec 创建的临时 worktree)
843
- * 幂等:重复调用不报错。
844
- * 三重清理:git worktree 注册 + worktree 目录 + meta 目录。
845
- * @param {string} changeName
846
- * @param {{ force?: boolean, maxRetries?: number }} opts
847
- * @returns {{ result: 'blocked'|'cleaned'|'force-cleaned'|'skipped'|'kept'|'partial', mode: string|null, details: string[], residual: string[] }}
848
- * result 取值:blocked=有未落主仓交付变更,fail-closed 拒绝清理(需 force 绕过,D-001@v1);
849
- * cleaned=git remove 成功;force-cleaned=git remove 失败但 fallback 清理完成;
850
- * partial=有残留(目录/meta/git 注册未清);skipped=无需清理;kept=native-worktree 保留。
851
- * residual:未清干净的路径/引用列表(空数组表示干净)。
852
- */
853
- /**
854
- * fail-closed:清理删分支前的审计引用校验(2026-08-18,两例实录:execute --done 批量完成 /
855
- * worktree apply 后自动 cleanup 均无条件删分支 ref,task commit 变 dangling)。
856
- * apply 只复制文件内容不携带 commit(主仓重 commit 后 hash 不同),分支 ref 一删,
857
- * task review.json 的 base/head 引用即悬空(gc 后真丢,git diff base..head 无法复核)。
858
- * 有引用 → cleanup 保留分支并提示手动删;校验自身异常也按"有引用"处理(宁保留勿误删)。
859
- * @private
860
- * @param {string} branch - 待删分支名
861
- * @returns {string[]} 引用该分支 commit 的 review.json 路径列表(空 = 无引用,删分支安全)
862
- */
863
- _branchReviewReferences(branch) {
864
- const runsDir = join(this.cwd, '.sillyspec', '.runtime', 'execute-runs');
865
- if (!existsSync(runsDir)) return [];
866
- const branchCommits = new Set(
867
- (gitQuiet(this.cwd, ['rev-list', branch]) || '').split('\n').map(s => s.trim()).filter(Boolean)
868
- );
869
- if (branchCommits.size === 0) return [];
870
- const refs = [];
871
- const visit = (dir) => {
872
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
873
- const p = join(dir, entry.name);
874
- if (entry.isDirectory()) visit(p);
875
- else if (entry.name === 'review.json') {
876
- try {
877
- const r = JSON.parse(readFileSync(p, 'utf8'));
878
- for (const key of ['base', 'head']) {
879
- const h = typeof r[key] === 'string' ? r[key].trim() : '';
880
- if (h && branchCommits.has(h)) { refs.push(p); break; }
881
- }
882
- } catch { /* review.json 损坏不参与判定 */ }
883
- }
884
- }
885
- };
886
- visit(runsDir);
887
- return refs;
888
- }
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
-
953
- cleanup(changeName, { force = false, maxRetries = 3 } = {}) {
954
- const name = validateChangeName(changeName);
955
- const meta = this.getMeta(name);
956
- const worktreePath = this.getWorktreePath(name);
957
- const metaDir = join(this.worktreeBase, name);
958
- const details = [];
959
-
960
- // 幂等:什么都不存在 → 直接跳过
961
- if (!meta && !existsSync(worktreePath) && !existsSync(metaDir)) {
962
- return { result: 'skipped', mode: null, details };
963
- }
964
-
965
- const mode = meta?.mode || 'worktree';
966
- // in-place 模式:worktreePath === 主工作区,绝对禁止删除目录本身,但 meta 目录仍应清理
967
- // (否则永久残留)。native-worktree:外部隔离环境,整体跳过。
968
- const isInPlace = mode === 'in-place-fallback';
969
-
970
- // 安全检查:native-worktree 是外部隔离环境,非 force 不碰
971
- if (!force && mode === 'native-worktree') {
972
- return { result: 'kept', mode, details: ['native-worktree: 外部隔离环境,跳过清理'], residual: [] };
973
- }
974
-
975
- // fail-closed 保护(D-001@v1):junction 解链与 git worktree remove --force 之前,检查未落主仓交付变更。
976
- // 清理即蒸发:worktree 有未 commit / 未 apply 到主仓 HEAD 的交付文件,拒绝清理,需显式 --force 绕过。
977
- // hasUnappliedChanges 判定 main HEAD(byte-identical),git apply --3way 不 commit → apply 后仍判 true,
978
- // 故 apply 后自动 cleanup 与 execute reset 显式传 force:true 绕过(D-006)。in-place / native-worktree
979
- // 由 hasUnappliedChanges 内部返回 hasChanges:false,自然跳过保护,零回归。
980
- if (!force) {
981
- const check = this.hasUnappliedChanges(name);
982
- if (check.hasChanges) {
983
- console.error(`🚫 worktree cleanup 拒绝:${check.changedFiles.length} 个交付变更未落地主工作区 HEAD,清理会丢失代码。`);
984
- for (const f of check.changedFiles) console.error(` ${f}`);
985
- console.error(' 请先落地(sillyspec worktree apply <name>)或 commit 到分支,或显式 --force 强制清理。');
986
- return { result: 'blocked', mode, details: [...details, 'blocked: uncommitted deliverable changes'], residual: [] };
987
- }
988
- }
989
-
990
- const branch = (meta && meta.branch) || BRANCH_PREFIX + name;
991
-
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)。
1001
- if (!isInPlace && existsSync(worktreePath)) {
1002
- unlinkNodeModulesLinks(worktreePath, meta, details)
1003
- }
1004
-
1005
- // 1. git worktree remove(带 retry)—— in-place 跳过:无 git worktree 注册,且 worktreePath 即主工作区
1006
- let gitRemoveOk = false;
1007
- if (!isInPlace && existsSync(worktreePath)) {
1008
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
1009
- try {
1010
- git(this.cwd, ['worktree', 'remove', worktreePath, '--force'], { timeout: 60000 });
1011
- gitRemoveOk = true;
1012
- details.push(`git worktree remove succeeded (attempt ${attempt})`);
1013
- break;
1014
- } catch (e) {
1015
- details.push(`git worktree remove attempt ${attempt}/${maxRetries} failed: ${e.message}`);
1016
- if (attempt < maxRetries) {
1017
- // 短暂等待后重试(跨平台 busy-wait,见 sleepMs)
1018
- sleepMs(500);
1019
- }
1020
- }
1021
- }
1022
- }
1023
-
1024
- // 2. fallback: 确保 worktree 目录已删除(in-place 跳过——worktreePath 是主工作区)
1025
- if (!isInPlace && existsSync(worktreePath)) {
1026
- try {
1027
- rmSync(worktreePath, { recursive: true, force: true });
1028
- details.push('worktree directory force-removed (fallback)');
1029
- } catch (e) {
1030
- details.push(`worktree directory force-remove failed: ${e.message}`);
1031
- }
1032
- }
1033
-
1034
- // 3. git worktree prune(清理 git 内部注册信息)
1035
- try {
1036
- gitQuiet(this.cwd, ['worktree', 'prune'], { timeout: 30000 });
1037
- } catch {
1038
- // prune 失败不阻断
1039
- }
1040
-
1041
- // 4. 删除分支(fail-closed:task review 引用可达性校验。force 也不绕过——force 语义 =
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
1048
- // 升级(坑 cleanup-branch-review-anchor-tag,2026-08-21 实证):分支被 review.json 引用
1049
- // 时不再只能手动保留——打 `sillyspec-audit/<branch>` 轻量 tag 锚定分支 tip(ref 前缀独立
1050
- // 于 sillyspec/* 分支族,doctor 孤儿分支扫描不误伤),commit 经 tag 保持可达(gc 安全),
1051
- // 随后正常删分支。tag 创建失败 → 回退保留(宁保留勿丢审计链)。
1052
- try {
1053
- const reviewRefs = this._branchReviewReferences(branch);
1054
- if (reviewRefs.length > 0) {
1055
- const tagName = 'sillyspec-audit/' + branch;
1056
- let tagOk = false;
1057
- try {
1058
- if (!gitQuiet(this.cwd, ['rev-parse', '--verify', '--quiet', `refs/tags/${tagName}`])) {
1059
- git(this.cwd, ['tag', tagName, branch]);
1060
- }
1061
- tagOk = true;
1062
- } catch (e) {
1063
- details.push(`audit tag creation failed: ${e.message}`);
1064
- }
1065
- if (tagOk) {
1066
- gitQuiet(this.cwd, ['branch', '-D', branch]);
1067
- details.push(`branch deleted after anchoring tip to tag ${tagName} (audit 链可达)`);
1068
- console.log(`🔗 审计锚定:${branch} 被 ${reviewRefs.length} 个 task review.json 引用其 commit——已打 tag ${tagName} 锚定(commit 保持可达,gc 安全)并删除分支 ref。`);
1069
- console.log(` 确认不再需要该审计链后可删 tag:git tag -d ${tagName}`);
1070
- } else {
1071
- details.push(`branch kept: ${reviewRefs.length} 个 task review.json 引用分支上的 commit(base/head 审计保护)`);
1072
- console.log(`🔗 分支保留:${branch} 上有 ${reviewRefs.length} 个 task review.json 引用其 commit(apply 只复制文件内容,ref 删除后 base/head 悬空无法复核)。确要删除:git branch -D ${branch}`);
1073
- }
1074
- } else {
1075
- gitQuiet(this.cwd, ['branch', '-D', branch]);
1076
- details.push('branch deleted');
1077
- }
1078
- } catch {
1079
- // 分支可能已被删除(幂等跳过);引用校验自身异常也归入此分支——不因校验失败而误删
1080
- }
1081
-
1082
- // 5. 清除 meta 目录(in-place 模式也执行——这是 in-place meta 残留的修复点)
1083
- if (existsSync(metaDir)) {
1084
- try {
1085
- rmSync(metaDir, { recursive: true, force: true });
1086
- details.push('meta directory cleaned');
1087
- } catch (e) {
1088
- details.push(`meta directory cleanup failed: ${e.message}`);
1089
- }
1090
- }
1091
-
1092
- // 6. 最终验证:确认清理完成(in-place 模式 worktreePath=主工作区,不纳入残留检查)
1093
- const residual = [];
1094
- if (!isInPlace && existsSync(worktreePath)) residual.push(`worktree dir: ${worktreePath}`);
1095
- if (existsSync(metaDir)) residual.push(`meta dir: ${metaDir}`);
1096
- // 斜杠方向归一后比较(体检 BUG-07):Windows 下 git worktree list 输出正斜杠、
1097
- // worktreePath 是反斜杠,直接 includes 恒 false → 残留场景漏报、cleanup 误报 cleaned
1098
- const toPosixNorm = (p) => String(p || '').replace(/\\/g, '/').toLowerCase()
1099
- const wtListOut = gitQuiet(this.cwd, ['worktree', 'list'], { timeout: 30000 })
1100
- if (!isInPlace && wtListOut && toPosixNorm(wtListOut).includes(toPosixNorm(worktreePath))) {
1101
- residual.push('git worktree list still references this worktree');
1102
- }
1103
- if (residual.length > 0) {
1104
- details.push(`⚠️ 残留: ${residual.join('; ')}`);
1105
- }
1106
-
1107
- // result:有残留→partial;in-place(无隔离目录可删,只清了 meta)→cleaned;否则按 git remove 成败
1108
- let result;
1109
- if (residual.length > 0) {
1110
- result = 'partial';
1111
- } else if (isInPlace) {
1112
- result = 'cleaned';
1113
- } else {
1114
- result = gitRemoveOk ? 'cleaned' : 'force-cleaned';
1115
- }
1116
- return { result, mode, details, residual };
1117
- }
1118
-
1119
- /**
1120
- * worktree 健康检查 + 可选修复
1121
- * 检查项:
1122
- * - git worktree list 中的孤儿条目(目录不存在)
1123
- * - worktree 目录存在但 git 不认识
1124
- * - meta 存在但 worktree 目录不存在
1125
- * - worktree 目录存在但 meta 不存在(幽灵目录)
1126
- * - SillySpec 分支残留(sillyspec/* 但无对应 meta)
1127
- * - 超过指定小时的过期 worktree
1128
- *
1129
- * @param {{ fix?: boolean, staleHours?: number }} opts
1130
- * @returns {{ issues: Array<{ type: string, name: string, detail: string, fixable: boolean }>, fixed: string[], unfixable: string[] }}
1131
- */
1132
- /**
1133
- * doctor --fix 的依赖重供给:先解 worktree/node_modules junction(保护主仓 node_modules),
1134
- * 再 provisionDeps(force:true) 强制走 install 分支重装。
1135
- *
1136
- * Windows 保护(与 cleanup 722-743 同源坑):不解链直接 install 会经 junction 误改主仓
1137
- * node_modules 内容。in-place-fallback 无独立 node_modules(worktreePath 即主仓),跳过解链,
1138
- * 仅 install。force=true 绕过 provisionDeps 的 lockfile 一致快路径,确保真重装而非幂等 linked。
1139
- *
1140
- * @param {string} name - changeName
1141
- * @param {string} wtPath - worktree 根目录(meta.worktreePath)
1142
- * @returns {{ ok: boolean, msg: string }}
1143
- */
1144
- _doctorReprovision(name, wtPath, opts = {}) {
1145
- try {
1146
- const meta = this.getMeta(name) || {};
1147
- const isInPlace = meta.mode === 'in-place-fallback';
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)
1151
- if (!isInPlace && existsSync(wtPath)) {
1152
- unlinkNodeModulesLinks(wtPath, meta)
1153
- }
1154
- // 触发分流(坑 doctor-reprovision-junction-missing,2026-08-22 实证:junction 未建的
1155
- // missing/failed 场景被 force install 强制重装——install 静默失败面大且慢;lockfile 一致时
1156
- // 重建 junction 才是对症动作。opts.relinkFirst(missing/failed 触发)→ 非 force 跑:解链后
1157
- // node_modules 不存在,tryLink 直接重建;lockfile 漂移自动落 install。stale/main-drift 维持
1158
- // force 重装(依赖确实变了)。
1159
- const deps = provisionDeps(wtPath, this.cwd, {
1160
- specBase: join(this.cwd, '.sillyspec'),
1161
- force: !opts.relinkFirst,
1162
- }) || {};
1163
- const metaPath = join(this.getWorktreePath(name), META_FILE);
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;
1171
- const merged = { ...meta, ...deps };
1172
- if (!hasDepError) delete merged.depsError;
1173
- writeMetaAtomic(metaPath, merged);
1174
- const msg = `re-provisioned ${name}: depsStatus=${deps.depsStatus}` + (deps.depsError ? `;⚠️ ${deps.depsError}` : '');
1175
- return hasDepError ? { ok: false, msg } : { ok: true, msg };
1176
- } catch (e) {
1177
- return { ok: false, msg: `re-provision failed for ${name}: ${e.message}` };
1178
- }
1179
- }
1180
-
1181
- /**
1182
- * worktree 健康检查 + 可选修复
1183
- * 检查项:
1184
- * - git worktree list 中的孤儿条目(目录不存在)
1185
- * - worktree 目录存在但 git 不认识
1186
- * - meta 存在但 worktree 目录不存在
1187
- * - worktree 目录存在但 meta 不存在(幽灵目录)
1188
- * - SillySpec 分支残留(sillyspec/* 但无对应 meta)
1189
- * - 超过指定小时的过期 worktree
1190
- * - deps 依赖状态(failed/missing/stale/main-drift,复用 checkDepsFreshness 统一判定)
1191
- *
1192
- * @param {{ fix?: boolean, staleHours?: number, changeName?: string|null }} opts
1193
- * - changeName:非 null 时仅扫描该 change(deps/ghost/stale/orphan-git/orphan-branch 全部按 changeName 过滤);
1194
- * 不传则全量扫(兼容现有行为)。
1195
- * @returns {{ issues: Array<{ type: string, name: string, detail: string, fixable: boolean }>, fixed: string[], unfixable: string[] }}
1196
- */
1197
- async doctor({ fix = false, staleHours = 24, changeName = null } = {}) {
1198
- const issues = [];
1199
- const fixed = [];
1200
- const unfixable = [];
1201
-
1202
- // 活跃变更注册表(坑 doctor-fix-orphan-branch-parallel-active,2026-08-20 实证):孤儿分支
1203
- // 判定原只看本地 meta 目录注册表(metaNames),与变更活跃态的权威注册表(进度库 changes 表)
1204
- // 数据源不一致——并行会话的活跃变更(meta 已清/in-place/平台模式 meta 在别处)分支会被全局
1205
- // doctor --fix 误删。删分支前交叉核对:分支名 ∈ 活跃变更 → 保留(fixable:false 提示人工确认)。
1206
- // 先探 DB 文件存在再实例化 ProgressManager(坑7 读路径建库:_ensureDB 不存在会建库污染)。
1207
- // null = 无法核对(读失败 或 无进度库——坑 worktree-user-branch-conflict 2026-08-24 收紧:
1208
- // 无库时无法区分孤儿与用户自建分支,从「照删」改保守保留,git-only 便利让位于不误删);
1209
- // Set = 进度库可读(空集=无活跃变更,非活跃孤儿仍可删)。
1210
- let activeChanges = null;
1211
- let dbMissing = false;
1212
- try {
1213
- const specBaseOfWt = dirname(dirname(this.worktreeBase)); // <specBase>(.runtime/worktrees 上两级)
1214
- if (existsSync(join(specBaseOfWt, '.runtime', 'sillyspec.db'))) {
1215
- const { ProgressManager } = await import('./progress.js');
1216
- activeChanges = new Set(new ProgressManager({ specDir: specBaseOfWt }).listChanges(this.cwd));
1217
- } else {
1218
- activeChanges = null;
1219
- dbMissing = true;
1220
- }
1221
- } catch (e) {
1222
- console.warn(`⚠️ doctor 进度库读取失败,孤儿分支的活跃态交叉核对不可用(保守不自动删): ${e.message}`);
1223
- activeChanges = null;
1224
- }
1225
-
1226
- // 1. 列出 git worktree list 中的条目
1227
- let gitWorktreeList = [];
1228
- try {
1229
- const raw = git(this.cwd, ['worktree', 'list', '--porcelain'], { timeout: 30000 });
1230
- const entries = raw.split(/\n\n/).filter(Boolean);
1231
- for (const entry of entries) {
1232
- const lines = entry.split('\n');
1233
- const wtPath = lines.find(l => l.startsWith('worktree '))?.replace('worktree ', '');
1234
- // git 2.20+ porcelain 在目录缺失时输出 `missing` 行;作为 existsSync 的权威交叉验证
1235
- const missing = lines.some(l => l === 'missing');
1236
- if (wtPath && wtPath !== this.cwd) { // 排除主工作区
1237
- gitWorktreeList.push({ path: wtPath, missing, raw: entry });
1238
- }
1239
- }
1240
- } catch {
1241
- // git worktree 不可用,跳过
1242
- }
1243
-
1244
- // 2. 列出 SillySpec meta 条目
1245
- const metaEntries = this.list();
1246
- const metaNames = new Set(metaEntries.map(m => m.changeName));
1247
-
1248
- // 3. 检查 git worktree list 中的孤儿条目
1249
- // ⚠️ 只在 git 自己标记 missing 时自动 prune。目录不可见但 git 未标记 missing 的
1250
- // 情况(平台模式/容器路径不一致、符号链接、Windows 路径格式、旧 git 无 missing 标记)
1251
- // 只告警不自动 prune —— existsSync 在这些场景会误判,自动 prune 会杀死实际在用的
1252
- // worktree(sillyspec-worktree-platform-mode-bug)。git 内部状态是 worktree 生命周期的
1253
- // 权威来源,用它做 prune 前提可杜绝误杀。
1254
- for (const wt of gitWorktreeList) {
1255
- if (!existsSync(wt.path)) {
1256
- const name = this._pathToChangeName(wt.path);
1257
- if (changeName && name !== changeName) continue; // --change 过滤:仅扫指定 change
1258
- if (wt.missing === true) {
1259
- // git 明确标记目录缺失(git 2.20+)→ 真 orphan,prune 安全
1260
- issues.push({ type: 'orphan-git-entry', name: name || wt.path, detail: `git worktree 标记 missing: ${wt.path}`, fixable: true });
1261
- if (fix) {
1262
- try { gitQuiet(this.cwd, ['worktree', 'prune'], { timeout: 30000 }); fixed.push(`pruned orphan: ${wt.path}`); } catch { unfixable.push(`prune failed for: ${wt.path}`); }
1263
- }
1264
- } else {
1265
- // 目录不可见但 git 未标记 missing → 可能 existsSync 误判,保守不自动 prune
1266
- issues.push({ type: 'orphan-git-entry', name: name || wt.path,
1267
- detail: `git worktree 引用 ${wt.path} 目录不可见但 git 未标记 missing——可能路径/权限导致误判,未自动 prune(避免误杀在用的 worktree)。确认废弃后手动: git worktree prune`,
1268
- fixable: false });
1269
- }
1270
- }
1271
- }
1272
-
1273
- // 4. 扫描 worktreeBase 目录,检查幽灵目录和孤儿 meta
1274
- if (existsSync(this.worktreeBase)) {
1275
- const entries = readdirSync(this.worktreeBase, { withFileTypes: true });
1276
- for (const entry of entries) {
1277
- if (!entry.isDirectory()) continue;
1278
- const name = entry.name;
1279
- if (changeName && name !== changeName) continue; // --change 过滤:仅扫指定 change
1280
- const dirPath = join(this.worktreeBase, name);
1281
- const hasMeta = existsSync(join(dirPath, META_FILE));
1282
- const meta = hasMeta ? this.getMeta(name) : null;
1283
-
1284
- // deps 依赖状态检查(change 2026-06-28-worktree-deps-provision / 2026-08-05-tooling-feedback-fixes)
1285
- // 复用 checkDepsFreshness(H1,worktree-deps.js),优先级 failed→missing→stale→main-drift→fresh。
1286
- // 放宽原 909 in-place-fallback 守卫:in-place 也跑(main-drift/stale/failed 对它同样有意义,
1287
- // 真 in-place 的 wtPath===主仓→wtHash===mainHash→不会误报 main-drift,仅 failed/stale 有意义)。
1288
- // fix 时 _doctorReprovision 自行判断是否解链(in-place 不解链,仅 install)。
1289
- // 归档态前置闸(坑 doctor-reprovision-archived-change,2026-08-21 实证:已归档变更的
1290
- // worktree 被 doctor 当活跃任务 re-provision——给死目录装依赖)。归档判定(changes/archive/
1291
- // 实体 或 进度库 status='archived')命中 → 跳过供给,fix 时走 cleanup(其内建
1292
- // hasUnappliedChanges 护栏仍在,未落仓内容照样拒删)。
1293
- if (meta && meta.worktreePath && existsSync(meta.worktreePath)) {
1294
- const isArchivedChange = existsSync(join(this.cwd, '.sillyspec', 'changes', 'archive', name))
1295
- || this._isChangeArchivedInDb(name);
1296
- if (isArchivedChange) {
1297
- issues.push({ type: 'worktree-archived-change', name, fixable: meta.mode !== 'native-worktree',
1298
- detail: `变更 ${name} 已归档但 worktree 残留——不供给依赖(死目录),建议清理(cleanup 内建未落仓护栏)` });
1299
- if (fix && meta.mode !== 'native-worktree') {
1300
- try {
1301
- const r = this.cleanup(name);
1302
- if (r.result === 'cleaned' || r.result === 'force-cleaned') {
1303
- fixed.push(`cleaned archived-change worktree: ${name}`);
1304
- } else if (r.result === 'blocked') {
1305
- unfixable.push(`cleanup blocked (archived change 有未落仓内容): ${name} — 先 apply/commit 再清`);
1306
- } else {
1307
- unfixable.push(`cleanup skipped (archived change): ${name}`);
1308
- }
1309
- } catch { unfixable.push(`cleanup failed (archived change): ${name}`); }
1310
- }
1311
- } else {
1312
- const wtPath = meta.worktreePath;
1313
- const fresh = checkDepsFreshness(meta, wtPath, this.cwd);
1314
- const issueTypeByStatus = {
1315
- failed: 'deps-failed',
1316
- missing: 'deps-missing',
1317
- stale: 'deps-stale',
1318
- 'main-drift': 'deps-main-drift',
1319
- };
1320
- const issueType = issueTypeByStatus[fresh.status] || null;
1321
- if (issueType) {
1322
- issues.push({ type: issueType, name, detail: fresh.detail, fixable: true });
1323
- if (fix) {
1324
- // relinkFirst:missing/failed 多为 junction 丢失/上次供给失败——link 优先重建;
1325
- // stale/main-drift 是依赖真变了——force 重装
1326
- const r = this._doctorReprovision(name, wtPath, { relinkFirst: issueType === 'deps-missing' || issueType === 'deps-failed' });
1327
- (r.ok ? fixed : unfixable).push(r.msg);
1328
- }
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 */ }
1341
- }
1342
- }
1343
-
1344
- // meta 存在但 worktree 目录不存在
1345
- if (meta && meta.worktreePath && !existsSync(meta.worktreePath)) {
1346
- issues.push({ type: 'meta-no-dir', name, detail: `meta 存在但 worktree 目录不存在: ${meta.worktreePath}`, fixable: true });
1347
- if (fix) {
1348
- try { rmSync(dirPath, { recursive: true, force: true }); fixed.push(`cleaned orphan meta: ${name}`); } catch { unfixable.push(`cleanup failed for: ${name}`); }
1349
- }
1350
- }
1351
-
1352
- // worktree 目录存在但 meta 不存在(幽灵目录)
1353
- if (!hasMeta && existsSync(dirPath)) {
1354
- // 可能是 in-place 模式的 meta-only 目录,或者真正的幽灵
1355
- const files = readdirSync(dirPath);
1356
- if (files.length === 0 || (files.length === 1 && files[0] === META_FILE)) {
1357
- issues.push({ type: 'ghost-dir', name, detail: `空目录/幽灵目录: ${dirPath}`, fixable: true });
1358
- if (fix) {
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)})`); }
1361
- }
1362
- } else {
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 });
1374
- }
1375
- }
1376
-
1377
- // 检查过期 worktree
1378
- if (meta && meta.createdAt) {
1379
- const ageMs = Date.now() - new Date(meta.createdAt).getTime();
1380
- const ageHours = ageMs / (1000 * 60 * 60);
1381
- const staleFixable = meta.mode !== 'native-worktree';
1382
- if (ageHours > staleHours) {
1383
- issues.push({ type: 'stale', name, detail: `worktree 已存在 ${Math.round(ageHours)} 小时(超过 ${staleHours}h 阈值)${staleFixable ? '' : '(native-worktree 外部环境,不可自动清理)'}`, fixable: staleFixable });
1384
- if (fix && staleFixable) {
1385
- try {
1386
- const result = this.cleanup(name);
1387
- if (result.result === 'cleaned' || result.result === 'force-cleaned') {
1388
- fixed.push(`cleaned stale: ${name}`);
1389
- } else if (result.result === 'blocked') {
1390
- console.error(`🚫 拒绝清理过期 worktree ${name}: 有未落主仓交付变更,请先 sillyspec worktree apply ${name} 或 commit 到分支,再重试 doctor --fix`);
1391
- unfixable.push(`cleanup blocked: ${name}(有未落主仓交付变更)`);
1392
- } else {
1393
- unfixable.push(`cleanup skipped: ${name}`);
1394
- }
1395
- } catch { unfixable.push(`cleanup failed: ${name}`); }
1396
- }
1397
- }
1398
- }
1399
- }
1400
- }
1401
-
1402
- // 5. 检查 SillySpec 分支残留(活跃变更交叉核对,见方法头 activeChanges 注释)
1403
- try {
1404
- // QUAL-01 收口:裸 execFileSync → git-helper git(原调用点未传 timeout,统一入口默认 5s 足够 branch --list)
1405
- const branches = git(this.cwd, ['branch', '--list', `${BRANCH_PREFIX}*`]);
1406
- if (branches) {
1407
- for (const line of branches.split('\n').filter(Boolean)) {
1408
- const branch = line.replace(/^\*?\s+/, '').trim();
1409
- const name = branch.replace(BRANCH_PREFIX, '');
1410
- if (changeName && name !== changeName) continue; // --change 过滤:仅扫指定 change
1411
- if (!metaNames.has(name)) {
1412
- if (activeChanges && activeChanges.has(name)) {
1413
- // 变更仍注册活跃:分支大概率是并行会话在用(或 apply 后被 review 引用审计保护保留)
1414
- // ——数据源不一致的正解是保留 + 人工确认,不是删
1415
- issues.push({ type: 'active-branch', name, fixable: false,
1416
- detail: `分支 ${branch} 无本地 meta,但变更 "${name}" 在进度库仍注册为活跃(并行会话在跑 / meta 已清分支在用)——保留。确认废弃后:先归档/结束该变更,或手动 git branch -D ${branch}` });
1417
- continue;
1418
- }
1419
- if (activeChanges === null) {
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) {
1432
- issues.push({ type: 'orphan-branch', name, fixable: false,
1433
- detail: `分支无对应 meta 但被 ${reviewRefs.length} 个 task review.json 的 base/head 引用(审计锚点)——保留。确要删除:先归档/迁移审计引用,或手动 git branch -D ${branch}` });
1434
- continue;
1435
- }
1436
- issues.push({ type: 'orphan-branch', name, detail: `分支残留(无对应 meta,且非活跃变更): ${branch}`, fixable: true });
1437
- if (fix) {
1438
- try { gitQuiet(this.cwd, ['branch', '-D', branch]); fixed.push(`deleted orphan branch: ${branch}`); } catch { unfixable.push(`branch delete failed: ${branch}`); }
1439
- }
1440
- }
1441
- }
1442
- }
1443
- } catch {}
1444
-
1445
- return { issues, fixed, unfixable };
1446
- }
1447
-
1448
- /**
1449
- * 检查 worktree 是否有尚未落到主工作区的交付变更。
1450
- *
1451
- * 语义:worktree 相对 baseline 的交付变更(tracked + untracked,排除 .sillyspec//meta.json)里,
1452
- * 哪些还没 byte-identical 出现在主工作区 HEAD。全部已在 main HEAD(含 cherry-pick/rebase/merge/apply
1453
- * 落地)→ hasChanges:false(调用方可安全 cleanup);否则 hasChanges:true(保留 worktree)。
1454
- * 检测失败/拿不准 → 保守 hasChanges:true(防误删未落代码)。
1455
- * @param {string} changeName
1456
- * @returns {{ hasChanges: boolean, changedFiles: string[], reason?: string }}
1457
- */
1458
- hasUnappliedChanges(changeName) {
1459
- const name = validateChangeName(changeName);
1460
- const meta = this.getMeta(name);
1461
- if (!meta) return { hasChanges: false, changedFiles: [], reason: 'no meta' };
1462
-
1463
- const worktreePath = meta.worktreePath;
1464
- if (!worktreePath || !existsSync(worktreePath)) {
1465
- // 目录不存在:无法判定是否有未落代码——分支可能有已 commit 但未 apply 的交付(execute 批量完成
1466
- // cleanup 删分支 ref 盲区,memory execute-batch-cleanup-deletes-branch-recovery)。保守保留
1467
- // (hasChanges:true),防 cleanup 误删分支让 commit 变 dangling。目录真丢时用户 --force 强清。
1468
- return { hasChanges: true, changedFiles: [], reason: 'worktree dir not found (conservative keep)' };
1469
- }
1470
-
1471
- // in-place 模式没有隔离目录,不算有未 apply 的变更
1472
- if (meta.mode === 'in-place-fallback') {
1473
- return { hasChanges: false, changedFiles: [], reason: 'in-place mode' };
1474
- }
1475
- // native-worktree 是用户外部隔离环境,不纳入"未应用"判定(与 execute 完成路径一致)
1476
- if (meta.mode === 'native-worktree') {
1477
- return { hasChanges: false, changedFiles: [], reason: 'native-worktree (external)' };
1478
- }
1479
-
1480
- const diffBase = meta.baselineCommit || meta.baseHash;
1481
- if (!diffBase) {
1482
- // 有 meta 但缺 diff 起点:无法判定是否有未落代码,保守保留(防 cleanup 删分支)
1483
- return { hasChanges: true, changedFiles: [], reason: 'no diff base (conservative keep)' };
1484
- }
1485
-
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
-
1522
- try {
1523
- // 1) 候选交付变更(worktree 工作区相对 diffBase)。--no-renames:rename 退化成 D+A,两侧文件都进集
1524
- const trackedRaw = gitQuiet(worktreePath, ['diff', '--no-renames', '--name-only', diffBase], { timeout: 30000 });
1525
- const untrackedRaw = gitQuiet(worktreePath, ['ls-files', '--others', '--exclude-standard'], { timeout: 30000 });
1526
- // git 检测失败(返回 null,如 worktree .git 半坏/目录部分删除)→ 不能当"无改动",保守保留。
1527
- // 只有 git 成功返回空才判"真无改动"(可安全清理)。
1528
- if (trackedRaw === null || untrackedRaw === null) {
1529
- return { hasChanges: true, changedFiles: [], reason: `git detection failed (conservative keep): tracked=${trackedRaw === null ? 'null' : 'ok'} untracked=${untrackedRaw === null ? 'null' : 'ok'}` };
1530
- }
1531
- const tracked = trackedRaw.split('\n').filter(Boolean).filter(isDeliverable);
1532
- const untracked = untrackedRaw.split('\n').filter(Boolean).filter(isDeliverable);
1533
-
1534
- if (tracked.length === 0 && untracked.length === 0) {
1535
- return { hasChanges: false, changedFiles: [], reason: 'no changes in worktree' };
1536
- }
1537
-
1538
- // 2) 候选集中尚未落到主工作区 HEAD 的子集
1539
- const pending = this._changesAlreadyOnMain(worktreePath, tracked, untracked);
1540
- // 3) main 工作区副本降噪层(坑 unapplied-false-positive-workspace-copy,2026-08-21 实证:
1541
- // apply 后 main 工作区有逐字节一致副本但未 commit → HEAD-only 判定报「未落仓」虚警拦
1542
- // doctor)。原注释「不查 main 工作区未提交副本(防误删)」的保护意图是内容未落地——
1543
- // 逐字节一致时内容确已落地(删 worktree 无损),仅逐字节不同的才保守保留。
1544
- const pendingAfterWs = pending.filter(f => {
1545
- try {
1546
- const mainCopy = join(this.cwd, f);
1547
- if (!existsSync(mainCopy)) return true; // main 工作区无副本 → 仍算未落仓
1548
- const wtCopy = join(worktreePath, f);
1549
- if (!existsSync(wtCopy)) return true; // worktree 侧是删除态、main 侧却在 → 内容分叉,保留
1550
- const a = readFileSync(wtCopy); const b = readFileSync(mainCopy);
1551
- return !(a.length === b.length && a.equals(b)); // 逐字节一致 → 已落地(剔除)
1552
- } catch { return true }
1553
- })
1554
- if (pendingAfterWs.length === 0) {
1555
- return { hasChanges: false, changedFiles: [], reason: 'all changes already on main (HEAD or identical workspace copy)' };
1556
- }
1557
- return { hasChanges: true, changedFiles: pendingAfterWs };
1558
- } catch (e) {
1559
- // 检测失败时保守处理:视为有变更,保留 worktree
1560
- return { hasChanges: true, changedFiles: [], reason: `check failed: ${e.message}` };
1561
- }
1562
- }
1563
-
1564
- /**
1565
- * 判定候选变更里哪些还没到主工作区 HEAD。
1566
- * - tracked:`git -C worktree diff --no-renames --name-only <mainHead> -- <files>`,
1567
- * 比较 worktree 工作区(含未提交)vs main HEAD,限定到候选集;空 = 已在 main HEAD。
1568
- * - untracked:worktree `hash-object`(默认带 filter,与 tree blob 同口径)vs main `ls-tree HEAD` blob;
1569
- * 不等 = 该新文件未在 main HEAD。HEAD-only,不查 main 工作区未提交副本(防误删)。
1570
- * 三种 mode 共享主 repo 对象库,mainHead 可在 worktree cwd 解析。
1571
- * @private
1572
- * @param {string} worktreePath
1573
- * @param {string[]} trackedFiles
1574
- * @param {string[]} untrackedFiles
1575
- * @returns {string[]} 尚未落到 main HEAD 的文件
1576
- */
1577
- _changesAlreadyOnMain(worktreePath, trackedFiles, untrackedFiles) {
1578
- const mainHead = git(this.cwd, ['rev-parse', 'HEAD']); // 失败即抛 → 外层 catch fail-safe
1579
- const pending = [];
1580
-
1581
- if (trackedFiles.length > 0) {
1582
- const diverged = (gitQuiet(worktreePath,
1583
- ['diff', '--no-renames', '--name-only', mainHead, '--', ...trackedFiles], { timeout: 30000 }) || '')
1584
- .split('\n').filter(Boolean);
1585
- pending.push(...diverged);
1586
- }
1587
-
1588
- if (untrackedFiles.length > 0) {
1589
- // hash-object 按 argv 顺序逐行输出 blob hash;某文件不存在则整命令失败 → gitQuiet 返回 null
1590
- const wtHashes = (gitQuiet(worktreePath, ['hash-object', '--', ...untrackedFiles], { timeout: 30000 }) || '')
1591
- .split('\n');
1592
- const mainBlobs = this._lsTreeBlobs(this.cwd, 'HEAD', untrackedFiles);
1593
- for (let i = 0; i < untrackedFiles.length; i++) {
1594
- // wtHashes[i] 缺失(命令失败/行数不齐)→ 视为未应用,保守保留
1595
- if (wtHashes[i] !== (mainBlobs.get(untrackedFiles[i]) ?? null)) {
1596
- pending.push(untrackedFiles[i]);
1597
- }
1598
- }
1599
- }
1600
-
1601
- return [...new Set(pending)];
1602
- }
1603
-
1604
- /**
1605
- * 一次 `git ls-tree <treeish> -- <files>` → Map<path, blobHash>(仅 tree 中存在者)。
1606
- * 与 worktree-apply.js 的 getBlobHashMap 同逻辑;此处内联私有,避免反向 import 循环依赖。
1607
- * @private
1608
- * @param {string} cwd
1609
- * @param {string} treeish
1610
- * @param {string[]} files
1611
- * @returns {Map<string, string>}
1612
- */
1613
- _lsTreeBlobs(cwd, treeish, files) {
1614
- const map = new Map();
1615
- if (!files || files.length === 0) return map; // 空 pathspec 会列整棵树,必须拦
1616
- const raw = gitQuiet(cwd, ['ls-tree', treeish, '--', ...files]);
1617
- if (!raw) return map;
1618
- for (const line of raw.split('\n')) {
1619
- if (!line) continue;
1620
- const tab = line.indexOf('\t');
1621
- if (tab === -1) continue;
1622
- const hash = line.slice(0, tab).split(' ')[2]; // "<mode> <type> <hash>"
1623
- if (hash) map.set(line.slice(tab + 1), hash);
1624
- }
1625
- return map;
1626
- }
1627
-
1628
- /**
1629
- * DB 归档态探测(坑 doctor-reprovision-archived-change):changes 表 status='archived'。
1630
- * 只读直查(node:sqlite)——doctor 是同步方法,惰性动态 import 不可用;DB 不存在/无行/
1631
- * 读失败 → false(保守退回普通 deps 供给路径)。
1632
- * @param {string} name
1633
- * @returns {boolean}
1634
- */
1635
- _isChangeArchivedInDb(name) {
1636
- try {
1637
- const dbPath = join(this.cwd, '.sillyspec', '.runtime', 'sillyspec.db');
1638
- if (!existsSync(dbPath)) return false;
1639
- const { openDatabase } = require('./db-engine.js');
1640
- const db = openDatabase(dbPath, { readOnly: true });
1641
- try {
1642
- const row = db.prepare('SELECT status FROM changes WHERE name = ?').get(name);
1643
- return row?.status === 'archived';
1644
- } finally { try { db.close() } catch {} }
1645
- } catch { return false }
1646
- }
1647
-
1648
- /**
1649
- * 从 worktree 路径反推 changeName
1650
- * @private
1651
- */
1652
- _pathToChangeName(wtPath) {
1653
- try {
1654
- const resolved = resolve(wtPath);
1655
- const baseResolved = resolve(this.worktreeBase);
1656
- // 用 path.relative 比 startsWith(base + sep) 更稳:
1657
- // - 自动用当前平台分隔符比较(Windows 上 resolve 返回反斜杠,硬编码 '/' 恒 false)
1658
- // - 跨盘符(C: vs D:)时返回绝对路径 → isAbsolute 守卫放行失败兜底 null
1659
- // - 同路径返回 '' → 视作非 changeName
1660
- const rel = relative(baseResolved, resolved);
1661
- if (rel && !rel.startsWith('..') && !isAbsolute(rel)) {
1662
- return rel;
1663
- }
1664
- } catch {}
1665
- return null;
1666
- }
1667
-
1668
- /**
1669
- * 将主工作区未提交变更同步到 worktree(dirty baseline overlay)
1670
- * 覆盖 staged + unstaged 的文件变更,以及 untracked 文件。
1671
- * 使用 git diff + git apply 确保正确处理删除/rename/binary。
1672
- *
1673
- * .sillyspec/ 隔离(坑 baseline-overlay-cross-change-contamination,2026-08-21 实证):
1674
- * overlay 原样全量吸收主仓未提交改动——多变更并行时其他变更的 spec 文档
1675
- * (changes/<他变更>/、ROADMAP.md、quicklog 等 39 个文件实测)被 checkpoint 进本变更
1676
- * baseline,apply 回 main 即随本变更交付,需人工隔离。spec 文档不参与 worktree 内
1677
- * 构建/测试(execute 的 spec 读写经 specDriftAnchor 锚回主仓),排除零功能损失;
1678
- * 排除清单显式打印保持可见(哪些跨变更文件被隔离、去哪了)。
1679
- * @param {string} mainCwd - 主工作区路径
1680
- * @param {string} worktreePath - worktree 路径
1681
- * @returns {Array<string>} overlay 的文件列表
1682
- */
1683
- _overlayBaseline(mainCwd, worktreePath) {
1684
- const files = [];
1685
- const errors = [];
1686
- // git pathspec 排除(execFileSync 数组传参不经 shell,字面安全):.sillyspec/ 整目录
1687
- const EXCLUDE_PATHSPEC = ':(exclude).sillyspec';
1688
- const collectExcluded = (raw, excluded) => {
1689
- for (const f of raw.split('\n').filter(Boolean)) {
1690
- const norm = f.replace(/\\/g, '/')
1691
- if (norm === '.sillyspec' || norm.startsWith('.sillyspec/')) excluded.push(f)
1692
- }
1693
- }
1694
-
1695
- try {
1696
- const excludedSpecFiles = [];
1697
- // staged 变更(pathspec 排除 .sillyspec/——跨变更 spec 文档不进 baseline)
1698
- const staged = gitQuiet(mainCwd, ['diff', '--cached', '--name-only', '--', '.', EXCLUDE_PATHSPEC], { timeout: 30000 }) || ''
1699
- const stagedAll = gitQuiet(mainCwd, ['diff', '--cached', '--name-only'], { timeout: 30000 }) || ''
1700
- collectExcluded(stagedAll, excludedSpecFiles)
1701
- if (staged) {
1702
- try {
1703
- // 用 Buffer 模式读取,避免二进制 patch 被 UTF-8 解码损坏
1704
- // QUAL-01 收口:git-helper 新增 encoding:'buffer' 支持(二进制输出专用,跳过 trim)
1705
- const patchBuf = git(mainCwd, ['diff', '--cached', '--binary', '--', '.', EXCLUDE_PATHSPEC], { encoding: 'buffer', timeout: 30000 });
1706
- if (patchBuf && patchBuf.length > 0) {
1707
- const patchFile = join(worktreePath, '.sillyspec-baseline-staged.patch');
1708
- try {
1709
- writeFileSync(patchFile, patchBuf);
1710
- git(worktreePath, ['apply', '--binary', patchFile], { timeout: 30000 });
1711
- } finally {
1712
- // git apply 抛错时也要清掉 patch 临时文件,避免泄漏到 worktree/主仓根
1713
- // (filterDeliverableFiles 不排除 .sillyspec-baseline-*,泄漏会级联 BLOCKED 下游 apply)
1714
- try { rmSync(patchFile, { force: true }); } catch {}
1715
- }
1716
- }
1717
- } catch (e) {
1718
- errors.push(`staged: ${e.message}`);
1719
- }
1720
- files.push(...staged.split('\n').filter(Boolean));
1721
- }
1722
-
1723
- // unstaged 变更(同上 pathspec 排除)
1724
- const unstaged = gitQuiet(mainCwd, ['diff', '--name-only', '--', '.', EXCLUDE_PATHSPEC], { timeout: 30000 }) || ''
1725
- const unstagedAll = gitQuiet(mainCwd, ['diff', '--name-only'], { timeout: 30000 }) || ''
1726
- collectExcluded(unstagedAll, excludedSpecFiles)
1727
- if (unstaged) {
1728
- try {
1729
- // 用 Buffer 模式读取,避免二进制 patch 被 UTF-8 解码损坏(QUAL-01 收口,同上)
1730
- const patchBuf = git(mainCwd, ['diff', '--binary', '--', '.', EXCLUDE_PATHSPEC], { encoding: 'buffer', timeout: 30000 });
1731
- if (patchBuf && patchBuf.length > 0) {
1732
- const patchFile = join(worktreePath, '.sillyspec-baseline-unstaged.patch');
1733
- try {
1734
- writeFileSync(patchFile, patchBuf);
1735
- git(worktreePath, ['apply', '--binary', patchFile], { timeout: 30000 });
1736
- } finally {
1737
- // git apply 抛错时也要清掉 patch 临时文件,避免泄漏到 worktree/主仓根
1738
- try { rmSync(patchFile, { force: true }); } catch {}
1739
- }
1740
- }
1741
- } catch (e) {
1742
- errors.push(`unstaged: ${e.message}`);
1743
- }
1744
- files.push(...unstaged.split('\n').filter(Boolean));
1745
- }
1746
-
1747
- // untracked 文件(排除 .sillyspec/.runtime 等);目录跳过避免 readFileSync EISDIR
1748
- const untracked = gitQuiet(mainCwd, ['ls-files', '--others', '--exclude-standard'], { timeout: 30000 }) || '';
1749
- const skippedDirs = [];
1750
- if (untracked) {
1751
- for (const f of untracked.split('\n').filter(Boolean)) {
1752
- const norm = f.replace(/\\/g, '/')
1753
- if (norm === '.sillyspec' || norm.startsWith('.sillyspec/')) { excludedSpecFiles.push(f); continue }
1754
- const r = copyUntrackedEntry(join(mainCwd, f), join(worktreePath, f));
1755
- if (r.status === 'copied') files.push(f);
1756
- else if (r.status === 'skipped-dir') skippedDirs.push(f);
1757
- else if (r.status === 'error') errors.push(`untracked ${f}: ${r.error}`);
1758
- }
1759
- }
1760
- if (skippedDirs.length > 0) {
1761
- console.log(`ℹ️ baseline overlay 跳过 ${skippedDirs.length} 个 untracked 目录(不读目录避免 EISDIR,坑 execute-worktree-overlay-untracked-dir-eisdir)`);
1762
- }
1763
- // 跨变更 spec 文档隔离可见性:列出被排除的 .sillyspec/ 文件(去重,截断展示),
1764
- // 让「ROADMAP 被谁改动、为何不在本 baseline」在 create 时刻可查,不需事后考古
1765
- const excludedUnique = [...new Set(excludedSpecFiles)]
1766
- if (excludedUnique.length > 0) {
1767
- const preview = excludedUnique.slice(0, 8).join(', ') + (excludedUnique.length > 8 ? ` …(共 ${excludedUnique.length} 个)` : '')
1768
- console.log(`🧹 baseline overlay 已隔离 ${excludedUnique.length} 个 .sillyspec/ 未提交文件(跨变更 spec 文档不进本变更 baseline,留在主仓各自归属):${preview}`)
1769
- }
1770
-
1771
- if (files.length > 0) {
1772
- console.log(`📁 baseline overlay: ${files.length} 个未提交文件已同步到 worktree`);
1773
- // 非阻断 advisory(治「已做完没提交」被裹进 execute 交付):这批未提交改动会单独 commit
1774
- // 成 baseline checkpoint(git 历史与本阶段新改动分层,可分开验收),但 apply 回 main 时会
1775
- // 随本阶段交付落地。若它们是独立变更、需要独立验收,先提交到独立分支另行处理——
1776
- // 注意不能在 main 直接 commit(那等于无验收并入主干、污染 main,正是坑1 形态)。
1777
- // sillyspec 只做确定性提示(改动是事实),该不该拆分属意图判定,留给 agent/用户。
1778
- console.log(` ℹ️ 它们将作为独立 baseline checkpoint 提交到 worktree 分支(与本阶段新改动分层、可分开验收),`);
1779
- console.log(` 但 apply 回 main 会随本阶段交付。若是独立变更、需独立验收:先提交到独立分支另行处理`);
1780
- console.log(` (不要在 main 直接 commit——那等于无验收并入主干、污染 main),再回到本变更跑 execute。`);
1781
- }
1782
- } catch (e) {
1783
- errors.push(`unexpected: ${e.message}`);
1784
- }
1785
-
1786
- // 有 pending 文件但 overlay 部分失败 → fail-fast
1787
- if (errors.length > 0) {
1788
- throw new Error(`baseline overlay 失败 (${errors.length} 个错误): ${errors.join('; ')}`);
1789
- }
1790
-
1791
- const uniqueFiles = [...new Set(files)];
1792
-
1793
- // 计算 baseline hash(用于 merge 前校验主工作区是否变化)
1794
- const baselineHash = uniqueFiles.length > 0 ? computeBaselineHash(mainCwd) : null;
1795
-
1796
- return { files: uniqueFiles, baselineHash };
1797
- }
1798
-
1799
- /**
1800
- * 在 worktree 内创建 baseline checkpoint commit
1801
- * 用于区分 "前置 dirty baseline" 和 "子代理新增改动"
1802
- * @param {string} worktreePath
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` 一眼可辨、可机械排除)
1808
- * @returns {string} commit hash
1809
- */
1810
- _createBaselineCheckpoint(worktreePath, changeName, baselineFiles = []) {
1811
- // 使用临时 git identity,避免用户未配置 user.name/user.email 导致失败
1812
- const env = {
1813
- GIT_AUTHOR_NAME: 'sillyspec',
1814
- GIT_AUTHOR_EMAIL: 'sillyspec@baseline',
1815
- GIT_COMMITTER_NAME: 'sillyspec',
1816
- GIT_COMMITTER_EMAIL: 'sillyspec@baseline',
1817
- };
1818
- try {
1819
- git(worktreePath, ['add', '-A'], { timeout: 30000 });
1820
- // 检查是否有实际变更(可能 overlay 后和 HEAD 完全一致)
1821
- const status = gitQuiet(worktreePath, ['status', '--porcelain'], { timeout: 30000 });
1822
- if (!status) {
1823
- return gitQuiet(worktreePath, ['rev-parse', 'HEAD']);
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
- : ''
1833
- // --no-verify:baseline 是锚点不是交付物,只是把主仓库 dirty 文件快照到 worktree
1834
- // 分支上以便区分「前置 baseline」与「子代理新增改动」。它不该触发项目 pre-commit
1835
- // hook(如 ruff format),否则主仓库 dirty 文件中任一不达标的会被 hook reformat
1836
- // 致 commit 失败 → worktree 创建失败 → execute 无法启动。
1837
- execFileSync(
1838
- 'git',
1839
- ['commit', '--no-verify', '-m', `sillyspec: baseline checkpoint for ${changeName}${body}`],
1840
- { cwd: worktreePath, encoding: 'utf8', stdio: ['pipe','pipe','pipe'], env }
1841
- );
1842
- const hash = git(worktreePath, ['rev-parse', 'HEAD']);
1843
- console.log(`📌 baseline checkpoint: ${hash}`);
1844
- return hash;
1845
- } catch (e) {
1846
- throw new Error(`baseline checkpoint 创建失败: ${e.message}`);
1847
- }
1848
- }
1849
- }