sillyspec 3.27.5 → 3.27.7

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 (1101) hide show
  1. package/.claude/skills/sillyspec-archive/SKILL.md +87 -87
  2. package/.claude/skills/sillyspec-auto/SKILL.md +93 -93
  3. package/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -114
  4. package/.claude/skills/sillyspec-commit/SKILL.md +67 -67
  5. package/.claude/skills/sillyspec-continue/SKILL.md +47 -47
  6. package/.claude/skills/sillyspec-doctor/SKILL.md +76 -76
  7. package/.claude/skills/sillyspec-execute/SKILL.md +214 -214
  8. package/.claude/skills/sillyspec-explore/SKILL.md +102 -102
  9. package/.claude/skills/sillyspec-export/SKILL.md +57 -57
  10. package/.claude/skills/sillyspec-init/SKILL.md +177 -177
  11. package/.claude/skills/sillyspec-knowledge/SKILL.md +269 -269
  12. package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
  13. package/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  14. package/.claude/skills/sillyspec-quick/SKILL.md +116 -116
  15. package/.claude/skills/sillyspec-resume/SKILL.md +70 -70
  16. package/.claude/skills/sillyspec-scan/SKILL.md +79 -79
  17. package/.claude/skills/sillyspec-state/SKILL.md +64 -64
  18. package/.claude/skills/sillyspec-status/SKILL.md +54 -54
  19. package/.claude/skills/sillyspec-verify/SKILL.md +87 -87
  20. package/.claude/skills/sillyspec-workspace/SKILL.md +175 -175
  21. package/.claude/skills/verify-per-user/SKILL.md +6 -0
  22. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  23. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  24. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  25. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  26. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  27. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  28. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  29. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  30. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +57 -0
  31. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +177 -0
  32. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  33. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  34. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  35. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  36. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  37. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  38. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +64 -0
  39. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +54 -0
  40. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  41. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  42. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +6 -0
  43. package/.worktrees/2c37b1d7/.gitattributes +2 -0
  44. package/.worktrees/2c37b1d7/.husky/pre-push +20 -0
  45. package/.worktrees/2c37b1d7/README.md +203 -0
  46. package/.worktrees/2c37b1d7/SKILL.md +91 -0
  47. package/.worktrees/2c37b1d7/architecture-analysis.md +448 -0
  48. package/.worktrees/2c37b1d7/bin/sillyspec.js +2 -0
  49. package/.worktrees/2c37b1d7/eval/README.md +86 -0
  50. package/.worktrees/2c37b1d7/eval/eval.config.json +28 -0
  51. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +63 -0
  52. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +27 -0
  53. package/.worktrees/2c37b1d7/eval/lib/config.mjs +82 -0
  54. package/.worktrees/2c37b1d7/eval/lib/db.mjs +76 -0
  55. package/.worktrees/2c37b1d7/eval/lib/report.mjs +120 -0
  56. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +157 -0
  57. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +73 -0
  58. package/.worktrees/2c37b1d7/eval/lib/util.mjs +107 -0
  59. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +30 -0
  60. package/.worktrees/2c37b1d7/eval/run.mjs +83 -0
  61. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +6 -0
  62. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  63. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +6 -0
  64. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +28 -0
  65. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +6 -0
  66. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  67. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  68. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +6 -0
  69. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +31 -0
  70. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  71. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +6 -0
  72. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  73. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +6 -0
  74. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +38 -0
  75. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  76. package/.worktrees/2c37b1d7/package-lock.json +977 -0
  77. package/.worktrees/2c37b1d7/package.json +41 -0
  78. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  79. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  80. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  81. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +16 -0
  82. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  83. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +836 -0
  84. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +256 -0
  85. package/.worktrees/2c37b1d7/packages/dashboard/package.json +25 -0
  86. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +95 -0
  87. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +679 -0
  88. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +526 -0
  89. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +357 -0
  90. package/.worktrees/2c37b1d7/src/agent-session-log.js +803 -0
  91. package/.worktrees/2c37b1d7/src/change-list.js +290 -0
  92. package/.worktrees/2c37b1d7/src/change-risk-profile.js +339 -0
  93. package/.worktrees/2c37b1d7/src/check-primitives.js +65 -0
  94. package/.worktrees/2c37b1d7/src/classify-change.js +109 -0
  95. package/.worktrees/2c37b1d7/src/commit-suggest.js +202 -0
  96. package/.worktrees/2c37b1d7/src/config-cat.js +88 -0
  97. package/.worktrees/2c37b1d7/src/config-schema.js +328 -0
  98. package/.worktrees/2c37b1d7/src/constants.js +97 -0
  99. package/.worktrees/2c37b1d7/src/contract-matrix.js +533 -0
  100. package/.worktrees/2c37b1d7/src/datetime.js +20 -0
  101. package/.worktrees/2c37b1d7/src/db-engine.js +55 -0
  102. package/.worktrees/2c37b1d7/src/db.js +381 -0
  103. package/.worktrees/2c37b1d7/src/decision-distill.js +517 -0
  104. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +155 -0
  105. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +245 -0
  106. package/.worktrees/2c37b1d7/src/dispatch/probe.js +246 -0
  107. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +121 -0
  108. package/.worktrees/2c37b1d7/src/docs-check.js +825 -0
  109. package/.worktrees/2c37b1d7/src/docs-debt.js +393 -0
  110. package/.worktrees/2c37b1d7/src/docs-gate.js +107 -0
  111. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +1099 -0
  112. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +409 -0
  113. package/.worktrees/2c37b1d7/src/foreign-declared.js +155 -0
  114. package/.worktrees/2c37b1d7/src/fs-atomic.js +73 -0
  115. package/.worktrees/2c37b1d7/src/git-helper.js +150 -0
  116. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +130 -0
  117. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +892 -0
  118. package/.worktrees/2c37b1d7/src/index.js +2854 -0
  119. package/.worktrees/2c37b1d7/src/init.js +626 -0
  120. package/.worktrees/2c37b1d7/src/knowledge-match.js +231 -0
  121. package/.worktrees/2c37b1d7/src/local-detect.js +128 -0
  122. package/.worktrees/2c37b1d7/src/local-register.js +104 -0
  123. package/.worktrees/2c37b1d7/src/machine-interface.js +543 -0
  124. package/.worktrees/2c37b1d7/src/migrate.js +127 -0
  125. package/.worktrees/2c37b1d7/src/module-impact.js +166 -0
  126. package/.worktrees/2c37b1d7/src/module-resolve.js +222 -0
  127. package/.worktrees/2c37b1d7/src/modules.js +580 -0
  128. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +126 -0
  129. package/.worktrees/2c37b1d7/src/progress/change-registry.js +336 -0
  130. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +355 -0
  131. package/.worktrees/2c37b1d7/src/progress/shared.js +36 -0
  132. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +594 -0
  133. package/.worktrees/2c37b1d7/src/progress/step-store.js +265 -0
  134. package/.worktrees/2c37b1d7/src/progress.js +1304 -0
  135. package/.worktrees/2c37b1d7/src/quick-recommend.js +115 -0
  136. package/.worktrees/2c37b1d7/src/quicklog.js +883 -0
  137. package/.worktrees/2c37b1d7/src/review-tier.js +77 -0
  138. package/.worktrees/2c37b1d7/src/run/command.js +1641 -0
  139. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +1552 -0
  140. package/.worktrees/2c37b1d7/src/run/complete.js +1259 -0
  141. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +156 -0
  142. package/.worktrees/2c37b1d7/src/run/gates.js +1111 -0
  143. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +208 -0
  144. package/.worktrees/2c37b1d7/src/run/next.js +128 -0
  145. package/.worktrees/2c37b1d7/src/run/prompt.js +843 -0
  146. package/.worktrees/2c37b1d7/src/run/quick-audit.js +186 -0
  147. package/.worktrees/2c37b1d7/src/run/scan-profile.js +269 -0
  148. package/.worktrees/2c37b1d7/src/run/shared.js +1562 -0
  149. package/.worktrees/2c37b1d7/src/run/stage.js +587 -0
  150. package/.worktrees/2c37b1d7/src/run.js +23 -0
  151. package/.worktrees/2c37b1d7/src/scan-diff.js +388 -0
  152. package/.worktrees/2c37b1d7/src/scan-postcheck.js +524 -0
  153. package/.worktrees/2c37b1d7/src/scan-staleness.js +95 -0
  154. package/.worktrees/2c37b1d7/src/setup.js +414 -0
  155. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +597 -0
  156. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +62 -0
  157. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +50 -0
  158. package/.worktrees/2c37b1d7/src/spec-sync.js +358 -0
  159. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +171 -0
  160. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +551 -0
  161. package/.worktrees/2c37b1d7/src/stage-contract.js +948 -0
  162. package/.worktrees/2c37b1d7/src/stage-review.js +597 -0
  163. package/.worktrees/2c37b1d7/src/stages/archive.js +199 -0
  164. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +285 -0
  165. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +624 -0
  166. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +145 -0
  167. package/.worktrees/2c37b1d7/src/stages/doctor.js +540 -0
  168. package/.worktrees/2c37b1d7/src/stages/execute.js +1277 -0
  169. package/.worktrees/2c37b1d7/src/stages/explore.js +43 -0
  170. package/.worktrees/2c37b1d7/src/stages/index.js +29 -0
  171. package/.worktrees/2c37b1d7/src/stages/knowledge.js +514 -0
  172. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +1398 -0
  173. package/.worktrees/2c37b1d7/src/stages/plan.js +655 -0
  174. package/.worktrees/2c37b1d7/src/stages/quick.js +167 -0
  175. package/.worktrees/2c37b1d7/src/stages/scan.js +608 -0
  176. package/.worktrees/2c37b1d7/src/stages/status.js +64 -0
  177. package/.worktrees/2c37b1d7/src/stages/verify.js +246 -0
  178. package/.worktrees/2c37b1d7/src/sync.js +1470 -0
  179. package/.worktrees/2c37b1d7/src/task-review.js +1498 -0
  180. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +21 -0
  181. package/.worktrees/2c37b1d7/src/taskcard.js +250 -0
  182. package/.worktrees/2c37b1d7/src/verify-postcheck.js +1718 -0
  183. package/.worktrees/2c37b1d7/src/verify-probes.js +327 -0
  184. package/.worktrees/2c37b1d7/src/version.js +19 -0
  185. package/.worktrees/2c37b1d7/src/workflow.js +600 -0
  186. package/.worktrees/2c37b1d7/src/workspace.js +125 -0
  187. package/.worktrees/2c37b1d7/src/worktree-apply.js +1611 -0
  188. package/.worktrees/2c37b1d7/src/worktree-deps.js +668 -0
  189. package/.worktrees/2c37b1d7/src/worktree.js +1849 -0
  190. package/.worktrees/2c37b1d7/templates/claude-instruction.md +23 -0
  191. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +29 -0
  192. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +12 -0
  193. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +32 -0
  194. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +79 -0
  195. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +132 -0
  196. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  197. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  198. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  199. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  200. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  201. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  202. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  203. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  204. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +57 -0
  205. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +177 -0
  206. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  207. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  208. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  209. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  210. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  211. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +64 -0
  212. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +54 -0
  213. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  214. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  215. package/.worktrees/542c4415/.gitattributes +2 -0
  216. package/.worktrees/542c4415/.husky/pre-push +20 -0
  217. package/.worktrees/542c4415/README.md +203 -0
  218. package/.worktrees/542c4415/SKILL.md +91 -0
  219. package/.worktrees/542c4415/architecture-analysis.md +448 -0
  220. package/.worktrees/542c4415/bin/sillyspec.js +2 -0
  221. package/.worktrees/542c4415/eval/README.md +86 -0
  222. package/.worktrees/542c4415/eval/eval.config.json +28 -0
  223. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +63 -0
  224. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +27 -0
  225. package/.worktrees/542c4415/eval/lib/config.mjs +82 -0
  226. package/.worktrees/542c4415/eval/lib/db.mjs +76 -0
  227. package/.worktrees/542c4415/eval/lib/report.mjs +120 -0
  228. package/.worktrees/542c4415/eval/lib/runner.mjs +157 -0
  229. package/.worktrees/542c4415/eval/lib/tasks.mjs +73 -0
  230. package/.worktrees/542c4415/eval/lib/util.mjs +107 -0
  231. package/.worktrees/542c4415/eval/lib/workdir.mjs +30 -0
  232. package/.worktrees/542c4415/eval/run.mjs +83 -0
  233. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +6 -0
  234. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  235. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +6 -0
  236. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +28 -0
  237. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +6 -0
  238. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  239. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  240. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +6 -0
  241. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +31 -0
  242. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  243. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +6 -0
  244. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  245. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +6 -0
  246. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +38 -0
  247. package/.worktrees/542c4415/logo.jpg +0 -0
  248. package/.worktrees/542c4415/package-lock.json +977 -0
  249. package/.worktrees/542c4415/package.json +41 -0
  250. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  251. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  252. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  253. package/.worktrees/542c4415/packages/dashboard/dist/index.html +16 -0
  254. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  255. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +836 -0
  256. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +256 -0
  257. package/.worktrees/542c4415/packages/dashboard/package.json +25 -0
  258. package/.worktrees/542c4415/packages/dashboard/server/executor.js +95 -0
  259. package/.worktrees/542c4415/packages/dashboard/server/index.js +679 -0
  260. package/.worktrees/542c4415/packages/dashboard/server/parser.js +526 -0
  261. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +357 -0
  262. package/.worktrees/542c4415/src/agent-session-log.js +803 -0
  263. package/.worktrees/542c4415/src/change-list.js +290 -0
  264. package/.worktrees/542c4415/src/change-risk-profile.js +339 -0
  265. package/.worktrees/542c4415/src/check-primitives.js +65 -0
  266. package/.worktrees/542c4415/src/classify-change.js +109 -0
  267. package/.worktrees/542c4415/src/commit-suggest.js +202 -0
  268. package/.worktrees/542c4415/src/config-cat.js +88 -0
  269. package/.worktrees/542c4415/src/config-schema.js +328 -0
  270. package/.worktrees/542c4415/src/constants.js +97 -0
  271. package/.worktrees/542c4415/src/contract-matrix.js +533 -0
  272. package/.worktrees/542c4415/src/datetime.js +20 -0
  273. package/.worktrees/542c4415/src/db-engine.js +55 -0
  274. package/.worktrees/542c4415/src/db.js +381 -0
  275. package/.worktrees/542c4415/src/decision-distill.js +517 -0
  276. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +155 -0
  277. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +245 -0
  278. package/.worktrees/542c4415/src/dispatch/probe.js +246 -0
  279. package/.worktrees/542c4415/src/dispatch/strategy.js +121 -0
  280. package/.worktrees/542c4415/src/docs-check.js +825 -0
  281. package/.worktrees/542c4415/src/docs-debt.js +393 -0
  282. package/.worktrees/542c4415/src/docs-gate.js +107 -0
  283. package/.worktrees/542c4415/src/doctor-diagnostics.js +1099 -0
  284. package/.worktrees/542c4415/src/endpoint-extractor.js +409 -0
  285. package/.worktrees/542c4415/src/foreign-declared.js +155 -0
  286. package/.worktrees/542c4415/src/fs-atomic.js +73 -0
  287. package/.worktrees/542c4415/src/git-helper.js +150 -0
  288. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +130 -0
  289. package/.worktrees/542c4415/src/hooks/worktree-guard.js +892 -0
  290. package/.worktrees/542c4415/src/index.js +2854 -0
  291. package/.worktrees/542c4415/src/init.js +626 -0
  292. package/.worktrees/542c4415/src/knowledge-match.js +231 -0
  293. package/.worktrees/542c4415/src/local-detect.js +128 -0
  294. package/.worktrees/542c4415/src/local-register.js +104 -0
  295. package/.worktrees/542c4415/src/machine-interface.js +543 -0
  296. package/.worktrees/542c4415/src/migrate.js +127 -0
  297. package/.worktrees/542c4415/src/module-impact.js +166 -0
  298. package/.worktrees/542c4415/src/module-resolve.js +222 -0
  299. package/.worktrees/542c4415/src/modules.js +580 -0
  300. package/.worktrees/542c4415/src/plan-adopt-waves.js +126 -0
  301. package/.worktrees/542c4415/src/progress/change-registry.js +336 -0
  302. package/.worktrees/542c4415/src/progress/consistency-doctor.js +355 -0
  303. package/.worktrees/542c4415/src/progress/shared.js +36 -0
  304. package/.worktrees/542c4415/src/progress/stage-machine.js +594 -0
  305. package/.worktrees/542c4415/src/progress/step-store.js +265 -0
  306. package/.worktrees/542c4415/src/progress.js +1304 -0
  307. package/.worktrees/542c4415/src/quick-recommend.js +115 -0
  308. package/.worktrees/542c4415/src/quicklog.js +883 -0
  309. package/.worktrees/542c4415/src/review-tier.js +77 -0
  310. package/.worktrees/542c4415/src/run/command.js +1641 -0
  311. package/.worktrees/542c4415/src/run/complete-handlers.js +1552 -0
  312. package/.worktrees/542c4415/src/run/complete.js +1259 -0
  313. package/.worktrees/542c4415/src/run/concurrent-detect.js +156 -0
  314. package/.worktrees/542c4415/src/run/gates.js +1111 -0
  315. package/.worktrees/542c4415/src/run/multi-repo-context.js +208 -0
  316. package/.worktrees/542c4415/src/run/next.js +128 -0
  317. package/.worktrees/542c4415/src/run/prompt.js +843 -0
  318. package/.worktrees/542c4415/src/run/quick-audit.js +186 -0
  319. package/.worktrees/542c4415/src/run/scan-profile.js +269 -0
  320. package/.worktrees/542c4415/src/run/shared.js +1562 -0
  321. package/.worktrees/542c4415/src/run/stage.js +587 -0
  322. package/.worktrees/542c4415/src/run.js +23 -0
  323. package/.worktrees/542c4415/src/scan-diff.js +388 -0
  324. package/.worktrees/542c4415/src/scan-postcheck.js +524 -0
  325. package/.worktrees/542c4415/src/scan-staleness.js +95 -0
  326. package/.worktrees/542c4415/src/setup.js +414 -0
  327. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +597 -0
  328. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +62 -0
  329. package/.worktrees/542c4415/src/spec-dir-typo.js +50 -0
  330. package/.worktrees/542c4415/src/spec-sync.js +358 -0
  331. package/.worktrees/542c4415/src/stage-contract-engine.js +171 -0
  332. package/.worktrees/542c4415/src/stage-contract-spec.js +551 -0
  333. package/.worktrees/542c4415/src/stage-contract.js +948 -0
  334. package/.worktrees/542c4415/src/stage-review.js +597 -0
  335. package/.worktrees/542c4415/src/stages/archive.js +199 -0
  336. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +285 -0
  337. package/.worktrees/542c4415/src/stages/brainstorm.js +624 -0
  338. package/.worktrees/542c4415/src/stages/cmd-existence.js +145 -0
  339. package/.worktrees/542c4415/src/stages/doctor.js +540 -0
  340. package/.worktrees/542c4415/src/stages/execute.js +1277 -0
  341. package/.worktrees/542c4415/src/stages/explore.js +43 -0
  342. package/.worktrees/542c4415/src/stages/index.js +29 -0
  343. package/.worktrees/542c4415/src/stages/knowledge.js +514 -0
  344. package/.worktrees/542c4415/src/stages/plan-postcheck.js +1398 -0
  345. package/.worktrees/542c4415/src/stages/plan.js +655 -0
  346. package/.worktrees/542c4415/src/stages/quick.js +167 -0
  347. package/.worktrees/542c4415/src/stages/scan.js +608 -0
  348. package/.worktrees/542c4415/src/stages/status.js +64 -0
  349. package/.worktrees/542c4415/src/stages/verify.js +246 -0
  350. package/.worktrees/542c4415/src/sync.js +1470 -0
  351. package/.worktrees/542c4415/src/task-review.js +1498 -0
  352. package/.worktrees/542c4415/src/taskcard-placeholders.js +21 -0
  353. package/.worktrees/542c4415/src/taskcard.js +250 -0
  354. package/.worktrees/542c4415/src/verify-postcheck.js +1718 -0
  355. package/.worktrees/542c4415/src/verify-probes.js +327 -0
  356. package/.worktrees/542c4415/src/version.js +19 -0
  357. package/.worktrees/542c4415/src/workflow.js +600 -0
  358. package/.worktrees/542c4415/src/workspace.js +125 -0
  359. package/.worktrees/542c4415/src/worktree-apply.js +1611 -0
  360. package/.worktrees/542c4415/src/worktree-deps.js +668 -0
  361. package/.worktrees/542c4415/src/worktree.js +1849 -0
  362. package/.worktrees/542c4415/templates/claude-instruction.md +23 -0
  363. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +29 -0
  364. package/.worktrees/542c4415/templates/prompts/testcase-design.md +12 -0
  365. package/.worktrees/542c4415/templates/prompts/verify-probes.md +32 -0
  366. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +79 -0
  367. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +132 -0
  368. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  369. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  370. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  371. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  372. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  373. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  374. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  375. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  376. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +57 -0
  377. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +177 -0
  378. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  379. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  380. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  381. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  382. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  383. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  384. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +64 -0
  385. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +54 -0
  386. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  387. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  388. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +6 -0
  389. package/.worktrees/8d2d0392/.gitattributes +2 -0
  390. package/.worktrees/8d2d0392/.husky/pre-push +20 -0
  391. package/.worktrees/8d2d0392/README.md +203 -0
  392. package/.worktrees/8d2d0392/SKILL.md +91 -0
  393. package/.worktrees/8d2d0392/architecture-analysis.md +448 -0
  394. package/.worktrees/8d2d0392/bin/sillyspec.js +2 -0
  395. package/.worktrees/8d2d0392/eval/README.md +86 -0
  396. package/.worktrees/8d2d0392/eval/eval.config.json +28 -0
  397. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +63 -0
  398. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +27 -0
  399. package/.worktrees/8d2d0392/eval/lib/config.mjs +82 -0
  400. package/.worktrees/8d2d0392/eval/lib/db.mjs +76 -0
  401. package/.worktrees/8d2d0392/eval/lib/report.mjs +120 -0
  402. package/.worktrees/8d2d0392/eval/lib/runner.mjs +157 -0
  403. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +73 -0
  404. package/.worktrees/8d2d0392/eval/lib/util.mjs +107 -0
  405. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +30 -0
  406. package/.worktrees/8d2d0392/eval/run.mjs +83 -0
  407. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +6 -0
  408. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  409. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +6 -0
  410. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +28 -0
  411. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +6 -0
  412. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  413. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  414. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +6 -0
  415. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +31 -0
  416. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  417. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +6 -0
  418. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  419. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +6 -0
  420. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +38 -0
  421. package/.worktrees/8d2d0392/logo.jpg +0 -0
  422. package/.worktrees/8d2d0392/package-lock.json +977 -0
  423. package/.worktrees/8d2d0392/package.json +41 -0
  424. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  425. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  426. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  427. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +16 -0
  428. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  429. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +836 -0
  430. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +256 -0
  431. package/.worktrees/8d2d0392/packages/dashboard/package.json +25 -0
  432. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +95 -0
  433. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +679 -0
  434. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +526 -0
  435. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +357 -0
  436. package/.worktrees/8d2d0392/src/agent-session-log.js +803 -0
  437. package/.worktrees/8d2d0392/src/change-list.js +290 -0
  438. package/.worktrees/8d2d0392/src/change-risk-profile.js +339 -0
  439. package/.worktrees/8d2d0392/src/check-primitives.js +65 -0
  440. package/.worktrees/8d2d0392/src/classify-change.js +109 -0
  441. package/.worktrees/8d2d0392/src/commit-suggest.js +202 -0
  442. package/.worktrees/8d2d0392/src/config-cat.js +88 -0
  443. package/.worktrees/8d2d0392/src/config-schema.js +328 -0
  444. package/.worktrees/8d2d0392/src/constants.js +97 -0
  445. package/.worktrees/8d2d0392/src/contract-matrix.js +533 -0
  446. package/.worktrees/8d2d0392/src/datetime.js +20 -0
  447. package/.worktrees/8d2d0392/src/db-engine.js +55 -0
  448. package/.worktrees/8d2d0392/src/db.js +381 -0
  449. package/.worktrees/8d2d0392/src/decision-distill.js +517 -0
  450. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +155 -0
  451. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +245 -0
  452. package/.worktrees/8d2d0392/src/dispatch/probe.js +246 -0
  453. package/.worktrees/8d2d0392/src/dispatch/strategy.js +121 -0
  454. package/.worktrees/8d2d0392/src/docs-check.js +825 -0
  455. package/.worktrees/8d2d0392/src/docs-debt.js +393 -0
  456. package/.worktrees/8d2d0392/src/docs-gate.js +107 -0
  457. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +1099 -0
  458. package/.worktrees/8d2d0392/src/endpoint-extractor.js +409 -0
  459. package/.worktrees/8d2d0392/src/foreign-declared.js +78 -0
  460. package/.worktrees/8d2d0392/src/fs-atomic.js +73 -0
  461. package/.worktrees/8d2d0392/src/git-helper.js +150 -0
  462. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +130 -0
  463. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +892 -0
  464. package/.worktrees/8d2d0392/src/index.js +2854 -0
  465. package/.worktrees/8d2d0392/src/init.js +626 -0
  466. package/.worktrees/8d2d0392/src/knowledge-match.js +231 -0
  467. package/.worktrees/8d2d0392/src/local-detect.js +128 -0
  468. package/.worktrees/8d2d0392/src/local-register.js +104 -0
  469. package/.worktrees/8d2d0392/src/machine-interface.js +543 -0
  470. package/.worktrees/8d2d0392/src/migrate.js +127 -0
  471. package/.worktrees/8d2d0392/src/module-impact.js +166 -0
  472. package/.worktrees/8d2d0392/src/module-resolve.js +222 -0
  473. package/.worktrees/8d2d0392/src/modules.js +580 -0
  474. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +126 -0
  475. package/.worktrees/8d2d0392/src/progress/change-registry.js +336 -0
  476. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +355 -0
  477. package/.worktrees/8d2d0392/src/progress/shared.js +36 -0
  478. package/.worktrees/8d2d0392/src/progress/stage-machine.js +594 -0
  479. package/.worktrees/8d2d0392/src/progress/step-store.js +265 -0
  480. package/.worktrees/8d2d0392/src/progress.js +1304 -0
  481. package/.worktrees/8d2d0392/src/quick-recommend.js +115 -0
  482. package/.worktrees/8d2d0392/src/quicklog.js +883 -0
  483. package/.worktrees/8d2d0392/src/review-tier.js +77 -0
  484. package/.worktrees/8d2d0392/src/run/command.js +1641 -0
  485. package/.worktrees/8d2d0392/src/run/complete-handlers.js +1552 -0
  486. package/.worktrees/8d2d0392/src/run/complete.js +1259 -0
  487. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +156 -0
  488. package/.worktrees/8d2d0392/src/run/gates.js +1094 -0
  489. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +208 -0
  490. package/.worktrees/8d2d0392/src/run/next.js +128 -0
  491. package/.worktrees/8d2d0392/src/run/prompt.js +843 -0
  492. package/.worktrees/8d2d0392/src/run/quick-audit.js +186 -0
  493. package/.worktrees/8d2d0392/src/run/scan-profile.js +269 -0
  494. package/.worktrees/8d2d0392/src/run/shared.js +1562 -0
  495. package/.worktrees/8d2d0392/src/run/stage.js +587 -0
  496. package/.worktrees/8d2d0392/src/run.js +23 -0
  497. package/.worktrees/8d2d0392/src/scan-diff.js +388 -0
  498. package/.worktrees/8d2d0392/src/scan-postcheck.js +524 -0
  499. package/.worktrees/8d2d0392/src/scan-staleness.js +95 -0
  500. package/.worktrees/8d2d0392/src/setup.js +414 -0
  501. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +597 -0
  502. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +62 -0
  503. package/.worktrees/8d2d0392/src/spec-dir-typo.js +50 -0
  504. package/.worktrees/8d2d0392/src/spec-sync.js +358 -0
  505. package/.worktrees/8d2d0392/src/stage-contract-engine.js +171 -0
  506. package/.worktrees/8d2d0392/src/stage-contract-spec.js +551 -0
  507. package/.worktrees/8d2d0392/src/stage-contract.js +948 -0
  508. package/.worktrees/8d2d0392/src/stage-review.js +597 -0
  509. package/.worktrees/8d2d0392/src/stages/archive.js +199 -0
  510. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +285 -0
  511. package/.worktrees/8d2d0392/src/stages/brainstorm.js +624 -0
  512. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +145 -0
  513. package/.worktrees/8d2d0392/src/stages/doctor.js +540 -0
  514. package/.worktrees/8d2d0392/src/stages/execute.js +1277 -0
  515. package/.worktrees/8d2d0392/src/stages/explore.js +43 -0
  516. package/.worktrees/8d2d0392/src/stages/index.js +29 -0
  517. package/.worktrees/8d2d0392/src/stages/knowledge.js +514 -0
  518. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +1398 -0
  519. package/.worktrees/8d2d0392/src/stages/plan.js +651 -0
  520. package/.worktrees/8d2d0392/src/stages/quick.js +167 -0
  521. package/.worktrees/8d2d0392/src/stages/scan.js +608 -0
  522. package/.worktrees/8d2d0392/src/stages/status.js +64 -0
  523. package/.worktrees/8d2d0392/src/stages/verify.js +246 -0
  524. package/.worktrees/8d2d0392/src/sync.js +1470 -0
  525. package/.worktrees/8d2d0392/src/task-review.js +1498 -0
  526. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +21 -0
  527. package/.worktrees/8d2d0392/src/taskcard.js +217 -0
  528. package/.worktrees/8d2d0392/src/verify-postcheck.js +1718 -0
  529. package/.worktrees/8d2d0392/src/verify-probes.js +327 -0
  530. package/.worktrees/8d2d0392/src/version.js +19 -0
  531. package/.worktrees/8d2d0392/src/workflow.js +600 -0
  532. package/.worktrees/8d2d0392/src/workspace.js +125 -0
  533. package/.worktrees/8d2d0392/src/worktree-apply.js +1611 -0
  534. package/.worktrees/8d2d0392/src/worktree-deps.js +576 -0
  535. package/.worktrees/8d2d0392/src/worktree.js +1838 -0
  536. package/.worktrees/8d2d0392/templates/claude-instruction.md +23 -0
  537. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +29 -0
  538. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +12 -0
  539. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +32 -0
  540. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +79 -0
  541. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +132 -0
  542. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  543. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  544. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  545. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  546. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  547. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  548. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  549. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  550. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +57 -0
  551. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +177 -0
  552. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  553. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  554. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  555. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  556. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  557. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +64 -0
  558. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +54 -0
  559. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  560. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  561. package/.worktrees/c1eae35e/.gitattributes +2 -0
  562. package/.worktrees/c1eae35e/.husky/pre-push +20 -0
  563. package/.worktrees/c1eae35e/README.md +203 -0
  564. package/.worktrees/c1eae35e/SKILL.md +91 -0
  565. package/.worktrees/c1eae35e/architecture-analysis.md +448 -0
  566. package/.worktrees/c1eae35e/bin/sillyspec.js +2 -0
  567. package/.worktrees/c1eae35e/eval/README.md +86 -0
  568. package/.worktrees/c1eae35e/eval/eval.config.json +28 -0
  569. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +63 -0
  570. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +27 -0
  571. package/.worktrees/c1eae35e/eval/lib/config.mjs +82 -0
  572. package/.worktrees/c1eae35e/eval/lib/db.mjs +76 -0
  573. package/.worktrees/c1eae35e/eval/lib/report.mjs +120 -0
  574. package/.worktrees/c1eae35e/eval/lib/runner.mjs +157 -0
  575. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +73 -0
  576. package/.worktrees/c1eae35e/eval/lib/util.mjs +107 -0
  577. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +30 -0
  578. package/.worktrees/c1eae35e/eval/run.mjs +83 -0
  579. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +6 -0
  580. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  581. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +6 -0
  582. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +28 -0
  583. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +6 -0
  584. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  585. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  586. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +6 -0
  587. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +31 -0
  588. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  589. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +6 -0
  590. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  591. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +6 -0
  592. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +38 -0
  593. package/.worktrees/c1eae35e/logo.jpg +0 -0
  594. package/.worktrees/c1eae35e/package-lock.json +977 -0
  595. package/.worktrees/c1eae35e/package.json +41 -0
  596. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  597. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  598. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  599. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +16 -0
  600. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  601. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +836 -0
  602. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +256 -0
  603. package/.worktrees/c1eae35e/packages/dashboard/package.json +25 -0
  604. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +95 -0
  605. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +679 -0
  606. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +526 -0
  607. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +357 -0
  608. package/.worktrees/c1eae35e/src/agent-session-log.js +803 -0
  609. package/.worktrees/c1eae35e/src/change-list.js +290 -0
  610. package/.worktrees/c1eae35e/src/change-risk-profile.js +339 -0
  611. package/.worktrees/c1eae35e/src/check-primitives.js +65 -0
  612. package/.worktrees/c1eae35e/src/classify-change.js +109 -0
  613. package/.worktrees/c1eae35e/src/commit-suggest.js +202 -0
  614. package/.worktrees/c1eae35e/src/config-cat.js +88 -0
  615. package/.worktrees/c1eae35e/src/config-schema.js +328 -0
  616. package/.worktrees/c1eae35e/src/constants.js +97 -0
  617. package/.worktrees/c1eae35e/src/contract-matrix.js +533 -0
  618. package/.worktrees/c1eae35e/src/datetime.js +20 -0
  619. package/.worktrees/c1eae35e/src/db-engine.js +55 -0
  620. package/.worktrees/c1eae35e/src/db.js +381 -0
  621. package/.worktrees/c1eae35e/src/decision-distill.js +517 -0
  622. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +155 -0
  623. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +245 -0
  624. package/.worktrees/c1eae35e/src/dispatch/probe.js +246 -0
  625. package/.worktrees/c1eae35e/src/dispatch/strategy.js +121 -0
  626. package/.worktrees/c1eae35e/src/docs-check.js +825 -0
  627. package/.worktrees/c1eae35e/src/docs-debt.js +393 -0
  628. package/.worktrees/c1eae35e/src/docs-gate.js +107 -0
  629. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +1099 -0
  630. package/.worktrees/c1eae35e/src/endpoint-extractor.js +409 -0
  631. package/.worktrees/c1eae35e/src/foreign-declared.js +155 -0
  632. package/.worktrees/c1eae35e/src/fs-atomic.js +73 -0
  633. package/.worktrees/c1eae35e/src/git-helper.js +150 -0
  634. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +130 -0
  635. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +892 -0
  636. package/.worktrees/c1eae35e/src/index.js +2854 -0
  637. package/.worktrees/c1eae35e/src/init.js +626 -0
  638. package/.worktrees/c1eae35e/src/knowledge-match.js +231 -0
  639. package/.worktrees/c1eae35e/src/local-detect.js +128 -0
  640. package/.worktrees/c1eae35e/src/local-register.js +104 -0
  641. package/.worktrees/c1eae35e/src/machine-interface.js +543 -0
  642. package/.worktrees/c1eae35e/src/migrate.js +127 -0
  643. package/.worktrees/c1eae35e/src/module-impact.js +166 -0
  644. package/.worktrees/c1eae35e/src/module-resolve.js +222 -0
  645. package/.worktrees/c1eae35e/src/modules.js +580 -0
  646. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +126 -0
  647. package/.worktrees/c1eae35e/src/progress/change-registry.js +336 -0
  648. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +355 -0
  649. package/.worktrees/c1eae35e/src/progress/shared.js +36 -0
  650. package/.worktrees/c1eae35e/src/progress/stage-machine.js +594 -0
  651. package/.worktrees/c1eae35e/src/progress/step-store.js +265 -0
  652. package/.worktrees/c1eae35e/src/progress.js +1304 -0
  653. package/.worktrees/c1eae35e/src/quick-recommend.js +115 -0
  654. package/.worktrees/c1eae35e/src/quicklog.js +883 -0
  655. package/.worktrees/c1eae35e/src/review-tier.js +77 -0
  656. package/.worktrees/c1eae35e/src/run/command.js +1641 -0
  657. package/.worktrees/c1eae35e/src/run/complete-handlers.js +1552 -0
  658. package/.worktrees/c1eae35e/src/run/complete.js +1259 -0
  659. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +156 -0
  660. package/.worktrees/c1eae35e/src/run/gates.js +1111 -0
  661. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +208 -0
  662. package/.worktrees/c1eae35e/src/run/next.js +128 -0
  663. package/.worktrees/c1eae35e/src/run/prompt.js +843 -0
  664. package/.worktrees/c1eae35e/src/run/quick-audit.js +186 -0
  665. package/.worktrees/c1eae35e/src/run/scan-profile.js +269 -0
  666. package/.worktrees/c1eae35e/src/run/shared.js +1562 -0
  667. package/.worktrees/c1eae35e/src/run/stage.js +587 -0
  668. package/.worktrees/c1eae35e/src/run.js +23 -0
  669. package/.worktrees/c1eae35e/src/scan-diff.js +388 -0
  670. package/.worktrees/c1eae35e/src/scan-postcheck.js +524 -0
  671. package/.worktrees/c1eae35e/src/scan-staleness.js +95 -0
  672. package/.worktrees/c1eae35e/src/setup.js +414 -0
  673. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +597 -0
  674. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +62 -0
  675. package/.worktrees/c1eae35e/src/spec-dir-typo.js +50 -0
  676. package/.worktrees/c1eae35e/src/spec-sync.js +358 -0
  677. package/.worktrees/c1eae35e/src/stage-contract-engine.js +171 -0
  678. package/.worktrees/c1eae35e/src/stage-contract-spec.js +551 -0
  679. package/.worktrees/c1eae35e/src/stage-contract.js +948 -0
  680. package/.worktrees/c1eae35e/src/stage-review.js +597 -0
  681. package/.worktrees/c1eae35e/src/stages/archive.js +199 -0
  682. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +285 -0
  683. package/.worktrees/c1eae35e/src/stages/brainstorm.js +624 -0
  684. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +145 -0
  685. package/.worktrees/c1eae35e/src/stages/doctor.js +540 -0
  686. package/.worktrees/c1eae35e/src/stages/execute.js +1277 -0
  687. package/.worktrees/c1eae35e/src/stages/explore.js +43 -0
  688. package/.worktrees/c1eae35e/src/stages/index.js +29 -0
  689. package/.worktrees/c1eae35e/src/stages/knowledge.js +514 -0
  690. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +1398 -0
  691. package/.worktrees/c1eae35e/src/stages/plan.js +655 -0
  692. package/.worktrees/c1eae35e/src/stages/quick.js +167 -0
  693. package/.worktrees/c1eae35e/src/stages/scan.js +608 -0
  694. package/.worktrees/c1eae35e/src/stages/status.js +64 -0
  695. package/.worktrees/c1eae35e/src/stages/verify.js +246 -0
  696. package/.worktrees/c1eae35e/src/sync.js +1470 -0
  697. package/.worktrees/c1eae35e/src/task-review.js +1498 -0
  698. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +21 -0
  699. package/.worktrees/c1eae35e/src/taskcard.js +250 -0
  700. package/.worktrees/c1eae35e/src/verify-postcheck.js +1718 -0
  701. package/.worktrees/c1eae35e/src/verify-probes.js +327 -0
  702. package/.worktrees/c1eae35e/src/version.js +19 -0
  703. package/.worktrees/c1eae35e/src/workflow.js +600 -0
  704. package/.worktrees/c1eae35e/src/workspace.js +125 -0
  705. package/.worktrees/c1eae35e/src/worktree-apply.js +1611 -0
  706. package/.worktrees/c1eae35e/src/worktree-deps.js +668 -0
  707. package/.worktrees/c1eae35e/src/worktree.js +1849 -0
  708. package/.worktrees/c1eae35e/templates/claude-instruction.md +23 -0
  709. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +29 -0
  710. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +12 -0
  711. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +32 -0
  712. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +79 -0
  713. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +132 -0
  714. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  715. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  716. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  717. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  718. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  719. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  720. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  721. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  722. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +57 -0
  723. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +177 -0
  724. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  725. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  726. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  727. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  728. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  729. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  730. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +64 -0
  731. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +54 -0
  732. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  733. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  734. package/.worktrees/dafc71ad/.gitattributes +2 -0
  735. package/.worktrees/dafc71ad/.husky/pre-push +20 -0
  736. package/.worktrees/dafc71ad/README.md +203 -0
  737. package/.worktrees/dafc71ad/SKILL.md +91 -0
  738. package/.worktrees/dafc71ad/analysis.md +366 -0
  739. package/.worktrees/dafc71ad/architecture-analysis.md +448 -0
  740. package/.worktrees/dafc71ad/bin/sillyspec.js +2 -0
  741. package/.worktrees/dafc71ad/eval/README.md +86 -0
  742. package/.worktrees/dafc71ad/eval/eval.config.json +28 -0
  743. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +63 -0
  744. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +27 -0
  745. package/.worktrees/dafc71ad/eval/lib/config.mjs +82 -0
  746. package/.worktrees/dafc71ad/eval/lib/db.mjs +76 -0
  747. package/.worktrees/dafc71ad/eval/lib/report.mjs +120 -0
  748. package/.worktrees/dafc71ad/eval/lib/runner.mjs +157 -0
  749. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +73 -0
  750. package/.worktrees/dafc71ad/eval/lib/util.mjs +107 -0
  751. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +30 -0
  752. package/.worktrees/dafc71ad/eval/run.mjs +83 -0
  753. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +6 -0
  754. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  755. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +6 -0
  756. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +28 -0
  757. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +6 -0
  758. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  759. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  760. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +6 -0
  761. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +31 -0
  762. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  763. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +6 -0
  764. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  765. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +6 -0
  766. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +38 -0
  767. package/.worktrees/dafc71ad/logo.jpg +0 -0
  768. package/.worktrees/dafc71ad/package-lock.json +977 -0
  769. package/.worktrees/dafc71ad/package.json +41 -0
  770. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  771. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  772. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  773. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +16 -0
  774. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  775. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +836 -0
  776. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +256 -0
  777. package/.worktrees/dafc71ad/packages/dashboard/package.json +25 -0
  778. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +95 -0
  779. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +679 -0
  780. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +526 -0
  781. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +357 -0
  782. package/.worktrees/dafc71ad/src/agent-session-log.js +803 -0
  783. package/.worktrees/dafc71ad/src/change-list.js +290 -0
  784. package/.worktrees/dafc71ad/src/change-risk-profile.js +339 -0
  785. package/.worktrees/dafc71ad/src/check-primitives.js +65 -0
  786. package/.worktrees/dafc71ad/src/classify-change.js +109 -0
  787. package/.worktrees/dafc71ad/src/commit-suggest.js +202 -0
  788. package/.worktrees/dafc71ad/src/config-cat.js +88 -0
  789. package/.worktrees/dafc71ad/src/config-schema.js +328 -0
  790. package/.worktrees/dafc71ad/src/constants.js +97 -0
  791. package/.worktrees/dafc71ad/src/contract-matrix.js +533 -0
  792. package/.worktrees/dafc71ad/src/datetime.js +20 -0
  793. package/.worktrees/dafc71ad/src/db-engine.js +55 -0
  794. package/.worktrees/dafc71ad/src/db.js +381 -0
  795. package/.worktrees/dafc71ad/src/decision-distill.js +517 -0
  796. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +155 -0
  797. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +245 -0
  798. package/.worktrees/dafc71ad/src/dispatch/probe.js +246 -0
  799. package/.worktrees/dafc71ad/src/dispatch/strategy.js +121 -0
  800. package/.worktrees/dafc71ad/src/docs-check.js +825 -0
  801. package/.worktrees/dafc71ad/src/docs-debt.js +393 -0
  802. package/.worktrees/dafc71ad/src/docs-gate.js +107 -0
  803. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +1099 -0
  804. package/.worktrees/dafc71ad/src/endpoint-extractor.js +409 -0
  805. package/.worktrees/dafc71ad/src/foreign-declared.js +155 -0
  806. package/.worktrees/dafc71ad/src/fs-atomic.js +73 -0
  807. package/.worktrees/dafc71ad/src/git-helper.js +150 -0
  808. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +130 -0
  809. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +892 -0
  810. package/.worktrees/dafc71ad/src/index.js +2854 -0
  811. package/.worktrees/dafc71ad/src/init.js +626 -0
  812. package/.worktrees/dafc71ad/src/knowledge-match.js +231 -0
  813. package/.worktrees/dafc71ad/src/local-detect.js +128 -0
  814. package/.worktrees/dafc71ad/src/local-register.js +104 -0
  815. package/.worktrees/dafc71ad/src/machine-interface.js +543 -0
  816. package/.worktrees/dafc71ad/src/migrate.js +127 -0
  817. package/.worktrees/dafc71ad/src/module-impact.js +166 -0
  818. package/.worktrees/dafc71ad/src/module-resolve.js +222 -0
  819. package/.worktrees/dafc71ad/src/modules.js +580 -0
  820. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +126 -0
  821. package/.worktrees/dafc71ad/src/progress/change-registry.js +336 -0
  822. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +355 -0
  823. package/.worktrees/dafc71ad/src/progress/shared.js +36 -0
  824. package/.worktrees/dafc71ad/src/progress/stage-machine.js +594 -0
  825. package/.worktrees/dafc71ad/src/progress/step-store.js +265 -0
  826. package/.worktrees/dafc71ad/src/progress.js +1304 -0
  827. package/.worktrees/dafc71ad/src/quick-recommend.js +115 -0
  828. package/.worktrees/dafc71ad/src/quicklog.js +883 -0
  829. package/.worktrees/dafc71ad/src/review-tier.js +77 -0
  830. package/.worktrees/dafc71ad/src/run/command.js +1641 -0
  831. package/.worktrees/dafc71ad/src/run/complete-handlers.js +1552 -0
  832. package/.worktrees/dafc71ad/src/run/complete.js +1259 -0
  833. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +156 -0
  834. package/.worktrees/dafc71ad/src/run/gates.js +1111 -0
  835. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +208 -0
  836. package/.worktrees/dafc71ad/src/run/next.js +128 -0
  837. package/.worktrees/dafc71ad/src/run/prompt.js +843 -0
  838. package/.worktrees/dafc71ad/src/run/quick-audit.js +186 -0
  839. package/.worktrees/dafc71ad/src/run/scan-profile.js +269 -0
  840. package/.worktrees/dafc71ad/src/run/shared.js +1562 -0
  841. package/.worktrees/dafc71ad/src/run/stage.js +587 -0
  842. package/.worktrees/dafc71ad/src/run.js +23 -0
  843. package/.worktrees/dafc71ad/src/scan-diff.js +388 -0
  844. package/.worktrees/dafc71ad/src/scan-postcheck.js +524 -0
  845. package/.worktrees/dafc71ad/src/scan-staleness.js +95 -0
  846. package/.worktrees/dafc71ad/src/setup.js +414 -0
  847. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +597 -0
  848. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +62 -0
  849. package/.worktrees/dafc71ad/src/spec-dir-typo.js +50 -0
  850. package/.worktrees/dafc71ad/src/spec-sync.js +358 -0
  851. package/.worktrees/dafc71ad/src/stage-contract-engine.js +171 -0
  852. package/.worktrees/dafc71ad/src/stage-contract-spec.js +551 -0
  853. package/.worktrees/dafc71ad/src/stage-contract.js +948 -0
  854. package/.worktrees/dafc71ad/src/stage-review.js +597 -0
  855. package/.worktrees/dafc71ad/src/stages/archive.js +199 -0
  856. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +285 -0
  857. package/.worktrees/dafc71ad/src/stages/brainstorm.js +624 -0
  858. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +145 -0
  859. package/.worktrees/dafc71ad/src/stages/doctor.js +540 -0
  860. package/.worktrees/dafc71ad/src/stages/execute.js +1277 -0
  861. package/.worktrees/dafc71ad/src/stages/explore.js +43 -0
  862. package/.worktrees/dafc71ad/src/stages/index.js +29 -0
  863. package/.worktrees/dafc71ad/src/stages/knowledge.js +514 -0
  864. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +1398 -0
  865. package/.worktrees/dafc71ad/src/stages/plan.js +655 -0
  866. package/.worktrees/dafc71ad/src/stages/quick.js +167 -0
  867. package/.worktrees/dafc71ad/src/stages/scan.js +608 -0
  868. package/.worktrees/dafc71ad/src/stages/status.js +64 -0
  869. package/.worktrees/dafc71ad/src/stages/verify.js +246 -0
  870. package/.worktrees/dafc71ad/src/sync.js +1470 -0
  871. package/.worktrees/dafc71ad/src/task-review.js +1498 -0
  872. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +21 -0
  873. package/.worktrees/dafc71ad/src/taskcard.js +250 -0
  874. package/.worktrees/dafc71ad/src/verify-postcheck.js +1718 -0
  875. package/.worktrees/dafc71ad/src/verify-probes.js +327 -0
  876. package/.worktrees/dafc71ad/src/version.js +19 -0
  877. package/.worktrees/dafc71ad/src/workflow.js +600 -0
  878. package/.worktrees/dafc71ad/src/workspace.js +125 -0
  879. package/.worktrees/dafc71ad/src/worktree-apply.js +1611 -0
  880. package/.worktrees/dafc71ad/src/worktree-deps.js +668 -0
  881. package/.worktrees/dafc71ad/src/worktree.js +1849 -0
  882. package/.worktrees/dafc71ad/templates/claude-instruction.md +23 -0
  883. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +29 -0
  884. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +12 -0
  885. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +32 -0
  886. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +79 -0
  887. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +132 -0
  888. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  889. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  890. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  891. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  892. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  893. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  894. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  895. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  896. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +57 -0
  897. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +177 -0
  898. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  899. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  900. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  901. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  902. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  903. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  904. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +64 -0
  905. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +54 -0
  906. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  907. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  908. package/.worktrees/e58fcc4c/.gitattributes +2 -0
  909. package/.worktrees/e58fcc4c/.husky/pre-push +20 -0
  910. package/.worktrees/e58fcc4c/README.md +203 -0
  911. package/.worktrees/e58fcc4c/SKILL.md +91 -0
  912. package/.worktrees/e58fcc4c/architecture-analysis.md +503 -0
  913. package/.worktrees/e58fcc4c/bin/sillyspec.js +2 -0
  914. package/.worktrees/e58fcc4c/eval/README.md +86 -0
  915. package/.worktrees/e58fcc4c/eval/eval.config.json +28 -0
  916. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +63 -0
  917. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +27 -0
  918. package/.worktrees/e58fcc4c/eval/lib/config.mjs +82 -0
  919. package/.worktrees/e58fcc4c/eval/lib/db.mjs +76 -0
  920. package/.worktrees/e58fcc4c/eval/lib/report.mjs +120 -0
  921. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +157 -0
  922. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +73 -0
  923. package/.worktrees/e58fcc4c/eval/lib/util.mjs +107 -0
  924. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +30 -0
  925. package/.worktrees/e58fcc4c/eval/run.mjs +83 -0
  926. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +6 -0
  927. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  928. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +6 -0
  929. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +28 -0
  930. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +6 -0
  931. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  932. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  933. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +6 -0
  934. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +31 -0
  935. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  936. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +6 -0
  937. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  938. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +6 -0
  939. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +38 -0
  940. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  941. package/.worktrees/e58fcc4c/package-lock.json +977 -0
  942. package/.worktrees/e58fcc4c/package.json +41 -0
  943. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  944. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  945. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  946. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +16 -0
  947. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  948. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +836 -0
  949. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +256 -0
  950. package/.worktrees/e58fcc4c/packages/dashboard/package.json +25 -0
  951. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +95 -0
  952. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +679 -0
  953. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +526 -0
  954. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +357 -0
  955. package/.worktrees/e58fcc4c/src/agent-session-log.js +803 -0
  956. package/.worktrees/e58fcc4c/src/change-list.js +290 -0
  957. package/.worktrees/e58fcc4c/src/change-risk-profile.js +339 -0
  958. package/.worktrees/e58fcc4c/src/check-primitives.js +65 -0
  959. package/.worktrees/e58fcc4c/src/classify-change.js +109 -0
  960. package/.worktrees/e58fcc4c/src/commit-suggest.js +202 -0
  961. package/.worktrees/e58fcc4c/src/config-cat.js +88 -0
  962. package/.worktrees/e58fcc4c/src/config-schema.js +328 -0
  963. package/.worktrees/e58fcc4c/src/constants.js +97 -0
  964. package/.worktrees/e58fcc4c/src/contract-matrix.js +533 -0
  965. package/.worktrees/e58fcc4c/src/datetime.js +20 -0
  966. package/.worktrees/e58fcc4c/src/db-engine.js +55 -0
  967. package/.worktrees/e58fcc4c/src/db.js +381 -0
  968. package/.worktrees/e58fcc4c/src/decision-distill.js +517 -0
  969. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +155 -0
  970. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +245 -0
  971. package/.worktrees/e58fcc4c/src/dispatch/probe.js +246 -0
  972. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +121 -0
  973. package/.worktrees/e58fcc4c/src/docs-check.js +825 -0
  974. package/.worktrees/e58fcc4c/src/docs-debt.js +393 -0
  975. package/.worktrees/e58fcc4c/src/docs-gate.js +107 -0
  976. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +1099 -0
  977. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +409 -0
  978. package/.worktrees/e58fcc4c/src/foreign-declared.js +155 -0
  979. package/.worktrees/e58fcc4c/src/fs-atomic.js +73 -0
  980. package/.worktrees/e58fcc4c/src/git-helper.js +150 -0
  981. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +130 -0
  982. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +892 -0
  983. package/.worktrees/e58fcc4c/src/index.js +2854 -0
  984. package/.worktrees/e58fcc4c/src/init.js +626 -0
  985. package/.worktrees/e58fcc4c/src/knowledge-match.js +231 -0
  986. package/.worktrees/e58fcc4c/src/local-detect.js +128 -0
  987. package/.worktrees/e58fcc4c/src/local-register.js +104 -0
  988. package/.worktrees/e58fcc4c/src/machine-interface.js +543 -0
  989. package/.worktrees/e58fcc4c/src/migrate.js +127 -0
  990. package/.worktrees/e58fcc4c/src/module-impact.js +166 -0
  991. package/.worktrees/e58fcc4c/src/module-resolve.js +222 -0
  992. package/.worktrees/e58fcc4c/src/modules.js +580 -0
  993. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +126 -0
  994. package/.worktrees/e58fcc4c/src/progress/change-registry.js +336 -0
  995. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +355 -0
  996. package/.worktrees/e58fcc4c/src/progress/shared.js +36 -0
  997. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +594 -0
  998. package/.worktrees/e58fcc4c/src/progress/step-store.js +265 -0
  999. package/.worktrees/e58fcc4c/src/progress.js +1304 -0
  1000. package/.worktrees/e58fcc4c/src/quick-recommend.js +115 -0
  1001. package/.worktrees/e58fcc4c/src/quicklog.js +883 -0
  1002. package/.worktrees/e58fcc4c/src/review-tier.js +77 -0
  1003. package/.worktrees/e58fcc4c/src/run/command.js +1641 -0
  1004. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +1552 -0
  1005. package/.worktrees/e58fcc4c/src/run/complete.js +1259 -0
  1006. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +156 -0
  1007. package/.worktrees/e58fcc4c/src/run/gates.js +1111 -0
  1008. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +208 -0
  1009. package/.worktrees/e58fcc4c/src/run/next.js +128 -0
  1010. package/.worktrees/e58fcc4c/src/run/prompt.js +843 -0
  1011. package/.worktrees/e58fcc4c/src/run/quick-audit.js +186 -0
  1012. package/.worktrees/e58fcc4c/src/run/scan-profile.js +269 -0
  1013. package/.worktrees/e58fcc4c/src/run/shared.js +1562 -0
  1014. package/.worktrees/e58fcc4c/src/run/stage.js +587 -0
  1015. package/.worktrees/e58fcc4c/src/run.js +23 -0
  1016. package/.worktrees/e58fcc4c/src/scan-diff.js +388 -0
  1017. package/.worktrees/e58fcc4c/src/scan-postcheck.js +524 -0
  1018. package/.worktrees/e58fcc4c/src/scan-staleness.js +95 -0
  1019. package/.worktrees/e58fcc4c/src/setup.js +414 -0
  1020. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +597 -0
  1021. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +62 -0
  1022. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +50 -0
  1023. package/.worktrees/e58fcc4c/src/spec-sync.js +358 -0
  1024. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +171 -0
  1025. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +551 -0
  1026. package/.worktrees/e58fcc4c/src/stage-contract.js +948 -0
  1027. package/.worktrees/e58fcc4c/src/stage-review.js +597 -0
  1028. package/.worktrees/e58fcc4c/src/stages/archive.js +199 -0
  1029. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +285 -0
  1030. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +624 -0
  1031. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +145 -0
  1032. package/.worktrees/e58fcc4c/src/stages/doctor.js +540 -0
  1033. package/.worktrees/e58fcc4c/src/stages/execute.js +1277 -0
  1034. package/.worktrees/e58fcc4c/src/stages/explore.js +43 -0
  1035. package/.worktrees/e58fcc4c/src/stages/index.js +29 -0
  1036. package/.worktrees/e58fcc4c/src/stages/knowledge.js +514 -0
  1037. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +1398 -0
  1038. package/.worktrees/e58fcc4c/src/stages/plan.js +655 -0
  1039. package/.worktrees/e58fcc4c/src/stages/quick.js +167 -0
  1040. package/.worktrees/e58fcc4c/src/stages/scan.js +608 -0
  1041. package/.worktrees/e58fcc4c/src/stages/status.js +64 -0
  1042. package/.worktrees/e58fcc4c/src/stages/verify.js +246 -0
  1043. package/.worktrees/e58fcc4c/src/sync.js +1470 -0
  1044. package/.worktrees/e58fcc4c/src/task-review.js +1498 -0
  1045. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +21 -0
  1046. package/.worktrees/e58fcc4c/src/taskcard.js +250 -0
  1047. package/.worktrees/e58fcc4c/src/verify-postcheck.js +1718 -0
  1048. package/.worktrees/e58fcc4c/src/verify-probes.js +327 -0
  1049. package/.worktrees/e58fcc4c/src/version.js +19 -0
  1050. package/.worktrees/e58fcc4c/src/workflow.js +600 -0
  1051. package/.worktrees/e58fcc4c/src/workspace.js +125 -0
  1052. package/.worktrees/e58fcc4c/src/worktree-apply.js +1611 -0
  1053. package/.worktrees/e58fcc4c/src/worktree-deps.js +668 -0
  1054. package/.worktrees/e58fcc4c/src/worktree.js +1849 -0
  1055. package/.worktrees/e58fcc4c/templates/claude-instruction.md +23 -0
  1056. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +29 -0
  1057. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +12 -0
  1058. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +32 -0
  1059. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +79 -0
  1060. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +132 -0
  1061. package/architecture-analysis.md +448 -0
  1062. package/package.json +1 -1
  1063. package/src/contract-matrix.js +7 -4
  1064. package/src/endpoint-extractor.js +41 -52
  1065. package/src/foreign-declared.js +88 -5
  1066. package/src/fs-atomic.js +20 -3
  1067. package/src/hooks/worktree-guard.js +9 -3
  1068. package/src/index.js +36 -19
  1069. package/src/module-impact.js +1 -1
  1070. package/src/modules.js +23 -21
  1071. package/src/progress/stage-machine.js +23 -0
  1072. package/src/progress.js +38 -2
  1073. package/src/quicklog.js +7 -5
  1074. package/src/run/command.js +7 -6
  1075. package/src/run/complete-handlers.js +6 -2
  1076. package/src/run/complete.js +33 -20
  1077. package/src/run/gates.js +31 -4
  1078. package/src/run/next.js +4 -3
  1079. package/src/run/prompt.js +66 -6
  1080. package/src/run/scan-profile.js +1 -0
  1081. package/src/run/shared.js +11 -5
  1082. package/src/run/stage.js +15 -12
  1083. package/src/scan-diff.js +4 -2
  1084. package/src/stage-contract-spec.js +1 -1
  1085. package/src/stage-contract.js +16 -8
  1086. package/src/stages/brainstorm-auto.js +43 -1
  1087. package/src/stages/brainstorm.js +24 -8
  1088. package/src/stages/execute.js +36 -9
  1089. package/src/stages/knowledge.js +18 -5
  1090. package/src/stages/plan-postcheck.js +63 -7
  1091. package/src/stages/plan.js +13 -6
  1092. package/src/stages/verify.js +1 -1
  1093. package/src/sync.js +27 -11
  1094. package/src/task-review.js +5 -3
  1095. package/src/taskcard.js +35 -0
  1096. package/src/verify-postcheck.js +24 -13
  1097. package/src/verify-probes.js +39 -13
  1098. package/src/worktree-apply.js +481 -292
  1099. package/src/worktree-deps.js +93 -1
  1100. package/src/worktree.js +91 -21
  1101. package/templates/prompts/taskcard-rules.md +1 -1
@@ -19,10 +19,26 @@ import { WorktreeManager } from './worktree.js';
19
19
  import { parseFileChangeList, parseFileChangeListDetailed, pathMatches } from './change-list.js';
20
20
  import { parseAllowedPaths, parseRepo } from './stages/plan-postcheck.js';
21
21
  import { git, gitQuiet } from './git-helper.js';
22
- import { resolveLatestExecuteRunId, readReview } from './task-review.js';
22
+ import { resolveLatestExecuteRunId, resolveLatestExecuteRunIdWithTasks, readReview, normalizeRepoKey } from './task-review.js';
23
23
 
24
24
  const CHANGES_REL = '.sillyspec/changes';
25
25
 
26
+ /**
27
+ * cleanup 返回值必须消费(坑 ghost-dir-junction-pierce,2026-08-23 实证:apply 后 partial
28
+ * 残留被静默丢弃,用户以为已干净、人工 rm -rf 时穿透 junction 删主仓 node_modules)。
29
+ * 模块级共享:applyWorktree 无变更早退 / skip-overlap / applyByMerge 成功路径三处统一走此消费。
30
+ */
31
+ function consumeCleanupResult(cr, result) {
32
+ if (cr && (cr.result === 'partial' || (Array.isArray(cr.residual) && cr.residual.length > 0))) {
33
+ result.warnings = result.warnings || [];
34
+ result.warnings.push(
35
+ `⚠️ worktree 部分清理残留(${cr.result}):${(cr.residual || []).join('; ') || 'worktree 目录'}` +
36
+ `——Windows 勿直接 rm -rf(会穿透 node_modules junction 删主仓依赖):先 cmd /c rmdir "<worktree>\\node_modules" 解链再删目录,或跑 sillyspec worktree doctor --fix`
37
+ );
38
+ }
39
+ return cr;
40
+ }
41
+
26
42
  /**
27
43
  * 过滤掉 worktree 基础设施文件(非交付物),让 apply 只关心真正的变更产出:
28
44
  * - meta.json:worktree 元数据,baseline commit 中被跟踪、working-tree 被 CLI 改写
@@ -229,6 +245,46 @@ export function resolveApplyAllowSet(projectRoot, changeName) {
229
245
  return repoMap;
230
246
  }
231
247
 
248
+ /**
249
+ * 收集最新 execute run 各 task review.json 的 changedFiles 声明 → Map<repoKey, string[]>。
250
+ *
251
+ * 坑 apply-undeclared-deviation-block(2026-08-24 用户反馈四期③):执行期有据越界文件
252
+ * (facade 转发/名单测试)不在 design §6 也不在 allowed_paths,Gate1 拦 apply 只能回改
253
+ * design.md。review.json changedFiles 是 reviewer 对实际改动的声明(Task Review Gate 的
254
+ * verifyReviewGitEvidence 已交叉校验其与真实 git diff 相交),作为第三源并入 allow set——
255
+ * 放行仅限「已声明且过证据校验」的文件,完全越界仍拦。口径与 complete-handlers 的
256
+ * collectExecuteChangedFiles 一致:change 戳归属 run、.sillyspec//meta.json 过滤、
257
+ * review.repo 切片(跨仓声明不进 main 集)。读不到 run/review → 空 Map(fail-closed 回退旧行为)。
258
+ *
259
+ * @param {string} projectRoot - 主仓库根
260
+ * @param {string} changeName - 变更名
261
+ * @returns {Map<string, string[]>}
262
+ */
263
+ export function collectReviewDeclaredFiles(projectRoot, changeName) {
264
+ const byRepo = new Map();
265
+ try {
266
+ const runtimeRoot = join(projectRoot, '.sillyspec', '.runtime');
267
+ const runId = resolveLatestExecuteRunIdWithTasks({ runtimeRoot, changeName });
268
+ if (!runId) return byRepo;
269
+ const runTasksDir = join(runtimeRoot, 'execute-runs', runId, 'tasks');
270
+ if (!existsSync(runTasksDir)) return byRepo;
271
+ for (const taskId of readdirSync(runTasksDir)) {
272
+ const r = readReview(join(runTasksDir, taskId, 'review.json'));
273
+ if (!r.ok || !r.review || !Array.isArray(r.review.changedFiles)) continue;
274
+ const repoKey = normalizeRepoKey(r.review.repo);
275
+ const list = byRepo.get(repoKey) || [];
276
+ for (const f of r.review.changedFiles) {
277
+ // 交付物过滤(与 collectExecuteChangedFiles 同口径):.sillyspec/ 运行时产物/meta.json 不进 allow
278
+ if (typeof f !== 'string' || f.trim() === '') continue;
279
+ if (f.startsWith('.sillyspec/') || f === 'meta.json') continue;
280
+ list.push(f);
281
+ }
282
+ byRepo.set(repoKey, list);
283
+ }
284
+ } catch { /* 读不到 run/review → 空 Map(fail-closed 回退旧行为) */ }
285
+ return byRepo;
286
+ }
287
+
232
288
  /**
233
289
  * 跨仓 task apply = no-op 校验(task-05 / D-009 / design §6 A3 G1)。
234
290
  *
@@ -384,7 +440,7 @@ export async function withMainRepoLock(projectRoot, changeName, purpose, fn, opt
384
440
  }
385
441
  }
386
442
 
387
- export function applyWorktree(changeName, { cwd, checkOnly = false, merge = false, base = 'merge-base', ctx = null, skipOverlap = false } = {}) {
443
+ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = false, base = 'merge-base', ctx = null, skipOverlap = false, stashDirty = false } = {}) {
388
444
  const projectRoot = cwd || process.cwd();
389
445
  const wm = new WorktreeManager({ cwd: projectRoot });
390
446
  const meta = wm.getMeta(changeName);
@@ -456,6 +512,10 @@ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = fals
456
512
  // 同时检测 untracked 新文件(git diff 不包含 untracked)
457
513
  let changedFiles;
458
514
  const deletedFiles = [];
515
+ // merge 后应「不存在于 main HEAD」的文件(D 删除 + R/C rename/copy 源路径):
516
+ // applyByMerge 落地校验按此分流——原实现一律要求 cat-file 存在,含删除文件的变更
517
+ // merge 成功也恒报「未落地」失败、worktree 永不清理(坑 apply-merge-deleted-misjudged)
518
+ const absentAfterMerge = [];
459
519
  try {
460
520
  // 用 --name-status 捕获 rename/delete(--name-only 会丢失 rename 源文件)
461
521
  // 交付集合判定:用 deliverableBase(baselineCommit||baseHash),保「只合子代理改动」语义
@@ -469,8 +529,11 @@ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = fals
469
529
  if (parts.length >= 3) statusFiles.add(parts[parts.length - 2]);
470
530
  // 删除文件(status D / D100)→ 收集到 deletedFiles(rescue DELETE 分类用,design §逐文件分类)
471
531
  if (parts[0].startsWith('D')) deletedFiles.push(parts[parts.length - 1]);
532
+ // rename/copy 源路径(R100/C99 old new 三段式)→ 同删除语义:merge 后 HEAD 中不应存在
533
+ if (parts.length >= 3 && !parts[0].startsWith('D')) absentAfterMerge.push(parts[parts.length - 2]);
472
534
  }
473
535
  }
536
+ for (const f of deletedFiles) absentAfterMerge.push(f);
474
537
 
475
538
  // untracked 新文件(deliverableBase 中不存在的文件)
476
539
  const untrackedRaw = gitQuiet(worktreePath, ['ls-files', '--others', '--exclude-standard']);
@@ -487,11 +550,12 @@ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = fals
487
550
 
488
551
  result.changedFiles = changedFiles;
489
552
  result.deletedFiles = deletedFiles;
553
+ result.absentAfterMerge = absentAfterMerge;
490
554
 
491
555
  if (changedFiles.length === 0) {
492
556
  // 没有变更
493
557
  if (!checkOnly) {
494
- wm.cleanup(changeName, { force: true });
558
+ consumeCleanupResult(wm.cleanup(changeName, { force: true }), result);
495
559
  }
496
560
  result.ok = true;
497
561
  return result;
@@ -502,6 +566,29 @@ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = fals
502
566
  // (主仓 worktree diff 只含主仓文件,跨仓文件在跨仓仓不进主仓 worktree diff)。跨仓 allowed_paths
503
567
  // 仅作 Map 切片返回供上游用,主流程不消费(跨仓 apply=no-op,D-009)。
504
568
  const allowMap = resolveApplyAllowSet(projectRoot, changeName);
569
+ // --- 3b. review.json 声明偏差文件并入(坑 apply-undeclared-deviation-block)---
570
+ // 第三源:reviewer 声明的 changedFiles(已过 Task Review Gate git 证据交叉校验)——执行期
571
+ // 有据越界(facade 转发/名单测试)不再逼回改 design.md。各 repo 切片各自并入;仅靠 review
572
+ // 放行的文件记审计 warning(result.reviewAdmittedFiles),完全越界文件仍拦(Gate1 在扩展后判)。
573
+ const reviewDeclaredByRepo = collectReviewDeclaredFiles(projectRoot, changeName);
574
+ const reviewAdmittedFiles = [];
575
+ for (const [repoKey, files] of reviewDeclaredByRepo) {
576
+ const repoSet = allowMap.get(repoKey);
577
+ if (!repoSet) continue; // 该 repo 无 design/任务卡清单(无清单=不校验),无需扩展
578
+ const existing = [...repoSet];
579
+ for (const f of files) {
580
+ if (!existing.some(ap => pathMatches(f, ap))) {
581
+ repoSet.add(f);
582
+ if (repoKey === 'main') reviewAdmittedFiles.push(f);
583
+ }
584
+ }
585
+ }
586
+ if (reviewAdmittedFiles.length > 0) {
587
+ result.reviewAdmittedFiles = reviewAdmittedFiles;
588
+ result.warnings = (result.warnings || []).concat([
589
+ `${reviewAdmittedFiles.length} 个变更文件不在 design.md/任务卡清单,但已被 task review.json changedFiles 声明(review 声明放行,已过 Task Review Gate git 证据校验;审计留痕):${reviewAdmittedFiles.join(', ')}`
590
+ ]);
591
+ }
505
592
  const allowSet = allowMap.get('main') || new Set();
506
593
  const hasAllowList = allowSet.size > 0;
507
594
 
@@ -541,7 +628,7 @@ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = fals
541
628
  if (violations.length > 0) {
542
629
  result.extraFiles.push(...violations);
543
630
  result.errors.push(
544
- `文件清单校验失败:以下变更文件不在 design.md 清单中:\n ${violations.join('\n ')}`
631
+ `文件清单校验失败:以下变更文件不在 design.md 清单、也不在 task review.json changedFiles 声明中:\n ${violations.join('\n ')}\n(若属执行期合理偏差:在 task review.json 的 changedFiles 声明,或在 design.md §6 清单补行)`
545
632
  );
546
633
  // checkOnly(assess)模式不短路:继续跑 Gate3,收集所有道供一次报全(坑 worktree-execute-apply-friction 坑4)。
547
634
  // 真实 apply(checkOnly=false)仍短路,保安全。
@@ -549,83 +636,178 @@ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = fals
549
636
  }
550
637
  }
551
638
 
552
- // --- 4.6 显式 --merge:用户显式选择 git merge 兜底(主干已提交推进重叠时的三方合并) ---
553
- // 触发点从「4.5 baseline 漂移自动降级」改为「用户显式 --merge flag」(D-001 保留,触发方式变化)。
554
- // 用 --merge 时跳过未提交 dirty 拦截——merge 同样要求工作区相对干净,此处仅提示风险,真正失败由 applyByMerge 报告。
555
- // keepConflicts:true——显式 --merge 冲突时保留现场供手工解决(不再直接 abort 丢上下文)。
556
- if (merge && !checkOnly) {
557
- return applyByMerge(result, changeName, projectRoot, wm, { keepConflicts: true });
639
+ // --- 4.4 --stash-dirty:主仓在途改动自动 stash(坑 apply-main-dirty-no-first-class, ---
640
+ // 2026-08-24 用户反馈四期①:主仓并行在途改动下默认 / --skip-overlap(全重叠「无可应用子集」)/
641
+ // --merge(git 拒在脏树启动合并)三路死锁,手工 stash→3way→pop 流程未内置。flag 显式 opt-in
642
+ // (自动触碰用户未提交工作区必须可审计):stash SHA 显著打印;恢复用 apply --index 保暂存区
643
+ // 状态(普通 pop 会把 staged 降级为 unstaged);恢复失败保留条目绝不自动 drop(SHA 兜底)。
644
+ // checkOnly(assess)只读,绝不 stash。放在 Gate1 之后:清单违规先拦,不动用户树。
645
+ let stashInfo = null;
646
+ if (stashDirty && !checkOnly) {
647
+ try {
648
+ const dirtyProbe = computeRescueDirtyFiles(projectRoot);
649
+ if (dirtyProbe.length > 0) {
650
+ const marker = `sillyspec apply ${changeName} --stash-dirty ${new Date().toISOString()}`;
651
+ const before = (gitQuiet(projectRoot, ['stash', 'list']) || '').split('\n').filter(Boolean).length;
652
+ // pathspec 限定 stash 范围与探针/4.5 同口径(排除 .sillyspec/ 运行时与他者 spec 产物、
653
+ // .claude/docs/CLAUDE.md)——裸 push -u 会把排除项的未跟踪文件一并卷走,恢复时与
654
+ // apply 期间重建的 spec 文件 already exists 互踩(实证 dbg)。
655
+ git(projectRoot, ['stash', 'push', '--include-untracked', '-m', marker,
656
+ '--', '.', ':(exclude).sillyspec/', ':(exclude).claude/', ':(exclude)docs/', ':(exclude)CLAUDE.md'], { timeout: 60000 });
657
+ const headEntry = ((gitQuiet(projectRoot, ['stash', 'list']) || '').split('\n')[0] || '');
658
+ const after = (gitQuiet(projectRoot, ['stash', 'list']) || '').split('\n').filter(Boolean).length;
659
+ const sha = gitQuiet(projectRoot, ['rev-parse', '--verify', 'stash@{0}']);
660
+ if (after !== before + 1 || !sha || !headEntry.includes(marker.split(' ').slice(0, 4).join(' '))) {
661
+ // 栈顶非本次条目(并行外部操作插队)——不盲动栈,fail-closed
662
+ throw new Error(`stash push 后栈顶校验失败(before=${before} after=${after} head=${headEntry.slice(0, 60)})`);
663
+ }
664
+ stashInfo = { sha: sha.trim(), marker };
665
+ console.log(`📦 主仓在途改动已 stash(--stash-dirty,${dirtyProbe.length} 个文件):stash@{0} = ${stashInfo.sha}`);
666
+ console.log(` apply 结束后自动恢复(git stash apply --index,保留暂存区状态);若恢复冲突,stash 条目保留不丢弃,用上述 SHA 兜底`);
667
+ }
668
+ } catch (e) {
669
+ result.errors.push(`--stash-dirty:主仓 stash 失败(apply 未开始,主仓未改动): ${e.message}——若栈中已有新条目请 git stash list 核对后再处置,勿盲 pop`);
670
+ return result;
671
+ }
558
672
  }
559
673
 
560
- // --- 4.5 校验:主工作区「未提交」脏文件是否与本次变更重叠(overlap-only 拦截)---
561
- // 分工:4.5(排除规则下 dirty∩changedFiles)+ 5a(更宽口径的同一交集)挡「未提交」dirty 重叠;
562
- // 5b 管「已提交」HEAD 分叉(已放宽)。
563
- // 2026-08-20 放宽(原全量拦截 → 只拦重叠):原「排除规则下任何未提交文件即整体拒绝」会把与本次
564
- // 变更无关的脏文件也硬挡,用户被迫走 rescue cp 手动路径。重叠(dirtyFiles ∩ changedFiles,
565
- // changedFiles 已含删除文件与 worktree 新增同名文件)才是 git apply 无法安全应用的实际危险区。
566
- // 残余风险与兜底(Windows/autocrlf):实测 autocrlf on 时 git apply --3way 对 dirty 工作区可报
567
- // `does not match index`(哪怕脏文件与 patch 不重叠;autocrlf off 时能干净应用,非 git 本质限制)。
568
- // 交集空前提下该失败是安全的:step7 catch → rollbackApply 只 checkout/删除 patch 涉及文件
569
- // (这些文件 apply 前无未提交修改,还原 = apply 前状态),无关脏文件不在 patch/rollback 范围
570
- // 不受影响 → fail-safe,报错后 stash 重试即可。放行时 warning 提示此路径。
571
- // 排除非交付物的元数据/文档 churn(execute 自身改的 + 多操作者常改的 agent 指引/文档),
572
- // 否则别人改 CLAUDE.md/docs/.claude → 判定 dirty → apply 误阻断(多操作者仓库高频踩坑)。
573
- // 注意:排除规则必须和 computeBaselineHash (worktree.js) 一致(虽已不比对 hash,仍用同一口径判当前 dirty)。
574
- if (meta.baselineHash) {
575
- // pathspec:`--` 结束选项,`.` 包含全部,后续 :(exclude) 排除非交付物元数据/文档 churn
576
- // (与 computeBaselineHash 同口径)。数组形式逐元素传递,:(exclude) magic 字面直传不经 shell。
577
- const exclude = ['--', '.', ':(exclude).sillyspec/', ':(exclude).claude/', ':(exclude)docs/', ':(exclude)CLAUDE.md'];
578
- const staged = gitQuiet(projectRoot, ['diff', '--cached', ...exclude]) || '';
579
- const unstaged = gitQuiet(projectRoot, ['diff', ...exclude]) || '';
580
- const untracked = gitQuiet(projectRoot, ['ls-files', '--others', '--exclude-standard', ...exclude]) || '';
581
- // 意图(与 computeBaselineHash 注释一致):只看「未提交 dirty」——git apply --3way 对 dirty 工作区不稳。
582
- // 不比对 hash 是否等于 execute 启动时 baselineHash:主仓 dirty→clean(execute 期间 commit 无关文件)后
583
- // hash 必变,若仍比对会永久死锁(须手改 meta.baselineHash)。改判「排除规则下当前是否有未提交 dirty」。
584
- const hasUncommittedDirty = staged !== '' || unstaged !== '' || untracked !== '';
585
- if (hasUncommittedDirty) {
586
- const dirtyFiles = [...new Set(
587
- ((gitQuiet(projectRoot, ['diff', '--name-only', 'HEAD']) || '').split('\n').filter(Boolean))
588
- .concat((gitQuiet(projectRoot, ['ls-files', '--others', '--exclude-standard']) || '').split('\n').filter(Boolean))
589
- )].filter(f => !f.startsWith('.sillyspec/') && f !== 'meta.json');
590
- const overlapDirty = dirtyFiles.filter(f => changedFiles.includes(f));
591
- if (overlapDirty.length > 0) {
592
- // --skip-overlap(坑 apply-overlap-all-or-nothing,2026-08-23 实证:多 agent 并发仓主仓
593
- // 常态有在途变更,overlap 整批拦截使 apply 基本不可用,rescue 手动 cp 又留混合状态):
594
- // 显式 opt-in 剔除重叠文件、应用干净子集。重叠文件留在 worktree——step8 非 force
595
- // cleanup 被 hasUnappliedChanges 护栏拦住(主仓工作区逐字节降噪层只剔除已应用文件),
596
- // 待主仓干净后重新 apply(此时只剩剩余文件)或人工裁决。
674
+ try {
675
+ // --- 4.6 显式 --merge:用户显式选择 git merge 兜底(主干已提交推进重叠时的三方合并) ---
676
+ // 触发点从「4.5 baseline 漂移自动降级」改为「用户显式 --merge flag」(D-001 保留,触发方式变化)。
677
+ // 用 --merge 时跳过未提交 dirty 拦截——merge 同样要求工作区相对干净,此处仅提示风险,真正失败由 applyByMerge 报告。
678
+ // keepConflicts:true——显式 --merge 冲突时保留现场供手工解决(不再直接 abort 丢上下文)。
679
+ if (merge && !checkOnly) {
680
+ return applyByMerge(result, changeName, projectRoot, wm, { keepConflicts: true });
681
+ }
682
+
683
+ // --- 4.5 校验:主工作区「未提交」脏文件是否与本次变更重叠(overlap-only 拦截)---
684
+ // 分工:4.5(排除规则下 dirty∩changedFiles)+ 5a(更宽口径的同一交集)挡「未提交」dirty 重叠;
685
+ // 5b 管「已提交」HEAD 分叉(已放宽)。
686
+ // 2026-08-20 放宽(原全量拦截 → 只拦重叠):原「排除规则下任何未提交文件即整体拒绝」会把与本次
687
+ // 变更无关的脏文件也硬挡,用户被迫走 rescue cp 手动路径。重叠(dirtyFiles ∩ changedFiles,
688
+ // changedFiles 已含删除文件与 worktree 新增同名文件)才是 git apply 无法安全应用的实际危险区。
689
+ // 残余风险与兜底(Windows/autocrlf):实测 autocrlf on 时 git apply --3way 对 dirty 工作区可报
690
+ // `does not match index`(哪怕脏文件与 patch 不重叠;autocrlf off 时能干净应用,非 git 本质限制)。
691
+ // 交集空前提下该失败是安全的:step7 catch → rollbackApply 只 checkout/删除 patch 涉及文件
692
+ // (这些文件 apply 前无未提交修改,还原 = apply 前状态),无关脏文件不在 patch/rollback 范围
693
+ // 不受影响 → fail-safe,报错后 stash 重试即可。放行时 warning 提示此路径。
694
+ // 排除非交付物的元数据/文档 churn(execute 自身改的 + 多操作者常改的 agent 指引/文档),
695
+ // 否则别人改 CLAUDE.md/docs/.claude → 判定 dirty → apply 误阻断(多操作者仓库高频踩坑)。
696
+ // 注意:排除规则必须和 computeBaselineHash (worktree.js) 一致(虽已不比对 hash,仍用同一口径判当前 dirty)。
697
+ if (meta.baselineHash) {
698
+ // pathspec:`--` 结束选项,`.` 包含全部,后续 :(exclude) 排除非交付物元数据/文档 churn
699
+ // (与 computeBaselineHash 同口径)。数组形式逐元素传递,:(exclude) magic 字面直传不经 shell。
700
+ const exclude = ['--', '.', ':(exclude).sillyspec/', ':(exclude).claude/', ':(exclude)docs/', ':(exclude)CLAUDE.md'];
701
+ const staged = gitQuiet(projectRoot, ['diff', '--cached', ...exclude]) || '';
702
+ const unstaged = gitQuiet(projectRoot, ['diff', ...exclude]) || '';
703
+ const untracked = gitQuiet(projectRoot, ['ls-files', '--others', '--exclude-standard', ...exclude]) || '';
704
+ // 意图(与 computeBaselineHash 注释一致):只看「未提交 dirty」——git apply --3way 对 dirty 工作区不稳。
705
+ // 不比对 hash 是否等于 execute 启动时 baselineHash:主仓 dirty→clean(execute 期间 commit 无关文件)后
706
+ // hash 必变,若仍比对会永久死锁(须手改 meta.baselineHash)。改判「排除规则下当前是否有未提交 dirty」。
707
+ const hasUncommittedDirty = staged !== '' || unstaged !== '' || untracked !== '';
708
+ if (hasUncommittedDirty) {
709
+ const dirtyFiles = [...new Set(
710
+ ((gitQuiet(projectRoot, ['diff', '--name-only', 'HEAD']) || '').split('\n').filter(Boolean))
711
+ .concat((gitQuiet(projectRoot, ['ls-files', '--others', '--exclude-standard']) || '').split('\n').filter(Boolean))
712
+ )].filter(f => !f.startsWith('.sillyspec/') && f !== 'meta.json');
713
+ const overlapDirty = dirtyFiles.filter(f => changedFiles.includes(f));
714
+ if (overlapDirty.length > 0) {
715
+ // --skip-overlap(坑 apply-overlap-all-or-nothing,2026-08-23 实证:多 agent 并发仓主仓
716
+ // 常态有在途变更,overlap 整批拦截使 apply 基本不可用,rescue 手动 cp 又留混合状态):
717
+ // 显式 opt-in 剔除重叠文件、应用干净子集。重叠文件留在 worktree——step8 非 force
718
+ // cleanup 被 hasUnappliedChanges 护栏拦住(主仓工作区逐字节降噪层只剔除已应用文件),
719
+ // 待主仓干净后重新 apply(此时只剩剩余文件)或人工裁决。
720
+ if (skipOverlap && !checkOnly) {
721
+ const skipSet = new Set(overlapDirty);
722
+ result.skippedOverlapFiles = overlapDirty.slice();
723
+ changedFiles = changedFiles.filter(f => !skipSet.has(f));
724
+ result.changedFiles = changedFiles;
725
+ result.deletedFiles = deletedFiles.filter(f => !skipSet.has(f));
726
+ result.hashMismatchFiles = (result.hashMismatchFiles || []).filter(f => !skipSet.has(f));
727
+ if (changedFiles.length === 0) {
728
+ result.errors.push(
729
+ `--skip-overlap:本次 ${overlapDirty.length} 个变更文件全部与主仓未提交改动重叠,无可应用子集:\n ${overlapDirty.join('\n ')}\n` +
730
+ `请先提交/stash 主仓改动后重试(不带 --skip-overlap),或 sillyspec worktree apply ${changeName} --stash-dirty(工具内置 stash→apply→恢复,保暂存区状态,SHA 兜底可审计)。`
731
+ );
732
+ return result;
733
+ }
734
+ result.warnings = (result.warnings || []).concat([
735
+ `--skip-overlap:跳过 ${overlapDirty.length} 个与主仓未提交改动重叠的文件(留在 worktree,未应用):${overlapDirty.join(', ')}——待主仓提交/stash 后重新 apply 只应用剩余文件,或确认放弃后 cleanup --force`
736
+ ]);
737
+ } else {
738
+ // 重叠拦截:只有与本次变更同文件的未提交改动才无法安全 apply(列重叠文件,非全部脏文件)
739
+ const rescueDirty = computeRescueDirtyFiles(projectRoot);
740
+ result.rescueCommands = generateRescueCommands({
741
+ changedFiles,
742
+ dirtyFiles: rescueDirty,
743
+ hashMismatchFiles: result.hashMismatchFiles,
744
+ deletedFiles: result.deletedFiles,
745
+ worktreePath,
746
+ projectRoot,
747
+ });
748
+ result.errors.push(
749
+ `主工作区以下未提交文件与本次 apply 的变更重叠,git apply 无法安全应用:\n ${overlapDirty.join('\n ')}\n` +
750
+ `请先提交或暂存这些改动,再重新 apply:\n git add -A && git commit -m "..." 或 git stash\n` +
751
+ `或 sillyspec worktree apply ${changeName} --stash-dirty(工具内置 stash→apply→恢复,保暂存区状态,SHA 兜底可审计)\n` +
752
+ `或应用非重叠部分(重叠文件留在 worktree,主仓干净后重新 apply 只补剩余):\n sillyspec worktree apply ${changeName} --skip-overlap\n` +
753
+ (result.rescueCommands.commands.length > 0 || result.rescueCommands.warnings.length > 0
754
+ ? `或手动 rescue(旁路 git apply,逐文件 cp 安全子集;cp 后需手动 sillyspec worktree cleanup ${changeName}):\n` +
755
+ result.rescueCommands.commands.map(c => ` ${c}`).join('\n') +
756
+ (result.rescueCommands.warnings.length > 0 ? '\n' + result.rescueCommands.warnings.map(w => ` ${w}`).join('\n') : '') +
757
+ `\n (共 ${result.rescueCommands.cpFileCount} 个可安全 cp,${result.rescueCommands.excludedCount} 个被排除)\n`
758
+ : '')
759
+ );
760
+ if (!checkOnly) return result; // checkOnly 收集不短路(一次报全);真实 apply 短路
761
+ }
762
+ } else {
763
+ // 无关脏文件放行(只校验重叠文件):--3way 若因 autocrlf 报 does not match index 会被
764
+ // step7 catch 回滚(交集空前提下无损,见上注释),stash 后重试即可——不再硬挡 rescue 手动路径
765
+ result.warnings = (result.warnings || []).concat([
766
+ `主工作区有 ${dirtyFiles.length} 个与本次 apply 无关的未提交文件,已放行(只校验重叠文件):` +
767
+ `${dirtyFiles.slice(0, 5).join(', ')}${dirtyFiles.length > 5 ? ' 等' : ''}` +
768
+ `——若 apply --3way 因 CRLF/autocrlf 报 does not match index,可 git stash 后重试`
769
+ ]);
770
+ }
771
+ }
772
+ }
773
+
774
+ // --- 5. 校验:主工作区文件 base hash 一致 ---
775
+ // 5a. 检查主工作区是否有未 commit 的脏文件(会影响 apply)
776
+ const mainDirtyRaw = gitQuiet(projectRoot, ['diff', '--name-only', 'HEAD']);
777
+ const mainDirtyFiles = mainDirtyRaw ? mainDirtyRaw.split('\n').filter(Boolean) : [];
778
+ if (mainDirtyFiles.length > 0) {
779
+ // 如果脏文件和本次 apply 的文件有交集 → 报错
780
+ const conflictDirty = mainDirtyFiles.filter(f => changedFiles.includes(f));
781
+ if (conflictDirty.length > 0) {
782
+ // --skip-overlap 同款剔除(4.5 过滤后此处残余多为 staged 口径差集,防御性同处理)
597
783
  if (skipOverlap && !checkOnly) {
598
- const skipSet = new Set(overlapDirty);
599
- result.skippedOverlapFiles = overlapDirty.slice();
600
- changedFiles = changedFiles.filter(f => !skipSet.has(f));
784
+ const skipSet5a = new Set(conflictDirty);
785
+ for (const f of conflictDirty) {
786
+ if (!result.skippedOverlapFiles.includes(f)) result.skippedOverlapFiles.push(f);
787
+ }
788
+ changedFiles = changedFiles.filter(f => !skipSet5a.has(f));
601
789
  result.changedFiles = changedFiles;
602
- result.deletedFiles = deletedFiles.filter(f => !skipSet.has(f));
603
- result.hashMismatchFiles = (result.hashMismatchFiles || []).filter(f => !skipSet.has(f));
790
+ result.deletedFiles = deletedFiles.filter(f => !skipSet5a.has(f));
791
+ result.hashMismatchFiles = (result.hashMismatchFiles || []).filter(f => !skipSet5a.has(f));
604
792
  if (changedFiles.length === 0) {
605
793
  result.errors.push(
606
- `--skip-overlap:本次 ${overlapDirty.length} 个变更文件全部与主仓未提交改动重叠,无可应用子集:\n ${overlapDirty.join('\n ')}\n` +
607
- `请先提交/stash 主仓改动后重试(不带 --skip-overlap)。`
794
+ `--skip-overlap:变更文件全部与主仓未提交改动重叠,无可应用子集:\n ${conflictDirty.join('\n ')}\n` +
795
+ `请先提交/stash 主仓改动后重试,或 sillyspec worktree apply ${changeName} --stash-dirty(工具内置 stash→apply→恢复,保暂存区状态,SHA 兜底可审计)。`
608
796
  );
609
797
  return result;
610
798
  }
611
799
  result.warnings = (result.warnings || []).concat([
612
- `--skip-overlap:跳过 ${overlapDirty.length} 个与主仓未提交改动重叠的文件(留在 worktree,未应用):${overlapDirty.join(', ')}——待主仓提交/stash 后重新 apply 只应用剩余文件,或确认放弃后 cleanup --force`
800
+ `--skip-overlap(5a 口径):再剔除 ${conflictDirty.length} 个重叠文件:${conflictDirty.join(', ')}`
613
801
  ]);
614
802
  } else {
615
- // 重叠拦截:只有与本次变更同文件的未提交改动才无法安全 apply(列重叠文件,非全部脏文件)
616
- const rescueDirty = computeRescueDirtyFiles(projectRoot);
803
+ const rescueDirty5a = computeRescueDirtyFiles(projectRoot);
617
804
  result.rescueCommands = generateRescueCommands({
618
- changedFiles,
619
- dirtyFiles: rescueDirty,
620
- hashMismatchFiles: result.hashMismatchFiles,
621
- deletedFiles: result.deletedFiles,
622
- worktreePath,
623
- projectRoot,
805
+ changedFiles, dirtyFiles: rescueDirty5a, hashMismatchFiles: result.hashMismatchFiles,
806
+ deletedFiles: result.deletedFiles, worktreePath, projectRoot,
624
807
  });
625
808
  result.errors.push(
626
- `主工作区以下未提交文件与本次 apply 的变更重叠,git apply 无法安全应用:\n ${overlapDirty.join('\n ')}\n` +
627
- `请先提交或暂存这些改动,再重新 apply:\n git add -A && git commit -m "..." 或 git stash\n` +
628
- `或应用非重叠部分(重叠文件留在 worktree,主仓干净后重新 apply 只补剩余):\n sillyspec worktree apply ${changeName} --skip-overlap\n` +
809
+ `主工作区有以下未 commit 的变更,会影响 apply:\n ${conflictDirty.join('\n ')}\n请先 commit 或 stash 这些变更。` +
810
+ `或应用非重叠部分:sillyspec worktree apply ${changeName} --skip-overlap` +
629
811
  (result.rescueCommands.commands.length > 0 || result.rescueCommands.warnings.length > 0
630
812
  ? `或手动 rescue(旁路 git apply,逐文件 cp 安全子集;cp 后需手动 sillyspec worktree cleanup ${changeName}):\n` +
631
813
  result.rescueCommands.commands.map(c => ` ${c}`).join('\n') +
@@ -635,260 +817,253 @@ export function applyWorktree(changeName, { cwd, checkOnly = false, merge = fals
635
817
  );
636
818
  if (!checkOnly) return result; // checkOnly 收集不短路(一次报全);真实 apply 短路
637
819
  }
638
- } else {
639
- // 无关脏文件放行(只校验重叠文件):--3way 若因 autocrlf 报 does not match index 会被
640
- // step7 catch 回滚(交集空前提下无损,见上注释),stash 后重试即可——不再硬挡 rescue 手动路径
641
- result.warnings = (result.warnings || []).concat([
642
- `主工作区有 ${dirtyFiles.length} 个与本次 apply 无关的未提交文件,已放行(只校验重叠文件):` +
643
- `${dirtyFiles.slice(0, 5).join(', ')}${dirtyFiles.length > 5 ? ' 等' : ''}` +
644
- `——若 apply --3way 因 CRLF/autocrlf 报 does not match index,可 git stash 后重试`
645
- ]);
646
- }
647
- }
648
- }
649
-
650
- // --- 5. 校验:主工作区文件 base hash 一致 ---
651
- // 5a. 检查主工作区是否有未 commit 的脏文件(会影响 apply)
652
- const mainDirtyRaw = gitQuiet(projectRoot, ['diff', '--name-only', 'HEAD']);
653
- const mainDirtyFiles = mainDirtyRaw ? mainDirtyRaw.split('\n').filter(Boolean) : [];
654
- if (mainDirtyFiles.length > 0) {
655
- // 如果脏文件和本次 apply 的文件有交集 → 报错
656
- const conflictDirty = mainDirtyFiles.filter(f => changedFiles.includes(f));
657
- if (conflictDirty.length > 0) {
658
- // --skip-overlap 同款剔除(4.5 过滤后此处残余多为 staged 口径差集,防御性同处理)
659
- if (skipOverlap && !checkOnly) {
660
- const skipSet5a = new Set(conflictDirty);
661
- for (const f of conflictDirty) {
662
- if (!result.skippedOverlapFiles.includes(f)) result.skippedOverlapFiles.push(f);
663
- }
664
- changedFiles = changedFiles.filter(f => !skipSet5a.has(f));
665
- result.changedFiles = changedFiles;
666
- result.deletedFiles = deletedFiles.filter(f => !skipSet5a.has(f));
667
- result.hashMismatchFiles = (result.hashMismatchFiles || []).filter(f => !skipSet5a.has(f));
668
- if (changedFiles.length === 0) {
669
- result.errors.push(
670
- `--skip-overlap:变更文件全部与主仓未提交改动重叠,无可应用子集:\n ${conflictDirty.join('\n ')}\n` +
671
- `请先提交/stash 主仓改动后重试。`
672
- );
673
- return result;
674
- }
675
- result.warnings = (result.warnings || []).concat([
676
- `--skip-overlap(5a 口径):再剔除 ${conflictDirty.length} 个重叠文件:${conflictDirty.join(', ')}`
677
- ]);
678
- } else {
679
- const rescueDirty5a = computeRescueDirtyFiles(projectRoot);
680
- result.rescueCommands = generateRescueCommands({
681
- changedFiles, dirtyFiles: rescueDirty5a, hashMismatchFiles: result.hashMismatchFiles,
682
- deletedFiles: result.deletedFiles, worktreePath, projectRoot,
683
- });
684
- result.errors.push(
685
- `主工作区有以下未 commit 的变更,会影响 apply:\n ${conflictDirty.join('\n ')}\n请先 commit 或 stash 这些变更。` +
686
- `或应用非重叠部分:sillyspec worktree apply ${changeName} --skip-overlap` +
687
- (result.rescueCommands.commands.length > 0 || result.rescueCommands.warnings.length > 0
688
- ? `或手动 rescue(旁路 git apply,逐文件 cp 安全子集;cp 后需手动 sillyspec worktree cleanup ${changeName}):\n` +
689
- result.rescueCommands.commands.map(c => ` ${c}`).join('\n') +
690
- (result.rescueCommands.warnings.length > 0 ? '\n' + result.rescueCommands.warnings.map(w => ` ${w}`).join('\n') : '') +
691
- `\n (共 ${result.rescueCommands.cpFileCount} 个可安全 cp,${result.rescueCommands.excludedCount} 个被排除)\n`
692
- : '')
693
- );
694
- if (!checkOnly) return result; // checkOnly 收集不短路(一次报全);真实 apply 短路
695
820
  }
696
821
  }
697
- }
698
822
 
699
- // 5b hashMismatch 计算已前移到 step3.5(Grill P0),见上
823
+ // 5b hashMismatch 计算已前移到 step3.5(Grill P0),见上
700
824
 
701
- // --- 6. checkOnly 模式:到此返回 ---
702
- if (checkOnly) {
703
- result.ok = true;
704
- return result;
705
- }
706
-
707
- // --- 7. 生成 patch 并 apply ---
708
- // 确定要包含在 patch 中的文件:有清单用「实际变更 ∩ 清单(pathMatches 容差)」,无清单用全部变更。
709
- // 口径与 classifyAllowListViolations 一致(坑 apply-glob-manifest-passes-check-but-not-patch)。
710
- const patchFiles = resolvePatchFiles(changedFiles, allowSet, hasAllowList);
825
+ // --- 6. checkOnly 模式:到此返回 ---
826
+ if (checkOnly) {
827
+ result.ok = true;
828
+ return result;
829
+ }
711
830
 
712
- // 创建临时文件
713
- const tmpDir = mkdtempSync(join(tmpdir(), 'sillyspec-patch-'));
714
- const patchPath = join(tmpDir, 'apply.patch');
715
- result.patchPath = patchPath;
831
+ // --- 7. 生成 patch 并 apply ---
832
+ // 确定要包含在 patch 中的文件:有清单用「实际变更 ∩ 清单(pathMatches 容差)」,无清单用全部变更。
833
+ // 口径与 classifyAllowListViolations 一致(坑 apply-glob-manifest-passes-check-but-not-patch)。
834
+ const patchFiles = resolvePatchFiles(changedFiles, allowSet, hasAllowList);
716
835
 
717
- try {
718
- // patch 以 Buffer 聚合:git diff --binary 对二进制/非 UTF-8 文件输出任意字节序列,
719
- // 按 utf8 string 拼接会破坏 NUL 字节成 U+FFFD → corrupt patch(git-helper.js git() 注释
720
- // 同款坑;worktree.js 的 diff 采集已是 encoding:'buffer' 正确写法)。
721
- const patchParts = [];
722
-
723
- // 分 tracked 变更和 untracked 新文件生成 patch
724
- // 批量化:一次 ls-tree(deliverableBase tree 中存在的文件)+ 一次 ls-files(index 中存在的文件)
725
- // 建集合,替代 per-file cat-file -e / ls-files --error-unmatch(原至多 2N spawn → 固定 2)。
726
- // 语义等价:cat-file -e deliverableBase:f 成功 ⟺ f 在 ls-tree deliverableBase 输出(getBlobHashMap key);
727
- // ls-files --error-unmatch f 成功 ⟺ f 在 ls-files -- 输出。
728
- // tracked 判定用 deliverableBase(集合判定侧)
729
- const inTree = getBlobHashMap(worktreePath, deliverableBase, patchFiles);
730
- const inIndexList = patchFiles.length > 0
731
- ? (gitQuiet(worktreePath, ['ls-files', '--', ...patchFiles]) || '').split('\n').filter(Boolean)
732
- : [];
733
- const inIndex = new Set(inIndexList);
734
- const trackedFiles = patchFiles.filter(f => inTree.has(f) || inIndex.has(f));
735
- const trackedSet = new Set(trackedFiles);
736
- const untrackedPatchFiles = patchFiles.filter(f => !trackedSet.has(f));
737
-
738
- // tracked 文件:git diff patchBase(patch 生成锚点,默认 merge-base)
739
- // 数组形式,文件名逐个展开为独立 argv,不经 shell;
740
- // encoding:'buffer' 保留二进制补丁原样,timeout 放大到 60s 防大 diff 超时——原裸 execSync 无 timeout
741
- if (trackedFiles.length > 0) {
742
- patchParts.push(git(
743
- worktreePath,
744
- ['diff', '--binary', patchBase, '--', ...trackedFiles],
745
- { encoding: 'buffer', timeout: 60000 }
746
- ));
747
- }
836
+ // 创建临时文件
837
+ const tmpDir = mkdtempSync(join(tmpdir(), 'sillyspec-patch-'));
838
+ const patchPath = join(tmpDir, 'apply.patch');
839
+ result.patchPath = patchPath;
748
840
 
749
- // untracked 新文件:git add 到 index,git diff --cached,然后 reset(均数组形式,文件名逐个展开)
750
- if (untrackedPatchFiles.length > 0) {
751
- git(worktreePath, ['add', '--', ...untrackedPatchFiles]);
752
- try {
753
- // encoding:'buffer' 保留二进制补丁原样,timeout 放大到 60s 防大 diff 超时
841
+ try {
842
+ // patch 以 Buffer 聚合:git diff --binary 对二进制/非 UTF-8 文件输出任意字节序列,
843
+ // 按 utf8 string 拼接会破坏 NUL 字节成 U+FFFD → corrupt patch(git-helper.js git() 注释
844
+ // 同款坑;worktree.js 的 diff 采集已是 encoding:'buffer' 正确写法)。
845
+ const patchParts = [];
846
+
847
+ // 分 tracked 变更和 untracked 新文件生成 patch
848
+ // 批量化:一次 ls-tree(deliverableBase tree 中存在的文件)+ 一次 ls-files(index 中存在的文件)
849
+ // 建集合,替代 per-file cat-file -e / ls-files --error-unmatch(原至多 2N spawn → 固定 2)。
850
+ // 语义等价:cat-file -e deliverableBase:f 成功 ⟺ f 在 ls-tree deliverableBase 输出(getBlobHashMap key);
851
+ // ls-files --error-unmatch f 成功 ⟺ f 在 ls-files -- 输出。
852
+ // tracked 判定用 deliverableBase(集合判定侧)
853
+ const inTree = getBlobHashMap(worktreePath, deliverableBase, patchFiles);
854
+ const inIndexList = patchFiles.length > 0
855
+ ? (gitQuiet(worktreePath, ['ls-files', '--', ...patchFiles]) || '').split('\n').filter(Boolean)
856
+ : [];
857
+ const inIndex = new Set(inIndexList);
858
+ const trackedFiles = patchFiles.filter(f => inTree.has(f) || inIndex.has(f));
859
+ const trackedSet = new Set(trackedFiles);
860
+ const untrackedPatchFiles = patchFiles.filter(f => !trackedSet.has(f));
861
+
862
+ // tracked 文件:git diff patchBase(patch 生成锚点,默认 merge-base)
863
+ // 数组形式,文件名逐个展开为独立 argv,不经 shell;
864
+ // encoding:'buffer' 保留二进制补丁原样,timeout 放大到 60s 防大 diff 超时——原裸 execSync 无 timeout
865
+ if (trackedFiles.length > 0) {
754
866
  patchParts.push(git(
755
867
  worktreePath,
756
- ['diff', '--binary', '--cached', '--', ...untrackedPatchFiles],
868
+ ['diff', '--binary', patchBase, '--', ...trackedFiles],
757
869
  { encoding: 'buffer', timeout: 60000 }
758
870
  ));
759
- } finally {
760
- // 重置 index(不保留 staged 状态)
761
- gitQuiet(worktreePath, ['reset', 'HEAD', '--', ...untrackedPatchFiles]);
762
871
  }
763
- }
764
872
 
765
- const patchContent = Buffer.concat(patchParts);
766
- if (patchContent.length === 0) {
767
- // patch 为空(清单中部分文件可能没实际变更)
768
- result.ok = true;
769
- rmSync(tmpDir, { recursive: true, force: true });
770
- return result;
771
- }
873
+ // untracked 新文件:git add 到 index,git diff --cached,然后 reset(均数组形式,文件名逐个展开)
874
+ if (untrackedPatchFiles.length > 0) {
875
+ git(worktreePath, ['add', '--', ...untrackedPatchFiles]);
876
+ try {
877
+ // encoding:'buffer' 保留二进制补丁原样,timeout 放大到 60s 防大 diff 超时
878
+ patchParts.push(git(
879
+ worktreePath,
880
+ ['diff', '--binary', '--cached', '--', ...untrackedPatchFiles],
881
+ { encoding: 'buffer', timeout: 60000 }
882
+ ));
883
+ } finally {
884
+ // 重置 index(不保留 staged 状态)
885
+ gitQuiet(worktreePath, ['reset', 'HEAD', '--', ...untrackedPatchFiles]);
886
+ }
887
+ }
772
888
 
773
- writeFileSync(patchPath, patchContent);
889
+ const patchContent = Buffer.concat(patchParts);
890
+ if (patchContent.length === 0) {
891
+ // patch 为空(清单中部分文件可能没实际变更)
892
+ result.ok = true;
893
+ rmSync(tmpDir, { recursive: true, force: true });
894
+ return result;
895
+ }
774
896
 
775
- // apply --check 预检失败不再拦截(--check 只测 clean apply,--3way 能处理 clean apply 失败的
776
- // 三路合并场景——主干已提交推进时 --check 恒失败但 --3way 可合)。故跳过 --check,直接试 --3way。
897
+ writeFileSync(patchPath, patchContent);
777
898
 
778
- // 回滚准备:记录 patch 涉及的 tracked 文件(--3way 冲突后需恢复 HEAD 版,不留半成品冲突标记)。
779
- // tracked 文件冲突 → git checkout -- <f> 还原;untracked 新建文件(--3way 不会对其冲突)不在回滚范围,
780
- // 但若 --3way 部分成功后冲突,已创建的新文件需删,故记录 untracked 集合。
781
- const trackedPatchFiles = patchFiles.filter(f => {
782
- // 该文件在主仓库 HEAD 存在 → 是 tracked(--3way 冲突时留标记需 checkout 还原)
783
- return gitQuiet(projectRoot, ['cat-file', '-e', `HEAD:${f}`]) === null ? false : true;
784
- });
785
- const newPatchFiles = patchFiles.filter(f => !trackedPatchFiles.includes(f));
899
+ // apply --check 预检失败不再拦截(--check 只测 clean apply,--3way 能处理 clean apply 失败的
900
+ // 三路合并场景——主干已提交推进时 --check 恒失败但 --3way 可合)。故跳过 --check,直接试 --3way。
786
901
 
787
- // apply --3way 正式应用(主干已提交推进时自动三路合并)
788
- try {
789
- git(projectRoot, ['apply', '--3way', patchPath], { timeout: 30000 });
790
- } catch (e) {
791
- // --3way 冲突(exit 1,工作区已留冲突标记):回滚到 apply 前干净状态,不留半成品
792
- // FR-06:解析 git 原始 stderr 提取冲突文件列表(不静默吞掉)
793
- const rawStderr = e.message || '';
794
- const rollback = rollbackApply(projectRoot, trackedPatchFiles, newPatchFiles, rawStderr);
795
- // autocrlf 副作用单独点名:主仓无关未提交 dirty + CRLF 转换可触发 does not match index
796
- // (非文件内容冲突,交集空时 step4.5 已放行到这里)——回滚无损,stash 后重试即可
797
- if (/does not match index/i.test(rawStderr)) {
902
+ // 回滚准备:记录 patch 涉及的 tracked 文件(--3way 冲突后需恢复 HEAD 版,不留半成品冲突标记)。
903
+ // tracked 文件冲突 → git checkout -- <f> 还原;untracked 新建文件(--3way 不会对其冲突)不在回滚范围,
904
+ // 但若 --3way 部分成功后冲突,已创建的新文件需删,故记录 untracked 集合。
905
+ const trackedPatchFiles = patchFiles.filter(f => {
906
+ // 该文件在主仓库 HEAD 存在 → 是 tracked(--3way 冲突时留标记需 checkout 还原)
907
+ return gitQuiet(projectRoot, ['cat-file', '-e', `HEAD:${f}`]) === null ? false : true;
908
+ });
909
+ const newPatchFiles = patchFiles.filter(f => !trackedPatchFiles.includes(f));
910
+
911
+ // apply --3way 正式应用(主干已提交推进时自动三路合并)
912
+ try {
913
+ git(projectRoot, ['apply', '--3way', patchPath], { timeout: 30000 });
914
+ } catch (e) {
915
+ // --3way 冲突(exit 1,工作区已留冲突标记):回滚到 apply 前干净状态,不留半成品
916
+ // FR-06:解析 git 原始 stderr 提取冲突文件列表(不静默吞掉)
917
+ const rawStderr = e.message || '';
918
+ const rollback = rollbackApply(projectRoot, trackedPatchFiles, newPatchFiles, rawStderr);
919
+ // autocrlf 副作用单独点名:主仓无关未提交 dirty + CRLF 转换可触发 does not match index
920
+ // (非文件内容冲突,交集空时 step4.5 已放行到这里)——回滚无损,stash 后重试即可
921
+ if (/does not match index/i.test(rawStderr)) {
922
+ result.errors.push(
923
+ `apply --3way 失败(does not match index):多为主仓未提交文件 + Windows autocrlf 的 CRLF 副作用触发,非文件内容冲突。\n` +
924
+ `已回滚工作区到 apply 前状态(无损,无关未提交文件未受影响)。\n` +
925
+ `处理:git stash 后重试 sillyspec worktree apply ${changeName}(手工 stash 记下 git stash list 的 SHA——pop 失败时兜底),或 --merge 兜底,或 --stash-dirty 由工具自动 stash→apply→恢复。`
926
+ );
927
+ if (rollback.error) result.warnings = (result.warnings || []).concat([`回滚警告: ${rollback.error}`]);
928
+ return result;
929
+ }
798
930
  result.errors.push(
799
- `apply --3way 失败(does not match index):多为主仓未提交文件 + Windows autocrlf 的 CRLF 副作用触发,非文件内容冲突。\n` +
800
- `已回滚工作区到 apply 前状态(无损,无关未提交文件未受影响)。\n` +
801
- `处理:git stash 后重试 sillyspec worktree apply ${changeName},或 --merge 兜底。`
931
+ `apply --3way 冲突:以下文件与主干「已提交」推进重叠,无法自动合并:\n` +
932
+ ` ${rollback.conflicts.length > 0 ? rollback.conflicts.join('\n ') : '(未能获取冲突文件列表)'}\n` +
933
+ `已回滚工作区到 apply 前状态(无半成品冲突标记)。\n` +
934
+ `可选:用 --merge 自动三方合并兜底(git merge sillyspec/${changeName},会引入合并提交):\n` +
935
+ ` sillyspec worktree apply ${changeName} --merge\n` +
936
+ `或手动解决后重试。`
802
937
  );
803
938
  if (rollback.error) result.warnings = (result.warnings || []).concat([`回滚警告: ${rollback.error}`]);
804
939
  return result;
805
940
  }
806
- result.errors.push(
807
- `apply --3way 冲突:以下文件与主干「已提交」推进重叠,无法自动合并:\n` +
808
- ` ${rollback.conflicts.length > 0 ? rollback.conflicts.join('\n ') : '(未能获取冲突文件列表)'}\n` +
809
- `已回滚工作区到 apply 前状态(无半成品冲突标记)。\n` +
810
- `可选:用 --merge 自动三方合并兜底(git merge sillyspec/${changeName},会引入合并提交):\n` +
811
- ` sillyspec worktree apply ${changeName} --merge\n` +
812
- `或手动解决后重试。`
813
- );
814
- if (rollback.error) result.warnings = (result.warnings || []).concat([`回滚警告: ${rollback.error}`]);
815
- return result;
816
- }
817
941
 
818
- result.ok = true;
942
+ result.ok = true;
819
943
 
820
- // --- 7.5 提交复用 pathspec(坑 apply-commit-pathspec-sweep,2026-08-21 实证)---
821
- // apply 后主仓常混有无关未提交文件(他者会话/并行 quick),agent 习惯 `git add <目录>/`
822
- // 会把无关文件扫进暂存需手工剔除。落盘本变更精确 pathspec 供提交直接复用:
823
- // 文件 + result 字段(CLI 输出可照抄 git add -- … / 长清单用 --pathspec-from-file)。
824
- try {
825
- const commitFiles = [...new Set(patchFiles)].sort().filter(Boolean);
826
- result.commitPathspec = commitFiles;
827
- const runtimeRoot = join(projectRoot, '.sillyspec', '.runtime');
828
- mkdirSync(runtimeRoot, { recursive: true });
829
- const pathspecFile = join(runtimeRoot, `apply-pathspec-${changeName}.txt`);
830
- writeFileSync(pathspecFile, commitFiles.join('\n') + '\n');
831
- result.pathspecFile = pathspecFile;
832
- } catch { /* pathspec 落盘失败不影响 apply 结果 */ }
833
-
834
- // --- 8. 成功后自动 cleanup(失败不影响整体结果) ---
835
- // --skip-overlap 时先查 hasUnappliedChanges:跳过文件未落主仓 → 保留 worktree(不触发
836
- // cleanup 的拦截横幅吓人,主动判断 + 温和提示);全部已落地(无跳过残留)才照常清理。
837
- // cleanup 返回值必须消费(坑 ghost-dir-junction-pierce,2026-08-23 实证:apply 后 partial
838
- // 残留被静默丢弃,用户以为已干净、人工 rm -rf 时穿透 junction 删主仓 node_modules)。
839
- const consumeCleanup = (cr) => {
840
- if (cr && (cr.result === 'partial' || (Array.isArray(cr.residual) && cr.residual.length > 0))) {
841
- result.warnings.push(
842
- `⚠️ worktree 部分清理残留(${cr.result}):${(cr.residual || []).join('; ') || 'worktree 目录'}` +
843
- `——Windows 勿直接 rm -rf(会穿透 node_modules junction 删主仓依赖):先 cmd /c rmdir "<worktree>\\node_modules" 解链再删目录,或跑 sillyspec worktree doctor --fix`
844
- )
845
- }
846
- return cr
847
- }
848
- try {
849
- if (skipOverlap) {
850
- const unapplied = wm.hasUnappliedChanges(changeName);
851
- if (unapplied.hasChanges) {
852
- const pend = unapplied.changedFiles || [];
853
- result.warnings.push(
854
- `worktree 已保留(--skip-overlap 有未应用文件):${pend.length} 个文件仍在 worktree` +
855
- `(${pend.slice(0, 5).join(', ')}${pend.length > 5 ? ' 等' : ''})——主仓提交/stash 后重新 sillyspec worktree apply ${changeName} 只应用剩余文件,或确认放弃后 sillyspec worktree cleanup ${changeName} --force`
856
- );
944
+ // --- 7.5 提交复用 pathspec(坑 apply-commit-pathspec-sweep,2026-08-21 实证)---
945
+ // apply 后主仓常混有无关未提交文件(他者会话/并行 quick),agent 习惯 `git add <目录>/`
946
+ // 会把无关文件扫进暂存需手工剔除。落盘本变更精确 pathspec 供提交直接复用:
947
+ // 文件 + result 字段(CLI 输出可照抄 git add -- … / 长清单用 --pathspec-from-file)。
948
+ try {
949
+ const commitFiles = [...new Set(patchFiles)].sort().filter(Boolean);
950
+ result.commitPathspec = commitFiles;
951
+ const runtimeRoot = join(projectRoot, '.sillyspec', '.runtime');
952
+ mkdirSync(runtimeRoot, { recursive: true });
953
+ const pathspecFile = join(runtimeRoot, `apply-pathspec-${changeName}.txt`);
954
+ writeFileSync(pathspecFile, commitFiles.join('\n') + '\n');
955
+ result.pathspecFile = pathspecFile;
956
+ } catch { /* pathspec 落盘失败不影响 apply 结果 */ }
957
+
958
+ // --- 8. 成功后自动 cleanup(失败不影响整体结果) ---
959
+ // --skip-overlap 时先查 hasUnappliedChanges:跳过文件未落主仓 → 保留 worktree(不触发
960
+ // cleanup 的拦截横幅吓人,主动判断 + 温和提示);全部已落地(无跳过残留)才照常清理。
961
+ // cleanup 返回值必须消费(坑 ghost-dir-junction-pierce,2026-08-23 实证:apply 后 partial
962
+ // 残留被静默丢弃,用户以为已干净、人工 rm -rf 时穿透 junction 删主仓 node_modules)。
963
+ // cleanup 返回值必须消费(坑 ghost-dir-junction-pierce)——实现提升为模块级 consumeCleanupResult,
964
+ // 与无变更早退 / applyByMerge 成功路径三处共用
965
+ const consumeCleanup = (cr) => consumeCleanupResult(cr, result)
966
+ try {
967
+ if (skipOverlap) {
968
+ const unapplied = wm.hasUnappliedChanges(changeName);
969
+ if (unapplied.hasChanges) {
970
+ const pend = unapplied.changedFiles || [];
971
+ result.warnings.push(
972
+ `worktree 已保留(--skip-overlap 有未应用文件):${pend.length} 个文件仍在 worktree` +
973
+ `(${pend.slice(0, 5).join(', ')}${pend.length > 5 ? ' 等' : ''})——主仓提交/stash 后重新 sillyspec worktree apply ${changeName} 只应用剩余文件,或确认放弃后 sillyspec worktree cleanup ${changeName} --force`
974
+ );
975
+ } else {
976
+ consumeCleanup(wm.cleanup(changeName, { force: true }));
977
+ }
857
978
  } else {
858
979
  consumeCleanup(wm.cleanup(changeName, { force: true }));
859
980
  }
860
- } else {
861
- consumeCleanup(wm.cleanup(changeName, { force: true }));
981
+ } catch (cleanupErr) {
982
+ result.warnings = result.warnings || [];
983
+ result.warnings.push(`cleanup 失败(不影响应用结果;Windows 手动清理先解 junction 再删,勿 rm -rf): ${cleanupErr.message}`);
862
984
  }
863
- } catch (cleanupErr) {
864
- result.warnings = result.warnings || [];
865
- result.warnings.push(`cleanup 失败(不影响应用结果;Windows 手动清理先解 junction 再删,勿 rm -rf): ${cleanupErr.message}`);
866
- }
867
985
 
868
- } catch (e) {
869
- // ENOBUFS 自动降级(坑 apply-spawnsync-enobufs,2026-08-22 实证:大 diff 的 binary patch
870
- // 超 maxBuffer 抛 ENOBUFS,此前只能 agent 手动 git merge 绕行)——git apply 路径走不通时
871
- // 自动落 applyByMerge(既有 --merge 兜底,语义同为三方合并)
872
- if (/ENOBUFS/i.test(String(e.message || e.code || ''))) {
873
- result.warnings = (result.warnings || []).concat(
874
- [`patch 生成超出进程缓冲区(ENOBUFS,超大 diff)——自动降级 git merge 路径应用`]
875
- );
876
- try {
877
- // keepConflicts:false——自动降级路径无人善后冲突状态,维持 abort 回滚干净态
878
- return applyByMerge(result, changeName, projectRoot, wm, { keepConflicts: false });
879
- } catch (mergeErr) {
880
- result.errors.push(`ENOBUFS 降级 merge 也失败: ${mergeErr.message}`);
881
- return result;
986
+ } catch (e) {
987
+ // ENOBUFS 自动降级(坑 apply-spawnsync-enobufs,2026-08-22 实证:大 diff 的 binary patch
988
+ // 超 maxBuffer 抛 ENOBUFS,此前只能 agent 手动 git merge 绕行)——git apply 路径走不通时
989
+ // 自动落 applyByMerge(既有 --merge 兜底,语义同为三方合并)
990
+ if (/ENOBUFS/i.test(String(e.message || e.code || ''))) {
991
+ result.warnings = (result.warnings || []).concat(
992
+ [`patch 生成超出进程缓冲区(ENOBUFS,超大 diff)——自动降级 git merge 路径应用`]
993
+ );
994
+ try {
995
+ // keepConflicts:false——自动降级路径无人善后冲突状态,维持 abort 回滚干净态
996
+ return applyByMerge(result, changeName, projectRoot, wm, { keepConflicts: false });
997
+ } catch (mergeErr) {
998
+ result.errors.push(`ENOBUFS 降级 merge 也失败: ${mergeErr.message}`);
999
+ return result;
1000
+ }
882
1001
  }
1002
+ result.errors.push(`patch 生成/应用异常: ${e.message}`);
1003
+ return result;
1004
+ } finally {
1005
+ // 清理临时目录
1006
+ try { rmSync(tmpDir, { recursive: true, force: true }); } catch {}
883
1007
  }
884
- result.errors.push(`patch 生成/应用异常: ${e.message}`);
1008
+
885
1009
  return result;
886
1010
  } finally {
887
- // 清理临时目录
888
- try { rmSync(tmpDir, { recursive: true, force: true }); } catch {}
1011
+ // stash 恢复(含 --merge 早退 / 各拦截 return / 异常路径——finally 全覆盖,绝不遗漏)
1012
+ if (stashInfo) restoreMainStash(projectRoot, stashInfo);
889
1013
  }
1014
+ }
890
1015
 
891
- return result;
1016
+ /**
1017
+ * --stash-dirty 的收尾恢复(applyWorktree finally 调用)。
1018
+ *
1019
+ * 语义(坑 apply-main-dirty-no-first-class / stash-pop-silent-noop,2026-08-24 用户反馈四期①②):
1020
+ * - 恢复用 `git stash apply --index`(保暂存区状态——普通 pop 会把 staged 降级为 unstaged);
1021
+ * - apply 成功后才 drop 本次条目,drop 后核验栈顶已非本 SHA(用户实证 stash pop 有静默不落地
1022
+ * 形态,退出码不可尽信);
1023
+ * - apply --index 冲突/异常 → stash 条目保留(git apply 失败不 drop),大字打印 SHA 兜底,
1024
+ * 绝不自动丢弃、绝不盲 pop 栈顶(并行外部操作可能插队,先按 SHA 校验栈顶归属)。
1025
+ * @param {string} projectRoot
1026
+ * @param {{ sha: string, marker: string }} stashInfo
1027
+ */
1028
+ function restoreMainStash(projectRoot, { sha, marker }) {
1029
+ // 栈顶归属校验按 SHA(git stash list 行不含 SHA,须 rev-parse 对比)——防并行外部操作插队后误恢复他者条目
1030
+ const headSha = (gitQuiet(projectRoot, ['rev-parse', '--verify', 'stash@{0}']) || '').trim();
1031
+ if (headSha !== sha) {
1032
+ console.error(`⚠️ stash 恢复跳过:栈顶 stash@{0} 已非本次条目(本次 ${sha},栈顶 ${headSha || '空'})——可能被并行操作消费/弹出。若本次条目仍在栈中:git stash list 找 ${sha.slice(0, 8)} 后 git stash apply --index <该ref>`);
1033
+ return;
1034
+ }
1035
+ // 两级恢复:① apply --index(保暂存区状态)——但 apply 本身会把变更留在工作区未提交,stash 树是
1036
+ // 全量快照,--index 的合并对「stash 树内但未被 stash 改动的脏文件」(正是刚 apply 落地的文件)
1037
+ // 会报 local changes would be overwritten;② 退普通 apply(内容保真恢复,staged 扁平化为
1038
+ // unstaged——诚实降级并提示重 add)。两级都失败 → 保留条目 + SHA 兜底,绝不自动丢弃。
1039
+ let restored = null // 'index' | 'plain'
1040
+ try {
1041
+ git(projectRoot, ['stash', 'apply', '--index', 'stash@{0}'], { timeout: 60000 });
1042
+ restored = 'index';
1043
+ } catch (eIndex) {
1044
+ try {
1045
+ git(projectRoot, ['stash', 'apply', 'stash@{0}'], { timeout: 60000 });
1046
+ restored = 'plain';
1047
+ console.warn(`⚠️ 暂存区状态未能完整还原(apply --index 与本次 apply 落地的未提交变更互斥),已退普通恢复——内容保真,staged 文件被扁平化为 unstaged,如需请重新 git add。原因:${String(eIndex.message || eIndex).split('\n').slice(-2)[0] || eIndex}`);
1048
+ } catch (e) {
1049
+ console.error(`⚠️ stash 恢复失败(apply 冲突或异常)——stash 条目已保留(未丢弃),SHA 兜底:${sha}`);
1050
+ console.error(` 处理:git stash list 定位条目(marker 含 "${String(marker || '').slice(0, 50)}");解决工作区冲突后 git stash apply stash@{N} 重试或人工合并;确认无需后再 git stash drop。未跟踪文件若报 already exists,比对内容后手动处理。`);
1051
+ console.error(` git 输出: ${String(e.message || e).split('\n').slice(0, 3).join('\n ')}`);
1052
+ return;
1053
+ }
1054
+ }
1055
+ try {
1056
+ git(projectRoot, ['stash', 'drop', 'stash@{0}'], { timeout: 60000 });
1057
+ // 防静默不落地(用户实证②):drop 后栈顶不得仍是本 SHA
1058
+ const headAfter = gitQuiet(projectRoot, ['rev-parse', '--verify', 'stash@{0}']);
1059
+ if (headAfter && headAfter.trim() === sha) {
1060
+ console.error(`⚠️ stash drop 未生效(栈顶仍为 ${sha})——改动应已恢复,确认 git status 后手动 git stash drop stash@{0}`);
1061
+ } else {
1062
+ console.log(`✅ 主仓在途改动已恢复(${restored === 'index' ? 'apply --index 保留暂存区状态' : '普通恢复,内容保真'})并清理 stash 条目:${sha}`);
1063
+ }
1064
+ } catch (e) {
1065
+ console.error(`⚠️ stash drop 失败(改动应已恢复)——手动 git stash drop stash@{0}(${sha}):${e.message}`);
1066
+ }
892
1067
  }
893
1068
 
894
1069
  /**
@@ -1145,7 +1320,7 @@ export function applyByMerge(result, changeName, projectRoot, wm, opts = {}) {
1145
1320
  result.errors.push(
1146
1321
  `git merge ${branch} 未执行成功——主仓有会被合并覆盖的未提交改动,git 拒绝启动合并(无冲突现场)。\n` +
1147
1322
  `git 输出: ${String(e.message || '').split('\n').slice(0, 3).join(' | ').slice(0, 300)}\n` +
1148
- `请先 commit/stash 主仓改动后重试,或用 --skip-overlap 应用非重叠子集。`
1323
+ `请先 commit/stash 主仓改动后重试,或用 --skip-overlap 应用非重叠子集,或 sillyspec worktree apply ${changeName} --stash-dirty(自动 stash→apply→恢复,保暂存区状态,SHA 兜底)。`
1149
1324
  );
1150
1325
  return result;
1151
1326
  }
@@ -1172,13 +1347,19 @@ export function applyByMerge(result, changeName, projectRoot, wm, opts = {}) {
1172
1347
 
1173
1348
  // 落地校验:merge 报成功(exit 0)不代表交付物真进 main——
1174
1349
  // 分支可能只含 baseline checkpoint(子代理改动未 commit),merge 产生空内容合并,文件零落地。
1175
- // 逐个确认 changedFiles 在 main HEAD 存在。任一缺失 → 不 cleanup(fail-open:保留 worktree 唯一副本)。
1350
+ // 落地语义按文件类型分流:普通交付文件应存在于 main HEAD;删除/rename 源文件(absentAfterMerge)
1351
+ // 应「不存在」——原实现一律要求存在,含删除文件的变更 merge 成功也恒报失败(坑 apply-merge-deleted-misjudged)。
1352
+ // 任一未按预期落地 → 不 cleanup(fail-open:保留 worktree 唯一副本)。
1176
1353
  result.merged = true;
1177
- const notLanded = changedFiles.filter(f => gitQuiet(projectRoot, ['cat-file', '-e', `HEAD:${f}`]) === null);
1354
+ const absentExpected = new Set(result.absentAfterMerge || []);
1355
+ const notLanded = changedFiles.filter(f => {
1356
+ const inHead = gitQuiet(projectRoot, ['cat-file', '-e', `HEAD:${f}`]) !== null;
1357
+ return absentExpected.has(f) ? inHead : !inHead;
1358
+ });
1178
1359
  if (notLanded.length > 0) {
1179
1360
  result.ok = false;
1180
1361
  result.errors.push(
1181
- `git merge ${branch} 报成功,但 ${notLanded.length}/${changedFiles.length} 个交付文件未出现在 main HEAD` +
1362
+ `git merge ${branch} 报成功,但 ${notLanded.length}/${changedFiles.length} 个交付文件未按预期落地 main HEAD` +
1182
1363
  `(分支可能只含 baseline checkpoint,子代理改动未 commit)。worktree 已保留(未 cleanup),` +
1183
1364
  `请用 git cherry-pick 或手动 cp 落地:\n ${notLanded.join('\n ')}`
1184
1365
  );
@@ -1188,7 +1369,7 @@ export function applyByMerge(result, changeName, projectRoot, wm, opts = {}) {
1188
1369
  result.ok = true;
1189
1370
  try { result.mergeSummary = git(projectRoot, ['log', '--oneline', '-1']); } catch {}
1190
1371
  try {
1191
- wm.cleanup(changeName, { force: true });
1372
+ consumeCleanupResult(wm.cleanup(changeName, { force: true }), result);
1192
1373
  } catch (cleanupErr) {
1193
1374
  result.warnings = result.warnings || [];
1194
1375
  result.warnings.push(`cleanup 失败(不影响 merge 结果): ${cleanupErr.message}`);
@@ -1266,20 +1447,28 @@ export function assessApplyRisk(changeName, { cwd } = {}) {
1266
1447
  const incidentalSet = new Set(
1267
1448
  parseFileChangeListDetailed(designPath).filter(e => e.incidental).map(e => e.path)
1268
1449
  );
1450
+ // review.json 声明偏差文件(坑 apply-undeclared-deviation-block):与顺带修复同等待遇——
1451
+ // reviewer 声明(已过 git 证据校验)的执行期偏差豁免 allowed_paths 严格校验,降 warning 注明来源。
1452
+ const reviewDeclaredSet = new Set(collectReviewDeclaredFiles(projectRoot, changeName).get('main') || []);
1269
1453
 
1270
- // 检查 2: 变更在 allowed_paths 内(仅在 TaskCard 存在时);顺带修复文件豁免。
1454
+ // 检查 2: 变更在 allowed_paths 内(仅在 TaskCard 存在时);顺带修复/review 声明文件豁免。
1271
1455
  // 匹配换 pathMatches(与 Gate1/plan-postcheck 同语义容差),消除原字面前缀弱匹配漂移。
1272
1456
  if (allowedPaths.size > 0) {
1273
1457
  const isIncidental = f => [...incidentalSet].some(ap => pathMatches(f, ap));
1458
+ const isReviewDeclared = f => [...reviewDeclaredSet].some(ap => pathMatches(f, ap));
1274
1459
  const outsideAll = changedFiles.filter(f => ![...allowedPaths].some(allowed => pathMatches(f, allowed)));
1275
- const outsidePaths = outsideAll.filter(f => !isIncidental(f));
1460
+ const outsidePaths = outsideAll.filter(f => !isIncidental(f) && !isReviewDeclared(f));
1276
1461
  const exempted = outsideAll.filter(f => isIncidental(f));
1462
+ const reviewExempted = outsideAll.filter(f => !isIncidental(f) && isReviewDeclared(f));
1277
1463
  if (outsidePaths.length > 0) {
1278
1464
  reasons.push(`变更文件超出 allowed_paths:\n ${outsidePaths.join('\n ')}`);
1279
1465
  }
1280
1466
  if (exempted.length > 0) {
1281
1467
  warnings.push(`顺带修复文件(已豁免 allowed_paths,来源 design §6 标记):${exempted.join(', ')}`);
1282
1468
  }
1469
+ if (reviewExempted.length > 0) {
1470
+ warnings.push(`review 声明偏差文件(已豁免 allowed_paths,来源 task review.json changedFiles,过 git 证据校验):${reviewExempted.join(', ')}`);
1471
+ }
1283
1472
  }
1284
1473
 
1285
1474
  // 检查 4+5: 高风险文件模式