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,1611 +0,0 @@
1
- /**
2
- * SillySpec applyWorktree — 将 worktree 中的变更应用到主工作区
3
- *
4
- * 流程:
5
- * 1. 读取 meta.json 获取 baseHash
6
- * 2. git diff --name-only baseHash 获取 worktree 中所有变更文件
7
- * 3. 从 design.md 解析文件变更清单(无清单 = 允许所有)
8
- * 4. 校验:变更文件 ⊆ 清单
9
- * 5. 校验:主工作区文件 base hash 一致
10
- * 6. --check-only 模式只输出检查结果
11
- * 7. 非 checkOnly:生成 patch → apply --check → apply --3way
12
- * 8. 成功后自动 cleanup
13
- */
14
-
15
- import { existsSync, unlinkSync, writeFileSync, mkdtempSync, rmSync, readdirSync, readFileSync, mkdirSync } from 'fs';
16
- import { join, resolve } from 'path';
17
- import { tmpdir } from 'os';
18
- import { WorktreeManager } from './worktree.js';
19
- import { parseFileChangeList, parseFileChangeListDetailed, pathMatches } from './change-list.js';
20
- import { parseAllowedPaths, parseRepo } from './stages/plan-postcheck.js';
21
- import { git, gitQuiet } from './git-helper.js';
22
- import { resolveLatestExecuteRunId, resolveLatestExecuteRunIdWithTasks, readReview, normalizeRepoKey } from './task-review.js';
23
-
24
- const CHANGES_REL = '.sillyspec/changes';
25
-
26
- /**
27
- * 过滤掉 worktree 基础设施文件(非交付物),让 apply 只关心真正的变更产出:
28
- * - meta.json:worktree 元数据,baseline commit 中被跟踪、working-tree 被 CLI 改写
29
- * (provisioning→linked 等)。它必须保持 modified(其 baselineCommit 字段是 apply diff
30
- * 的锚点,保证 baseline overlay 文件不被误判为变更)。若不排除,modified-tracked 的
31
- * meta.json 会落入 changedFiles,触发「不在 design.md 清单」误判,导致每个 execute 的
32
- * assess 恒 BLOCKED。
33
- * - .sillyspec/changes/:变更文档(worktree 专属,apply 回主仓污染进度库)。
34
- * - .sillyspec/.runtime/:运行时产物(进度库/锁/review 产物,非源码)。
35
- * - .sillyspec/quicklog/:quicklog 条目(worktree 进度,非交付物)。
36
- * 保留 .sillyspec/docs/(dogfood 模块规范文档 = 交付物,apply 回主仓)。
37
- * 对 modified-tracked(git diff)与 untracked(ls-files --others)一视同仁。
38
- */
39
- export function filterDeliverableFiles(files) {
40
- return files.filter(f =>
41
- !f.startsWith('.sillyspec/changes/') &&
42
- !f.startsWith('.sillyspec/.runtime/') &&
43
- !f.startsWith('.sillyspec/quicklog/') &&
44
- f !== 'meta.json'
45
- );
46
- }
47
-
48
- /**
49
- * dirty 拦截触发时生成「逐文件 rescue 指令」——旁路 git apply 的安全逃生通道(design §接口定义 generateRescueCommands)。
50
- *
51
- * 逐文件四分类(按优先级判定,命中即 continue):
52
- * 1. DELETE ∈ deletedFiles → rm "<projectRoot>/<f>"(不计 cpFileCount 也不计 excludedCount)
53
- * 2. EXCLUDE-DIRTY ∈ dirtyFiles → warning(cp 会覆盖 main 工作区未提交改动),excludedCount++
54
- * 3. EXCLUDE-MISMATCH ∈ hashMismatchFiles → warning(cp 会回退主干已提交推进改动),excludedCount++
55
- * 4. SAFE-CP 其余(main 该文件干净)→ cp "<worktreePath>/<f>" "<projectRoot>/<f>",cpFileCount++
56
- *
57
- * 路径用 path.join 拼接后 replace 反斜杠为正斜杠(Git Bash 兼容,规则 13)。
58
- *
59
- * 纯函数:无 git/fs 调用无副作用,不读 meta/worktree 状态,不 mutate 入参;
60
- * 所有 dirtyFiles/hashMismatchFiles/deletedFiles 集合均由调用方(step4.5/5a/assess)算好传入。
61
- *
62
- * @param {object} args
63
- * @param {string[]} args.changedFiles filterDeliverableFiles 后的实际变更路径
64
- * @param {Set<string>|string[]} args.dirtyFiles main 工作区未提交文件集(统一口径:tracked-modified ∪ untracked,排 .sillyspec/+meta.json)
65
- * @param {string[]} args.hashMismatchFiles 主干已提交推进文件(step3.5 前移算,依赖 baseHash/HEAD blob 对比)
66
- * @param {string[]} [args.deletedFiles=[]] worktree 删除文件(git diff name-status D)
67
- * @param {string} args.worktreePath
68
- * @param {string} args.projectRoot
69
- * @returns {{
70
- * commands: string[], // 可复制粘贴 shell 命令(cp/rm),正斜杠路径
71
- * warnings: string[], // 被排除文件(dirty/mismatch)的风险标注
72
- * cpFileCount: number, // SAFE-CP 文件数
73
- * excludedCount: number // EXCLUDE-DIRTY + EXCLUDE-MISMATCH 数
74
- * }}
75
- */
76
- export function generateRescueCommands({ changedFiles, dirtyFiles, hashMismatchFiles, deletedFiles = [], worktreePath, projectRoot }) {
77
- // 集合归一:dirtyFiles 接受 Set 或数组(调用方 step4.5/5a 可能传任一形态),其余统一数组→Set
78
- const dirtySet = dirtyFiles instanceof Set ? dirtyFiles : new Set(dirtyFiles || []);
79
- const mismatchSet = new Set(hashMismatchFiles || []);
80
- const deletedSet = new Set(deletedFiles || []);
81
-
82
- const commands = [];
83
- const warnings = [];
84
- let cpFileCount = 0;
85
- let excludedCount = 0;
86
-
87
- for (const f of changedFiles) {
88
- // 优先级 1→2→3→4,命中即 continue(DELETE 最先判)
89
- if (deletedSet.has(f)) {
90
- commands.push(`rm "${join(projectRoot, f).replace(/\\/g, '/')}"`);
91
- continue;
92
- }
93
- if (dirtySet.has(f)) {
94
- warnings.push(`跳过 ${f}:EXCLUDE-DIRTY(main 工作区该文件有未提交改动,cp 会覆盖)`);
95
- excludedCount++;
96
- continue;
97
- }
98
- if (mismatchSet.has(f)) {
99
- warnings.push(`跳过 ${f}:EXCLUDE-MISMATCH(主干已提交推进该文件,cp 会回退他人改动;请先 commit main 未提交改动再正常 apply 走 --3way 合并)`);
100
- excludedCount++;
101
- continue;
102
- }
103
- commands.push(`cp "${join(worktreePath, f).replace(/\\/g, '/')}" "${join(projectRoot, f).replace(/\\/g, '/')}"`);
104
- cpFileCount++;
105
- }
106
-
107
- return { commands, warnings, cpFileCount, excludedCount };
108
- }
109
-
110
- /**
111
- * 算 rescue 用的统一 dirtyFiles 口径:main 工作区所有未提交文件 = tracked-modified(git diff HEAD)
112
- * ∪ untracked(git ls-files others),再用 filterDeliverableFiles 过滤(排 .sillyspec/changes/.runtime/quicklog
113
- * + meta.json,保留 .sillyspec/docs/——对齐 changedFiles 同宇宙,闭合 design Grill 的 .sillyspec/docs/ 残留 gap)。
114
- * 注意:此口径与 step4.5「是否触发拦截」的判定口径(排除 .claude/docs/CLAUDE.md)不同,二者不混用(design §dirtyFiles 口径统一)。
115
- * @param {string} projectRoot
116
- * @returns {string[]} 未提交文件(filterDeliverableFiles 过滤后)
117
- */
118
- export function computeRescueDirtyFiles(projectRoot) {
119
- const tracked = (gitQuiet(projectRoot, ['diff', '--name-only', 'HEAD']) || '').split('\n').filter(Boolean);
120
- const untracked = (gitQuiet(projectRoot, ['ls-files', '--others', '--exclude-standard']) || '').split('\n').filter(Boolean);
121
- return filterDeliverableFiles([...new Set([...tracked, ...untracked])]);
122
- }
123
-
124
- /**
125
- * 校验变更文件是否都在 design.md 清单内——容差匹配(与 plan-postcheck validateDesignFileCoverage
126
- * 同语义):design 清单写 glob(双星通配)或目录前缀(如 src/ 子树)也能覆盖 git diff 出的具体路径,
127
- * 避免「plan 阶段放过、apply 阶段卡死」逼用户回去补字面文件名。
128
- *
129
- * @param {string[]} changedFiles git diff 出的具体变更路径
130
- * @param {Set<string>} allowSet design.md 清单项(可能含 glob / 目录前缀)
131
- * @returns {string[]} 不被任何清单项覆盖的文件(违规项,apply 将据此 BLOCK)
132
- */
133
- export function classifyAllowListViolations(changedFiles, allowSet) {
134
- const allow = [...allowSet];
135
- return changedFiles.filter(f => !allow.some(ap => pathMatches(f, ap)));
136
- }
137
-
138
- /**
139
- * 确定进 patch 的文件:有清单取「实际变更 ∩ 清单(pathMatches 容差)」,无清单取全部变更。
140
- *
141
- * 口径须与 classifyAllowListViolations 一致——否则 design §6 用 glob(如 test_*.py)或多路径
142
- * 单 cell 覆盖的文件过 manifest 校验(Gate1 用 pathMatches 放行),却因字面 includes 不在
143
- * changedFiles → 被滤出 patchFiles → patch 不含 → 主工作区静默丢失(坑 apply-glob-manifest)。
144
- * 以 changedFiles 为基按容差圈定,glob/前缀覆盖的具体文件都能进 patch。
145
- *
146
- * @param {string[]} changedFiles filterDeliverableFiles 已过滤的实际变更路径
147
- * @param {Set<string>} allowSet design §6 清单 ∪ task allowed_paths(可含 glob / 目录前缀)
148
- * @param {boolean} hasAllowList 是否有清单
149
- * @returns {string[]} 进 patch 的文件
150
- */
151
- export function resolvePatchFiles(changedFiles, allowSet, hasAllowList) {
152
- if (!hasAllowList) return changedFiles;
153
- return changedFiles.filter(f => [...allowSet].some(ap => pathMatches(f, ap)));
154
- }
155
- /**
156
- * 批量获取多个文件在某个 treeish 中的 blob hash(一次 git ls-tree 替代 N 次 rev-parse)。
157
- *
158
- * 语义等价于对每个文件调 `git rev-parse <treeish>:<path>`:
159
- * - 文件在 tree 中 → Map<f, hash>(与 rev-parse 返回的同一 blob hash)
160
- * - 文件不在 tree 中 → 不在 Map 中(调用方 map.get(f) ?? null 得 null,等同 rev-parse 失败→null)
161
- * ls-tree 输出 "<mode> <type> <hash>\t<path>"。path 恒为文件路径(来自 git diff/ls-files),
162
- * 非目录,故不带 -r 也正确——文件在 tree 时 rev-parse treeish:path 与 ls-tree 都给同一 hash,
163
- * 不在时都不给,等价。(沿用公共 git() 数组形式,不经 shell、不引入引号/空格破法。)
164
- *
165
- * @param {string} cwd
166
- * @param {string} treeish
167
- * @param {string[]} files
168
- * @returns {Map<string, string>} path → blob hash(仅含存在于 tree 中的文件)
169
- */
170
- function getBlobHashMap(cwd, treeish, files) {
171
- const map = new Map();
172
- if (files.length === 0) return map; // 空 pathspec 会让 ls-tree 列出整棵树,必须拦截
173
- const raw = gitQuiet(cwd, ['ls-tree', treeish, '--', ...files]);
174
- if (!raw) return map;
175
- for (const line of raw.split('\n')) {
176
- if (!line) continue;
177
- const tabIdx = line.indexOf('\t');
178
- if (tabIdx === -1) continue;
179
- const filePath = line.slice(tabIdx + 1);
180
- const hash = line.slice(0, tabIdx).split(' ')[2]; // "<mode> <type> <hash>"
181
- if (hash) map.set(filePath, hash);
182
- }
183
- return map;
184
- }
185
-
186
- /**
187
- * apply 的文件清单 = design §6 清单 ∪ plan TaskCard allowed_paths(execute 复盘 c)。
188
- *
189
- * design §6 常只列源码、漏测试/产物文件,而 task allowed_paths(plan 阶段产出)已含——apply 若只认
190
- * design 清单会在测试/产物文件上误拦(assess 用 task allowed_paths 已放行、apply 用 design 清单又拦,
191
- * 两 gate 口径不一致)。union 后两源并集为准;plan 已过 validateDesignFileCoverage 单向校验(design ⊆
192
- * plan),union 不会放开 design/plan 之外的任意文件(仍拦完全越界文件)。
193
- *
194
- * **跨仓切片(task-05 / D-009 / design §6 A4)**:返回 `Map<repoKey, Set<path>>`,按 task 卡片
195
- * `repo:` 字段把 allowed_paths 归属到对应 repo;design §6 清单归属 'main'(清单文件相对主仓根)。
196
- * 单仓 change(task 卡无 repo:)→ 所有 allowed_paths 归 'main' → `{main: Set}` 退化零回归
197
- * (GOAL-2)。allowed_paths 基准=各 repo 自身根(跨仓 task 卡片 allowed_paths 相对跨仓仓根,design §7.2)。
198
- *
199
- * 主流程(applyWorktree A5 主仓 apply)只消费 main 仓的 Set(主仓 worktree diff 只含主仓文件,
200
- * 跨仓文件不在主仓 worktree 故永不进 diff);跨仓 task 走 no-op(D-009),其 allowed_paths 仅
201
- * 作 Map 切片返回,供上游(assess / 跨仓 review 校验)按 repo 取用。
202
- *
203
- * @param {string} projectRoot - 主仓库根
204
- * @param {string} changeName - 变更名
205
- * @returns {Map<string, Set<string>>} repoKey → 并集清单 Set(无 design 清单且无 task 卡片时为空 Map)
206
- */
207
- export function resolveApplyAllowSet(projectRoot, changeName) {
208
- const repoMap = new Map();
209
- const getOrCreate = (key) => {
210
- if (!repoMap.has(key)) repoMap.set(key, new Set());
211
- return repoMap.get(key);
212
- };
213
- // design §6 清单归属 main(清单路径相对主仓根;跨仓 task 的 allowed_paths 由 task 卡片 repo 切片)
214
- const mainSet = getOrCreate('main');
215
- parseFileChangeList(
216
- join(projectRoot, CHANGES_REL, changeName, 'design.md'),
217
- { keepSillyspecDocs: true }
218
- ).forEach(p => mainSet.add(p));
219
- const tasksDir = join(projectRoot, CHANGES_REL, changeName, 'tasks');
220
- if (existsSync(tasksDir)) {
221
- for (const tf of readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))) {
222
- const content = readFileSync(join(tasksDir, tf), 'utf8');
223
- // task 卡 repo: 字段切片(缺省='main',design §7.2);跨仓 task 的 allowed_paths 相对跨仓仓根。
224
- const repoKey = parseRepo(content) || 'main';
225
- const repoSet = getOrCreate(repoKey);
226
- for (const p of parseAllowedPaths(content)) repoSet.add(p);
227
- }
228
- }
229
- return repoMap;
230
- }
231
-
232
- /**
233
- * 收集最新 execute run 各 task review.json 的 changedFiles 声明 → Map<repoKey, string[]>。
234
- *
235
- * 坑 apply-undeclared-deviation-block(2026-08-24 用户反馈四期③):执行期有据越界文件
236
- * (facade 转发/名单测试)不在 design §6 也不在 allowed_paths,Gate1 拦 apply 只能回改
237
- * design.md。review.json changedFiles 是 reviewer 对实际改动的声明(Task Review Gate 的
238
- * verifyReviewGitEvidence 已交叉校验其与真实 git diff 相交),作为第三源并入 allow set——
239
- * 放行仅限「已声明且过证据校验」的文件,完全越界仍拦。口径与 complete-handlers 的
240
- * collectExecuteChangedFiles 一致:change 戳归属 run、.sillyspec//meta.json 过滤、
241
- * review.repo 切片(跨仓声明不进 main 集)。读不到 run/review → 空 Map(fail-closed 回退旧行为)。
242
- *
243
- * @param {string} projectRoot - 主仓库根
244
- * @param {string} changeName - 变更名
245
- * @returns {Map<string, string[]>}
246
- */
247
- export function collectReviewDeclaredFiles(projectRoot, changeName) {
248
- const byRepo = new Map();
249
- try {
250
- const runtimeRoot = join(projectRoot, '.sillyspec', '.runtime');
251
- const runId = resolveLatestExecuteRunIdWithTasks({ runtimeRoot, changeName });
252
- if (!runId) return byRepo;
253
- const runTasksDir = join(runtimeRoot, 'execute-runs', runId, 'tasks');
254
- if (!existsSync(runTasksDir)) return byRepo;
255
- for (const taskId of readdirSync(runTasksDir)) {
256
- const r = readReview(join(runTasksDir, taskId, 'review.json'));
257
- if (!r.ok || !r.review || !Array.isArray(r.review.changedFiles)) continue;
258
- const repoKey = normalizeRepoKey(r.review.repo);
259
- const list = byRepo.get(repoKey) || [];
260
- for (const f of r.review.changedFiles) {
261
- // 交付物过滤(与 collectExecuteChangedFiles 同口径):.sillyspec/ 运行时产物/meta.json 不进 allow
262
- if (typeof f !== 'string' || f.trim() === '') continue;
263
- if (f.startsWith('.sillyspec/') || f === 'meta.json') continue;
264
- list.push(f);
265
- }
266
- byRepo.set(repoKey, list);
267
- }
268
- } catch { /* 读不到 run/review → 空 Map(fail-closed 回退旧行为) */ }
269
- return byRepo;
270
- }
271
-
272
- /**
273
- * 跨仓 task apply = no-op 校验(task-05 / D-009 / design §6 A3 G1)。
274
- *
275
- * 跨仓 task 的 commit 已由子代理直接落跨仓仓主干(NG-3),apply 阶段无 patch 可打(跨仓仓无
276
- * worktree/meta/分支——A5 patch 路径不可复用)。本函数对每个跨仓 repo 的 task review.head
277
- * 校验是否为该跨仓仓真实 commit(约束①+② 保险,R-05:子代理漏 commit / head 伪造 → 这里拦)。
278
- *
279
- * 不调 wm.cleanup(跨仓仓无主仓 worktree 可清——wm.cleanup 只作用主仓 worktree,跨仓仓主干工作区
280
- * 永不进主仓 worktree 生命周期,无需也无法 cleanup)。这是 D-009 no-op 的关键:跨仓 commit 已落主干,
281
- * apply 只校验不复用 patch、不 cleanup。
282
- *
283
- * review.json 物理在主仓 execute-runs(D-003),含 repo + head 字段(design §7.4)。本函数读主仓
284
- * execute-runs 取最新 runId 的 reviews,按 review.repo 切片到对应跨仓 entry 校验 head。
285
- *
286
- * 无 review.json(execute 未走完 / 单 task --done 中途)→ 记 warning 不阻断(apply 可在 review 落盘前
287
- * 被调用,如 worktree apply --check-only 预检;真阻断由 Task Review Gate 负责,这里不重复)。
288
- *
289
- * @param {object} ctx - MultiRepoContext(design §7.1)
290
- * @param {string} projectRoot - 主仓根(读 .sillyspec/.runtime/execute-runs)
291
- * @param {string} changeName
292
- * @returns {{ errors: string[], warnings: string[], validated: Array<{repo:string, task:string, head:string}> }}
293
- */
294
- function validateCrossRepoNoOp(ctx, projectRoot, changeName) {
295
- const errors = [];
296
- const warnings = [];
297
- const validated = [];
298
- if (!ctx || typeof ctx.hasCrossRepo !== 'function' || !ctx.hasCrossRepo()) {
299
- return { errors, warnings, validated }; // 单仓退化:无跨仓,no-op 无事可做(零回归)
300
- }
301
- // review.json 物理在主仓 .runtime/execute-runs(D-003)。runtimeRoot = <projectRoot>/.sillyspec/.runtime
302
- const runtimeRoot = join(projectRoot, '.sillyspec', '.runtime');
303
- const runId = resolveLatestExecuteRunId({ runtimeRoot, changeName });
304
- if (!runId) {
305
- // 无 execute run → 无 review 可校验。不阻断(Task Review Gate 负责拦截 review 缺失),
306
- // 仅 warn 提示跨仓 head 校验被跳过(约束①保险在此场景未触发,但功能不崩)。
307
- warnings.push(`跨仓 task no-op 校验跳过:未找到 execute runId(${runtimeRoot}),无法读取跨仓 review.head。跨仓 commit 校验交由 Task Review Gate 负责。`);
308
- return { errors, warnings, validated };
309
- }
310
- const tasksDir = join(runtimeRoot, 'execute-runs', runId, 'tasks');
311
- if (!existsSync(tasksDir)) {
312
- warnings.push(`跨仓 task no-op 校验跳过:execute run ${runId} 无 tasks/ 目录。`);
313
- return { errors, warnings, validated };
314
- }
315
- // 遍历 ctx.repos,只对跨仓 entry(isMain=false)校验。每 entry 读所有 review.json 取 repo 匹配的 head。
316
- for (const [repoKey, entry] of ctx.repos) {
317
- if (entry.isMain) continue; // 主仓走 A5,不在此 no-op
318
- // 扫 tasks/ 下 review.json,取 repo === repoKey 的 head 校验
319
- let taskEntries = [];
320
- try { taskEntries = readdirSync(tasksDir).filter(f => /^task-\d+$/.test(f)); } catch { taskEntries = []; }
321
- for (const taskId of taskEntries) {
322
- const reviewPath = join(tasksDir, taskId, 'review.json');
323
- if (!existsSync(reviewPath)) continue;
324
- const r = readReview(reviewPath);
325
- // readReview 走 validateReviewSchema(task-03 扩展 repo 字段后兼容);review 不完整则跳过(不在此拦)
326
- if (!r.ok || !r.review) continue;
327
- const reviewRepo = r.review.repo || 'main'; // schemaVersion=1 无 repo 视 main(design §9 兼容)
328
- if (reviewRepo !== repoKey) continue;
329
- const head = r.review.head;
330
- if (!head) continue; // schema 校验已挡缺 head,防御性跳过
331
- // 校验 head 是该跨仓仓真实 commit:git cat-file -e HEAD~0 / rev-parse 校验存在
332
- // 用 cat-file -e <head> 校验 commit 存在(rev-parse 对缩写/不存在都非零退出)
333
- const exists = gitQuiet(entry.gitDir, ['cat-file', '-e', head]);
334
- if (exists === null) {
335
- errors.push(
336
- `跨仓 task no-op 校验失败:task ${taskId}(repo: ${repoKey})的 review.head ${head} ` +
337
- `不是跨仓仓 ${entry.gitDir} 的真实 commit(git cat-file -e 失败)。` +
338
- `跨仓 task 的 commit 必须由子代理直接落跨仓仓主干(D-009),apply 为 no-op 不复用 patch,` +
339
- `故 head 真实性是跨仓改动落地的唯一保险(约束①+②,R-05)。请检查子代理是否漏 commit 或 head 锡点漂移。`
340
- );
341
- } else {
342
- validated.push({ repo: repoKey, task: taskId, head });
343
- }
344
- }
345
- }
346
- return { errors, warnings, validated };
347
- }
348
-
349
- /**
350
- * apply worktree 变更到主工作区
351
- *
352
- * **跨仓 task no-op(task-05 / D-009 / design §6 A3/A5)**:当传 ctx 且 ctx.hasCrossRepo() 时,
353
- * 跨仓 task 的 commit 已由子代理直接落跨仓仓主干(NG-3 跨仓不经主仓 worktree),apply 阶段对跨仓
354
- * task = no-op(无 patch 可打,跨仓仓无 worktree/meta/分支——A5 patch 路径不可复用)。只校验跨仓
355
- * task review.head 是跨仓仓真实 commit(约束①+② 保险,R-05)+ 不调 wm.cleanup(跨仓仓无主仓 worktree
356
- * 可清,wm.cleanup 只作用于主仓 worktree)。主仓 task 走原 A5 完整 apply 不动(GOAL-2 单仓零回归)。
357
- *
358
- * @param {string} changeName - 变更名
359
- * @param {{ cwd?: string, checkOnly?: boolean, merge?: boolean, ctx?: object }} opts
360
- * - ctx:可选 MultiRepoContext(design §7.1)。缺省=单仓退化(仅主仓 apply,零行为变化,GOAL-2)。
361
- * 提供 ctx 且含跨仓 entry 时,触发跨仓 no-op 校验(校验 review.head 真实 + 不 cleanup 跨仓)。
362
- * @returns {{
363
- * ok: boolean,
364
- * changedFiles: string[],
365
- * extraFiles: string[],
366
- * hashMismatchFiles: string[],
367
- * patchPath: string|null,
368
- * errors: string[],
369
- * crossRepoValidated?: Array<{ repo: string, head: string }>
370
- * }}
371
- */
372
- /**
373
- * 主仓级互斥锁(坑 main-apply-no-mutex → 泛化 main-repo-no-mutex,2026-08-23 二批实证:
374
- * 除 apply 外,cleanup(worktree 注册表/分支删除)、archive 收尾(目录 rename + 共享 index
375
- * 的 git add + marker 删除)同样直接改主仓共享状态且零互斥——两会话并发操作互踩。泛化为
376
- * withMainRepoLock:同一把主仓锁保护所有「写主仓的破坏性短操作」(apply / cleanup / archive
377
- * 收尾);verify 的长时间测试执行**不**上锁(读树为主,靠对账归属过滤与归因提示治误伤)。
378
- *
379
- * 锁粒度 = 主仓级(竞争资源是 main 工作区/.git 状态,非 change):O_EXCL 文件锁复用
380
- * quicklog 的 withFileLock(stale 偷锁 + rename 防 TOCTOU),锁内容写
381
- * {pid, changeName, purpose, startedAt} 供超时报错展示持有者。staleMs 10min(大 diff/deps
382
- * 可慢);抢锁等待 60s 仍失败 → fail-closed 报错退出:写主仓操作并发互踩不可自动恢复,
383
- * 宁可明确失败让人重试,不硬闯。只读路径(--check-only/status)不加锁。
384
- */
385
- export async function withMainRepoLock(projectRoot, changeName, purpose, fn, opts = {}) {
386
- const { withFileLock } = await import('./quicklog.js');
387
- const lockPath = join(projectRoot, '.sillyspec', '.runtime', 'main-repo.lock');
388
- const holder = JSON.stringify({ pid: process.pid, changeName, purpose: purpose || 'unknown', startedAt: new Date().toISOString() });
389
- const { staleMs = 10 * 60 * 1000, retryMs = 200 } = opts;
390
- // 等待时长可被 env 覆盖(测试与紧急调参用;opts.timeoutMs 显式传入仍最高优先)
391
- const envTimeout = parseInt(process.env.SILLYSPEC_MAIN_REPO_LOCK_TIMEOUT_MS || '', 10);
392
- const defaultTimeout = Number.isFinite(envTimeout) && envTimeout > 0 ? envTimeout : 60 * 1000;
393
- const { timeoutMs = defaultTimeout } = opts;
394
- // 进程退出兜底清锁:临界区内 process.exit(如 archiveChangeDirectory 的 guard exit(1))不会走
395
- // withFileLock 的 finally——不挂此钩子锁会残留挡他者直到 staleMs(10min)被偷。正常路径
396
- // finally 先释放并注销钩子,钩子只在进程真正退出时执行,无双删竞态。
397
- const onExit = () => { try { unlinkSync(lockPath) } catch {} };
398
- process.on('exit', onExit);
399
- try {
400
- return await withFileLock(lockPath, fn, {
401
- content: holder,
402
- staleMs,
403
- timeoutMs,
404
- retryMs,
405
- });
406
- } catch (e) {
407
- if (/文件锁超时/.test(String(e.message))) {
408
- let holderInfo = '';
409
- try {
410
- const raw = readFileSync(lockPath, 'utf8');
411
- try {
412
- const h = JSON.parse(raw);
413
- holderInfo = `(持有者: pid=${h.pid}, change=${h.changeName}, 操作=${h.purpose}, 始于 ${h.startedAt})`;
414
- } catch { holderInfo = `(持有者标识: ${raw.slice(0, 120)})`; }
415
- } catch { /* 锁文件已被释放(竞态窗口)→ 无持有者信息 */ }
416
- throw new Error(
417
- `主仓互斥锁被占用${holderInfo}:另一会话正在对主仓执行写操作(apply/cleanup/归档会写主仓工作区与 git 状态,并发互踩会互相清文件)。` +
418
- `等它完成后重试即可;若确认持有进程已崩溃退出,删除锁文件后重试:${lockPath}`
419
- );
420
- }
421
- throw e;
422
- } finally {
423
- process.removeListener('exit', onExit);
424
- }
425
- }
426
-
427
- export function applyWorktree(changeName, { cwd, checkOnly = false, merge = false, base = 'merge-base', ctx = null, skipOverlap = false, stashDirty = false } = {}) {
428
- const projectRoot = cwd || process.cwd();
429
- const wm = new WorktreeManager({ cwd: projectRoot });
430
- const meta = wm.getMeta(changeName);
431
- const result = {
432
- ok: false,
433
- changedFiles: [],
434
- extraFiles: [],
435
- hashMismatchFiles: [],
436
- deletedFiles: [],
437
- rescueCommands: null,
438
- patchPath: null,
439
- errors: [],
440
- merged: false,
441
- crossRepoValidated: [],
442
- skippedOverlapFiles: [],
443
- };
444
-
445
- // --- 0. 跨仓 task no-op 校验(task-05 / D-009) ---
446
- // 跨仓 task 的 commit 已落跨仓仓主干,apply = no-op(无 patch)。仅校验 review.head 是跨仓仓真实
447
- // commit + 不 cleanup(wm.cleanup 只作用主仓 worktree)。校验失败 → 推 errors 阻断 apply(R-05)。
448
- // 单仓 ctx 缺省 / 无跨仓 entry → validateCrossRepoNoOp 直接返回空(零回归)。
449
- if (ctx) {
450
- const cross = validateCrossRepoNoOp(ctx, projectRoot, changeName);
451
- for (const e of cross.errors) result.errors.push(e);
452
- if (cross.warnings.length > 0) result.warnings = (result.warnings || []).concat(cross.warnings);
453
- result.crossRepoValidated = cross.validated;
454
- // 跨仓 head 校验失败 = 跨仓改动未真落地,apply 不可继续(即使主仓 patch 能跑,跨仓 task 实际未完成)
455
- if (cross.errors.length > 0) return result;
456
- }
457
-
458
- // --- 1. 校验 worktree 存在 + meta.json 有效 ---
459
- if (!meta) {
460
- result.errors.push(`worktree not found: ${changeName}。meta.json 不存在或已损坏。`);
461
- return result;
462
- }
463
-
464
- const { worktreePath, baseHash, baselineCommit, branch } = meta;
465
- // 改动点 5:交付集合锚点(判定 changedFiles,保「只合子代理改动」语义)
466
- const deliverableBase = baselineCommit || baseHash;
467
-
468
- // 改动点 6:patch 锚点(生成 patch preimage,默认 merge-base 消除占位文件假冲突)
469
- let patchBase;
470
- if (base === 'baseline') {
471
- // 显式回退旧行为
472
- patchBase = deliverableBase;
473
- } else {
474
- // 默认 merge-base:在 projectRoot 计算 merge-base <baseBranch> <branchTip>
475
- const baseBranch = meta.baseBranch || 'master'; // meta.baseBranch 优先,否则默认 master
476
- const branchTip = branch || `sillyspec/${changeName}`; // meta.branch 优先,否则按命名约定
477
- try {
478
- patchBase = gitQuiet(projectRoot, ['merge-base', baseBranch, branchTip]);
479
- if (!patchBase) {
480
- console.warn(`⚠️ merge-base 计算失败(分支可能已删除),回退到 baseline 锚点`);
481
- patchBase = deliverableBase;
482
- }
483
- } catch (e) {
484
- console.warn(`⚠️ merge-base 计算异常(${e.message}),回退到 baseline 锚点`);
485
- patchBase = deliverableBase;
486
- }
487
- }
488
-
489
- if (!existsSync(worktreePath)) {
490
- result.errors.push(`worktree 目录不存在: ${worktreePath}`);
491
- return result;
492
- }
493
-
494
- // --- 2. 获取变更文件列表 ---
495
- // worktree 内修改可能没有 commit,用 git diff <baseHash>(比较 baseHash 到工作区内容)
496
- // 同时检测 untracked 新文件(git diff 不包含 untracked)
497
- let changedFiles;
498
- const deletedFiles = [];
499
- try {
500
- // 用 --name-status 捕获 rename/delete(--name-only 会丢失 rename 源文件)
501
- // 交付集合判定:用 deliverableBase(baselineCommit||baseHash),保「只合子代理改动」语义
502
- const statusRaw = git(worktreePath, ['diff', '--name-status', deliverableBase]);
503
- const statusFiles = new Set();
504
- if (statusRaw) {
505
- for (const line of statusRaw.split('\n').filter(Boolean)) {
506
- const parts = line.split('\t');
507
- // R100 old.txt new.txt → 提取两个文件
508
- if (parts.length >= 2) statusFiles.add(parts[parts.length - 1]);
509
- if (parts.length >= 3) statusFiles.add(parts[parts.length - 2]);
510
- // 删除文件(status D / D100)→ 收集到 deletedFiles(rescue DELETE 分类用,design §逐文件分类)
511
- if (parts[0].startsWith('D')) deletedFiles.push(parts[parts.length - 1]);
512
- }
513
- }
514
-
515
- // untracked 新文件(deliverableBase 中不存在的文件)
516
- const untrackedRaw = gitQuiet(worktreePath, ['ls-files', '--others', '--exclude-standard']);
517
- const untrackedFiles = untrackedRaw ? untrackedRaw.split('\n').filter(Boolean) : [];
518
-
519
- // 排除 worktree 基础设施文件(meta.json / .sillyspec/,见 filterDeliverableFiles)。
520
- // 对 modified-tracked(statusFiles)与 untracked 一视同仁——否则 modified 的 meta.json
521
- // 会被误算入 changedFiles,触发 design.md 清单校验失败(assess 恒 BLOCKED)。
522
- changedFiles = filterDeliverableFiles([...new Set([...statusFiles, ...untrackedFiles])]);
523
- } catch (e) {
524
- result.errors.push(`获取变更文件列表失败: ${e.message}`);
525
- return result;
526
- }
527
-
528
- result.changedFiles = changedFiles;
529
- result.deletedFiles = deletedFiles;
530
-
531
- if (changedFiles.length === 0) {
532
- // 没有变更
533
- if (!checkOnly) {
534
- wm.cleanup(changeName, { force: true });
535
- }
536
- result.ok = true;
537
- return result;
538
- }
539
-
540
- // --- 3. 解析 apply 文件清单(design §6 清单 ∪ plan TaskCard allowed_paths,execute 复盘 c) ---
541
- // resolveApplyAllowSet 返回 Map<repo, Set>(task-05 跨仓切片);主仓 apply 只消费 main 仓 Set
542
- // (主仓 worktree diff 只含主仓文件,跨仓文件在跨仓仓不进主仓 worktree diff)。跨仓 allowed_paths
543
- // 仅作 Map 切片返回供上游用,主流程不消费(跨仓 apply=no-op,D-009)。
544
- const allowMap = resolveApplyAllowSet(projectRoot, changeName);
545
- // --- 3b. review.json 声明偏差文件并入(坑 apply-undeclared-deviation-block)---
546
- // 第三源:reviewer 声明的 changedFiles(已过 Task Review Gate git 证据交叉校验)——执行期
547
- // 有据越界(facade 转发/名单测试)不再逼回改 design.md。各 repo 切片各自并入;仅靠 review
548
- // 放行的文件记审计 warning(result.reviewAdmittedFiles),完全越界文件仍拦(Gate1 在扩展后判)。
549
- const reviewDeclaredByRepo = collectReviewDeclaredFiles(projectRoot, changeName);
550
- const reviewAdmittedFiles = [];
551
- for (const [repoKey, files] of reviewDeclaredByRepo) {
552
- const repoSet = allowMap.get(repoKey);
553
- if (!repoSet) continue; // 该 repo 无 design/任务卡清单(无清单=不校验),无需扩展
554
- const existing = [...repoSet];
555
- for (const f of files) {
556
- if (!existing.some(ap => pathMatches(f, ap))) {
557
- repoSet.add(f);
558
- if (repoKey === 'main') reviewAdmittedFiles.push(f);
559
- }
560
- }
561
- }
562
- if (reviewAdmittedFiles.length > 0) {
563
- result.reviewAdmittedFiles = reviewAdmittedFiles;
564
- result.warnings = (result.warnings || []).concat([
565
- `${reviewAdmittedFiles.length} 个变更文件不在 design.md/任务卡清单,但已被 task review.json changedFiles 声明(review 声明放行,已过 Task Review Gate git 证据校验;审计留痕):${reviewAdmittedFiles.join(', ')}`
566
- ]);
567
- }
568
- const allowSet = allowMap.get('main') || new Set();
569
- const hasAllowList = allowSet.size > 0;
570
-
571
- // --- 3.5 主干已提交推进检测:hashMismatch 前移(Grill P0 修复,design §step 顺序修正)---
572
- // 原在 step5b,但 step4.5/5a dirty 拦截短路在 step5b 之前,致 rescue 拿不到 hashMismatchFiles
573
- // → EXCLUDE-MISMATCH 失效 → cp 覆盖主干已提交推进。前移到 step4.5 之前(仅依赖 baseHash/HEAD blob
574
- // 对比,无 dirty 依赖;allowSet/changedFiles/baseHash 均在本步之前可得,前移安全)。
575
- // 仅记录不拦截(交 step7 --3way 实测,真重叠回滚提示 --merge)。
576
- const targetFiles = hasAllowList ? [...allowSet] : changedFiles;
577
- const wtHashMap = getBlobHashMap(worktreePath, baseHash, targetFiles);
578
- const mainHashMap = getBlobHashMap(projectRoot, 'HEAD', targetFiles);
579
- for (const f of targetFiles) {
580
- const wtBlob = wtHashMap.get(f) ?? null;
581
- const mainBlob = mainHashMap.get(f) ?? null;
582
- if (wtBlob === null && mainBlob === null) continue;
583
- if (wtBlob === mainBlob) continue;
584
- result.hashMismatchFiles.push(f);
585
- }
586
- // 派生产物基线漂移 advisory(坑 derived-artifact-stale-baseline,2026-08-23 实证:多 agent
587
- // 并发仓中 worktree 旧基线生成的 api-types 被 apply 落地,把并行变更已合入主仓的新枚举刷掉,
588
- // 一次 build 红)。hashMismatchFiles 此前只在 rescue 分类 / merge 冲突时冒头——语义级覆盖
589
- // (旧内容文本可合 → --3way 静默成功)零提示。纯 warning 不阻断(生成器类变更的产物是合法
590
- // 交付,是否重跑生成命令由 agent 判断)。
591
- {
592
- const derivedRisk = result.hashMismatchFiles.filter(f => changedFiles.includes(f));
593
- if (derivedRisk.length > 0) {
594
- result.warnings = (result.warnings || []).concat([
595
- `${derivedRisk.length} 个变更文件在 worktree 基线后主仓已有新提交(并行变更可能已合入):${derivedRisk.slice(0, 5).join(', ')}${derivedRisk.length > 5 ? ' 等' : ''}` +
596
- `——若其中含生成产物(api-types/generated 等),本次 apply 可能以旧基线内容覆盖已合入的新内容;apply 后在新基线重跑生成命令(如 gen:types)再验证`
597
- ]);
598
- }
599
- }
600
-
601
- // --- 4. 校验:变更文件 ⊆ 清单(无清单则跳过)---
602
- if (hasAllowList) {
603
- const violations = classifyAllowListViolations(changedFiles, allowSet);
604
- if (violations.length > 0) {
605
- result.extraFiles.push(...violations);
606
- result.errors.push(
607
- `文件清单校验失败:以下变更文件不在 design.md 清单、也不在 task review.json changedFiles 声明中:\n ${violations.join('\n ')}\n(若属执行期合理偏差:在 task review.json 的 changedFiles 声明,或在 design.md §6 清单补行)`
608
- );
609
- // checkOnly(assess)模式不短路:继续跑 Gate3,收集所有道供一次报全(坑 worktree-execute-apply-friction 坑4)。
610
- // 真实 apply(checkOnly=false)仍短路,保安全。
611
- if (!checkOnly) return result;
612
- }
613
- }
614
-
615
- // --- 4.4 --stash-dirty:主仓在途改动自动 stash(坑 apply-main-dirty-no-first-class, ---
616
- // 2026-08-24 用户反馈四期①:主仓并行在途改动下默认 / --skip-overlap(全重叠「无可应用子集」)/
617
- // --merge(git 拒在脏树启动合并)三路死锁,手工 stash→3way→pop 流程未内置。flag 显式 opt-in
618
- // (自动触碰用户未提交工作区必须可审计):stash SHA 显著打印;恢复用 apply --index 保暂存区
619
- // 状态(普通 pop 会把 staged 降级为 unstaged);恢复失败保留条目绝不自动 drop(SHA 兜底)。
620
- // checkOnly(assess)只读,绝不 stash。放在 Gate1 之后:清单违规先拦,不动用户树。
621
- let stashInfo = null;
622
- if (stashDirty && !checkOnly) {
623
- try {
624
- const dirtyProbe = computeRescueDirtyFiles(projectRoot);
625
- if (dirtyProbe.length > 0) {
626
- const marker = `sillyspec apply ${changeName} --stash-dirty ${new Date().toISOString()}`;
627
- const before = (gitQuiet(projectRoot, ['stash', 'list']) || '').split('\n').filter(Boolean).length;
628
- // pathspec 限定 stash 范围与探针/4.5 同口径(排除 .sillyspec/ 运行时与他者 spec 产物、
629
- // .claude/docs/CLAUDE.md)——裸 push -u 会把排除项的未跟踪文件一并卷走,恢复时与
630
- // apply 期间重建的 spec 文件 already exists 互踩(实证 dbg)。
631
- git(projectRoot, ['stash', 'push', '--include-untracked', '-m', marker,
632
- '--', '.', ':(exclude).sillyspec/', ':(exclude).claude/', ':(exclude)docs/', ':(exclude)CLAUDE.md'], { timeout: 60000 });
633
- const headEntry = ((gitQuiet(projectRoot, ['stash', 'list']) || '').split('\n')[0] || '');
634
- const after = (gitQuiet(projectRoot, ['stash', 'list']) || '').split('\n').filter(Boolean).length;
635
- const sha = gitQuiet(projectRoot, ['rev-parse', '--verify', 'stash@{0}']);
636
- if (after !== before + 1 || !sha || !headEntry.includes(marker.split(' ').slice(0, 4).join(' '))) {
637
- // 栈顶非本次条目(并行外部操作插队)——不盲动栈,fail-closed
638
- throw new Error(`stash push 后栈顶校验失败(before=${before} after=${after} head=${headEntry.slice(0, 60)})`);
639
- }
640
- stashInfo = { sha: sha.trim(), marker };
641
- console.log(`📦 主仓在途改动已 stash(--stash-dirty,${dirtyProbe.length} 个文件):stash@{0} = ${stashInfo.sha}`);
642
- console.log(` apply 结束后自动恢复(git stash apply --index,保留暂存区状态);若恢复冲突,stash 条目保留不丢弃,用上述 SHA 兜底`);
643
- }
644
- } catch (e) {
645
- result.errors.push(`--stash-dirty:主仓 stash 失败(apply 未开始,主仓未改动): ${e.message}——若栈中已有新条目请 git stash list 核对后再处置,勿盲 pop`);
646
- return result;
647
- }
648
- }
649
-
650
- try {
651
- // --- 4.6 显式 --merge:用户显式选择 git merge 兜底(主干已提交推进重叠时的三方合并) ---
652
- // 触发点从「4.5 baseline 漂移自动降级」改为「用户显式 --merge flag」(D-001 保留,触发方式变化)。
653
- // 用 --merge 时跳过未提交 dirty 拦截——merge 同样要求工作区相对干净,此处仅提示风险,真正失败由 applyByMerge 报告。
654
- // keepConflicts:true——显式 --merge 冲突时保留现场供手工解决(不再直接 abort 丢上下文)。
655
- if (merge && !checkOnly) {
656
- return applyByMerge(result, changeName, projectRoot, wm, { keepConflicts: true });
657
- }
658
-
659
- // --- 4.5 校验:主工作区「未提交」脏文件是否与本次变更重叠(overlap-only 拦截)---
660
- // 分工:4.5(排除规则下 dirty∩changedFiles)+ 5a(更宽口径的同一交集)挡「未提交」dirty 重叠;
661
- // 5b 管「已提交」HEAD 分叉(已放宽)。
662
- // 2026-08-20 放宽(原全量拦截 → 只拦重叠):原「排除规则下任何未提交文件即整体拒绝」会把与本次
663
- // 变更无关的脏文件也硬挡,用户被迫走 rescue cp 手动路径。重叠(dirtyFiles ∩ changedFiles,
664
- // changedFiles 已含删除文件与 worktree 新增同名文件)才是 git apply 无法安全应用的实际危险区。
665
- // 残余风险与兜底(Windows/autocrlf):实测 autocrlf on 时 git apply --3way 对 dirty 工作区可报
666
- // `does not match index`(哪怕脏文件与 patch 不重叠;autocrlf off 时能干净应用,非 git 本质限制)。
667
- // 交集空前提下该失败是安全的:step7 catch → rollbackApply 只 checkout/删除 patch 涉及文件
668
- // (这些文件 apply 前无未提交修改,还原 = apply 前状态),无关脏文件不在 patch/rollback 范围
669
- // 不受影响 → fail-safe,报错后 stash 重试即可。放行时 warning 提示此路径。
670
- // 排除非交付物的元数据/文档 churn(execute 自身改的 + 多操作者常改的 agent 指引/文档),
671
- // 否则别人改 CLAUDE.md/docs/.claude → 判定 dirty → apply 误阻断(多操作者仓库高频踩坑)。
672
- // 注意:排除规则必须和 computeBaselineHash (worktree.js) 一致(虽已不比对 hash,仍用同一口径判当前 dirty)。
673
- if (meta.baselineHash) {
674
- // pathspec:`--` 结束选项,`.` 包含全部,后续 :(exclude) 排除非交付物元数据/文档 churn
675
- // (与 computeBaselineHash 同口径)。数组形式逐元素传递,:(exclude) magic 字面直传不经 shell。
676
- const exclude = ['--', '.', ':(exclude).sillyspec/', ':(exclude).claude/', ':(exclude)docs/', ':(exclude)CLAUDE.md'];
677
- const staged = gitQuiet(projectRoot, ['diff', '--cached', ...exclude]) || '';
678
- const unstaged = gitQuiet(projectRoot, ['diff', ...exclude]) || '';
679
- const untracked = gitQuiet(projectRoot, ['ls-files', '--others', '--exclude-standard', ...exclude]) || '';
680
- // 意图(与 computeBaselineHash 注释一致):只看「未提交 dirty」——git apply --3way 对 dirty 工作区不稳。
681
- // 不比对 hash 是否等于 execute 启动时 baselineHash:主仓 dirty→clean(execute 期间 commit 无关文件)后
682
- // hash 必变,若仍比对会永久死锁(须手改 meta.baselineHash)。改判「排除规则下当前是否有未提交 dirty」。
683
- const hasUncommittedDirty = staged !== '' || unstaged !== '' || untracked !== '';
684
- if (hasUncommittedDirty) {
685
- const dirtyFiles = [...new Set(
686
- ((gitQuiet(projectRoot, ['diff', '--name-only', 'HEAD']) || '').split('\n').filter(Boolean))
687
- .concat((gitQuiet(projectRoot, ['ls-files', '--others', '--exclude-standard']) || '').split('\n').filter(Boolean))
688
- )].filter(f => !f.startsWith('.sillyspec/') && f !== 'meta.json');
689
- const overlapDirty = dirtyFiles.filter(f => changedFiles.includes(f));
690
- if (overlapDirty.length > 0) {
691
- // --skip-overlap(坑 apply-overlap-all-or-nothing,2026-08-23 实证:多 agent 并发仓主仓
692
- // 常态有在途变更,overlap 整批拦截使 apply 基本不可用,rescue 手动 cp 又留混合状态):
693
- // 显式 opt-in 剔除重叠文件、应用干净子集。重叠文件留在 worktree——step8 非 force
694
- // cleanup 被 hasUnappliedChanges 护栏拦住(主仓工作区逐字节降噪层只剔除已应用文件),
695
- // 待主仓干净后重新 apply(此时只剩剩余文件)或人工裁决。
696
- if (skipOverlap && !checkOnly) {
697
- const skipSet = new Set(overlapDirty);
698
- result.skippedOverlapFiles = overlapDirty.slice();
699
- changedFiles = changedFiles.filter(f => !skipSet.has(f));
700
- result.changedFiles = changedFiles;
701
- result.deletedFiles = deletedFiles.filter(f => !skipSet.has(f));
702
- result.hashMismatchFiles = (result.hashMismatchFiles || []).filter(f => !skipSet.has(f));
703
- if (changedFiles.length === 0) {
704
- result.errors.push(
705
- `--skip-overlap:本次 ${overlapDirty.length} 个变更文件全部与主仓未提交改动重叠,无可应用子集:\n ${overlapDirty.join('\n ')}\n` +
706
- `请先提交/stash 主仓改动后重试(不带 --skip-overlap),或 sillyspec worktree apply ${changeName} --stash-dirty(工具内置 stash→apply→恢复,保暂存区状态,SHA 兜底可审计)。`
707
- );
708
- return result;
709
- }
710
- result.warnings = (result.warnings || []).concat([
711
- `--skip-overlap:跳过 ${overlapDirty.length} 个与主仓未提交改动重叠的文件(留在 worktree,未应用):${overlapDirty.join(', ')}——待主仓提交/stash 后重新 apply 只应用剩余文件,或确认放弃后 cleanup --force`
712
- ]);
713
- } else {
714
- // 重叠拦截:只有与本次变更同文件的未提交改动才无法安全 apply(列重叠文件,非全部脏文件)
715
- const rescueDirty = computeRescueDirtyFiles(projectRoot);
716
- result.rescueCommands = generateRescueCommands({
717
- changedFiles,
718
- dirtyFiles: rescueDirty,
719
- hashMismatchFiles: result.hashMismatchFiles,
720
- deletedFiles: result.deletedFiles,
721
- worktreePath,
722
- projectRoot,
723
- });
724
- result.errors.push(
725
- `主工作区以下未提交文件与本次 apply 的变更重叠,git apply 无法安全应用:\n ${overlapDirty.join('\n ')}\n` +
726
- `请先提交或暂存这些改动,再重新 apply:\n git add -A && git commit -m "..." 或 git stash\n` +
727
- `或 sillyspec worktree apply ${changeName} --stash-dirty(工具内置 stash→apply→恢复,保暂存区状态,SHA 兜底可审计)\n` +
728
- `或应用非重叠部分(重叠文件留在 worktree,主仓干净后重新 apply 只补剩余):\n sillyspec worktree apply ${changeName} --skip-overlap\n` +
729
- (result.rescueCommands.commands.length > 0 || result.rescueCommands.warnings.length > 0
730
- ? `或手动 rescue(旁路 git apply,逐文件 cp 安全子集;cp 后需手动 sillyspec worktree cleanup ${changeName}):\n` +
731
- result.rescueCommands.commands.map(c => ` ${c}`).join('\n') +
732
- (result.rescueCommands.warnings.length > 0 ? '\n' + result.rescueCommands.warnings.map(w => ` ${w}`).join('\n') : '') +
733
- `\n (共 ${result.rescueCommands.cpFileCount} 个可安全 cp,${result.rescueCommands.excludedCount} 个被排除)\n`
734
- : '')
735
- );
736
- if (!checkOnly) return result; // checkOnly 收集不短路(一次报全);真实 apply 短路
737
- }
738
- } else {
739
- // 无关脏文件放行(只校验重叠文件):--3way 若因 autocrlf 报 does not match index 会被
740
- // step7 catch 回滚(交集空前提下无损,见上注释),stash 后重试即可——不再硬挡 rescue 手动路径
741
- result.warnings = (result.warnings || []).concat([
742
- `主工作区有 ${dirtyFiles.length} 个与本次 apply 无关的未提交文件,已放行(只校验重叠文件):` +
743
- `${dirtyFiles.slice(0, 5).join(', ')}${dirtyFiles.length > 5 ? ' 等' : ''}` +
744
- `——若 apply --3way 因 CRLF/autocrlf 报 does not match index,可 git stash 后重试`
745
- ]);
746
- }
747
- }
748
- }
749
-
750
- // --- 5. 校验:主工作区文件 base hash 一致 ---
751
- // 5a. 检查主工作区是否有未 commit 的脏文件(会影响 apply)
752
- const mainDirtyRaw = gitQuiet(projectRoot, ['diff', '--name-only', 'HEAD']);
753
- const mainDirtyFiles = mainDirtyRaw ? mainDirtyRaw.split('\n').filter(Boolean) : [];
754
- if (mainDirtyFiles.length > 0) {
755
- // 如果脏文件和本次 apply 的文件有交集 → 报错
756
- const conflictDirty = mainDirtyFiles.filter(f => changedFiles.includes(f));
757
- if (conflictDirty.length > 0) {
758
- // --skip-overlap 同款剔除(4.5 过滤后此处残余多为 staged 口径差集,防御性同处理)
759
- if (skipOverlap && !checkOnly) {
760
- const skipSet5a = new Set(conflictDirty);
761
- for (const f of conflictDirty) {
762
- if (!result.skippedOverlapFiles.includes(f)) result.skippedOverlapFiles.push(f);
763
- }
764
- changedFiles = changedFiles.filter(f => !skipSet5a.has(f));
765
- result.changedFiles = changedFiles;
766
- result.deletedFiles = deletedFiles.filter(f => !skipSet5a.has(f));
767
- result.hashMismatchFiles = (result.hashMismatchFiles || []).filter(f => !skipSet5a.has(f));
768
- if (changedFiles.length === 0) {
769
- result.errors.push(
770
- `--skip-overlap:变更文件全部与主仓未提交改动重叠,无可应用子集:\n ${conflictDirty.join('\n ')}\n` +
771
- `请先提交/stash 主仓改动后重试,或 sillyspec worktree apply ${changeName} --stash-dirty(工具内置 stash→apply→恢复,保暂存区状态,SHA 兜底可审计)。`
772
- );
773
- return result;
774
- }
775
- result.warnings = (result.warnings || []).concat([
776
- `--skip-overlap(5a 口径):再剔除 ${conflictDirty.length} 个重叠文件:${conflictDirty.join(', ')}`
777
- ]);
778
- } else {
779
- const rescueDirty5a = computeRescueDirtyFiles(projectRoot);
780
- result.rescueCommands = generateRescueCommands({
781
- changedFiles, dirtyFiles: rescueDirty5a, hashMismatchFiles: result.hashMismatchFiles,
782
- deletedFiles: result.deletedFiles, worktreePath, projectRoot,
783
- });
784
- result.errors.push(
785
- `主工作区有以下未 commit 的变更,会影响 apply:\n ${conflictDirty.join('\n ')}\n请先 commit 或 stash 这些变更。` +
786
- `或应用非重叠部分:sillyspec worktree apply ${changeName} --skip-overlap` +
787
- (result.rescueCommands.commands.length > 0 || result.rescueCommands.warnings.length > 0
788
- ? `或手动 rescue(旁路 git apply,逐文件 cp 安全子集;cp 后需手动 sillyspec worktree cleanup ${changeName}):\n` +
789
- result.rescueCommands.commands.map(c => ` ${c}`).join('\n') +
790
- (result.rescueCommands.warnings.length > 0 ? '\n' + result.rescueCommands.warnings.map(w => ` ${w}`).join('\n') : '') +
791
- `\n (共 ${result.rescueCommands.cpFileCount} 个可安全 cp,${result.rescueCommands.excludedCount} 个被排除)\n`
792
- : '')
793
- );
794
- if (!checkOnly) return result; // checkOnly 收集不短路(一次报全);真实 apply 短路
795
- }
796
- }
797
- }
798
-
799
- // 5b hashMismatch 计算已前移到 step3.5(Grill P0),见上
800
-
801
- // --- 6. checkOnly 模式:到此返回 ---
802
- if (checkOnly) {
803
- result.ok = true;
804
- return result;
805
- }
806
-
807
- // --- 7. 生成 patch 并 apply ---
808
- // 确定要包含在 patch 中的文件:有清单用「实际变更 ∩ 清单(pathMatches 容差)」,无清单用全部变更。
809
- // 口径与 classifyAllowListViolations 一致(坑 apply-glob-manifest-passes-check-but-not-patch)。
810
- const patchFiles = resolvePatchFiles(changedFiles, allowSet, hasAllowList);
811
-
812
- // 创建临时文件
813
- const tmpDir = mkdtempSync(join(tmpdir(), 'sillyspec-patch-'));
814
- const patchPath = join(tmpDir, 'apply.patch');
815
- result.patchPath = patchPath;
816
-
817
- try {
818
- // patch 以 Buffer 聚合:git diff --binary 对二进制/非 UTF-8 文件输出任意字节序列,
819
- // 按 utf8 string 拼接会破坏 NUL 字节成 U+FFFD → corrupt patch(git-helper.js git() 注释
820
- // 同款坑;worktree.js 的 diff 采集已是 encoding:'buffer' 正确写法)。
821
- const patchParts = [];
822
-
823
- // 分 tracked 变更和 untracked 新文件生成 patch
824
- // 批量化:一次 ls-tree(deliverableBase tree 中存在的文件)+ 一次 ls-files(index 中存在的文件)
825
- // 建集合,替代 per-file cat-file -e / ls-files --error-unmatch(原至多 2N spawn → 固定 2)。
826
- // 语义等价:cat-file -e deliverableBase:f 成功 ⟺ f 在 ls-tree deliverableBase 输出(getBlobHashMap key);
827
- // ls-files --error-unmatch f 成功 ⟺ f 在 ls-files -- 输出。
828
- // tracked 判定用 deliverableBase(集合判定侧)
829
- const inTree = getBlobHashMap(worktreePath, deliverableBase, patchFiles);
830
- const inIndexList = patchFiles.length > 0
831
- ? (gitQuiet(worktreePath, ['ls-files', '--', ...patchFiles]) || '').split('\n').filter(Boolean)
832
- : [];
833
- const inIndex = new Set(inIndexList);
834
- const trackedFiles = patchFiles.filter(f => inTree.has(f) || inIndex.has(f));
835
- const trackedSet = new Set(trackedFiles);
836
- const untrackedPatchFiles = patchFiles.filter(f => !trackedSet.has(f));
837
-
838
- // tracked 文件:git diff patchBase(patch 生成锚点,默认 merge-base)
839
- // 数组形式,文件名逐个展开为独立 argv,不经 shell;
840
- // encoding:'buffer' 保留二进制补丁原样,timeout 放大到 60s 防大 diff 超时——原裸 execSync 无 timeout
841
- if (trackedFiles.length > 0) {
842
- patchParts.push(git(
843
- worktreePath,
844
- ['diff', '--binary', patchBase, '--', ...trackedFiles],
845
- { encoding: 'buffer', timeout: 60000 }
846
- ));
847
- }
848
-
849
- // untracked 新文件:git add 到 index,git diff --cached,然后 reset(均数组形式,文件名逐个展开)
850
- if (untrackedPatchFiles.length > 0) {
851
- git(worktreePath, ['add', '--', ...untrackedPatchFiles]);
852
- try {
853
- // encoding:'buffer' 保留二进制补丁原样,timeout 放大到 60s 防大 diff 超时
854
- patchParts.push(git(
855
- worktreePath,
856
- ['diff', '--binary', '--cached', '--', ...untrackedPatchFiles],
857
- { encoding: 'buffer', timeout: 60000 }
858
- ));
859
- } finally {
860
- // 重置 index(不保留 staged 状态)
861
- gitQuiet(worktreePath, ['reset', 'HEAD', '--', ...untrackedPatchFiles]);
862
- }
863
- }
864
-
865
- const patchContent = Buffer.concat(patchParts);
866
- if (patchContent.length === 0) {
867
- // patch 为空(清单中部分文件可能没实际变更)
868
- result.ok = true;
869
- rmSync(tmpDir, { recursive: true, force: true });
870
- return result;
871
- }
872
-
873
- writeFileSync(patchPath, patchContent);
874
-
875
- // apply --check 预检失败不再拦截(--check 只测 clean apply,--3way 能处理 clean apply 失败的
876
- // 三路合并场景——主干已提交推进时 --check 恒失败但 --3way 可合)。故跳过 --check,直接试 --3way。
877
-
878
- // 回滚准备:记录 patch 涉及的 tracked 文件(--3way 冲突后需恢复 HEAD 版,不留半成品冲突标记)。
879
- // tracked 文件冲突 → git checkout -- <f> 还原;untracked 新建文件(--3way 不会对其冲突)不在回滚范围,
880
- // 但若 --3way 部分成功后冲突,已创建的新文件需删,故记录 untracked 集合。
881
- const trackedPatchFiles = patchFiles.filter(f => {
882
- // 该文件在主仓库 HEAD 存在 → 是 tracked(--3way 冲突时留标记需 checkout 还原)
883
- return gitQuiet(projectRoot, ['cat-file', '-e', `HEAD:${f}`]) === null ? false : true;
884
- });
885
- const newPatchFiles = patchFiles.filter(f => !trackedPatchFiles.includes(f));
886
-
887
- // apply --3way 正式应用(主干已提交推进时自动三路合并)
888
- try {
889
- git(projectRoot, ['apply', '--3way', patchPath], { timeout: 30000 });
890
- } catch (e) {
891
- // --3way 冲突(exit 1,工作区已留冲突标记):回滚到 apply 前干净状态,不留半成品
892
- // FR-06:解析 git 原始 stderr 提取冲突文件列表(不静默吞掉)
893
- const rawStderr = e.message || '';
894
- const rollback = rollbackApply(projectRoot, trackedPatchFiles, newPatchFiles, rawStderr);
895
- // autocrlf 副作用单独点名:主仓无关未提交 dirty + CRLF 转换可触发 does not match index
896
- // (非文件内容冲突,交集空时 step4.5 已放行到这里)——回滚无损,stash 后重试即可
897
- if (/does not match index/i.test(rawStderr)) {
898
- result.errors.push(
899
- `apply --3way 失败(does not match index):多为主仓未提交文件 + Windows autocrlf 的 CRLF 副作用触发,非文件内容冲突。\n` +
900
- `已回滚工作区到 apply 前状态(无损,无关未提交文件未受影响)。\n` +
901
- `处理:git stash 后重试 sillyspec worktree apply ${changeName}(手工 stash 记下 git stash list 的 SHA——pop 失败时兜底),或 --merge 兜底,或 --stash-dirty 由工具自动 stash→apply→恢复。`
902
- );
903
- if (rollback.error) result.warnings = (result.warnings || []).concat([`回滚警告: ${rollback.error}`]);
904
- return result;
905
- }
906
- result.errors.push(
907
- `apply --3way 冲突:以下文件与主干「已提交」推进重叠,无法自动合并:\n` +
908
- ` ${rollback.conflicts.length > 0 ? rollback.conflicts.join('\n ') : '(未能获取冲突文件列表)'}\n` +
909
- `已回滚工作区到 apply 前状态(无半成品冲突标记)。\n` +
910
- `可选:用 --merge 自动三方合并兜底(git merge sillyspec/${changeName},会引入合并提交):\n` +
911
- ` sillyspec worktree apply ${changeName} --merge\n` +
912
- `或手动解决后重试。`
913
- );
914
- if (rollback.error) result.warnings = (result.warnings || []).concat([`回滚警告: ${rollback.error}`]);
915
- return result;
916
- }
917
-
918
- result.ok = true;
919
-
920
- // --- 7.5 提交复用 pathspec(坑 apply-commit-pathspec-sweep,2026-08-21 实证)---
921
- // apply 后主仓常混有无关未提交文件(他者会话/并行 quick),agent 习惯 `git add <目录>/`
922
- // 会把无关文件扫进暂存需手工剔除。落盘本变更精确 pathspec 供提交直接复用:
923
- // 文件 + result 字段(CLI 输出可照抄 git add -- … / 长清单用 --pathspec-from-file)。
924
- try {
925
- const commitFiles = [...new Set(patchFiles)].sort().filter(Boolean);
926
- result.commitPathspec = commitFiles;
927
- const runtimeRoot = join(projectRoot, '.sillyspec', '.runtime');
928
- mkdirSync(runtimeRoot, { recursive: true });
929
- const pathspecFile = join(runtimeRoot, `apply-pathspec-${changeName}.txt`);
930
- writeFileSync(pathspecFile, commitFiles.join('\n') + '\n');
931
- result.pathspecFile = pathspecFile;
932
- } catch { /* pathspec 落盘失败不影响 apply 结果 */ }
933
-
934
- // --- 8. 成功后自动 cleanup(失败不影响整体结果) ---
935
- // --skip-overlap 时先查 hasUnappliedChanges:跳过文件未落主仓 → 保留 worktree(不触发
936
- // cleanup 的拦截横幅吓人,主动判断 + 温和提示);全部已落地(无跳过残留)才照常清理。
937
- // cleanup 返回值必须消费(坑 ghost-dir-junction-pierce,2026-08-23 实证:apply 后 partial
938
- // 残留被静默丢弃,用户以为已干净、人工 rm -rf 时穿透 junction 删主仓 node_modules)。
939
- const consumeCleanup = (cr) => {
940
- if (cr && (cr.result === 'partial' || (Array.isArray(cr.residual) && cr.residual.length > 0))) {
941
- result.warnings.push(
942
- `⚠️ worktree 部分清理残留(${cr.result}):${(cr.residual || []).join('; ') || 'worktree 目录'}` +
943
- `——Windows 勿直接 rm -rf(会穿透 node_modules junction 删主仓依赖):先 cmd /c rmdir "<worktree>\\node_modules" 解链再删目录,或跑 sillyspec worktree doctor --fix`
944
- )
945
- }
946
- return cr
947
- }
948
- try {
949
- if (skipOverlap) {
950
- const unapplied = wm.hasUnappliedChanges(changeName);
951
- if (unapplied.hasChanges) {
952
- const pend = unapplied.changedFiles || [];
953
- result.warnings.push(
954
- `worktree 已保留(--skip-overlap 有未应用文件):${pend.length} 个文件仍在 worktree` +
955
- `(${pend.slice(0, 5).join(', ')}${pend.length > 5 ? ' 等' : ''})——主仓提交/stash 后重新 sillyspec worktree apply ${changeName} 只应用剩余文件,或确认放弃后 sillyspec worktree cleanup ${changeName} --force`
956
- );
957
- } else {
958
- consumeCleanup(wm.cleanup(changeName, { force: true }));
959
- }
960
- } else {
961
- consumeCleanup(wm.cleanup(changeName, { force: true }));
962
- }
963
- } catch (cleanupErr) {
964
- result.warnings = result.warnings || [];
965
- result.warnings.push(`cleanup 失败(不影响应用结果;Windows 手动清理先解 junction 再删,勿 rm -rf): ${cleanupErr.message}`);
966
- }
967
-
968
- } catch (e) {
969
- // ENOBUFS 自动降级(坑 apply-spawnsync-enobufs,2026-08-22 实证:大 diff 的 binary patch
970
- // 超 maxBuffer 抛 ENOBUFS,此前只能 agent 手动 git merge 绕行)——git apply 路径走不通时
971
- // 自动落 applyByMerge(既有 --merge 兜底,语义同为三方合并)
972
- if (/ENOBUFS/i.test(String(e.message || e.code || ''))) {
973
- result.warnings = (result.warnings || []).concat(
974
- [`patch 生成超出进程缓冲区(ENOBUFS,超大 diff)——自动降级 git merge 路径应用`]
975
- );
976
- try {
977
- // keepConflicts:false——自动降级路径无人善后冲突状态,维持 abort 回滚干净态
978
- return applyByMerge(result, changeName, projectRoot, wm, { keepConflicts: false });
979
- } catch (mergeErr) {
980
- result.errors.push(`ENOBUFS 降级 merge 也失败: ${mergeErr.message}`);
981
- return result;
982
- }
983
- }
984
- result.errors.push(`patch 生成/应用异常: ${e.message}`);
985
- return result;
986
- } finally {
987
- // 清理临时目录
988
- try { rmSync(tmpDir, { recursive: true, force: true }); } catch {}
989
- }
990
-
991
- return result;
992
- } finally {
993
- // stash 恢复(含 --merge 早退 / 各拦截 return / 异常路径——finally 全覆盖,绝不遗漏)
994
- if (stashInfo) restoreMainStash(projectRoot, stashInfo);
995
- }
996
- }
997
-
998
- /**
999
- * --stash-dirty 的收尾恢复(applyWorktree finally 调用)。
1000
- *
1001
- * 语义(坑 apply-main-dirty-no-first-class / stash-pop-silent-noop,2026-08-24 用户反馈四期①②):
1002
- * - 恢复用 `git stash apply --index`(保暂存区状态——普通 pop 会把 staged 降级为 unstaged);
1003
- * - apply 成功后才 drop 本次条目,drop 后核验栈顶已非本 SHA(用户实证 stash pop 有静默不落地
1004
- * 形态,退出码不可尽信);
1005
- * - apply --index 冲突/异常 → stash 条目保留(git apply 失败不 drop),大字打印 SHA 兜底,
1006
- * 绝不自动丢弃、绝不盲 pop 栈顶(并行外部操作可能插队,先按 SHA 校验栈顶归属)。
1007
- * @param {string} projectRoot
1008
- * @param {{ sha: string, marker: string }} stashInfo
1009
- */
1010
- function restoreMainStash(projectRoot, { sha, marker }) {
1011
- // 栈顶归属校验按 SHA(git stash list 行不含 SHA,须 rev-parse 对比)——防并行外部操作插队后误恢复他者条目
1012
- const headSha = (gitQuiet(projectRoot, ['rev-parse', '--verify', 'stash@{0}']) || '').trim();
1013
- if (headSha !== sha) {
1014
- console.error(`⚠️ stash 恢复跳过:栈顶 stash@{0} 已非本次条目(本次 ${sha},栈顶 ${headSha || '空'})——可能被并行操作消费/弹出。若本次条目仍在栈中:git stash list 找 ${sha.slice(0, 8)} 后 git stash apply --index <该ref>`);
1015
- return;
1016
- }
1017
- // 两级恢复:① apply --index(保暂存区状态)——但 apply 本身会把变更留在工作区未提交,stash 树是
1018
- // 全量快照,--index 的合并对「stash 树内但未被 stash 改动的脏文件」(正是刚 apply 落地的文件)
1019
- // 会报 local changes would be overwritten;② 退普通 apply(内容保真恢复,staged 扁平化为
1020
- // unstaged——诚实降级并提示重 add)。两级都失败 → 保留条目 + SHA 兜底,绝不自动丢弃。
1021
- let restored = null // 'index' | 'plain'
1022
- try {
1023
- git(projectRoot, ['stash', 'apply', '--index', 'stash@{0}'], { timeout: 60000 });
1024
- restored = 'index';
1025
- } catch (eIndex) {
1026
- try {
1027
- git(projectRoot, ['stash', 'apply', 'stash@{0}'], { timeout: 60000 });
1028
- restored = 'plain';
1029
- console.warn(`⚠️ 暂存区状态未能完整还原(apply --index 与本次 apply 落地的未提交变更互斥),已退普通恢复——内容保真,staged 文件被扁平化为 unstaged,如需请重新 git add。原因:${String(eIndex.message || eIndex).split('\n').slice(-2)[0] || eIndex}`);
1030
- } catch (e) {
1031
- console.error(`⚠️ stash 恢复失败(apply 冲突或异常)——stash 条目已保留(未丢弃),SHA 兜底:${sha}`);
1032
- console.error(` 处理:git stash list 定位条目(marker 含 "${String(marker || '').slice(0, 50)}");解决工作区冲突后 git stash apply stash@{N} 重试或人工合并;确认无需后再 git stash drop。未跟踪文件若报 already exists,比对内容后手动处理。`);
1033
- console.error(` git 输出: ${String(e.message || e).split('\n').slice(0, 3).join('\n ')}`);
1034
- return;
1035
- }
1036
- }
1037
- try {
1038
- git(projectRoot, ['stash', 'drop', 'stash@{0}'], { timeout: 60000 });
1039
- // 防静默不落地(用户实证②):drop 后栈顶不得仍是本 SHA
1040
- const headAfter = gitQuiet(projectRoot, ['rev-parse', '--verify', 'stash@{0}']);
1041
- if (headAfter && headAfter.trim() === sha) {
1042
- console.error(`⚠️ stash drop 未生效(栈顶仍为 ${sha})——改动应已恢复,确认 git status 后手动 git stash drop stash@{0}`);
1043
- } else {
1044
- console.log(`✅ 主仓在途改动已恢复(${restored === 'index' ? 'apply --index 保留暂存区状态' : '普通恢复,内容保真'})并清理 stash 条目:${sha}`);
1045
- }
1046
- } catch (e) {
1047
- console.error(`⚠️ stash drop 失败(改动应已恢复)——手动 git stash drop stash@{0}(${sha}):${e.message}`);
1048
- }
1049
- }
1050
-
1051
- /**
1052
- * 回滚 --3way 冲突后的工作区到 apply 前状态(不留半成品冲突标记)。
1053
- * tracked 文件:git checkout -- <f> 还原 HEAD 版(清除冲突标记)。
1054
- * 新文件(apply 前不存在):删除(--3way 可能部分创建)。
1055
- * @param {string} projectRoot
1056
- * @param {string[]} trackedFiles 主仓库 HEAD 已存在、patch 触及的文件
1057
- * @param {string[]} newFiles apply 前不存在、patch 可能新建的文件
1058
- * @param {string} [rawStderr] git apply 原始错误输出(FR-06:解析冲突文件列表)
1059
- * @returns {{ conflicts: string[], error: string|null }} conflicts=冲突文件列表
1060
- */
1061
- function rollbackApply(projectRoot, trackedFiles, newFiles, rawStderr = '') {
1062
- let error = null;
1063
- // 冲突文件来源:git status 探测 + stderr 解析(FR-06)
1064
- let conflicts = [];
1065
-
1066
- // 1. git status 探测(工作区遗留的 UU/AA 标记)
1067
- try {
1068
- const unmerged = gitQuiet(projectRoot, ['diff', '--name-only', '--diff-filter=U']) || '';
1069
- conflicts = unmerged.split('\n').filter(Boolean);
1070
- } catch {}
1071
-
1072
- // 2. 解析 git apply stderr(FR-06):提取冲突文件列表
1073
- let stderrConflicts = [];
1074
- if (rawStderr) {
1075
- try {
1076
- // 匹配模式:
1077
- // - error: patch failed: <file>:<line>
1078
- // - error: <file>: does not exist in index
1079
- // - CONFLICT (modify/delete): <file>
1080
- // - error: <file>: already exists in working directory
1081
- // - <file>: patch does not apply
1082
- // 容错:Windows 路径正斜杠、CRLF、引号包裹
1083
- const patterns = [
1084
- /error:\s+patch\s+failed:\s+(.+?)(?::\d+)?$/m,
1085
- /error:\s+(.+?):\s+does\s+not\s+exist\s+in\s+index$/m,
1086
- /CONFLICT\s+\([^)]+\):\s+(.+?)$/m,
1087
- /error:\s+(.+?):\s+already\s+exists/im,
1088
- /(.+?):\s+patch\s+does\s+not\s+apply$/m
1089
- ];
1090
-
1091
- for (const pat of patterns) {
1092
- const match = rawStderr.match(pat);
1093
- if (match) {
1094
- let file = match[1].trim();
1095
- // 去除引号(git 有时给文件名加引号)
1096
- file = file.replace(/^['"]|['"]$/g, '');
1097
- // 统一路径分隔符(Windows 混用 \ 和 /)
1098
- file = file.replace(/\\/g, '/');
1099
- if (file && !stderrConflicts.includes(file)) {
1100
- stderrConflicts.push(file);
1101
- }
1102
- }
1103
- }
1104
- } catch (parseErr) {
1105
- // 解析失败静默忽略,不影响原有流程(FR-06 容错要求)
1106
- }
1107
- }
1108
-
1109
- // 3. 合并去重
1110
- conflicts = [...new Set([...conflicts, ...stderrConflicts])];
1111
-
1112
- // 4. 双源皆空:错误信息附原始 stderr 尾部(截 800 字符)
1113
- if (conflicts.length === 0 && rawStderr) {
1114
- const tail = rawStderr.length > 800 ?
1115
- '\n ...(前略)...\n ' + rawStderr.slice(-800) :
1116
- '\n ' + rawStderr;
1117
- error = (error ? error + '\n' : '') + `原始 git apply 错误:${tail}`;
1118
- }
1119
- // 回滚 tracked 文件到 HEAD(强制从 HEAD 还原——--3way 冲突标记同时污染工作区和 index,
1120
- // `checkout -- f` 从 index 还原会拿到冲突版,必须 `checkout HEAD -- f` 才能还原干净)
1121
- for (const f of trackedFiles) {
1122
- try { gitQuiet(projectRoot, ['checkout', 'HEAD', '--', f]); } catch (e) { error = (error ? error + '; ' : '') + `checkout ${f}: ${e.message}`; }
1123
- }
1124
- // 删除 --3way 可能新建的文件(apply 前不存在)
1125
- for (const f of newFiles) {
1126
- try {
1127
- const p = join(projectRoot, f);
1128
- if (existsSync(p)) unlinkSync(p);
1129
- } catch (e) { error = (error ? error + '; ' : '') + `delete ${f}: ${e.message}`; }
1130
- }
1131
- // 兜底:若 index 处于 unmerged 状态,重置 index(不影响工作区已还原的文件)
1132
- try { gitQuiet(projectRoot, ['reset', '--quiet']); } catch {}
1133
- return { conflicts, error };
1134
- }
1135
-
1136
- /**
1137
- * merge 前预对齐 baseline 并行文件到 main 版(D-002@v1 / task-02)。
1138
- *
1139
- * 背景:baseline checkpoint 把 execute 启动时主仓 dirty 的并行会话文件快照进了 worktree 分支
1140
- * (worktree.js _createBaselineCheckpoint)。apply --merge 时主仓常已把这批文件推进(并行会话
1141
- * 落了 commit),分支侧旧快照与 main 新版在 merge-base 两侧同改同一文件 → merge 冲突。预对齐在
1142
- * merge 前把这批文件 checkout 成 main 版并提交到分支,使三方合并对该文件 ours == theirs,
1143
- * 消除冲突主因。
1144
- *
1145
- * 过滤集(四条件全满足才对齐;任一不满足跳过该文件):
1146
- * a. baseline checkpoint 文件集(已提交口径):git diff --name-only <baseHash>..<baselineCommit>
1147
- * ——不用 result.changedFiles(工作区口径且已过滤基础设施文件)
1148
- * b. ∩ main 已推进集:git diff --name-only <merge-base>..<main HEAD>
1149
- * (merge-base = 分支与 main HEAD 的最近公共祖先)
1150
- * c. ∖ 分支已变更集:git diff --name-only <baselineCommit>..<branch> 含该文件(本变更交付,不动)
1151
- * d. ∖ worktree 工作区 dirty 集:git status --porcelain -- <file> 非空(未提交改动会被 checkout 覆盖)
1152
- * 另排除「main HEAD 与分支 tip 内容已一致」的文件(对齐无意义,且防 nothing-to-commit 空提交)。
1153
- *
1154
- * 执行 cwd:checkout/commit 在 worktreePath(改的是 worktree 分支的 index+工作区);mainHead /
1155
- * merge-base 锚点在 projectRoot 读取。merge 本身仍在 projectRoot(applyByMerge 原逻辑不动)。
1156
- *
1157
- * 降级(不阻断):不适用场景(无 baseline checkpoint / 非 worktree 模式(in-place 的 worktreePath
1158
- * 就是主工作区,在其上 commit 等于绕过验收污染 main;native-worktree 是外部隔离环境)/ worktree
1159
- * 目录丢失 / worktree HEAD ≠ 分支 tip(checkout+commit 会落错分支,merge 的却是 meta.branch))
1160
- * 静默跳过;任一 git 步骤失败 → best-effort 回滚已 checkout 文件 + console.warn + result.warnings
1161
- * → 调用方走原 merge 路径(降级不阻断,D-002@v1 约束③)。
1162
- *
1163
- * @param {object} p
1164
- * @param {object} p.meta - worktree meta(baseHash / baselineCommit / worktreePath / mode)
1165
- * @param {string} p.branch - 将被 merge 的分支名(meta.branch)
1166
- * @param {string} p.projectRoot - 主仓库根(merge 的执行侧)
1167
- * @param {object} p.result - applyWorktree 的 result(预对齐信息写入 result.warnings,可追溯,约束④)
1168
- * @returns {{ aligned: string[], commit: string|null }} aligned=本次对齐的文件(空数组=未对齐)
1169
- */
1170
- function preAlignBaselineToMain({ meta, branch, projectRoot, result }) {
1171
- const pushWarning = (msg) => {
1172
- result.warnings = result.warnings || [];
1173
- result.warnings.push(msg);
1174
- };
1175
-
1176
- // 不适用场景(非失败,静默跳过)
1177
- if (!meta || !meta.baseHash || !meta.baselineCommit) return { aligned: [], commit: null };
1178
- if (meta.mode && meta.mode !== 'worktree') return { aligned: [], commit: null };
1179
- const worktreePath = meta.worktreePath;
1180
- if (!worktreePath || !existsSync(worktreePath)) return { aligned: [], commit: null };
1181
- const wtHead = gitQuiet(worktreePath, ['rev-parse', 'HEAD']);
1182
- const branchTip = gitQuiet(projectRoot, ['rev-parse', branch]);
1183
- if (!wtHead || !branchTip || wtHead !== branchTip) return { aligned: [], commit: null };
1184
-
1185
- const { baseHash, baselineCommit } = meta;
1186
- const done = []; // 已 checkout 的文件(失败回滚用)
1187
- try {
1188
- // (a) baseline checkpoint 文件集(已提交口径;--no-renames:rename 退化为 D+A,两侧路径都进集)
1189
- const baselineSet = new Set(
1190
- (git(worktreePath, ['diff', '--no-renames', '--name-only', baseHash, baselineCommit]) || '')
1191
- .split('\n').filter(Boolean)
1192
- );
1193
- if (baselineSet.size === 0) return { aligned: [], commit: null };
1194
-
1195
- // (b) main 已推进集(merge-base 后 main HEAD 的树差异;锚点拿不到 → 交原 merge,不算失败)
1196
- const mainHead = git(projectRoot, ['rev-parse', 'HEAD']);
1197
- const mergeBase = git(projectRoot, ['merge-base', branch, 'HEAD']);
1198
- if (!mainHead || !mergeBase) return { aligned: [], commit: null };
1199
- const mainAdvanced = new Set(
1200
- (git(projectRoot, ['diff', '--no-renames', '--name-only', mergeBase, mainHead]) || '')
1201
- .split('\n').filter(Boolean)
1202
- );
1203
-
1204
- // (c) 分支已变更集(baselineCommit → 分支 tip 的已提交交付,不动)
1205
- const branchChanged = new Set(
1206
- (git(worktreePath, ['diff', '--no-renames', '--name-only', baselineCommit, branchTip]) || '')
1207
- .split('\n').filter(Boolean)
1208
- );
1209
-
1210
- // (d) worktree 工作区 dirty + 两侧 HEAD 同内容排除 → 最终对齐集
1211
- const candidates = [];
1212
- for (const f of baselineSet) {
1213
- if (!mainAdvanced.has(f) || branchChanged.has(f)) continue;
1214
- // dirty(checkout 会覆盖 worktree 未提交改动)→ 跳过该文件
1215
- if ((gitQuiet(worktreePath, ['status', '--porcelain', '--', f]) || '') !== '') continue;
1216
- // main HEAD 与分支 tip 内容已一致 → 对齐无意义 + 防空提交
1217
- if ((gitQuiet(worktreePath, ['diff', '--name-only', mainHead, branchTip, '--', f]) || '') === '') continue;
1218
- candidates.push(f);
1219
- }
1220
- if (candidates.length === 0) return { aligned: [], commit: null };
1221
-
1222
- // 对齐:逐文件 checkout main 版(worktree 内执行,同时更新 worktree 分支的 index+工作区)
1223
- for (const f of candidates) {
1224
- git(worktreePath, ['checkout', mainHead, '--', f]);
1225
- done.push(f);
1226
- }
1227
- // 显式 pathspec 提交:只提交对齐文件,不扫入 worktree 内其他 staged 改动(坑 git-commit-sweeps-prestaged)。
1228
- // --no-verify:对齐 commit 与 baseline checkpoint 同性质(锚点非交付物,worktree.js _createBaselineCheckpoint
1229
- // 同款处理)——项目 pre-commit hook(如 husky lint+全量测试)会把预对齐拖成分钟级甚至失败降级。
1230
- git(worktreePath, [
1231
- 'commit', '--no-verify', '-m',
1232
- `sillyspec: align baseline files to main (pre-merge, ${done.length} files)`,
1233
- '--', ...done,
1234
- ]);
1235
- const shortHash = gitQuiet(worktreePath, ['rev-parse', '--short', 'HEAD']);
1236
- pushWarning(
1237
- `merge 前预对齐 ${done.length} 个 baseline 并行文件到 main 版` +
1238
- `${shortHash ? `(align commit ${shortHash})` : ''}:${done.join(', ')}`
1239
- );
1240
- return { aligned: done, commit: shortHash };
1241
- } catch (e) {
1242
- // 降级:任一步失败 → best-effort 回滚已 checkout 文件(checkout <branchTip> -- f 还原 index+工作区)
1243
- for (const f of done) {
1244
- gitQuiet(worktreePath, ['checkout', branchTip, '--', f]);
1245
- }
1246
- const msg = `baseline 预对齐失败,已跳过(降级走原 merge 路径):${(e.message || '').split('\n')[0]}` +
1247
- (done.length > 0 ? `;已回滚 ${done.length} 个已 checkout 文件` : '');
1248
- console.warn(`⚠️ ${msg}`);
1249
- pushWarning(msg);
1250
- return { aligned: [], commit: null };
1251
- }
1252
- }
1253
-
1254
- /**
1255
- * baseline 漂移时的 merge 降级路径(D-001)。
1256
- *
1257
- * 当主工作区 baseline 在 execute 期间漂移、patch 无法干净应用时,用
1258
- * `git merge sillyspec/<change>` 替代 patch apply(BRANCH_PREFIX='sillyspec/',worktree.js:18)。
1259
- * git merge 比 patch 鲁棒,能处理 baseline 漂移 + 潜在冲突。会引入合并提交
1260
- * (D-002:与 worktree.md:84「patch 而非 merge 保持线性历史」架构决策的张力——
1261
- * 仅作 --merge 显式 opt-in,不改变默认 patch 行为)。
1262
- * merge 前先经 preAlignBaselineToMain 预对齐 baseline 并行文件到 main 版(D-002@v1 / task-02,失败降级走原 merge)。
1263
- *
1264
- * merge 冲突时不自动解决:git merge --abort 回滚到合并前状态 + 报冲突文件列表。
1265
- *
1266
- * @param {object} result - applyWorktree 的 result 对象(mutate 后返回)
1267
- * @param {string} changeName
1268
- * @param {string} projectRoot - 主仓库根
1269
- * @param {object} wm - WorktreeManager 实例
1270
- * @returns {object} result(merged=true 表示走了 merge 降级)
1271
- */
1272
- // opts.keepConflicts(坑 merge-conflict-abort-no-chance,2026-08-23 实证:--merge 遇冲突直接
1273
- // abort 回滚,用户想手工解决只能自己重新 git merge——冲突现场与解决上下文全部丢失):
1274
- // true(显式 --merge 路径)→ 冲突时保留 merge-in-progress 现场 + 完整解决指引(编辑冲突 →
1275
- // git add + git commit;或 git merge --abort 放弃)。worktree/分支/meta 本就保留。
1276
- // false(ENOBUFS 自动降级路径,默认)→ 维持 abort——自动降级无人善后冲突状态,回滚到
1277
- // 干净态让用户显式重来更安全。
1278
- export function applyByMerge(result, changeName, projectRoot, wm, opts = {}) {
1279
- const { keepConflicts = false } = opts;
1280
- const meta = wm.getMeta(changeName);
1281
- const changedFiles = result.changedFiles || [];
1282
- // 用 meta.branch(native-worktree 模式分支名可能不是 sillyspec/<change>),不硬编码。
1283
- const branch = meta.branch || `sillyspec/${changeName}`;
1284
-
1285
- // --- merge 前预对齐(D-002@v1 / task-02):baseline 并行旧文件对齐 main 版,消除 merge 冲突主因 ---
1286
- preAlignBaselineToMain({ meta, branch, projectRoot, result });
1287
-
1288
- try {
1289
- git(projectRoot, ['merge', '--no-ff', branch], { timeout: 30000 });
1290
- } catch (e) {
1291
- // merge 失败两形态须区分(原实现混为一谈:dirty 拒绝启动也被当「冲突」报):
1292
- // ① 未启动:主仓有会被合并覆盖的未提交改动,git 直接拒绝(无 MERGE_HEAD)——没有现场
1293
- // 可保留也无需 abort,指引 commit/stash 或 --skip-overlap
1294
- // ② 真冲突:merge 已启动留 MERGE_HEAD + 冲突标记——keepConflicts 时保留现场供手工解决
1295
- let conflictFiles = [];
1296
- try {
1297
- const cf = gitQuiet(projectRoot, ['diff', '--name-only', '--diff-filter=U']);
1298
- conflictFiles = cf ? cf.split('\n').filter(Boolean) : [];
1299
- } catch {}
1300
- const mergeInProgress = gitQuiet(projectRoot, ['rev-parse', '-q', '--verify', 'MERGE_HEAD']) !== null;
1301
- if (!mergeInProgress) {
1302
- result.errors.push(
1303
- `git merge ${branch} 未执行成功——主仓有会被合并覆盖的未提交改动,git 拒绝启动合并(无冲突现场)。\n` +
1304
- `git 输出: ${String(e.message || '').split('\n').slice(0, 3).join(' | ').slice(0, 300)}\n` +
1305
- `请先 commit/stash 主仓改动后重试,或用 --skip-overlap 应用非重叠子集,或 sillyspec worktree apply ${changeName} --stash-dirty(自动 stash→apply→恢复,保暂存区状态,SHA 兜底)。`
1306
- );
1307
- return result;
1308
- }
1309
- if (keepConflicts) {
1310
- // 保留冲突现场(显式 --merge):主仓处于 merge-in-progress(MERGE_HEAD + unmerged index +
1311
- // 冲突标记),用户可直接手工解决——解决前 git 操作受限由指引明示,sillyspec 主仓命令
1312
- // (apply/cleanup 等)也会被 dirty/merge 状态挡住,属预期。
1313
- result.errors.push(
1314
- `git merge ${branch} 冲突,已在主仓保留冲突现场(未 abort)。冲突文件:\n` +
1315
- (conflictFiles.length ? ` ${conflictFiles.join('\n ')}\n` : ` (未能获取冲突文件列表——git diff --name-only --diff-filter=U 查看)\n`) +
1316
- `手工解决:编辑上述冲突文件 → git add <file> → git commit 完成合并(worktree/分支已保留,解决后无需重跑 apply)。\n` +
1317
- `放弃合并:git merge --abort 回到合并前状态后重试。注意:解决前主仓处于 merge 中状态,其他 sillyspec 主仓命令会被阻挡。`
1318
- );
1319
- return result;
1320
- }
1321
- try { gitQuiet(projectRoot, ['merge', '--abort']); } catch {}
1322
- result.errors.push(
1323
- `git merge ${branch} 冲突,请手动解决。冲突文件:\n` +
1324
- (conflictFiles.length ? ` ${conflictFiles.join('\n ')}\n` : ` (未能获取冲突文件列表)\n`) +
1325
- `已执行 git merge --abort 回滚到合并前状态。`
1326
- );
1327
- return result;
1328
- }
1329
-
1330
- // 落地校验:merge 报成功(exit 0)不代表交付物真进 main——
1331
- // 分支可能只含 baseline checkpoint(子代理改动未 commit),merge 产生空内容合并,文件零落地。
1332
- // 逐个确认 changedFiles 在 main HEAD 存在。任一缺失 → 不 cleanup(fail-open:保留 worktree 唯一副本)。
1333
- result.merged = true;
1334
- const notLanded = changedFiles.filter(f => gitQuiet(projectRoot, ['cat-file', '-e', `HEAD:${f}`]) === null);
1335
- if (notLanded.length > 0) {
1336
- result.ok = false;
1337
- result.errors.push(
1338
- `git merge ${branch} 报成功,但 ${notLanded.length}/${changedFiles.length} 个交付文件未出现在 main HEAD` +
1339
- `(分支可能只含 baseline checkpoint,子代理改动未 commit)。worktree 已保留(未 cleanup),` +
1340
- `请用 git cherry-pick 或手动 cp 落地:\n ${notLanded.join('\n ')}`
1341
- );
1342
- return result;
1343
- }
1344
-
1345
- result.ok = true;
1346
- try { result.mergeSummary = git(projectRoot, ['log', '--oneline', '-1']); } catch {}
1347
- try {
1348
- wm.cleanup(changeName, { force: true });
1349
- } catch (cleanupErr) {
1350
- result.warnings = result.warnings || [];
1351
- result.warnings.push(`cleanup 失败(不影响 merge 结果): ${cleanupErr.message}`);
1352
- }
1353
- return result;
1354
- }
1355
-
1356
- /**
1357
- * 风险审计:评估 worktree 变更是否可以安全自动 apply
1358
- *
1359
- * 检查项:
1360
- * 1. patch --check 通过
1361
- * 2. 所有变更在 allowed_paths 内
1362
- * 3. 主工作区 baseline 未变化
1363
- * 4. 没有删除/重命名关键文件
1364
- * 5. 没有改高风险文件(lockfile/migration/配置/入口)除非任务显式允许
1365
- * 6. diff 规模没有异常膨胀
1366
- *
1367
- * @param {string} changeName
1368
- * @param {{ cwd?: string }} opts
1369
- * @returns {{
1370
- * decision: 'SAFE' | 'WARNING' | 'BLOCKED',
1371
- * changedFiles: string[],
1372
- * reasons: string[],
1373
- * warnings: string[],
1374
- * stats: { additions: number, deletions: number }
1375
- * }}
1376
- */
1377
- export function assessApplyRisk(changeName, { cwd } = {}) {
1378
- const projectRoot = cwd || process.cwd();
1379
- const reasons = [];
1380
- const warnings = [];
1381
-
1382
- // 先跑 --check-only 模式的 applyWorktree 获取变更文件列表
1383
- const checkResult = applyWorktree(changeName, { cwd: projectRoot, checkOnly: true });
1384
-
1385
- // applyWorktree(checkOnly) 已收集所有道(Gate1/3 不短路)——其 errors 纳入 reasons,
1386
- // 继续跑 Gate2/4/6 一次报全(坑 worktree-execute-apply-friction 坑4:原此处提前 return 致逐道挤牙膏)。
1387
- reasons.push(...checkResult.errors);
1388
- if (checkResult.warnings?.length) warnings.push(...checkResult.warnings);
1389
-
1390
- const changedFiles = checkResult.changedFiles;
1391
-
1392
- if (changedFiles.length === 0) {
1393
- // 无变更:若仍有 Gate 错误(如主区 dirty)则 BLOCKED,否则 SAFE
1394
- if (reasons.length > 0) {
1395
- return { decision: 'BLOCKED', changedFiles: [], reasons, warnings, stats: { additions: 0, deletions: 0 }, rescueCommands: checkResult.rescueCommands || null };
1396
- }
1397
- return {
1398
- decision: 'SAFE',
1399
- changedFiles: [],
1400
- reasons: ['无变更需要应用'],
1401
- warnings: [],
1402
- stats: { additions: 0, deletions: 0 },
1403
- rescueCommands: checkResult.rescueCommands || null
1404
- };
1405
- }
1406
-
1407
- // 解析 TaskCard allowed_paths(复用 plan-postcheck.parseAllowedPaths,消除内联重复实现漂移)
1408
- const wm = new WorktreeManager({ cwd: projectRoot });
1409
- const meta = wm.getMeta(changeName);
1410
- const tasksDir = join(projectRoot, CHANGES_REL, changeName, 'tasks');
1411
- const allowedPaths = new Set();
1412
- if (existsSync(tasksDir)) {
1413
- for (const tf of readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))) {
1414
- for (const p of parseAllowedPaths(readFileSync(join(tasksDir, tf), 'utf8'))) {
1415
- if (p) allowedPaths.add(p);
1416
- }
1417
- }
1418
- }
1419
-
1420
- // design §6 标记为「顺带修复」的文件(坑 worktree-execute-apply-friction 坑1):合规修预存债,
1421
- // 不属任何 task 边界,assess 豁免 allowed_paths 严格校验(降级 warning),避免被迫 cherry-pick 绕过。
1422
- const designPath = join(projectRoot, CHANGES_REL, changeName, 'design.md');
1423
- const incidentalSet = new Set(
1424
- parseFileChangeListDetailed(designPath).filter(e => e.incidental).map(e => e.path)
1425
- );
1426
- // review.json 声明偏差文件(坑 apply-undeclared-deviation-block):与顺带修复同等待遇——
1427
- // reviewer 声明(已过 git 证据校验)的执行期偏差豁免 allowed_paths 严格校验,降 warning 注明来源。
1428
- const reviewDeclaredSet = new Set(collectReviewDeclaredFiles(projectRoot, changeName).get('main') || []);
1429
-
1430
- // 检查 2: 变更在 allowed_paths 内(仅在 TaskCard 存在时);顺带修复/review 声明文件豁免。
1431
- // 匹配换 pathMatches(与 Gate1/plan-postcheck 同语义容差),消除原字面前缀弱匹配漂移。
1432
- if (allowedPaths.size > 0) {
1433
- const isIncidental = f => [...incidentalSet].some(ap => pathMatches(f, ap));
1434
- const isReviewDeclared = f => [...reviewDeclaredSet].some(ap => pathMatches(f, ap));
1435
- const outsideAll = changedFiles.filter(f => ![...allowedPaths].some(allowed => pathMatches(f, allowed)));
1436
- const outsidePaths = outsideAll.filter(f => !isIncidental(f) && !isReviewDeclared(f));
1437
- const exempted = outsideAll.filter(f => isIncidental(f));
1438
- const reviewExempted = outsideAll.filter(f => !isIncidental(f) && isReviewDeclared(f));
1439
- if (outsidePaths.length > 0) {
1440
- reasons.push(`变更文件超出 allowed_paths:\n ${outsidePaths.join('\n ')}`);
1441
- }
1442
- if (exempted.length > 0) {
1443
- warnings.push(`顺带修复文件(已豁免 allowed_paths,来源 design §6 标记):${exempted.join(', ')}`);
1444
- }
1445
- if (reviewExempted.length > 0) {
1446
- warnings.push(`review 声明偏差文件(已豁免 allowed_paths,来源 task review.json changedFiles,过 git 证据校验):${reviewExempted.join(', ')}`);
1447
- }
1448
- }
1449
-
1450
- // 检查 4+5: 高风险文件模式
1451
- const HIGH_RISK_PATTERNS = [
1452
- /(^|\/)package-lock\.json$/,
1453
- /(^|\/)pnpm-lock\.yaml$/,
1454
- /(^|\/)yarn\.lock$/,
1455
- /(^|\/)\.env($|\.)/,
1456
- /(^|\/)docker-compose.*\.ya?ml$/,
1457
- /(^|\/)Dockerfile$/,
1458
- /migration[\w.-]*\.(sql|js|ts)$/i,
1459
- /(^|\/).*entry.*\.(js|ts)$/i,
1460
- /(^|\/)main\.(js|ts)$/i,
1461
- /(^|\/)index\.(js|ts)$/i,
1462
- /(^|\/)app\.(js|ts)$/i,
1463
- ];
1464
- const riskyFiles = changedFiles.filter(f => HIGH_RISK_PATTERNS.some(p => p.test(f)));
1465
- if (riskyFiles.length > 0) {
1466
- // 高风险文件只有在 allowedPaths 显式包含时才放行
1467
- const trulyRisky = riskyFiles.filter(f => !
1468
- [...allowedPaths].some(allowed => f === allowed)
1469
- );
1470
- if (trulyRisky.length > 0) {
1471
- reasons.push(`高风险文件变更(未在 allowed_paths 中显式声明):\n ${trulyRisky.join('\n ')}`);
1472
- } else {
1473
- warnings.push(`高风险文件变更(已在 allowed_paths 中声明):${riskyFiles.join(', ')}`);
1474
- }
1475
- }
1476
-
1477
- // 检查 6: diff 规模异常(两档:>5000 行 BLOCKED;2000~5000 行 WARNING——正常规模 change
1478
- // 常超 2000 行(如 +2368),单档硬拦把正常变更逼进 rescue cp 手动路径,见 ql-20260815-001 复盘)
1479
- const wtPath = meta?.worktreePath;
1480
- const diffBase = meta?.baselineCommit || meta?.baseHash;
1481
- let additions = 0, deletions = 0;
1482
- if (wtPath && diffBase) {
1483
- try {
1484
- const shortstat = gitQuiet(wtPath, ['diff', '--shortstat', diffBase]);
1485
- const insMatch = shortstat?.match(/(\d+) insertion/);
1486
- const delMatch = shortstat?.match(/(\d+) deletion/);
1487
- additions = insMatch ? parseInt(insMatch[1]) : 0;
1488
- deletions = delMatch ? parseInt(delMatch[1]) : 0;
1489
- if (additions + deletions > 5000) {
1490
- reasons.push(`diff 规模异常(${additions} additions + ${deletions} deletions = ${additions + deletions} 行,超过 5000 硬上限)`);
1491
- } else if (additions + deletions > 2000) {
1492
- warnings.push(`diff 规模偏大(${additions} additions + ${deletions} deletions = ${additions + deletions} 行,2000~5000 区间放行为 WARNING,请确认属正常变更规模)`);
1493
- }
1494
- } catch {}
1495
- }
1496
-
1497
- // 判定
1498
- let decision;
1499
- if (reasons.length > 0) {
1500
- decision = 'BLOCKED';
1501
- } else if (warnings.length > 0) {
1502
- decision = 'WARNING';
1503
- } else {
1504
- decision = 'SAFE';
1505
- }
1506
-
1507
- return { decision, changedFiles, reasons, warnings, stats: { additions, deletions }, rescueCommands: checkResult.rescueCommands || null };
1508
- }
1509
-
1510
- /**
1511
- * 格式化 execute run summary(人类可读)
1512
- *
1513
- * 只展示 CLI 真实掌握的信息,不声称知道 per-task 状态。
1514
- * @param {object} opts
1515
- * @param {string} opts.changeName - 变更名
1516
- * @param {number} opts.stepsCompleted - 已完成步骤数
1517
- * @param {number} opts.stepsTotal - 总步骤数
1518
- * @param {string} opts.agentSummary - Agent 最终输出摘要
1519
- * @param {string} [opts.cwd] - 项目根目录(默认 process.cwd())
1520
- * @returns {string} 格式化的 summary 文本
1521
- */
1522
- export function formatExecuteSummary({ changeName, stepsCompleted, stepsTotal, agentSummary, cwd }) {
1523
- const wm = new WorktreeManager({ cwd });
1524
- const meta = wm.getMeta(changeName);
1525
- const lines = [];
1526
-
1527
- const SEPARATOR = '─'.repeat(32);
1528
-
1529
- // --- Header ---
1530
- lines.push(`Execute Summary`);
1531
- lines.push(SEPARATOR);
1532
-
1533
- // --- Status ---
1534
- if (!meta) {
1535
- // worktree 不存在(可能已 cleanup 或没有用过 worktree)
1536
- lines.push(`Status: COMPLETED`);
1537
- lines.push(`Steps: ${stepsCompleted} / ${stepsTotal}`);
1538
- lines.push(`Apply: N/A`);
1539
- } else {
1540
- const hasBaseline = meta.baselineCommit != null;
1541
- const wtExists = existsSync(meta.worktreePath);
1542
-
1543
- const applyStatus = wtExists ? 'pending' : 'applied';
1544
- const baselineCount = meta.baselineFiles?.length || 0;
1545
- const baselineStatus = hasBaseline
1546
- ? `dirty (${baselineCount} baseline file${baselineCount === 1 ? '' : 's'} protected)`
1547
- : 'clean';
1548
-
1549
- // Worktree 最终状态
1550
- const mode = meta.mode || 'worktree';
1551
- let worktreeStatus;
1552
- if (mode === 'native-worktree') {
1553
- worktreeStatus = 'kept (external worktree)';
1554
- } else if (mode === 'in-place-fallback') {
1555
- worktreeStatus = 'none (in-place)';
1556
- } else if (!wtExists) {
1557
- worktreeStatus = 'cleaned';
1558
- } else {
1559
- worktreeStatus = 'exists';
1560
- }
1561
-
1562
- lines.push(`Status: COMPLETED`);
1563
- lines.push(`Steps: ${stepsCompleted} / ${stepsTotal}`);
1564
- lines.push(`Baseline: ${baselineStatus}`);
1565
- lines.push(`Apply: ${applyStatus}`);
1566
- lines.push(`Worktree: ${worktreeStatus}`);
1567
- }
1568
-
1569
- // --- Changed files ---
1570
- // 从主工作区 diff 获取(worktree 已 apply)或从 worktree diff 获取
1571
- if (meta && existsSync(meta.worktreePath)) {
1572
- // worktree 还在,用 baselineCommit 或 baseHash 做 diff
1573
- try {
1574
- const diffBase = meta.baselineCommit || meta.baseHash;
1575
- // QUAL-01 收口:裸 execFileSync → git-helper git(stderr 由 helper stdio 配置吞掉,
1576
- // 替代 `2>/dev/null`——Windows cmd.exe 无法解析该重定向,导致 Windows 上恒抛错→Changed Files 空)
1577
- const filesRaw = git(meta.worktreePath, ['diff', '--name-only', diffBase], { timeout: 30000 });
1578
- const files = filesRaw ? filesRaw.trim().split('\n').filter(Boolean) : [];
1579
- if (files.length > 0) {
1580
- lines.push(``);
1581
- const maxShow = 10;
1582
- const showFiles = files.slice(0, maxShow);
1583
- const remain = files.length - maxShow;
1584
- lines.push(`Changed Files (${files.length})`);
1585
- showFiles.forEach(f => lines.push(` ${f}`));
1586
- if (remain > 0) {
1587
- lines.push(` ... ${remain} more`);
1588
- }
1589
- }
1590
- } catch {}
1591
- }
1592
-
1593
- // --- Agent Summary ---
1594
- if (agentSummary) {
1595
- lines.push(``);
1596
- lines.push(`Agent Summary`);
1597
- // 缩进每行,截断过长内容
1598
- const maxLen = 200;
1599
- const summary = agentSummary.length > maxLen
1600
- ? agentSummary.slice(0, maxLen) + '...'
1601
- : agentSummary;
1602
- summary.split('\n').forEach(l => lines.push(` ${l}`));
1603
- }
1604
-
1605
- // --- Next ---
1606
- lines.push(``);
1607
- lines.push(`Next`);
1608
- lines.push(` → sillyspec run verify`);
1609
-
1610
- return lines.join('\n');
1611
- }