sillyspec 3.27.12 → 3.28.0

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 (1207) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +214 -214
  2. package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
  3. package/.claude/skills/sillyspec-quick/SKILL.md +116 -116
  4. package/package.json +1 -1
  5. package/src/agent-session-log.js +77 -10
  6. package/src/config-schema.js +2 -2
  7. package/src/contract-matrix.js +15 -2
  8. package/src/doctor-diagnostics.js +64 -1
  9. package/src/endpoint-extractor.js +100 -24
  10. package/src/index.js +36 -5
  11. package/src/machine-interface.js +63 -0
  12. package/src/progress/stage-machine.js +106 -1
  13. package/src/progress.js +3 -0
  14. package/src/run/command.js +1 -1
  15. package/src/run/complete-handlers.js +31 -3
  16. package/src/run/complete.js +12 -4
  17. package/src/run/quick-audit.js +98 -0
  18. package/src/run/shared.js +54 -0
  19. package/src/run/stage.js +18 -11
  20. package/src/spec-sync.js +191 -14
  21. package/src/stages/execute.js +6 -2
  22. package/src/sync.js +122 -4
  23. package/src/task-review.js +51 -4
  24. package/src/verify-postcheck.js +60 -8
  25. package/src/verify-probes.js +3 -0
  26. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  27. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  28. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  29. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  30. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  31. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  32. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  33. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  34. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +0 -57
  35. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +0 -177
  36. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  37. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  38. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  39. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  40. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  41. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +0 -64
  42. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +0 -54
  43. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  44. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  45. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +0 -2
  46. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +0 -20
  47. package/.claude/worktrees/sillyspec-data-model-research/README.md +0 -203
  48. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +0 -91
  49. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +0 -2
  50. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  51. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +0 -977
  52. package/.claude/worktrees/sillyspec-data-model-research/package.json +0 -39
  53. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  54. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  55. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  56. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +0 -16
  57. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  58. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +0 -836
  59. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +0 -256
  60. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +0 -25
  61. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +0 -95
  62. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +0 -679
  63. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +0 -526
  64. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +0 -357
  65. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +0 -803
  66. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +0 -290
  67. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +0 -270
  68. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +0 -65
  69. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +0 -109
  70. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +0 -202
  71. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +0 -88
  72. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +0 -328
  73. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +0 -97
  74. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +0 -480
  75. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +0 -20
  76. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +0 -55
  77. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +0 -381
  78. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +0 -517
  79. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +0 -155
  80. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +0 -245
  81. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +0 -246
  82. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +0 -121
  83. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +0 -825
  84. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +0 -393
  85. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +0 -107
  86. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +0 -1099
  87. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +0 -420
  88. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +0 -78
  89. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +0 -73
  90. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +0 -150
  91. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +0 -130
  92. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +0 -892
  93. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +0 -2798
  94. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +0 -626
  95. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +0 -231
  96. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +0 -128
  97. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +0 -104
  98. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +0 -543
  99. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +0 -127
  100. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +0 -166
  101. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +0 -222
  102. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +0 -580
  103. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +0 -336
  104. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +0 -355
  105. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +0 -36
  106. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +0 -594
  107. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +0 -265
  108. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +0 -1304
  109. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +0 -115
  110. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +0 -852
  111. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +0 -77
  112. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +0 -1595
  113. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +0 -1552
  114. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +0 -1259
  115. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +0 -156
  116. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +0 -1084
  117. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +0 -208
  118. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +0 -128
  119. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +0 -843
  120. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +0 -186
  121. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +0 -269
  122. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +0 -1562
  123. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +0 -584
  124. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +0 -23
  125. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +0 -388
  126. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +0 -512
  127. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +0 -95
  128. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +0 -414
  129. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +0 -597
  130. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +0 -62
  131. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +0 -50
  132. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +0 -358
  133. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +0 -171
  134. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +0 -550
  135. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +0 -889
  136. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +0 -597
  137. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +0 -199
  138. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +0 -236
  139. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +0 -617
  140. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +0 -145
  141. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +0 -540
  142. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +0 -1275
  143. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +0 -43
  144. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +0 -29
  145. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +0 -514
  146. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +0 -1344
  147. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +0 -650
  148. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +0 -167
  149. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +0 -608
  150. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +0 -64
  151. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +0 -246
  152. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +0 -1470
  153. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +0 -1498
  154. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +0 -210
  155. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +0 -1718
  156. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +0 -277
  157. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +0 -19
  158. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +0 -600
  159. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +0 -125
  160. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +0 -1446
  161. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +0 -576
  162. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +0 -1715
  163. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +0 -23
  164. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +0 -28
  165. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +0 -12
  166. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +0 -32
  167. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +0 -79
  168. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +0 -132
  169. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  170. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  171. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  172. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  173. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  174. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  175. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  176. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  177. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +0 -57
  178. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +0 -177
  179. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  180. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  181. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  182. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  183. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  184. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  185. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +0 -64
  186. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +0 -54
  187. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  188. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  189. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +0 -6
  190. package/.worktrees/2c37b1d7/.gitattributes +0 -2
  191. package/.worktrees/2c37b1d7/.husky/pre-push +0 -20
  192. package/.worktrees/2c37b1d7/README.md +0 -203
  193. package/.worktrees/2c37b1d7/SKILL.md +0 -91
  194. package/.worktrees/2c37b1d7/architecture-analysis.md +0 -448
  195. package/.worktrees/2c37b1d7/bin/sillyspec.js +0 -2
  196. package/.worktrees/2c37b1d7/eval/README.md +0 -86
  197. package/.worktrees/2c37b1d7/eval/eval.config.json +0 -28
  198. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +0 -63
  199. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +0 -27
  200. package/.worktrees/2c37b1d7/eval/lib/config.mjs +0 -82
  201. package/.worktrees/2c37b1d7/eval/lib/db.mjs +0 -76
  202. package/.worktrees/2c37b1d7/eval/lib/report.mjs +0 -120
  203. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +0 -157
  204. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +0 -73
  205. package/.worktrees/2c37b1d7/eval/lib/util.mjs +0 -107
  206. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +0 -30
  207. package/.worktrees/2c37b1d7/eval/run.mjs +0 -83
  208. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +0 -6
  209. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  210. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +0 -6
  211. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +0 -28
  212. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +0 -6
  213. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  214. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  215. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +0 -6
  216. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +0 -31
  217. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  218. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +0 -6
  219. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  220. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +0 -6
  221. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +0 -38
  222. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  223. package/.worktrees/2c37b1d7/package-lock.json +0 -977
  224. package/.worktrees/2c37b1d7/package.json +0 -41
  225. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  226. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  227. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  228. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +0 -16
  229. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  230. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +0 -836
  231. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +0 -256
  232. package/.worktrees/2c37b1d7/packages/dashboard/package.json +0 -25
  233. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +0 -95
  234. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +0 -679
  235. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +0 -526
  236. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +0 -357
  237. package/.worktrees/2c37b1d7/src/agent-session-log.js +0 -803
  238. package/.worktrees/2c37b1d7/src/change-list.js +0 -290
  239. package/.worktrees/2c37b1d7/src/change-risk-profile.js +0 -339
  240. package/.worktrees/2c37b1d7/src/check-primitives.js +0 -65
  241. package/.worktrees/2c37b1d7/src/classify-change.js +0 -109
  242. package/.worktrees/2c37b1d7/src/commit-suggest.js +0 -202
  243. package/.worktrees/2c37b1d7/src/config-cat.js +0 -88
  244. package/.worktrees/2c37b1d7/src/config-schema.js +0 -328
  245. package/.worktrees/2c37b1d7/src/constants.js +0 -97
  246. package/.worktrees/2c37b1d7/src/contract-matrix.js +0 -533
  247. package/.worktrees/2c37b1d7/src/datetime.js +0 -20
  248. package/.worktrees/2c37b1d7/src/db-engine.js +0 -55
  249. package/.worktrees/2c37b1d7/src/db.js +0 -381
  250. package/.worktrees/2c37b1d7/src/decision-distill.js +0 -517
  251. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +0 -155
  252. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +0 -245
  253. package/.worktrees/2c37b1d7/src/dispatch/probe.js +0 -246
  254. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +0 -121
  255. package/.worktrees/2c37b1d7/src/docs-check.js +0 -825
  256. package/.worktrees/2c37b1d7/src/docs-debt.js +0 -393
  257. package/.worktrees/2c37b1d7/src/docs-gate.js +0 -107
  258. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +0 -1099
  259. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +0 -409
  260. package/.worktrees/2c37b1d7/src/foreign-declared.js +0 -155
  261. package/.worktrees/2c37b1d7/src/fs-atomic.js +0 -73
  262. package/.worktrees/2c37b1d7/src/git-helper.js +0 -150
  263. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +0 -130
  264. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +0 -892
  265. package/.worktrees/2c37b1d7/src/index.js +0 -2854
  266. package/.worktrees/2c37b1d7/src/init.js +0 -626
  267. package/.worktrees/2c37b1d7/src/knowledge-match.js +0 -231
  268. package/.worktrees/2c37b1d7/src/local-detect.js +0 -128
  269. package/.worktrees/2c37b1d7/src/local-register.js +0 -104
  270. package/.worktrees/2c37b1d7/src/machine-interface.js +0 -543
  271. package/.worktrees/2c37b1d7/src/migrate.js +0 -127
  272. package/.worktrees/2c37b1d7/src/module-impact.js +0 -166
  273. package/.worktrees/2c37b1d7/src/module-resolve.js +0 -222
  274. package/.worktrees/2c37b1d7/src/modules.js +0 -580
  275. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +0 -126
  276. package/.worktrees/2c37b1d7/src/progress/change-registry.js +0 -336
  277. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +0 -355
  278. package/.worktrees/2c37b1d7/src/progress/shared.js +0 -36
  279. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +0 -594
  280. package/.worktrees/2c37b1d7/src/progress/step-store.js +0 -265
  281. package/.worktrees/2c37b1d7/src/progress.js +0 -1304
  282. package/.worktrees/2c37b1d7/src/quick-recommend.js +0 -115
  283. package/.worktrees/2c37b1d7/src/quicklog.js +0 -883
  284. package/.worktrees/2c37b1d7/src/review-tier.js +0 -77
  285. package/.worktrees/2c37b1d7/src/run/command.js +0 -1641
  286. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +0 -1552
  287. package/.worktrees/2c37b1d7/src/run/complete.js +0 -1259
  288. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +0 -156
  289. package/.worktrees/2c37b1d7/src/run/gates.js +0 -1111
  290. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +0 -208
  291. package/.worktrees/2c37b1d7/src/run/next.js +0 -128
  292. package/.worktrees/2c37b1d7/src/run/prompt.js +0 -843
  293. package/.worktrees/2c37b1d7/src/run/quick-audit.js +0 -186
  294. package/.worktrees/2c37b1d7/src/run/scan-profile.js +0 -269
  295. package/.worktrees/2c37b1d7/src/run/shared.js +0 -1562
  296. package/.worktrees/2c37b1d7/src/run/stage.js +0 -587
  297. package/.worktrees/2c37b1d7/src/run.js +0 -23
  298. package/.worktrees/2c37b1d7/src/scan-diff.js +0 -388
  299. package/.worktrees/2c37b1d7/src/scan-postcheck.js +0 -524
  300. package/.worktrees/2c37b1d7/src/scan-staleness.js +0 -95
  301. package/.worktrees/2c37b1d7/src/setup.js +0 -414
  302. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +0 -597
  303. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +0 -62
  304. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +0 -50
  305. package/.worktrees/2c37b1d7/src/spec-sync.js +0 -358
  306. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +0 -171
  307. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +0 -551
  308. package/.worktrees/2c37b1d7/src/stage-contract.js +0 -948
  309. package/.worktrees/2c37b1d7/src/stage-review.js +0 -597
  310. package/.worktrees/2c37b1d7/src/stages/archive.js +0 -199
  311. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +0 -285
  312. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +0 -624
  313. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +0 -145
  314. package/.worktrees/2c37b1d7/src/stages/doctor.js +0 -540
  315. package/.worktrees/2c37b1d7/src/stages/execute.js +0 -1277
  316. package/.worktrees/2c37b1d7/src/stages/explore.js +0 -43
  317. package/.worktrees/2c37b1d7/src/stages/index.js +0 -29
  318. package/.worktrees/2c37b1d7/src/stages/knowledge.js +0 -514
  319. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +0 -1398
  320. package/.worktrees/2c37b1d7/src/stages/plan.js +0 -655
  321. package/.worktrees/2c37b1d7/src/stages/quick.js +0 -167
  322. package/.worktrees/2c37b1d7/src/stages/scan.js +0 -608
  323. package/.worktrees/2c37b1d7/src/stages/status.js +0 -64
  324. package/.worktrees/2c37b1d7/src/stages/verify.js +0 -246
  325. package/.worktrees/2c37b1d7/src/sync.js +0 -1470
  326. package/.worktrees/2c37b1d7/src/task-review.js +0 -1498
  327. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +0 -21
  328. package/.worktrees/2c37b1d7/src/taskcard.js +0 -250
  329. package/.worktrees/2c37b1d7/src/verify-postcheck.js +0 -1718
  330. package/.worktrees/2c37b1d7/src/verify-probes.js +0 -327
  331. package/.worktrees/2c37b1d7/src/version.js +0 -19
  332. package/.worktrees/2c37b1d7/src/workflow.js +0 -600
  333. package/.worktrees/2c37b1d7/src/workspace.js +0 -125
  334. package/.worktrees/2c37b1d7/src/worktree-apply.js +0 -1611
  335. package/.worktrees/2c37b1d7/src/worktree-deps.js +0 -668
  336. package/.worktrees/2c37b1d7/src/worktree.js +0 -1849
  337. package/.worktrees/2c37b1d7/templates/claude-instruction.md +0 -23
  338. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +0 -29
  339. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +0 -12
  340. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +0 -32
  341. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +0 -79
  342. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +0 -132
  343. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  344. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  345. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  346. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  347. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  348. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  349. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  350. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  351. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +0 -57
  352. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +0 -177
  353. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  354. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  355. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  356. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  357. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  358. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +0 -64
  359. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +0 -54
  360. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  361. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  362. package/.worktrees/542c4415/.gitattributes +0 -2
  363. package/.worktrees/542c4415/.husky/pre-push +0 -20
  364. package/.worktrees/542c4415/README.md +0 -203
  365. package/.worktrees/542c4415/SKILL.md +0 -91
  366. package/.worktrees/542c4415/architecture-analysis.md +0 -448
  367. package/.worktrees/542c4415/bin/sillyspec.js +0 -2
  368. package/.worktrees/542c4415/eval/README.md +0 -86
  369. package/.worktrees/542c4415/eval/eval.config.json +0 -28
  370. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +0 -63
  371. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +0 -27
  372. package/.worktrees/542c4415/eval/lib/config.mjs +0 -82
  373. package/.worktrees/542c4415/eval/lib/db.mjs +0 -76
  374. package/.worktrees/542c4415/eval/lib/report.mjs +0 -120
  375. package/.worktrees/542c4415/eval/lib/runner.mjs +0 -157
  376. package/.worktrees/542c4415/eval/lib/tasks.mjs +0 -73
  377. package/.worktrees/542c4415/eval/lib/util.mjs +0 -107
  378. package/.worktrees/542c4415/eval/lib/workdir.mjs +0 -30
  379. package/.worktrees/542c4415/eval/run.mjs +0 -83
  380. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +0 -6
  381. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  382. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +0 -6
  383. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +0 -28
  384. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +0 -6
  385. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  386. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  387. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +0 -6
  388. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +0 -31
  389. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  390. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +0 -6
  391. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  392. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +0 -6
  393. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +0 -38
  394. package/.worktrees/542c4415/logo.jpg +0 -0
  395. package/.worktrees/542c4415/package-lock.json +0 -977
  396. package/.worktrees/542c4415/package.json +0 -41
  397. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  398. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  399. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  400. package/.worktrees/542c4415/packages/dashboard/dist/index.html +0 -16
  401. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  402. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +0 -836
  403. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +0 -256
  404. package/.worktrees/542c4415/packages/dashboard/package.json +0 -25
  405. package/.worktrees/542c4415/packages/dashboard/server/executor.js +0 -95
  406. package/.worktrees/542c4415/packages/dashboard/server/index.js +0 -679
  407. package/.worktrees/542c4415/packages/dashboard/server/parser.js +0 -526
  408. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +0 -357
  409. package/.worktrees/542c4415/src/agent-session-log.js +0 -803
  410. package/.worktrees/542c4415/src/change-list.js +0 -290
  411. package/.worktrees/542c4415/src/change-risk-profile.js +0 -339
  412. package/.worktrees/542c4415/src/check-primitives.js +0 -65
  413. package/.worktrees/542c4415/src/classify-change.js +0 -109
  414. package/.worktrees/542c4415/src/commit-suggest.js +0 -202
  415. package/.worktrees/542c4415/src/config-cat.js +0 -88
  416. package/.worktrees/542c4415/src/config-schema.js +0 -328
  417. package/.worktrees/542c4415/src/constants.js +0 -97
  418. package/.worktrees/542c4415/src/contract-matrix.js +0 -533
  419. package/.worktrees/542c4415/src/datetime.js +0 -20
  420. package/.worktrees/542c4415/src/db-engine.js +0 -55
  421. package/.worktrees/542c4415/src/db.js +0 -381
  422. package/.worktrees/542c4415/src/decision-distill.js +0 -517
  423. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +0 -155
  424. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +0 -245
  425. package/.worktrees/542c4415/src/dispatch/probe.js +0 -246
  426. package/.worktrees/542c4415/src/dispatch/strategy.js +0 -121
  427. package/.worktrees/542c4415/src/docs-check.js +0 -825
  428. package/.worktrees/542c4415/src/docs-debt.js +0 -393
  429. package/.worktrees/542c4415/src/docs-gate.js +0 -107
  430. package/.worktrees/542c4415/src/doctor-diagnostics.js +0 -1099
  431. package/.worktrees/542c4415/src/endpoint-extractor.js +0 -409
  432. package/.worktrees/542c4415/src/foreign-declared.js +0 -155
  433. package/.worktrees/542c4415/src/fs-atomic.js +0 -73
  434. package/.worktrees/542c4415/src/git-helper.js +0 -150
  435. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +0 -130
  436. package/.worktrees/542c4415/src/hooks/worktree-guard.js +0 -892
  437. package/.worktrees/542c4415/src/index.js +0 -2854
  438. package/.worktrees/542c4415/src/init.js +0 -626
  439. package/.worktrees/542c4415/src/knowledge-match.js +0 -231
  440. package/.worktrees/542c4415/src/local-detect.js +0 -128
  441. package/.worktrees/542c4415/src/local-register.js +0 -104
  442. package/.worktrees/542c4415/src/machine-interface.js +0 -543
  443. package/.worktrees/542c4415/src/migrate.js +0 -127
  444. package/.worktrees/542c4415/src/module-impact.js +0 -166
  445. package/.worktrees/542c4415/src/module-resolve.js +0 -222
  446. package/.worktrees/542c4415/src/modules.js +0 -580
  447. package/.worktrees/542c4415/src/plan-adopt-waves.js +0 -126
  448. package/.worktrees/542c4415/src/progress/change-registry.js +0 -336
  449. package/.worktrees/542c4415/src/progress/consistency-doctor.js +0 -355
  450. package/.worktrees/542c4415/src/progress/shared.js +0 -36
  451. package/.worktrees/542c4415/src/progress/stage-machine.js +0 -594
  452. package/.worktrees/542c4415/src/progress/step-store.js +0 -265
  453. package/.worktrees/542c4415/src/progress.js +0 -1304
  454. package/.worktrees/542c4415/src/quick-recommend.js +0 -115
  455. package/.worktrees/542c4415/src/quicklog.js +0 -883
  456. package/.worktrees/542c4415/src/review-tier.js +0 -77
  457. package/.worktrees/542c4415/src/run/command.js +0 -1641
  458. package/.worktrees/542c4415/src/run/complete-handlers.js +0 -1552
  459. package/.worktrees/542c4415/src/run/complete.js +0 -1259
  460. package/.worktrees/542c4415/src/run/concurrent-detect.js +0 -156
  461. package/.worktrees/542c4415/src/run/gates.js +0 -1111
  462. package/.worktrees/542c4415/src/run/multi-repo-context.js +0 -208
  463. package/.worktrees/542c4415/src/run/next.js +0 -128
  464. package/.worktrees/542c4415/src/run/prompt.js +0 -843
  465. package/.worktrees/542c4415/src/run/quick-audit.js +0 -186
  466. package/.worktrees/542c4415/src/run/scan-profile.js +0 -269
  467. package/.worktrees/542c4415/src/run/shared.js +0 -1562
  468. package/.worktrees/542c4415/src/run/stage.js +0 -587
  469. package/.worktrees/542c4415/src/run.js +0 -23
  470. package/.worktrees/542c4415/src/scan-diff.js +0 -388
  471. package/.worktrees/542c4415/src/scan-postcheck.js +0 -524
  472. package/.worktrees/542c4415/src/scan-staleness.js +0 -95
  473. package/.worktrees/542c4415/src/setup.js +0 -414
  474. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +0 -597
  475. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +0 -62
  476. package/.worktrees/542c4415/src/spec-dir-typo.js +0 -50
  477. package/.worktrees/542c4415/src/spec-sync.js +0 -358
  478. package/.worktrees/542c4415/src/stage-contract-engine.js +0 -171
  479. package/.worktrees/542c4415/src/stage-contract-spec.js +0 -551
  480. package/.worktrees/542c4415/src/stage-contract.js +0 -948
  481. package/.worktrees/542c4415/src/stage-review.js +0 -597
  482. package/.worktrees/542c4415/src/stages/archive.js +0 -199
  483. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +0 -285
  484. package/.worktrees/542c4415/src/stages/brainstorm.js +0 -624
  485. package/.worktrees/542c4415/src/stages/cmd-existence.js +0 -145
  486. package/.worktrees/542c4415/src/stages/doctor.js +0 -540
  487. package/.worktrees/542c4415/src/stages/execute.js +0 -1277
  488. package/.worktrees/542c4415/src/stages/explore.js +0 -43
  489. package/.worktrees/542c4415/src/stages/index.js +0 -29
  490. package/.worktrees/542c4415/src/stages/knowledge.js +0 -514
  491. package/.worktrees/542c4415/src/stages/plan-postcheck.js +0 -1398
  492. package/.worktrees/542c4415/src/stages/plan.js +0 -655
  493. package/.worktrees/542c4415/src/stages/quick.js +0 -167
  494. package/.worktrees/542c4415/src/stages/scan.js +0 -608
  495. package/.worktrees/542c4415/src/stages/status.js +0 -64
  496. package/.worktrees/542c4415/src/stages/verify.js +0 -246
  497. package/.worktrees/542c4415/src/sync.js +0 -1470
  498. package/.worktrees/542c4415/src/task-review.js +0 -1498
  499. package/.worktrees/542c4415/src/taskcard-placeholders.js +0 -21
  500. package/.worktrees/542c4415/src/taskcard.js +0 -250
  501. package/.worktrees/542c4415/src/verify-postcheck.js +0 -1718
  502. package/.worktrees/542c4415/src/verify-probes.js +0 -327
  503. package/.worktrees/542c4415/src/version.js +0 -19
  504. package/.worktrees/542c4415/src/workflow.js +0 -600
  505. package/.worktrees/542c4415/src/workspace.js +0 -125
  506. package/.worktrees/542c4415/src/worktree-apply.js +0 -1611
  507. package/.worktrees/542c4415/src/worktree-deps.js +0 -668
  508. package/.worktrees/542c4415/src/worktree.js +0 -1849
  509. package/.worktrees/542c4415/templates/claude-instruction.md +0 -23
  510. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +0 -29
  511. package/.worktrees/542c4415/templates/prompts/testcase-design.md +0 -12
  512. package/.worktrees/542c4415/templates/prompts/verify-probes.md +0 -32
  513. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +0 -79
  514. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +0 -132
  515. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  516. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  517. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  518. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  519. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  520. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  521. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  522. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  523. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +0 -57
  524. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +0 -177
  525. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  526. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  527. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  528. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  529. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  530. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  531. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +0 -64
  532. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +0 -54
  533. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  534. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  535. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +0 -6
  536. package/.worktrees/8d2d0392/.gitattributes +0 -2
  537. package/.worktrees/8d2d0392/.husky/pre-push +0 -20
  538. package/.worktrees/8d2d0392/README.md +0 -203
  539. package/.worktrees/8d2d0392/SKILL.md +0 -91
  540. package/.worktrees/8d2d0392/architecture-analysis.md +0 -448
  541. package/.worktrees/8d2d0392/bin/sillyspec.js +0 -2
  542. package/.worktrees/8d2d0392/eval/README.md +0 -86
  543. package/.worktrees/8d2d0392/eval/eval.config.json +0 -28
  544. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +0 -63
  545. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +0 -27
  546. package/.worktrees/8d2d0392/eval/lib/config.mjs +0 -82
  547. package/.worktrees/8d2d0392/eval/lib/db.mjs +0 -76
  548. package/.worktrees/8d2d0392/eval/lib/report.mjs +0 -120
  549. package/.worktrees/8d2d0392/eval/lib/runner.mjs +0 -157
  550. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +0 -73
  551. package/.worktrees/8d2d0392/eval/lib/util.mjs +0 -107
  552. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +0 -30
  553. package/.worktrees/8d2d0392/eval/run.mjs +0 -83
  554. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +0 -6
  555. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  556. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +0 -6
  557. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +0 -28
  558. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +0 -6
  559. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  560. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  561. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +0 -6
  562. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +0 -31
  563. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  564. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +0 -6
  565. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  566. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +0 -6
  567. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +0 -38
  568. package/.worktrees/8d2d0392/logo.jpg +0 -0
  569. package/.worktrees/8d2d0392/package-lock.json +0 -977
  570. package/.worktrees/8d2d0392/package.json +0 -41
  571. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  572. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  573. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  574. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +0 -16
  575. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  576. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +0 -836
  577. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +0 -256
  578. package/.worktrees/8d2d0392/packages/dashboard/package.json +0 -25
  579. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +0 -95
  580. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +0 -679
  581. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +0 -526
  582. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +0 -357
  583. package/.worktrees/8d2d0392/src/agent-session-log.js +0 -803
  584. package/.worktrees/8d2d0392/src/change-list.js +0 -290
  585. package/.worktrees/8d2d0392/src/change-risk-profile.js +0 -339
  586. package/.worktrees/8d2d0392/src/check-primitives.js +0 -65
  587. package/.worktrees/8d2d0392/src/classify-change.js +0 -109
  588. package/.worktrees/8d2d0392/src/commit-suggest.js +0 -202
  589. package/.worktrees/8d2d0392/src/config-cat.js +0 -88
  590. package/.worktrees/8d2d0392/src/config-schema.js +0 -328
  591. package/.worktrees/8d2d0392/src/constants.js +0 -97
  592. package/.worktrees/8d2d0392/src/contract-matrix.js +0 -533
  593. package/.worktrees/8d2d0392/src/datetime.js +0 -20
  594. package/.worktrees/8d2d0392/src/db-engine.js +0 -55
  595. package/.worktrees/8d2d0392/src/db.js +0 -381
  596. package/.worktrees/8d2d0392/src/decision-distill.js +0 -517
  597. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +0 -155
  598. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +0 -245
  599. package/.worktrees/8d2d0392/src/dispatch/probe.js +0 -246
  600. package/.worktrees/8d2d0392/src/dispatch/strategy.js +0 -121
  601. package/.worktrees/8d2d0392/src/docs-check.js +0 -825
  602. package/.worktrees/8d2d0392/src/docs-debt.js +0 -393
  603. package/.worktrees/8d2d0392/src/docs-gate.js +0 -107
  604. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +0 -1099
  605. package/.worktrees/8d2d0392/src/endpoint-extractor.js +0 -409
  606. package/.worktrees/8d2d0392/src/foreign-declared.js +0 -78
  607. package/.worktrees/8d2d0392/src/fs-atomic.js +0 -73
  608. package/.worktrees/8d2d0392/src/git-helper.js +0 -150
  609. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +0 -130
  610. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +0 -892
  611. package/.worktrees/8d2d0392/src/index.js +0 -2854
  612. package/.worktrees/8d2d0392/src/init.js +0 -626
  613. package/.worktrees/8d2d0392/src/knowledge-match.js +0 -231
  614. package/.worktrees/8d2d0392/src/local-detect.js +0 -128
  615. package/.worktrees/8d2d0392/src/local-register.js +0 -104
  616. package/.worktrees/8d2d0392/src/machine-interface.js +0 -543
  617. package/.worktrees/8d2d0392/src/migrate.js +0 -127
  618. package/.worktrees/8d2d0392/src/module-impact.js +0 -166
  619. package/.worktrees/8d2d0392/src/module-resolve.js +0 -222
  620. package/.worktrees/8d2d0392/src/modules.js +0 -580
  621. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +0 -126
  622. package/.worktrees/8d2d0392/src/progress/change-registry.js +0 -336
  623. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +0 -355
  624. package/.worktrees/8d2d0392/src/progress/shared.js +0 -36
  625. package/.worktrees/8d2d0392/src/progress/stage-machine.js +0 -594
  626. package/.worktrees/8d2d0392/src/progress/step-store.js +0 -265
  627. package/.worktrees/8d2d0392/src/progress.js +0 -1304
  628. package/.worktrees/8d2d0392/src/quick-recommend.js +0 -115
  629. package/.worktrees/8d2d0392/src/quicklog.js +0 -883
  630. package/.worktrees/8d2d0392/src/review-tier.js +0 -77
  631. package/.worktrees/8d2d0392/src/run/command.js +0 -1641
  632. package/.worktrees/8d2d0392/src/run/complete-handlers.js +0 -1552
  633. package/.worktrees/8d2d0392/src/run/complete.js +0 -1259
  634. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +0 -156
  635. package/.worktrees/8d2d0392/src/run/gates.js +0 -1094
  636. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +0 -208
  637. package/.worktrees/8d2d0392/src/run/next.js +0 -128
  638. package/.worktrees/8d2d0392/src/run/prompt.js +0 -843
  639. package/.worktrees/8d2d0392/src/run/quick-audit.js +0 -186
  640. package/.worktrees/8d2d0392/src/run/scan-profile.js +0 -269
  641. package/.worktrees/8d2d0392/src/run/shared.js +0 -1562
  642. package/.worktrees/8d2d0392/src/run/stage.js +0 -587
  643. package/.worktrees/8d2d0392/src/run.js +0 -23
  644. package/.worktrees/8d2d0392/src/scan-diff.js +0 -388
  645. package/.worktrees/8d2d0392/src/scan-postcheck.js +0 -524
  646. package/.worktrees/8d2d0392/src/scan-staleness.js +0 -95
  647. package/.worktrees/8d2d0392/src/setup.js +0 -414
  648. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +0 -597
  649. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +0 -62
  650. package/.worktrees/8d2d0392/src/spec-dir-typo.js +0 -50
  651. package/.worktrees/8d2d0392/src/spec-sync.js +0 -358
  652. package/.worktrees/8d2d0392/src/stage-contract-engine.js +0 -171
  653. package/.worktrees/8d2d0392/src/stage-contract-spec.js +0 -551
  654. package/.worktrees/8d2d0392/src/stage-contract.js +0 -948
  655. package/.worktrees/8d2d0392/src/stage-review.js +0 -597
  656. package/.worktrees/8d2d0392/src/stages/archive.js +0 -199
  657. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +0 -285
  658. package/.worktrees/8d2d0392/src/stages/brainstorm.js +0 -624
  659. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +0 -145
  660. package/.worktrees/8d2d0392/src/stages/doctor.js +0 -540
  661. package/.worktrees/8d2d0392/src/stages/execute.js +0 -1277
  662. package/.worktrees/8d2d0392/src/stages/explore.js +0 -43
  663. package/.worktrees/8d2d0392/src/stages/index.js +0 -29
  664. package/.worktrees/8d2d0392/src/stages/knowledge.js +0 -514
  665. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +0 -1398
  666. package/.worktrees/8d2d0392/src/stages/plan.js +0 -651
  667. package/.worktrees/8d2d0392/src/stages/quick.js +0 -167
  668. package/.worktrees/8d2d0392/src/stages/scan.js +0 -608
  669. package/.worktrees/8d2d0392/src/stages/status.js +0 -64
  670. package/.worktrees/8d2d0392/src/stages/verify.js +0 -246
  671. package/.worktrees/8d2d0392/src/sync.js +0 -1470
  672. package/.worktrees/8d2d0392/src/task-review.js +0 -1498
  673. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +0 -21
  674. package/.worktrees/8d2d0392/src/taskcard.js +0 -217
  675. package/.worktrees/8d2d0392/src/verify-postcheck.js +0 -1718
  676. package/.worktrees/8d2d0392/src/verify-probes.js +0 -327
  677. package/.worktrees/8d2d0392/src/version.js +0 -19
  678. package/.worktrees/8d2d0392/src/workflow.js +0 -600
  679. package/.worktrees/8d2d0392/src/workspace.js +0 -125
  680. package/.worktrees/8d2d0392/src/worktree-apply.js +0 -1611
  681. package/.worktrees/8d2d0392/src/worktree-deps.js +0 -576
  682. package/.worktrees/8d2d0392/src/worktree.js +0 -1838
  683. package/.worktrees/8d2d0392/templates/claude-instruction.md +0 -23
  684. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +0 -29
  685. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +0 -12
  686. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +0 -32
  687. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +0 -79
  688. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +0 -132
  689. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  690. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  691. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  692. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  693. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  694. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  695. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  696. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  697. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +0 -57
  698. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +0 -177
  699. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  700. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  701. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  702. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  703. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  704. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +0 -64
  705. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +0 -54
  706. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  707. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  708. package/.worktrees/c1eae35e/.gitattributes +0 -2
  709. package/.worktrees/c1eae35e/.husky/pre-push +0 -20
  710. package/.worktrees/c1eae35e/README.md +0 -203
  711. package/.worktrees/c1eae35e/SKILL.md +0 -91
  712. package/.worktrees/c1eae35e/architecture-analysis.md +0 -448
  713. package/.worktrees/c1eae35e/bin/sillyspec.js +0 -2
  714. package/.worktrees/c1eae35e/eval/README.md +0 -86
  715. package/.worktrees/c1eae35e/eval/eval.config.json +0 -28
  716. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +0 -63
  717. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +0 -27
  718. package/.worktrees/c1eae35e/eval/lib/config.mjs +0 -82
  719. package/.worktrees/c1eae35e/eval/lib/db.mjs +0 -76
  720. package/.worktrees/c1eae35e/eval/lib/report.mjs +0 -120
  721. package/.worktrees/c1eae35e/eval/lib/runner.mjs +0 -157
  722. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +0 -73
  723. package/.worktrees/c1eae35e/eval/lib/util.mjs +0 -107
  724. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +0 -30
  725. package/.worktrees/c1eae35e/eval/run.mjs +0 -83
  726. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +0 -6
  727. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  728. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +0 -6
  729. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +0 -28
  730. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +0 -6
  731. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  732. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  733. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +0 -6
  734. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +0 -31
  735. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  736. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +0 -6
  737. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  738. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +0 -6
  739. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +0 -38
  740. package/.worktrees/c1eae35e/logo.jpg +0 -0
  741. package/.worktrees/c1eae35e/package-lock.json +0 -977
  742. package/.worktrees/c1eae35e/package.json +0 -41
  743. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  744. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  745. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  746. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +0 -16
  747. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  748. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +0 -836
  749. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +0 -256
  750. package/.worktrees/c1eae35e/packages/dashboard/package.json +0 -25
  751. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +0 -95
  752. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +0 -679
  753. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +0 -526
  754. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +0 -357
  755. package/.worktrees/c1eae35e/src/agent-session-log.js +0 -803
  756. package/.worktrees/c1eae35e/src/change-list.js +0 -290
  757. package/.worktrees/c1eae35e/src/change-risk-profile.js +0 -339
  758. package/.worktrees/c1eae35e/src/check-primitives.js +0 -65
  759. package/.worktrees/c1eae35e/src/classify-change.js +0 -109
  760. package/.worktrees/c1eae35e/src/commit-suggest.js +0 -202
  761. package/.worktrees/c1eae35e/src/config-cat.js +0 -88
  762. package/.worktrees/c1eae35e/src/config-schema.js +0 -328
  763. package/.worktrees/c1eae35e/src/constants.js +0 -97
  764. package/.worktrees/c1eae35e/src/contract-matrix.js +0 -533
  765. package/.worktrees/c1eae35e/src/datetime.js +0 -20
  766. package/.worktrees/c1eae35e/src/db-engine.js +0 -55
  767. package/.worktrees/c1eae35e/src/db.js +0 -381
  768. package/.worktrees/c1eae35e/src/decision-distill.js +0 -517
  769. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +0 -155
  770. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +0 -245
  771. package/.worktrees/c1eae35e/src/dispatch/probe.js +0 -246
  772. package/.worktrees/c1eae35e/src/dispatch/strategy.js +0 -121
  773. package/.worktrees/c1eae35e/src/docs-check.js +0 -825
  774. package/.worktrees/c1eae35e/src/docs-debt.js +0 -393
  775. package/.worktrees/c1eae35e/src/docs-gate.js +0 -107
  776. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +0 -1099
  777. package/.worktrees/c1eae35e/src/endpoint-extractor.js +0 -409
  778. package/.worktrees/c1eae35e/src/foreign-declared.js +0 -155
  779. package/.worktrees/c1eae35e/src/fs-atomic.js +0 -73
  780. package/.worktrees/c1eae35e/src/git-helper.js +0 -150
  781. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +0 -130
  782. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +0 -892
  783. package/.worktrees/c1eae35e/src/index.js +0 -2854
  784. package/.worktrees/c1eae35e/src/init.js +0 -626
  785. package/.worktrees/c1eae35e/src/knowledge-match.js +0 -231
  786. package/.worktrees/c1eae35e/src/local-detect.js +0 -128
  787. package/.worktrees/c1eae35e/src/local-register.js +0 -104
  788. package/.worktrees/c1eae35e/src/machine-interface.js +0 -543
  789. package/.worktrees/c1eae35e/src/migrate.js +0 -127
  790. package/.worktrees/c1eae35e/src/module-impact.js +0 -166
  791. package/.worktrees/c1eae35e/src/module-resolve.js +0 -222
  792. package/.worktrees/c1eae35e/src/modules.js +0 -580
  793. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +0 -126
  794. package/.worktrees/c1eae35e/src/progress/change-registry.js +0 -336
  795. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +0 -355
  796. package/.worktrees/c1eae35e/src/progress/shared.js +0 -36
  797. package/.worktrees/c1eae35e/src/progress/stage-machine.js +0 -594
  798. package/.worktrees/c1eae35e/src/progress/step-store.js +0 -265
  799. package/.worktrees/c1eae35e/src/progress.js +0 -1304
  800. package/.worktrees/c1eae35e/src/quick-recommend.js +0 -115
  801. package/.worktrees/c1eae35e/src/quicklog.js +0 -883
  802. package/.worktrees/c1eae35e/src/review-tier.js +0 -77
  803. package/.worktrees/c1eae35e/src/run/command.js +0 -1641
  804. package/.worktrees/c1eae35e/src/run/complete-handlers.js +0 -1552
  805. package/.worktrees/c1eae35e/src/run/complete.js +0 -1259
  806. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +0 -156
  807. package/.worktrees/c1eae35e/src/run/gates.js +0 -1111
  808. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +0 -208
  809. package/.worktrees/c1eae35e/src/run/next.js +0 -128
  810. package/.worktrees/c1eae35e/src/run/prompt.js +0 -843
  811. package/.worktrees/c1eae35e/src/run/quick-audit.js +0 -186
  812. package/.worktrees/c1eae35e/src/run/scan-profile.js +0 -269
  813. package/.worktrees/c1eae35e/src/run/shared.js +0 -1562
  814. package/.worktrees/c1eae35e/src/run/stage.js +0 -587
  815. package/.worktrees/c1eae35e/src/run.js +0 -23
  816. package/.worktrees/c1eae35e/src/scan-diff.js +0 -388
  817. package/.worktrees/c1eae35e/src/scan-postcheck.js +0 -524
  818. package/.worktrees/c1eae35e/src/scan-staleness.js +0 -95
  819. package/.worktrees/c1eae35e/src/setup.js +0 -414
  820. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +0 -597
  821. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +0 -62
  822. package/.worktrees/c1eae35e/src/spec-dir-typo.js +0 -50
  823. package/.worktrees/c1eae35e/src/spec-sync.js +0 -358
  824. package/.worktrees/c1eae35e/src/stage-contract-engine.js +0 -171
  825. package/.worktrees/c1eae35e/src/stage-contract-spec.js +0 -551
  826. package/.worktrees/c1eae35e/src/stage-contract.js +0 -948
  827. package/.worktrees/c1eae35e/src/stage-review.js +0 -597
  828. package/.worktrees/c1eae35e/src/stages/archive.js +0 -199
  829. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +0 -285
  830. package/.worktrees/c1eae35e/src/stages/brainstorm.js +0 -624
  831. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +0 -145
  832. package/.worktrees/c1eae35e/src/stages/doctor.js +0 -540
  833. package/.worktrees/c1eae35e/src/stages/execute.js +0 -1277
  834. package/.worktrees/c1eae35e/src/stages/explore.js +0 -43
  835. package/.worktrees/c1eae35e/src/stages/index.js +0 -29
  836. package/.worktrees/c1eae35e/src/stages/knowledge.js +0 -514
  837. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +0 -1398
  838. package/.worktrees/c1eae35e/src/stages/plan.js +0 -655
  839. package/.worktrees/c1eae35e/src/stages/quick.js +0 -167
  840. package/.worktrees/c1eae35e/src/stages/scan.js +0 -608
  841. package/.worktrees/c1eae35e/src/stages/status.js +0 -64
  842. package/.worktrees/c1eae35e/src/stages/verify.js +0 -246
  843. package/.worktrees/c1eae35e/src/sync.js +0 -1470
  844. package/.worktrees/c1eae35e/src/task-review.js +0 -1498
  845. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +0 -21
  846. package/.worktrees/c1eae35e/src/taskcard.js +0 -250
  847. package/.worktrees/c1eae35e/src/verify-postcheck.js +0 -1718
  848. package/.worktrees/c1eae35e/src/verify-probes.js +0 -327
  849. package/.worktrees/c1eae35e/src/version.js +0 -19
  850. package/.worktrees/c1eae35e/src/workflow.js +0 -600
  851. package/.worktrees/c1eae35e/src/workspace.js +0 -125
  852. package/.worktrees/c1eae35e/src/worktree-apply.js +0 -1611
  853. package/.worktrees/c1eae35e/src/worktree-deps.js +0 -668
  854. package/.worktrees/c1eae35e/src/worktree.js +0 -1849
  855. package/.worktrees/c1eae35e/templates/claude-instruction.md +0 -23
  856. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +0 -29
  857. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +0 -12
  858. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +0 -32
  859. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +0 -79
  860. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +0 -132
  861. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  862. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  863. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  864. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  865. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  866. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  867. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  868. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  869. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +0 -57
  870. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +0 -177
  871. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  872. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  873. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  874. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  875. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  876. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  877. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +0 -64
  878. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +0 -54
  879. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  880. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  881. package/.worktrees/dafc71ad/.gitattributes +0 -2
  882. package/.worktrees/dafc71ad/.husky/pre-push +0 -20
  883. package/.worktrees/dafc71ad/README.md +0 -203
  884. package/.worktrees/dafc71ad/SKILL.md +0 -91
  885. package/.worktrees/dafc71ad/analysis.md +0 -366
  886. package/.worktrees/dafc71ad/architecture-analysis.md +0 -448
  887. package/.worktrees/dafc71ad/bin/sillyspec.js +0 -2
  888. package/.worktrees/dafc71ad/eval/README.md +0 -86
  889. package/.worktrees/dafc71ad/eval/eval.config.json +0 -28
  890. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +0 -63
  891. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +0 -27
  892. package/.worktrees/dafc71ad/eval/lib/config.mjs +0 -82
  893. package/.worktrees/dafc71ad/eval/lib/db.mjs +0 -76
  894. package/.worktrees/dafc71ad/eval/lib/report.mjs +0 -120
  895. package/.worktrees/dafc71ad/eval/lib/runner.mjs +0 -157
  896. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +0 -73
  897. package/.worktrees/dafc71ad/eval/lib/util.mjs +0 -107
  898. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +0 -30
  899. package/.worktrees/dafc71ad/eval/run.mjs +0 -83
  900. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +0 -6
  901. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  902. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +0 -6
  903. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +0 -28
  904. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +0 -6
  905. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  906. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  907. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +0 -6
  908. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +0 -31
  909. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  910. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +0 -6
  911. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  912. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +0 -6
  913. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +0 -38
  914. package/.worktrees/dafc71ad/logo.jpg +0 -0
  915. package/.worktrees/dafc71ad/package-lock.json +0 -977
  916. package/.worktrees/dafc71ad/package.json +0 -41
  917. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  918. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  919. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  920. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +0 -16
  921. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  922. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +0 -836
  923. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +0 -256
  924. package/.worktrees/dafc71ad/packages/dashboard/package.json +0 -25
  925. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +0 -95
  926. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +0 -679
  927. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +0 -526
  928. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +0 -357
  929. package/.worktrees/dafc71ad/src/agent-session-log.js +0 -803
  930. package/.worktrees/dafc71ad/src/change-list.js +0 -290
  931. package/.worktrees/dafc71ad/src/change-risk-profile.js +0 -339
  932. package/.worktrees/dafc71ad/src/check-primitives.js +0 -65
  933. package/.worktrees/dafc71ad/src/classify-change.js +0 -109
  934. package/.worktrees/dafc71ad/src/commit-suggest.js +0 -202
  935. package/.worktrees/dafc71ad/src/config-cat.js +0 -88
  936. package/.worktrees/dafc71ad/src/config-schema.js +0 -328
  937. package/.worktrees/dafc71ad/src/constants.js +0 -97
  938. package/.worktrees/dafc71ad/src/contract-matrix.js +0 -533
  939. package/.worktrees/dafc71ad/src/datetime.js +0 -20
  940. package/.worktrees/dafc71ad/src/db-engine.js +0 -55
  941. package/.worktrees/dafc71ad/src/db.js +0 -381
  942. package/.worktrees/dafc71ad/src/decision-distill.js +0 -517
  943. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +0 -155
  944. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +0 -245
  945. package/.worktrees/dafc71ad/src/dispatch/probe.js +0 -246
  946. package/.worktrees/dafc71ad/src/dispatch/strategy.js +0 -121
  947. package/.worktrees/dafc71ad/src/docs-check.js +0 -825
  948. package/.worktrees/dafc71ad/src/docs-debt.js +0 -393
  949. package/.worktrees/dafc71ad/src/docs-gate.js +0 -107
  950. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +0 -1099
  951. package/.worktrees/dafc71ad/src/endpoint-extractor.js +0 -409
  952. package/.worktrees/dafc71ad/src/foreign-declared.js +0 -155
  953. package/.worktrees/dafc71ad/src/fs-atomic.js +0 -73
  954. package/.worktrees/dafc71ad/src/git-helper.js +0 -150
  955. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +0 -130
  956. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +0 -892
  957. package/.worktrees/dafc71ad/src/index.js +0 -2854
  958. package/.worktrees/dafc71ad/src/init.js +0 -626
  959. package/.worktrees/dafc71ad/src/knowledge-match.js +0 -231
  960. package/.worktrees/dafc71ad/src/local-detect.js +0 -128
  961. package/.worktrees/dafc71ad/src/local-register.js +0 -104
  962. package/.worktrees/dafc71ad/src/machine-interface.js +0 -543
  963. package/.worktrees/dafc71ad/src/migrate.js +0 -127
  964. package/.worktrees/dafc71ad/src/module-impact.js +0 -166
  965. package/.worktrees/dafc71ad/src/module-resolve.js +0 -222
  966. package/.worktrees/dafc71ad/src/modules.js +0 -580
  967. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +0 -126
  968. package/.worktrees/dafc71ad/src/progress/change-registry.js +0 -336
  969. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +0 -355
  970. package/.worktrees/dafc71ad/src/progress/shared.js +0 -36
  971. package/.worktrees/dafc71ad/src/progress/stage-machine.js +0 -594
  972. package/.worktrees/dafc71ad/src/progress/step-store.js +0 -265
  973. package/.worktrees/dafc71ad/src/progress.js +0 -1304
  974. package/.worktrees/dafc71ad/src/quick-recommend.js +0 -115
  975. package/.worktrees/dafc71ad/src/quicklog.js +0 -883
  976. package/.worktrees/dafc71ad/src/review-tier.js +0 -77
  977. package/.worktrees/dafc71ad/src/run/command.js +0 -1641
  978. package/.worktrees/dafc71ad/src/run/complete-handlers.js +0 -1552
  979. package/.worktrees/dafc71ad/src/run/complete.js +0 -1259
  980. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +0 -156
  981. package/.worktrees/dafc71ad/src/run/gates.js +0 -1111
  982. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +0 -208
  983. package/.worktrees/dafc71ad/src/run/next.js +0 -128
  984. package/.worktrees/dafc71ad/src/run/prompt.js +0 -843
  985. package/.worktrees/dafc71ad/src/run/quick-audit.js +0 -186
  986. package/.worktrees/dafc71ad/src/run/scan-profile.js +0 -269
  987. package/.worktrees/dafc71ad/src/run/shared.js +0 -1562
  988. package/.worktrees/dafc71ad/src/run/stage.js +0 -587
  989. package/.worktrees/dafc71ad/src/run.js +0 -23
  990. package/.worktrees/dafc71ad/src/scan-diff.js +0 -388
  991. package/.worktrees/dafc71ad/src/scan-postcheck.js +0 -524
  992. package/.worktrees/dafc71ad/src/scan-staleness.js +0 -95
  993. package/.worktrees/dafc71ad/src/setup.js +0 -414
  994. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +0 -597
  995. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +0 -62
  996. package/.worktrees/dafc71ad/src/spec-dir-typo.js +0 -50
  997. package/.worktrees/dafc71ad/src/spec-sync.js +0 -358
  998. package/.worktrees/dafc71ad/src/stage-contract-engine.js +0 -171
  999. package/.worktrees/dafc71ad/src/stage-contract-spec.js +0 -551
  1000. package/.worktrees/dafc71ad/src/stage-contract.js +0 -948
  1001. package/.worktrees/dafc71ad/src/stage-review.js +0 -597
  1002. package/.worktrees/dafc71ad/src/stages/archive.js +0 -199
  1003. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +0 -285
  1004. package/.worktrees/dafc71ad/src/stages/brainstorm.js +0 -624
  1005. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +0 -145
  1006. package/.worktrees/dafc71ad/src/stages/doctor.js +0 -540
  1007. package/.worktrees/dafc71ad/src/stages/execute.js +0 -1277
  1008. package/.worktrees/dafc71ad/src/stages/explore.js +0 -43
  1009. package/.worktrees/dafc71ad/src/stages/index.js +0 -29
  1010. package/.worktrees/dafc71ad/src/stages/knowledge.js +0 -514
  1011. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +0 -1398
  1012. package/.worktrees/dafc71ad/src/stages/plan.js +0 -655
  1013. package/.worktrees/dafc71ad/src/stages/quick.js +0 -167
  1014. package/.worktrees/dafc71ad/src/stages/scan.js +0 -608
  1015. package/.worktrees/dafc71ad/src/stages/status.js +0 -64
  1016. package/.worktrees/dafc71ad/src/stages/verify.js +0 -246
  1017. package/.worktrees/dafc71ad/src/sync.js +0 -1470
  1018. package/.worktrees/dafc71ad/src/task-review.js +0 -1498
  1019. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +0 -21
  1020. package/.worktrees/dafc71ad/src/taskcard.js +0 -250
  1021. package/.worktrees/dafc71ad/src/verify-postcheck.js +0 -1718
  1022. package/.worktrees/dafc71ad/src/verify-probes.js +0 -327
  1023. package/.worktrees/dafc71ad/src/version.js +0 -19
  1024. package/.worktrees/dafc71ad/src/workflow.js +0 -600
  1025. package/.worktrees/dafc71ad/src/workspace.js +0 -125
  1026. package/.worktrees/dafc71ad/src/worktree-apply.js +0 -1611
  1027. package/.worktrees/dafc71ad/src/worktree-deps.js +0 -668
  1028. package/.worktrees/dafc71ad/src/worktree.js +0 -1849
  1029. package/.worktrees/dafc71ad/templates/claude-instruction.md +0 -23
  1030. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +0 -29
  1031. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +0 -12
  1032. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +0 -32
  1033. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +0 -79
  1034. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +0 -132
  1035. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  1036. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  1037. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  1038. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  1039. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  1040. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  1041. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  1042. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  1043. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +0 -57
  1044. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +0 -177
  1045. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  1046. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  1047. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  1048. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  1049. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  1050. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  1051. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +0 -64
  1052. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +0 -54
  1053. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  1054. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  1055. package/.worktrees/e58fcc4c/.gitattributes +0 -2
  1056. package/.worktrees/e58fcc4c/.husky/pre-push +0 -20
  1057. package/.worktrees/e58fcc4c/README.md +0 -203
  1058. package/.worktrees/e58fcc4c/SKILL.md +0 -91
  1059. package/.worktrees/e58fcc4c/architecture-analysis.md +0 -503
  1060. package/.worktrees/e58fcc4c/bin/sillyspec.js +0 -2
  1061. package/.worktrees/e58fcc4c/eval/README.md +0 -86
  1062. package/.worktrees/e58fcc4c/eval/eval.config.json +0 -28
  1063. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +0 -63
  1064. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +0 -27
  1065. package/.worktrees/e58fcc4c/eval/lib/config.mjs +0 -82
  1066. package/.worktrees/e58fcc4c/eval/lib/db.mjs +0 -76
  1067. package/.worktrees/e58fcc4c/eval/lib/report.mjs +0 -120
  1068. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +0 -157
  1069. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +0 -73
  1070. package/.worktrees/e58fcc4c/eval/lib/util.mjs +0 -107
  1071. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +0 -30
  1072. package/.worktrees/e58fcc4c/eval/run.mjs +0 -83
  1073. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +0 -6
  1074. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  1075. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +0 -6
  1076. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +0 -28
  1077. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +0 -6
  1078. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  1079. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  1080. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +0 -6
  1081. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +0 -31
  1082. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  1083. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +0 -6
  1084. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  1085. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +0 -6
  1086. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +0 -38
  1087. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  1088. package/.worktrees/e58fcc4c/package-lock.json +0 -977
  1089. package/.worktrees/e58fcc4c/package.json +0 -41
  1090. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  1091. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  1092. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  1093. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +0 -16
  1094. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  1095. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +0 -836
  1096. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +0 -256
  1097. package/.worktrees/e58fcc4c/packages/dashboard/package.json +0 -25
  1098. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +0 -95
  1099. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +0 -679
  1100. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +0 -526
  1101. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +0 -357
  1102. package/.worktrees/e58fcc4c/src/agent-session-log.js +0 -803
  1103. package/.worktrees/e58fcc4c/src/change-list.js +0 -290
  1104. package/.worktrees/e58fcc4c/src/change-risk-profile.js +0 -339
  1105. package/.worktrees/e58fcc4c/src/check-primitives.js +0 -65
  1106. package/.worktrees/e58fcc4c/src/classify-change.js +0 -109
  1107. package/.worktrees/e58fcc4c/src/commit-suggest.js +0 -202
  1108. package/.worktrees/e58fcc4c/src/config-cat.js +0 -88
  1109. package/.worktrees/e58fcc4c/src/config-schema.js +0 -328
  1110. package/.worktrees/e58fcc4c/src/constants.js +0 -97
  1111. package/.worktrees/e58fcc4c/src/contract-matrix.js +0 -533
  1112. package/.worktrees/e58fcc4c/src/datetime.js +0 -20
  1113. package/.worktrees/e58fcc4c/src/db-engine.js +0 -55
  1114. package/.worktrees/e58fcc4c/src/db.js +0 -381
  1115. package/.worktrees/e58fcc4c/src/decision-distill.js +0 -517
  1116. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +0 -155
  1117. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +0 -245
  1118. package/.worktrees/e58fcc4c/src/dispatch/probe.js +0 -246
  1119. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +0 -121
  1120. package/.worktrees/e58fcc4c/src/docs-check.js +0 -825
  1121. package/.worktrees/e58fcc4c/src/docs-debt.js +0 -393
  1122. package/.worktrees/e58fcc4c/src/docs-gate.js +0 -107
  1123. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +0 -1099
  1124. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +0 -409
  1125. package/.worktrees/e58fcc4c/src/foreign-declared.js +0 -155
  1126. package/.worktrees/e58fcc4c/src/fs-atomic.js +0 -73
  1127. package/.worktrees/e58fcc4c/src/git-helper.js +0 -150
  1128. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +0 -130
  1129. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +0 -892
  1130. package/.worktrees/e58fcc4c/src/index.js +0 -2854
  1131. package/.worktrees/e58fcc4c/src/init.js +0 -626
  1132. package/.worktrees/e58fcc4c/src/knowledge-match.js +0 -231
  1133. package/.worktrees/e58fcc4c/src/local-detect.js +0 -128
  1134. package/.worktrees/e58fcc4c/src/local-register.js +0 -104
  1135. package/.worktrees/e58fcc4c/src/machine-interface.js +0 -543
  1136. package/.worktrees/e58fcc4c/src/migrate.js +0 -127
  1137. package/.worktrees/e58fcc4c/src/module-impact.js +0 -166
  1138. package/.worktrees/e58fcc4c/src/module-resolve.js +0 -222
  1139. package/.worktrees/e58fcc4c/src/modules.js +0 -580
  1140. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +0 -126
  1141. package/.worktrees/e58fcc4c/src/progress/change-registry.js +0 -336
  1142. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +0 -355
  1143. package/.worktrees/e58fcc4c/src/progress/shared.js +0 -36
  1144. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +0 -594
  1145. package/.worktrees/e58fcc4c/src/progress/step-store.js +0 -265
  1146. package/.worktrees/e58fcc4c/src/progress.js +0 -1304
  1147. package/.worktrees/e58fcc4c/src/quick-recommend.js +0 -115
  1148. package/.worktrees/e58fcc4c/src/quicklog.js +0 -883
  1149. package/.worktrees/e58fcc4c/src/review-tier.js +0 -77
  1150. package/.worktrees/e58fcc4c/src/run/command.js +0 -1641
  1151. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +0 -1552
  1152. package/.worktrees/e58fcc4c/src/run/complete.js +0 -1259
  1153. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +0 -156
  1154. package/.worktrees/e58fcc4c/src/run/gates.js +0 -1111
  1155. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +0 -208
  1156. package/.worktrees/e58fcc4c/src/run/next.js +0 -128
  1157. package/.worktrees/e58fcc4c/src/run/prompt.js +0 -843
  1158. package/.worktrees/e58fcc4c/src/run/quick-audit.js +0 -186
  1159. package/.worktrees/e58fcc4c/src/run/scan-profile.js +0 -269
  1160. package/.worktrees/e58fcc4c/src/run/shared.js +0 -1562
  1161. package/.worktrees/e58fcc4c/src/run/stage.js +0 -587
  1162. package/.worktrees/e58fcc4c/src/run.js +0 -23
  1163. package/.worktrees/e58fcc4c/src/scan-diff.js +0 -388
  1164. package/.worktrees/e58fcc4c/src/scan-postcheck.js +0 -524
  1165. package/.worktrees/e58fcc4c/src/scan-staleness.js +0 -95
  1166. package/.worktrees/e58fcc4c/src/setup.js +0 -414
  1167. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +0 -597
  1168. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +0 -62
  1169. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +0 -50
  1170. package/.worktrees/e58fcc4c/src/spec-sync.js +0 -358
  1171. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +0 -171
  1172. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +0 -551
  1173. package/.worktrees/e58fcc4c/src/stage-contract.js +0 -948
  1174. package/.worktrees/e58fcc4c/src/stage-review.js +0 -597
  1175. package/.worktrees/e58fcc4c/src/stages/archive.js +0 -199
  1176. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +0 -285
  1177. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +0 -624
  1178. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +0 -145
  1179. package/.worktrees/e58fcc4c/src/stages/doctor.js +0 -540
  1180. package/.worktrees/e58fcc4c/src/stages/execute.js +0 -1277
  1181. package/.worktrees/e58fcc4c/src/stages/explore.js +0 -43
  1182. package/.worktrees/e58fcc4c/src/stages/index.js +0 -29
  1183. package/.worktrees/e58fcc4c/src/stages/knowledge.js +0 -514
  1184. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +0 -1398
  1185. package/.worktrees/e58fcc4c/src/stages/plan.js +0 -655
  1186. package/.worktrees/e58fcc4c/src/stages/quick.js +0 -167
  1187. package/.worktrees/e58fcc4c/src/stages/scan.js +0 -608
  1188. package/.worktrees/e58fcc4c/src/stages/status.js +0 -64
  1189. package/.worktrees/e58fcc4c/src/stages/verify.js +0 -246
  1190. package/.worktrees/e58fcc4c/src/sync.js +0 -1470
  1191. package/.worktrees/e58fcc4c/src/task-review.js +0 -1498
  1192. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +0 -21
  1193. package/.worktrees/e58fcc4c/src/taskcard.js +0 -250
  1194. package/.worktrees/e58fcc4c/src/verify-postcheck.js +0 -1718
  1195. package/.worktrees/e58fcc4c/src/verify-probes.js +0 -327
  1196. package/.worktrees/e58fcc4c/src/version.js +0 -19
  1197. package/.worktrees/e58fcc4c/src/workflow.js +0 -600
  1198. package/.worktrees/e58fcc4c/src/workspace.js +0 -125
  1199. package/.worktrees/e58fcc4c/src/worktree-apply.js +0 -1611
  1200. package/.worktrees/e58fcc4c/src/worktree-deps.js +0 -668
  1201. package/.worktrees/e58fcc4c/src/worktree.js +0 -1849
  1202. package/.worktrees/e58fcc4c/templates/claude-instruction.md +0 -23
  1203. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +0 -29
  1204. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +0 -12
  1205. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +0 -32
  1206. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +0 -79
  1207. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +0 -132
@@ -1,1552 +0,0 @@
1
- /**
2
- * run/complete-handlers.js(W6 Step5 从 run.js 抽出)。
3
- *
4
- * completeStep 的子 handler + archive 收尾(自洽叶子模块,仅被 completeStep 调用):
5
- * - handleArchiveConfirmStep:archive「确认归档」步骤 --confirm 门控 + 推荐文档校验
6
- * - handlePlanGeneratePlanStep:plan「generate_plan」完成后动态插入 coordinator + postcheck 步骤
7
- * - handleScanProjectListStep:scan step 2 完成后按项目展开 perProject 步骤(用 sanitizeProjectName/validateParsedProjects)
8
- * - archiveChangeDirectory:归档移动变更目录(6 处 process.exit(1) + worktree 清理;handleArchiveConfirmStep 内部调用)
9
- * srcDir 缺失时走 findAlreadyArchivedDir 幂等自愈(issue archive-stage-physical-tracking-desync);
10
- * archiveChangeDirectory + findAlreadyArchivedDir 已 export 供 test 直接 import
11
- * - sanitizeProjectName / validateParsedProjects:项目名清洗 + 列表校验纯函数(handleScanProjectListStep 专用)
12
- *
13
- * 安全锚:run.js 始终 barrel。3 handler 由 run.js import 回来;sanitizeProjectName + validateParsedProjects
14
- * 被 test 直接 import(run-sanitize-project-name / run-scan-project-parse),run.js barrel re-export 契约保留。
15
- * 4 目标 handler 无 test 直接 import;archiveChangeDirectory + findAlreadyArchivedDir 供自愈 test 直接 import,无需 barrel re-export。completeStep(Step7 搬)将把 import 行带走。
16
- *
17
- * 路径修正(相对 src/run/):
18
- * - resolveChangeDir 从 './shared.js';renameSyncRetry 从 '../fs-atomic.js';stageRegistry 从 '../stages/index.js'
19
- * - 动态 import './stages/plan.js' / './worktree.js' → '../'(src/ 下,退一层;真环依赖保留动态)
20
- * - 删除 archiveChangeDirectory 内死代码 `const { renameSync } = await import('fs')`(renameSync 解构未用,实际走 renameSyncRetry)
21
- *
22
- * archiveChangeDirectory 的 6 处 process.exit 全 exit(1):5 个顶层 guard 直接终止;L1325 在 catch 内主动 exit
23
- * (非被外层吞);process.exit 不可被 try 捕获 → 搬迁行为完全等价。
24
- */
25
- import { basename, join, resolve, relative, isAbsolute } from 'node:path'
26
- import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, rmSync } from 'node:fs'
27
- import { renameSyncRetry, writeAtomicSync } from '../fs-atomic.js'
28
- import { resolveChangeDir, resolveQuickSessionsDir, safeGit, auditQuickCompletion, triggerSync, isQuickMetadata, resolveRuntimeRoot, collectOtherQuickSessionDeclarations } from './shared.js'
29
- import { detectConcurrentChanges, formatConcurrentWarning, resolveConcurrentAnchor } from './concurrent-detect.js'
30
- import { stageRegistry } from '../stages/index.js'
31
- import { SCAN_STATUS, POINTER_STATUS } from '../constants.js'
32
- import { printQuickAuditReview } from './quick-audit.js'
33
- import { validateQuickResult, allocateQuicklogEntry, findQuicklogEntry, completeQuicklogEntry, extractTitleFromResult } from '../quicklog.js'
34
- import { getRule } from '../stage-contract-spec.js'
35
- import { archiveDestDirName } from '../stage-contract.js'
36
-
37
- /**
38
- * 清洗项目名:只保留 ASCII 字母/数字/横线/下划线/点,过滤中文和特殊字符。
39
- * - 必须含至少一个字母(拒绝纯数字 "0"/"7"/"07",避免 scan-projects.json 脏数据)
40
- * - 长度必须 ≥ 2(拒绝单字符 "a"/"0")
41
- * @param {string} name - 原始项目名候选
42
- * @returns {string | null} 合法项目名或 null(拒绝)
43
- */
44
- export function sanitizeProjectName(name) {
45
- if (!name) return null
46
- const clean = String(name).replace(/[^a-zA-Z0-9_\-.]/g, '').trim()
47
- if (!clean) return null
48
- if (!/[a-zA-Z]/.test(clean)) return null // 纯数字/符号拒绝("0"/"7"/"07")
49
- if (clean.length < 2) return null // 单字符拒绝("a"/"0")
50
- return clean
51
- }
52
- /**
53
- * 校验从 step 2 解析出的项目列表。
54
- * 不通过则不落盘 projects/*.yaml、不展开 perProject 步骤。
55
- *
56
- * @param {Array<{id: string, path?: string}>} projects - 项目列表(含可选 path)
57
- * @param {string} sourceRoot - 源码根目录,用于 path 安全校验
58
- */
59
- export function validateParsedProjects(projects, sourceRoot) {
60
- const errors = []
61
- if (!projects || projects.length === 0) {
62
- return { ok: false, errors: ['项目列表为空'] }
63
- }
64
- if (projects.length > 10) {
65
- return { ok: false, errors: [`项目数量 ${projects.length} 超过上限 10,疑似误解析`] }
66
- }
67
- const safeRoot = resolve(sourceRoot)
68
- const seen = new Set()
69
- for (const proj of projects) {
70
- const id = proj.id || proj
71
- if (seen.has(id)) {
72
- errors.push(`重复项目名: ${id}`)
73
- }
74
- seen.add(id)
75
- // slug 合法性:只允许 a-z 0-9 _ - .,长度 2-64
76
- if (!/^[a-zA-Z][\w\-.]{1,63}$/.test(id)) {
77
- errors.push(`项目名 "${id}" 不合法(需 slug 格式:字母开头,只含 a-zA-Z0-9_-., 长度 2-64)`)
78
- }
79
- // path 安全校验(如果提供了 path)
80
- if (proj.path) {
81
- if (proj.path.includes('..')) {
82
- errors.push(`项目 "${id}" 的 path 包含 .. ,拒绝越界`)
83
- } else {
84
- const absPath = resolve(safeRoot, proj.path)
85
- const rel = relative(safeRoot, absPath)
86
- if (rel.startsWith('..') || isAbsolute(rel)) {
87
- errors.push(`项目 "${id}" 的 path "${proj.path}" 解析后超出 source_root`)
88
- }
89
- if (!existsSync(absPath)) {
90
- errors.push(`项目 "${id}" 的 path "${proj.path}" 不存在`)
91
- }
92
- }
93
- }
94
- }
95
- if (errors.length > 0) return { ok: false, errors }
96
- return { ok: true, errors: [] }
97
- }
98
- /**
99
- * 在 changes/archive/ 下查找变更 <changeName> 是否已被归档(archive 脱钩自愈用)。
100
- *
101
- * 归档目录名 = 原变更名(直接移入 archive/,不重命名)。
102
- * 精确匹配 + 要求目录含 plan.md(归档必备产物,防止同名巧合误判)。
103
- * issue: archive-stage-physical-tracking-desync。
104
- *
105
- * @param {string} archiveDir - changes/archive 绝对路径
106
- * @param {string} changeName - 变更名(currentChange)
107
- * @returns {string|null} 命中的归档目录绝对路径,无则 null
108
- */
109
- export function findAlreadyArchivedDir(archiveDir, changeName) {
110
- if (!existsSync(archiveDir)) return null
111
- let entries
112
- try {
113
- entries = readdirSync(archiveDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name)
114
- } catch {
115
- return null
116
- }
117
- // 精确原名命中
118
- const exact = entries.find((e) => e === changeName && existsSync(join(archiveDir, e, 'plan.md')))
119
- if (exact) return join(archiveDir, exact)
120
- return null
121
- }
122
-
123
- /**
124
- * 归档时清理可能残留的 worktree(execute 自动清理未走到 / 有未 apply 变更被遗弃)。
125
- * 安全策略:有未 apply 变更时保留 worktree 并警告,避免误删用户未应用的代码。
126
- * 同时清理该变更的 execute / stage-review runId marker(只写不删的累积物,
127
- * 见 stage.js execute 启动固定 executeRunId / stage-review.js stageReviewMarkerPath)。
128
- * 从 archiveChangeDirectory 抽出,供正常归档 + 自愈归档复用。
129
- */
130
- export async function archiveWorktreeCleanup(cwd, archiveChangeName, specBase, platformOpts = {}) {
131
- // ── 清理 runId marker:execute(current-execute-run-id-<change>)与 stage-review
132
- // (current-stage-review-run-id-<stage>-<change>)。marker 只服务 execute→verify→archive
133
- // 期间,归档后无读者;不删则 .runtime 随变更数无限累积。runtimeRoot 解析同写入侧
134
- // (resolveRuntimeRoot 锚主仓),避免平台模式清理错位置。
135
- try {
136
- const runtimeRoot = resolveRuntimeRoot(platformOpts, specBase)
137
- if (existsSync(runtimeRoot)) {
138
- // stage-review marker 精确匹配(坑 marker-suffix-overmatch):marker 名是
139
- // current-stage-review-run-id-<stage>-<change>,按 endsWith('-'+change) 后缀匹配会在归档
140
- // 手工短名变更(如 login)时误删自动日期前缀变更(2026-08-01-login 天然以 '-login' 结尾)
141
- // 的 marker。stage 集合与写入侧 stageReviewMarkerPath 的调用方一致。
142
- const REVIEW_STAGES = ['brainstorm', 'plan', 'execute', 'verify', 'archive']
143
- const markers = readdirSync(runtimeRoot).filter((f) =>
144
- f === `current-execute-run-id-${archiveChangeName}` ||
145
- REVIEW_STAGES.some(st => f === `current-stage-review-run-id-${st}-${archiveChangeName}`),
146
- )
147
- for (const m of markers) {
148
- try { unlinkSync(join(runtimeRoot, m)) } catch {}
149
- }
150
- if (markers.length > 0) {
151
- console.log(`🧹 归档清理 ${markers.length} 个 runId marker(execute/stage-review)`)
152
- }
153
- }
154
- } catch (e) {
155
- console.warn(`⚠️ 归档 runId marker 清理失败(不阻断归档): ${e.message}`)
156
- }
157
- try {
158
- const { WorktreeManager } = await import('../worktree.js')
159
- const wm = new WorktreeManager({ cwd })
160
- const meta = wm.getMeta(archiveChangeName)
161
- if (!meta) {
162
- // 无 meta 兜底(坑 archive-cleanup-orphan-physical-dir,2026-08-21 实证):meta 已被先行
163
- // 流程注销(apply 自动 cleanup / doctor 幽灵清理)时此前直接 return——若物理目录因中途
164
- // 失败残留下就是孤儿(无 meta=无锚定基准,残留即孤儿)。force 清理(幂等:什么都不存在
165
- // 时 cleanup 返回 skipped 零副作用)。
166
- const orphan = wm.cleanup(archiveChangeName, { force: true })
167
- if (orphan.result === 'cleaned' || orphan.result === 'force-cleaned' || orphan.result === 'partial') {
168
- console.log(`🧹 归档清理孤儿 worktree 残留(meta 已注销): ${archiveChangeName}${orphan.residual?.length ? '(残留: ' + orphan.residual.join('; ') + ')' : ''}`)
169
- }
170
- return
171
- }
172
- const check = meta.mode !== 'in-place-fallback' ? wm.hasUnappliedChanges(archiveChangeName) : { hasChanges: false }
173
- if (check.hasChanges) {
174
- console.warn(`⚠️ 归档时 worktree 仍有 ${check.changedFiles.length} 个未 apply 变更,保留 worktree`)
175
- console.warn(` 确认不需要后手动清理: sillyspec worktree cleanup ${archiveChangeName} --force`)
176
- return
177
- }
178
- const cleanResult = wm.cleanup(archiveChangeName)
179
- if (cleanResult.residual?.length > 0) {
180
- console.warn(`⚠️ 归档 worktree 清理残留: ${cleanResult.residual.join('; ')}`)
181
- console.warn(` 手动处理: sillyspec worktree cleanup ${archiveChangeName} --force`)
182
- }
183
- } catch (e) {
184
- console.warn(`⚠️ 归档 worktree 清理失败(不阻断归档): ${e.message}`)
185
- }
186
- }
187
-
188
- /**
189
- * 提取 module-impact.md「更新结果」表中的未清文档同步死信行(债单 D-5)。
190
- *
191
- * 只在「## 更新结果」段内扫描表格行(| 分隔),状态判定取**末列** trim 后精确匹配
192
- * pending / 待办 / 未同步 / not-done(大小写不敏感)。不做全文 grep——
193
- * sync_manual_get_pending / pending_review / pending-leases 等代码标识符出现在
194
- * 矩阵摘要列是合法内容,不能误报(实证:archive 全量扫描唯一死信形态是末列 pending)。
195
- *
196
- * 纯函数:无 fs/git 调用,export 供 test 直接 import。
197
- * @param {string} content module-impact.md 全文(CRLF/LF 均容)
198
- * @returns {string[]} 死信行原文(去首尾空白),空数组 = 无死信
199
- */
200
- export function extractPendingDocSyncRows(content) {
201
- if (!content || typeof content !== 'string') return []
202
- const normalized = content.replace(/\r\n/g, '\n')
203
- const sectionStart = normalized.search(/^#{2,3}\s*更新结果\s*$/m)
204
- if (sectionStart === -1) return []
205
- // 跳过标题行本身(matchFirstLine 吃掉标题),再找下一个章节边界
206
- const titleMatch = normalized.slice(sectionStart).match(/^#{2,3}\s*更新结果\s*$/m)
207
- const bodyStart = sectionStart + titleMatch[0].length
208
- const afterTitle = normalized.slice(bodyStart)
209
- const nextSection = afterTitle.search(/^#{1,3}\s/m)
210
- const section = nextSection === -1 ? afterTitle : afterTitle.slice(0, nextSection)
211
- const PENDING_STATUSES = new Set(['pending', '待办', '未同步', 'not-done', 'todo'])
212
- const rows = []
213
- for (const line of section.split('\n')) {
214
- const trimmed = line.trim()
215
- if (!trimmed.startsWith('|')) continue
216
- const cells = trimmed.split('|').map(c => c.trim())
217
- // split 首尾产生空串(行首行尾的 |),真实单元格在中间;末列 = 最后一个非空单元格之后
218
- // 表格行结构 | 模块文档 | 操作 | 状态 | → cells = ['', '模块文档', '操作', '状态', '']
219
- const lastCell = cells[cells.length - 1]
220
- if (lastCell === '' && cells.length >= 2) cells.pop()
221
- const statusCell = cells[cells.length - 1]
222
- if (statusCell && PENDING_STATUSES.has(statusCell.toLowerCase())) rows.push(trimmed)
223
- }
224
- return rows
225
- }
226
-
227
- /**
228
- * 提取 module-impact.md「更新结果」表中的已完成(done)行声明的目标文档路径(债单 D-4 窄口径)。
229
- *
230
- * done 行首列是目标标识:`modules/<id>.md`(模块卡片)、`_module-map.yaml`(映射索引)、
231
- * `.sillyspec/docs/<project>/modules/<f>.md`(含仓库前缀的全路径)等。本函数提取首列里
232
- * 能解析出的文档路径 token,供调用方校验文件存在性——声明 done 但目标文件不存在 = 假申报。
233
- *
234
- * 提取规则(保守,宁可漏报不误报):
235
- * - 首列以反引号包裹或裸写的 `.md`/`.yaml` 结尾路径 token(含路径分隔符 /)
236
- * - `modules/<id>.md` 相对写法解析为 `<specBase>/docs/<project>/modules/<id>.md`——但 project
237
- * 归属需读 _module-map,此处只返回原样 token,路径解析留给调用方(有 specBase 上下文)
238
- * - `_module-map.yaml` 裸名跳过(存在性由 map 本身保证,且各项目都有)
239
- *
240
- * 纯函数:无 fs/git 调用,export 供 test 直接 import。
241
- * @param {string} content module-impact.md 全文
242
- * @returns {string[]} done 行声明的文档路径 token(去重)
243
- */
244
- export function extractDoneDocTargets(content) {
245
- if (!content || typeof content !== 'string') return []
246
- const normalized = content.replace(/\r\n/g, '\n')
247
- const sectionStart = normalized.search(/^#{2,3}\s*更新结果\s*$/m)
248
- if (sectionStart === -1) return []
249
- const titleMatch = normalized.slice(sectionStart).match(/^#{2,3}\s*更新结果\s*$/m)
250
- const bodyStart = sectionStart + titleMatch[0].length
251
- const afterTitle = normalized.slice(bodyStart)
252
- const nextSection = afterTitle.search(/^#{1,3}\s/m)
253
- const section = nextSection === -1 ? afterTitle : afterTitle.slice(0, nextSection)
254
- const targets = new Set()
255
- for (const line of section.split('\n')) {
256
- const trimmed = line.trim()
257
- if (!trimmed.startsWith('|')) continue
258
- const cells = trimmed.split('|').map(c => c.trim())
259
- if (cells.length >= 2) cells.pop() // 行尾空 cell
260
- const statusCell = cells[cells.length - 1]
261
- if (!statusCell || statusCell.toLowerCase() !== 'done') continue
262
- // 首个非空 cell(跳过 split 产生的行首空串)
263
- const firstCell = cells.slice(1).find(c => c !== '') || ''
264
- // 从首列提取 .md/.yaml 结尾且含 / 的路径 token(modules/x.md 或 a/b/c.yaml);
265
- // 反引号包裹优先,裸写次之。_module-map.yaml 无 / 跳过(见 docstring)。
266
- const m = firstCell.match(/`([^`]*\.(?:md|yaml))`/) || firstCell.match(/(^|\s|()([\w./-]+\/[\w./-]*\.(?:md|yaml))/)
267
- if (m) {
268
- const token = (m[2] !== undefined && m[2] !== null && m[1] !== '`') ? m[2] : m[1]
269
- if (token && !token.endsWith('_module-map.yaml')) targets.add(token)
270
- }
271
- }
272
- return [...targets]
273
- }
274
-
275
- export async function archiveChangeDirectory(pm, cwd, progress, specBase, platformOpts = {}) {
276
- const archiveChangeName = progress.currentChange
277
- if (!archiveChangeName) {
278
- console.error('❌ 归档失败:未找到当前变更名(currentChange)')
279
- process.exit(1)
280
- }
281
- const changesDir = join(specBase, 'changes')
282
- const archiveDir = join(changesDir, 'archive')
283
- const srcDir = join(changesDir, archiveChangeName)
284
- const date = new Date().toISOString().slice(0, 10)
285
- const destName = archiveDestDirName(date, archiveChangeName)
286
- const destDir = join(archiveDir, destName)
287
-
288
- if (!existsSync(srcDir)) {
289
- // 幂等自愈(issue archive-stage-physical-tracking-desync):源目录已不存在,但变更可能已被
290
- // 手动 / 部分流程移到 changes/archive/ 并 commit,而 --done --confirm 从未正式跑完 → 进度 DB
291
- // 卡 archive 阶段、active 列表仍列此 change。检测到已归档则回填进度(unregisterChange)并
292
- // 成功返回,让收尾流程把 archive 阶段标完成,而非 exit(1) 死路(source 已移走无法重跑 move)。
293
- const alreadyArchivedDir = findAlreadyArchivedDir(archiveDir, archiveChangeName)
294
- if (alreadyArchivedDir) {
295
- console.log(`ℹ️ 源目录不存在但变更已在 archive/(${basename(alreadyArchivedDir)}),判定已归档,自愈进度 DB`)
296
- // 终态一致化(坑 manual-archive-desync-status-only):手动搬目录绕过标准归档后,本自愈路径
297
- // 不能只翻 status——同时收尾 archive 阶段(steps/stages/current_stage),否则推送平台的终态
298
- // 是「已归档 + 归档 0/5 + 停在 execute」的矛盾体,详情页渲染成「进度丢失」
299
- pm.unregisterChange(cwd, archiveChangeName, { archiveStepNames: typeof pm.archiveStepNamesForArchive === 'function' ? pm.archiveStepNamesForArchive() : null })
300
- await archiveWorktreeCleanup(cwd, archiveChangeName, specBase, platformOpts)
301
- console.log(`📦 已自愈归档:${archiveChangeName} → archive/${basename(alreadyArchivedDir)}/`)
302
- return alreadyArchivedDir
303
- }
304
- console.error(`❌ 归档失败:源目录不存在 ${srcDir}`)
305
- console.error(` 且 changes/archive/ 下未找到该变更的归档目录。若已手动归档请核对目录名;否则先补全变更产物。`)
306
- process.exit(1)
307
- }
308
- // 移动前硬校验:变更包必须含 plan.md,否则不该归档。
309
- // 在移动前阻断(而非移动后),目录尚未动,用户可直接修复后重试。
310
- if (!existsSync(join(srcDir, 'plan.md'))) {
311
- console.error(`❌ 归档失败:变更目录缺少 plan.md(${srcDir})`)
312
- console.error(` plan.md 是归档的必需产物。请先补全 plan 阶段产出再归档。`)
313
- process.exit(1)
314
- }
315
- // 移动前硬校验(债单 D-5):module-impact.md「更新结果」表存在 pending 死信 → 阻断。
316
- // 修复场景:perf-remediation 类变更把文档同步显式推给 archive(「(execute 完成后由 archive
317
- // 阶段同步)| 待办 | pending」),archive 又没做 → 带 pending 归档且 verify 全 PASS,死信无人回填。
318
- // 只查「## 更新结果」段内表格行的状态列(末列)精确匹配 pending/待办/未同步——不做全文 grep,
319
- // 防 sync_manual_get_pending / pending_review 等代码标识符误报。
320
- const impactPath = join(srcDir, 'module-impact.md')
321
- if (existsSync(impactPath)) {
322
- const pendingRows = extractPendingDocSyncRows(readFileSync(impactPath, 'utf8'))
323
- if (pendingRows.length > 0) {
324
- console.error(`❌ 归档失败:module-impact.md「更新结果」表存在 ${pendingRows.length} 个未清 pending/待办项(死信)`)
325
- for (const row of pendingRows) console.error(` - ${row}`)
326
- console.error(` 这些文档同步项从未落地。请先完成同步并回填状态为 done/skipped(说明原因),再归档。`)
327
- process.exit(1)
328
- }
329
- }
330
- if (existsSync(destDir)) {
331
- console.error(`❌ 归档失败:目标目录已存在 ${destDir}`)
332
- process.exit(1)
333
- }
334
- mkdirSync(archiveDir, { recursive: true })
335
- try {
336
- renameSyncRetry(srcDir, destDir)
337
- } catch (e) {
338
- console.error(`❌ 归档失败:移动变更目录时出错(${e.message})`)
339
- console.error(` 常见原因:变更目录内文件被 IDE / 杀毒 / 索引占用,已重试 5 次仍失败。请关闭相关程序后重试。`)
340
- process.exit(1)
341
- }
342
-
343
- if (!existsSync(destDir) || existsSync(srcDir)) {
344
- console.error('❌ 归档校验失败:移动操作异常')
345
- process.exit(1)
346
- }
347
-
348
- // 正常路径同样走终态一致化(坑 manual-archive-desync-status-only):标准 --done --confirm 流程
349
- // 中 completeStep 随后也会逐项完成,此处先收尾是幂等写同值——保证任何走出本函数的归档终态一致
350
- pm.unregisterChange(cwd, archiveChangeName, { archiveStepNames: typeof pm.archiveStepNamesForArchive === 'function' ? pm.archiveStepNamesForArchive() : null })
351
-
352
- // CLI 下沉 git add(坑4,FR-04):确定性暂存归档目录 + 模块文档,不靠 step5 prompt 驱动。
353
- // step5 prompt 的 git add 保留作幂等兜底;POSIX 路径跨平台(git 接受正斜杠)。
354
- // safeGit 内部已 try-catch(返回 {value,error} 不抛),外层 try 兜底防御;失败不阻断归档
355
- // (目录已移动 + change 已注销),由 step5 prompt git add + agent git status 核对兜底。
356
- try {
357
- safeGit(cwd, ['add', '--', '.sillyspec/changes/archive/'])
358
- safeGit(cwd, ['add', '--', '.sillyspec/docs/'])
359
- } catch {}
360
-
361
- // ── 他者半归档残留探测(坑 archive-other-residual-rename,2026-08-21 实证)──
362
- // 并行变更的手动归档把 R 残留(源目录 rename 目标行)留在暂存区;本变更归档提交时
363
- // git status 显示它们,agent 会误判「还没提交完 / 要做第二次提交」。区分:
364
- // 本变更:未暂存的源侧移动(` D changes/<me>/...` + 未跟踪 archive/<me>/...)→ 补暂存
365
- // 让归档成单次原子提交;
366
- // 他者:已暂存的 rename(`R changes/<他人>/... -> changes/archive/<他人>/...`)→ 只 warn
367
- // 提示归属(不 stage 不动——别人的归别人的)。
368
- try {
369
- const raw = gitQuiet(cwd, ['status', '--porcelain'], { trim: false, timeout: 30000 })
370
- if (raw && raw.trim()) {
371
- const changesPrefix = '.sillyspec/changes/'
372
- const minePaths = []
373
- const othersResidual = []
374
- for (const line of raw.split('\n')) {
375
- if (!line || line.length < 4) continue
376
- const x = line[0], y = line[1]
377
- const body = line.slice(3).trim()
378
- const arrow = body.indexOf(' -> ')
379
- const src = arrow !== -1 ? body.slice(0, arrow).replace(/^"|"$/g, '') : null
380
- const dst = (arrow !== -1 ? body.slice(arrow + 4) : body).replace(/^"|"$/g, '')
381
- if (x === 'R' && y === ' ' && arrow !== -1 && dst.startsWith(changesPrefix + 'archive/')) {
382
- // 已暂存 rename → 半归档残留;按目标目录名归属他者变更
383
- const m = /^\.sillyspec\/changes\/archive\/([^/]+)\//.exec(dst)
384
- const owner = m ? m[1] : '?'
385
- if (owner !== archiveChangeName) othersResidual.push(owner)
386
- } else if (x === ' ' && (y === 'D' || y === 'A' || y === 'M')) {
387
- // 未暂存的源侧移动:源目录 D / 新位置 A——指向本变更的补暂存
388
- const p = dst || src
389
- if (p && (p.startsWith(changesPrefix + archiveChangeName + '/')
390
- || p.startsWith(changesPrefix + 'archive/' + archiveChangeName + '/'))) {
391
- minePaths.push(p)
392
- }
393
- }
394
- }
395
- if (minePaths.length > 0) {
396
- try { safeGit(cwd, ['add', '-A', '--', changesPrefix]) } catch {}
397
- console.log(`🧾 已补暂存本变更归档的源侧移动(${minePaths.length} 项,归档成单次原子提交)`)
398
- }
399
- if (othersResidual.length > 0) {
400
- const owners = [...new Set(othersResidual)].filter(Boolean)
401
- console.warn(`⚠️ 检测到「他者半归档」残留(暂存区存在其他变更的 rename 记录):${owners.join('、')}`)
402
- console.warn(` 这些是别的变更此前手动归档留下的暂存项,不属于本次归档——git status 里看到它们是正常的,`)
403
- console.warn(` 本变更归档已完成,无需为其做第二次提交;如需清理走它们自己的收尾(或 git restore --staged 后核对)。`)
404
- }
405
- }
406
- } catch { /* 探测失败不阻断归档(advisory) */ }
407
-
408
- // 归档时清理可能残留的 worktree(自愈路径也复用,见上方 srcDir 缺失分支)。
409
- await archiveWorktreeCleanup(cwd, archiveChangeName, specBase, platformOpts)
410
-
411
- console.log(`📦 已归档:${archiveChangeName} → archive/${destName}/`)
412
- return destDir
413
- }
414
- /**
415
- * archive 阶段「确认归档」步骤的收尾处理器(从 completeStep 抽出,行为保持)。
416
- *
417
- * 两件事:
418
- * 1. --confirm 门控:缺 --confirm → 回退 step 状态、提示、返回 early-return 对象(completeStep 透传)
419
- * 2. --confirm 通过 → archiveChangeDirectory 移动变更目录 + 推荐文档(design.md / module-impact.md)校验
420
- * (contracts.archive.validators 为空,两个 validator 生效窗口互斥;plan.md 已在移动前硬校验阻断)
421
- *
422
- * @returns {{stageCompleted:false,currentIdx,nextPendingIdx:number}|null}
423
- */
424
- export async function handleArchiveConfirmStep({ stageName, steps, currentIdx, confirm, outputText, pm, cwd, progress, changeName, specBase, platformOpts = {} }) {
425
- if (stageName !== 'archive' || steps[currentIdx]?.name !== '确认归档') return null
426
- if (!confirm) {
427
- steps[currentIdx].status = 'pending'
428
- steps[currentIdx].completedAt = null
429
- if (outputText) steps[currentIdx].output = null
430
- pm._write(cwd, progress, changeName)
431
- console.log('⚠️ 请添加 --confirm 确认归档,例如:sillyspec run archive --done --confirm --output "确认归档"')
432
- return { stageCompleted: false, currentIdx, nextPendingIdx: currentIdx }
433
- }
434
- // 主仓互斥锁(坑 main-repo-no-mutex 二批):archiveChangeDirectory 改主仓共享状态(目录
435
- // rename + 共享 index 的 git add + marker 删除 + worktree 清理),与并行会话的 apply/cleanup
436
- // 互踩。exit 钩子兜底:其内部 guard 失败 exit(1) 时锁也会被清(见 withMainRepoLock)。
437
- const { withMainRepoLock } = await import('../worktree-apply.js')
438
- const archivedDir = await withMainRepoLock(cwd, changeName, 'archive-finalize', () => archiveChangeDirectory(pm, cwd, progress, specBase, platformOpts))
439
- if (archivedDir && existsSync(archivedDir)) {
440
- // 内存快照同步(坑 archive-progress-show-stale,2026-08-21 实证):archiveChangeDirectory 内
441
- // unregisterChange 已在 DB 写 current_stage='archive'(终态一致化),但本进程 progress 是命令
442
- // 开始时读的旧快照——不同步的话,completeStep 后续 _write 会用旧值(如停在 verify)把
443
- // DB 覆盖回去,progress show 就一直显示归档前的阶段
444
- progress.currentStage = 'archive'
445
- const recommendedDocs = ['design.md', 'module-impact.md']
446
- const missingRecommended = recommendedDocs.filter(d => !existsSync(join(archivedDir, d)))
447
- if (missingRecommended.length > 0) {
448
- console.warn(`\n⚠️ 归档校验警告:归档目录缺少推荐文档`)
449
- for (const d of missingRecommended) console.warn(` - ${d}(${archivedDir})`)
450
- } else {
451
- console.log(`\n✅ 归档校验通过:核心文档齐全`)
452
- }
453
- // D-4 窄口径:更新结果表 done 行声明的目标文档存在性对账(warning 不阻断——
454
- // 目标路径写法多样(modules/x.md 相对/全路径)+ 语义对账推 sillyhub,此处只抓
455
- // 能确定性解析且确实不存在的假申报)。
456
- const impactContent = existsSync(join(archivedDir, 'module-impact.md'))
457
- ? readFileSync(join(archivedDir, 'module-impact.md'), 'utf8') : ''
458
- const doneTargets = extractDoneDocTargets(impactContent)
459
- if (doneTargets.length > 0) {
460
- const missing = doneTargets.filter(t => {
461
- // 相对 specBase 解析:modules/<x> → docs/<project>/modules/<x> 由 _module-map 归属,
462
- // CLI 不猜 project——只对全路径(.sillyspec/docs/ 开头或含 3+ 段路径)做存在性判定
463
- if (!t.includes('/')) return false
464
- const abs = isAbsolute(t) ? t : resolve(cwd, t)
465
- return !existsSync(abs)
466
- })
467
- if (missing.length > 0) {
468
- console.warn(`\n⚠️ 归档校验警告:module-impact「更新结果」声明 done 的文档路径不存在(假申报嫌疑)`)
469
- for (const t of missing) console.warn(` - ${t}`)
470
- console.warn(` 相对写法(modules/<id>.md)不在此校验范围;全路径声明但文件不存在请核实。`)
471
- }
472
- }
473
- }
474
- return null
475
- }
476
- /**
477
- * plan 阶段「generate_plan」步骤完成后,动态插入任务蓝图(coordinator)+ postcheck 步骤
478
- * (从 completeStep 抽出,行为保持)。使用稳定 id 匹配,不依赖中文标题。
479
- *
480
- * plan.md 已含任务时,buildPlanSteps 返回 [fixedPrefix(classify/generate_plan/review_plan),
481
- * coordinator, postcheck];本函数把 generate_plan 之后的 coordinator+postcheck 插到当前步后。
482
- */
483
- export async function handlePlanGeneratePlanStep({ stageName, steps, currentIdx, defStepsForCurrent, cwd, progress }) {
484
- if (stageName !== 'plan') return
485
- const currentStepDef = defStepsForCurrent?.[currentIdx]
486
- const currentStepEntry = steps[currentIdx]
487
- const stepId = currentStepDef?.id || currentStepEntry?.id || currentStepEntry?._stepId
488
- if (stepId !== 'generate_plan') return
489
- const changeDir = resolveChangeDir(cwd, progress)
490
- if (!changeDir) return
491
- const planFile = join(changeDir, 'plan.md')
492
- if (!existsSync(planFile)) return
493
- const planContent = readFileSync(planFile, 'utf8')
494
- const { buildPlanSteps, fixedPrefix, fixedSuffix } = await import('../stages/plan.js')
495
- const fullSteps = buildPlanSteps(changeDir, planContent)
496
- const prefixLen = fixedPrefix.length
497
- const suffixLen = fixedSuffix.length
498
- // 新结构:[...fixedPrefix, coordinatorStep?, postcheckStep?];fixedSuffix 为空,coordinator+postcheck 都在 prefix 之后
499
- const coordinatorSteps = fullSteps.slice(prefixLen, suffixLen > 0 ? -suffixLen : undefined)
500
- if (coordinatorSteps.length === 0) return
501
- for (let i = 0; i < coordinatorSteps.length; i++) {
502
- const stepDef = coordinatorSteps[i]
503
- const stepEntry = {
504
- id: stepDef.id,
505
- name: stepDef.name,
506
- status: 'pending',
507
- prompt: stepDef.prompt || '',
508
- outputHint: stepDef.outputHint,
509
- optional: stepDef.optional
510
- }
511
- // 传递 noAI / _cliAction 属性
512
- if (stepDef.noAI) stepEntry.noAI = true
513
- if (stepDef._cliAction) stepEntry._cliAction = stepDef._cliAction
514
- steps.splice(currentIdx + 1 + i, 0, stepEntry)
515
- }
516
- console.log(` 📝 已动态插入 ${coordinatorSteps.length} 个步骤(${coordinatorSteps.map(s => s.name).join(', ')})`)
517
- }
518
- /**
519
- * scan 阶段 step 2「构建扫描项目列表」完成后,按项目展开 perProject 步骤(从 completeStep 抽出,行为保持)。
520
- *
521
- * 只接受结构化输出(scan_projects YAML block 或 BEGIN_PROJECT_LIST 标记块),校验通过后
522
- * 自动注册 projects/<id>.yaml + 写 scan-projects.json + 把 perProject 步骤按项目展开。
523
- * 不展开 completeStep 提前 return(失败只记 validationError,由 completeStep 继续推进下一步)。
524
- */
525
- export async function handleScanProjectListStep({ stageName, steps, currentIdx, outputText, stageData, specBase, cwd, platformOpts }) {
526
- if (stageName !== 'scan' || steps[currentIdx]?.name !== '构建扫描项目列表') return
527
- // 解析项目列表:只接受结构化输出(YAML block 或 BEGIN_PROJECT_LIST 标记)
528
- // 不再从自由文本猜测项目名——自由文本列表的误解析会导致垃圾项目落盘
529
- let parsedProjects = [] // Array<{id, path?}>
530
- let parsedFromStructuredOutput = false
531
- if (outputText) {
532
- // 格式 A: YAML block — 匹配 scan_projects: 下所有 - id: xxx 条目(含多行属性)
533
- const yamlBlock = outputText.match(/scan_projects:\s*\n([\s\S]+?)(?=$|\n[^\s])/)
534
- if (yamlBlock) {
535
- const entries = [...yamlBlock[1].matchAll(/-\s+id:\s*(\S+)(?:[\s\S]*?)(?=\n\s+-\s+id:|$)/g)]
536
- for (const m of entries) {
537
- const id = sanitizeProjectName(m[1])
538
- if (!id) continue
539
- // 提取可选 path 字段
540
- const pathMatch = m[0].match(/path:\s*(\S+)/)
541
- const entry = pathMatch ? { id, path: pathMatch[1].trim() } : { id }
542
- parsedProjects.push(entry)
543
- }
544
- parsedFromStructuredOutput = parsedProjects.length > 0
545
- }
546
- // 格式 B: BEGIN_PROJECT_LIST ... END_PROJECT_LIST 标记块
547
- if (!parsedFromStructuredOutput) {
548
- const blockMatch = outputText.match(/BEGIN_PROJECT_LIST\s*\n([\s\S]*?)\n*END_PROJECT_LIST/)
549
- if (blockMatch) {
550
- const raw = [...blockMatch[1].matchAll(/^-\s+(\S+)/gm)].map(m => m[1])
551
- parsedProjects = raw.map(s => sanitizeProjectName(s)).filter(Boolean).map(id => ({ id }))
552
- parsedFromStructuredOutput = parsedProjects.length > 0
553
- }
554
- }
555
- }
556
-
557
- const projectNames = parsedProjects.map(p => p.id)
558
-
559
- if (parsedFromStructuredOutput) {
560
- stageData.scanMeta = stageData.scanMeta || {}
561
- stageData.scanMeta.projectListParsed = true
562
- } else {
563
- // 结构化输出未解析到 → 回退读取已有 projects/*.yaml
564
- // 读取时也校验:path 不存在的 yaml 视为垃圾,直接跳过
565
- console.warn('⚠️ step 2 未输出结构化项目列表,回退扫描已注册项目')
566
- stageData.scanMeta = stageData.scanMeta || {}
567
- stageData.scanMeta.projectListParsed = false
568
- const projectsDir = join(specBase, 'projects')
569
- if (existsSync(projectsDir)) {
570
- const yamlFiles = readdirSync(projectsDir).filter(f => f.endsWith('.yaml'))
571
- const fallbackProjects = []
572
- const fallbackSkipped = []
573
- for (const yf of yamlFiles) {
574
- const pName = yf.replace(/\.yaml$/, '')
575
- const yamlContent = readFileSync(join(projectsDir, yf), 'utf8')
576
- const pathMatch = yamlContent.match(/^path:\s*(.+)/m)
577
- const pPath = pathMatch ? pathMatch[1].trim() : pName
578
- // 校验 path 是否存在且在 source_root 内。
579
- // 用 relative 判越界(与 validateParsedProjects 同口径):startsWith 前缀比较
580
- // 无分隔符,C:\repo 会放行兄弟目录 C:\repository2(体检 BUG-13)
581
- const absPath = resolve(cwd, pPath)
582
- const rel = relative(resolve(cwd), absPath)
583
- if (rel.startsWith('..') || isAbsolute(rel)) {
584
- fallbackSkipped.push(`${pName} (path 越界: ${pPath})`)
585
- continue
586
- }
587
- if (!existsSync(absPath)) {
588
- fallbackSkipped.push(`${pName} (path 不存在: ${pPath})`)
589
- continue
590
- }
591
- fallbackProjects.push({ id: pName, path: pPath })
592
- }
593
- if (fallbackSkipped.length > 0) {
594
- console.warn(`⚠️ 跳过 ${fallbackSkipped.length} 个垃圾/过期项目配置:${fallbackSkipped.join(', ')}`)
595
- console.warn(' 建议清理 projects/ 下的无效 yaml 文件')
596
- }
597
- parsedProjects = fallbackProjects
598
- projectNames.length = 0
599
- projectNames.push(...fallbackProjects.map(p => p.id))
600
- }
601
- if (parsedProjects.length === 0) {
602
- // 无结构化输出 + 无合法已有项目 → step 2 失败
603
- console.error('❌ step 2 未输出结构化项目列表,且 projects/ 下无合法项目配置')
604
- console.error(' 请在 --output 中输出 scan_projects YAML block 或 BEGIN_PROJECT_LIST 标记块')
605
- steps[currentIdx].validationError = '未输出结构化项目列表且无合法 fallback'
606
- // 不展开 perProject 步骤,直接跳到下一步
607
- }
608
- }
609
-
610
- // 校验解析出的项目列表(原子守卫:不通过就不落盘)
611
- const validation = validateParsedProjects(parsedProjects, cwd)
612
- if (!validation.ok) {
613
- console.error(`❌ 项目列表校验失败: ${validation.errors.join('; ')}`)
614
- console.error(' step 2 完成,但不展开 perProject 步骤。请检查 --output 中的项目列表。')
615
- steps[currentIdx].validationError = validation.errors.join('; ')
616
- }
617
-
618
- // 自动注册 + 保存 runtime + 展开 perProject 步骤(仅在校验通过时)
619
- const projectsDir = join(specBase, 'projects')
620
- if (validation.ok) {
621
- for (const proj of parsedProjects) {
622
- const pName = proj.id
623
- const projYaml = join(projectsDir, `${pName}.yaml`)
624
- if (!existsSync(projYaml)) {
625
- mkdirSync(projectsDir, { recursive: true })
626
- const candidates = [
627
- join(cwd, pName),
628
- join(cwd, 'backend', pName),
629
- join(cwd, 'packages', pName),
630
- join(cwd, 'apps', pName),
631
- join(cwd, 'services', pName),
632
- ]
633
- const detected = candidates.find(c => existsSync(c))
634
- const regPath = detected || join(cwd, pName)
635
- writeFileSync(projYaml, `name: ${pName}\npath: ${regPath}\nstatus: active\n`)
636
- console.log(` 📝 自动注册子项目: ${pName} → ${regPath}`)
637
- }
638
- }
639
-
640
- // 保存 runtime 状态
641
- const scanStatePath = join(specBase, '.runtime', 'scan-projects.json')
642
- mkdirSync(join(specBase, '.runtime'), { recursive: true })
643
- let scanState = { projects: projectNames, expanded: false }
644
- if (existsSync(scanStatePath)) {
645
- try { scanState = JSON.parse(readFileSync(scanStatePath, 'utf8')) } catch {}
646
- }
647
-
648
- // 收集当前步骤之后所有 perProject 步骤
649
- const stageDef = stageRegistry[stageName]
650
- const allSteps = stageDef?.steps || []
651
- const perProjectSteps = allSteps.filter(s => s.perProject)
652
-
653
- // 防重复展开
654
- const alreadyExpanded = scanState.expanded || steps.some(s => s.name?.match(/\[.+\]\s*$/))
655
- if (!alreadyExpanded && perProjectSteps.length > 0) {
656
- // 找到当前步骤(step 2)在动态 steps 中的位置
657
- const insertBase = currentIdx + 1
658
- let insertPos = insertBase
659
- for (const pName of projectNames) {
660
- // 读取项目配置获取 projectRoot
661
- const projYaml = join(specBase, 'projects', `${pName}.yaml`)
662
- let projectRoot = '.'
663
- if (existsSync(projYaml)) {
664
- const yamlContent = readFileSync(projYaml, 'utf8')
665
- const pathMatch = yamlContent.match(/^path:\s*(.+)/m)
666
- if (pathMatch) projectRoot = pathMatch[1].trim()
667
- }
668
- const docOutputDir = platformOpts.specRoot ? `${specBase}/docs/${pName}` : `.sillyspec/docs/${pName}`
669
- const contextPrefix = `\n---\n## 当前项目\n- **项目名**: ${pName}\n- **项目路径**: ${projectRoot}\n- **文档输出**: ${docOutputDir}\n\n⚠️ 本步骤只处理上面这个项目,不要处理其他项目。\n---\n\n`
670
-
671
- for (const ppStep of perProjectSteps) {
672
- steps.splice(insertPos, 0, {
673
- name: `${ppStep.name} [${pName}]`,
674
- project: pName,
675
- status: 'pending',
676
- prompt: contextPrefix + ppStep.prompt,
677
- outputHint: ppStep.outputHint,
678
- optional: ppStep.optional
679
- })
680
- insertPos++
681
- }
682
- }
683
- // 移除原始的 perProject 步骤(未展开的版本)
684
- for (let i = steps.length - 1; i >= 0; i--) {
685
- if (steps[i].perProject && !steps[i].name?.includes('[')) {
686
- steps.splice(i, 1)
687
- }
688
- }
689
- console.log(` 📝 已按项目展开 ${perProjectSteps.length} 个步骤 × ${projectNames.length} 个项目 = ${perProjectSteps.length * projectNames.length} 个项目步骤`)
690
- console.log(` 📁 扫描项目:${projectNames.join(', ')}`)
691
- // 标记已展开,防止 resume 重复插入
692
- scanState.expanded = true
693
- writeFileSync(scanStatePath, JSON.stringify(scanState))
694
- } // end !alreadyExpanded
695
- } // end validation.ok
696
- }
697
- /**
698
- * Workflow post_check(W6 Step6 从 completeStep 内联块抽出):
699
- * - scan「深度扫描」完成 → 跑 scan-docs workflow postcheck,失败阻断推进(early-return)
700
- * - archive「extract-module-impact」完成 → 跑 archive-impact workflow postcheck(impact-analyzer 结果)
701
- * 返回 early-return 对象({stageCompleted:false,...})由 completeStep 透传;null = 放行。
702
- *
703
- * ctx 字段:stageName/steps/currentIdx/cwd/specBase/progress/platformOpts/changeName(completeStep 局部)。
704
- * 辅助函数直接 import:basename/join/existsSync/readdirSync(顶部静态);loadWorkflow/runPostCheck/
705
- * formatCheckReport/saveWorkflowRun 动态 import ../workflow.js(真环依赖保留动态)。
706
- *
707
- *搬迁清理:删除死代码 `typeof change !== 'undefined'`(completeStep 作用域无 change 变量,恒 null)。
708
- */
709
- export async function handleWorkflowPostCheck({ stageName, steps, currentIdx, cwd, specBase, progress, platformOpts, changeName }) {
710
- // Workflow post_check:scan 深度扫描完成后自动检查产物
711
- if (stageName === 'scan' && steps[currentIdx]?.name?.includes('深度扫描')) {
712
- try {
713
- const { loadWorkflow, runPostCheck, formatCheckReport, saveWorkflowRun } = await import('../workflow.js')
714
- const wf = loadWorkflow(cwd, 'scan-docs')
715
- if (wf) {
716
- // 确定当前项目(优先级链):
717
- // progress.project (dbProjectName,平台模式真实项目名,与 outputStep 占位符渲染对齐)
718
- // > change?.project (变更对象的项目字段,平台模式 change 创建时传入)
719
- // > steps[idx].project (perProject 展开标记,兼容旧模式)
720
- // > steps[idx].name 正则提取 [xxx] 后缀
721
- // > null(回退检查所有项目)
722
- // task-05 修复:日志显示项目名变 frontend 是 perProject 误展开 bug,
723
- // 用 progress.project(与 outputStep 占位符渲染路径一致)修正 myaaa/frontend 分裂。
724
- const currentProjectName = progress.project
725
- || steps[currentIdx].project
726
- || (steps[currentIdx].name.match(/\[([^\]]+)\]\s*$/) || [])[1]
727
- || null
728
-
729
- // 确定要检查的项目列表
730
- let projectsToCheck = []
731
- if (currentProjectName) {
732
- // 按项目展开模式:只检查当前项目
733
- projectsToCheck = [currentProjectName]
734
- } else {
735
- // 兼容旧模式(未展开):检查所有项目
736
- const projectsDir = join(specBase, 'projects')
737
- const projectFiles = existsSync(projectsDir)
738
- ? readdirSync(projectsDir).filter(f => f.endsWith('.yaml'))
739
- : []
740
- projectsToCheck = projectFiles.map(f => f.replace(/\.yaml$/, ''))
741
- }
742
-
743
- let anyFailed = false
744
- for (const pName of projectsToCheck) {
745
- const result = runPostCheck(wf, cwd, pName, {}, specBase)
746
- const report = formatCheckReport(result)
747
- console.log(report)
748
- if (result.status === 'fail') {
749
- anyFailed = true
750
- // retry_prompts 由 _checkWorkflow 自动生成
751
- for (const rp of (result.retry_prompts || [])) {
752
- console.log(`\n🔄 重试提示(项目 ${pName}):\n`)
753
- console.log(rp.prompt)
754
- }
755
- }
756
- const saved = saveWorkflowRun(result, {
757
- cwd,
758
- source: 'run.js',
759
- stage: 'scan',
760
- step: steps[currentIdx]?.name,
761
- ...(platformOpts.runtimeRoot ? { runtimeRoot: platformOpts.runtimeRoot } : {}),
762
- ...(platformOpts.scanRunId ? { scanRunId: platformOpts.scanRunId } : {})
763
- })
764
- if (saved) console.log(`📁 结果已归档:${saved}`)
765
- }
766
- if (anyFailed) {
767
- console.log(`\n⚠️ 存在检查失败项,请按上面的重试提示修复后再继续。`)
768
- // task-07: 阻断推进(与 task-06 平台模式 scan-postcheck 失败分支 return 结构对齐)
769
- // scan 深度扫描产物校验未通过时,不允许 clean success / 进入下一 step,
770
- // 让上层走"完成但不推进"分支,--done 被拒。
771
- return { stageCompleted: false, currentIdx, nextPendingIdx: currentIdx }
772
- }
773
- }
774
- } catch (e) {
775
- console.warn(`⚠️ workflow 检查跳过:${e.message}`)
776
- }
777
- }
778
-
779
- // Workflow post_check:archive extract-module-impact 完成后检查产物
780
- if (stageName === 'archive' && steps[currentIdx]?.name?.includes('extract-module-impact')) {
781
- try {
782
- const { loadWorkflow, runPostCheck, formatCheckReport, saveWorkflowRun } = await import('../workflow.js')
783
- const wf = loadWorkflow(cwd, 'archive-impact')
784
- if (wf && changeName) {
785
- const raw = JSON.stringify(wf)
786
- const resolved = JSON.parse(raw.replace(/<change-name>/g, changeName))
787
- const result = runPostCheck(resolved, cwd, progress.project || basename(cwd), {}, specBase)
788
- // 只报告 impact-analyzer 的结果(doc-syncer 是后续步骤)
789
- const impactResult = (result.roles || []).find(r => r.id === 'impact-analyzer')
790
- if (impactResult) {
791
- const icon = impactResult.status === 'pass' ? '✅' : '❌'
792
- console.log(`${icon} module-impact.md 检查${impactResult.status === 'pass' ? '通过' : '失败'}`)
793
- for (const f of (result.failures || []).filter(f => f.role_id === 'impact-analyzer')) {
794
- // f 是 {level,role_id,output,check,message} 对象——直接 ${f} 打印裸 [object Object](ql-20260819-006);
795
- // message 才是人类可读 detail(如「缺少章节: …」),缺字段时 stringify 兜底防再退化成不可诊断输出
796
- console.log(` └─ ${f.message ?? JSON.stringify(f)}`)
797
- }
798
- }
799
- const saved = saveWorkflowRun(result, {
800
- cwd,
801
- source: 'run.js',
802
- stage: 'archive',
803
- step: steps[currentIdx]?.name,
804
- ...(platformOpts.runtimeRoot ? { runtimeRoot: platformOpts.runtimeRoot } : {}),
805
- ...(platformOpts.scanRunId ? { scanRunId: platformOpts.scanRunId } : {})
806
- })
807
- if (saved) console.log(`📁 结果已归档:${saved}`)
808
- }
809
- } catch (e) {
810
- console.warn(`⚠️ workflow 检查跳过:${e.message}`)
811
- }
812
- }
813
- return null
814
- }
815
- /**
816
- * quick 阶段完成收尾(W6 Step6b 从 completeStep 内联块抽出):
817
- * 强校验 QUICKLOG 条目 + 审计(auditQuickCompletion)+ 结果摘要结构校验 + 翻状态/勾 tasks.md
818
- * (CLI 接管 QUICKLOG 分配/写入/收尾)。blocked → process.exit(1)(无 early-return,调用点纯 await)。
819
- *
820
- * ctx:stageName/steps/currentIdx/cwd/progress/changeName/specBase/outputText/confirm/
821
- * isForceBaseline/isAllowNew/platformOpts。辅助函数直接 import(safeGit/auditQuickCompletion ← shared,
822
- * printQuickAuditReview ← quick-audit,4 个 quicklog fns ← quicklog,unlinkSync/rmSync ← fs 静态)。
823
- */
824
- export async function handleQuickStageCompletion({ stageName, steps, currentIdx, cwd, progress, changeName, specBase, outputText, confirm, isForceBaseline, isAllowNew, isAllowDelete, platformOpts, pm }) {
825
- // quick 收尾:强校验 QUICKLOG 条目 + 翻状态 + 勾 tasks.md(CLI 接管)
826
- if (stageName === 'quick') {
827
- // §4.6 从 session guard.json 读 guard(不依赖 progress.quickGuard)。
828
- // D-003@v1:progress._write 不持久化顶层 quickGuard,跨进程 --done 时读出的 progress 无 quickGuard,
829
- // 若仍用 if (progress.quickGuard) 驱动收尾会整体跳过,导致 .runtime/quick-sessions/<sessionId>/ 残留僵尸。
830
- // 改为从文件读 guard:优先 session 目录 guard.json,回退旧单文件 quick-guard.json(task-03 前兼容)。
831
- // sessionId == changeName == quick-<uuid8>(completeStep 作用域内 changeName 已解构自 options)。
832
- // session 目录经 resolveQuickSessionsDir 单一解析(multi-agent-review Q4):与 stage.js 写入路径对齐,
833
- // 平台模式 runtimeRoot 与 specBase/.runtime 不同时不再读不到 guard。
834
- const sessionGuardFile = join(resolveQuickSessionsDir(platformOpts, specBase), changeName, 'guard.json')
835
- const legacyGuardFile = join(specBase, '.runtime', 'quick-guard.json')
836
- let guard = null
837
- try {
838
- guard = existsSync(sessionGuardFile)
839
- ? JSON.parse(readFileSync(sessionGuardFile, 'utf8'))
840
- : (existsSync(legacyGuardFile) ? JSON.parse(readFileSync(legacyGuardFile, 'utf8')) : null)
841
- } catch {}
842
-
843
- // 强校验 / 收尾:本会话必须有一条真实 QUICKLOG 条目(治「报 SAFE 但漏写」bug)。
844
- // guard 缺失(brownfield:新代码前启动的会话)不阻断——兜底补写一条记录,保住「完成必有记录」不变量。
845
- const gitUser = safeGit(cwd, ['config', 'user.name']).value || 'unknown'
846
- let qlId = guard?.quicklogId || null
847
- const linkedChanges = Array.isArray(guard?.linkedChanges) ? guard.linkedChanges : []
848
- // 审计结果(仅 guard 存在时填充)。提到 if(guard) 外声明,供下方回填 QUICKLOG 文件行复用
849
- // review.changedFiles;brownfield 无 guard 时保持 null → 文件行不回填(降级,不报错)。
850
- let review = null
851
-
852
- // 审计:仅在有 guard 时跑(brownfield 无 guard 跳过,兼容 D-003 brownfield 行为)。
853
- // task-02:mergedGuard 提升到 if 外声明,供下方并发预检钩子复用与 auditQuickCompletion
854
- // 同源的 guard 字段(baselineFiles/linkedChanges)。brownfield 无 guard 时保持 null,
855
- // 钩子 ownFiles/linkedChanges 走 ?? [] 兜底(D-003 不抛 TypeError)。
856
- let mergedGuard = null
857
- if (guard) {
858
- // --done 的 --force-baseline/--allow-new 并入 guard(与 step1 持久化值取或)。
859
- // 修复 ql-20260713-002-7628:旧代码解析了这两个 flag 但只传 {isConfirm} 给审计,
860
- // 致 --done --force-baseline 静默无效、用户被误导「重跑 --confirm」也无法解锁。
861
- mergedGuard = {
862
- ...guard,
863
- forceBaseline: guard.forceBaseline || isForceBaseline,
864
- allowNew: guard.allowNew || isAllowNew,
865
- allowDelete: guard.allowDelete || isAllowDelete,
866
- // O-1(docs-signals-o12):specBase/projectName 透传给审计——docSyncHint 模块归属用
867
- // (平台模式 resolveSpecDir(cwd) 会 miss specRoot 静默丢信号,plan 审查 gap-5)
868
- specBase,
869
- projectName: progress?.project || null,
870
- // 他者 active 会话声明索引(坑 foreign-session-declared-false-block):多 agent 并发时
871
- // 并行会话 --files 声明的文件退栈归该会话审计,不再误拦本会话。与上方 guard 读取同源
872
- // (resolveQuickSessionsDir 同参,平台模式 runtimeRoot 对齐);fail-open:采集失败 → 空
873
- // → 回到无豁免现状。
874
- otherSessionsDeclared: collectOtherQuickSessionDeclarations(platformOpts, specBase, changeName),
875
- }
876
- review = await auditQuickCompletion(cwd, mergedGuard, { isConfirm: confirm })
877
- printQuickAuditReview(review)
878
- if (review.status === 'blocked') {
879
- steps[currentIdx].status = 'pending'
880
- steps[currentIdx].completedAt = null
881
- if (outputText) steps[currentIdx].output = null
882
- process.exit(1)
883
- }
884
- progress.lastQuickReview = review
885
- }
886
-
887
- // task-02 并发预检(FR-05/FR-07,纯副作用 advisory):auditQuickCompletion 返回后、推进前
888
- // 扫工作树,识别他者未提交改动 / 他者脏变更目录,有则 console.warn。不改 status/gate、
889
- // 不 exit、不 return early(FR-07 铁律)。ownFiles 必含 baselineFiles(D-001:脏工作树 quick
890
- // 完成时本会话 baseline 不被他者误报);review/mergedGuard 均可能为 null(brownfield 无 guard,
891
- // D-003),用 ?. + ?? [] 兜底防 spread undefined 抛 TypeError(B-005)。整钩子 try/catch 隔离
892
- // ——detect 本就 fail-open,保守再包一层,任何异常只吞不 bubble,主完成流程不受影响。
893
- try {
894
- // ownFiles 锚点(2026-08-18 误归属修复):声明会话 = baselineFiles ∪ allowedFiles(声明即归属),
895
- // 不再用 changedFiles 全量——他者窗口文件已被污染进 changedFiles,旧口径自吞致预检对
896
- // ql-20260818-003 形态结构性失明。未声明会话维持旧口径(changed ∪ baseline):无声明无归属
897
- // 信息,收窄锚点会把自身未声明改动全误报他者。resolveConcurrentAnchor 纯函数(concurrent-detect)。
898
- const ownFiles = resolveConcurrentAnchor({
899
- changedFiles: review?.changedFiles ?? [],
900
- baselineFiles: mergedGuard?.baselineFiles ?? [],
901
- allowedFiles: mergedGuard?.allowedFiles ?? [],
902
- })
903
- const detected = detectConcurrentChanges(cwd, {
904
- changeName,
905
- linkedChanges: mergedGuard?.linkedChanges ?? [],
906
- ownFiles,
907
- })
908
- const warn = formatConcurrentWarning(detected)
909
- if (warn) console.warn(warn)
910
- } catch (e) {
911
- // fail-open:并发预检异常绝不阻断主完成流程(FR-07)。
912
- }
913
-
914
- // 结果摘要结构校验(最后一步、isDone 且带了 --output 时):--output 是 QUICKLOG「结果:」
915
- // 归档的唯一来源,要求按 需求/根因/方案/结果 模板给全(见 stages/quick.js step3 prompt)。
916
- // 确定性校验:只查必填字段是否齐全,不判内容质量。缺字段 → 本次不完成(回滚 step 状态 +
917
- // exit 1),保留「进行中」条目,agent 补全 --output 后重跑 --done 即可,不丢进度。
918
- // 仅 completeQuicklogEntry 会实际持久化时才校验;前两个 step 的 --done output 不入 QUICKLOG,不校验。
919
- // Q6:quick 末步 --done 必须带 --output(四字段结果是 QUICKLOG「结果:」唯一来源)。缺则回退 pending +
920
- // exit(1),不静默落空结果条目(原 if(outputText) 守卫致 outputText 为空时跳过校验,completeQuicklogEntry
921
- // 又用 outputText||'' 兜底 → 结果块为空却翻「已完成」)。handleQuickStageCompletion 仅在阶段完成(=末步)时触发。
922
- const isLastStep = currentIdx === steps.length - 1
923
- if (isLastStep && !outputText) {
924
- console.error('\n❌ quick 最后一步 --done 必须带 --output(四字段结果模板)。')
925
- console.error(' --output 是 QUICKLOG「结果:」归档的唯一来源。补全后重跑 --done(不丢进度),推荐四参数形式(CLI 自动合成,无嵌套冒号事故面):')
926
- console.error(' sillyspec run quick --done --change <changeName> --req "一句话语义化短标题" --cause "为什么这样改" --solution "怎么改的" --result "验证情况(测试数 / lint / typecheck / 部署状态)"')
927
- console.error(' 兼容旧形式:--output "需求:… 根因:… 方案:… 结果:…"')
928
- steps[currentIdx].status = 'pending'
929
- steps[currentIdx].completedAt = null
930
- process.exit(1)
931
- }
932
- if (outputText) {
933
- const resultCheck = validateQuickResult(outputText)
934
- if (!resultCheck.ok) {
935
- console.error('\n' + getRule('quick.result-labels').failMessage.replaceAll('${missing}', resultCheck.missing.join('、')))
936
- console.error(` --output 是 QUICKLOG「结果:」归档的唯一来源,四个标签必须放在 --output 里(不是 --input)。`)
937
- console.error(` 补全后重跑 --done(不丢进度)。推荐四参数形式(CLI 自动合成结构化模板,避免旧形式嵌套全角冒号被拆分判定缺字段):`)
938
- console.error(` sillyspec run quick --done --change <changeName> --req "一句话语义化短标题(即 QUICKLOG 条目标题)" --cause "为什么这样改(纯新增/样式则写「无,纯新增/纯样式」)" --solution "怎么改的" --result "验证情况(测试数 / lint / typecheck / 部署状态)"`)
939
- console.error(` 或照抄旧形式模板:`)
940
- console.error(` sillyspec run quick --done --change <changeName> --output "需求:用户/任务要什么`)
941
- console.error(` 根因:为什么这样改(纯新增/样式则写「无,纯新增/纯样式」)`)
942
- console.error(` 方案:怎么改的`)
943
- console.error(` 结果:验证情况(测试数 / lint / typecheck / 部署状态)"`)
944
- steps[currentIdx].status = 'pending'
945
- steps[currentIdx].completedAt = null
946
- if (outputText) steps[currentIdx].output = null
947
- process.exit(1)
948
- }
949
- }
950
-
951
- if (!qlId) {
952
- // 无 ql-ID(guard 缺失或 brownfield 无 quicklogId):补分配后立即完成,不阻断。
953
- try {
954
- const alloc = await allocateQuicklogEntry(specBase, gitUser, {
955
- description: guard?.taskDescription || '(补分配)',
956
- linkedChanges,
957
- allowedFiles: Array.isArray(guard?.allowedFiles) ? guard.allowedFiles : [],
958
- })
959
- qlId = alloc.qlId
960
- console.log(`📝 QUICKLOG 兜底补写: ${qlId}(guard 缺失/brownfield 会话)`)
961
- } catch (e) {
962
- console.error(`\n❌ QUICKLOG 补分配失败: ${e.message}`)
963
- steps[currentIdx].status = 'pending'
964
- steps[currentIdx].completedAt = null
965
- if (outputText) steps[currentIdx].output = null
966
- process.exit(1)
967
- }
968
- }
969
- if (!findQuicklogEntry(specBase, gitUser, qlId)) {
970
- console.error(`\n❌ quick 阶段完成校验失败:QUICKLOG 条目 ${qlId} 不存在。`)
971
- console.error(` 会话期间记录被删除或从未写入。请检查 .sillyspec/quicklog/ 后重跑 --done。`)
972
- steps[currentIdx].status = 'pending'
973
- steps[currentIdx].completedAt = null
974
- if (outputText) steps[currentIdx].output = null
975
- process.exit(1)
976
- }
977
- // 翻状态进行中→已完成 + 追加结果 + 勾选关联 tasks.md
978
- // resultText 不再截断:结构化结果块(需求/根因/方案/结果)完整落盘,多行写成字段化块。
979
- try {
980
- // 回填实际改动文件:review.changedFiles 含 quick 自身元数据(quicklog/.runtime/modules 等),
981
- // 用 isQuickMetadata 过滤掉,只留真实业务文件。brownfield 无 review → 空数组,文件行不动。
982
- // 归属口径(2026-08-18 误归属修复):声明会话优先 attributedFiles(窗口∩声明∪同文件并发命中),
983
- // 他者窗口文件不进文件行;未声明会话/旧 review 无 attributedFiles → 兜底 changedFiles 全量。
984
- const auditFiles = Array.isArray(review?.attributedFiles)
985
- ? review.attributedFiles
986
- : (Array.isArray(review?.changedFiles) ? review.changedFiles : [])
987
- const realFiles = auditFiles.filter(f => !isQuickMetadata(f, linkedChanges))
988
- // D-8 落盘(2026-08-18 修):advisory 欠账信号从「纯打印」升级为「随条目落盘」——修复
989
- // 「欠账已记录(QUICKLOG reasons)」的不实承诺(交叉审查实证 reasons 纯 stdout,事后不可审计)。
990
- // 两周实测(2026-08-31 裁决,doc-consistency-debt §七)需要分母:信号触发次数必须可追溯。
991
- const auditNotes = []
992
- if (review?.docSyncHint && review.docSyncHint.touchedSource > 0 && review.docSyncHint.docFiles.length === 0) {
993
- const mods = Array.isArray(review.docSyncHint.modules) && review.docSyncHint.modules.length > 0
994
- ? `(涉及模块:${review.docSyncHint.modules.map((m) => m.id).join(' · ')})` : ''
995
- auditNotes.push(`📝 文档欠账(D-8):${review.docSyncHint.touchedSource} 个源码文件改动未同步任何模块文档${mods}`)
996
- }
997
- if (review?.docsCheckHint && review.docsCheckHint.invalid > 0) {
998
- auditNotes.push(`📎 文档引用失效:${review.docsCheckHint.invalid}/${review.docsCheckHint.total} 处 file:line 失效(sillyspec docs check 可复现)`)
999
- }
1000
- // 归属切分注(2026-08-18 误归属修复):窗口内未声明脏文件不进「文件:」行,但必须落盘可追溯
1001
- // (多 agent 并发仓他者窗口改动 / 本会话漏声明均可能),防真实改动被静默挤走。
1002
- if (Array.isArray(review?.undeclaredFiles) && review.undeclaredFiles.length > 0) {
1003
- const undeclared = review.undeclaredFiles.filter(f => !isQuickMetadata(f, linkedChanges))
1004
- if (undeclared.length > 0) {
1005
- auditNotes.push(`⚖️ 归属切分:${undeclared.length} 个窗口内未声明脏文件未计入文件行(并行会话改动或本会话漏声明):${undeclared.join(', ')}`)
1006
- }
1007
- }
1008
- await completeQuicklogEntry(specBase, gitUser, qlId, {
1009
- resultText: outputText || '',
1010
- linkedChanges,
1011
- changedFiles: realFiles,
1012
- auditNotes,
1013
- })
1014
- console.log(`📝 QUICKLOG 条目 ${qlId} 已标记完成`)
1015
- // 刷新 DB title:从 step3「需求:」提取(agent 可改 title 的途径),覆盖启动时的兜底快照。
1016
- // 与 QUICKLOG 标题刷新(flipEntryInContent 内 extractTitleFromResult)同源,保持 DB↔QUICKLOG 一致。
1017
- try {
1018
- const refinedTitle = extractTitleFromResult(outputText || '');
1019
- if (refinedTitle) pm.updateChangeMeta(cwd, changeName, { title: refinedTitle });
1020
- } catch { /* title 刷新失败不阻断完成 */ }
1021
- } catch (e) {
1022
- console.warn(`⚠️ QUICKLOG 完成态写入失败: ${e.message}`)
1023
- }
1024
-
1025
- // 轻量归档任务已全勾选的关联真实变更
1026
- try {
1027
- const closeResult = await closeQuickLinkedChanges({ pm, cwd, specBase, linkedChanges, platformOpts })
1028
- if (closeResult.closed.length > 0) {
1029
- console.log(`📦 已自动归档 ${closeResult.closed.length} 个关联变更:${closeResult.closed.join(', ')}`)
1030
- }
1031
- if (closeResult.skipped.length > 0) {
1032
- for (const s of closeResult.skipped) {
1033
- console.log(`⏭️ 关联变更 ${s.name} 未归档:${s.reason}`)
1034
- }
1035
- }
1036
- } catch (e) {
1037
- console.warn(`⚠️ 关联变更轻量归档失败(不阻断 quick 完成): ${e.message}`)
1038
- }
1039
-
1040
- // 清理 session 目录(rmSync/unlinkSync 容忍不存在)。路径与写入对齐(Q4 resolveQuickSessionsDir)。
1041
- try {
1042
- if (changeName) {
1043
- const sessionDir = join(resolveQuickSessionsDir(platformOpts, specBase), changeName)
1044
- rmSync(sessionDir, { recursive: true, force: true })
1045
- }
1046
- if (existsSync(legacyGuardFile)) unlinkSync(legacyGuardFile)
1047
- } catch {}
1048
-
1049
- // 注销 quick 会话注册的 changes 行(quick-<uuid8>),避免 active 行随每次 quick 单调累积污染
1050
- // listChanges / doctor / resolveQuickLinkedChanges(multi-agent-review Q1)。quick 是收尾型会话,
1051
- // 不走 archive,旧代码从不调 unregisterChange → DB 里 active 的 quick-<hex> 行只增不减。
1052
- // 仅对 quick-<8hex> sessionId 注销——非 sessionId 形态的变更名是旧兼容路径/真实关联变更,
1053
- // 误注销会把用户真实变更标 archived(与 command.js:569 sessionId 守卫同形正则)。
1054
- if (changeName && /^quick-[0-9a-f]{8}$/.test(changeName)) {
1055
- try {
1056
- pm.unregisterChange(cwd, changeName)
1057
- } catch (e) {
1058
- console.warn(`⚠️ 注销 quick 会话 changes 行失败(不阻断完成): ${e.message}`)
1059
- }
1060
- }
1061
- }
1062
-
1063
- return null
1064
- }
1065
-
1066
- /**
1067
- * 判定变更 tasks.md 是否全部勾选完成。
1068
- * 无 tasks.md 或有未勾选项均返回 false(保守策略)。
1069
- *
1070
- * @param {string} specBase - .sillyspec 根目录
1071
- * @param {string} changeName - 变更名
1072
- * @returns {boolean}
1073
- */
1074
- function isChangeTasksComplete(specBase, changeName) {
1075
- const tasksPath = join(specBase, 'changes', changeName, 'tasks.md')
1076
- if (!existsSync(tasksPath)) return false
1077
- try {
1078
- const content = readFileSync(tasksPath, 'utf8').replace(/\r\n/g, '\n')
1079
- return !/^-\s*\[\s*\]\s+/m.test(content)
1080
- } catch {
1081
- return false
1082
- }
1083
- }
1084
-
1085
- /**
1086
- * 对单个已完成的关联真实变更执行轻量归档(不校验 plan.md/module-impact.md)。
1087
- *
1088
- * @param {Object} opts
1089
- * @param {ProgressManager} opts.pm
1090
- * @param {string} opts.cwd
1091
- * @param {string} opts.specBase
1092
- * @param {string} opts.changeName
1093
- * @param {Object} [opts.platformOpts]
1094
- * @returns {Promise<{closed:boolean, destDir?:string, reason?:string}>}
1095
- */
1096
- async function closeSingleQuickLinkedChange({ pm, cwd, specBase, changeName, platformOpts = {} }) {
1097
- const srcDir = join(specBase, 'changes', changeName)
1098
- if (!existsSync(srcDir)) {
1099
- return { closed: false, reason: '源目录不存在' }
1100
- }
1101
- const changesDir = join(specBase, 'changes')
1102
- const archiveDir = join(changesDir, 'archive')
1103
- const date = new Date().toISOString().slice(0, 10)
1104
- const destName = archiveDestDirName(date, changeName)
1105
- const destDir = join(archiveDir, destName)
1106
-
1107
- // 幂等:目标目录已存在或已在 archive/ 中
1108
- if (existsSync(destDir) || findAlreadyArchivedDir(archiveDir, changeName)) {
1109
- return { closed: false, reason: `目标目录已存在(${destName})` }
1110
- }
1111
-
1112
- mkdirSync(archiveDir, { recursive: true })
1113
- try {
1114
- renameSyncRetry(srcDir, destDir)
1115
- } catch (e) {
1116
- return { closed: false, reason: `移动目录失败:${e.message}` }
1117
- }
1118
-
1119
- // 终态一致化同标准归档(坑 manual-archive-desync-status-only):轻量归档路径不能只翻 status
1120
- pm.unregisterChange(cwd, changeName, { archiveStepNames: typeof pm.archiveStepNamesForArchive === 'function' ? pm.archiveStepNamesForArchive() : null })
1121
- await archiveWorktreeCleanup(cwd, changeName, specBase, platformOpts)
1122
- safeGit(cwd, ['add', '--', `.sillyspec/changes/archive/${destName}/`])
1123
-
1124
- console.log(`📦 关联变更已自动归档:${changeName} → archive/${destName}/`)
1125
- return { closed: true, destDir }
1126
- }
1127
-
1128
- /**
1129
- * quick 轻量归档的阶段闸允许集:仅「从未进入完整流程」的变更可被 quick --done 自动归档
1130
- * (d192f89 原始场景:评估 small 转 quick、停在 brainstorm 的僵尸变更)。execute 完成后
1131
- * tasks.md 必然全勾选而流程未收尾——不看 current_stage 会把 verify/中途的完整流程变更
1132
- * 绕过 verify/archive 校验直接归档注销(quick-close-midflight 缺陷)。
1133
- *
1134
- * 阶段名允许集之外还有「阶段完成态」闸(ql-20260819-010,quick-done-autoarchive-misfire
1135
- * 缺陷①):current_stage=brainstorm 但该阶段 status=completed(brainstorm 收尾到 plan
1136
- * 开始之间的空窗)≠ 僵尸变更——此时关联 quick --done 会把即将进 plan 的进行中变更误
1137
- * 轻量归档。stage_status=completed 一律走原流程收尾。
1138
- */
1139
- const QUICK_CLOSE_ALLOWED_STAGES = new Set(['', 'scan', 'brainstorm'])
1140
-
1141
- /**
1142
- * quick --done 完成后,自动关闭任务已全部完成的关联真实变更。
1143
- * quick-<hex> sessionId 自身不在此处理(由调用方单独注销)。
1144
- * 单个归档失败 catch warn,不阻断 quick 完成。
1145
- *
1146
- * 阶段闸(fail-closed):先查 changes.current_stage——无 DB 记录(未注册目录桩)或停在
1147
- * scan/brainstorm 才继续 tasks 判定;plan/execute/verify/archive 一律 skip 走原流程收尾。
1148
- * pm 缺 getChangeStage 接口或查询抛错同样 skip,不静默放行。
1149
- *
1150
- * @param {Object} opts
1151
- * @param {ProgressManager} opts.pm
1152
- * @param {string} opts.cwd
1153
- * @param {string} opts.specBase
1154
- * @param {string[]} [opts.linkedChanges]
1155
- * @param {Object} [opts.platformOpts]
1156
- * @returns {Promise<{closed:string[], skipped:{name:string,reason:string}[]}>}
1157
- */
1158
- export async function closeQuickLinkedChanges({ pm, cwd, specBase, linkedChanges = [], platformOpts = {} }) {
1159
- const closed = []
1160
- const skipped = []
1161
- // 只处理真实变更,跳过 quick 会话 sessionId
1162
- const realChanges = linkedChanges.filter((name) => !/^quick-[0-9a-f]{8}$/.test(name))
1163
- for (const changeName of realChanges) {
1164
- try {
1165
- if (typeof pm.getChangeStage !== 'function') {
1166
- skipped.push({ name: changeName, reason: '进度库接口缺失(getChangeStage),无法判定流程阶段,不自动归档' })
1167
- continue
1168
- }
1169
- const stageInfo = pm.getChangeStage(cwd, changeName)
1170
- if (stageInfo !== null && !QUICK_CLOSE_ALLOWED_STAGES.has(stageInfo.current_stage || '')) {
1171
- skipped.push({
1172
- name: changeName,
1173
- reason: `变更处于完整流程「${stageInfo.current_stage}」阶段(tasks.md 全勾不等于流程收尾),不自动归档——请走原流程收尾(sillyspec progress show 查看进度)`,
1174
- })
1175
- continue
1176
- }
1177
- // ql-20260819-010(quick-done-autoarchive-misfire 缺陷①):当前阶段已完成 ≠
1178
- // 从未进入完整流程的僵尸。brainstorm 收尾到 plan 开始之间的空窗里 current_stage
1179
- // 仍读 brainstorm,只看阶段名会把即将进 plan 的变更误轻量归档(propose 骨架
1180
- // tasks.md 除 quick 追加的 ql 行外没有任务行,「无未勾选框=全勾」恒真)。
1181
- // stage_status=completed 一律原流程收尾;null(无阶段行/brownfield)与旧调用方
1182
- // mock 缺字段(undefined)均按未完成放行,僵尸逃生通道行为不变。
1183
- if (stageInfo !== null && stageInfo.stage_status === 'completed') {
1184
- skipped.push({
1185
- name: changeName,
1186
- reason: `变更当前阶段「${stageInfo.current_stage || '(空)'}」已完成(推进/收尾中,非僵尸变更),不自动归档——请走原流程收尾(sillyspec progress show 查看进度)`,
1187
- })
1188
- continue
1189
- }
1190
- if (!isChangeTasksComplete(specBase, changeName)) {
1191
- skipped.push({ name: changeName, reason: 'tasks.md 未全勾选或不存在' })
1192
- continue
1193
- }
1194
- const result = await closeSingleQuickLinkedChange({ pm, cwd, specBase, changeName, platformOpts })
1195
- if (result.closed) {
1196
- closed.push(changeName)
1197
- } else {
1198
- skipped.push({ name: changeName, reason: result.reason || '未知原因' })
1199
- }
1200
- } catch (e) {
1201
- console.warn(`⚠️ 关联变更 ${changeName} 轻量归档失败(不阻断 quick 完成): ${e.message}`)
1202
- skipped.push({ name: changeName, reason: e.message })
1203
- }
1204
- }
1205
- return { closed, skipped }
1206
- }
1207
-
1208
- /**
1209
- * execute「Wave N 执行」步骤完成后扫 worktree 提取 provider endpoint artifact(W6 Step6c 从
1210
- * completeStep 内联块抽出)。供 verify 阶段 parity 对账 + consumer task 上游契约注入。
1211
- * 接线自 contract-matrix pipeline。step 级(每个 Wave 执行步骤后跑),无 early-return(try/catch warn)。
1212
- *
1213
- * ctx:stageName/steps/currentIdx/changeName/specBase/cwd。extractArtifactsForChange ← 动态 ../contract-matrix.js,
1214
- * WorktreeManager ← 动态 ../worktree.js(真环依赖保留动态)。
1215
- */
1216
- export async function handleExecuteWaveArtifact({ stageName, steps, currentIdx, changeName, specBase, cwd }) {
1217
- if (stageName === 'execute' && /^Wave \d+ 执行$/.test(steps[currentIdx]?.name || '')) {
1218
- try {
1219
- const { extractArtifactsForChange } = await import('../contract-matrix.js')
1220
- let worktreePath = null
1221
- try {
1222
- const { WorktreeManager } = await import('../worktree.js')
1223
- const meta = new WorktreeManager({ cwd }).getMeta(changeName)
1224
- if (meta?.worktreePath && existsSync(meta.worktreePath)) worktreePath = meta.worktreePath
1225
- } catch {}
1226
- const msg = extractArtifactsForChange({ changeDir: join(specBase, 'changes', changeName), specBase, changeName, worktreePath })
1227
- if (msg) console.log(msg)
1228
- } catch (e) { console.warn(`⚠️ 契约 artifact 提取跳过: ${e?.message || e}`) }
1229
- }
1230
- return null
1231
- }
1232
-
1233
- /**
1234
- * 聚合最新 execute run 各 task review.json 的 changedFiles(主仓 repo 过滤)。
1235
- *
1236
- * 复用 resolveLatestExecuteRunIdWithTasks(task-review.js:684,规避 marker 漂移)+ readReview。
1237
- * 仅主仓 repo(review.repo 缺省或 'main')的 changedFiles 参与主仓核验;跨仓 repo 的 task 文件
1238
- * 由跨仓仓独立落地,不在主仓 worktree/分支,混入会误报 missing(Grill M11)。
1239
- *
1240
- * @param {{ runtimeRoot: string, changeName: string }} opts
1241
- * @returns {Promise<string[]>} 主仓 changedFiles 聚合(去重保序);无 run / 无 tasks / 读取失败 → []
1242
- */
1243
- export async function collectExecuteChangedFiles({ runtimeRoot, changeName }) {
1244
- if (!runtimeRoot || !changeName) return []
1245
- const { resolveLatestExecuteRunIdWithTasks, readReview, normalizeRepoKey } = await import('../task-review.js')
1246
- // changeName 透传:run 解析按 change 戳优先归属(坑 worktree-cleanup-marker-chain),
1247
- // 避免 marker 断裂后聚合到其他变更 run 的 changedFiles 误报 missing
1248
- const runId = resolveLatestExecuteRunIdWithTasks({ runtimeRoot, changeName })
1249
- if (!runId) return []
1250
- const tasksDir = join(runtimeRoot, 'execute-runs', runId, 'tasks')
1251
- if (!existsSync(tasksDir)) return []
1252
- let taskIds
1253
- try {
1254
- taskIds = readdirSync(tasksDir)
1255
- } catch {
1256
- return []
1257
- }
1258
- const files = []
1259
- for (const taskId of taskIds) {
1260
- const r = readReview(join(tasksDir, taskId, 'review.json'))
1261
- if (!r.ok || !r.review) continue
1262
- // 跨仓 repo 过滤:仅主仓(repo 缺省视 'main')参与主仓核验,避免误报
1263
- if (normalizeRepoKey(r.review.repo) !== 'main') continue
1264
- if (Array.isArray(r.review.changedFiles)) {
1265
- for (const f of r.review.changedFiles) {
1266
- // 交付物过滤(与 worktree.js hasUnappliedChanges isDeliverable 同口径):.sillyspec/ 蓝图/
1267
- // runtime 产物与 meta.json 不参与落盘核验——它们随主仓/并行 session 维护,不在 worktree 分支,
1268
- // 混入会误报 missing
1269
- if (typeof f !== 'string' || f.trim() === '') continue
1270
- if (f.startsWith('.sillyspec/') || f === 'meta.json') continue
1271
- files.push(f)
1272
- }
1273
- }
1274
- }
1275
- return [...new Set(files)]
1276
- }
1277
-
1278
- /**
1279
- * execute 阶段级核验(防空跑谎报,D-002@v1 / FR-04/05/06):聚合最新 execute run 各 task review 声称的
1280
- * 交付文件,用 findMissingDeliverables 核验其存在于 worktree 分支 tree 或 worktree 工作区。
1281
- *
1282
- * - missing 文件 → console.warn 列清单,提示"apply 将无源可复制"(宽松非阻断,不 exit 不 throw)。
1283
- * - checked:false(worktree 目录 / 分支不存在)→ 保守提示"无法核验,请人工确认"。
1284
- * - 与 Task Review Gate 既有校验(零改动伪造 / 不相交伪造,task-review.js:590-623)互补不重复拦截:
1285
- * 本核验的真实增量窗口是「review 通过后文件被删且未 commit」+「无法核验时给人工确认提示」。
1286
- *
1287
- * 由 handleExecuteWorktreeCleanup 开头调用:核验发生在 worktree cleanup 之前,目录被清前先判定
1288
- * 交付文件是否落盘。整个钩子 try/catch 兜底——任何异常只 warn,绝不影响 execute 完成(FR-07)。
1289
- *
1290
- * ctx:stageName/changeName/cwd。WorktreeManager + findMissingDeliverables ← 动态 ../worktree.js;
1291
- * task-review 读取 ← 动态 ../task-review.js。runtimeRoot 用本地 specBase 解析(无 platformOpts 传入
1292
- * 时平台 runtimeRoot 不在本函数作用域,降级为本仓 .runtime,读不到 review 则跳过,零误报)。
1293
- */
1294
- export async function handleExecuteDeliverableCheck({ stageName, changeName, cwd }) {
1295
- if (stageName !== 'execute' || !changeName) return null
1296
- try {
1297
- const { WorktreeManager, findMissingDeliverables } = await import('../worktree.js')
1298
- const wm = new WorktreeManager({ cwd })
1299
- const meta = wm.getMeta(changeName)
1300
- if (!meta) return null // 无 worktree meta(非 worktree execute / 已清),无需核验
1301
- const specBase = join(cwd, '.sillyspec')
1302
- const runtimeRoot = resolveRuntimeRoot({}, specBase)
1303
- const changedFiles = await collectExecuteChangedFiles({ runtimeRoot, changeName })
1304
- if (changedFiles.length === 0) return null
1305
- const { missing, checked } = findMissingDeliverables({
1306
- worktreePath: meta.worktreePath,
1307
- branch: meta.branch,
1308
- changedFiles,
1309
- })
1310
- if (!checked) {
1311
- console.warn('⚠️ execute 阶段级核验:无法核验(worktree 目录或分支不存在),请人工确认交付文件已落盘。')
1312
- return null
1313
- }
1314
- if (missing.length > 0) {
1315
- console.warn(`⚠️ execute 阶段级核验:以下 ${missing.length} 个声称实现的交付文件既不在分支也不在工作区,疑似空跑/从未落盘:`)
1316
- for (const f of missing) console.warn(` ${f}`)
1317
- console.warn(' 请检查子代理是否真实实现,或先 commit 到分支;apply 将无源可复制。')
1318
- }
1319
- } catch (e) {
1320
- console.warn(`⚠️ execute 阶段级核验跳过: ${e?.message || e}`)
1321
- }
1322
- return null
1323
- }
1324
-
1325
- /**
1326
- * execute 阶段完成时条件性清理 worktree(W6 Step6c 从 completeStep 完成路径内联块抽出)。
1327
- * 不依赖 AI agent 的完成确认步骤:有未 apply 变更 → 保留 worktree;否则 cleanup(含 in-place 安全清理)。
1328
- * stage 级(execute 阶段全部完成时跑),无 early-return(try/catch warn)。
1329
- *
1330
- * ctx:stageName/changeName/cwd。WorktreeManager ← 动态 ../worktree.js。
1331
- */
1332
- export async function handleExecuteWorktreeCleanup({ stageName, changeName, cwd }) {
1333
- // 阶段级核验(D-002@v1,防空跑谎报):cleanup 之前判定 review 声称实现的交付文件是否落盘。
1334
- // 宽松非阻断:缺失 warn / 无法核验保守提示 / 异常只 warn,均不影响下方 cleanup 与 execute 完成。
1335
- await handleExecuteDeliverableCheck({ stageName, changeName, cwd })
1336
- if (stageName === 'execute' && changeName) {
1337
- try {
1338
- const { WorktreeManager } = await import('../worktree.js');
1339
- const wm = new WorktreeManager({ cwd });
1340
- const meta = wm.getMeta(changeName);
1341
- if (!meta) {
1342
- console.log('🔗 Worktree: n/a (no meta)');
1343
- } else if (meta.mode === 'native-worktree') {
1344
- console.log('🔗 Worktree: kept (外部隔离环境)');
1345
- } else {
1346
- // in-place 模式不再短路:cleanup 现在能安全处理 in-place(只清 meta,不碰主工作区)。
1347
- // 主仓互斥锁(坑 main-repo-no-mutex 二批):检查+清理与并行会话的 apply/cleanup 互斥
1348
- // (防 TOCTOU:检查时他者正在 apply → 判定漂移)。best-effort:锁超时不阻断 execute
1349
- // 完成,降级为保留 worktree + 手动清理指引。
1350
- try {
1351
- const { withMainRepoLock } = await import('../worktree-apply.js')
1352
- const cleanResult = await withMainRepoLock(cwd, changeName, 'execute-cleanup', () => {
1353
- const check = wm.hasUnappliedChanges(changeName);
1354
- if (check.hasChanges) {
1355
- return { kept: true, check }
1356
- }
1357
- return { kept: false, result: wm.cleanup(changeName) }
1358
- })
1359
- if (cleanResult.kept) {
1360
- console.log(`🔗 Worktree: pending apply (${cleanResult.check.changedFiles.length} 个未应用变更)`);
1361
- console.log(` 下一步: sillyspec worktree apply ${changeName}`);
1362
- } else {
1363
- console.log(`🔗 Worktree: ${cleanResult.result.result}`);
1364
- if (cleanResult.result.residual?.length > 0) {
1365
- console.warn(` ⚠️ 清理残留: ${cleanResult.result.residual.join('; ')}`);
1366
- console.warn(` 手动处理: sillyspec worktree cleanup ${changeName} --force`);
1367
- } else if (cleanResult.result.details?.length > 0) {
1368
- for (const d of cleanResult.result.details) {
1369
- if (d.startsWith('⚠️')) console.log(` ${d}`);
1370
- }
1371
- }
1372
- }
1373
- } catch (lockErr) {
1374
- if (/互斥锁被占用/.test(String(lockErr.message))) {
1375
- console.log(`🔗 Worktree 自动清理跳过(主仓互斥锁被他者会话持有)——稍后手动: sillyspec worktree cleanup ${changeName}`);
1376
- } else {
1377
- console.warn(`⚠️ worktree 清理异常(不阻断): ${lockErr.message}`);
1378
- }
1379
- }
1380
- }
1381
- } catch (e) {
1382
- console.warn(`🔗 Worktree: check failed — ${e.message}`);
1383
- }
1384
- }
1385
- return null
1386
- }
1387
- /**
1388
- * scan 阶段完成后处理(W6 Step6d 从 completeStep 完成路径内联块抽出):
1389
- * - 平台模式(specRoot/runtimeRoot):写 manifest.json + 跑 scan-postcheck + 结构化结果 +
1390
- * 更新平台指针(SCAN_COMPLETED)+ failed_post_check 阻断(exit 1 / early-return)
1391
- * - 非平台模式:轻量 postcheck + 结构化结果写 .runtime/
1392
- * 返回 early-return 对象(platform failed_post_check 非 exit 路径)由 completeStep 透传;null = 放行。
1393
- *
1394
- * ctx:stageName/currentIdx/cwd/progress/pm/stageData/changeName/outputText/platformOpts。
1395
- * safeGit/triggerSync ← shared;writeAtomicSync ← fs-atomic;SCAN_STATUS/POINTER_STATUS ← constants;
1396
- * mkdirSync/writeFileSync/readFileSync/unlinkSync/join ← 顶部静态;runScanPostCheck 等 ← 动态 ../scan-postcheck.js。
1397
- *
1398
- * 搬迁清理:删 4 个冗余动态 builtin import(fs/path/child_process,execSync 死代码)+ _readFileSync 别名改回 readFileSync。
1399
- */
1400
- export async function handleScanStageCompleted({ stageName, currentIdx, cwd, progress, pm, stageData, changeName, outputText, platformOpts }) {
1401
- // 平台模式:scan 完成后生成 manifest.json + post-check
1402
- if (stageName === 'scan' && (platformOpts.specRoot || platformOpts.runtimeRoot)) {
1403
- if (!platformOpts.specRoot) {
1404
- // 只传 runtimeRoot 无 specRoot(command.js 允许的组合):manifest 无处落盘。
1405
- // 显式 fail-closed 报错——此前 mkdirSync(null) 抛 TypeError 被外层 catch 吞掉,
1406
- // postcheck/指针升级/阻断全部静默跳过,scan 失败也"干净成功"(体检 BUG-12)
1407
- console.error(`❌ 平台模式缺少 --spec-root,无法写 manifest.json(scan postcheck 中止)`)
1408
- stageData.scanMeta = stageData.scanMeta || {}; stageData.scanMeta.manifestWritten = false
1409
- stageData.scanMeta.manifestError = 'missing specRoot'
1410
- return
1411
- }
1412
- try {
1413
- stageData.scanMeta = stageData.scanMeta || {}; stageData.scanMeta.manifestWritten = false; // 默认失败
1414
- const manifestDir = platformOpts.specRoot
1415
- mkdirSync(manifestDir, { recursive: true })
1416
- let sourceCommit = null
1417
- let sourceCommitError = null
1418
- try {
1419
- const gitResult = safeGit(cwd, ['rev-parse', 'HEAD'])
1420
- sourceCommit = gitResult.value
1421
- sourceCommitError = gitResult.error
1422
- } catch (e) {
1423
- sourceCommitError = e.message
1424
- }
1425
- const manifest = {
1426
- workspace_id: platformOpts.workspaceId || null,
1427
- scan_run_id: platformOpts.scanRunId || null,
1428
- source_root: cwd,
1429
- spec_root: platformOpts.specRoot || null,
1430
- runtime_root: platformOpts.runtimeRoot || null,
1431
- source_commit: sourceCommit,
1432
- source_commit_error: sourceCommit === null ? (sourceCommitError || 'unknown') : undefined,
1433
- generated_at: new Date().toISOString(),
1434
- schema_version: 1,
1435
- scan_profile: stageData.scanProfile
1436
- ? { mode: stageData.scanProfile.mode, reason: stageData.scanProfile.reason }
1437
- : null,
1438
- postcheck_result_path: null,
1439
- workflow_runs_dir: platformOpts.runtimeRoot
1440
- ? join(platformOpts.runtimeRoot, 'scan-runs', platformOpts.scanRunId || 'unknown', 'workflow-runs')
1441
- : null,
1442
- platform_pointer_path: join(cwd, '.sillyspec-platform.json'),
1443
- platform_pointer_status: POINTER_STATUS.ACTIVE,
1444
- }
1445
- const manifestPath = join(manifestDir, 'manifest.json')
1446
- writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n')
1447
- console.log(`📄 manifest.json 已写入: ${manifestPath}`)
1448
- stageData.scanMeta = stageData.scanMeta || {}; stageData.scanMeta.manifestWritten = true;
1449
- if (!sourceCommit) {
1450
- console.log(`⚠️ source_commit 无法获取(可能非 git 目录),已设为 null`)
1451
- }
1452
- // 清理平台参数临时文件
1453
- const platformOptsFile = join(manifestDir, '.runtime', 'platform-scan.json')
1454
- try { unlinkSync(platformOptsFile) } catch {}
1455
-
1456
- // CLI 层 post-check(替代旧的简单检查)
1457
- const { runScanPostCheck, printScanPostCheckResult, formatStructuredResult, writeStructuredResult } = await import('../scan-postcheck.js')
1458
- const postResult = runScanPostCheck({
1459
- cwd,
1460
- specDir: platformOpts.specRoot,
1461
- outputText,
1462
- scanMeta: {
1463
- projectListParsed: stageData.scanMeta?.projectListParsed ?? null,
1464
- manifestWritten: stageData.scanMeta?.manifestWritten ?? null,
1465
- },
1466
- scanProfile: stageData.scanProfile || null,
1467
- })
1468
- printScanPostCheckResult(postResult)
1469
-
1470
- // 生成结构化 JSON 并写入 runtime(供 SillyHub 消费)
1471
- const structured = formatStructuredResult(postResult, {
1472
- workspace_id: platformOpts.workspaceId,
1473
- scan_run_id: platformOpts.scanRunId,
1474
- source_root: cwd,
1475
- spec_root: platformOpts.specRoot,
1476
- runtime_root: platformOpts.runtimeRoot,
1477
- })
1478
- const postcheckJsonPath = writeStructuredResult(structured, platformOpts.specRoot, {
1479
- runtimeRoot: platformOpts.runtimeRoot,
1480
- scanRunId: platformOpts.scanRunId,
1481
- })
1482
- if (postcheckJsonPath) {
1483
- console.log(`📄 postcheck-result.json 已写入: ${postcheckJsonPath}`)
1484
- manifest.postcheck_result_path = postcheckJsonPath
1485
- }
1486
-
1487
- // 将 post-check 结果写入 manifest
1488
- manifest.scan_post_check = {
1489
- status: postResult.status,
1490
- checks: postResult.checks,
1491
- }
1492
- // 更新 manifest
1493
- writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n')
1494
- console.log(`📄 manifest.json 已更新(含 post-check 结果)`)
1495
-
1496
- // 更新平台指针状态为 scan_completed
1497
- const pointerPath = join(cwd, '.sillyspec-platform.json')
1498
- try {
1499
- const pointer = JSON.parse(readFileSync(pointerPath, 'utf8'))
1500
- pointer.status = POINTER_STATUS.SCAN_COMPLETED
1501
- pointer.completedAt = new Date().toISOString()
1502
- pointer.scanStatus = postResult.status
1503
- writeAtomicSync(pointerPath, JSON.stringify(pointer, null, 2) + '\n')
1504
- } catch (e) {
1505
- // 不阻断 scan 主流程,但暴露失败——pointer 写失败会让平台看不到 scan_completed,
1506
- // 与项目 fail-loud 原则一致:宁可可见地 warn,也不静默吞错。
1507
- console.warn(`⚠️ 更新平台指针状态失败(scan_completed 可能未落盘): ${e.message}`)
1508
- }
1509
-
1510
- // failed_post_check 时强制阻止 clean success
1511
- if (postResult.status === 'failed_post_check') {
1512
- stageData.status = SCAN_STATUS.FAILED_POST_CHECK
1513
- stageData.completedAt = new Date().toLocaleString('zh-CN',{hour12:false})
1514
- pm._write(cwd, progress, changeName)
1515
- triggerSync(cwd, changeName, platformOpts)
1516
- console.error(`\n❌ scan post-check 失败,状态设为 failed_post_check。不允许 clean success。`)
1517
- console.error(` 请检查上方错误信息并修复后重新 scan。`)
1518
- // 平台模式:exit(1) 让 daemon/SillyHub 感知非 0 退出码(manifest.json 已落盘,不会被撤销)
1519
- if (platformOpts.specRoot || platformOpts.runtimeRoot) {
1520
- console.error(' 平台模式:CLI 将以 exit code 1 退出,通知 SillyHub scan 失败。')
1521
- process.exit(1)
1522
- }
1523
- // 接口与 plan contract (run.js:2551 附近 plan 失败分支) 对齐:
1524
- // 返回 { stageCompleted:false, currentIdx, nextPendingIdx: currentIdx }
1525
- // 让上层 runStage 走"完成但不推进"分支,--done 被拒
1526
- return { stageCompleted: false, currentIdx, nextPendingIdx: currentIdx }
1527
- } else if (postResult.status === 'completed_with_warnings') {
1528
- // 警告不阻止完成,但记录
1529
- stageData.status = 'completed'
1530
- stageData.completedAt = new Date().toLocaleString('zh-CN',{hour12:false})
1531
- pm._write(cwd, progress, changeName)
1532
- }
1533
- } catch (e) {
1534
- console.warn(`⚠️ manifest.json 写入失败: ${e.message}`)
1535
- }
1536
- }
1537
-
1538
- // 非 platform 模式 scan 也做轻量 post-check + 结构化输出
1539
- if (stageName === 'scan' && !platformOpts.specRoot && !platformOpts.runtimeRoot) {
1540
- const { runScanPostCheck, printScanPostCheckResult, formatStructuredResult, writeStructuredResult } = await import('../scan-postcheck.js')
1541
- const postResult = runScanPostCheck({ cwd, specDir: null, outputText, scanProfile: stageData.scanProfile || null })
1542
- printScanPostCheckResult(postResult)
1543
- // 结构化结果写入 .sillyspec/.runtime/
1544
- const structured = formatStructuredResult(postResult, { source_root: cwd })
1545
- const postcheckJsonPath = writeStructuredResult(structured, join(cwd, '.sillyspec'))
1546
- if (postcheckJsonPath) {
1547
- console.log(`📄 postcheck-result.json 已写入: ${postcheckJsonPath}`)
1548
- }
1549
- }
1550
- return null
1551
- }
1552
-