sillyspec 3.27.12 → 3.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1234) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +214 -214
  2. package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
  3. package/.claude/skills/sillyspec-quick/SKILL.md +116 -116
  4. package/package.json +1 -1
  5. package/src/agent-session-log.js +77 -10
  6. package/src/archive-delta.js +419 -0
  7. package/src/config-schema.js +2 -2
  8. package/src/contract-matrix.js +15 -2
  9. package/src/design-facts.js +354 -0
  10. package/src/docs-check.js +79 -8
  11. package/src/doctor-diagnostics.js +75 -3
  12. package/src/endpoint-baseline.js +109 -0
  13. package/src/endpoint-extractor.js +100 -24
  14. package/src/git-helper.js +31 -0
  15. package/src/index.js +248 -8
  16. package/src/machine-interface.js +63 -0
  17. package/src/modules.js +41 -12
  18. package/src/progress/change-registry.js +20 -0
  19. package/src/progress/consistency-doctor.js +124 -5
  20. package/src/progress/stage-machine.js +118 -2
  21. package/src/progress.js +6 -0
  22. package/src/quicklog.js +51 -0
  23. package/src/run/command.js +71 -2
  24. package/src/run/complete-handlers.js +84 -7
  25. package/src/run/complete.js +58 -5
  26. package/src/run/gates.js +333 -2
  27. package/src/run/prompt.js +70 -0
  28. package/src/run/quick-audit.js +98 -0
  29. package/src/run/scan-profile.js +98 -6
  30. package/src/run/shared.js +66 -1
  31. package/src/run/stage.js +25 -12
  32. package/src/scan-diff.js +54 -1
  33. package/src/scan-facts.js +173 -0
  34. package/src/scan-postcheck.js +110 -3
  35. package/src/spec-sync.js +210 -16
  36. package/src/stage-review.js +62 -3
  37. package/src/stages/archive.js +5 -5
  38. package/src/stages/brainstorm.js +10 -10
  39. package/src/stages/execute.js +21 -15
  40. package/src/stages/plan-postcheck.js +194 -1
  41. package/src/stages/plan.js +6 -2
  42. package/src/stages/scan.js +44 -102
  43. package/src/stages/verify.js +9 -7
  44. package/src/sync.js +122 -4
  45. package/src/task-review.js +51 -4
  46. package/src/taskcard.js +8 -1
  47. package/src/verify-postcheck.js +670 -10
  48. package/src/verify-probes.js +92 -10
  49. package/src/workflow.js +30 -0
  50. package/templates/agents-instruction.md +1 -1
  51. package/templates/prompts/taskcard-rules.md +5 -0
  52. package/templates/workflows/scan-docs.yaml +6 -0
  53. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  54. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  55. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  56. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  57. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  58. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  59. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  60. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  61. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +0 -57
  62. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +0 -177
  63. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  64. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  65. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  66. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  67. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  68. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +0 -64
  69. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +0 -54
  70. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  71. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  72. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +0 -2
  73. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +0 -20
  74. package/.claude/worktrees/sillyspec-data-model-research/README.md +0 -203
  75. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +0 -91
  76. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +0 -2
  77. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  78. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +0 -977
  79. package/.claude/worktrees/sillyspec-data-model-research/package.json +0 -39
  80. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  81. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  82. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  83. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +0 -16
  84. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  85. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +0 -836
  86. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +0 -256
  87. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +0 -25
  88. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +0 -95
  89. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +0 -679
  90. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +0 -526
  91. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +0 -357
  92. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +0 -803
  93. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +0 -290
  94. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +0 -270
  95. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +0 -65
  96. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +0 -109
  97. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +0 -202
  98. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +0 -88
  99. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +0 -328
  100. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +0 -97
  101. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +0 -480
  102. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +0 -20
  103. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +0 -55
  104. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +0 -381
  105. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +0 -517
  106. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +0 -155
  107. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +0 -245
  108. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +0 -246
  109. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +0 -121
  110. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +0 -825
  111. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +0 -393
  112. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +0 -107
  113. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +0 -1099
  114. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +0 -420
  115. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +0 -78
  116. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +0 -73
  117. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +0 -150
  118. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +0 -130
  119. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +0 -892
  120. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +0 -2798
  121. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +0 -626
  122. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +0 -231
  123. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +0 -128
  124. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +0 -104
  125. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +0 -543
  126. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +0 -127
  127. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +0 -166
  128. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +0 -222
  129. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +0 -580
  130. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +0 -336
  131. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +0 -355
  132. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +0 -36
  133. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +0 -594
  134. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +0 -265
  135. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +0 -1304
  136. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +0 -115
  137. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +0 -852
  138. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +0 -77
  139. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +0 -1595
  140. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +0 -1552
  141. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +0 -1259
  142. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +0 -156
  143. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +0 -1084
  144. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +0 -208
  145. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +0 -128
  146. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +0 -843
  147. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +0 -186
  148. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +0 -269
  149. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +0 -1562
  150. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +0 -584
  151. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +0 -23
  152. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +0 -388
  153. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +0 -512
  154. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +0 -95
  155. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +0 -414
  156. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +0 -597
  157. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +0 -62
  158. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +0 -50
  159. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +0 -358
  160. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +0 -171
  161. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +0 -550
  162. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +0 -889
  163. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +0 -597
  164. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +0 -199
  165. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +0 -236
  166. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +0 -617
  167. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +0 -145
  168. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +0 -540
  169. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +0 -1275
  170. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +0 -43
  171. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +0 -29
  172. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +0 -514
  173. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +0 -1344
  174. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +0 -650
  175. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +0 -167
  176. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +0 -608
  177. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +0 -64
  178. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +0 -246
  179. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +0 -1470
  180. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +0 -1498
  181. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +0 -210
  182. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +0 -1718
  183. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +0 -277
  184. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +0 -19
  185. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +0 -600
  186. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +0 -125
  187. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +0 -1446
  188. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +0 -576
  189. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +0 -1715
  190. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +0 -23
  191. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +0 -28
  192. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +0 -12
  193. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +0 -32
  194. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +0 -79
  195. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +0 -132
  196. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  197. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  198. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  199. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  200. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  201. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  202. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  203. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  204. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +0 -57
  205. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +0 -177
  206. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  207. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  208. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  209. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  210. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  211. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  212. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +0 -64
  213. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +0 -54
  214. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  215. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  216. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +0 -6
  217. package/.worktrees/2c37b1d7/.gitattributes +0 -2
  218. package/.worktrees/2c37b1d7/.husky/pre-push +0 -20
  219. package/.worktrees/2c37b1d7/README.md +0 -203
  220. package/.worktrees/2c37b1d7/SKILL.md +0 -91
  221. package/.worktrees/2c37b1d7/architecture-analysis.md +0 -448
  222. package/.worktrees/2c37b1d7/bin/sillyspec.js +0 -2
  223. package/.worktrees/2c37b1d7/eval/README.md +0 -86
  224. package/.worktrees/2c37b1d7/eval/eval.config.json +0 -28
  225. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +0 -63
  226. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +0 -27
  227. package/.worktrees/2c37b1d7/eval/lib/config.mjs +0 -82
  228. package/.worktrees/2c37b1d7/eval/lib/db.mjs +0 -76
  229. package/.worktrees/2c37b1d7/eval/lib/report.mjs +0 -120
  230. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +0 -157
  231. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +0 -73
  232. package/.worktrees/2c37b1d7/eval/lib/util.mjs +0 -107
  233. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +0 -30
  234. package/.worktrees/2c37b1d7/eval/run.mjs +0 -83
  235. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +0 -6
  236. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  237. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +0 -6
  238. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +0 -28
  239. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +0 -6
  240. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  241. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  242. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +0 -6
  243. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +0 -31
  244. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  245. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +0 -6
  246. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  247. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +0 -6
  248. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +0 -38
  249. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  250. package/.worktrees/2c37b1d7/package-lock.json +0 -977
  251. package/.worktrees/2c37b1d7/package.json +0 -41
  252. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  253. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  254. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  255. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +0 -16
  256. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  257. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +0 -836
  258. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +0 -256
  259. package/.worktrees/2c37b1d7/packages/dashboard/package.json +0 -25
  260. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +0 -95
  261. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +0 -679
  262. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +0 -526
  263. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +0 -357
  264. package/.worktrees/2c37b1d7/src/agent-session-log.js +0 -803
  265. package/.worktrees/2c37b1d7/src/change-list.js +0 -290
  266. package/.worktrees/2c37b1d7/src/change-risk-profile.js +0 -339
  267. package/.worktrees/2c37b1d7/src/check-primitives.js +0 -65
  268. package/.worktrees/2c37b1d7/src/classify-change.js +0 -109
  269. package/.worktrees/2c37b1d7/src/commit-suggest.js +0 -202
  270. package/.worktrees/2c37b1d7/src/config-cat.js +0 -88
  271. package/.worktrees/2c37b1d7/src/config-schema.js +0 -328
  272. package/.worktrees/2c37b1d7/src/constants.js +0 -97
  273. package/.worktrees/2c37b1d7/src/contract-matrix.js +0 -533
  274. package/.worktrees/2c37b1d7/src/datetime.js +0 -20
  275. package/.worktrees/2c37b1d7/src/db-engine.js +0 -55
  276. package/.worktrees/2c37b1d7/src/db.js +0 -381
  277. package/.worktrees/2c37b1d7/src/decision-distill.js +0 -517
  278. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +0 -155
  279. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +0 -245
  280. package/.worktrees/2c37b1d7/src/dispatch/probe.js +0 -246
  281. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +0 -121
  282. package/.worktrees/2c37b1d7/src/docs-check.js +0 -825
  283. package/.worktrees/2c37b1d7/src/docs-debt.js +0 -393
  284. package/.worktrees/2c37b1d7/src/docs-gate.js +0 -107
  285. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +0 -1099
  286. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +0 -409
  287. package/.worktrees/2c37b1d7/src/foreign-declared.js +0 -155
  288. package/.worktrees/2c37b1d7/src/fs-atomic.js +0 -73
  289. package/.worktrees/2c37b1d7/src/git-helper.js +0 -150
  290. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +0 -130
  291. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +0 -892
  292. package/.worktrees/2c37b1d7/src/index.js +0 -2854
  293. package/.worktrees/2c37b1d7/src/init.js +0 -626
  294. package/.worktrees/2c37b1d7/src/knowledge-match.js +0 -231
  295. package/.worktrees/2c37b1d7/src/local-detect.js +0 -128
  296. package/.worktrees/2c37b1d7/src/local-register.js +0 -104
  297. package/.worktrees/2c37b1d7/src/machine-interface.js +0 -543
  298. package/.worktrees/2c37b1d7/src/migrate.js +0 -127
  299. package/.worktrees/2c37b1d7/src/module-impact.js +0 -166
  300. package/.worktrees/2c37b1d7/src/module-resolve.js +0 -222
  301. package/.worktrees/2c37b1d7/src/modules.js +0 -580
  302. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +0 -126
  303. package/.worktrees/2c37b1d7/src/progress/change-registry.js +0 -336
  304. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +0 -355
  305. package/.worktrees/2c37b1d7/src/progress/shared.js +0 -36
  306. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +0 -594
  307. package/.worktrees/2c37b1d7/src/progress/step-store.js +0 -265
  308. package/.worktrees/2c37b1d7/src/progress.js +0 -1304
  309. package/.worktrees/2c37b1d7/src/quick-recommend.js +0 -115
  310. package/.worktrees/2c37b1d7/src/quicklog.js +0 -883
  311. package/.worktrees/2c37b1d7/src/review-tier.js +0 -77
  312. package/.worktrees/2c37b1d7/src/run/command.js +0 -1641
  313. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +0 -1552
  314. package/.worktrees/2c37b1d7/src/run/complete.js +0 -1259
  315. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +0 -156
  316. package/.worktrees/2c37b1d7/src/run/gates.js +0 -1111
  317. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +0 -208
  318. package/.worktrees/2c37b1d7/src/run/next.js +0 -128
  319. package/.worktrees/2c37b1d7/src/run/prompt.js +0 -843
  320. package/.worktrees/2c37b1d7/src/run/quick-audit.js +0 -186
  321. package/.worktrees/2c37b1d7/src/run/scan-profile.js +0 -269
  322. package/.worktrees/2c37b1d7/src/run/shared.js +0 -1562
  323. package/.worktrees/2c37b1d7/src/run/stage.js +0 -587
  324. package/.worktrees/2c37b1d7/src/run.js +0 -23
  325. package/.worktrees/2c37b1d7/src/scan-diff.js +0 -388
  326. package/.worktrees/2c37b1d7/src/scan-postcheck.js +0 -524
  327. package/.worktrees/2c37b1d7/src/scan-staleness.js +0 -95
  328. package/.worktrees/2c37b1d7/src/setup.js +0 -414
  329. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +0 -597
  330. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +0 -62
  331. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +0 -50
  332. package/.worktrees/2c37b1d7/src/spec-sync.js +0 -358
  333. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +0 -171
  334. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +0 -551
  335. package/.worktrees/2c37b1d7/src/stage-contract.js +0 -948
  336. package/.worktrees/2c37b1d7/src/stage-review.js +0 -597
  337. package/.worktrees/2c37b1d7/src/stages/archive.js +0 -199
  338. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +0 -285
  339. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +0 -624
  340. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +0 -145
  341. package/.worktrees/2c37b1d7/src/stages/doctor.js +0 -540
  342. package/.worktrees/2c37b1d7/src/stages/execute.js +0 -1277
  343. package/.worktrees/2c37b1d7/src/stages/explore.js +0 -43
  344. package/.worktrees/2c37b1d7/src/stages/index.js +0 -29
  345. package/.worktrees/2c37b1d7/src/stages/knowledge.js +0 -514
  346. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +0 -1398
  347. package/.worktrees/2c37b1d7/src/stages/plan.js +0 -655
  348. package/.worktrees/2c37b1d7/src/stages/quick.js +0 -167
  349. package/.worktrees/2c37b1d7/src/stages/scan.js +0 -608
  350. package/.worktrees/2c37b1d7/src/stages/status.js +0 -64
  351. package/.worktrees/2c37b1d7/src/stages/verify.js +0 -246
  352. package/.worktrees/2c37b1d7/src/sync.js +0 -1470
  353. package/.worktrees/2c37b1d7/src/task-review.js +0 -1498
  354. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +0 -21
  355. package/.worktrees/2c37b1d7/src/taskcard.js +0 -250
  356. package/.worktrees/2c37b1d7/src/verify-postcheck.js +0 -1718
  357. package/.worktrees/2c37b1d7/src/verify-probes.js +0 -327
  358. package/.worktrees/2c37b1d7/src/version.js +0 -19
  359. package/.worktrees/2c37b1d7/src/workflow.js +0 -600
  360. package/.worktrees/2c37b1d7/src/workspace.js +0 -125
  361. package/.worktrees/2c37b1d7/src/worktree-apply.js +0 -1611
  362. package/.worktrees/2c37b1d7/src/worktree-deps.js +0 -668
  363. package/.worktrees/2c37b1d7/src/worktree.js +0 -1849
  364. package/.worktrees/2c37b1d7/templates/claude-instruction.md +0 -23
  365. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +0 -29
  366. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +0 -12
  367. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +0 -32
  368. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +0 -79
  369. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +0 -132
  370. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  371. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  372. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  373. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  374. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  375. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  376. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  377. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  378. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +0 -57
  379. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +0 -177
  380. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  381. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  382. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  383. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  384. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  385. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +0 -64
  386. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +0 -54
  387. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  388. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  389. package/.worktrees/542c4415/.gitattributes +0 -2
  390. package/.worktrees/542c4415/.husky/pre-push +0 -20
  391. package/.worktrees/542c4415/README.md +0 -203
  392. package/.worktrees/542c4415/SKILL.md +0 -91
  393. package/.worktrees/542c4415/architecture-analysis.md +0 -448
  394. package/.worktrees/542c4415/bin/sillyspec.js +0 -2
  395. package/.worktrees/542c4415/eval/README.md +0 -86
  396. package/.worktrees/542c4415/eval/eval.config.json +0 -28
  397. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +0 -63
  398. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +0 -27
  399. package/.worktrees/542c4415/eval/lib/config.mjs +0 -82
  400. package/.worktrees/542c4415/eval/lib/db.mjs +0 -76
  401. package/.worktrees/542c4415/eval/lib/report.mjs +0 -120
  402. package/.worktrees/542c4415/eval/lib/runner.mjs +0 -157
  403. package/.worktrees/542c4415/eval/lib/tasks.mjs +0 -73
  404. package/.worktrees/542c4415/eval/lib/util.mjs +0 -107
  405. package/.worktrees/542c4415/eval/lib/workdir.mjs +0 -30
  406. package/.worktrees/542c4415/eval/run.mjs +0 -83
  407. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +0 -6
  408. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  409. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +0 -6
  410. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +0 -28
  411. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +0 -6
  412. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  413. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  414. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +0 -6
  415. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +0 -31
  416. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  417. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +0 -6
  418. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  419. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +0 -6
  420. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +0 -38
  421. package/.worktrees/542c4415/logo.jpg +0 -0
  422. package/.worktrees/542c4415/package-lock.json +0 -977
  423. package/.worktrees/542c4415/package.json +0 -41
  424. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  425. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  426. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  427. package/.worktrees/542c4415/packages/dashboard/dist/index.html +0 -16
  428. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  429. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +0 -836
  430. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +0 -256
  431. package/.worktrees/542c4415/packages/dashboard/package.json +0 -25
  432. package/.worktrees/542c4415/packages/dashboard/server/executor.js +0 -95
  433. package/.worktrees/542c4415/packages/dashboard/server/index.js +0 -679
  434. package/.worktrees/542c4415/packages/dashboard/server/parser.js +0 -526
  435. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +0 -357
  436. package/.worktrees/542c4415/src/agent-session-log.js +0 -803
  437. package/.worktrees/542c4415/src/change-list.js +0 -290
  438. package/.worktrees/542c4415/src/change-risk-profile.js +0 -339
  439. package/.worktrees/542c4415/src/check-primitives.js +0 -65
  440. package/.worktrees/542c4415/src/classify-change.js +0 -109
  441. package/.worktrees/542c4415/src/commit-suggest.js +0 -202
  442. package/.worktrees/542c4415/src/config-cat.js +0 -88
  443. package/.worktrees/542c4415/src/config-schema.js +0 -328
  444. package/.worktrees/542c4415/src/constants.js +0 -97
  445. package/.worktrees/542c4415/src/contract-matrix.js +0 -533
  446. package/.worktrees/542c4415/src/datetime.js +0 -20
  447. package/.worktrees/542c4415/src/db-engine.js +0 -55
  448. package/.worktrees/542c4415/src/db.js +0 -381
  449. package/.worktrees/542c4415/src/decision-distill.js +0 -517
  450. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +0 -155
  451. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +0 -245
  452. package/.worktrees/542c4415/src/dispatch/probe.js +0 -246
  453. package/.worktrees/542c4415/src/dispatch/strategy.js +0 -121
  454. package/.worktrees/542c4415/src/docs-check.js +0 -825
  455. package/.worktrees/542c4415/src/docs-debt.js +0 -393
  456. package/.worktrees/542c4415/src/docs-gate.js +0 -107
  457. package/.worktrees/542c4415/src/doctor-diagnostics.js +0 -1099
  458. package/.worktrees/542c4415/src/endpoint-extractor.js +0 -409
  459. package/.worktrees/542c4415/src/foreign-declared.js +0 -155
  460. package/.worktrees/542c4415/src/fs-atomic.js +0 -73
  461. package/.worktrees/542c4415/src/git-helper.js +0 -150
  462. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +0 -130
  463. package/.worktrees/542c4415/src/hooks/worktree-guard.js +0 -892
  464. package/.worktrees/542c4415/src/index.js +0 -2854
  465. package/.worktrees/542c4415/src/init.js +0 -626
  466. package/.worktrees/542c4415/src/knowledge-match.js +0 -231
  467. package/.worktrees/542c4415/src/local-detect.js +0 -128
  468. package/.worktrees/542c4415/src/local-register.js +0 -104
  469. package/.worktrees/542c4415/src/machine-interface.js +0 -543
  470. package/.worktrees/542c4415/src/migrate.js +0 -127
  471. package/.worktrees/542c4415/src/module-impact.js +0 -166
  472. package/.worktrees/542c4415/src/module-resolve.js +0 -222
  473. package/.worktrees/542c4415/src/modules.js +0 -580
  474. package/.worktrees/542c4415/src/plan-adopt-waves.js +0 -126
  475. package/.worktrees/542c4415/src/progress/change-registry.js +0 -336
  476. package/.worktrees/542c4415/src/progress/consistency-doctor.js +0 -355
  477. package/.worktrees/542c4415/src/progress/shared.js +0 -36
  478. package/.worktrees/542c4415/src/progress/stage-machine.js +0 -594
  479. package/.worktrees/542c4415/src/progress/step-store.js +0 -265
  480. package/.worktrees/542c4415/src/progress.js +0 -1304
  481. package/.worktrees/542c4415/src/quick-recommend.js +0 -115
  482. package/.worktrees/542c4415/src/quicklog.js +0 -883
  483. package/.worktrees/542c4415/src/review-tier.js +0 -77
  484. package/.worktrees/542c4415/src/run/command.js +0 -1641
  485. package/.worktrees/542c4415/src/run/complete-handlers.js +0 -1552
  486. package/.worktrees/542c4415/src/run/complete.js +0 -1259
  487. package/.worktrees/542c4415/src/run/concurrent-detect.js +0 -156
  488. package/.worktrees/542c4415/src/run/gates.js +0 -1111
  489. package/.worktrees/542c4415/src/run/multi-repo-context.js +0 -208
  490. package/.worktrees/542c4415/src/run/next.js +0 -128
  491. package/.worktrees/542c4415/src/run/prompt.js +0 -843
  492. package/.worktrees/542c4415/src/run/quick-audit.js +0 -186
  493. package/.worktrees/542c4415/src/run/scan-profile.js +0 -269
  494. package/.worktrees/542c4415/src/run/shared.js +0 -1562
  495. package/.worktrees/542c4415/src/run/stage.js +0 -587
  496. package/.worktrees/542c4415/src/run.js +0 -23
  497. package/.worktrees/542c4415/src/scan-diff.js +0 -388
  498. package/.worktrees/542c4415/src/scan-postcheck.js +0 -524
  499. package/.worktrees/542c4415/src/scan-staleness.js +0 -95
  500. package/.worktrees/542c4415/src/setup.js +0 -414
  501. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +0 -597
  502. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +0 -62
  503. package/.worktrees/542c4415/src/spec-dir-typo.js +0 -50
  504. package/.worktrees/542c4415/src/spec-sync.js +0 -358
  505. package/.worktrees/542c4415/src/stage-contract-engine.js +0 -171
  506. package/.worktrees/542c4415/src/stage-contract-spec.js +0 -551
  507. package/.worktrees/542c4415/src/stage-contract.js +0 -948
  508. package/.worktrees/542c4415/src/stage-review.js +0 -597
  509. package/.worktrees/542c4415/src/stages/archive.js +0 -199
  510. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +0 -285
  511. package/.worktrees/542c4415/src/stages/brainstorm.js +0 -624
  512. package/.worktrees/542c4415/src/stages/cmd-existence.js +0 -145
  513. package/.worktrees/542c4415/src/stages/doctor.js +0 -540
  514. package/.worktrees/542c4415/src/stages/execute.js +0 -1277
  515. package/.worktrees/542c4415/src/stages/explore.js +0 -43
  516. package/.worktrees/542c4415/src/stages/index.js +0 -29
  517. package/.worktrees/542c4415/src/stages/knowledge.js +0 -514
  518. package/.worktrees/542c4415/src/stages/plan-postcheck.js +0 -1398
  519. package/.worktrees/542c4415/src/stages/plan.js +0 -655
  520. package/.worktrees/542c4415/src/stages/quick.js +0 -167
  521. package/.worktrees/542c4415/src/stages/scan.js +0 -608
  522. package/.worktrees/542c4415/src/stages/status.js +0 -64
  523. package/.worktrees/542c4415/src/stages/verify.js +0 -246
  524. package/.worktrees/542c4415/src/sync.js +0 -1470
  525. package/.worktrees/542c4415/src/task-review.js +0 -1498
  526. package/.worktrees/542c4415/src/taskcard-placeholders.js +0 -21
  527. package/.worktrees/542c4415/src/taskcard.js +0 -250
  528. package/.worktrees/542c4415/src/verify-postcheck.js +0 -1718
  529. package/.worktrees/542c4415/src/verify-probes.js +0 -327
  530. package/.worktrees/542c4415/src/version.js +0 -19
  531. package/.worktrees/542c4415/src/workflow.js +0 -600
  532. package/.worktrees/542c4415/src/workspace.js +0 -125
  533. package/.worktrees/542c4415/src/worktree-apply.js +0 -1611
  534. package/.worktrees/542c4415/src/worktree-deps.js +0 -668
  535. package/.worktrees/542c4415/src/worktree.js +0 -1849
  536. package/.worktrees/542c4415/templates/claude-instruction.md +0 -23
  537. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +0 -29
  538. package/.worktrees/542c4415/templates/prompts/testcase-design.md +0 -12
  539. package/.worktrees/542c4415/templates/prompts/verify-probes.md +0 -32
  540. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +0 -79
  541. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +0 -132
  542. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  543. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  544. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  545. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  546. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  547. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  548. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  549. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  550. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +0 -57
  551. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +0 -177
  552. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  553. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  554. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  555. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  556. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  557. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  558. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +0 -64
  559. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +0 -54
  560. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  561. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  562. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +0 -6
  563. package/.worktrees/8d2d0392/.gitattributes +0 -2
  564. package/.worktrees/8d2d0392/.husky/pre-push +0 -20
  565. package/.worktrees/8d2d0392/README.md +0 -203
  566. package/.worktrees/8d2d0392/SKILL.md +0 -91
  567. package/.worktrees/8d2d0392/architecture-analysis.md +0 -448
  568. package/.worktrees/8d2d0392/bin/sillyspec.js +0 -2
  569. package/.worktrees/8d2d0392/eval/README.md +0 -86
  570. package/.worktrees/8d2d0392/eval/eval.config.json +0 -28
  571. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +0 -63
  572. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +0 -27
  573. package/.worktrees/8d2d0392/eval/lib/config.mjs +0 -82
  574. package/.worktrees/8d2d0392/eval/lib/db.mjs +0 -76
  575. package/.worktrees/8d2d0392/eval/lib/report.mjs +0 -120
  576. package/.worktrees/8d2d0392/eval/lib/runner.mjs +0 -157
  577. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +0 -73
  578. package/.worktrees/8d2d0392/eval/lib/util.mjs +0 -107
  579. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +0 -30
  580. package/.worktrees/8d2d0392/eval/run.mjs +0 -83
  581. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +0 -6
  582. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  583. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +0 -6
  584. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +0 -28
  585. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +0 -6
  586. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  587. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  588. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +0 -6
  589. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +0 -31
  590. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  591. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +0 -6
  592. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  593. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +0 -6
  594. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +0 -38
  595. package/.worktrees/8d2d0392/logo.jpg +0 -0
  596. package/.worktrees/8d2d0392/package-lock.json +0 -977
  597. package/.worktrees/8d2d0392/package.json +0 -41
  598. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  599. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  600. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  601. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +0 -16
  602. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  603. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +0 -836
  604. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +0 -256
  605. package/.worktrees/8d2d0392/packages/dashboard/package.json +0 -25
  606. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +0 -95
  607. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +0 -679
  608. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +0 -526
  609. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +0 -357
  610. package/.worktrees/8d2d0392/src/agent-session-log.js +0 -803
  611. package/.worktrees/8d2d0392/src/change-list.js +0 -290
  612. package/.worktrees/8d2d0392/src/change-risk-profile.js +0 -339
  613. package/.worktrees/8d2d0392/src/check-primitives.js +0 -65
  614. package/.worktrees/8d2d0392/src/classify-change.js +0 -109
  615. package/.worktrees/8d2d0392/src/commit-suggest.js +0 -202
  616. package/.worktrees/8d2d0392/src/config-cat.js +0 -88
  617. package/.worktrees/8d2d0392/src/config-schema.js +0 -328
  618. package/.worktrees/8d2d0392/src/constants.js +0 -97
  619. package/.worktrees/8d2d0392/src/contract-matrix.js +0 -533
  620. package/.worktrees/8d2d0392/src/datetime.js +0 -20
  621. package/.worktrees/8d2d0392/src/db-engine.js +0 -55
  622. package/.worktrees/8d2d0392/src/db.js +0 -381
  623. package/.worktrees/8d2d0392/src/decision-distill.js +0 -517
  624. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +0 -155
  625. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +0 -245
  626. package/.worktrees/8d2d0392/src/dispatch/probe.js +0 -246
  627. package/.worktrees/8d2d0392/src/dispatch/strategy.js +0 -121
  628. package/.worktrees/8d2d0392/src/docs-check.js +0 -825
  629. package/.worktrees/8d2d0392/src/docs-debt.js +0 -393
  630. package/.worktrees/8d2d0392/src/docs-gate.js +0 -107
  631. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +0 -1099
  632. package/.worktrees/8d2d0392/src/endpoint-extractor.js +0 -409
  633. package/.worktrees/8d2d0392/src/foreign-declared.js +0 -78
  634. package/.worktrees/8d2d0392/src/fs-atomic.js +0 -73
  635. package/.worktrees/8d2d0392/src/git-helper.js +0 -150
  636. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +0 -130
  637. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +0 -892
  638. package/.worktrees/8d2d0392/src/index.js +0 -2854
  639. package/.worktrees/8d2d0392/src/init.js +0 -626
  640. package/.worktrees/8d2d0392/src/knowledge-match.js +0 -231
  641. package/.worktrees/8d2d0392/src/local-detect.js +0 -128
  642. package/.worktrees/8d2d0392/src/local-register.js +0 -104
  643. package/.worktrees/8d2d0392/src/machine-interface.js +0 -543
  644. package/.worktrees/8d2d0392/src/migrate.js +0 -127
  645. package/.worktrees/8d2d0392/src/module-impact.js +0 -166
  646. package/.worktrees/8d2d0392/src/module-resolve.js +0 -222
  647. package/.worktrees/8d2d0392/src/modules.js +0 -580
  648. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +0 -126
  649. package/.worktrees/8d2d0392/src/progress/change-registry.js +0 -336
  650. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +0 -355
  651. package/.worktrees/8d2d0392/src/progress/shared.js +0 -36
  652. package/.worktrees/8d2d0392/src/progress/stage-machine.js +0 -594
  653. package/.worktrees/8d2d0392/src/progress/step-store.js +0 -265
  654. package/.worktrees/8d2d0392/src/progress.js +0 -1304
  655. package/.worktrees/8d2d0392/src/quick-recommend.js +0 -115
  656. package/.worktrees/8d2d0392/src/quicklog.js +0 -883
  657. package/.worktrees/8d2d0392/src/review-tier.js +0 -77
  658. package/.worktrees/8d2d0392/src/run/command.js +0 -1641
  659. package/.worktrees/8d2d0392/src/run/complete-handlers.js +0 -1552
  660. package/.worktrees/8d2d0392/src/run/complete.js +0 -1259
  661. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +0 -156
  662. package/.worktrees/8d2d0392/src/run/gates.js +0 -1094
  663. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +0 -208
  664. package/.worktrees/8d2d0392/src/run/next.js +0 -128
  665. package/.worktrees/8d2d0392/src/run/prompt.js +0 -843
  666. package/.worktrees/8d2d0392/src/run/quick-audit.js +0 -186
  667. package/.worktrees/8d2d0392/src/run/scan-profile.js +0 -269
  668. package/.worktrees/8d2d0392/src/run/shared.js +0 -1562
  669. package/.worktrees/8d2d0392/src/run/stage.js +0 -587
  670. package/.worktrees/8d2d0392/src/run.js +0 -23
  671. package/.worktrees/8d2d0392/src/scan-diff.js +0 -388
  672. package/.worktrees/8d2d0392/src/scan-postcheck.js +0 -524
  673. package/.worktrees/8d2d0392/src/scan-staleness.js +0 -95
  674. package/.worktrees/8d2d0392/src/setup.js +0 -414
  675. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +0 -597
  676. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +0 -62
  677. package/.worktrees/8d2d0392/src/spec-dir-typo.js +0 -50
  678. package/.worktrees/8d2d0392/src/spec-sync.js +0 -358
  679. package/.worktrees/8d2d0392/src/stage-contract-engine.js +0 -171
  680. package/.worktrees/8d2d0392/src/stage-contract-spec.js +0 -551
  681. package/.worktrees/8d2d0392/src/stage-contract.js +0 -948
  682. package/.worktrees/8d2d0392/src/stage-review.js +0 -597
  683. package/.worktrees/8d2d0392/src/stages/archive.js +0 -199
  684. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +0 -285
  685. package/.worktrees/8d2d0392/src/stages/brainstorm.js +0 -624
  686. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +0 -145
  687. package/.worktrees/8d2d0392/src/stages/doctor.js +0 -540
  688. package/.worktrees/8d2d0392/src/stages/execute.js +0 -1277
  689. package/.worktrees/8d2d0392/src/stages/explore.js +0 -43
  690. package/.worktrees/8d2d0392/src/stages/index.js +0 -29
  691. package/.worktrees/8d2d0392/src/stages/knowledge.js +0 -514
  692. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +0 -1398
  693. package/.worktrees/8d2d0392/src/stages/plan.js +0 -651
  694. package/.worktrees/8d2d0392/src/stages/quick.js +0 -167
  695. package/.worktrees/8d2d0392/src/stages/scan.js +0 -608
  696. package/.worktrees/8d2d0392/src/stages/status.js +0 -64
  697. package/.worktrees/8d2d0392/src/stages/verify.js +0 -246
  698. package/.worktrees/8d2d0392/src/sync.js +0 -1470
  699. package/.worktrees/8d2d0392/src/task-review.js +0 -1498
  700. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +0 -21
  701. package/.worktrees/8d2d0392/src/taskcard.js +0 -217
  702. package/.worktrees/8d2d0392/src/verify-postcheck.js +0 -1718
  703. package/.worktrees/8d2d0392/src/verify-probes.js +0 -327
  704. package/.worktrees/8d2d0392/src/version.js +0 -19
  705. package/.worktrees/8d2d0392/src/workflow.js +0 -600
  706. package/.worktrees/8d2d0392/src/workspace.js +0 -125
  707. package/.worktrees/8d2d0392/src/worktree-apply.js +0 -1611
  708. package/.worktrees/8d2d0392/src/worktree-deps.js +0 -576
  709. package/.worktrees/8d2d0392/src/worktree.js +0 -1838
  710. package/.worktrees/8d2d0392/templates/claude-instruction.md +0 -23
  711. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +0 -29
  712. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +0 -12
  713. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +0 -32
  714. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +0 -79
  715. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +0 -132
  716. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  717. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  718. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  719. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  720. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  721. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  722. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  723. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  724. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +0 -57
  725. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +0 -177
  726. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  727. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  728. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  729. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  730. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  731. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +0 -64
  732. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +0 -54
  733. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  734. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  735. package/.worktrees/c1eae35e/.gitattributes +0 -2
  736. package/.worktrees/c1eae35e/.husky/pre-push +0 -20
  737. package/.worktrees/c1eae35e/README.md +0 -203
  738. package/.worktrees/c1eae35e/SKILL.md +0 -91
  739. package/.worktrees/c1eae35e/architecture-analysis.md +0 -448
  740. package/.worktrees/c1eae35e/bin/sillyspec.js +0 -2
  741. package/.worktrees/c1eae35e/eval/README.md +0 -86
  742. package/.worktrees/c1eae35e/eval/eval.config.json +0 -28
  743. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +0 -63
  744. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +0 -27
  745. package/.worktrees/c1eae35e/eval/lib/config.mjs +0 -82
  746. package/.worktrees/c1eae35e/eval/lib/db.mjs +0 -76
  747. package/.worktrees/c1eae35e/eval/lib/report.mjs +0 -120
  748. package/.worktrees/c1eae35e/eval/lib/runner.mjs +0 -157
  749. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +0 -73
  750. package/.worktrees/c1eae35e/eval/lib/util.mjs +0 -107
  751. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +0 -30
  752. package/.worktrees/c1eae35e/eval/run.mjs +0 -83
  753. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +0 -6
  754. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  755. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +0 -6
  756. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +0 -28
  757. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +0 -6
  758. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  759. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  760. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +0 -6
  761. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +0 -31
  762. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  763. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +0 -6
  764. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  765. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +0 -6
  766. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +0 -38
  767. package/.worktrees/c1eae35e/logo.jpg +0 -0
  768. package/.worktrees/c1eae35e/package-lock.json +0 -977
  769. package/.worktrees/c1eae35e/package.json +0 -41
  770. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  771. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  772. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  773. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +0 -16
  774. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  775. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +0 -836
  776. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +0 -256
  777. package/.worktrees/c1eae35e/packages/dashboard/package.json +0 -25
  778. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +0 -95
  779. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +0 -679
  780. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +0 -526
  781. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +0 -357
  782. package/.worktrees/c1eae35e/src/agent-session-log.js +0 -803
  783. package/.worktrees/c1eae35e/src/change-list.js +0 -290
  784. package/.worktrees/c1eae35e/src/change-risk-profile.js +0 -339
  785. package/.worktrees/c1eae35e/src/check-primitives.js +0 -65
  786. package/.worktrees/c1eae35e/src/classify-change.js +0 -109
  787. package/.worktrees/c1eae35e/src/commit-suggest.js +0 -202
  788. package/.worktrees/c1eae35e/src/config-cat.js +0 -88
  789. package/.worktrees/c1eae35e/src/config-schema.js +0 -328
  790. package/.worktrees/c1eae35e/src/constants.js +0 -97
  791. package/.worktrees/c1eae35e/src/contract-matrix.js +0 -533
  792. package/.worktrees/c1eae35e/src/datetime.js +0 -20
  793. package/.worktrees/c1eae35e/src/db-engine.js +0 -55
  794. package/.worktrees/c1eae35e/src/db.js +0 -381
  795. package/.worktrees/c1eae35e/src/decision-distill.js +0 -517
  796. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +0 -155
  797. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +0 -245
  798. package/.worktrees/c1eae35e/src/dispatch/probe.js +0 -246
  799. package/.worktrees/c1eae35e/src/dispatch/strategy.js +0 -121
  800. package/.worktrees/c1eae35e/src/docs-check.js +0 -825
  801. package/.worktrees/c1eae35e/src/docs-debt.js +0 -393
  802. package/.worktrees/c1eae35e/src/docs-gate.js +0 -107
  803. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +0 -1099
  804. package/.worktrees/c1eae35e/src/endpoint-extractor.js +0 -409
  805. package/.worktrees/c1eae35e/src/foreign-declared.js +0 -155
  806. package/.worktrees/c1eae35e/src/fs-atomic.js +0 -73
  807. package/.worktrees/c1eae35e/src/git-helper.js +0 -150
  808. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +0 -130
  809. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +0 -892
  810. package/.worktrees/c1eae35e/src/index.js +0 -2854
  811. package/.worktrees/c1eae35e/src/init.js +0 -626
  812. package/.worktrees/c1eae35e/src/knowledge-match.js +0 -231
  813. package/.worktrees/c1eae35e/src/local-detect.js +0 -128
  814. package/.worktrees/c1eae35e/src/local-register.js +0 -104
  815. package/.worktrees/c1eae35e/src/machine-interface.js +0 -543
  816. package/.worktrees/c1eae35e/src/migrate.js +0 -127
  817. package/.worktrees/c1eae35e/src/module-impact.js +0 -166
  818. package/.worktrees/c1eae35e/src/module-resolve.js +0 -222
  819. package/.worktrees/c1eae35e/src/modules.js +0 -580
  820. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +0 -126
  821. package/.worktrees/c1eae35e/src/progress/change-registry.js +0 -336
  822. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +0 -355
  823. package/.worktrees/c1eae35e/src/progress/shared.js +0 -36
  824. package/.worktrees/c1eae35e/src/progress/stage-machine.js +0 -594
  825. package/.worktrees/c1eae35e/src/progress/step-store.js +0 -265
  826. package/.worktrees/c1eae35e/src/progress.js +0 -1304
  827. package/.worktrees/c1eae35e/src/quick-recommend.js +0 -115
  828. package/.worktrees/c1eae35e/src/quicklog.js +0 -883
  829. package/.worktrees/c1eae35e/src/review-tier.js +0 -77
  830. package/.worktrees/c1eae35e/src/run/command.js +0 -1641
  831. package/.worktrees/c1eae35e/src/run/complete-handlers.js +0 -1552
  832. package/.worktrees/c1eae35e/src/run/complete.js +0 -1259
  833. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +0 -156
  834. package/.worktrees/c1eae35e/src/run/gates.js +0 -1111
  835. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +0 -208
  836. package/.worktrees/c1eae35e/src/run/next.js +0 -128
  837. package/.worktrees/c1eae35e/src/run/prompt.js +0 -843
  838. package/.worktrees/c1eae35e/src/run/quick-audit.js +0 -186
  839. package/.worktrees/c1eae35e/src/run/scan-profile.js +0 -269
  840. package/.worktrees/c1eae35e/src/run/shared.js +0 -1562
  841. package/.worktrees/c1eae35e/src/run/stage.js +0 -587
  842. package/.worktrees/c1eae35e/src/run.js +0 -23
  843. package/.worktrees/c1eae35e/src/scan-diff.js +0 -388
  844. package/.worktrees/c1eae35e/src/scan-postcheck.js +0 -524
  845. package/.worktrees/c1eae35e/src/scan-staleness.js +0 -95
  846. package/.worktrees/c1eae35e/src/setup.js +0 -414
  847. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +0 -597
  848. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +0 -62
  849. package/.worktrees/c1eae35e/src/spec-dir-typo.js +0 -50
  850. package/.worktrees/c1eae35e/src/spec-sync.js +0 -358
  851. package/.worktrees/c1eae35e/src/stage-contract-engine.js +0 -171
  852. package/.worktrees/c1eae35e/src/stage-contract-spec.js +0 -551
  853. package/.worktrees/c1eae35e/src/stage-contract.js +0 -948
  854. package/.worktrees/c1eae35e/src/stage-review.js +0 -597
  855. package/.worktrees/c1eae35e/src/stages/archive.js +0 -199
  856. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +0 -285
  857. package/.worktrees/c1eae35e/src/stages/brainstorm.js +0 -624
  858. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +0 -145
  859. package/.worktrees/c1eae35e/src/stages/doctor.js +0 -540
  860. package/.worktrees/c1eae35e/src/stages/execute.js +0 -1277
  861. package/.worktrees/c1eae35e/src/stages/explore.js +0 -43
  862. package/.worktrees/c1eae35e/src/stages/index.js +0 -29
  863. package/.worktrees/c1eae35e/src/stages/knowledge.js +0 -514
  864. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +0 -1398
  865. package/.worktrees/c1eae35e/src/stages/plan.js +0 -655
  866. package/.worktrees/c1eae35e/src/stages/quick.js +0 -167
  867. package/.worktrees/c1eae35e/src/stages/scan.js +0 -608
  868. package/.worktrees/c1eae35e/src/stages/status.js +0 -64
  869. package/.worktrees/c1eae35e/src/stages/verify.js +0 -246
  870. package/.worktrees/c1eae35e/src/sync.js +0 -1470
  871. package/.worktrees/c1eae35e/src/task-review.js +0 -1498
  872. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +0 -21
  873. package/.worktrees/c1eae35e/src/taskcard.js +0 -250
  874. package/.worktrees/c1eae35e/src/verify-postcheck.js +0 -1718
  875. package/.worktrees/c1eae35e/src/verify-probes.js +0 -327
  876. package/.worktrees/c1eae35e/src/version.js +0 -19
  877. package/.worktrees/c1eae35e/src/workflow.js +0 -600
  878. package/.worktrees/c1eae35e/src/workspace.js +0 -125
  879. package/.worktrees/c1eae35e/src/worktree-apply.js +0 -1611
  880. package/.worktrees/c1eae35e/src/worktree-deps.js +0 -668
  881. package/.worktrees/c1eae35e/src/worktree.js +0 -1849
  882. package/.worktrees/c1eae35e/templates/claude-instruction.md +0 -23
  883. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +0 -29
  884. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +0 -12
  885. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +0 -32
  886. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +0 -79
  887. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +0 -132
  888. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  889. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  890. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  891. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  892. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  893. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  894. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  895. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  896. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +0 -57
  897. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +0 -177
  898. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  899. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  900. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  901. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  902. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  903. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  904. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +0 -64
  905. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +0 -54
  906. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  907. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  908. package/.worktrees/dafc71ad/.gitattributes +0 -2
  909. package/.worktrees/dafc71ad/.husky/pre-push +0 -20
  910. package/.worktrees/dafc71ad/README.md +0 -203
  911. package/.worktrees/dafc71ad/SKILL.md +0 -91
  912. package/.worktrees/dafc71ad/analysis.md +0 -366
  913. package/.worktrees/dafc71ad/architecture-analysis.md +0 -448
  914. package/.worktrees/dafc71ad/bin/sillyspec.js +0 -2
  915. package/.worktrees/dafc71ad/eval/README.md +0 -86
  916. package/.worktrees/dafc71ad/eval/eval.config.json +0 -28
  917. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +0 -63
  918. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +0 -27
  919. package/.worktrees/dafc71ad/eval/lib/config.mjs +0 -82
  920. package/.worktrees/dafc71ad/eval/lib/db.mjs +0 -76
  921. package/.worktrees/dafc71ad/eval/lib/report.mjs +0 -120
  922. package/.worktrees/dafc71ad/eval/lib/runner.mjs +0 -157
  923. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +0 -73
  924. package/.worktrees/dafc71ad/eval/lib/util.mjs +0 -107
  925. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +0 -30
  926. package/.worktrees/dafc71ad/eval/run.mjs +0 -83
  927. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +0 -6
  928. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  929. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +0 -6
  930. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +0 -28
  931. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +0 -6
  932. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  933. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  934. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +0 -6
  935. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +0 -31
  936. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  937. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +0 -6
  938. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  939. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +0 -6
  940. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +0 -38
  941. package/.worktrees/dafc71ad/logo.jpg +0 -0
  942. package/.worktrees/dafc71ad/package-lock.json +0 -977
  943. package/.worktrees/dafc71ad/package.json +0 -41
  944. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  945. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  946. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  947. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +0 -16
  948. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  949. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +0 -836
  950. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +0 -256
  951. package/.worktrees/dafc71ad/packages/dashboard/package.json +0 -25
  952. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +0 -95
  953. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +0 -679
  954. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +0 -526
  955. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +0 -357
  956. package/.worktrees/dafc71ad/src/agent-session-log.js +0 -803
  957. package/.worktrees/dafc71ad/src/change-list.js +0 -290
  958. package/.worktrees/dafc71ad/src/change-risk-profile.js +0 -339
  959. package/.worktrees/dafc71ad/src/check-primitives.js +0 -65
  960. package/.worktrees/dafc71ad/src/classify-change.js +0 -109
  961. package/.worktrees/dafc71ad/src/commit-suggest.js +0 -202
  962. package/.worktrees/dafc71ad/src/config-cat.js +0 -88
  963. package/.worktrees/dafc71ad/src/config-schema.js +0 -328
  964. package/.worktrees/dafc71ad/src/constants.js +0 -97
  965. package/.worktrees/dafc71ad/src/contract-matrix.js +0 -533
  966. package/.worktrees/dafc71ad/src/datetime.js +0 -20
  967. package/.worktrees/dafc71ad/src/db-engine.js +0 -55
  968. package/.worktrees/dafc71ad/src/db.js +0 -381
  969. package/.worktrees/dafc71ad/src/decision-distill.js +0 -517
  970. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +0 -155
  971. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +0 -245
  972. package/.worktrees/dafc71ad/src/dispatch/probe.js +0 -246
  973. package/.worktrees/dafc71ad/src/dispatch/strategy.js +0 -121
  974. package/.worktrees/dafc71ad/src/docs-check.js +0 -825
  975. package/.worktrees/dafc71ad/src/docs-debt.js +0 -393
  976. package/.worktrees/dafc71ad/src/docs-gate.js +0 -107
  977. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +0 -1099
  978. package/.worktrees/dafc71ad/src/endpoint-extractor.js +0 -409
  979. package/.worktrees/dafc71ad/src/foreign-declared.js +0 -155
  980. package/.worktrees/dafc71ad/src/fs-atomic.js +0 -73
  981. package/.worktrees/dafc71ad/src/git-helper.js +0 -150
  982. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +0 -130
  983. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +0 -892
  984. package/.worktrees/dafc71ad/src/index.js +0 -2854
  985. package/.worktrees/dafc71ad/src/init.js +0 -626
  986. package/.worktrees/dafc71ad/src/knowledge-match.js +0 -231
  987. package/.worktrees/dafc71ad/src/local-detect.js +0 -128
  988. package/.worktrees/dafc71ad/src/local-register.js +0 -104
  989. package/.worktrees/dafc71ad/src/machine-interface.js +0 -543
  990. package/.worktrees/dafc71ad/src/migrate.js +0 -127
  991. package/.worktrees/dafc71ad/src/module-impact.js +0 -166
  992. package/.worktrees/dafc71ad/src/module-resolve.js +0 -222
  993. package/.worktrees/dafc71ad/src/modules.js +0 -580
  994. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +0 -126
  995. package/.worktrees/dafc71ad/src/progress/change-registry.js +0 -336
  996. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +0 -355
  997. package/.worktrees/dafc71ad/src/progress/shared.js +0 -36
  998. package/.worktrees/dafc71ad/src/progress/stage-machine.js +0 -594
  999. package/.worktrees/dafc71ad/src/progress/step-store.js +0 -265
  1000. package/.worktrees/dafc71ad/src/progress.js +0 -1304
  1001. package/.worktrees/dafc71ad/src/quick-recommend.js +0 -115
  1002. package/.worktrees/dafc71ad/src/quicklog.js +0 -883
  1003. package/.worktrees/dafc71ad/src/review-tier.js +0 -77
  1004. package/.worktrees/dafc71ad/src/run/command.js +0 -1641
  1005. package/.worktrees/dafc71ad/src/run/complete-handlers.js +0 -1552
  1006. package/.worktrees/dafc71ad/src/run/complete.js +0 -1259
  1007. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +0 -156
  1008. package/.worktrees/dafc71ad/src/run/gates.js +0 -1111
  1009. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +0 -208
  1010. package/.worktrees/dafc71ad/src/run/next.js +0 -128
  1011. package/.worktrees/dafc71ad/src/run/prompt.js +0 -843
  1012. package/.worktrees/dafc71ad/src/run/quick-audit.js +0 -186
  1013. package/.worktrees/dafc71ad/src/run/scan-profile.js +0 -269
  1014. package/.worktrees/dafc71ad/src/run/shared.js +0 -1562
  1015. package/.worktrees/dafc71ad/src/run/stage.js +0 -587
  1016. package/.worktrees/dafc71ad/src/run.js +0 -23
  1017. package/.worktrees/dafc71ad/src/scan-diff.js +0 -388
  1018. package/.worktrees/dafc71ad/src/scan-postcheck.js +0 -524
  1019. package/.worktrees/dafc71ad/src/scan-staleness.js +0 -95
  1020. package/.worktrees/dafc71ad/src/setup.js +0 -414
  1021. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +0 -597
  1022. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +0 -62
  1023. package/.worktrees/dafc71ad/src/spec-dir-typo.js +0 -50
  1024. package/.worktrees/dafc71ad/src/spec-sync.js +0 -358
  1025. package/.worktrees/dafc71ad/src/stage-contract-engine.js +0 -171
  1026. package/.worktrees/dafc71ad/src/stage-contract-spec.js +0 -551
  1027. package/.worktrees/dafc71ad/src/stage-contract.js +0 -948
  1028. package/.worktrees/dafc71ad/src/stage-review.js +0 -597
  1029. package/.worktrees/dafc71ad/src/stages/archive.js +0 -199
  1030. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +0 -285
  1031. package/.worktrees/dafc71ad/src/stages/brainstorm.js +0 -624
  1032. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +0 -145
  1033. package/.worktrees/dafc71ad/src/stages/doctor.js +0 -540
  1034. package/.worktrees/dafc71ad/src/stages/execute.js +0 -1277
  1035. package/.worktrees/dafc71ad/src/stages/explore.js +0 -43
  1036. package/.worktrees/dafc71ad/src/stages/index.js +0 -29
  1037. package/.worktrees/dafc71ad/src/stages/knowledge.js +0 -514
  1038. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +0 -1398
  1039. package/.worktrees/dafc71ad/src/stages/plan.js +0 -655
  1040. package/.worktrees/dafc71ad/src/stages/quick.js +0 -167
  1041. package/.worktrees/dafc71ad/src/stages/scan.js +0 -608
  1042. package/.worktrees/dafc71ad/src/stages/status.js +0 -64
  1043. package/.worktrees/dafc71ad/src/stages/verify.js +0 -246
  1044. package/.worktrees/dafc71ad/src/sync.js +0 -1470
  1045. package/.worktrees/dafc71ad/src/task-review.js +0 -1498
  1046. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +0 -21
  1047. package/.worktrees/dafc71ad/src/taskcard.js +0 -250
  1048. package/.worktrees/dafc71ad/src/verify-postcheck.js +0 -1718
  1049. package/.worktrees/dafc71ad/src/verify-probes.js +0 -327
  1050. package/.worktrees/dafc71ad/src/version.js +0 -19
  1051. package/.worktrees/dafc71ad/src/workflow.js +0 -600
  1052. package/.worktrees/dafc71ad/src/workspace.js +0 -125
  1053. package/.worktrees/dafc71ad/src/worktree-apply.js +0 -1611
  1054. package/.worktrees/dafc71ad/src/worktree-deps.js +0 -668
  1055. package/.worktrees/dafc71ad/src/worktree.js +0 -1849
  1056. package/.worktrees/dafc71ad/templates/claude-instruction.md +0 -23
  1057. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +0 -29
  1058. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +0 -12
  1059. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +0 -32
  1060. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +0 -79
  1061. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +0 -132
  1062. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  1063. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  1064. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  1065. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  1066. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  1067. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  1068. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  1069. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  1070. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +0 -57
  1071. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +0 -177
  1072. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  1073. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  1074. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  1075. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  1076. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  1077. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  1078. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +0 -64
  1079. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +0 -54
  1080. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  1081. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  1082. package/.worktrees/e58fcc4c/.gitattributes +0 -2
  1083. package/.worktrees/e58fcc4c/.husky/pre-push +0 -20
  1084. package/.worktrees/e58fcc4c/README.md +0 -203
  1085. package/.worktrees/e58fcc4c/SKILL.md +0 -91
  1086. package/.worktrees/e58fcc4c/architecture-analysis.md +0 -503
  1087. package/.worktrees/e58fcc4c/bin/sillyspec.js +0 -2
  1088. package/.worktrees/e58fcc4c/eval/README.md +0 -86
  1089. package/.worktrees/e58fcc4c/eval/eval.config.json +0 -28
  1090. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +0 -63
  1091. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +0 -27
  1092. package/.worktrees/e58fcc4c/eval/lib/config.mjs +0 -82
  1093. package/.worktrees/e58fcc4c/eval/lib/db.mjs +0 -76
  1094. package/.worktrees/e58fcc4c/eval/lib/report.mjs +0 -120
  1095. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +0 -157
  1096. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +0 -73
  1097. package/.worktrees/e58fcc4c/eval/lib/util.mjs +0 -107
  1098. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +0 -30
  1099. package/.worktrees/e58fcc4c/eval/run.mjs +0 -83
  1100. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +0 -6
  1101. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  1102. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +0 -6
  1103. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +0 -28
  1104. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +0 -6
  1105. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  1106. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  1107. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +0 -6
  1108. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +0 -31
  1109. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  1110. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +0 -6
  1111. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  1112. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +0 -6
  1113. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +0 -38
  1114. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  1115. package/.worktrees/e58fcc4c/package-lock.json +0 -977
  1116. package/.worktrees/e58fcc4c/package.json +0 -41
  1117. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  1118. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  1119. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  1120. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +0 -16
  1121. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  1122. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +0 -836
  1123. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +0 -256
  1124. package/.worktrees/e58fcc4c/packages/dashboard/package.json +0 -25
  1125. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +0 -95
  1126. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +0 -679
  1127. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +0 -526
  1128. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +0 -357
  1129. package/.worktrees/e58fcc4c/src/agent-session-log.js +0 -803
  1130. package/.worktrees/e58fcc4c/src/change-list.js +0 -290
  1131. package/.worktrees/e58fcc4c/src/change-risk-profile.js +0 -339
  1132. package/.worktrees/e58fcc4c/src/check-primitives.js +0 -65
  1133. package/.worktrees/e58fcc4c/src/classify-change.js +0 -109
  1134. package/.worktrees/e58fcc4c/src/commit-suggest.js +0 -202
  1135. package/.worktrees/e58fcc4c/src/config-cat.js +0 -88
  1136. package/.worktrees/e58fcc4c/src/config-schema.js +0 -328
  1137. package/.worktrees/e58fcc4c/src/constants.js +0 -97
  1138. package/.worktrees/e58fcc4c/src/contract-matrix.js +0 -533
  1139. package/.worktrees/e58fcc4c/src/datetime.js +0 -20
  1140. package/.worktrees/e58fcc4c/src/db-engine.js +0 -55
  1141. package/.worktrees/e58fcc4c/src/db.js +0 -381
  1142. package/.worktrees/e58fcc4c/src/decision-distill.js +0 -517
  1143. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +0 -155
  1144. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +0 -245
  1145. package/.worktrees/e58fcc4c/src/dispatch/probe.js +0 -246
  1146. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +0 -121
  1147. package/.worktrees/e58fcc4c/src/docs-check.js +0 -825
  1148. package/.worktrees/e58fcc4c/src/docs-debt.js +0 -393
  1149. package/.worktrees/e58fcc4c/src/docs-gate.js +0 -107
  1150. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +0 -1099
  1151. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +0 -409
  1152. package/.worktrees/e58fcc4c/src/foreign-declared.js +0 -155
  1153. package/.worktrees/e58fcc4c/src/fs-atomic.js +0 -73
  1154. package/.worktrees/e58fcc4c/src/git-helper.js +0 -150
  1155. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +0 -130
  1156. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +0 -892
  1157. package/.worktrees/e58fcc4c/src/index.js +0 -2854
  1158. package/.worktrees/e58fcc4c/src/init.js +0 -626
  1159. package/.worktrees/e58fcc4c/src/knowledge-match.js +0 -231
  1160. package/.worktrees/e58fcc4c/src/local-detect.js +0 -128
  1161. package/.worktrees/e58fcc4c/src/local-register.js +0 -104
  1162. package/.worktrees/e58fcc4c/src/machine-interface.js +0 -543
  1163. package/.worktrees/e58fcc4c/src/migrate.js +0 -127
  1164. package/.worktrees/e58fcc4c/src/module-impact.js +0 -166
  1165. package/.worktrees/e58fcc4c/src/module-resolve.js +0 -222
  1166. package/.worktrees/e58fcc4c/src/modules.js +0 -580
  1167. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +0 -126
  1168. package/.worktrees/e58fcc4c/src/progress/change-registry.js +0 -336
  1169. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +0 -355
  1170. package/.worktrees/e58fcc4c/src/progress/shared.js +0 -36
  1171. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +0 -594
  1172. package/.worktrees/e58fcc4c/src/progress/step-store.js +0 -265
  1173. package/.worktrees/e58fcc4c/src/progress.js +0 -1304
  1174. package/.worktrees/e58fcc4c/src/quick-recommend.js +0 -115
  1175. package/.worktrees/e58fcc4c/src/quicklog.js +0 -883
  1176. package/.worktrees/e58fcc4c/src/review-tier.js +0 -77
  1177. package/.worktrees/e58fcc4c/src/run/command.js +0 -1641
  1178. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +0 -1552
  1179. package/.worktrees/e58fcc4c/src/run/complete.js +0 -1259
  1180. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +0 -156
  1181. package/.worktrees/e58fcc4c/src/run/gates.js +0 -1111
  1182. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +0 -208
  1183. package/.worktrees/e58fcc4c/src/run/next.js +0 -128
  1184. package/.worktrees/e58fcc4c/src/run/prompt.js +0 -843
  1185. package/.worktrees/e58fcc4c/src/run/quick-audit.js +0 -186
  1186. package/.worktrees/e58fcc4c/src/run/scan-profile.js +0 -269
  1187. package/.worktrees/e58fcc4c/src/run/shared.js +0 -1562
  1188. package/.worktrees/e58fcc4c/src/run/stage.js +0 -587
  1189. package/.worktrees/e58fcc4c/src/run.js +0 -23
  1190. package/.worktrees/e58fcc4c/src/scan-diff.js +0 -388
  1191. package/.worktrees/e58fcc4c/src/scan-postcheck.js +0 -524
  1192. package/.worktrees/e58fcc4c/src/scan-staleness.js +0 -95
  1193. package/.worktrees/e58fcc4c/src/setup.js +0 -414
  1194. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +0 -597
  1195. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +0 -62
  1196. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +0 -50
  1197. package/.worktrees/e58fcc4c/src/spec-sync.js +0 -358
  1198. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +0 -171
  1199. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +0 -551
  1200. package/.worktrees/e58fcc4c/src/stage-contract.js +0 -948
  1201. package/.worktrees/e58fcc4c/src/stage-review.js +0 -597
  1202. package/.worktrees/e58fcc4c/src/stages/archive.js +0 -199
  1203. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +0 -285
  1204. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +0 -624
  1205. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +0 -145
  1206. package/.worktrees/e58fcc4c/src/stages/doctor.js +0 -540
  1207. package/.worktrees/e58fcc4c/src/stages/execute.js +0 -1277
  1208. package/.worktrees/e58fcc4c/src/stages/explore.js +0 -43
  1209. package/.worktrees/e58fcc4c/src/stages/index.js +0 -29
  1210. package/.worktrees/e58fcc4c/src/stages/knowledge.js +0 -514
  1211. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +0 -1398
  1212. package/.worktrees/e58fcc4c/src/stages/plan.js +0 -655
  1213. package/.worktrees/e58fcc4c/src/stages/quick.js +0 -167
  1214. package/.worktrees/e58fcc4c/src/stages/scan.js +0 -608
  1215. package/.worktrees/e58fcc4c/src/stages/status.js +0 -64
  1216. package/.worktrees/e58fcc4c/src/stages/verify.js +0 -246
  1217. package/.worktrees/e58fcc4c/src/sync.js +0 -1470
  1218. package/.worktrees/e58fcc4c/src/task-review.js +0 -1498
  1219. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +0 -21
  1220. package/.worktrees/e58fcc4c/src/taskcard.js +0 -250
  1221. package/.worktrees/e58fcc4c/src/verify-postcheck.js +0 -1718
  1222. package/.worktrees/e58fcc4c/src/verify-probes.js +0 -327
  1223. package/.worktrees/e58fcc4c/src/version.js +0 -19
  1224. package/.worktrees/e58fcc4c/src/workflow.js +0 -600
  1225. package/.worktrees/e58fcc4c/src/workspace.js +0 -125
  1226. package/.worktrees/e58fcc4c/src/worktree-apply.js +0 -1611
  1227. package/.worktrees/e58fcc4c/src/worktree-deps.js +0 -668
  1228. package/.worktrees/e58fcc4c/src/worktree.js +0 -1849
  1229. package/.worktrees/e58fcc4c/templates/claude-instruction.md +0 -23
  1230. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +0 -29
  1231. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +0 -12
  1232. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +0 -32
  1233. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +0 -79
  1234. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +0 -132
@@ -1,1562 +0,0 @@
1
- /**
2
- * run.js 共享纯工具(W6 Step1 从 run.js 抽出)。
3
- *
4
- * 安全锚:run.js 始终是 barrel。这些函数搬至此模块后,run.js import 回来;
5
- * parsePorcelainPath + auditQuickCompletion 被 test 直接 import,run.js 必须 re-export。
6
- *
7
- * 路径修正(相对 src/run/):
8
- * - resolvePromptIncludes 的 templates/prompts 在仓库根 → __dirname 上两层
9
- * - triggerSync 的动态 import './sync.js' → '../sync.js'(src/sync.js)
10
- * - safeGit 已收口到 src/git-helper.js(单一公共 git 调用入口,数组形式不经 shell),
11
- * 本模块仅 re-export,run/ 层现有调用方路径与行为不变。
12
- */
13
- import { basename, join, resolve, dirname, sep } from 'node:path'
14
- import { existsSync, readdirSync, readFileSync, statSync, mkdirSync, writeFileSync, appendFileSync, realpathSync } from 'node:fs'
15
- import { fileURLToPath } from 'node:url'
16
- import os from 'node:os'
17
-
18
- // safeGit 收口至 src/git-helper.js:import 建本地词法绑定(本模块内部 L128/130/431 调用)+
19
- // re-export 供 run/ 层现有调用方继续从 shared.js 引用(pure re-export 不建本地绑定,会致内部 ReferenceError)。
20
- // unquoteGitPath 同理:parsePorcelainPath 内部消费 + re-export。
21
- import { safeGit, unquoteGitPath } from '../git-helper.js'
22
- import { createHash } from 'node:crypto'
23
- export { safeGit, unquoteGitPath }
24
-
25
- const __dirname = dirname(fileURLToPath(import.meta.url))
26
-
27
- // ── Wait State Constants ──(W6 Step3 从 run.js 搬入:prompt.js outputStep 与 run.js wait-detection 共用)
28
- // 正则匹配:只识别独立一行的标记,避免误伤文档正文引用
29
- export const WAIT_MARKER_RE = /^\s*\[(WAIT_FOR_USER|NEEDS_CONFIRM|NEEDS_DECISION)\]\s*$/m
30
-
31
- // ── did-you-mean(命令级 + flag 级 typo 建议,零依赖)──
32
- // 历史:agent 打错命令名/flag 名只报「未知」+整屏列表,要自己捞正确拼写。
33
- export function levenshtein(a, b) {
34
- const m = String(a).length, n = String(b).length
35
- if (!m) return n; if (!n) return m
36
- let prev = Array.from({ length: n + 1 }, (_, i) => i)
37
- for (let i = 1; i <= m; i++) {
38
- const cur = [i]
39
- for (let j = 1; j <= n; j++) {
40
- cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1))
41
- }
42
- prev = cur
43
- }
44
- return prev[n]
45
- }
46
- export function didYouMean(input, candidates) {
47
- if (!input) return null
48
- let best = null, bestD = Infinity
49
- for (const c of candidates) {
50
- const d = levenshtein(String(input).toLowerCase(), String(c).toLowerCase())
51
- if (d < bestD) { bestD = d; best = c }
52
- }
53
- return (best !== null && bestD <= Math.max(1, Math.floor(String(input).length / 2))) ? best : null
54
- }
55
-
56
- // ── 变更名路径穿越消毒(F6)──
57
- // change 名会被 join 进 .sillyspec/changes/<name>/ 当目录用。若含 ../ 或路径分隔符,
58
- // 会逃出 changes/ 写到任意位置(如 --change ../../etc/x 把 proposal.md 写到 changes 同级之外)。
59
- // 在 --change 解析边界统一消毒,比在每个 join 点守卫更集中。合法名:字母/数字/._-,禁分隔符与 ..
60
- export function assertSafeChangeName(name, label = '变更名') {
61
- if (name == null) return
62
- const s = String(name)
63
- if (s === '') throw new Error(`${label}不能为空`)
64
- // 含路径分隔符 或 父目录穿越段 → 拒绝(Windows 下 \\ 也算)
65
- if (/[\\/]/.test(s) || /(^|[/\\])\.\.(?=$|[/\\])/.test(s) || s === '..' || s.includes('..')) {
66
- throw new Error(`${label}「${s}」含路径分隔符或 ..,禁止路径穿越(变更名只能是 .sillyspec/changes/ 下的一个目录名,不能逃出)`)
67
- }
68
- if (!/^[\w.\-]+$/.test(s)) {
69
- throw new Error(`${label}「${s}」含非法字符(仅允许字母、数字、._-)`)
70
- }
71
- }
72
-
73
- import { buildExecuteSteps } from '../stages/execute.js'
74
- import { buildPlanSteps } from '../stages/plan.js'
75
- import { stageRegistry } from '../stages/index.js'
76
- import { parseRepo, parseRepoRegistry } from '../stages/plan-postcheck.js'
77
- import { MultiRepoContext } from './multi-repo-context.js'
78
-
79
- /**
80
- * 解析 prompt 中的 {{include: <name>}} 占位符:读包内 templates/prompts/<name>.md 注入。
81
- * 把 stage step prompt 里 self-contained 的大块抽到外部模板,CLI 端组装时注入——
82
- * agent 收到的仍是自包含 prompt 字符串,无需自己 Read。单次替换(不递归);
83
- * 模板缺失则保留占位符并 warn,便于发现配置错误。
84
- */
85
- export function resolvePromptIncludes(text) {
86
- return text.replace(/\{\{include:\s*([\w.-]+)\s*\}\}/g, (match, name) => {
87
- // shared.js 在 src/run/,templates/prompts 在仓库根 → 上两层
88
- const tplPath = join(__dirname, '..', '..', 'templates', 'prompts', `${name}.md`)
89
- if (!existsSync(tplPath)) {
90
- console.warn(`⚠️ prompt include 模板缺失: ${name} (期望: ${tplPath})`)
91
- return match
92
- }
93
- return readFileSync(tplPath, 'utf8')
94
- })
95
- }
96
-
97
- /**
98
- * 找 .sillyspec 祖先目录:用户指定 specDir 优先,否则从 cwd 向上找。
99
- * home 拒绝守卫:home 下的 .sillyspec 恒不命中——历史污染源(smoke 测试在 home 下临时目录
100
- * 跑 CLI,_ensureDB 读路径即建库,~/.sillyspec 长出一整套平行进度库后,任何 home 子目录
101
- * 跑命令都会向上撞它,污染自我延续)。撞 home 即停,回退 cwd/.sillyspec(子目录自建)。
102
- * @param {string} cwd
103
- * @param {object} [opts]
104
- * @param {string} [opts.specDir] - 用户指定的 specDir(通过 --spec-dir 或 --spec-root)
105
- * @returns {string} 规范目录的绝对路径
106
- */
107
- export function resolveSpecDir(cwd, opts = {}) {
108
- if (opts.specDir) return resolve(opts.specDir)
109
- const home = os.homedir()
110
- let dir = resolve(cwd)
111
- while (true) {
112
- // home 拒绝守卫:cwd 本身就在 home 下(含恰好在 home 跑命令)时,home 层不匹配 .sillyspec,
113
- // 继续向上只会离项目更远(home 的父目录不可能有真项目 .sillyspec),直接回退 cwd/.sillyspec。
114
- if (dir !== home) {
115
- const candidate = join(dir, '.sillyspec')
116
- if (existsSync(candidate)) return candidate
117
- }
118
- const parent = dirname(dir)
119
- if (parent === dir) break
120
- dir = parent
121
- }
122
- return join(resolve(cwd), '.sillyspec')
123
- }
124
-
125
- /**
126
- * 枚举 cwd 祖先链(含自身)上所有 .sillyspec 目录的绝对路径,上界 = git root。
127
- *
128
- * 返回顺序:从 cwd 最近开始向上到 git root(含两端命中项)。单实例项目任意子目录恒返回 [自身]。
129
- *
130
- * 上界 = git root(monorepo 天然边界)。必须有限上界:一路数到文件系统根会撞 home 等
131
- * 无关祖先的孤立 .sillyspec(home 下任何项目都被误报多实例)。非 git 仓库:不向上数,
132
- * 只看 cwd 自身(≤1,永不误报)。
133
- *
134
- * 被 countAncestorSpecDirs(漂移提醒 warn)与 locateQuickSessionGuard(quick 漂移 fail-fast
135
- * 守卫,坑 quick-cwd-drift-splits-specdir)共用 —— 单一真相源,避免两处各自重写祖先枚举漂移。
136
- */
137
- // 祖先链 ceiling(git 主仓根)按 cwd 进程级缓存:每条 stage 命令必经(countAncestorSpecDirs
138
- // 漂移提醒 + quick 漂移守卫两条路径),此前固定 2 次串行 git spawn(Windows 60-200ms)。
139
- // 只缓存"git root 已找到"的结果——非 git 仓库不缓存,防测试流程中途 git init 后读到陈旧 null。
140
- const _ancestorCeilingCache = new Map()
141
-
142
- function resolveAncestorCeiling(resolved) {
143
- if (_ancestorCeilingCache.has(resolved)) return _ancestorCeilingCache.get(resolved)
144
- // 一次 spawn 拿两值(rev-parse 按参数序输出,每值一行)
145
- const out = safeGit(resolved, ['rev-parse', '--show-toplevel', '--git-common-dir']).value
146
- let ceiling = null
147
- if (out) {
148
- const lines = out.split('\n')
149
- const topLevel = (lines[0] || '').trim()
150
- if (topLevel) ceiling = resolve(topLevel)
151
- const commonDir = (lines[1] || '').trim()
152
- if (commonDir) {
153
- const absCommonDir = resolve(resolved, commonDir)
154
- if (existsSync(absCommonDir) && statSync(absCommonDir).isDirectory()) {
155
- const mainRoot = dirname(absCommonDir)
156
- // 主仓根是 worktree 根的祖先时取它(更靠上);monorepo/单仓两者相等不替换,行为不变
157
- if (!ceiling || resolve(ceiling).startsWith(resolve(mainRoot) + sep)) ceiling = mainRoot
158
- }
159
- }
160
- }
161
- if (ceiling) _ancestorCeilingCache.set(resolved, ceiling)
162
- return ceiling
163
- }
164
-
165
- export function ancestorSpecDirs(cwd) {
166
- const resolved = resolve(cwd)
167
- // 上界 = git root。但 linked worktree 内 --show-toplevel 返回 worktree 根(非主仓根),
168
- // 祖先链到不了主仓 .sillyspec → 漂移提醒/quick 守卫全哑(坑 worktree-execute-spec-drift)。
169
- // 复刻 worktree.js _resolveMainRepoRoot:--git-common-dir 的 dirname 才是主仓根,取更靠上者作 ceiling。
170
- // (git 可能返回相对路径,须 resolve(cwd, commonDir) 绝对化,否则相对 process.cwd 误解析。)
171
- const ceiling = resolveAncestorCeiling(resolved)
172
- const dirs = []
173
- let dir = resolved
174
- while (true) {
175
- if (existsSync(join(dir, '.sillyspec'))) dirs.push(join(dir, '.sillyspec'))
176
- if (!ceiling || resolve(dir) === resolve(ceiling)) break
177
- const parent = dirname(dir)
178
- if (parent === dir) break
179
- dir = parent
180
- }
181
- return dirs
182
- }
183
-
184
- /**
185
- * 统计 cwd 祖先链上有多少个 .sillyspec 目录(= ancestorSpecDirs(cwd).length)。
186
- *
187
- * ≥2 个 = monorepo 多实例(子项目独立 .sillyspec + 根 .sillyspec 并存),resolveSpecDir 命中的
188
- * 「最近」实例未必是用户意图的项目(如 cd 进被独立 scan 的子项目跑测试后忘回根)→ 漂移风险。
189
- * 单实例项目在任意子目录工作恒返回 1,不误报。
190
- */
191
- export function countAncestorSpecDirs(cwd) {
192
- return ancestorSpecDirs(cwd).length
193
- }
194
-
195
- /**
196
- * 在 cwd 祖先链的各 specBase 中查找 quick 会话 guard.json(坑 quick-cwd-drift-splits-specdir)。
197
- *
198
- * sessionId(quick-<uuid8>)全局唯一,但 guard.json 按 specBase 分散落盘
199
- * (<specBase>/.runtime/quick-sessions/<sessionId>/guard.json)。cd 漂移到子项目后,当前 specBase
200
- * 下读不到本 session 的 guard,但祖先链别处的 specBase(创建 session 的根)仍有它 → 据此定位
201
- * session 真正归属,供 detectQuickSessionDrift 的 fail-fast 守卫判断。
202
- *
203
- * 遍历顺序 = ancestorSpecDirs(cwd 最近 → git root),返回第一个命中。
204
- *
205
- * @param {string} cwd
206
- * @param {string} sessionId - quick-<uuid8>
207
- * @returns {{ specBase: string, guard: object } | null}
208
- */
209
- export function locateQuickSessionGuard(cwd, sessionId) {
210
- if (!sessionId) return null
211
- for (const specBase of ancestorSpecDirs(cwd)) {
212
- const guardFile = join(specBase, '.runtime', 'quick-sessions', sessionId, 'guard.json')
213
- if (existsSync(guardFile)) {
214
- try {
215
- const guard = JSON.parse(readFileSync(guardFile, 'utf8'))
216
- return { specBase, guard }
217
- } catch {
218
- // guard.json 损坏:当作不存在,继续找下一个(不阻断主流程)
219
- }
220
- }
221
- }
222
- return null
223
- }
224
-
225
- /**
226
- * 检测 quick 会话是否跨 specDir 漂移(坑 quick-cwd-drift-splits-specdir)。
227
- *
228
- * quick 被 validateChangeExists 的 sessionId 豁免(quick-<8hex> 不在 changes/ 下),故 quick
229
- * 漂移除 countAncestorSpecDirs 的 warn 外无硬守卫 → 无声分裂(progress/artifact/QUICKLOG 落
230
- * 子项目、根 session 停滞)。本函数补这个口:
231
- * - 当前 specBase 已有本 session guard → null(同一 specDir,无漂移)
232
- * - 当前 specBase 没有,但祖先链别处有同 sessionId guard → 判漂移,返回引导信息供调用方 fail-fast
233
- * - 别处也没有 → null(真·新会话首次启动,guard 尚未建,放行 —— 不误伤子项目主动启新 quick)
234
- *
235
- * 风格仿 validateChangeExists:null = 通过,对象 = 失败(含 message)。
236
- *
237
- * @param {string} cwd
238
- * @param {string} currentSpecBase - 当前命中的 specBase
239
- * @param {string} sessionId - quick-<uuid8>
240
- * @returns {{ realSpecBase: string, message: string } | null}
241
- */
242
- export function detectQuickSessionDrift(cwd, currentSpecBase, sessionId) {
243
- if (!sessionId || !currentSpecBase) return null
244
- // 当前 specBase 已有本 session guard → 同一 specDir,无漂移
245
- const currentGuard = join(currentSpecBase, '.runtime', 'quick-sessions', sessionId, 'guard.json')
246
- if (existsSync(currentGuard)) return null
247
- // 当前没有 → 看祖先链别处有没有同 sessionId 的 guard
248
- const located = locateQuickSessionGuard(cwd, sessionId)
249
- if (!located) return null // 别处也没有 = 真·新会话首次启动,放行
250
- return {
251
- realSpecBase: located.specBase,
252
- message: `quick 会话 "${sessionId}" 创建于 ${located.specBase},当前 cwd 解析到 ${currentSpecBase}(跨 specDir 漂移)。` +
253
- `继续会把 progress/artifact/QUICKLOG 写到错误的 spec,与原会话分裂。` +
254
- `排查:① cd 回 ${dirname(located.specBase)}(原 spec 所属项目根)再跑;② 或显式 --spec-dir ${located.specBase} 指定原 spec。`,
255
- }
256
- }
257
-
258
- /**
259
- * 检测 specBase 是否命中 worktree 内 checkout 出来的 .sillyspec 副本(坑 worktree-execute-spec-drift)。
260
- *
261
- * worktree 根 = <mainRepo>/.sillyspec/.runtime/worktrees/<changeName>/(worktree.js WORKTREES_REL)。
262
- * worktree 是主仓完整 checkout,若 .sillyspec/changes/ 被跟踪 → 副本里 change 目录真实存在,
263
- * validateChangeExists 被骗放行 → 进度/产出写进副本,与主仓 .sillyspec 分裂(副本随工作树清理丢失)。
264
- *
265
- * 判据:specBase 路径含 `.sillyspec/.runtime/worktrees/<seg>/.sillyspec`。主仓 specBase=<mainRepo>/.sillyspec
266
- * 无此段 → null,零误伤。返回 null=通过;对象=漂移(含 mainSpecBase/changeName/message),风格仿
267
- * validateChangeExists。覆盖 plan/execute/verify/archive(同 Set)——都要求 change 已存在、都会被副本骗过。
268
- * 平台模式/--spec-dir 已明确指定,由调用方跳过。
269
- */
270
- export function detectWorktreeSpecDrift(specBase) {
271
- if (!specBase) return null
272
- const seg = resolve(specBase).split(sep)
273
- // specBase 恒以 .sillyspec 结尾(command.js specBase=join(cwd,'.sillyspec'))。worktree 副本形如
274
- // <mainRepo>/.sillyspec/.runtime/worktrees/<change>/.sillyspec —— 尾段也须是 .sillyspec,
275
- // 否则 worktree 根目录本身(<.../worktrees/<change>)会被误判(它不是 spec,不会作 specBase 传入)。
276
- if (seg[seg.length - 1] !== '.sillyspec') return null
277
- for (let i = 0; i + 3 < seg.length; i++) {
278
- if (seg[i] === '.sillyspec' && seg[i + 1] === '.runtime' && seg[i + 2] === 'worktrees') {
279
- const changeName = seg[i + 3]
280
- const mainSpec = seg.slice(0, i + 1).join(sep) // <mainRepo>/.sillyspec
281
- return {
282
- changeName,
283
- mainSpecBase: mainSpec,
284
- message: `当前 spec 命中 worktree 副本(${specBase})——这是 ${changeName} 隔离工作树内 checkout 出来的 .sillyspec,不是主仓 spec。\n` +
285
- ` 在此跑 plan/execute/verify/archive 会把进度与产出写到副本,与主仓 .sillyspec 分裂(副本随工作树清理而丢失)。\n` +
286
- ` 排查:① cd 回 ${dirname(mainSpec)}(主仓根)再跑;② 或 --spec-dir ${mainSpec} 显式指定主仓 spec。`,
287
- }
288
- }
289
- }
290
- return null
291
- }
292
-
293
- /**
294
- * 统一解析 .runtime 根目录(坑 execute-runs-isolation)。
295
- *
296
- * 优先级:平台模式 runtimeRoot > drift 锚点 specDriftAnchor > 本地 specBase/.runtime。
297
- * specDriftAnchor 仅在此处消费,不参与平台 sentinel(specRoot||runtimeRoot)判定,
298
- * 避免误跳 triggerSync(:286)/ checkApproval(:313)/ 平台渲染分支(D-02)。
299
- *
300
- * 历史:drift 守卫(command.js)命中时只重写本地 specBase/specRoot/specDir/pm(progress 落主仓),
301
- * 但漏设 platformOpts 字段——下游 15 处 runtimeRoot 解析从 cwd(仍 worktree)重算 → execute-runs /
302
- * stage-reviews 落 worktree,被 cleanup 整目录删。本函数 + specDriftAnchor 锚点堵此源头。
303
- *
304
- * @param {object} [platformOpts] - { runtimeRoot?, specDriftAnchor?, ... }(可 null/undefined)
305
- * @param {string} localSpecBase - 本地 specBase(cwd/.sillyspec),兜底落点
306
- * @returns {string} .runtime 根目录绝对路径
307
- */
308
- export function resolveRuntimeRoot(platformOpts, localSpecBase) {
309
- if (platformOpts?.runtimeRoot) return platformOpts.runtimeRoot
310
- if (platformOpts?.specDriftAnchor) return join(platformOpts.specDriftAnchor, '.runtime')
311
- return join(localSpecBase, '.runtime')
312
- }
313
-
314
- /**
315
- * quick 会话目录(.runtime/quick-sessions)的单一解析入口(multi-agent-review Q4)。
316
- *
317
- * 历史 bug:stage.js 写 guard 用 `specBase/.runtime/quick-sessions/`,收尾 handleQuickStageCompletion
318
- * 读/清理用 `resolveRuntimeRoot`(runtimeRoot 被设时返回 runtimeRoot)。两者在平台模式(runtimeRoot 与
319
- * specBase/.runtime 不同)下分裂——guard 写到 specBase/.runtime、收尾从 runtimeRoot 读不到 → guard=null
320
- * brownfield 分支整体跳过边界审计 + 兜底重分配 qlId + session 目录清错位置。
321
- *
322
- * 收敛到此函数后,写/读/清理三处共用同一解析(基于 resolveRuntimeRoot),任何平台/漂移模式都对齐。
323
- *
324
- * @param {object} [platformOpts] - { runtimeRoot?, specDriftAnchor?, ... }(可 null/undefined)
325
- * @param {string} localSpecBase - 本地 specBase(cwd/.sillyspec),兜底落点
326
- * @returns {string} quick-sessions 目录绝对路径
327
- */
328
- export function resolveQuickSessionsDir(platformOpts, localSpecBase) {
329
- return join(resolveRuntimeRoot(platformOpts, localSpecBase), 'quick-sessions')
330
- }
331
-
332
- // 他者会话声明豁免的僵尸阈值:超龄会话的声明不再作为豁免依据。与 doctor 幽灵清理
333
- // GHOST_EMPTY_DIR_STALE_MS 同口径(7 天)——正常并发会话间隔在分钟/小时级,7 天未收尾的
334
- // 会话按僵尸处理,防崩溃残留的 guard 永久「认领」文件侵蚀危险门。
335
- const FOREIGN_SESSION_STALE_MS = 7 * 24 * 60 * 60 * 1000
336
-
337
- /**
338
- * 枚举其他 active quick 会话的显式文件声明(坑 foreign-session-declared-false-block)。
339
- *
340
- * 多 agent 并发时,并行 quick 会话在**本会话启动后**改的文件不在本会话 baseline →
341
- * auditQuickCompletion 把它算进本会话窗口 → 命中危险清单(src/run/、package.json 等)或
342
- * .sillyspec/ 判定即 blocked,只能 --force-baseline 无差别逃生。豁免口径 = 他者会话的
343
- * **显式声明**(guard.allowedFiles,--files 传入)——他者的 baselineFiles 是「启动时已脏」
344
- * 快照而非所有权声明,不作豁免依据(否则任何预存脏文件都能被洗白)。
345
- *
346
- * fail-open:目录不存在/损坏 guard.json/超龄僵尸/任何异常 → 跳过或整体返回 [],
347
- * 采集失败回到无豁免现状(不放大豁免面)。
348
- *
349
- * @param {object} [platformOpts] 平台选项(resolveQuickSessionsDir 同参)
350
- * @param {string} localSpecBase 本地 specBase(resolveQuickSessionsDir 同参)
351
- * @param {string} currentSessionId 当前会话 sessionId(quick-<hex8>),枚举时排除
352
- * @param {number} [nowMs] 当前时间戳(可注入,测试用)
353
- * @returns {Array<{sessionId: string, files: string[]}>} 其他 active 会话的声明清单
354
- */
355
- export function collectOtherQuickSessionDeclarations(platformOpts, localSpecBase, currentSessionId, nowMs = Date.now()) {
356
- const out = []
357
- try {
358
- const sessionsDir = resolveQuickSessionsDir(platformOpts, localSpecBase)
359
- let sessionDirs = []
360
- try {
361
- sessionDirs = readdirSync(sessionsDir, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name)
362
- } catch { return out } // 目录不存在/不可读 → 无他者会话
363
- for (const sessionName of sessionDirs) {
364
- if (sessionName === currentSessionId) continue
365
- const guardFile = join(sessionsDir, sessionName, 'guard.json')
366
- let guard = null
367
- try { guard = JSON.parse(readFileSync(guardFile, 'utf8')) } catch { continue } // 损坏/缺失跳过
368
- // 僵尸防御:超龄会话(崩溃残留,--done/--cancel 都不会再走)的声明不再认领文件
369
- if (guard.startedAt) {
370
- const startedAtMs = Date.parse(guard.startedAt)
371
- if (Number.isFinite(startedAtMs) && nowMs - startedAtMs > FOREIGN_SESSION_STALE_MS) continue
372
- }
373
- const files = (Array.isArray(guard.allowedFiles) ? guard.allowedFiles : []).filter(f => typeof f === 'string' && f)
374
- if (files.length === 0) continue
375
- out.push({ sessionId: guard.sessionId || sessionName, files })
376
- }
377
- } catch { /* fail-open:整体异常返回已采集部分 */ }
378
- return out
379
- }
380
-
381
- /**
382
- * 平台指针三写(单一数据源,runCommand scan 与 cmdInit 平台模式共用)。
383
- *
384
- * 写三处:
385
- * 1. <specRoot>/.runtime/platform-scan.json — 主持久化文件(后续 run/--done 恢复)
386
- * 2. <cwd>/.sillyspec-platform.json — 轻量恢复指针(供裸调——不带 --spec-root——找回 specDir)
387
- * 3. <cwd>/.sillyspec-platform-managed — 平台接管声明(无过期,独立于指针生命周期;
388
- * 指针被 cleanup/STALE 清理后它仍在,resolvePlatformSpecDir/runCommand 恢复链靠它
389
- * fail-closed 防静默落本地库。唯一删除路径 = platform disconnect)
390
- *
391
- * status 字段语义(POINTER_STATUS):
392
- * - init 落盘时传 status: 'active'(已接入未 scan,24h STALE 清理不作用于它)
393
- * - scan 完成时 complete-handlers 升级为 'scan_completed'
394
- * - 不传 status 则省略(与 runCommand 历史行为一致)
395
- *
396
- * 写失败静默(不阻断主流程),返回 true/false 供调用方决定是否提示。
397
- *
398
- * @param {string} cwd - 恢复指针落盘目录(= 调用方命令的 cwd,通常为项目根)
399
- * @param {object} platformOpts - { specRoot, runtimeRoot?, workspaceId?, scanRunId? }
400
- * @param {object} [extra] - 追加字段(如 { status: 'active' },只进指针/主文件不进声明)
401
- * @returns {boolean} 是否全部写入成功
402
- */
403
- export const PLATFORM_MANAGED_FILENAME = '.sillyspec-platform-managed'
404
-
405
- export function writePlatformPointer(cwd, platformOpts, extra = {}) {
406
- if (!platformOpts || (!platformOpts.specRoot && !platformOpts.runtimeRoot)) return false
407
- // 自指写入拦截(FR-4,变更 2026-08-23-repo-native-spec-backfill):specRoot 经 realpath
408
- // 解析回本地 .sillyspec(repo-native junction 回环)时拒绝三写(主文件/指针/声明全不落盘)。
409
- // 单点收口同时覆盖 runCommand 与 cmdInit(writeInitPlatformPointer) 两调用方——旧模板
410
- // scan flag / init 平台模式显式传自指 specRoot 也不再重新投毒。runtimeRoot-only 组合
411
- // 无 specRoot 可判(isSelfReferentialSpecRoot 对 null 恒 false),原语义不变。
412
- if (isSelfReferentialSpecRoot(cwd, platformOpts.specRoot)) {
413
- console.warn(`⚠️ 检测到自指平台指针(repo-native junction 回环,specRoot 指回本地 .sillyspec),已跳过指针写入并按本地模式运行: ${platformOpts.specRoot}`)
414
- return false
415
- }
416
- // HUB-05:合并保留既有生命周期字段。scan 完成时指针被写入 status/completedAt/scanStatus
417
- //(complete-handlers),但下一次任何平台模式 run(含只读 --status)都会重写指针——
418
- // 恢复链只回填 specRoot 等四字段,不保留 status → 指针永远回 active、isPointerStale
419
- // 恒 false、`platform pointer --cleanup` 的 STALE 分支不可达。extra 显式传值仍可覆盖。
420
- let preserved = {}
421
- try {
422
- const existing = JSON.parse(readFileSync(join(cwd, '.sillyspec-platform.json'), 'utf8'))
423
- if (existing && typeof existing === 'object') {
424
- for (const k of ['status', 'completedAt', 'scanStatus']) {
425
- if (existing[k] !== undefined && extra[k] === undefined) preserved[k] = existing[k]
426
- }
427
- }
428
- } catch { /* 无既有指针/损坏 → 全新写入 */ }
429
- const payload = {
430
- specRoot: platformOpts.specRoot || null,
431
- runtimeRoot: platformOpts.runtimeRoot || null,
432
- workspaceId: platformOpts.workspaceId || null,
433
- scanRunId: platformOpts.scanRunId || null,
434
- savedAt: new Date().toISOString(),
435
- ...preserved,
436
- ...extra,
437
- }
438
- // 声明文件字段集独立于指针 payload(D-E@v2 四字段:无 status/savedAt/scanRunId——
439
- // 声明语义是"项目归平台管"这一持久事实,非 scan 会话状态)
440
- const declaration = {
441
- managed: true,
442
- specRoot: platformOpts.specRoot || null,
443
- workspaceId: platformOpts.workspaceId || null,
444
- declaredAt: new Date().toISOString(),
445
- }
446
- try {
447
- // platform-scan.json 只在 specRoot 存在时可写(坑 pointer-runtime-root-only-null-join):
448
- // runtimeRoot-only 平台组合(command.js 明确允许)下 specRoot 为 null,此前 join(null,…)
449
- // 抛 ERR_INVALID_ARG_TYPE 落入总 catch → 指针与接管声明也一并静默未写,双入口 fail-closed
450
- // 对该组合整体失效。分步写:specRoot 缺失只跳过 platform-scan.json,指针/声明照写。
451
- if (platformOpts.specRoot) {
452
- mkdirSync(join(platformOpts.specRoot, '.runtime'), { recursive: true })
453
- writeFileSync(join(platformOpts.specRoot, '.runtime', 'platform-scan.json'), JSON.stringify(payload, null, 2) + '\n')
454
- }
455
- writeFileSync(join(cwd, '.sillyspec-platform.json'), JSON.stringify(payload, null, 2) + '\n')
456
- writeFileSync(join(cwd, PLATFORM_MANAGED_FILENAME), JSON.stringify(declaration, null, 2) + '\n')
457
- return true
458
- } catch {
459
- return false
460
- }
461
- }
462
-
463
- /**
464
- * 读平台接管声明(读侧宽容:任何异常情况返回 null = 视同无声明,不抛错)。
465
- * 供 resolvePlatformSpecDir / runCommand 恢复链 / doctor 诊断三处消费。
466
- *
467
- * @param {string} cwd - 项目根(声明查找目录)
468
- * @returns {{managed:true, specRoot, workspaceId, declaredAt}|null}
469
- * 文件不存在 / JSON 损坏 / managed 非 true → null
470
- */
471
- export function checkPlatformManaged(cwd) {
472
- const p = join(resolve(cwd), PLATFORM_MANAGED_FILENAME)
473
- if (!existsSync(p)) return null
474
- try {
475
- const decl = JSON.parse(readFileSync(p, 'utf8'))
476
- if (!decl || decl.managed !== true) return null
477
- return {
478
- managed: true,
479
- specRoot: decl.specRoot || null,
480
- workspaceId: decl.workspaceId || null,
481
- declaredAt: decl.declaredAt || null,
482
- }
483
- } catch {
484
- return null
485
- }
486
- }
487
-
488
- /**
489
- * 自指 specRoot 判定(repo-native junction 回环检测,变更 2026-08-23-repo-native-spec-backfill)。
490
- *
491
- * daemon repo-native 工作区把缓存目录(--spec-root 入参,~/.sillyhub/daemon/specs/{ws})以
492
- * junction/symlink 指回源项目 <cwd>/.sillyspec——该 specRoot 经 realpath 解析后与本地
493
- * .sillyspec 同物理目录,属"自指回环":不应让 CLI 进入平台模式(内置 sync / auto-pull
494
- * 按本地模式语义运行,断链修复见 design.md Phase 2)。
495
- *
496
- * 双方 fs.realpathSync(native,junction/symlink 跨平台穿透)后严格相等 → true;
497
- * specRoot 空 / 任一路径不存在 / realpath 抛错 → false(按外部目录处理,保守不干预)。
498
- * 约束:cwd 必须为项目根(与指针查找 join(cwd,'.sillyspec-platform.json') 同基准)。
499
- *
500
- * @param {string} cwd - 项目根
501
- * @param {string|null} [specRoot] - 平台 specRoot(可 null/undefined/空串)
502
- * @returns {boolean} 是否自指回环
503
- */
504
- export function isSelfReferentialSpecRoot(cwd, specRoot) {
505
- if (!specRoot || typeof specRoot !== 'string') return false
506
- try {
507
- return realpathSync(specRoot) === realpathSync(join(cwd, '.sillyspec'))
508
- } catch {
509
- return false
510
- }
511
- }
512
-
513
- /**
514
- * 平台模式判定单一数据源(自指免疫,变更 2026-08-23-repo-native-spec-backfill)。
515
- *
516
- * 语义:(specRoot || runtimeRoot) 存在且非自指 → 平台模式;自指回环(repo-native
517
- * junction)按本地模式处理。本模块内平台模式门禁统一经本函数,裸表达式仅此一处
518
- * (grep 验证:triggerSync/triggerPull/triggerPullActiveChange/checkApproval 四处收敛)。
519
- * runtimeRoot 落在 specRoot 内,自指判定以 specRoot 为准即可覆盖;runtimeRoot-only
520
- * 组合无 specRoot 可判,不触发自指豁免(保持平台模式)。
521
- *
522
- * @param {object} [platformOpts] - { specRoot?, runtimeRoot?, ... }(可 null/undefined)
523
- * @param {string} cwd - 项目根(isSelfReferentialSpecRoot 同基准)
524
- * @returns {boolean}
525
- */
526
- export function isPlatformMode(platformOpts, cwd) {
527
- return Boolean((platformOpts?.specRoot || platformOpts?.runtimeRoot) && !isSelfReferentialSpecRoot(cwd, platformOpts?.specRoot))
528
- }
529
-
530
- /**
531
- * 统一查找变更目录(与 progress.js 的变更检测逻辑一致)。
532
- */
533
- export function resolveChangeDir(cwd, progress, specDir = null) {
534
- const changesDir = join(specDir || resolveSpecDir(cwd), 'changes')
535
- if (!existsSync(changesDir)) return null
536
-
537
- // 1. 优先用 currentChange
538
- if (progress.currentChange) {
539
- const target = join(changesDir, progress.currentChange)
540
- if (existsSync(target)) return target
541
- }
542
-
543
- // 2. fallback:唯一非 archive 目录
544
- const entries = readdirSync(changesDir, { withFileTypes: true })
545
- .filter(e => e.isDirectory() && e.name !== 'archive')
546
- if (entries.length === 1) return join(changesDir, entries[0].name)
547
-
548
- return null
549
- }
550
-
551
- /**
552
- * 触发 sync(平台模式走自己的链路,跳过;否则 await import sync.js)。
553
- */
554
- // sync 总超时熔断:sync.js 是 best-effort 后台回传(每请求已有 10s 超时),但 sync() 可能串行多次
555
- // fetchJson 累积等待、阻塞 --done。给 8s 总超时,超时放弃(best-effort,失败不影响正确性,下次 --done 重试)。
556
- // 历史痛点:--done 在 sync 慢时体感 hang,用户被迫用外部 timeout 兜底。
557
- // HUB-09:熔断超时时必须 abort 底层在飞请求(opts.signal 一路传到 fetch)——否则熔断后请求
558
- // 仍在跑,平台可能已接受推送而客户端当作超时放弃(spec 树推送无 base_ts 自愈兜底)。
559
- const SYNC_TOTAL_TIMEOUT_MS = 8_000
560
-
561
- /**
562
- * 熔断 race + 确定性取消:超时触发 controller.abort() 并 resolve,在飞 fetch 收到
563
- * AbortError 后自然失败(各调用方 catch 返回降级值,进程不挂起)。
564
- * @param {() => Promise} op 接收 { signal } 的异步操作
565
- * @param {number} timeoutMs 熔断时长(测试可缩短)
566
- */
567
- async function raceWithAbort(op, timeoutMs = SYNC_TOTAL_TIMEOUT_MS) {
568
- const controller = new AbortController()
569
- let timer
570
- try {
571
- await Promise.race([
572
- op({ signal: controller.signal }),
573
- new Promise((resolve) => { timer = setTimeout(() => { controller.abort(); resolve(null) }, timeoutMs) }),
574
- ])
575
- } finally {
576
- clearTimeout(timer)
577
- }
578
- }
579
-
580
- // quick 会话 ID 形态(quick-<hex8>)。与 run/command.js QUICK_SID_RE、progress.js
581
- // initChange 的跳过实体目录判断同源;shared.js 不反向 import command.js(重模块),
582
- // 局部复制正则保持轻载——改形态时三处同改(prompt.js 经本导出消费,勿再复制一份)。
583
- export const QUICK_SID_RE = /^quick-[0-9a-f]{8}$/
584
-
585
- export async function triggerSync(cwd, changeName, platformOpts = {}, opts = {}) {
586
- // 平台模式(SillyHub)走自己的回传链路,不走 CLI 内置 sync;自指回环(repo-native junction)按本地模式处理
587
- if (isPlatformMode(platformOpts, cwd)) return
588
- try {
589
- // ql-20260818-011:quick 会话按设计无实体变更目录(progress.js initChange 同款
590
- // 跳过建目录),progress/四件套上行对它是孤儿数据;但 spec 树增量(QUICKLOG/
591
- // 模块文档的上行通道)以服务器清单为锚,与变更目录无关——降级只推 spec 树。
592
- if (changeName && QUICK_SID_RE.test(changeName) && !existsSync(join(cwd, '.sillyspec', 'changes', changeName))) {
593
- // shared.js 在 src/run/,sync.js 在 src/ → 退一层
594
- const syncMod = await import('../sync.js')
595
- await raceWithAbort((sig) => syncMod.syncSpecTreeOnly(changeName, cwd, sig), opts.timeoutMs)
596
- return
597
- }
598
- // 目录缺失的非 quick 变更不再静默 return(archive-final-state-sync):归档把
599
- // changes/<name>/ 移到 changes/archive/<name>/ 并注销 DB 行后,第 4/5 步收尾的
600
- // triggerSync 仍会触发——DB 里的终态(steps 完成态 + status='archived')与文件树
601
- // 移动必须推平台,否则平台进度永远停在移动前的最后一步。sync() 内部对目录缺失
602
- // 本就是 warn-and-continue(serializeForSync 从 DB 读不依赖目录);真实拼错名时
603
- // 无 DB 行,sync() 在发出任何 HTTP 前即 return,仅多一行 warn(未连接平台则完全静默)。
604
- // shared.js 在 src/run/,sync.js 在 src/ → 退一层
605
- const syncMod = await import('../sync.js')
606
- await raceWithAbort((sig) => syncMod.sync(changeName, cwd, sig), opts.timeoutMs)
607
- } catch (e) {
608
- // sync.js 不存在或同步失败,静默跳过
609
- console.warn('⚠️ 同步失败:', e.message)
610
- }
611
- }
612
-
613
- /**
614
- * 自动 pull 节流(体检 PERF-02):triggerPull/triggerPullActiveChange 在每条 stage 命令
615
- * 启动时注入,agent 命令往往是秒级连发——每次都发 HTTP GET(daemon 挂/慢时单命令最多
616
- * 阻塞 8s)。跨进程 marker 节流:10s 内已有自动 pull 则跳过(手动 `platform pull` 不走
617
- * 此门,语义不变)。错过窗口的平台更新由下一条 >10s 的命令或 push 409 自愈兜底。
618
- */
619
- const AUTO_PULL_THROTTLE_MS = 10_000
620
-
621
- // 自动 pull 专属熔断(2026-08-21 性能审查 PERF-04):自动注入点(stage 命令分发前 / approve 前)
622
- // 在打印任何输出前 await,daemon 慢/挂时每 10s 窗口首条命令硬等上限即体感 hang——降为 2s。
623
- // 手动 `platform pull` 不经此路径(用户显式发起,等待 8s 合理)。超时语义与 8s 版一致:
624
- // abort 在飞请求(HUB-09),错过窗口的平台更新由下一条 >10s 命令或 push 409 自愈兜底。
625
- const AUTO_PULL_TIMEOUT_MS = 2_000
626
-
627
- function _autoPullThrottlePath(cwd) {
628
- return join(cwd, '.sillyspec', '.runtime', 'auto-pull-throttle.json')
629
- }
630
-
631
- function _autoPullRecently(cwd) {
632
- try {
633
- const t = JSON.parse(readFileSync(_autoPullThrottlePath(cwd), 'utf8'))
634
- return typeof t.at === 'number' && Date.now() - t.at < AUTO_PULL_THROTTLE_MS
635
- } catch {
636
- return false
637
- }
638
- }
639
-
640
- function _stampAutoPull(cwd) {
641
- try {
642
- mkdirSync(dirname(_autoPullThrottlePath(cwd)), { recursive: true })
643
- writeFileSync(_autoPullThrottlePath(cwd), JSON.stringify({ at: Date.now() }) + '\n', 'utf8')
644
- } catch { /* best-effort:节流失效仅退化为逐次 pull */ }
645
- }
646
-
647
- /**
648
- * 触发 pull(下行同步,task-10 / D-009 / FR-04 / FR-06)。
649
- * 熔断走 AUTO_PULL_TIMEOUT_MS(2s,见常量注释)与 Best Effort 语义;未连接平台静默跳过(与现状一致)。
650
- * 注入时机:stage 命令启动(顶层别名 + case 'run',ql-20260818-008 补齐后者)+ 关键决策点
651
- * (approve 前)+ 手动 platform pull。不在每步 pull(避免高频写入与网络压力),仅低频边界点。
652
- * 自动注入走 skipIfLocalDirty 保守守卫:本地有未同步改动时 pull 内部跳过 import,
653
- * 防「本地领先」被平台旧快照覆盖(手动 platform pull 不受影响)。
654
- * @param {string} cwd
655
- * @param {string} changeName - 当前活跃变更(多变更时传 null 跳过,避免误拉)
656
- * @param {object} [platformOpts] - 平台模式 opts(specRoot/runtimeRoot 存在则跳过,走平台自有链路)
657
- */
658
- export async function triggerPull(cwd, changeName, platformOpts = {}, opts = {}) {
659
- // 平台模式(SillyHub)走自己的链路,跳过;自指回环(repo-native junction)按本地模式处理
660
- if (isPlatformMode(platformOpts, cwd)) return
661
- try {
662
- const syncMod = await import('../sync.js')
663
- const sm = new syncMod.SyncManager(cwd)
664
- // 未连接平台静默跳过(本地独立用户合法状态,不噪音)——节流 stamp 必须在此之后:
665
- // 否则未连接的项目每次 run 都写 .sillyspec/.runtime/ 标记(凭空造目录)
666
- if (!sm._getPlatform()) return
667
- if (_autoPullRecently(cwd)) return
668
- _stampAutoPull(cwd)
669
- await raceWithAbort((sig) => sm.pull(changeName, { skipIfLocalDirty: true, signal: sig.signal }), opts.timeoutMs ?? AUTO_PULL_TIMEOUT_MS)
670
- } catch (e) {
671
- // pull 失败静默跳过(Best Effort,失败不影响正确性)
672
- console.warn('⚠️ 拉取失败:', e.message)
673
- }
674
- }
675
-
676
- /**
677
- * triggerPull 的便捷封装:未显式传 changeName 时自动推导单活跃变更(task-10)。
678
- * 多活跃 / 无活跃变更时跳过(无法确定目标,避免误拉);其余语义同 triggerPull。
679
- * 供 index.js 在 stage 命令(run/--done/archive)与 approve 决策点注入一行调用。
680
- */
681
- export async function triggerPullActiveChange(cwd, platformOpts = {}) {
682
- // 平台模式走自己的链路,跳过;自指回环(repo-native junction)按本地模式处理
683
- if (isPlatformMode(platformOpts, cwd)) return
684
- // 先检查是否连接平台:未连接直接 return,避免 _ensureDB 在无 local.yaml 的 cwd 创建空 DB 污染
685
- let sm = null
686
- try {
687
- const syncMod = await import('../sync.js')
688
- sm = new syncMod.SyncManager(cwd)
689
- if (!sm._getPlatform()) return
690
- } catch {
691
- return
692
- }
693
- // PERF-02 节流(连接确认后才 stamp——未连接项目不得凭空写 .sillyspec/.runtime/):
694
- // 与 triggerPull 共用同一 marker(本函数与它在同一命令启动链上互斥出现)
695
- if (_autoPullRecently(cwd)) return
696
- _stampAutoPull(cwd)
697
- let cn = null
698
- try {
699
- const { ProgressManager } = await import('../progress.js')
700
- const pm = new ProgressManager({})
701
- const changes = pm.listChanges(cwd)
702
- if (changes.length === 1) cn = changes[0]
703
- } catch {
704
- // progress 不可达则跳过(Best Effort)
705
- }
706
- if (!cn) return
707
- // 已确认连接 + 单活跃变更,调 pull(自动注入 2s 熔断 + abort(HUB-09);skipIfLocalDirty 保守守卫
708
- // 同 triggerPull——本地脏时跳过 import,防平台旧快照覆盖本地领先进度,ql-20260818-008)
709
- try {
710
- await raceWithAbort((sig) => sm.pull(cn, { skipIfLocalDirty: true, signal: sig.signal }), AUTO_PULL_TIMEOUT_MS)
711
- } catch (e) {
712
- console.warn('⚠️ 拉取失败:', e.message)
713
- }
714
- }
715
-
716
- /**
717
- * 审批状态 unknown(体检 HUB-07)的统一处置:醒目多行警告 + 落 .runtime/approval-unknown.log 留痕。
718
- *
719
- * 语义边界:unknown = 已连接平台但 404/断网/超时/非 JSON——**不是审批通过**。放行是
720
- * fail-open 的既定取舍(网络故障不应硬阻断每一条 execute),但静默放行会让团队审批
721
- * 形同虚设且无迹可查;至少要(a)让操作者当场看见(b)留下可审计记录。
722
- * 留痕选 .runtime 日志而非 QUICKLOG:QUICKLOG 是 quick 会话的任务记录,run 流程的
723
- * 审批事件写进去会污染 quick 语义与边界审计。
724
- * @param {string} cwd
725
- * @param {string} changeName
726
- * @param {string} reason checkApproval 返回的 reason
727
- */
728
- export function warnApprovalUnknown(cwd, changeName, reason) {
729
- console.warn('')
730
- console.warn('⚠️⚠️⚠️══════════════════════════════════════════════')
731
- console.warn(`⚠️ 审批状态未知:变更「${changeName}」无法核实审批(${reason || '请求失败'})`)
732
- console.warn('⚠️ 本次 execute 按 fail-open 放行——这不是审批通过;平台恢复后请到平台复核审批记录')
733
- console.warn('⚠️ 排查:平台服务是否可达(sillyspec platform status)/ 网络代理;确认无需审批可 --skip-approval 显式跳过')
734
- console.warn('⚠️ 本次放行已记录:.sillyspec/.runtime/approval-unknown.log')
735
- console.warn('⚠️⚠️══════════════════════════════════════════════')
736
- try {
737
- const logDir = join(cwd, '.sillyspec', '.runtime')
738
- mkdirSync(logDir, { recursive: true })
739
- appendFileSync(join(logDir, 'approval-unknown.log'),
740
- `${new Date().toISOString()} | change=${changeName} | reason=${reason || 'unknown'}\n`, 'utf8')
741
- } catch { /* 留痕失败不阻断流程(警告横幅已输出) */ }
742
- }
743
-
744
- /**
745
- * 审批检查:execute 阶段启动前检查(W6 Step8a 从 run.js 搬入,runStage + runAutoMode 共用)。
746
- * 平台模式走自己的链路,跳过;否则 await import sync.js。
747
- * @returns {{ status: string, reason?: string } | null}
748
- */export async function checkApproval(cwd, changeName, platformOpts = {}) {
749
- // 平台模式不需要 CLI 内置审批检查;自指回环(repo-native junction)按本地模式处理
750
- if (isPlatformMode(platformOpts, cwd)) return null
751
- try {
752
- // shared.js 在 src/run/,sync.js 在 src/ → 退一层
753
- const syncMod = await import('../sync.js')
754
- return await syncMod.checkApproval(changeName, cwd)
755
- } catch (e) {
756
- return null
757
- }
758
- }
759
-
760
- /**
761
- * 解析 git status --porcelain 单行 → 文件路径(去引号/处理 rename/归一化)。
762
- * 注意:line.slice(3) —— porcelain 行前 2 字符是状态码 + 1 空格,路径从 index 3 开始。
763
- */
764
- export function parsePorcelainPath(line) {
765
- if (!line) return ''
766
- let path = line.slice(3).trim()
767
- if (path.length >= 2 && path.startsWith('"') && path.endsWith('"')) {
768
- // unquoteGitPath:\\ \" \n \t 与 \NNN 八进制字节聚合 UTF-8 解码——原 \\(.) 逐字符
769
- // 解引会把 "\346\226\207.md" 拆成 "346226207.md"。git-helper 已统一 core.quotepath=false
770
- // (非 ASCII 路径裸输出),此处兜底仍会被引号转义的路径(含控制字符等)。
771
- path = unquoteGitPath(path.slice(1, -1))
772
- }
773
- const arrow = path.indexOf(' -> ')
774
- if (arrow !== -1) path = path.slice(arrow + 4)
775
- return path.replace(/\\/g, '/')
776
- }
777
-
778
- /**
779
- * quick 自身写入的 .sillyspec/ 元数据判定(auditQuickCompletion 审计 与 QUICKLOG「文件:」行回填
780
- * 单源)。回填文件行时复用:review.changedFiles 含这些元数据时过滤掉,只留真实业务文件。
781
- *
782
- * 归类口径:
783
- * - quicklog/.runtime/modules/_module-map/knowledge-uncategorized 等 quick 自身产物 → 元数据
784
- * - .sillyspec/changes/:quick 自己没有该目录,其下文件要么是关联变更(reverse-sync),
785
- * 要么是并发他者会话的工作。非关联变更目录整体视为元数据放行;关联变更文件不算(属本 quick 真实改动)
786
- *
787
- * 「并发工作 vs 偷建变更」的意图软判定留给 sillyhub,确定性校验只做路径归类。
788
- *
789
- * @param {string} p 文件路径(容错 \\ / 混用)
790
- * @param {string[]} [linkedChanges] 关联变更名列表(影响 changes/ 归类)
791
- * @returns {boolean} true=quick 元数据,应从业务文件列表过滤掉
792
- */
793
- export function isQuickMetadata(p, linkedChanges = []) {
794
- const normalizeGitPath = (x) => String(x).replace(/\\/g, '/')
795
- const file = normalizeGitPath(p)
796
- if (file.startsWith('.sillyspec/quicklog/')
797
- || file.startsWith('.sillyspec/.runtime/')
798
- || file === '.sillyspec/knowledge/uncategorized.md'
799
- || (/^\.sillyspec\/docs\/[^/]+\/modules\/[^/]+\.md$/.test(file))
800
- || (/^\.sillyspec\/docs\/[^/]+\/modules\/_module-map\.yaml$/.test(file))) return true
801
- if (file.startsWith('.sillyspec/changes/')) {
802
- const linkedChangeNames = new Set((Array.isArray(linkedChanges) ? linkedChanges : []).map(c => normalizeGitPath(c)))
803
- const m = file.match(/^\.sillyspec\/changes\/([^/]+)(\/|$)/)
804
- // bare 折叠 token(git 把全新未跟踪 changes/ 折叠成 `changes/`)或具体但非关联的变更 → 放行
805
- if (!m || !linkedChangeNames.has(m[1])) return true
806
- }
807
- return false
808
- }
809
-
810
- /**
811
- * quick 完成审计:对比 baseline 与实际变更。
812
- * @returns {{ status: 'safe'|'warning'|'blocked', reasons: string[], changedFiles: string[], newFiles: string[], deletedFiles: string[], baselineHit: string[], stagedTotal: number, attributedFiles: string[], undeclaredFiles: string[], foreignSessionDeclared: Array<{file: string, sessions: string[]}> }}
813
- */
814
- /**
815
- * D-8 O-1 模块归属(2026-08-15 docs-signals-o12):quick 欠账 hint 从"改了 N 文件"升级为
816
- * "涉及哪些模块卡"。只做归属(matchFilesToModules 纯函数零 git),不算 behind——对账是
817
- * execute Wave [docs-debt] 的职责(design D-001 轻量边界)。map 缺失/解析空/异常 → 空数组
818
- * 降级(hint 仍打,modules 省略),不报错不阻断。
819
- * 动态 import docs-debt.js/modules.js:prompt.js 已静态 import shared(本模块),静态互引成 ESM 环。
820
- */
821
- async function matchQuickModules(srcChanged, specBase, projectName) {
822
- if (!specBase || !projectName || srcChanged.length === 0) return []
823
- try {
824
- const { join } = await import('node:path')
825
- const { existsSync: ex, readFileSync: rf } = await import('node:fs')
826
- const mapPath = join(specBase, 'docs', projectName, 'modules', '_module-map.yaml')
827
- if (!ex(mapPath)) return []
828
- const { parseModuleMapSimple } = await import('../modules.js')
829
- const idx = parseModuleMapSimple(rf(mapPath, 'utf8'))
830
- if (!idx || Object.keys(idx).length === 0) return []
831
- const { matchFilesToModules } = await import('../docs-debt.js')
832
- const cardsDir = join(specBase, 'docs', projectName, 'modules')
833
- const { byModule } = matchFilesToModules(srcChanged, idx, { cardsDir })
834
- return [...byModule.entries()].map(([id, e]) => ({ id, doc: e.doc }))
835
- } catch {
836
- return []
837
- }
838
- }
839
-
840
- // ── task-03(2026-08-16-state-split-fixes): 活文档漂移提示辅助 ──
841
- // 背景:platform-interface-map.md 等活文档持续维护 src 主入口的 file:line 映射;并行会话改
842
- // src/ 后引用行号静默失效,docs gate 只能事后拦到别人的流程上。审计(auditQuickCompletion)
843
- // 当场检测「本次改动的 src 文件是否被活文档引用」并提示(advisory 不阻断,docs gate 语义不变)。
844
-
845
- /** 缺省活文档:src 主入口 ↔ 文档接口映射(file:line 锚点密度最高的持续维护文档)。 */
846
- export const DEFAULT_LIVING_DOC = 'docs/sillyspec/platform-interface-map.md'
847
-
848
- /**
849
- * 解析活文档集合:local.yaml `docs-check.living-docs` 列表【只追加不覆盖】缺省集合。
850
- * 与 docs-check.paths 的覆盖语义刻意不同——paths 是扫描范围(配了即整体替换缺省),
851
- * living-docs 是监控点登记(配了是加哨兵,不该把缺省监控点挤掉)。读配置走本模块现成的
852
- * readLocalYamlRaw + js-yaml 动态 import(readDocsCheckConfig 不回 living-docs 键;动态
853
- * import 与上方 docs-check 的隔离约定一致);坏 YAML / 非数组 / 读失败 → 仅缺省。
854
- * @param {string} cwd 仓库根(local.yaml 在 <cwd>/.sillyspec/local.yaml)
855
- * @returns {Promise<string[]>} 去重后的活文档相对路径(仓库根相对 POSIX)
856
- */
857
- export async function resolveLivingDocs(cwd) {
858
- let configured = []
859
- const raw = readLocalYamlRaw(cwd)
860
- if (raw) {
861
- try {
862
- const mod = await import('js-yaml')
863
- const yamlLoad = mod.load || mod.default?.load
864
- const doc = yamlLoad(raw)
865
- const dc = doc && typeof doc === 'object' ? doc['docs-check'] : null
866
- const ld = dc && typeof dc === 'object' ? dc['living-docs'] : null
867
- if (Array.isArray(ld)) configured = ld.filter((s) => typeof s === 'string' && s.trim() !== '')
868
- } catch { /* 坏 YAML → 忽略配置,仅缺省 */ }
869
- }
870
- return [...new Set([DEFAULT_LIVING_DOC, ...configured])]
871
- }
872
-
873
- /**
874
- * 纯函数:活文档引用的源码文件与本次改动的 src/ 文件求交。
875
- * 匹配口径对齐 docs-check resolveCandidates 的三形态(纯路径比对,不查盘):
876
- * ①仓库根相对:changed === ref(如 src/a.js)
877
- * ②src 内部相对:changed === 'src/' + ref(如 run/b.js → src/run/b.js)
878
- * ③裸名/中缀后缀:changed.endsWith('/' + ref)(如 b.js;前导斜杠防 aa.js 被引用 a.js 误吃)
879
- * changedFiles 口径 = git status porcelain 归一后的仓库根相对 POSIX 路径(parsePorcelainPath 产物)。
880
- * 同名多文件时后缀形态可能多报——与 docs-check 多候选宽容同向,advisory 仅提示可接受。
881
- * @param {string[]} srcChangedFiles changedFiles 中 src/ 前缀的文件
882
- * @param {Array<{file: string}>} refs collectDocRefs(md) 产物(只用 .file)
883
- * @returns {string[]} 命中的 srcChangedFiles 子集(去重保序)
884
- */
885
- export function matchLivingDocRefs(srcChangedFiles, refs) {
886
- const hit = new Set()
887
- for (const c of srcChangedFiles) {
888
- if (refs.some((r) => r && typeof r.file === 'string' &&
889
- (c === r.file || c === 'src/' + r.file || c.endsWith('/' + r.file)))) {
890
- hit.add(c)
891
- }
892
- }
893
- return [...hit]
894
- }
895
-
896
- /**
897
- * 纯函数:docs check invalid 条目与本次改动 src 文件求交(2026-08-18 漂移提示精度对齐)。
898
- * runDocsCheck 的 invalid 只带 ref 全串(`path:line(-end)`)——剥尾部行号段还原引用文件,
899
- * 再按 matchLivingDocRefs 同款三形态匹配(仓库根相对 / src 内部相对 / 裸名后缀)。
900
- * ref 空串(文档不存在条目)不匹配。
901
- * @param {Array<{ref?: string, doc?: string, docLine?: number, reason?: string}>} invalidRefs runDocsCheck().invalid
902
- * @param {string[]} srcChangedFiles changedFiles 中 src/ 前缀的文件
903
- * @returns {Array<{changed: string, doc: string, docLine: number, ref: string, reason: string}>} 真失效且指向本次改动文件的引用
904
- */
905
- export function matchInvalidRefsToChanged(invalidRefs, srcChangedFiles) {
906
- const out = []
907
- for (const x of Array.isArray(invalidRefs) ? invalidRefs : []) {
908
- if (!x || typeof x.ref !== 'string' || x.ref === '') continue
909
- const refFile = x.ref.replace(/:\d+(-\d+)?$/, '')
910
- const changed = srcChangedFiles.find((c) => c === refFile || c === 'src/' + refFile || c.endsWith('/' + refFile))
911
- if (changed) out.push({ changed, doc: x.doc || '', docLine: x.docLine || 0, ref: x.ref, reason: x.reason || '' })
912
- }
913
- return out
914
- }
915
-
916
- export async function auditQuickCompletion(cwd, guard, options = {}) {
917
- const { baselineFiles, allowedFiles = [], allowNew = false, forceBaseline = false, allowDelete = false, specBase = null, projectName = null } = guard
918
- const { isConfirm } = options
919
- // stagedTotal:当前所有非 quick 元数据的未提交条目(含前序 baseline 残留)。
920
- // 与 changedFiles(扣 baseline 后的本轮新增)区分,供审计文案同时展示「本轮新增 vs 累计暂存」,
921
- // 避免叠加 quick 会话时把前序会话未提交文件误读为「本会话只动了 N 个」。
922
- const result = { status: 'safe', reasons: [], changedFiles: [], newFiles: [], deletedFiles: [], baselineHit: [], stagedTotal: 0, attributedFiles: [], undeclaredFiles: [], foreignSessionDeclared: [] }
923
-
924
- try {
925
- // safeGit 带 -c safe.directory,避免 linked worktree/容器异 uid/挂载点下裸 `git status` 抛错被
926
- // 外层 catch 吞成 warning(multi-agent-review Q3)。safeGit 返回 {value,error} 不抛;若仍有 error
927
- // 说明真读不到 git 状态,保守阻断(审计无锚点不能放行),不静默降级。
928
- // trim:false 必传:porcelain 首行前导空格是状态码一部分,trim 会削掉致 parsePorcelainPath 丢首字符。
929
- // timeout 15000 + retryOnTimeout:机器忙时 git 子进程启动慢,默认 5s 偏紧易瞬时超时(ETIMEDOUT),
930
- // 审计锚点失败即 blocked 中断 quick。加大到 15s 并对 ETIMEDOUT 重试一次(重试 30s),消化绝大多数
931
- // 瞬时抖动,免去用户手工重跑(实测反馈:审计 git 偶发 ETIMEDOUT,重试即过)。
932
- const statusResult = safeGit(cwd, ['status', '--porcelain'], { trim: false, timeout: 15000, retryOnTimeout: true })
933
- if (statusResult.error) {
934
- result.reasons.push(`审计失败(git status): ${statusResult.error}`)
935
- result.status = 'blocked'
936
- return result
937
- }
938
- const gitStatus = statusResult.value || ''
939
- // 不对整段 .trim():会削首行前导空格致首文件路径丢首字符(见 parsePorcelainPath 注释)。
940
- const currentEntries = gitStatus.split('\n').filter(Boolean)
941
-
942
- const normalizeGitPath = (p) => p.replace(/\\/g, '/')
943
- // step1 启动时记录的全量脏文件 = 预存改动(非本次 quick 产生)。审计必须排除它们,
944
- // 否则脏工作区下预存文件持续留在 git status → 命中 baselineFiles → 误判「覆盖 baseline」
945
- // → 永远 blocked(--force-baseline 也救不回来,因为 status 判定看 baselineHit 数组)。
946
- // 前缀匹配:baseline 录入时未跟踪目录会被 git 折叠成 `dir/`(带尾斜杠)token,审计时若该
947
- // 目录下文件被跟踪则展开成文件级 `dir/file`——精确匹配对不上,故尾斜杠 token 按目录前缀放行。
948
- const normBaseline = (baselineFiles || []).map(f => normalizeGitPath(f))
949
- const baselineExact = new Set(normBaseline.filter(f => !f.endsWith('/')))
950
- const baselineDirs = normBaseline.filter(f => f.endsWith('/'))
951
- const isBaselineFile = (p) => {
952
- const f = normalizeGitPath(p)
953
- return baselineExact.has(f) || baselineDirs.some(d => f.startsWith(d))
954
- }
955
- // 他者 active 会话声明索引(坑 foreign-session-declared-false-block,2026-08-23 实证:多 agent
956
- // 并发时并行会话窗口内改的文件——尤其命中危险清单的(daemon/router.py 之于本仓是 src/run/*、
957
- // package.json)或 .sillyspec/ 下的——不在本会话 baseline,被算进本会话窗口直接 blocked,
958
- // 只能 --force-baseline 无差别逃生)。声明即归属的他向版本:他者会话显式声明(--files)的文件
959
- // 退栈归该会话审计。本会话也声明同一文件(--files 重叠)时不退栈——同文件并发归本会话审计
960
- // (sameFileHits advisory 管辖)。豁免面 = 他者显式声明,不含他者 baseline 快照(那是「启动时
961
- // 已脏」非所有权声明,当豁免依据会洗白任何预存脏文件)。
962
- const ownDeclaredNorm = new Set((allowedFiles || []).map(f => normalizeGitPath(f)))
963
- const foreignDeclaredIndex = new Map()
964
- for (const s of Array.isArray(guard.otherSessionsDeclared) ? guard.otherSessionsDeclared : []) {
965
- if (!s || typeof s !== 'object') continue
966
- for (const f of Array.isArray(s.files) ? s.files : []) {
967
- const nf = normalizeGitPath(f)
968
- if (!nf || ownDeclaredNorm.has(nf)) continue
969
- if (!foreignDeclaredIndex.has(nf)) foreignDeclaredIndex.set(nf, [])
970
- if (!foreignDeclaredIndex.get(nf).includes(s.sessionId)) foreignDeclaredIndex.get(nf).push(s.sessionId)
971
- }
972
- }
973
- const findForeignDeclaredOwner = (p) => {
974
- const f = normalizeGitPath(p)
975
- if (f.endsWith('/')) {
976
- // 折叠目录 token(porcelain 把全新未跟踪目录折成 `dir/`):目录下任一文件被他者声明 →
977
- // 整目录归他者;但本会话在同目录下有声明时不退栈——目录内混有双方文件,留给各门判定
978
- // (fail-closed:宁可误拦不可漏放,误拦有 --files 追加声明的明确出口)。
979
- if ([...ownDeclaredNorm].some(x => x.startsWith(f))) return null
980
- for (const [nf, owners] of foreignDeclaredIndex) {
981
- if (nf.startsWith(f)) return owners
982
- }
983
- return null
984
- }
985
- return foreignDeclaredIndex.get(f) || null
986
- }
987
- const DANGEROUS_PATTERNS = [
988
- 'package.json',
989
- 'package-lock.json',
990
- 'yarn.lock',
991
- 'pnpm-lock.yaml',
992
- '.eslintrc',
993
- 'tsconfig.json',
994
- // SillySpec 核心流程代码。W6 重构后 src/run.js(23 行 barrel)/ src/progress.js(facade)
995
- // 把真正逻辑下沉到 src/run/、src/progress/ 子目录——旧的精确文件名匹配
996
- // (file === 'src/run.js')命中不到 src/run/command.js(. 与 / 不可混同),致危险文件门
997
- // 静默失效。改用「目录前缀(带尾斜杠,startsWith 不会误伤 src/runtime-* 等同名前缀)+
998
- // barrel/facade 本体精确名」双重覆盖。重构 src/ 模块时须同步本清单(multi-agent-review Q5)。
999
- 'src/run.js',
1000
- 'src/run/',
1001
- 'src/progress.js',
1002
- 'src/progress/',
1003
- 'src/db.js',
1004
- 'src/stage-contract.js',
1005
- 'src/stage-contract-spec.js',
1006
- 'src/worktree.js',
1007
- 'src/worktree-apply.js',
1008
- 'src/hooks/',
1009
- ]
1010
-
1011
- for (const entry of currentEntries) {
1012
- // porcelain 两字符状态码(X=暂存区 Y=工作区)不能先 trim:' D'.trim()==='D' 使第二分支恒假、
1013
- // 'DD'/'AD' 等 trim 后不等于 'D' 而漏检——--allow-delete 门对此类删除静默放行(体检 BUG-04)。
1014
- // 用原始两字符判定任一侧为 D 即删除。
1015
- const rawStatus = entry.slice(0, 2)
1016
- const status = rawStatus.trim()
1017
- const file = parsePorcelainPath(entry) // 已去引号/处理 rename/归一化,修正首行丢首字符
1018
- if (!file) continue
1019
-
1020
- // 累计暂存计数:所有非 quick 元数据的未提交条目(含下方将被 baseline 跳过的前序残留)。
1021
- // 放在 isBaselineFile 跳过之前,确保 baseline 内文件也计入「累计暂存」。
1022
- if (!isQuickMetadata(file, guard.linkedChanges)) result.stagedTotal++
1023
-
1024
- // 预存脏文件:step1 baseline 已记录,非本次 quick 产生,跳过审计(含折叠目录前缀匹配)
1025
- if (isBaselineFile(file)) continue
1026
-
1027
- // 他者 active 会话已声明 → 完全退栈归该会话审计(危险/删除/新增/越界/baseline 全部门跳过),
1028
- // 收进 foreignSessionDeclared 供 printQuickAuditReview 软警告——放行可见可审计不静默
1029
- // (与 linkedChangeLeftovers 同哲学)。stagedTotal 已在上方计数,累计暂存口径不受退栈影响。
1030
- const foreignOwners = findForeignDeclaredOwner(file)
1031
- if (foreignOwners) {
1032
- result.foreignSessionDeclared.push({ file, sessions: foreignOwners })
1033
- continue
1034
- }
1035
-
1036
- result.changedFiles.push(file)
1037
- if (rawStatus[0] === 'D' || rawStatus[1] === 'D') result.deletedFiles.push(file)
1038
- if (status === '??') result.newFiles.push(file)
1039
-
1040
- // 检查是否命中 baseline protected files
1041
- if (baselineFiles.includes(file)) {
1042
- result.baselineHit.push(file)
1043
- }
1044
-
1045
- // 检查危险文件(除非 force-baseline)
1046
- if (file.startsWith('.sillyspec/') && !isQuickMetadata(file, guard.linkedChanges) && !forceBaseline) {
1047
- // 关联变更目录遗留放行(坑 linked-change-leftover-false-block,2026-08-22 实证:并发下
1048
- // 关联变更目录里他者/上个 session 的遗留脏文件——审计时不在本会话 baseline(启动后出现)
1049
- // 且 isQuickMetadata 对关联变更目录不豁免 → 落「危险文件」blocked,只能 --force-baseline。
1050
- // quick 无法区分「他者遗留」与「本次偷改」,按用户裁决放行降 warning:完全剔除出本会话
1051
- // 归属(changedFiles/newFiles/deletedFiles 均退栈),不计文件行、不触发危险/新增/越界
1052
- // 三道门,遗留给关联变更自己的流程收尾。非关联的 .sillyspec/ 仍 blocked。
1053
- const linkedDir = (Array.isArray(guard.linkedChanges) ? guard.linkedChanges : [])
1054
- .find(lc => file.startsWith(`.sillyspec/changes/${String(lc).replace(/\\/g, '/')}/`))
1055
- if (linkedDir) {
1056
- result.changedFiles.pop()
1057
- if (status === '??') result.newFiles.pop()
1058
- if (rawStatus[0] === 'D' || rawStatus[1] === 'D') result.deletedFiles.pop()
1059
- result.linkedChangeLeftovers = result.linkedChangeLeftovers || []
1060
- result.linkedChangeLeftovers.push(file)
1061
- continue
1062
- }
1063
- result.reasons.push(`危险文件变更: ${file}`)
1064
- }
1065
-
1066
- if (DANGEROUS_PATTERNS.some(p => p === file || file.startsWith(p)) && !forceBaseline) {
1067
- result.reasons.push(`危险文件变更: ${file}`)
1068
- }
1069
- }
1070
-
1071
- // 检查 deleted files(--allow-delete 显式放行:删除是破坏性操作,默认 fail-closed,flag 即知情 opt-in)
1072
- if (!allowDelete) {
1073
- for (const f of result.deletedFiles) {
1074
- result.reasons.push(`删除文件: ${f}`)
1075
- }
1076
- }
1077
-
1078
- // 检查 baseline hit(除非 force-baseline)
1079
- if (!forceBaseline) {
1080
- for (const f of result.baselineHit) {
1081
- result.reasons.push(`覆盖 baseline 文件: ${f}`)
1082
- }
1083
- }
1084
-
1085
- // 检查 new files(除非 allow-new)
1086
- if (!allowNew) {
1087
- for (const f of result.newFiles) {
1088
- if (!isQuickMetadata(f, guard.linkedChanges)) {
1089
- result.reasons.push(`新增文件(需 --allow-new): ${f}`)
1090
- }
1091
- }
1092
- }
1093
-
1094
- // 检查 allowedFiles 范围
1095
- if (allowedFiles.length > 0) {
1096
- for (const f of result.changedFiles) {
1097
- if (!allowedFiles.includes(f) && !isQuickMetadata(f, guard.linkedChanges)) {
1098
- result.reasons.push(`超出 allowedFiles: ${f}`)
1099
- }
1100
- }
1101
- }
1102
-
1103
- // 判定结果(force-baseline 降级 baselineHit → 非 blocked;allow-new 降级新增文件 → 非 warning;
1104
- // allow-delete 降级删除文件 → 非 blocked。reasons 文案本就受 flag 控制,但原判定直接看数组长度,
1105
- // 致 flag 对 status 失效。)
1106
- if ((!forceBaseline && result.baselineHit.length > 0) || (!allowDelete && result.deletedFiles.length > 0) || result.reasons.some(r => r.startsWith('危险') || r.startsWith('删除'))) {
1107
- result.status = 'blocked'
1108
- } else if ((!allowNew && result.newFiles.some(f => !isQuickMetadata(f, guard.linkedChanges))) || (allowedFiles.length > 0 && result.reasons.some(r => r.startsWith('超出')))) {
1109
- // newFiles 按元数据过滤后判定(坑 quick-metadata-warning-no-reason):.sillyspec/ 被 git
1110
- // 跟踪的仓库里 quick 新建的 quicklog/*.md 是合法元数据,不过滤会 status=warning 而
1111
- // reasons 为空(reasons 侧已过滤),打印空原因的 WARNING 噪声。
1112
- result.status = 'warning'
1113
- }
1114
-
1115
- // quicklog 存在性检查(specBase 感知:平台模式 quicklog 写在 specRoot 下,stage.js
1116
- // allocateQuicklogEntry 同源;硬编码 cwd/.sillyspec 会恒误报「目录不存在」抬 warning)
1117
- try {
1118
- const quicklogDir = join(specBase || join(cwd, '.sillyspec'), 'quicklog')
1119
- if (existsSync(quicklogDir)) {
1120
- const qlFiles = readdirSync(quicklogDir).filter(f => f.endsWith('.md'))
1121
- if (qlFiles.length === 0) {
1122
- result.reasons.push('quicklog 目录为空(无任务记录)')
1123
- if (result.status === 'safe') result.status = 'warning'
1124
- }
1125
- } else {
1126
- result.reasons.push('quicklog 目录不存在(agent 未创建任务记录)')
1127
- if (result.status === 'safe') result.status = 'warning'
1128
- }
1129
- } catch {}
1130
-
1131
- // D-8 文档欠账显性化(advisory):本次改动含源码文件但不含任何文档文件 → 打标记 warn。
1132
- // quick 是低摩擦通道(不强制文档同步),但欠账要显性化——72% 流量 86% 不动文档是系统性欠账
1133
- // 主通道(doc-consistency-debt D-8)。不阻断不改 status,只 warn + 记 reasons 供 QUICKLOG 追溯。
1134
- const isDocFile = (f) =>
1135
- f.endsWith('.md') || f.endsWith('.yaml') || f.endsWith('.yml') ||
1136
- f.startsWith('docs/') || f.startsWith('.sillyspec/docs/')
1137
- const srcChanged = result.changedFiles.filter(f => !isDocFile(f) && !isQuickMetadata(f, guard.linkedChanges))
1138
- const docChanged = result.changedFiles.filter(isDocFile)
1139
- if (srcChanged.length > 0 && docChanged.length === 0) {
1140
- result.reasons.push(`本次未同步模块文档(${srcChanged.length} 个源码文件改动,无文档文件)`)
1141
- result.docSyncHint = { touchedSource: srcChanged.length, docFiles: [], modules: await matchQuickModules(srcChanged, specBase, projectName) }
1142
- } else if (srcChanged.length > 0 && docChanged.length > 0) {
1143
- result.docSyncHint = { touchedSource: srcChanged.length, docFiles: docChanged }
1144
- }
1145
-
1146
- // docs check advisory(doc-consistency-debt D-6 后续):本次改动的 .md 文档跑 file:line
1147
- // 引用校验,失效即 warn + reasons——检测能力落地后欠账只涨不跌的最后一公里。只查本次
1148
- // changedFiles 的文档(归因到本次改动),不扫全仓历史欠账(那是存量问题,quick 不背锅)。
1149
- // 排除删除文件(troubleshooting #9):删除的 .md 不在盘,runDocsCheck 只会报「文档不存在」
1150
- // 假失效——删除语义归 --allow-delete 管,无引用校验可言(并行会话的删除尤其不该归属本会话)。
1151
- // docs-check 是 IO 面(walkGlob/existsSync),动态 import 隔离;任何异常 fail-open 只跳过。
1152
- const deletedSet = new Set(result.deletedFiles)
1153
- const mdChanged = result.changedFiles.filter((f) => f.endsWith('.md') && !deletedSet.has(f) && !isQuickMetadata(f, guard.linkedChanges))
1154
- if (mdChanged.length > 0) {
1155
- try {
1156
- const { runDocsCheck, readDocsCheckConfig } = await import('../docs-check.js')
1157
- // HUB-06:补传 crossRepoRoots(与 docs gate / index.js docs check 同口径)——
1158
- // 否则 repo:// 跨仓引用在这条链路恒跳过;无 local.yaml 配置时 undefined = 不启用
1159
- let quickCfg = {}
1160
- try { quickCfg = readDocsCheckConfig(cwd) || {} } catch { quickCfg = {} }
1161
- const dc = runDocsCheck({ projectRoot: cwd, docs: mdChanged, crossRepoRoots: quickCfg.crossRepoRoots })
1162
- if (!dc.ok) {
1163
- result.reasons.push(`本次改动文档含 ${dc.invalid.length} 处失效 file:line 引用(sillyspec docs check 可复现)`)
1164
- result.docsCheckHint = { invalid: dc.invalid.length, total: dc.total }
1165
- if (result.status === 'safe') result.status = 'warning'
1166
- }
1167
- } catch { /* docs-check 不可用(老版本包等)→ 静默跳过,不阻断 quick */ }
1168
- }
1169
-
1170
- // task-03: 活文档漂移提示(advisory,不阻断不改 status,docs gate 语义不变)。
1171
- // 方向与上方 docsCheckHint 相反:那是「本次改的文档引用失效吗」,这是「本次改的 src 被活文档
1172
- // 引用吗」——并行会话改 src/ 主入口后 platform-interface-map.md 的 file:line 行号静默失效,
1173
- // gate 事后拦到别人流程上。fail-open:活文档缺失/读失败/校验机器不可用 → 静默跳过(不误报不阻断)。
1174
- // 2026-08-18 精度对齐:原路径级「被引用即提示」在行号锚未真断时误报(实测 advisory 报漂移、
1175
- // docs check 417/417 全过)。升级为复用 runDocsCheck 分层真校验(存在 + 行界 + 关键词窗口),
1176
- // 只报「真失效且指向本次改动文件」的引用;全过 → 零输出(与 docs check 结论同源)。
1177
- // matchLivingDocRefs 留作廉价预过滤:该文档不引用任何本次改动文件时跳过整档真校验(省 IO)。
1178
- const srcChangedFiles = result.changedFiles.filter((f) => f.startsWith('src/') && !deletedSet.has(f))
1179
- if (srcChangedFiles.length > 0) {
1180
- try {
1181
- const { collectDocRefs, runDocsCheck, readDocsCheckConfig } = await import('../docs-check.js')
1182
- // HUB-06:活文档(platform-interface-map.md 等最可能写 repo:// 引用的文档)同样补传
1183
- // crossRepoRoots;配置读一次提到循环外(per-cwd 恒同)
1184
- let livingCfg = {}
1185
- try { livingCfg = readDocsCheckConfig(cwd) || {} } catch { livingCfg = {} }
1186
- const livingDocs = await resolveLivingDocs(cwd)
1187
- const files = []
1188
- const docs = []
1189
- const invalidAll = []
1190
- for (const docRel of livingDocs) {
1191
- let md
1192
- try { md = readFileSync(join(cwd, docRel), 'utf8') } catch { continue } // 活文档缺失/读失败 → 跳过
1193
- const hit = matchLivingDocRefs(srcChangedFiles, collectDocRefs(md))
1194
- if (hit.length === 0) continue
1195
- files.push(...hit)
1196
- docs.push(docRel)
1197
- const r = runDocsCheck({ projectRoot: cwd, docs: [docRel], keywordAssert: true, crossRepoRoots: livingCfg.crossRepoRoots })
1198
- for (const x of r.invalid) invalidAll.push({ ...x, doc: docRel })
1199
- }
1200
- const invalid = matchInvalidRefsToChanged(invalidAll, srcChangedFiles)
1201
- if (invalid.length > 0) {
1202
- const uniqFiles = [...new Set(files)]
1203
- result.docsCheckHint = { ...(result.docsCheckHint || {}), livingDocDrift: { files: uniqFiles, docs, total: srcChangedFiles.length, invalid } }
1204
- result.reasons.push(`活文档引用真失效: ${invalid.length} 处指向本次改动文件的引用校验失败(${docs.join(', ')})`)
1205
- }
1206
- } catch { /* 校验机器不可用 → 静默跳过 */ }
1207
- }
1208
-
1209
- // task-02: 同文件并发检测——allowedFile 在 baseline(他者改过)且当前 hash ≠ step1 hash(我也改了)
1210
- // → commit 整文件 pathspec 会夹带他者 hunk,warn 给分离指引(advisory,不阻断,D-002)
1211
- // sameFileHits 提升到本层作用域:下方归属切分要把「baseline 声明文件且我也改了」并入
1212
- // attributedFiles(这类文件先被 isBaselineFile 跳过不进 changedFiles,但确属本会话产物)。
1213
- const sameFileHits = []
1214
- if (allowedFiles.length > 0 && guard.allowedFilesHash) {
1215
- for (const f of allowedFiles) {
1216
- if (isBaselineFile(f) && guard.allowedFilesHash[f] !== undefined) {
1217
- try {
1218
- const cur = createHash('sha256').update(readFileSync(join(cwd, f))).digest('hex')
1219
- if (cur !== guard.allowedFilesHash[f]) sameFileHits.push(f)
1220
- } catch {} // 文件读失败(删除等)跳过
1221
- }
1222
- }
1223
- if (sameFileHits.length > 0) {
1224
- result.reasons.push(`同文件并发: ${sameFileHits.length} 个 allowedFile 含他者+你的改动(${sameFileHits.join(', ')})`)
1225
- console.warn(`\n⚠️ 同文件并发(${sameFileHits.length} 个 allowedFile 含他者改动+你的改动,commit 整文件会夹带他者 hunk):`)
1226
- for (const f of sameFileHits) {
1227
- console.warn(` - ${f}`)
1228
- console.warn(` 分离:git add -p ${f}(交互选你的 hunk)或 git diff ${f} > mine.patch(编辑留你的)+ git apply --cached mine.patch`)
1229
- }
1230
- // 宽严差异明示(坑 concurrent-policy-inconsistency,2026-08-22 实证:quick 同文件并发只
1231
- // warn 不阻断、plan 阶段同 Wave 同文件却硬拦——两阶段宽严不一致易误判边界)。差异是设计
1232
- // 使然:quick 是轻量流程无子代理并行,同文件并发最坏后果是 commit 夹带他者 hunk(git 可
1233
- // 分离,提示分离命令即可);plan 的同 Wave 同文件会让 execute 的并行子代理互相覆盖(不可
1234
- // 自动恢复),必须设计期硬拦。
1235
- console.warn(` ℹ️ 边界说明:quick 对同文件并发只提示不阻断(最坏后果=commit 夹带他者 hunk,git 可分离);`)
1236
- console.warn(` plan 阶段同 Wave 同文件是硬错误(execute 并行子代理会互相覆盖,不可自动恢复)——两阶段宽严不同是设计使然,勿以 quick 的宽松推断 plan 的边界。`)
1237
- }
1238
- }
1239
-
1240
- // 归属切分(2026-08-18 误归属修复,ql-20260818-003 实证):窗口 diff(changedFiles)在多 agent
1241
- // 并发仓库分不清「本会话改」与「他者窗口内改」,他者文件会污染 QUICKLOG「文件:」行。声明即归属:
1242
- // allowedFiles 非空时 attributedFiles = 窗口∩声明 ∪ sameFileHits(同文件并发 = 我也改了),
1243
- // undeclaredFiles = 窗口−声明(他者或漏声明,供「审计:」行落盘追溯——不静默丢,防漏声明时
1244
- // 真实改动被挤走无痕)。未声明会话无归属信息不猜,维持全量口径(attributed = changed)。
1245
- const declaredNorm = new Set(allowedFiles.map(f => normalizeGitPath(f)))
1246
- if (declaredNorm.size > 0) {
1247
- const own = result.changedFiles.filter(f => declaredNorm.has(normalizeGitPath(f)))
1248
- for (const f of sameFileHits) if (!own.includes(f)) own.push(f)
1249
- result.attributedFiles = own
1250
- result.undeclaredFiles = result.changedFiles.filter(f => !declaredNorm.has(normalizeGitPath(f)))
1251
- } else {
1252
- result.attributedFiles = result.changedFiles
1253
- result.undeclaredFiles = []
1254
- }
1255
-
1256
- // --confirm 模式:展示 diff 并等待确认
1257
- if (isConfirm && (result.status === 'warning' || result.status === 'blocked')) {
1258
- console.log(`\n📋 quick 变更概览:`)
1259
- console.log(` 新增: ${result.newFiles.length}, 修改: ${result.changedFiles.length - result.newFiles.length - result.deletedFiles.length}, 删除: ${result.deletedFiles.length}`)
1260
- if (result.changedFiles.length > 0) {
1261
- console.log(`\n 变更文件:`)
1262
- for (const f of result.changedFiles) {
1263
- const isBaseline = baselineFiles.includes(f)
1264
- const isDangerous = DANGEROUS_PATTERNS.some(p => f.includes(p))
1265
- const marker = isBaseline ? '🔴' : isDangerous ? '⚠️' : ' '
1266
- console.log(` ${marker} ${f}`)
1267
- }
1268
- }
1269
- console.log(`\n 状态: ${result.status.toUpperCase()}`)
1270
- if (result.reasons.length > 0) {
1271
- console.log(` 原因:`)
1272
- for (const r of result.reasons) {
1273
- console.log(` - ${r}`)
1274
- }
1275
- }
1276
- if (result.deletedFiles.length > 0) {
1277
- if (guard.allowDelete) {
1278
- console.log(`\n ℹ️ 已确认删除文件 ${result.deletedFiles.length} 个(--allow-delete 显式解锁):${result.deletedFiles.join(', ')}`)
1279
- } else {
1280
- console.log(`\n ⛔ 本次含删除文件 ${result.deletedFiles.length} 个——删除是破坏性操作默认 fail-closed,确认删除请带 --allow-delete 显式解锁:`)
1281
- console.log(` sillyspec run quick --done --allow-delete --change <id> --output "..."`)
1282
- console.log(` (--force-baseline / --allow-new 不能解锁删除;不确认请 git restore 撤回删除后再 --done,或走完整流程 execute 由 review 把关)`)
1283
- }
1284
- } else {
1285
- console.log(`\n 如确认接受这些变更,重新运行 --done 时带上对应 flag 即可解锁:`)
1286
- console.log(` sillyspec run quick --done --force-baseline --allow-new --change <id> --output "..."`)
1287
- console.log(` (--force-baseline 覆盖受保护/危险文件如 src/run.js;--allow-new 允许新增文件;--allow-delete 允许删除文件)`)
1288
- console.log(` 或在首个 sillyspec run quick 启动(step 1)时就声明这些 flag,持久化进 guard。`)
1289
- }
1290
- }
1291
- } catch (e) {
1292
- result.reasons.push(`审计失败: ${e.message}`)
1293
- result.status = 'warning'
1294
- }
1295
-
1296
- return result
1297
- }
1298
-
1299
- // ── Step 处理辅助(W6 Step7a 从 run.js 搬入:getStageSteps/formatWaitOptions 被 run.js + complete.js 共用)──
1300
- /**
1301
- * 格式化 waitOptions 为人类可读字符串
1302
- */
1303
- export function formatWaitOptions(raw) {
1304
- if (!raw) return null
1305
- try {
1306
- const parsed = JSON.parse(raw)
1307
- if (Array.isArray(parsed)) return parsed.join(', ')
1308
- return raw
1309
- } catch {
1310
- return raw
1311
- }
1312
- }
1313
-
1314
-
1315
- /**
1316
- * 进程级 MultiRepoContext 缓存(D-013 G2:execute 启动构造一次,贯穿 execute/apply/verify 不重建)。
1317
- *
1318
- * key = `${cwd} ${changeName}`(cwd 隔离防多仓并发串扰;changeName 隔离防同进程多 change 切换串扰)。
1319
- * 跨 CLI 命令(execute vs apply vs verify 各是独立进程)各自构造——design §7.2 G2 明确 apply/verify
1320
- * 「复用 execute 实例,**或**从 review.json.repo + local.yaml repos 反推」,进程级缓存指同一 CLI 命令内复用。
1321
- *
1322
- * 失效语义:ctx 是纯内存对象(task-01 不持久化),进程结束自动释放。无需手动清理。
1323
- * 缓存命中场景:execute 单次 --done 内 getStageSteps(派发)+ completeStageGates(gate)+ 阶段完成
1324
- * 收尾多次取同一 ctx;apply/verify 同理。fail-closed 抛错不缓存(下次重试重新构造)。
1325
- */
1326
- const _multiRepoCtxCache = new Map()
1327
-
1328
- /**
1329
- * 读 local.yaml 原始文本(best-effort,不存在/读失败返 '')。
1330
- * 与 sync.js readLocalYamlRaw 同风格,但本模块不引 sync.js(避免循环依赖 + sync.js 非 export)。
1331
- * local.yaml 路径 = `<cwd>/.sillyspec/local.yaml`(与 sync.js/config-schema.js 一致)。
1332
- * @param {string} cwd
1333
- * @returns {string}
1334
- */
1335
- function readLocalYamlRaw(cwd) {
1336
- const p = join(cwd, '.sillyspec', 'local.yaml')
1337
- if (!existsSync(p)) return ''
1338
- try {
1339
- return readFileSync(p, 'utf8')
1340
- } catch {
1341
- return ''
1342
- }
1343
- }
1344
-
1345
- /**
1346
- * 从 plan.md 内容聚合所有 task 卡片声明的 repo:(去重,含 'main' 隐式)。
1347
- *
1348
- * design §5.4 execute 启动段 + §7.2:扫 plan.md 所有 task 卡片 frontmatter,用 parseRepo 解析
1349
- * repo: 字段(缺省='main'),去重后返回数组。'main' 永远隐式在列(主仓 task 不写 repo: 也算主仓)。
1350
- *
1351
- * 聚合策略:plan.md 由 plan 阶段生成,task 卡片 frontmatter 形如 `---\nrepo: sillyspec\n...\n---`
1352
- * (与 task-NN.md 同源)。本函数全局匹配所有 frontmatter 块(`/^---\n([\s\S]*?)\n---/mg`),
1353
- * 每块重新拼成完整 frontmatter 喂 parseRepo(parseRepo 内部 `^---\n...\n---` 锚开头)。
1354
- *
1355
- * @param {string} planContent
1356
- * @returns {string[]} 去重后的 repo 数组(至少含 'main')
1357
- */
1358
- export function aggregateDeclaredRepos(planContent) {
1359
- const seen = new Set(['main']) // main 永远隐式
1360
- if (!planContent) return ['main']
1361
- // 全局匹配所有 frontmatter 块(m 标志让 ^ 匹配每行行首,但此处 ^--- 要求行首 ---,
1362
- // 配合 [\s\S]*? 非贪婪到下一个 ---)。每块重新拼完整 frontmatter 喂 parseRepo。
1363
- const fmRegex = /^---\r?\n([\s\S]*?)\r?\n---/gm
1364
- let match
1365
- while ((match = fmRegex.exec(planContent)) !== null) {
1366
- const fmBody = match[1]
1367
- // 重新拼成 parseRepo 期望的完整 frontmatter(---\n<body>\n---)
1368
- const repo = parseRepo(`---\n${fmBody}\n---`)
1369
- if (repo && !seen.has(repo)) seen.add(repo)
1370
- }
1371
- return Array.from(seen)
1372
- }
1373
-
1374
- /**
1375
- * 坑7 补扫:读 tasks/task-NN.md 独立卡片,拼成可被 aggregateDeclaredRepos 的 frontmatter
1376
- * 正则识别的文本(每张卡内容原样拼接,卡内容自带的 ---\n…\n--- frontmatter 会被同一正则命中)。
1377
- *
1378
- * plan 阶段标准产出形态是 plan.md 内联卡片块 + tasks/ 独立卡片双写,但实际执行中 plan.md
1379
- * 可能只留 checkbox 行(卡片全在 tasks/)——此时 plan.md 聚合不到跨仓 repo,跨仓 review
1380
- * 误报伪造。本函数读 tasks/ 目录兜底,任一文件读失败跳过(fail-open,兜底源不引入新阻断)。
1381
- *
1382
- * @param {string} specDir - spec 根(change 目录的父级)
1383
- * @param {string} changeName
1384
- * @returns {string} 拼接文本(无 tasks/ 或全空 → '',plan.md 原行为零回归)
1385
- */
1386
- function collectTaskCardReposFallback(specDir, changeName) {
1387
- const tasksDir = join(specDir, 'changes', changeName, 'tasks')
1388
- if (!existsSync(tasksDir)) return ''
1389
- let merged = ''
1390
- for (const f of readdirSync(tasksDir)) {
1391
- if (!/^task-\d+\.md$/i.test(f)) continue
1392
- const p = join(tasksDir, f)
1393
- // CRLF 卡片:\r?\n 容差在 aggregateDeclaredRepos 正则里,这里只管拼接不归一
1394
- try {
1395
- merged += '\n' + readFileSync(p, 'utf8') + '\n'
1396
- } catch {
1397
- // 单文件读失败跳过——兜底源缺失不该阻断主聚合
1398
- }
1399
- }
1400
- return merged
1401
- }
1402
-
1403
- /**
1404
- * 构造或取进程级 MultiRepoContext 单例(D-013 G2)。
1405
- *
1406
- * design §5.4 execute 启动段 + §7.2 G2 + 决策 D-001/D-013:
1407
- * - 读 local.yaml repos: 段(parseRepoRegistry)→ repoRegistry Map(main 隐式不注册)
1408
- * - 扫 plan.md 所有 task 卡片 repo:(aggregateDeclaredRepos)→ declaredRepos(含 'main')
1409
- * - 构造 MultiRepoContext(约束② fail-closed:未注册 repo / 跨仓 git 不可用抛错阻断)
1410
- * - 按 `${cwd} ${changeName}` 缓存,同进程同 change 复用
1411
- *
1412
- * **单仓退化**(design §7.2 「main 隐式为 cwd 不用注册」):local.yaml 无 repos: 段 + 单仓 change
1413
- * (declaredRepos=['main'])→ repoRegistry=空 Map,MultiRepoContext 退化为 {main:{...}} 单值 map,
1414
- * hasCrossRepo()=false,所有 ctx 透传点缺省行为零回归(task-01/04/05/06/07/08 各模块 ctx=null 等价)。
1415
- *
1416
- * **跨仓 fail-closed**(约束② D-007):declaredRepos 含 local.yaml 未注册的 repo key,或跨仓仓
1417
- * git rev-parse 失败 → MultiRepoContext 构造抛错,本函数**不缓存**该错误,原样上抛阻断 execute 启动。
1418
- *
1419
- * 缓存语义:命中返回已构造实例;未命中且构造成功则缓存后返回;构造失败不缓存(下次重试重新构造)。
1420
- *
1421
- * @param {Object} opts
1422
- * @param {string} opts.cwd - 主仓 cwd
1423
- * @param {string} opts.changeName - 当前 change 名
1424
- * @param {Object} [opts.platformOpts] - 平台选项(specRoot 等,透传给 MultiRepoContext 预留)
1425
- * @param {boolean} [opts.noCache=false] - 跳过缓存(测试 / 显式重建场景)
1426
- * @returns {MultiRepoContext|null} changeName/cwd 缺失或无 plan.md 时返回 null(单仓退化,调用方按 ctx=null 处理)
1427
- * @throws {Error} MultiRepoContext 构造 fail-closed(约束②未注册/跨仓git不可用)
1428
- */
1429
- export async function getOrCreateMultiRepoContext({ cwd, changeName, platformOpts = {}, noCache = false } = {}) {
1430
- if (!cwd || !changeName) return null
1431
- const cacheKey = `${cwd} ${changeName}`
1432
- if (!noCache && _multiRepoCtxCache.has(cacheKey)) {
1433
- return _multiRepoCtxCache.get(cacheKey)
1434
- }
1435
-
1436
- // 读 plan.md(execute 启动入口的 change 目录),无 plan.md → 无法聚合 declaredRepos → 退化 null
1437
- const specDir = platformOpts?.specRoot || resolveSpecDir(cwd)
1438
- const planFile = join(specDir, 'changes', changeName, 'plan.md')
1439
- let planContent = ''
1440
- if (existsSync(planFile)) {
1441
- try {
1442
- planContent = readFileSync(planFile, 'utf8')
1443
- } catch {
1444
- planContent = ''
1445
- }
1446
- }
1447
- if (!planContent) {
1448
- // 无 plan.md(plan 未完成 / brainstorm 阶段 / quick 等场景)→ 无 task 卡片可扫,
1449
- // 不构造 ctx(返 null 退化单仓)。跨仓 task 必须 plan.md 落地后才进 execute,此处安全。
1450
- return null
1451
- }
1452
-
1453
- // 聚合 declaredRepos(扫 plan.md task 卡片 repo:)+ 读 local.yaml repos: 段
1454
- // 坑7 兼扫 tasks/task-NN.md:plan 阶段把卡片写到 tasks/、plan.md 只留 checkbox 行时,
1455
- // plan.md 内联 frontmatter 聚合不到跨仓 repo → ctx 不含跨仓 entry → 跨仓 review 退回主仓
1456
- // gitDir 校验,误报「base 不是真实 commit — 疑似伪造」(真实 commit 在跨仓仓可达)。
1457
- // 两源并入同一聚合:plan.md 内联块(原行为,零回归)+ tasks/ 独立卡片(坑7 补扫)。
1458
- const declaredRepos = aggregateDeclaredRepos(
1459
- planContent + collectTaskCardReposFallback(specDir, changeName)
1460
- )
1461
- const repoRegistry = parseRepoRegistry(readLocalYamlRaw(cwd))
1462
-
1463
- // 构造 WorktreeManager(主仓 meta 读取;与 getStageSteps 同源范式)
1464
- let worktreeManager
1465
- try {
1466
- const { WorktreeManager } = await import('../worktree.js')
1467
- worktreeManager = new WorktreeManager({ cwd })
1468
- } catch {
1469
- // WorktreeManager 不可用 → 退化为最小桩(in-place-fallback 兜底 cwd)
1470
- worktreeManager = { getMeta: () => null }
1471
- }
1472
-
1473
- const ctx = new MultiRepoContext({
1474
- cwd,
1475
- changeName,
1476
- platformOpts,
1477
- declaredRepos,
1478
- repoRegistry,
1479
- worktreeManager,
1480
- })
1481
-
1482
- if (!noCache) {
1483
- _multiRepoCtxCache.set(cacheKey, ctx)
1484
- }
1485
- return ctx
1486
- }
1487
-
1488
- /**
1489
- * 清除进程级 MultiRepoContext 缓存(测试隔离用)。生产代码不需手动清。
1490
- * @param {string} [cwd]
1491
- * @param {string} [changeName]
1492
- */
1493
- export function _clearMultiRepoCtxCache(cwd, changeName) {
1494
- if (cwd && changeName) {
1495
- _multiRepoCtxCache.delete(`${cwd} ${changeName}`)
1496
- } else {
1497
- _multiRepoCtxCache.clear()
1498
- }
1499
- }
1500
-
1501
-
1502
- /**
1503
- * 获取阶段的步骤定义(execute 需要动态构建)
1504
- */
1505
- export async function getStageSteps(stageName, cwd, progress, specDir = null) {
1506
- if (stageName === 'execute') {
1507
- const changeDir = resolveChangeDir(cwd, progress, specDir)
1508
- let planFile = null
1509
- let worktreePath = null
1510
- let changeName = null
1511
- if (changeDir) {
1512
- const p = join(changeDir, 'plan.md')
1513
- if (existsSync(p)) planFile = p
1514
- changeName = basename(changeDir)
1515
- // 自动检测 worktree 路径,注入 Wave prompt 的 workdir 指令
1516
- // 修复:之前未传 worktreePath 给 buildExecuteSteps,导致 Wave prompt 缺失工作目录指令,
1517
- // 子代理可能把文件写到主工作区而非 worktree 内,破坏隔离。
1518
- try {
1519
- const { WorktreeManager } = await import('../worktree.js')
1520
- const wm = new WorktreeManager({ cwd })
1521
- const meta = wm.getMeta(changeName)
1522
- if (meta?.worktreePath && existsSync(meta.worktreePath)) {
1523
- worktreePath = meta.worktreePath
1524
- }
1525
- } catch {
1526
- // 无 worktree meta 不阻断——可能是首次启动或 in-place 模式
1527
- }
1528
- }
1529
- // W3 task-09:execute 启动入口构造 MultiRepoContext 单例(D-013 G2),贯穿 execute/apply/verify。
1530
- // 单仓 change(无 repo: / 无 local.yaml repos 段)→ ctx=null 退化单仓零回归(task-08 buildExecuteSteps 缺省 null)。
1531
- // 跨仓 change 缺注册 / 跨仓 git 不可用 → getOrCreateMultiRepoContext 抛错阻断 execute 启动(约束②)。
1532
- let ctx = null
1533
- if (changeName) {
1534
- try {
1535
- ctx = await getOrCreateMultiRepoContext({ cwd, changeName, platformOpts: specDir ? { specRoot: specDir } : {} })
1536
- } catch (e) {
1537
- // fail-closed 阻断:execute 启动期 ctx 构造失败(未注册 repo / 跨仓 git 不可用),
1538
- // 抛错让上层 runCommand 把错误返回给 Agent(不降级单仓跑——跨仓 apply 走错仓=数据所有权事故)。
1539
- throw new Error(`execute 启动失败:跨仓 MultiRepoContext 构造失败(${e.message})`)
1540
- }
1541
- }
1542
- return buildExecuteSteps(planFile, { worktreePath, ctx })
1543
- }
1544
- if (stageName === 'plan') {
1545
- const changeDir = resolveChangeDir(cwd, progress, specDir)
1546
- return buildPlanSteps(changeDir)
1547
- }
1548
- if (stageName === 'scan') {
1549
- // quick 档感知(坑 scan-quick-profile-step-mismatch):scan 的 scanProfile 在首进程
1550
- // runStage 里算出并持久化(stageData.scanProfile),quick 档把 11 步注册表裁成 3 步。
1551
- // 此处恒返回注册表会让后续进程 ensureStageSteps 见 3 vs 11 触发漂移重播种(quick 已完成
1552
- // 步丢失、从未执行的注册表步骤被 --done),同进程 outputStep 也用错位 defSteps 渲染。
1553
- // quick 档 → 与 applyScanProfileSteps 同源返回 3 步表;standard/deep 与注册表同长度零影响。
1554
- if (progress?.stages?.scan?.scanProfile?.mode === 'quick') {
1555
- const { buildQuickScanSteps } = await import('./scan-profile.js')
1556
- return buildQuickScanSteps()
1557
- }
1558
- }
1559
- const def = stageRegistry[stageName]
1560
- return def ? def.steps : null
1561
- }
1562
-