sillyspec 3.27.12 → 3.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1207) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +214 -214
  2. package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
  3. package/.claude/skills/sillyspec-quick/SKILL.md +116 -116
  4. package/package.json +1 -1
  5. package/src/agent-session-log.js +77 -10
  6. package/src/config-schema.js +2 -2
  7. package/src/contract-matrix.js +15 -2
  8. package/src/doctor-diagnostics.js +64 -1
  9. package/src/endpoint-extractor.js +100 -24
  10. package/src/index.js +36 -5
  11. package/src/machine-interface.js +63 -0
  12. package/src/progress/stage-machine.js +106 -1
  13. package/src/progress.js +3 -0
  14. package/src/run/command.js +1 -1
  15. package/src/run/complete-handlers.js +31 -3
  16. package/src/run/complete.js +12 -4
  17. package/src/run/quick-audit.js +98 -0
  18. package/src/run/shared.js +54 -0
  19. package/src/run/stage.js +18 -11
  20. package/src/spec-sync.js +191 -14
  21. package/src/stages/execute.js +6 -2
  22. package/src/sync.js +122 -4
  23. package/src/task-review.js +51 -4
  24. package/src/verify-postcheck.js +60 -8
  25. package/src/verify-probes.js +3 -0
  26. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  27. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  28. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  29. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  30. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  31. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  32. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  33. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  34. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +0 -57
  35. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +0 -177
  36. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  37. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  38. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  39. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  40. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  41. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +0 -64
  42. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +0 -54
  43. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  44. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  45. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +0 -2
  46. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +0 -20
  47. package/.claude/worktrees/sillyspec-data-model-research/README.md +0 -203
  48. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +0 -91
  49. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +0 -2
  50. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  51. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +0 -977
  52. package/.claude/worktrees/sillyspec-data-model-research/package.json +0 -39
  53. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  54. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  55. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  56. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +0 -16
  57. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  58. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +0 -836
  59. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +0 -256
  60. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +0 -25
  61. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +0 -95
  62. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +0 -679
  63. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +0 -526
  64. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +0 -357
  65. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +0 -803
  66. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +0 -290
  67. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +0 -270
  68. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +0 -65
  69. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +0 -109
  70. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +0 -202
  71. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +0 -88
  72. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +0 -328
  73. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +0 -97
  74. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +0 -480
  75. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +0 -20
  76. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +0 -55
  77. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +0 -381
  78. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +0 -517
  79. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +0 -155
  80. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +0 -245
  81. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +0 -246
  82. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +0 -121
  83. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +0 -825
  84. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +0 -393
  85. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +0 -107
  86. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +0 -1099
  87. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +0 -420
  88. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +0 -78
  89. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +0 -73
  90. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +0 -150
  91. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +0 -130
  92. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +0 -892
  93. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +0 -2798
  94. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +0 -626
  95. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +0 -231
  96. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +0 -128
  97. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +0 -104
  98. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +0 -543
  99. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +0 -127
  100. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +0 -166
  101. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +0 -222
  102. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +0 -580
  103. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +0 -336
  104. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +0 -355
  105. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +0 -36
  106. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +0 -594
  107. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +0 -265
  108. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +0 -1304
  109. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +0 -115
  110. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +0 -852
  111. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +0 -77
  112. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +0 -1595
  113. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +0 -1552
  114. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +0 -1259
  115. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +0 -156
  116. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +0 -1084
  117. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +0 -208
  118. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +0 -128
  119. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +0 -843
  120. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +0 -186
  121. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +0 -269
  122. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +0 -1562
  123. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +0 -584
  124. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +0 -23
  125. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +0 -388
  126. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +0 -512
  127. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +0 -95
  128. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +0 -414
  129. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +0 -597
  130. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +0 -62
  131. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +0 -50
  132. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +0 -358
  133. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +0 -171
  134. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +0 -550
  135. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +0 -889
  136. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +0 -597
  137. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +0 -199
  138. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +0 -236
  139. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +0 -617
  140. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +0 -145
  141. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +0 -540
  142. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +0 -1275
  143. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +0 -43
  144. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +0 -29
  145. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +0 -514
  146. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +0 -1344
  147. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +0 -650
  148. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +0 -167
  149. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +0 -608
  150. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +0 -64
  151. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +0 -246
  152. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +0 -1470
  153. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +0 -1498
  154. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +0 -210
  155. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +0 -1718
  156. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +0 -277
  157. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +0 -19
  158. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +0 -600
  159. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +0 -125
  160. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +0 -1446
  161. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +0 -576
  162. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +0 -1715
  163. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +0 -23
  164. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +0 -28
  165. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +0 -12
  166. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +0 -32
  167. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +0 -79
  168. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +0 -132
  169. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  170. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  171. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  172. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  173. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  174. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  175. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  176. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  177. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +0 -57
  178. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +0 -177
  179. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  180. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  181. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  182. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  183. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  184. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  185. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +0 -64
  186. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +0 -54
  187. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  188. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  189. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +0 -6
  190. package/.worktrees/2c37b1d7/.gitattributes +0 -2
  191. package/.worktrees/2c37b1d7/.husky/pre-push +0 -20
  192. package/.worktrees/2c37b1d7/README.md +0 -203
  193. package/.worktrees/2c37b1d7/SKILL.md +0 -91
  194. package/.worktrees/2c37b1d7/architecture-analysis.md +0 -448
  195. package/.worktrees/2c37b1d7/bin/sillyspec.js +0 -2
  196. package/.worktrees/2c37b1d7/eval/README.md +0 -86
  197. package/.worktrees/2c37b1d7/eval/eval.config.json +0 -28
  198. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +0 -63
  199. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +0 -27
  200. package/.worktrees/2c37b1d7/eval/lib/config.mjs +0 -82
  201. package/.worktrees/2c37b1d7/eval/lib/db.mjs +0 -76
  202. package/.worktrees/2c37b1d7/eval/lib/report.mjs +0 -120
  203. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +0 -157
  204. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +0 -73
  205. package/.worktrees/2c37b1d7/eval/lib/util.mjs +0 -107
  206. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +0 -30
  207. package/.worktrees/2c37b1d7/eval/run.mjs +0 -83
  208. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +0 -6
  209. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  210. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +0 -6
  211. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +0 -28
  212. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +0 -6
  213. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  214. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  215. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +0 -6
  216. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +0 -31
  217. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  218. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +0 -6
  219. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  220. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +0 -6
  221. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +0 -38
  222. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  223. package/.worktrees/2c37b1d7/package-lock.json +0 -977
  224. package/.worktrees/2c37b1d7/package.json +0 -41
  225. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  226. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  227. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  228. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +0 -16
  229. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  230. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +0 -836
  231. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +0 -256
  232. package/.worktrees/2c37b1d7/packages/dashboard/package.json +0 -25
  233. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +0 -95
  234. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +0 -679
  235. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +0 -526
  236. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +0 -357
  237. package/.worktrees/2c37b1d7/src/agent-session-log.js +0 -803
  238. package/.worktrees/2c37b1d7/src/change-list.js +0 -290
  239. package/.worktrees/2c37b1d7/src/change-risk-profile.js +0 -339
  240. package/.worktrees/2c37b1d7/src/check-primitives.js +0 -65
  241. package/.worktrees/2c37b1d7/src/classify-change.js +0 -109
  242. package/.worktrees/2c37b1d7/src/commit-suggest.js +0 -202
  243. package/.worktrees/2c37b1d7/src/config-cat.js +0 -88
  244. package/.worktrees/2c37b1d7/src/config-schema.js +0 -328
  245. package/.worktrees/2c37b1d7/src/constants.js +0 -97
  246. package/.worktrees/2c37b1d7/src/contract-matrix.js +0 -533
  247. package/.worktrees/2c37b1d7/src/datetime.js +0 -20
  248. package/.worktrees/2c37b1d7/src/db-engine.js +0 -55
  249. package/.worktrees/2c37b1d7/src/db.js +0 -381
  250. package/.worktrees/2c37b1d7/src/decision-distill.js +0 -517
  251. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +0 -155
  252. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +0 -245
  253. package/.worktrees/2c37b1d7/src/dispatch/probe.js +0 -246
  254. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +0 -121
  255. package/.worktrees/2c37b1d7/src/docs-check.js +0 -825
  256. package/.worktrees/2c37b1d7/src/docs-debt.js +0 -393
  257. package/.worktrees/2c37b1d7/src/docs-gate.js +0 -107
  258. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +0 -1099
  259. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +0 -409
  260. package/.worktrees/2c37b1d7/src/foreign-declared.js +0 -155
  261. package/.worktrees/2c37b1d7/src/fs-atomic.js +0 -73
  262. package/.worktrees/2c37b1d7/src/git-helper.js +0 -150
  263. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +0 -130
  264. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +0 -892
  265. package/.worktrees/2c37b1d7/src/index.js +0 -2854
  266. package/.worktrees/2c37b1d7/src/init.js +0 -626
  267. package/.worktrees/2c37b1d7/src/knowledge-match.js +0 -231
  268. package/.worktrees/2c37b1d7/src/local-detect.js +0 -128
  269. package/.worktrees/2c37b1d7/src/local-register.js +0 -104
  270. package/.worktrees/2c37b1d7/src/machine-interface.js +0 -543
  271. package/.worktrees/2c37b1d7/src/migrate.js +0 -127
  272. package/.worktrees/2c37b1d7/src/module-impact.js +0 -166
  273. package/.worktrees/2c37b1d7/src/module-resolve.js +0 -222
  274. package/.worktrees/2c37b1d7/src/modules.js +0 -580
  275. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +0 -126
  276. package/.worktrees/2c37b1d7/src/progress/change-registry.js +0 -336
  277. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +0 -355
  278. package/.worktrees/2c37b1d7/src/progress/shared.js +0 -36
  279. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +0 -594
  280. package/.worktrees/2c37b1d7/src/progress/step-store.js +0 -265
  281. package/.worktrees/2c37b1d7/src/progress.js +0 -1304
  282. package/.worktrees/2c37b1d7/src/quick-recommend.js +0 -115
  283. package/.worktrees/2c37b1d7/src/quicklog.js +0 -883
  284. package/.worktrees/2c37b1d7/src/review-tier.js +0 -77
  285. package/.worktrees/2c37b1d7/src/run/command.js +0 -1641
  286. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +0 -1552
  287. package/.worktrees/2c37b1d7/src/run/complete.js +0 -1259
  288. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +0 -156
  289. package/.worktrees/2c37b1d7/src/run/gates.js +0 -1111
  290. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +0 -208
  291. package/.worktrees/2c37b1d7/src/run/next.js +0 -128
  292. package/.worktrees/2c37b1d7/src/run/prompt.js +0 -843
  293. package/.worktrees/2c37b1d7/src/run/quick-audit.js +0 -186
  294. package/.worktrees/2c37b1d7/src/run/scan-profile.js +0 -269
  295. package/.worktrees/2c37b1d7/src/run/shared.js +0 -1562
  296. package/.worktrees/2c37b1d7/src/run/stage.js +0 -587
  297. package/.worktrees/2c37b1d7/src/run.js +0 -23
  298. package/.worktrees/2c37b1d7/src/scan-diff.js +0 -388
  299. package/.worktrees/2c37b1d7/src/scan-postcheck.js +0 -524
  300. package/.worktrees/2c37b1d7/src/scan-staleness.js +0 -95
  301. package/.worktrees/2c37b1d7/src/setup.js +0 -414
  302. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +0 -597
  303. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +0 -62
  304. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +0 -50
  305. package/.worktrees/2c37b1d7/src/spec-sync.js +0 -358
  306. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +0 -171
  307. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +0 -551
  308. package/.worktrees/2c37b1d7/src/stage-contract.js +0 -948
  309. package/.worktrees/2c37b1d7/src/stage-review.js +0 -597
  310. package/.worktrees/2c37b1d7/src/stages/archive.js +0 -199
  311. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +0 -285
  312. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +0 -624
  313. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +0 -145
  314. package/.worktrees/2c37b1d7/src/stages/doctor.js +0 -540
  315. package/.worktrees/2c37b1d7/src/stages/execute.js +0 -1277
  316. package/.worktrees/2c37b1d7/src/stages/explore.js +0 -43
  317. package/.worktrees/2c37b1d7/src/stages/index.js +0 -29
  318. package/.worktrees/2c37b1d7/src/stages/knowledge.js +0 -514
  319. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +0 -1398
  320. package/.worktrees/2c37b1d7/src/stages/plan.js +0 -655
  321. package/.worktrees/2c37b1d7/src/stages/quick.js +0 -167
  322. package/.worktrees/2c37b1d7/src/stages/scan.js +0 -608
  323. package/.worktrees/2c37b1d7/src/stages/status.js +0 -64
  324. package/.worktrees/2c37b1d7/src/stages/verify.js +0 -246
  325. package/.worktrees/2c37b1d7/src/sync.js +0 -1470
  326. package/.worktrees/2c37b1d7/src/task-review.js +0 -1498
  327. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +0 -21
  328. package/.worktrees/2c37b1d7/src/taskcard.js +0 -250
  329. package/.worktrees/2c37b1d7/src/verify-postcheck.js +0 -1718
  330. package/.worktrees/2c37b1d7/src/verify-probes.js +0 -327
  331. package/.worktrees/2c37b1d7/src/version.js +0 -19
  332. package/.worktrees/2c37b1d7/src/workflow.js +0 -600
  333. package/.worktrees/2c37b1d7/src/workspace.js +0 -125
  334. package/.worktrees/2c37b1d7/src/worktree-apply.js +0 -1611
  335. package/.worktrees/2c37b1d7/src/worktree-deps.js +0 -668
  336. package/.worktrees/2c37b1d7/src/worktree.js +0 -1849
  337. package/.worktrees/2c37b1d7/templates/claude-instruction.md +0 -23
  338. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +0 -29
  339. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +0 -12
  340. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +0 -32
  341. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +0 -79
  342. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +0 -132
  343. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  344. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  345. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  346. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  347. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  348. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  349. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  350. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  351. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +0 -57
  352. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +0 -177
  353. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  354. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  355. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  356. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  357. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  358. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +0 -64
  359. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +0 -54
  360. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  361. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  362. package/.worktrees/542c4415/.gitattributes +0 -2
  363. package/.worktrees/542c4415/.husky/pre-push +0 -20
  364. package/.worktrees/542c4415/README.md +0 -203
  365. package/.worktrees/542c4415/SKILL.md +0 -91
  366. package/.worktrees/542c4415/architecture-analysis.md +0 -448
  367. package/.worktrees/542c4415/bin/sillyspec.js +0 -2
  368. package/.worktrees/542c4415/eval/README.md +0 -86
  369. package/.worktrees/542c4415/eval/eval.config.json +0 -28
  370. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +0 -63
  371. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +0 -27
  372. package/.worktrees/542c4415/eval/lib/config.mjs +0 -82
  373. package/.worktrees/542c4415/eval/lib/db.mjs +0 -76
  374. package/.worktrees/542c4415/eval/lib/report.mjs +0 -120
  375. package/.worktrees/542c4415/eval/lib/runner.mjs +0 -157
  376. package/.worktrees/542c4415/eval/lib/tasks.mjs +0 -73
  377. package/.worktrees/542c4415/eval/lib/util.mjs +0 -107
  378. package/.worktrees/542c4415/eval/lib/workdir.mjs +0 -30
  379. package/.worktrees/542c4415/eval/run.mjs +0 -83
  380. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +0 -6
  381. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  382. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +0 -6
  383. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +0 -28
  384. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +0 -6
  385. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  386. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  387. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +0 -6
  388. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +0 -31
  389. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  390. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +0 -6
  391. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  392. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +0 -6
  393. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +0 -38
  394. package/.worktrees/542c4415/logo.jpg +0 -0
  395. package/.worktrees/542c4415/package-lock.json +0 -977
  396. package/.worktrees/542c4415/package.json +0 -41
  397. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  398. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  399. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  400. package/.worktrees/542c4415/packages/dashboard/dist/index.html +0 -16
  401. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  402. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +0 -836
  403. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +0 -256
  404. package/.worktrees/542c4415/packages/dashboard/package.json +0 -25
  405. package/.worktrees/542c4415/packages/dashboard/server/executor.js +0 -95
  406. package/.worktrees/542c4415/packages/dashboard/server/index.js +0 -679
  407. package/.worktrees/542c4415/packages/dashboard/server/parser.js +0 -526
  408. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +0 -357
  409. package/.worktrees/542c4415/src/agent-session-log.js +0 -803
  410. package/.worktrees/542c4415/src/change-list.js +0 -290
  411. package/.worktrees/542c4415/src/change-risk-profile.js +0 -339
  412. package/.worktrees/542c4415/src/check-primitives.js +0 -65
  413. package/.worktrees/542c4415/src/classify-change.js +0 -109
  414. package/.worktrees/542c4415/src/commit-suggest.js +0 -202
  415. package/.worktrees/542c4415/src/config-cat.js +0 -88
  416. package/.worktrees/542c4415/src/config-schema.js +0 -328
  417. package/.worktrees/542c4415/src/constants.js +0 -97
  418. package/.worktrees/542c4415/src/contract-matrix.js +0 -533
  419. package/.worktrees/542c4415/src/datetime.js +0 -20
  420. package/.worktrees/542c4415/src/db-engine.js +0 -55
  421. package/.worktrees/542c4415/src/db.js +0 -381
  422. package/.worktrees/542c4415/src/decision-distill.js +0 -517
  423. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +0 -155
  424. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +0 -245
  425. package/.worktrees/542c4415/src/dispatch/probe.js +0 -246
  426. package/.worktrees/542c4415/src/dispatch/strategy.js +0 -121
  427. package/.worktrees/542c4415/src/docs-check.js +0 -825
  428. package/.worktrees/542c4415/src/docs-debt.js +0 -393
  429. package/.worktrees/542c4415/src/docs-gate.js +0 -107
  430. package/.worktrees/542c4415/src/doctor-diagnostics.js +0 -1099
  431. package/.worktrees/542c4415/src/endpoint-extractor.js +0 -409
  432. package/.worktrees/542c4415/src/foreign-declared.js +0 -155
  433. package/.worktrees/542c4415/src/fs-atomic.js +0 -73
  434. package/.worktrees/542c4415/src/git-helper.js +0 -150
  435. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +0 -130
  436. package/.worktrees/542c4415/src/hooks/worktree-guard.js +0 -892
  437. package/.worktrees/542c4415/src/index.js +0 -2854
  438. package/.worktrees/542c4415/src/init.js +0 -626
  439. package/.worktrees/542c4415/src/knowledge-match.js +0 -231
  440. package/.worktrees/542c4415/src/local-detect.js +0 -128
  441. package/.worktrees/542c4415/src/local-register.js +0 -104
  442. package/.worktrees/542c4415/src/machine-interface.js +0 -543
  443. package/.worktrees/542c4415/src/migrate.js +0 -127
  444. package/.worktrees/542c4415/src/module-impact.js +0 -166
  445. package/.worktrees/542c4415/src/module-resolve.js +0 -222
  446. package/.worktrees/542c4415/src/modules.js +0 -580
  447. package/.worktrees/542c4415/src/plan-adopt-waves.js +0 -126
  448. package/.worktrees/542c4415/src/progress/change-registry.js +0 -336
  449. package/.worktrees/542c4415/src/progress/consistency-doctor.js +0 -355
  450. package/.worktrees/542c4415/src/progress/shared.js +0 -36
  451. package/.worktrees/542c4415/src/progress/stage-machine.js +0 -594
  452. package/.worktrees/542c4415/src/progress/step-store.js +0 -265
  453. package/.worktrees/542c4415/src/progress.js +0 -1304
  454. package/.worktrees/542c4415/src/quick-recommend.js +0 -115
  455. package/.worktrees/542c4415/src/quicklog.js +0 -883
  456. package/.worktrees/542c4415/src/review-tier.js +0 -77
  457. package/.worktrees/542c4415/src/run/command.js +0 -1641
  458. package/.worktrees/542c4415/src/run/complete-handlers.js +0 -1552
  459. package/.worktrees/542c4415/src/run/complete.js +0 -1259
  460. package/.worktrees/542c4415/src/run/concurrent-detect.js +0 -156
  461. package/.worktrees/542c4415/src/run/gates.js +0 -1111
  462. package/.worktrees/542c4415/src/run/multi-repo-context.js +0 -208
  463. package/.worktrees/542c4415/src/run/next.js +0 -128
  464. package/.worktrees/542c4415/src/run/prompt.js +0 -843
  465. package/.worktrees/542c4415/src/run/quick-audit.js +0 -186
  466. package/.worktrees/542c4415/src/run/scan-profile.js +0 -269
  467. package/.worktrees/542c4415/src/run/shared.js +0 -1562
  468. package/.worktrees/542c4415/src/run/stage.js +0 -587
  469. package/.worktrees/542c4415/src/run.js +0 -23
  470. package/.worktrees/542c4415/src/scan-diff.js +0 -388
  471. package/.worktrees/542c4415/src/scan-postcheck.js +0 -524
  472. package/.worktrees/542c4415/src/scan-staleness.js +0 -95
  473. package/.worktrees/542c4415/src/setup.js +0 -414
  474. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +0 -597
  475. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +0 -62
  476. package/.worktrees/542c4415/src/spec-dir-typo.js +0 -50
  477. package/.worktrees/542c4415/src/spec-sync.js +0 -358
  478. package/.worktrees/542c4415/src/stage-contract-engine.js +0 -171
  479. package/.worktrees/542c4415/src/stage-contract-spec.js +0 -551
  480. package/.worktrees/542c4415/src/stage-contract.js +0 -948
  481. package/.worktrees/542c4415/src/stage-review.js +0 -597
  482. package/.worktrees/542c4415/src/stages/archive.js +0 -199
  483. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +0 -285
  484. package/.worktrees/542c4415/src/stages/brainstorm.js +0 -624
  485. package/.worktrees/542c4415/src/stages/cmd-existence.js +0 -145
  486. package/.worktrees/542c4415/src/stages/doctor.js +0 -540
  487. package/.worktrees/542c4415/src/stages/execute.js +0 -1277
  488. package/.worktrees/542c4415/src/stages/explore.js +0 -43
  489. package/.worktrees/542c4415/src/stages/index.js +0 -29
  490. package/.worktrees/542c4415/src/stages/knowledge.js +0 -514
  491. package/.worktrees/542c4415/src/stages/plan-postcheck.js +0 -1398
  492. package/.worktrees/542c4415/src/stages/plan.js +0 -655
  493. package/.worktrees/542c4415/src/stages/quick.js +0 -167
  494. package/.worktrees/542c4415/src/stages/scan.js +0 -608
  495. package/.worktrees/542c4415/src/stages/status.js +0 -64
  496. package/.worktrees/542c4415/src/stages/verify.js +0 -246
  497. package/.worktrees/542c4415/src/sync.js +0 -1470
  498. package/.worktrees/542c4415/src/task-review.js +0 -1498
  499. package/.worktrees/542c4415/src/taskcard-placeholders.js +0 -21
  500. package/.worktrees/542c4415/src/taskcard.js +0 -250
  501. package/.worktrees/542c4415/src/verify-postcheck.js +0 -1718
  502. package/.worktrees/542c4415/src/verify-probes.js +0 -327
  503. package/.worktrees/542c4415/src/version.js +0 -19
  504. package/.worktrees/542c4415/src/workflow.js +0 -600
  505. package/.worktrees/542c4415/src/workspace.js +0 -125
  506. package/.worktrees/542c4415/src/worktree-apply.js +0 -1611
  507. package/.worktrees/542c4415/src/worktree-deps.js +0 -668
  508. package/.worktrees/542c4415/src/worktree.js +0 -1849
  509. package/.worktrees/542c4415/templates/claude-instruction.md +0 -23
  510. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +0 -29
  511. package/.worktrees/542c4415/templates/prompts/testcase-design.md +0 -12
  512. package/.worktrees/542c4415/templates/prompts/verify-probes.md +0 -32
  513. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +0 -79
  514. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +0 -132
  515. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  516. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  517. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  518. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  519. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  520. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  521. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  522. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  523. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +0 -57
  524. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +0 -177
  525. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  526. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  527. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  528. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  529. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  530. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  531. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +0 -64
  532. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +0 -54
  533. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  534. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  535. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +0 -6
  536. package/.worktrees/8d2d0392/.gitattributes +0 -2
  537. package/.worktrees/8d2d0392/.husky/pre-push +0 -20
  538. package/.worktrees/8d2d0392/README.md +0 -203
  539. package/.worktrees/8d2d0392/SKILL.md +0 -91
  540. package/.worktrees/8d2d0392/architecture-analysis.md +0 -448
  541. package/.worktrees/8d2d0392/bin/sillyspec.js +0 -2
  542. package/.worktrees/8d2d0392/eval/README.md +0 -86
  543. package/.worktrees/8d2d0392/eval/eval.config.json +0 -28
  544. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +0 -63
  545. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +0 -27
  546. package/.worktrees/8d2d0392/eval/lib/config.mjs +0 -82
  547. package/.worktrees/8d2d0392/eval/lib/db.mjs +0 -76
  548. package/.worktrees/8d2d0392/eval/lib/report.mjs +0 -120
  549. package/.worktrees/8d2d0392/eval/lib/runner.mjs +0 -157
  550. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +0 -73
  551. package/.worktrees/8d2d0392/eval/lib/util.mjs +0 -107
  552. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +0 -30
  553. package/.worktrees/8d2d0392/eval/run.mjs +0 -83
  554. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +0 -6
  555. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  556. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +0 -6
  557. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +0 -28
  558. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +0 -6
  559. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  560. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  561. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +0 -6
  562. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +0 -31
  563. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  564. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +0 -6
  565. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  566. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +0 -6
  567. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +0 -38
  568. package/.worktrees/8d2d0392/logo.jpg +0 -0
  569. package/.worktrees/8d2d0392/package-lock.json +0 -977
  570. package/.worktrees/8d2d0392/package.json +0 -41
  571. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  572. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  573. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  574. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +0 -16
  575. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  576. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +0 -836
  577. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +0 -256
  578. package/.worktrees/8d2d0392/packages/dashboard/package.json +0 -25
  579. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +0 -95
  580. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +0 -679
  581. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +0 -526
  582. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +0 -357
  583. package/.worktrees/8d2d0392/src/agent-session-log.js +0 -803
  584. package/.worktrees/8d2d0392/src/change-list.js +0 -290
  585. package/.worktrees/8d2d0392/src/change-risk-profile.js +0 -339
  586. package/.worktrees/8d2d0392/src/check-primitives.js +0 -65
  587. package/.worktrees/8d2d0392/src/classify-change.js +0 -109
  588. package/.worktrees/8d2d0392/src/commit-suggest.js +0 -202
  589. package/.worktrees/8d2d0392/src/config-cat.js +0 -88
  590. package/.worktrees/8d2d0392/src/config-schema.js +0 -328
  591. package/.worktrees/8d2d0392/src/constants.js +0 -97
  592. package/.worktrees/8d2d0392/src/contract-matrix.js +0 -533
  593. package/.worktrees/8d2d0392/src/datetime.js +0 -20
  594. package/.worktrees/8d2d0392/src/db-engine.js +0 -55
  595. package/.worktrees/8d2d0392/src/db.js +0 -381
  596. package/.worktrees/8d2d0392/src/decision-distill.js +0 -517
  597. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +0 -155
  598. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +0 -245
  599. package/.worktrees/8d2d0392/src/dispatch/probe.js +0 -246
  600. package/.worktrees/8d2d0392/src/dispatch/strategy.js +0 -121
  601. package/.worktrees/8d2d0392/src/docs-check.js +0 -825
  602. package/.worktrees/8d2d0392/src/docs-debt.js +0 -393
  603. package/.worktrees/8d2d0392/src/docs-gate.js +0 -107
  604. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +0 -1099
  605. package/.worktrees/8d2d0392/src/endpoint-extractor.js +0 -409
  606. package/.worktrees/8d2d0392/src/foreign-declared.js +0 -78
  607. package/.worktrees/8d2d0392/src/fs-atomic.js +0 -73
  608. package/.worktrees/8d2d0392/src/git-helper.js +0 -150
  609. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +0 -130
  610. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +0 -892
  611. package/.worktrees/8d2d0392/src/index.js +0 -2854
  612. package/.worktrees/8d2d0392/src/init.js +0 -626
  613. package/.worktrees/8d2d0392/src/knowledge-match.js +0 -231
  614. package/.worktrees/8d2d0392/src/local-detect.js +0 -128
  615. package/.worktrees/8d2d0392/src/local-register.js +0 -104
  616. package/.worktrees/8d2d0392/src/machine-interface.js +0 -543
  617. package/.worktrees/8d2d0392/src/migrate.js +0 -127
  618. package/.worktrees/8d2d0392/src/module-impact.js +0 -166
  619. package/.worktrees/8d2d0392/src/module-resolve.js +0 -222
  620. package/.worktrees/8d2d0392/src/modules.js +0 -580
  621. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +0 -126
  622. package/.worktrees/8d2d0392/src/progress/change-registry.js +0 -336
  623. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +0 -355
  624. package/.worktrees/8d2d0392/src/progress/shared.js +0 -36
  625. package/.worktrees/8d2d0392/src/progress/stage-machine.js +0 -594
  626. package/.worktrees/8d2d0392/src/progress/step-store.js +0 -265
  627. package/.worktrees/8d2d0392/src/progress.js +0 -1304
  628. package/.worktrees/8d2d0392/src/quick-recommend.js +0 -115
  629. package/.worktrees/8d2d0392/src/quicklog.js +0 -883
  630. package/.worktrees/8d2d0392/src/review-tier.js +0 -77
  631. package/.worktrees/8d2d0392/src/run/command.js +0 -1641
  632. package/.worktrees/8d2d0392/src/run/complete-handlers.js +0 -1552
  633. package/.worktrees/8d2d0392/src/run/complete.js +0 -1259
  634. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +0 -156
  635. package/.worktrees/8d2d0392/src/run/gates.js +0 -1094
  636. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +0 -208
  637. package/.worktrees/8d2d0392/src/run/next.js +0 -128
  638. package/.worktrees/8d2d0392/src/run/prompt.js +0 -843
  639. package/.worktrees/8d2d0392/src/run/quick-audit.js +0 -186
  640. package/.worktrees/8d2d0392/src/run/scan-profile.js +0 -269
  641. package/.worktrees/8d2d0392/src/run/shared.js +0 -1562
  642. package/.worktrees/8d2d0392/src/run/stage.js +0 -587
  643. package/.worktrees/8d2d0392/src/run.js +0 -23
  644. package/.worktrees/8d2d0392/src/scan-diff.js +0 -388
  645. package/.worktrees/8d2d0392/src/scan-postcheck.js +0 -524
  646. package/.worktrees/8d2d0392/src/scan-staleness.js +0 -95
  647. package/.worktrees/8d2d0392/src/setup.js +0 -414
  648. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +0 -597
  649. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +0 -62
  650. package/.worktrees/8d2d0392/src/spec-dir-typo.js +0 -50
  651. package/.worktrees/8d2d0392/src/spec-sync.js +0 -358
  652. package/.worktrees/8d2d0392/src/stage-contract-engine.js +0 -171
  653. package/.worktrees/8d2d0392/src/stage-contract-spec.js +0 -551
  654. package/.worktrees/8d2d0392/src/stage-contract.js +0 -948
  655. package/.worktrees/8d2d0392/src/stage-review.js +0 -597
  656. package/.worktrees/8d2d0392/src/stages/archive.js +0 -199
  657. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +0 -285
  658. package/.worktrees/8d2d0392/src/stages/brainstorm.js +0 -624
  659. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +0 -145
  660. package/.worktrees/8d2d0392/src/stages/doctor.js +0 -540
  661. package/.worktrees/8d2d0392/src/stages/execute.js +0 -1277
  662. package/.worktrees/8d2d0392/src/stages/explore.js +0 -43
  663. package/.worktrees/8d2d0392/src/stages/index.js +0 -29
  664. package/.worktrees/8d2d0392/src/stages/knowledge.js +0 -514
  665. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +0 -1398
  666. package/.worktrees/8d2d0392/src/stages/plan.js +0 -651
  667. package/.worktrees/8d2d0392/src/stages/quick.js +0 -167
  668. package/.worktrees/8d2d0392/src/stages/scan.js +0 -608
  669. package/.worktrees/8d2d0392/src/stages/status.js +0 -64
  670. package/.worktrees/8d2d0392/src/stages/verify.js +0 -246
  671. package/.worktrees/8d2d0392/src/sync.js +0 -1470
  672. package/.worktrees/8d2d0392/src/task-review.js +0 -1498
  673. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +0 -21
  674. package/.worktrees/8d2d0392/src/taskcard.js +0 -217
  675. package/.worktrees/8d2d0392/src/verify-postcheck.js +0 -1718
  676. package/.worktrees/8d2d0392/src/verify-probes.js +0 -327
  677. package/.worktrees/8d2d0392/src/version.js +0 -19
  678. package/.worktrees/8d2d0392/src/workflow.js +0 -600
  679. package/.worktrees/8d2d0392/src/workspace.js +0 -125
  680. package/.worktrees/8d2d0392/src/worktree-apply.js +0 -1611
  681. package/.worktrees/8d2d0392/src/worktree-deps.js +0 -576
  682. package/.worktrees/8d2d0392/src/worktree.js +0 -1838
  683. package/.worktrees/8d2d0392/templates/claude-instruction.md +0 -23
  684. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +0 -29
  685. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +0 -12
  686. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +0 -32
  687. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +0 -79
  688. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +0 -132
  689. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  690. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  691. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  692. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  693. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  694. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  695. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  696. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  697. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +0 -57
  698. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +0 -177
  699. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  700. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  701. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  702. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  703. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  704. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +0 -64
  705. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +0 -54
  706. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  707. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  708. package/.worktrees/c1eae35e/.gitattributes +0 -2
  709. package/.worktrees/c1eae35e/.husky/pre-push +0 -20
  710. package/.worktrees/c1eae35e/README.md +0 -203
  711. package/.worktrees/c1eae35e/SKILL.md +0 -91
  712. package/.worktrees/c1eae35e/architecture-analysis.md +0 -448
  713. package/.worktrees/c1eae35e/bin/sillyspec.js +0 -2
  714. package/.worktrees/c1eae35e/eval/README.md +0 -86
  715. package/.worktrees/c1eae35e/eval/eval.config.json +0 -28
  716. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +0 -63
  717. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +0 -27
  718. package/.worktrees/c1eae35e/eval/lib/config.mjs +0 -82
  719. package/.worktrees/c1eae35e/eval/lib/db.mjs +0 -76
  720. package/.worktrees/c1eae35e/eval/lib/report.mjs +0 -120
  721. package/.worktrees/c1eae35e/eval/lib/runner.mjs +0 -157
  722. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +0 -73
  723. package/.worktrees/c1eae35e/eval/lib/util.mjs +0 -107
  724. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +0 -30
  725. package/.worktrees/c1eae35e/eval/run.mjs +0 -83
  726. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +0 -6
  727. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  728. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +0 -6
  729. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +0 -28
  730. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +0 -6
  731. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  732. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  733. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +0 -6
  734. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +0 -31
  735. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  736. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +0 -6
  737. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  738. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +0 -6
  739. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +0 -38
  740. package/.worktrees/c1eae35e/logo.jpg +0 -0
  741. package/.worktrees/c1eae35e/package-lock.json +0 -977
  742. package/.worktrees/c1eae35e/package.json +0 -41
  743. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  744. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  745. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  746. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +0 -16
  747. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  748. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +0 -836
  749. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +0 -256
  750. package/.worktrees/c1eae35e/packages/dashboard/package.json +0 -25
  751. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +0 -95
  752. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +0 -679
  753. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +0 -526
  754. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +0 -357
  755. package/.worktrees/c1eae35e/src/agent-session-log.js +0 -803
  756. package/.worktrees/c1eae35e/src/change-list.js +0 -290
  757. package/.worktrees/c1eae35e/src/change-risk-profile.js +0 -339
  758. package/.worktrees/c1eae35e/src/check-primitives.js +0 -65
  759. package/.worktrees/c1eae35e/src/classify-change.js +0 -109
  760. package/.worktrees/c1eae35e/src/commit-suggest.js +0 -202
  761. package/.worktrees/c1eae35e/src/config-cat.js +0 -88
  762. package/.worktrees/c1eae35e/src/config-schema.js +0 -328
  763. package/.worktrees/c1eae35e/src/constants.js +0 -97
  764. package/.worktrees/c1eae35e/src/contract-matrix.js +0 -533
  765. package/.worktrees/c1eae35e/src/datetime.js +0 -20
  766. package/.worktrees/c1eae35e/src/db-engine.js +0 -55
  767. package/.worktrees/c1eae35e/src/db.js +0 -381
  768. package/.worktrees/c1eae35e/src/decision-distill.js +0 -517
  769. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +0 -155
  770. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +0 -245
  771. package/.worktrees/c1eae35e/src/dispatch/probe.js +0 -246
  772. package/.worktrees/c1eae35e/src/dispatch/strategy.js +0 -121
  773. package/.worktrees/c1eae35e/src/docs-check.js +0 -825
  774. package/.worktrees/c1eae35e/src/docs-debt.js +0 -393
  775. package/.worktrees/c1eae35e/src/docs-gate.js +0 -107
  776. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +0 -1099
  777. package/.worktrees/c1eae35e/src/endpoint-extractor.js +0 -409
  778. package/.worktrees/c1eae35e/src/foreign-declared.js +0 -155
  779. package/.worktrees/c1eae35e/src/fs-atomic.js +0 -73
  780. package/.worktrees/c1eae35e/src/git-helper.js +0 -150
  781. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +0 -130
  782. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +0 -892
  783. package/.worktrees/c1eae35e/src/index.js +0 -2854
  784. package/.worktrees/c1eae35e/src/init.js +0 -626
  785. package/.worktrees/c1eae35e/src/knowledge-match.js +0 -231
  786. package/.worktrees/c1eae35e/src/local-detect.js +0 -128
  787. package/.worktrees/c1eae35e/src/local-register.js +0 -104
  788. package/.worktrees/c1eae35e/src/machine-interface.js +0 -543
  789. package/.worktrees/c1eae35e/src/migrate.js +0 -127
  790. package/.worktrees/c1eae35e/src/module-impact.js +0 -166
  791. package/.worktrees/c1eae35e/src/module-resolve.js +0 -222
  792. package/.worktrees/c1eae35e/src/modules.js +0 -580
  793. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +0 -126
  794. package/.worktrees/c1eae35e/src/progress/change-registry.js +0 -336
  795. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +0 -355
  796. package/.worktrees/c1eae35e/src/progress/shared.js +0 -36
  797. package/.worktrees/c1eae35e/src/progress/stage-machine.js +0 -594
  798. package/.worktrees/c1eae35e/src/progress/step-store.js +0 -265
  799. package/.worktrees/c1eae35e/src/progress.js +0 -1304
  800. package/.worktrees/c1eae35e/src/quick-recommend.js +0 -115
  801. package/.worktrees/c1eae35e/src/quicklog.js +0 -883
  802. package/.worktrees/c1eae35e/src/review-tier.js +0 -77
  803. package/.worktrees/c1eae35e/src/run/command.js +0 -1641
  804. package/.worktrees/c1eae35e/src/run/complete-handlers.js +0 -1552
  805. package/.worktrees/c1eae35e/src/run/complete.js +0 -1259
  806. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +0 -156
  807. package/.worktrees/c1eae35e/src/run/gates.js +0 -1111
  808. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +0 -208
  809. package/.worktrees/c1eae35e/src/run/next.js +0 -128
  810. package/.worktrees/c1eae35e/src/run/prompt.js +0 -843
  811. package/.worktrees/c1eae35e/src/run/quick-audit.js +0 -186
  812. package/.worktrees/c1eae35e/src/run/scan-profile.js +0 -269
  813. package/.worktrees/c1eae35e/src/run/shared.js +0 -1562
  814. package/.worktrees/c1eae35e/src/run/stage.js +0 -587
  815. package/.worktrees/c1eae35e/src/run.js +0 -23
  816. package/.worktrees/c1eae35e/src/scan-diff.js +0 -388
  817. package/.worktrees/c1eae35e/src/scan-postcheck.js +0 -524
  818. package/.worktrees/c1eae35e/src/scan-staleness.js +0 -95
  819. package/.worktrees/c1eae35e/src/setup.js +0 -414
  820. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +0 -597
  821. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +0 -62
  822. package/.worktrees/c1eae35e/src/spec-dir-typo.js +0 -50
  823. package/.worktrees/c1eae35e/src/spec-sync.js +0 -358
  824. package/.worktrees/c1eae35e/src/stage-contract-engine.js +0 -171
  825. package/.worktrees/c1eae35e/src/stage-contract-spec.js +0 -551
  826. package/.worktrees/c1eae35e/src/stage-contract.js +0 -948
  827. package/.worktrees/c1eae35e/src/stage-review.js +0 -597
  828. package/.worktrees/c1eae35e/src/stages/archive.js +0 -199
  829. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +0 -285
  830. package/.worktrees/c1eae35e/src/stages/brainstorm.js +0 -624
  831. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +0 -145
  832. package/.worktrees/c1eae35e/src/stages/doctor.js +0 -540
  833. package/.worktrees/c1eae35e/src/stages/execute.js +0 -1277
  834. package/.worktrees/c1eae35e/src/stages/explore.js +0 -43
  835. package/.worktrees/c1eae35e/src/stages/index.js +0 -29
  836. package/.worktrees/c1eae35e/src/stages/knowledge.js +0 -514
  837. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +0 -1398
  838. package/.worktrees/c1eae35e/src/stages/plan.js +0 -655
  839. package/.worktrees/c1eae35e/src/stages/quick.js +0 -167
  840. package/.worktrees/c1eae35e/src/stages/scan.js +0 -608
  841. package/.worktrees/c1eae35e/src/stages/status.js +0 -64
  842. package/.worktrees/c1eae35e/src/stages/verify.js +0 -246
  843. package/.worktrees/c1eae35e/src/sync.js +0 -1470
  844. package/.worktrees/c1eae35e/src/task-review.js +0 -1498
  845. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +0 -21
  846. package/.worktrees/c1eae35e/src/taskcard.js +0 -250
  847. package/.worktrees/c1eae35e/src/verify-postcheck.js +0 -1718
  848. package/.worktrees/c1eae35e/src/verify-probes.js +0 -327
  849. package/.worktrees/c1eae35e/src/version.js +0 -19
  850. package/.worktrees/c1eae35e/src/workflow.js +0 -600
  851. package/.worktrees/c1eae35e/src/workspace.js +0 -125
  852. package/.worktrees/c1eae35e/src/worktree-apply.js +0 -1611
  853. package/.worktrees/c1eae35e/src/worktree-deps.js +0 -668
  854. package/.worktrees/c1eae35e/src/worktree.js +0 -1849
  855. package/.worktrees/c1eae35e/templates/claude-instruction.md +0 -23
  856. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +0 -29
  857. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +0 -12
  858. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +0 -32
  859. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +0 -79
  860. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +0 -132
  861. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  862. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  863. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  864. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  865. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  866. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  867. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  868. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  869. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +0 -57
  870. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +0 -177
  871. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  872. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  873. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  874. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  875. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  876. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  877. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +0 -64
  878. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +0 -54
  879. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  880. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  881. package/.worktrees/dafc71ad/.gitattributes +0 -2
  882. package/.worktrees/dafc71ad/.husky/pre-push +0 -20
  883. package/.worktrees/dafc71ad/README.md +0 -203
  884. package/.worktrees/dafc71ad/SKILL.md +0 -91
  885. package/.worktrees/dafc71ad/analysis.md +0 -366
  886. package/.worktrees/dafc71ad/architecture-analysis.md +0 -448
  887. package/.worktrees/dafc71ad/bin/sillyspec.js +0 -2
  888. package/.worktrees/dafc71ad/eval/README.md +0 -86
  889. package/.worktrees/dafc71ad/eval/eval.config.json +0 -28
  890. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +0 -63
  891. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +0 -27
  892. package/.worktrees/dafc71ad/eval/lib/config.mjs +0 -82
  893. package/.worktrees/dafc71ad/eval/lib/db.mjs +0 -76
  894. package/.worktrees/dafc71ad/eval/lib/report.mjs +0 -120
  895. package/.worktrees/dafc71ad/eval/lib/runner.mjs +0 -157
  896. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +0 -73
  897. package/.worktrees/dafc71ad/eval/lib/util.mjs +0 -107
  898. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +0 -30
  899. package/.worktrees/dafc71ad/eval/run.mjs +0 -83
  900. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +0 -6
  901. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  902. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +0 -6
  903. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +0 -28
  904. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +0 -6
  905. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  906. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  907. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +0 -6
  908. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +0 -31
  909. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  910. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +0 -6
  911. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  912. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +0 -6
  913. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +0 -38
  914. package/.worktrees/dafc71ad/logo.jpg +0 -0
  915. package/.worktrees/dafc71ad/package-lock.json +0 -977
  916. package/.worktrees/dafc71ad/package.json +0 -41
  917. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  918. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  919. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  920. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +0 -16
  921. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  922. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +0 -836
  923. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +0 -256
  924. package/.worktrees/dafc71ad/packages/dashboard/package.json +0 -25
  925. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +0 -95
  926. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +0 -679
  927. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +0 -526
  928. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +0 -357
  929. package/.worktrees/dafc71ad/src/agent-session-log.js +0 -803
  930. package/.worktrees/dafc71ad/src/change-list.js +0 -290
  931. package/.worktrees/dafc71ad/src/change-risk-profile.js +0 -339
  932. package/.worktrees/dafc71ad/src/check-primitives.js +0 -65
  933. package/.worktrees/dafc71ad/src/classify-change.js +0 -109
  934. package/.worktrees/dafc71ad/src/commit-suggest.js +0 -202
  935. package/.worktrees/dafc71ad/src/config-cat.js +0 -88
  936. package/.worktrees/dafc71ad/src/config-schema.js +0 -328
  937. package/.worktrees/dafc71ad/src/constants.js +0 -97
  938. package/.worktrees/dafc71ad/src/contract-matrix.js +0 -533
  939. package/.worktrees/dafc71ad/src/datetime.js +0 -20
  940. package/.worktrees/dafc71ad/src/db-engine.js +0 -55
  941. package/.worktrees/dafc71ad/src/db.js +0 -381
  942. package/.worktrees/dafc71ad/src/decision-distill.js +0 -517
  943. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +0 -155
  944. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +0 -245
  945. package/.worktrees/dafc71ad/src/dispatch/probe.js +0 -246
  946. package/.worktrees/dafc71ad/src/dispatch/strategy.js +0 -121
  947. package/.worktrees/dafc71ad/src/docs-check.js +0 -825
  948. package/.worktrees/dafc71ad/src/docs-debt.js +0 -393
  949. package/.worktrees/dafc71ad/src/docs-gate.js +0 -107
  950. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +0 -1099
  951. package/.worktrees/dafc71ad/src/endpoint-extractor.js +0 -409
  952. package/.worktrees/dafc71ad/src/foreign-declared.js +0 -155
  953. package/.worktrees/dafc71ad/src/fs-atomic.js +0 -73
  954. package/.worktrees/dafc71ad/src/git-helper.js +0 -150
  955. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +0 -130
  956. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +0 -892
  957. package/.worktrees/dafc71ad/src/index.js +0 -2854
  958. package/.worktrees/dafc71ad/src/init.js +0 -626
  959. package/.worktrees/dafc71ad/src/knowledge-match.js +0 -231
  960. package/.worktrees/dafc71ad/src/local-detect.js +0 -128
  961. package/.worktrees/dafc71ad/src/local-register.js +0 -104
  962. package/.worktrees/dafc71ad/src/machine-interface.js +0 -543
  963. package/.worktrees/dafc71ad/src/migrate.js +0 -127
  964. package/.worktrees/dafc71ad/src/module-impact.js +0 -166
  965. package/.worktrees/dafc71ad/src/module-resolve.js +0 -222
  966. package/.worktrees/dafc71ad/src/modules.js +0 -580
  967. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +0 -126
  968. package/.worktrees/dafc71ad/src/progress/change-registry.js +0 -336
  969. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +0 -355
  970. package/.worktrees/dafc71ad/src/progress/shared.js +0 -36
  971. package/.worktrees/dafc71ad/src/progress/stage-machine.js +0 -594
  972. package/.worktrees/dafc71ad/src/progress/step-store.js +0 -265
  973. package/.worktrees/dafc71ad/src/progress.js +0 -1304
  974. package/.worktrees/dafc71ad/src/quick-recommend.js +0 -115
  975. package/.worktrees/dafc71ad/src/quicklog.js +0 -883
  976. package/.worktrees/dafc71ad/src/review-tier.js +0 -77
  977. package/.worktrees/dafc71ad/src/run/command.js +0 -1641
  978. package/.worktrees/dafc71ad/src/run/complete-handlers.js +0 -1552
  979. package/.worktrees/dafc71ad/src/run/complete.js +0 -1259
  980. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +0 -156
  981. package/.worktrees/dafc71ad/src/run/gates.js +0 -1111
  982. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +0 -208
  983. package/.worktrees/dafc71ad/src/run/next.js +0 -128
  984. package/.worktrees/dafc71ad/src/run/prompt.js +0 -843
  985. package/.worktrees/dafc71ad/src/run/quick-audit.js +0 -186
  986. package/.worktrees/dafc71ad/src/run/scan-profile.js +0 -269
  987. package/.worktrees/dafc71ad/src/run/shared.js +0 -1562
  988. package/.worktrees/dafc71ad/src/run/stage.js +0 -587
  989. package/.worktrees/dafc71ad/src/run.js +0 -23
  990. package/.worktrees/dafc71ad/src/scan-diff.js +0 -388
  991. package/.worktrees/dafc71ad/src/scan-postcheck.js +0 -524
  992. package/.worktrees/dafc71ad/src/scan-staleness.js +0 -95
  993. package/.worktrees/dafc71ad/src/setup.js +0 -414
  994. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +0 -597
  995. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +0 -62
  996. package/.worktrees/dafc71ad/src/spec-dir-typo.js +0 -50
  997. package/.worktrees/dafc71ad/src/spec-sync.js +0 -358
  998. package/.worktrees/dafc71ad/src/stage-contract-engine.js +0 -171
  999. package/.worktrees/dafc71ad/src/stage-contract-spec.js +0 -551
  1000. package/.worktrees/dafc71ad/src/stage-contract.js +0 -948
  1001. package/.worktrees/dafc71ad/src/stage-review.js +0 -597
  1002. package/.worktrees/dafc71ad/src/stages/archive.js +0 -199
  1003. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +0 -285
  1004. package/.worktrees/dafc71ad/src/stages/brainstorm.js +0 -624
  1005. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +0 -145
  1006. package/.worktrees/dafc71ad/src/stages/doctor.js +0 -540
  1007. package/.worktrees/dafc71ad/src/stages/execute.js +0 -1277
  1008. package/.worktrees/dafc71ad/src/stages/explore.js +0 -43
  1009. package/.worktrees/dafc71ad/src/stages/index.js +0 -29
  1010. package/.worktrees/dafc71ad/src/stages/knowledge.js +0 -514
  1011. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +0 -1398
  1012. package/.worktrees/dafc71ad/src/stages/plan.js +0 -655
  1013. package/.worktrees/dafc71ad/src/stages/quick.js +0 -167
  1014. package/.worktrees/dafc71ad/src/stages/scan.js +0 -608
  1015. package/.worktrees/dafc71ad/src/stages/status.js +0 -64
  1016. package/.worktrees/dafc71ad/src/stages/verify.js +0 -246
  1017. package/.worktrees/dafc71ad/src/sync.js +0 -1470
  1018. package/.worktrees/dafc71ad/src/task-review.js +0 -1498
  1019. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +0 -21
  1020. package/.worktrees/dafc71ad/src/taskcard.js +0 -250
  1021. package/.worktrees/dafc71ad/src/verify-postcheck.js +0 -1718
  1022. package/.worktrees/dafc71ad/src/verify-probes.js +0 -327
  1023. package/.worktrees/dafc71ad/src/version.js +0 -19
  1024. package/.worktrees/dafc71ad/src/workflow.js +0 -600
  1025. package/.worktrees/dafc71ad/src/workspace.js +0 -125
  1026. package/.worktrees/dafc71ad/src/worktree-apply.js +0 -1611
  1027. package/.worktrees/dafc71ad/src/worktree-deps.js +0 -668
  1028. package/.worktrees/dafc71ad/src/worktree.js +0 -1849
  1029. package/.worktrees/dafc71ad/templates/claude-instruction.md +0 -23
  1030. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +0 -29
  1031. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +0 -12
  1032. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +0 -32
  1033. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +0 -79
  1034. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +0 -132
  1035. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  1036. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  1037. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  1038. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  1039. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  1040. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  1041. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  1042. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  1043. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +0 -57
  1044. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +0 -177
  1045. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  1046. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  1047. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  1048. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  1049. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  1050. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  1051. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +0 -64
  1052. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +0 -54
  1053. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  1054. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  1055. package/.worktrees/e58fcc4c/.gitattributes +0 -2
  1056. package/.worktrees/e58fcc4c/.husky/pre-push +0 -20
  1057. package/.worktrees/e58fcc4c/README.md +0 -203
  1058. package/.worktrees/e58fcc4c/SKILL.md +0 -91
  1059. package/.worktrees/e58fcc4c/architecture-analysis.md +0 -503
  1060. package/.worktrees/e58fcc4c/bin/sillyspec.js +0 -2
  1061. package/.worktrees/e58fcc4c/eval/README.md +0 -86
  1062. package/.worktrees/e58fcc4c/eval/eval.config.json +0 -28
  1063. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +0 -63
  1064. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +0 -27
  1065. package/.worktrees/e58fcc4c/eval/lib/config.mjs +0 -82
  1066. package/.worktrees/e58fcc4c/eval/lib/db.mjs +0 -76
  1067. package/.worktrees/e58fcc4c/eval/lib/report.mjs +0 -120
  1068. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +0 -157
  1069. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +0 -73
  1070. package/.worktrees/e58fcc4c/eval/lib/util.mjs +0 -107
  1071. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +0 -30
  1072. package/.worktrees/e58fcc4c/eval/run.mjs +0 -83
  1073. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +0 -6
  1074. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  1075. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +0 -6
  1076. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +0 -28
  1077. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +0 -6
  1078. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  1079. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  1080. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +0 -6
  1081. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +0 -31
  1082. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  1083. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +0 -6
  1084. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  1085. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +0 -6
  1086. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +0 -38
  1087. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  1088. package/.worktrees/e58fcc4c/package-lock.json +0 -977
  1089. package/.worktrees/e58fcc4c/package.json +0 -41
  1090. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  1091. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  1092. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  1093. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +0 -16
  1094. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  1095. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +0 -836
  1096. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +0 -256
  1097. package/.worktrees/e58fcc4c/packages/dashboard/package.json +0 -25
  1098. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +0 -95
  1099. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +0 -679
  1100. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +0 -526
  1101. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +0 -357
  1102. package/.worktrees/e58fcc4c/src/agent-session-log.js +0 -803
  1103. package/.worktrees/e58fcc4c/src/change-list.js +0 -290
  1104. package/.worktrees/e58fcc4c/src/change-risk-profile.js +0 -339
  1105. package/.worktrees/e58fcc4c/src/check-primitives.js +0 -65
  1106. package/.worktrees/e58fcc4c/src/classify-change.js +0 -109
  1107. package/.worktrees/e58fcc4c/src/commit-suggest.js +0 -202
  1108. package/.worktrees/e58fcc4c/src/config-cat.js +0 -88
  1109. package/.worktrees/e58fcc4c/src/config-schema.js +0 -328
  1110. package/.worktrees/e58fcc4c/src/constants.js +0 -97
  1111. package/.worktrees/e58fcc4c/src/contract-matrix.js +0 -533
  1112. package/.worktrees/e58fcc4c/src/datetime.js +0 -20
  1113. package/.worktrees/e58fcc4c/src/db-engine.js +0 -55
  1114. package/.worktrees/e58fcc4c/src/db.js +0 -381
  1115. package/.worktrees/e58fcc4c/src/decision-distill.js +0 -517
  1116. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +0 -155
  1117. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +0 -245
  1118. package/.worktrees/e58fcc4c/src/dispatch/probe.js +0 -246
  1119. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +0 -121
  1120. package/.worktrees/e58fcc4c/src/docs-check.js +0 -825
  1121. package/.worktrees/e58fcc4c/src/docs-debt.js +0 -393
  1122. package/.worktrees/e58fcc4c/src/docs-gate.js +0 -107
  1123. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +0 -1099
  1124. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +0 -409
  1125. package/.worktrees/e58fcc4c/src/foreign-declared.js +0 -155
  1126. package/.worktrees/e58fcc4c/src/fs-atomic.js +0 -73
  1127. package/.worktrees/e58fcc4c/src/git-helper.js +0 -150
  1128. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +0 -130
  1129. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +0 -892
  1130. package/.worktrees/e58fcc4c/src/index.js +0 -2854
  1131. package/.worktrees/e58fcc4c/src/init.js +0 -626
  1132. package/.worktrees/e58fcc4c/src/knowledge-match.js +0 -231
  1133. package/.worktrees/e58fcc4c/src/local-detect.js +0 -128
  1134. package/.worktrees/e58fcc4c/src/local-register.js +0 -104
  1135. package/.worktrees/e58fcc4c/src/machine-interface.js +0 -543
  1136. package/.worktrees/e58fcc4c/src/migrate.js +0 -127
  1137. package/.worktrees/e58fcc4c/src/module-impact.js +0 -166
  1138. package/.worktrees/e58fcc4c/src/module-resolve.js +0 -222
  1139. package/.worktrees/e58fcc4c/src/modules.js +0 -580
  1140. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +0 -126
  1141. package/.worktrees/e58fcc4c/src/progress/change-registry.js +0 -336
  1142. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +0 -355
  1143. package/.worktrees/e58fcc4c/src/progress/shared.js +0 -36
  1144. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +0 -594
  1145. package/.worktrees/e58fcc4c/src/progress/step-store.js +0 -265
  1146. package/.worktrees/e58fcc4c/src/progress.js +0 -1304
  1147. package/.worktrees/e58fcc4c/src/quick-recommend.js +0 -115
  1148. package/.worktrees/e58fcc4c/src/quicklog.js +0 -883
  1149. package/.worktrees/e58fcc4c/src/review-tier.js +0 -77
  1150. package/.worktrees/e58fcc4c/src/run/command.js +0 -1641
  1151. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +0 -1552
  1152. package/.worktrees/e58fcc4c/src/run/complete.js +0 -1259
  1153. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +0 -156
  1154. package/.worktrees/e58fcc4c/src/run/gates.js +0 -1111
  1155. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +0 -208
  1156. package/.worktrees/e58fcc4c/src/run/next.js +0 -128
  1157. package/.worktrees/e58fcc4c/src/run/prompt.js +0 -843
  1158. package/.worktrees/e58fcc4c/src/run/quick-audit.js +0 -186
  1159. package/.worktrees/e58fcc4c/src/run/scan-profile.js +0 -269
  1160. package/.worktrees/e58fcc4c/src/run/shared.js +0 -1562
  1161. package/.worktrees/e58fcc4c/src/run/stage.js +0 -587
  1162. package/.worktrees/e58fcc4c/src/run.js +0 -23
  1163. package/.worktrees/e58fcc4c/src/scan-diff.js +0 -388
  1164. package/.worktrees/e58fcc4c/src/scan-postcheck.js +0 -524
  1165. package/.worktrees/e58fcc4c/src/scan-staleness.js +0 -95
  1166. package/.worktrees/e58fcc4c/src/setup.js +0 -414
  1167. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +0 -597
  1168. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +0 -62
  1169. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +0 -50
  1170. package/.worktrees/e58fcc4c/src/spec-sync.js +0 -358
  1171. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +0 -171
  1172. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +0 -551
  1173. package/.worktrees/e58fcc4c/src/stage-contract.js +0 -948
  1174. package/.worktrees/e58fcc4c/src/stage-review.js +0 -597
  1175. package/.worktrees/e58fcc4c/src/stages/archive.js +0 -199
  1176. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +0 -285
  1177. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +0 -624
  1178. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +0 -145
  1179. package/.worktrees/e58fcc4c/src/stages/doctor.js +0 -540
  1180. package/.worktrees/e58fcc4c/src/stages/execute.js +0 -1277
  1181. package/.worktrees/e58fcc4c/src/stages/explore.js +0 -43
  1182. package/.worktrees/e58fcc4c/src/stages/index.js +0 -29
  1183. package/.worktrees/e58fcc4c/src/stages/knowledge.js +0 -514
  1184. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +0 -1398
  1185. package/.worktrees/e58fcc4c/src/stages/plan.js +0 -655
  1186. package/.worktrees/e58fcc4c/src/stages/quick.js +0 -167
  1187. package/.worktrees/e58fcc4c/src/stages/scan.js +0 -608
  1188. package/.worktrees/e58fcc4c/src/stages/status.js +0 -64
  1189. package/.worktrees/e58fcc4c/src/stages/verify.js +0 -246
  1190. package/.worktrees/e58fcc4c/src/sync.js +0 -1470
  1191. package/.worktrees/e58fcc4c/src/task-review.js +0 -1498
  1192. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +0 -21
  1193. package/.worktrees/e58fcc4c/src/taskcard.js +0 -250
  1194. package/.worktrees/e58fcc4c/src/verify-postcheck.js +0 -1718
  1195. package/.worktrees/e58fcc4c/src/verify-probes.js +0 -327
  1196. package/.worktrees/e58fcc4c/src/version.js +0 -19
  1197. package/.worktrees/e58fcc4c/src/workflow.js +0 -600
  1198. package/.worktrees/e58fcc4c/src/workspace.js +0 -125
  1199. package/.worktrees/e58fcc4c/src/worktree-apply.js +0 -1611
  1200. package/.worktrees/e58fcc4c/src/worktree-deps.js +0 -668
  1201. package/.worktrees/e58fcc4c/src/worktree.js +0 -1849
  1202. package/.worktrees/e58fcc4c/templates/claude-instruction.md +0 -23
  1203. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +0 -29
  1204. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +0 -12
  1205. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +0 -32
  1206. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +0 -79
  1207. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +0 -132
@@ -1,1398 +0,0 @@
1
- /**
2
- * Plan Postcheck 模块
3
- *
4
- * 从 run.js 和 plan.js 拆出的确定性校验逻辑:
5
- * - 拓扑排序(topoSortWaves)
6
- * - 蓝图一致性校验(validateBlueprintConsistency)
7
- * - plan 产物校验(validatePlanArtifacts)
8
- * - 执行入口(executePlanPostcheck)
9
- *
10
- * 这些都是 noAI 步骤,不需要 LLM 参与。
11
- */
12
- import { existsSync, readFileSync as _readFileSync, readdirSync, mkdtempSync, writeFileSync, rmSync } from 'fs'
13
- // 归一化行尾为 LF:Windows 下 python/编辑器文本模式写 .md 会产生 CRLF,致本模块多处
14
- // frontmatter/字段正则(`^---\n`、`allowed_paths:\s*\n…`、`^goal:` 等)失配,报「缺 frontmatter
15
- // /缺字段」假错误(见缺陷 windows-python-crlf-taskcard)。读取时统一转 LF,一处覆盖全部正则。
16
- const readFileSync = (filePath, encoding) => _readFileSync(filePath, encoding).replace(/\r\n/g, '\n')
17
- import { join as pJoin, basename } from 'path'
18
- import { tmpdir } from 'os'
19
- import jsYaml from 'js-yaml'
20
- import { parseFileChangeList, pathMatches } from '../change-list.js'
21
- import { getRule } from '../stage-contract-spec.js'
22
- import { TASKCARD_PLACEHOLDERS } from '../taskcard-placeholders.js'
23
- import { validateScriptCommands } from './cmd-existence.js'
24
-
25
- // ═══════════════════════════════════════════════════════════════
26
- // 解析工具(从 plan.js 迁移)
27
- // ═══════════════════════════════════════════════════════════════
28
-
29
- /**
30
- * 从 task-NN.md frontmatter 解析 depends_on 字段
31
- * @param {string} content - task 文件内容
32
- * @returns {string[]}
33
- */
34
- function parseDependsOn(content) {
35
- content = content.replace(/\r\n/g, '\n') // 外部调用方(worktree-apply 等)原生 readFileSync 喂 CRLF 时 ^---\n 锚点失配
36
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
37
- if (!fmMatch) return []
38
- const fm = fmMatch[1]
39
- const inlineMatch = fm.match(/depends_on:\s*\[([^\]]*)\]/)
40
- if (inlineMatch) {
41
- return inlineMatch[1].split(',').map(s => s.trim().replace(/['"]/g, '')).filter(Boolean)
42
- }
43
- // 块列表:列表项允许顶格或缩进([ \t]*,坑6——原 \s* 贪婪吃掉换行与前导空白,
44
- // 顶格 `depends_on:\n- task-01` 标准 YAML 写法永远失配,静默判「无依赖」)
45
- const blockMatch = fm.match(/depends_on:[ \t]*\n((?:[ \t]*-[ \t]+.+\n?)+)/)
46
- if (blockMatch) {
47
- return blockMatch[1].match(/[ \t]*-[ \t]+(.+)/g)?.map(s => s.replace(/^[ \t]*-[ \t]+/, '').trim().replace(/['"]/g, '')) || []
48
- }
49
- return []
50
- }
51
-
52
- /**
53
- * 解析 task-NN.md 的 task id(从 frontmatter 或文件名)
54
- * @param {string} content - task 文件内容
55
- * @param {string} filename - 文件名
56
- * @returns {string|null}
57
- */
58
- function parseTaskId(content, filename) {
59
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
60
- if (fmMatch) {
61
- const idMatch = fmMatch[1].match(/^id:\s*(.+)/m)
62
- if (idMatch) return idMatch[1].trim()
63
- }
64
- const fileMatch = filename.match(/(task-\d+)/i)
65
- return fileMatch ? fileMatch[1] : null
66
- }
67
-
68
- /**
69
- * 解析 task-NN.md 的 allowed_paths
70
- * @param {string} content
71
- * @returns {string[]}
72
- */
73
- export function parseAllowedPaths(content) {
74
- content = content.replace(/\r\n/g, '\n') // 同 parseDependsOn:入口归一,保护喂原始 CRLF 内容的外部调用方
75
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
76
- if (!fmMatch) return []
77
- const fm = fmMatch[1]
78
- const inlineMatch = fm.match(/allowed_paths:\s*\[([^\]]*)\]/)
79
- if (inlineMatch) {
80
- return inlineMatch[1].split(',').map(s => s.trim().replace(/['"`]/g, '')).filter(Boolean)
81
- }
82
- // 块列表:列表项允许顶格或缩进(坑6①——原 `\s*\n` 的 \s 贪婪匹配换行+前导空白,
83
- // 标准 YAML 块列表 `allowed_paths:\n- src/a.js`(顶格)永远失配,静默判「缺 allowed_paths」;
84
- // 缩进式 \s+- 恰可命中是巧合幸存。改 [ \t]*(不吃换行)+ 行内 [ \t]*-[ \t]+ 顶格缩进通吃)
85
- const blockMatch = fm.match(/allowed_paths:[ \t]*\n((?:[ \t]*-[ \t]+.+\n?)+)/)
86
- if (blockMatch) {
87
- // 剥首尾成对反引号(坑7 家族:`src/a.js` 整项以反引号开头时 js-yaml/正则路径带 ` 匹配失败报未覆盖;
88
- // 与 change-list.js 的 cell 归一化同语义——剥两端包裹引号,不动路径内部字符)
89
- return blockMatch[1].match(/[ \t]*-[ \t]+(.+)/g)?.map(s => {
90
- const raw = s.replace(/^[ \t]*-[ \t]+/, '').trim()
91
- return raw.replace(/^`([^`]*)`$/, '$1').replace(/^['"]|['"]$/g, '').trim()
92
- }).filter(Boolean) || []
93
- }
94
- return []
95
- }
96
-
97
- /**
98
- * 从 task-NN.md frontmatter 解析标量字段(repo / base_commit / head_commit)。
99
- * 复用 parseTaskContracts 的 frontmatter 提取 + js-yaml load 模式(标量可选字段,正则对引号/空值脆弱)。
100
- *
101
- * design §7.2 跨仓 task 卡 frontmatter 协议:
102
- * repo: sillyspec # 可选,缺省='main'(调用方视 null 为 main)
103
- * base_commit: <sha> # 可选,CLI 锡点写入(派发前落盘 base)
104
- * head_commit: <sha> # 可选,CLI 锡点写入(回收 review 前落盘 head)
105
- *
106
- * 缺省 / 空值 / 无 frontmatter → null(向后兼容旧 task 卡)。
107
- * @param {string} content - task 文件内容
108
- * @param {string} field - frontmatter 字段名
109
- * @returns {string|null}
110
- */
111
- function parseFrontmatterScalar(content, field) {
112
- content = content.replace(/\r\n/g, '\n') // 同 parseAllowedPaths:入口归一 CRLF
113
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
114
- if (!fmMatch) return null
115
- let fm
116
- try {
117
- fm = jsYaml.load(fmMatch[1]) || {}
118
- } catch {
119
- return null
120
- }
121
- const v = fm[field]
122
- if (v == null) return null
123
- const s = String(v).trim()
124
- return s === '' ? null : s
125
- }
126
-
127
- /**
128
- * 解析 task-NN.md frontmatter 的 repo 字段(跨仓 task 声明)。
129
- * 缺省=null(=main,调用方按主仓处理)。design §7.2 / D-001。
130
- * @param {string} content
131
- * @returns {string|null}
132
- */
133
- export function parseRepo(content) {
134
- return parseFrontmatterScalar(content, 'repo')
135
- }
136
-
137
- /**
138
- * 解析 task-NN.md frontmatter 的 base_commit 字段(CLI 派发跨仓 task 前落盘的 base 锡点)。
139
- * 缺省=null(未锡点 / 单仓 task)。design §7.2 / D-010。
140
- * @param {string} content
141
- * @returns {string|null}
142
- */
143
- export function parseBaseCommit(content) {
144
- return parseFrontmatterScalar(content, 'base_commit')
145
- }
146
-
147
- /**
148
- * 解析 task-NN.md frontmatter 的 head_commit 字段(CLI 回收 review 前落盘的 head 锡点)。
149
- * 缺省=null(未锡点 / 单仓 task)。design §7.2 / D-010。
150
- * @param {string} content
151
- * @returns {string|null}
152
- */
153
- export function parseHeadCommit(content) {
154
- return parseFrontmatterScalar(content, 'head_commit')
155
- }
156
-
157
- /**
158
- * 从 local.yaml 文本解析 repos: 段(跨仓 workspace 注册表)。
159
- * 与 parseLocalYamlModules 同风格(轻量行扫描,不引 yaml 依赖),结构 Map<repoKey, absolutePath>。
160
- *
161
- * design §7.3 local.yaml repos schema:
162
- * repos:
163
- * sillyspec: C:/Users/qinyi/IdeaProjects/sillyspec
164
- * # main 不用注册(隐式 = cwd / specRoot 父目录)
165
- *
166
- * 无 repos 段 / 空段 / 入参空 → 空 Map(单仓 change 不读,向后兼容)。
167
- *
168
- * **职责边界**:本函数只 parse local.yaml 文本,不读 local.yaml 文件(文件读取入口归
169
- * execute 启动 / task-09)。本函数不校验 declaredRepos ⊆ registry(D-007 fail-closed
170
- * 校验在 MultiRepoContext 构造时做)。
171
- * @param {string} yamlText
172
- * @returns {Map<string, string>} repoKey → absolutePath
173
- */
174
- export function parseRepoRegistry(yamlText) {
175
- const reg = new Map()
176
- if (!yamlText) return reg
177
- // CRLF 归一(坑 register-repo-crlf-idempotent-loop,2026-08-23 实证:Windows 下 agent Write
178
- // 工具/编辑器写出的 local.yaml 带 \r——条目正则 `(.*)$` 的 `.` 不匹配 \r、`$` 又要求真串尾,
179
- // 行尾残留 \r 时整条失配 → 空 Map → MultiRepoContext fail-closed 报「未注册」→ register-repo
180
- // 幂等跳过不落盘 → 死循环。同文件 parseAllowedPaths/parseDependsOn/parseBaseCommit 均有此
181
- // 归一,本函数是唯一缺口)
182
- const lines = String(yamlText).replace(/\r\n?/g, '\n').split('\n')
183
- let startIdx = -1
184
- for (let i = 0; i < lines.length; i++) {
185
- if (/^repos:\s*(?:#.*)?$/.test(lines[i])) { startIdx = i; break }
186
- }
187
- if (startIdx === -1) return reg
188
- for (let i = startIdx + 1; i < lines.length; i++) {
189
- const line = lines[i]
190
- // 遇到新的顶层 key(行首非空格且非注释)→ repos 段结束
191
- if (line.length > 0 && !line.startsWith(' ') && !line.startsWith('\t') && !line.startsWith('#') && line.trim() !== '') break
192
- // 条目格式: <key>: <value>(key 限 [A-Za-z0-9_.\-],与 parseLocalYamlModules 对齐)
193
- const entry = line.match(/^\s+([A-Za-z0-9_.\-]+):\s*(.*)$/)
194
- if (!entry) continue
195
- const value = (entry[2] || '').trim()
196
- if (value === '' || value.startsWith('#')) continue
197
- // 去可选行内注释(`value # comment`)—— 注意路径不含 ` #`,注释前必带空格
198
- const cleaned = value.replace(/\s+#.*$/, '').trim()
199
- if (cleaned === '') continue
200
- // 去首尾可选引号(YAML 字符串引用),保留路径内反斜杠原样
201
- const path = cleaned.replace(/^['"]|['"]$/g, '')
202
- if (path === '') continue
203
- reg.set(entry[1], path)
204
- }
205
- return reg
206
- }
207
-
208
- /**
209
- * 检查 task-NN.md 是否包含验收标准章节
210
- * @param {string} content
211
- * @returns {boolean}
212
- */
213
- function hasAcceptanceCriteria(content) {
214
- // 新模板把 goal/implementation/acceptance/verify/constraints 放在 frontmatter
215
- // (acceptance: 作为 fm 字段),老格式或人工写的卡片可能用 body 章节。
216
- // 两种都认,避免「模板格式」与「postcheck 判定」不一致导致卡片过不了校验。
217
- if (/^acceptance:/m.test(content)) return true
218
- return /##\s*验收标准/.test(content) || /##\s*Acceptance/.test(content)
219
- }
220
-
221
- /**
222
- * 检查 task-NN.md 是否包含 TDD/验证步骤
223
- * @param {string} content
224
- * @returns {boolean}
225
- */
226
- function hasTddOrVerify(content) {
227
- // 同 hasAcceptanceCriteria:新模板用 frontmatter 的 verify: 字段,老格式用 body 章节。
228
- if (/^verify:/m.test(content)) return true
229
- return /##\s*TDD/.test(content) || /##\s*验证/.test(content) || /##\s*Verify/.test(content)
230
- }
231
-
232
- /**
233
- * 解析 task-NN.md 的跨任务契约字段 provides / expects_from
234
- * 用 js-yaml 解析 frontmatter(嵌套结构,正则不可靠)。
235
- * provides/expects_from 为可选字段;缺失或解析失败时返回空(不阻断)。
236
- * @param {string} content - task 文件内容
237
- * @returns {{ provides: Array<{contract, fields}>, expectsFrom: Record<string, Array<{contract, needs}>> }}
238
- */
239
- export function parseTaskContracts(content) {
240
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
241
- if (!fmMatch) return { provides: [], expectsFrom: {} }
242
- let fm
243
- try {
244
- fm = jsYaml.load(fmMatch[1]) || {}
245
- } catch {
246
- // frontmatter 非合法 YAML(老格式/手写不规范)—— 当作无契约字段,不阻断
247
- return { provides: [], expectsFrom: {} }
248
- }
249
-
250
- const provides = Array.isArray(fm.provides)
251
- ? fm.provides.map(p => ({
252
- contract: String(p?.contract || ''),
253
- fields: Array.isArray(p?.fields) ? p.fields.map(String) : [],
254
- })).filter(p => p.contract)
255
- : []
256
-
257
- const expectsFrom = {}
258
- if (fm.expects_from && typeof fm.expects_from === 'object' && !Array.isArray(fm.expects_from)) {
259
- for (const [providerTask, contracts] of Object.entries(fm.expects_from)) {
260
- if (!Array.isArray(contracts)) continue
261
- expectsFrom[providerTask] = contracts
262
- .map(c => ({
263
- contract: String(c?.contract || ''),
264
- needs: Array.isArray(c?.needs) ? c.needs.map(String) : [],
265
- }))
266
- .filter(c => c.contract)
267
- }
268
- }
269
-
270
- return { provides, expectsFrom }
271
- }
272
-
273
- // ═══════════════════════════════════════════════════════════════
274
- // 核心逻辑
275
- // ═══════════════════════════════════════════════════════════════
276
-
277
- /**
278
- * 拓扑排序:根据 depends_on 计算波次
279
- * @param {Map<string, string[]>} depMap - taskId → depends_on list
280
- * @returns {{ waves: string[][], error: string|null }}
281
- */
282
- export function topoSortWaves(depMap) {
283
- const tasks = [...depMap.keys()]
284
- const waves = []
285
- const assigned = new Set()
286
- const visited = new Set()
287
-
288
- // 先做循环依赖检测(DFS)
289
- function hasCycle(task, path) {
290
- if (path.has(task)) return true
291
- if (visited.has(task)) return false
292
- path.add(task)
293
- const deps = depMap.get(task) || []
294
- for (const dep of deps) {
295
- if (!depMap.has(dep)) continue // 依赖不存在(可能是外部引用),跳过
296
- if (hasCycle(dep, path)) return true
297
- }
298
- path.delete(task)
299
- visited.add(task)
300
- return false
301
- }
302
- for (const task of tasks) {
303
- if (hasCycle(task, new Set())) {
304
- return { waves: [], error: `检测到循环依赖,涉及 task: ${task}` }
305
- }
306
- }
307
-
308
- // 逐层分配 Wave
309
- while (assigned.size < tasks.length) {
310
- const currentWave = []
311
- for (const task of tasks) {
312
- if (assigned.has(task)) continue
313
- const deps = (depMap.get(task) || []).filter(d => depMap.has(d))
314
- if (deps.every(d => assigned.has(d))) {
315
- currentWave.push(task)
316
- }
317
- }
318
- if (currentWave.length === 0) {
319
- const remaining = tasks.filter(t => !assigned.has(t))
320
- return { waves: [], error: `无法解析依赖关系,剩余 task: ${remaining.join(', ')}` }
321
- }
322
- for (const task of currentWave) {
323
- assigned.add(task)
324
- }
325
- waves.push(currentWave)
326
- }
327
-
328
- return { waves, error: null }
329
- }
330
-
331
- /**
332
- * 解析 plan.md 显式 Wave 分组 → Map<taskId, waveIndex>。
333
- *
334
- * Wave 口径与 execute.js parseWavesFromPlan 一致(execute 的真实并行单元,非 topoSort 建议值):
335
- * - `## Wave N` 标题下的 task-XX checkbox 归入 Wave N;
336
- * - 非 Wave 标题行(## 自检 等)退出当前 Wave 段,避免其 checkbox 混入。
337
- * 返回 null = plan.md 不存在或无显式 Wave 标题 → execute 会把所有 task 放进单个隐式 Wave
338
- * 全并行(execute.js:402-408),调用方据此判「同文件即冲突」。
339
- *
340
- * @param {string} planPath - plan.md 绝对路径
341
- * @returns {Map<string, number>|null} taskId → waveIndex;null = 无显式 Wave
342
- */
343
- function parseTaskWavesFromPlan(planPath) {
344
- if (!existsSync(planPath)) return null
345
- const content = readFileSync(planPath, 'utf8')
346
- if (!/^#+\s*Wave\s+\d+/im.test(content)) return null
347
- const map = new Map()
348
- let currentWave = null
349
- for (const line of content.split('\n')) {
350
- const wm = line.match(/^#+\s*Wave\s+(\d+)/i)
351
- if (wm) { currentWave = parseInt(wm[1], 10); continue }
352
- if (/^#+\s/.test(line)) { currentWave = null; continue } // 非 Wave 标题退出当前 Wave 段
353
- // 2026-08-20-task-truth-unify:Wave 段下为纯 ID 引用行(- task-XX);旧 checkbox 行同收
354
- // (旧变更读侧兼容——新格式由 validatePlanForExecute 拦旧形态,此处不重复把关)
355
- const tm = line.match(/^[-*]\s+(?:\[[ x]\]\s*)?(task-\d+)\s*[::\s]*$/i)
356
- || line.match(/^[-*]\s*\[[ x]\]\s*(task-\d+)\b/i)
357
- // id 归一补零(与卡片/注册表 task-01 口径一致,坑 wave-ref-unpadded):plan.md 写
358
- // `- task-1` 时裸用捕获原文做 key,永远匹配不到卡片 id task-01 → 被判「未列入任何
359
- // Wave」,同 Wave 共享文件检测静默跳过。execute.js parseWavesFromPlan 已补零,对齐。
360
- if (tm && currentWave !== null) map.set(String(tm[1]).replace(/^task-(\d+)$/i, (_, n) => `task-${n.padStart(2, '0')}`), currentWave)
361
- }
362
- return map
363
- }
364
-
365
- /**
366
- * 收集任务卡 depends_on → Map<taskId, deps>(Wave 重排 / plan-adopt-waves 共用)。
367
- * taskId 优先取卡内 frontmatter id:(与文件名解耦——文件名 task-01 但 id 改写过时以 id 为准)。
368
- * @param {string} tasksDir - changes/<name>/tasks 目录
369
- * @returns {Map<string, string[]>}
370
- */
371
- export function collectTaskDepMap(tasksDir) {
372
- const depMap = new Map()
373
- if (!existsSync(tasksDir)) return depMap
374
- for (const file of readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))) {
375
- const content = readFileSync(pJoin(tasksDir, file), 'utf8')
376
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
377
- let taskId = file.replace('.md', '')
378
- if (fmMatch) {
379
- const idMatch = fmMatch[1].match(/^id:\s*(.+)/m)
380
- if (idMatch) taskId = idMatch[1].trim()
381
- }
382
- depMap.set(taskId, parseDependsOn(content))
383
- }
384
- return depMap
385
- }
386
-
387
- /**
388
- * 本地一致性校验器
389
- * @param {string} changeDir - 变更目录
390
- * @returns {{ ok: boolean, errors: string[], warnings: string[] }}
391
- */
392
- export function validateBlueprintConsistency(changeDir) {
393
- const errors = []
394
- const warnings = []
395
-
396
- const tasksDir = pJoin(changeDir, 'tasks')
397
- if (!existsSync(tasksDir)) {
398
- return { ok: false, errors: ['tasks/ 目录不存在'], warnings }
399
- }
400
-
401
- const taskFiles = readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))
402
- if (taskFiles.length === 0) {
403
- return { ok: false, errors: ['tasks/ 目录下没有 task-NN.md 文件'], warnings }
404
- }
405
-
406
- // task 卡片基础字段文案从 manifest 同源(plan.task-card-structure);${id} 由下方 `${taskId} (${file})` 替换。
407
- const bsRule = getRule('plan.task-card-structure')
408
- const taskInfo = new Map()
409
- // pathOwners 按 (repo, path) 二元组聚合(design §5.3 约束③ / D-008):键 = `${repo}|${path}`,
410
- // repo 缺省='main'(parseRepo 返 null → main)。跨仓 task 与主仓 task 同名物理路径分属不同 repo
411
- // → 二元组键不同 → 不误判同 Wave 冲突(如主仓 src/task-review.js vs sillyspec src/task-review.js)。
412
- // ⚠️ 键分隔符 `|` 假设 repo 名与 path 均不含 `|`(repo 名约束 [A-Za-z0-9_.\-]、path 含 / \,极低概率含 |)。
413
- // value 结构 { repo, path, owners }:冲突文案对外仍显示纯 path(用户体验),内部按二元组判冲突。
414
- const pathOwners = new Map()
415
-
416
- for (const file of taskFiles) {
417
- const filePath = pJoin(tasksDir, file)
418
- const content = readFileSync(filePath, 'utf8')
419
- const taskId = parseTaskId(content, file)
420
- if (!taskId) {
421
- errors.push(`${file}: 无法解析 task id`)
422
- continue
423
- }
424
-
425
- const dependsOn = parseDependsOn(content)
426
- const allowedPaths = parseAllowedPaths(content)
427
- const hasAcceptance = hasAcceptanceCriteria(content)
428
- const hasTdd = hasTddOrVerify(content)
429
- // repo 缺省='main'(parseRepo 返 null → 单仓 task,与既有行为零回归)
430
- const repo = parseRepo(content) || 'main'
431
-
432
- taskInfo.set(taskId, { dependsOn, allowedPaths, hasAcceptance, hasTdd, file })
433
-
434
- if (allowedPaths.length === 0) {
435
- errors.push(bsRule.data.messageAllowedPaths.replaceAll('${id}', `${taskId} (${file})`))
436
- }
437
- if (!hasAcceptance) {
438
- errors.push(bsRule.data.messageAcceptance.replaceAll('${id}', `${taskId} (${file})`))
439
- }
440
- if (!hasTdd) {
441
- warnings.push(bsRule.data.messageTdd.replaceAll('${id}', `${taskId} (${file})`))
442
- }
443
-
444
- for (const p of allowedPaths) {
445
- const key = `${repo}|${p}`
446
- if (!pathOwners.has(key)) pathOwners.set(key, { repo, path: p, owners: [] })
447
- pathOwners.get(key).owners.push(taskId)
448
- }
449
- }
450
-
451
- // 路径冲突(Wave 感知):同 repo 同 Wave 内 >1 task 共享 allowed_path → execute 强制并行(execute.js:603)
452
- // 子代理会互相覆盖该文件 → error。跨 Wave 同文件 → 串行执行安全 → warning。
453
- // 按 (repo, path) 二元组判冲突(约束③):跨仓 task 与主仓 task 同名路径不误判(不同 repo → 不同键)。
454
- // Wave 口径 = plan.md 显式 `## Wave N`(parseTaskWavesFromPlan,与 execute 同源,非 topoSort 建议值);
455
- // plan.md 无显式 Wave → execute 全并行(隐式单 Wave,execute.js:402-408)→ 同 repo 同文件即冲突。
456
- const waveOfTask = parseTaskWavesFromPlan(pJoin(changeDir, 'plan.md'))
457
- for (const [, { repo, path: p, owners }] of pathOwners) {
458
- if (owners.length < 2) continue
459
- if (waveOfTask === null) {
460
- errors.push(
461
- `路径 ${p} 被 ${owners.length} 个 task 修改: ${owners.join(', ')} — plan.md 无显式 Wave 划分,` +
462
- `execute 会把它们放进同一隐式 Wave 全并行(execute.js:402-408),子代理互相覆盖。` +
463
- `解法:拆到不同 Wave(串行),或合并为单个 task。`
464
- )
465
- continue
466
- }
467
- // 显式 Wave:按 wave 分组 owners,找同 Wave 冲突
468
- const byWave = new Map()
469
- for (const t of owners) {
470
- const w = waveOfTask.get(t)
471
- if (w === undefined) continue // 未列入任何 Wave → execute 不执行,不参与冲突判定
472
- if (!byWave.has(w)) byWave.set(w, [])
473
- byWave.get(w).push(t)
474
- }
475
- for (const [w, ts] of byWave) {
476
- if (ts.length > 1) {
477
- errors.push(
478
- `路径 ${p} 被 Wave ${w} 内 ${ts.length} 个 task 修改: ${ts.join(', ')} — 同 Wave 任务 execute 强制并行(execute.js:603),` +
479
- `子代理会互相覆盖该文件。解法:把它们拆到不同 Wave(串行)。` +
480
- `(注:quick 阶段对同文件并发只提示不阻断——那是轻量流程无并行子代理、最坏后果 git 可分离;` +
481
- `此处硬拦是因并行覆盖不可自动恢复,两阶段宽严不同是设计使然)`
482
- )
483
- }
484
- }
485
- // 跨 Wave 共享:串行安全,仅提示
486
- if (byWave.size > 1) {
487
- warnings.push(`路径 ${p} 跨 Wave 被修改: ${owners.join(', ')}(不同 Wave 串行执行,安全;确认是否有意共享)`)
488
- }
489
- }
490
-
491
- // 任务声明 ↔ tasks/ 卡片双向对账(债单 D-2b;2026-08-20-task-truth-unify:声明源迁 tasks.md 注册表):
492
- // 注册表列 17 任务只出 12 卡(尾部文档同步类任务漏卡)时,无卡任务不进 Wave、
493
- // 不受 execute 审计 → 零失败信号漏做。口径与 execute.js parseTaskRegistry 一致
494
- // (`- [ ] task-NN` checkbox 行;file 命名 task-NN.md + 卡内 id task-NN 均取,缺一即漏卡)。
495
- const planMdPath = pJoin(changeDir, 'plan.md')
496
- const declaredIds = new Set()
497
- const tasksMdPath = pJoin(changeDir, 'tasks.md')
498
- if (existsSync(tasksMdPath)) {
499
- for (const line of readFileSync(tasksMdPath, 'utf8').split('\n')) {
500
- const m = line.match(/^[-*]\s*\[[ x]\]\s*(task-\d+)\b/i)
501
- if (m) declaredIds.add(m[1].toLowerCase())
502
- }
503
- }
504
- if (declaredIds.size === 0 && existsSync(planMdPath)) {
505
- // 兼容读侧:tasks.md 缺失/无声明时回退解析 plan.md 旧 checkbox 声明(旧归档变更)
506
- for (const line of readFileSync(planMdPath, 'utf8').split('\n')) {
507
- const m = line.match(/^[-*]\s*\[[ x]\]\s*(task-\d+)\b/i)
508
- if (m) declaredIds.add(m[1].toLowerCase())
509
- }
510
- }
511
- if (declaredIds.size > 0) {
512
- const tprRule = getRule('plan.task-plan-reconciliation')
513
- const cardIds = new Set([...taskInfo.keys()].map(id => id.toLowerCase()))
514
- const missing = [...declaredIds].filter(id => !cardIds.has(id))
515
- if (missing.length > 0) {
516
- errors.push(
517
- tprRule.data.messageMissingCards
518
- .replaceAll('${declared}', declaredIds.size)
519
- .replaceAll('${missing}', missing.join(', '))
520
- )
521
- }
522
- const orphans = [...cardIds].filter(id => !declaredIds.has(id))
523
- if (orphans.length > 0) {
524
- errors.push(
525
- tprRule.data.messageOrphanCards.replaceAll('${orphans}', orphans.join(', '))
526
- )
527
- }
528
- }
529
- // declaredIds.size === 0:注册表无 task 声明(极端格式)→ 跳过对账,
530
- // 由 validatePlanArtifacts/validatePlanForExecute 把关,不在此误伤。
531
-
532
- // 拓扑排序 + 循环依赖
533
- const depMap = new Map()
534
- for (const [taskId, info] of taskInfo) {
535
- depMap.set(taskId, info.dependsOn)
536
- }
537
- const { error: topoError } = topoSortWaves(depMap)
538
- if (topoError) {
539
- errors.push(topoError)
540
- }
541
-
542
- return { ok: errors.length === 0, errors, warnings }
543
- }
544
-
545
- /**
546
- * 跨任务契约校验器:对账 consumer.expects_from ↔ provider.provides
547
- *
548
- * 修复场景:consumer task 声明期望 provider 产出某 DTO 的某字段,
549
- * 但 provider 的 provides 未承诺(或字段缺失)→ plan 阶段阻断,
550
- * 避免到 execute/verify 才暴露(典型表现:前端 fallback 错误字段 → 403/500)。
551
- *
552
- * provides / expects_from 均为可选字段:未声明时不校验(向后兼容)。
553
- * @param {string} changeDir - 变更目录
554
- * @returns {{ ok: boolean, errors: string[], warnings: string[] }}
555
- */
556
- export function validateCrossTaskContracts(changeDir) {
557
- const errors = []
558
- const warnings = []
559
-
560
- const tasksDir = pJoin(changeDir, 'tasks')
561
- if (!existsSync(tasksDir)) {
562
- return { ok: true, errors, warnings }
563
- }
564
-
565
- const taskFiles = readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))
566
- if (taskFiles.length === 0) {
567
- return { ok: true, errors, warnings }
568
- }
569
-
570
- // 第一遍:收集每个 task 的 provides(taskId → Map(contract → Set(fields)))
571
- const providesByTask = new Map()
572
- for (const file of taskFiles) {
573
- const content = readFileSync(pJoin(tasksDir, file), 'utf8')
574
- const taskId = parseTaskId(content, file)
575
- if (!taskId) continue
576
- const { provides } = parseTaskContracts(content)
577
- const contractMap = new Map()
578
- for (const p of provides) {
579
- contractMap.set(p.contract, new Set(p.fields))
580
- }
581
- providesByTask.set(taskId, contractMap)
582
- }
583
-
584
- // 第二遍:校验每个 consumer 的 expects_from 是否被 provider.provides 覆盖。
585
- // 3 种断裂文案(unknown-provider / undeclared / missing-fields)从 manifest 同源
586
- // (plan.cross-task-contract.data),${consumer}/${provider}/${contract}/${needs}/${available} replaceAll。
587
- const ctRule = getRule('plan.cross-task-contract')
588
- const renderCtMsg = (tmpl, consumer, provider, contract, needs, available) => tmpl
589
- .replaceAll('${consumer}', consumer)
590
- .replaceAll('${provider}', provider)
591
- .replaceAll('${contract}', contract)
592
- .replaceAll('${needs}', needs)
593
- .replaceAll('${available}', available)
594
- for (const file of taskFiles) {
595
- const content = readFileSync(pJoin(tasksDir, file), 'utf8')
596
- const consumerId = parseTaskId(content, file)
597
- if (!consumerId) continue
598
- const { expectsFrom } = parseTaskContracts(content)
599
-
600
- for (const [providerTask, contracts] of Object.entries(expectsFrom)) {
601
- if (!providesByTask.has(providerTask)) {
602
- for (const c of contracts) {
603
- errors.push(renderCtMsg(ctRule.data.messageUnknownProvider, consumerId, providerTask, c.contract, c.needs.join(', '), ''))
604
- }
605
- continue
606
- }
607
-
608
- const providerContracts = providesByTask.get(providerTask)
609
- for (const c of contracts) {
610
- const providerFields = providerContracts.get(c.contract)
611
- if (providerFields === undefined) {
612
- errors.push(renderCtMsg(ctRule.data.messageUndeclaredContract, consumerId, providerTask, c.contract, c.needs.join(', '), ''))
613
- continue
614
- }
615
- const missing = c.needs.filter(f => !providerFields.has(f))
616
- if (missing.length > 0) {
617
- errors.push(renderCtMsg(ctRule.data.messageMissingFields, consumerId, providerTask, c.contract, missing.join(', '), [...providerFields].join(', ')))
618
- }
619
- }
620
- }
621
- }
622
-
623
- return { ok: errors.length === 0, errors, warnings }
624
- }
625
-
626
- /**
627
- * 从 local.yaml 文本解析 modules 块(monorepo 子包定位)。
628
- *
629
- * 与 verify-postcheck.extractModules 同风格(轻量行扫描,不引 yaml 依赖),不复用是为避免
630
- * plan-postcheck → verify-postcheck → contract-matrix → plan-postcheck 的循环导入。
631
- * 只取 path 字段(test 字段此处用不到),结构 { name: { path } }。
632
- *
633
- * modules:
634
- * backend: { path: "backend/", test: "cd backend && uv run pytest" }
635
- *
636
- * @param {string} yamlText
637
- * @returns {Record<string, {path:string}>|null} 无 modules 块或无有效条目 → null
638
- */
639
- export function parseLocalYamlModules(yamlText) {
640
- if (!yamlText) return null
641
- const lines = yamlText.split('\n')
642
- let startIdx = -1
643
- for (let i = 0; i < lines.length; i++) {
644
- if (/^modules:\s*(?:#.*)?$/.test(lines[i])) { startIdx = i; break }
645
- }
646
- if (startIdx === -1) return null
647
- const modules = {}
648
- for (let i = startIdx + 1; i < lines.length; i++) {
649
- const line = lines[i]
650
- const entry = line.match(/^([ \t]+)([A-Za-z0-9_.\-]+):\s*(.*)$/)
651
- if (!entry) {
652
- // 遇到新的顶层 key(行首非空格且非注释)→ modules 块结束
653
- if (line.length > 0 && !line.startsWith(' ') && !line.startsWith('#') && line.trim() !== '') break
654
- continue
655
- }
656
- // 条目缩进放宽为「任意非零空白」(坑 modules-indent-hardcoded):此前硬编码恰 2 空格,
657
- // 4 空格/Tab 缩进的条目不匹配且不触发块结束 → 被静默跳过 → modules 丢失 →
658
- // validateScriptCommands 退化为只查根 package.json,monorepo 子包命令被误报不存在。
659
- const rest = entry[3] || ''
660
- // path 值:带引号或不带引号(flow mapping),取第一个匹配
661
- const pathMatch = rest.match(/path:\s*"([^"]+)"/) || rest.match(/path:\s*([^,\s}]+)/)
662
- if (pathMatch) modules[entry[2]] = { path: pathMatch[1] }
663
- }
664
- return Object.keys(modules).length > 0 ? modules : null
665
- }
666
-
667
- /**
668
- * TaskCard 命令存在性校验器(调共享 validateScriptCommands,硬阻断)。
669
- *
670
- * 修复场景(design D-04 / 问题 3):TaskCard verify/implementation 写 `pnpm gen:types`
671
- * 但根 package.json 无此 script(实际在 monorepo 子包 packages 目录下),plan 阶段零校验
672
- * → execute 子代理跑死命令。scan-postcheck 的命令校验只看 local.yaml 且维持 warning;
673
- * 本函数对 TaskCard 升 error(同 helper、严重度由调用方定)。
674
- *
675
- * modules 从 local.yaml 提取(monorepo 子包感知):无 modules 块时仅查根 package.json
676
- * (与 scan-postcheck 历史行为一致);有 modules 块时多候选子包 package.json 任一命中即通过。
677
- *
678
- * @param {string} changeDir - 变更目录
679
- * @param {string} projectRoot - 项目根目录(package.json 查找基准)
680
- * @param {object|null} modules - local.yaml modules 块({ name: { path } }),可选
681
- * @returns {{ ok: boolean, errors: string[], warnings: string[] }}
682
- */
683
- export function validateTaskCommands(changeDir, projectRoot, modules = null) {
684
- const errors = []
685
- const warnings = []
686
-
687
- const tasksDir = pJoin(changeDir, 'tasks')
688
- if (!existsSync(tasksDir)) {
689
- return { ok: true, errors, warnings }
690
- }
691
- const taskFiles = readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))
692
- if (taskFiles.length === 0) {
693
- return { ok: true, errors, warnings }
694
- }
695
-
696
- for (const file of taskFiles) {
697
- const content = readFileSync(pJoin(tasksDir, file), 'utf8')
698
- const taskId = parseTaskId(content, file) || file
699
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
700
- if (!fmMatch) continue // feasibility 已报 frontmatter 缺失,不重复
701
- let fm
702
- try {
703
- fm = jsYaml.load(fmMatch[1]) || {}
704
- } catch {
705
- continue // 非法 YAML 由 feasibility 处理,不重复
706
- }
707
-
708
- // 合并 verify + implementation 文本(命令可能出现在任一字段)。
709
- // 字段两形态都收(坑 taskcard-block-list-noop):规范格式(taskcard.js 骨架 / plan 模板)的
710
- // verify/implementation 是 YAML 块列表 → js-yaml 解析为数组;此前只收 string,规范卡片
711
- // 恒落空 → 「命令存在性校验」(hard-error)对合规 TaskCard 整体 no-op,只有违规写成
712
- // 纯标量的卡片才被校验。数组按行 join 回文本,与标量同管道。
713
- const toCmdText = (v) => Array.isArray(v) ? v.map(String).join('\n') : (typeof v === 'string' ? v : '')
714
- const verifyText = toCmdText(fm.verify)
715
- const implText = toCmdText(fm.implementation)
716
- const text = `${verifyText}\n${implText}`
717
- if (!text.trim()) continue
718
-
719
- const { invalid } = validateScriptCommands(text, { projectRoot, modules })
720
- for (const inv of invalid) {
721
- errors.push(`${taskId}: ${inv.cmd} 命令不存在(${inv.reason})`)
722
- }
723
- }
724
-
725
- return { ok: errors.length === 0, errors, warnings }
726
- }
727
-
728
- // 路径容差匹配(normalizePath / globMatch / pathMatches)复用自 change-list.js,
729
- // design 清单解析与 allowed_paths 对账共用同一套匹配语义,避免两处逻辑漂移。
730
-
731
- /**
732
- * design §6 按仓分段段头识别(D-014):`## <repo> 仓变更`(如 `## sillyspec 仓变更`)。
733
- * 段头为 h2,repo 名取段头首 token(去空白/编号前缀)。容忍可选编号前缀与尾随空白/冒号。
734
- * 不命中(非仓变更段头)→ null。
735
- */
736
- const REPO_SECTION_HEADER_RE = /^#{2,3}\s+(?:\d+[.)]\s*)?([A-Za-z0-9_.\-]+)\s*仓变更\s*[::]?\s*$/
737
-
738
- /**
739
- * design §6 文件清单章节标题(与 change-list.js FILE_LIST_SECTION_RE 同源,避免 import 私有常量)。
740
- * 容忍可选编号前缀(`## 6. 文件变更清单`),与 change-list 解析口径一致。
741
- */
742
- const FILE_LIST_SECTION_RE = /^#{2,3}\s*(?:\d+[.)]\s*)?(文件变更清单|变更文件清单|文件清单|File Changes|Files to Change)/im
743
-
744
- /**
745
- * 按 repo 解析 design §6 文件清单(约束③ / D-014)。
746
- *
747
- * 支持 design §6 按仓分段:`## <repo> 仓变更` 段头下的路径归该 repo;无段头时整章节归 'main'
748
- * (向后兼容单仓 design,与原 parseFileChangeList 行为等价)。段内路径解析复用 parseFileChangeList
749
- * (表格列定位 / exclude 子段 / 占位符过滤 / CRLF 容错全部继承,零漂移)——方法是:把每段内容包成
750
- * 临时 design 文件(前置标准 `## 文件变更清单` 标题),写 OS tmp 调 parseFileChangeList,立即清理。
751
- *
752
- * 为什么不复用单次 parseFileChangeList:change-list.js 的通用 parser 把段头 `## <repo> 仓变更`
753
- * 当成「下一个 ## 章节」截断主章节(line 173 `^##\s`),跨仓段路径会丢——这正是 task-03 要修的。
754
- *
755
- * 返回值结构(与 pathOwners 二元组对齐):
756
- * Map<repo, Set<path>> —— 每个 repo 的 design 清单路径集
757
- * 外加 _hasSegmentHeader 标记(调用方据此决定是否走分段对账路径)
758
- *
759
- * @param {string} designPath - design.md 绝对路径
760
- * @returns {{ byRepo: Map<string, Set<string>>, hasSegmentHeader: boolean, allFiles: string[] }}
761
- */
762
- function parseDesignCoverageByRepo(designPath) {
763
- const byRepo = new Map()
764
- const allFiles = []
765
- if (!designPath || !existsSync(designPath)) {
766
- return { byRepo, hasSegmentHeader: false, allFiles }
767
- }
768
- const content = readFileSync(designPath, 'utf8')
769
-
770
- const sectionMatch = content.match(FILE_LIST_SECTION_RE)
771
- if (!sectionMatch) {
772
- return { byRepo, hasSegmentHeader: false, allFiles }
773
- }
774
-
775
- // 主章节起点(match index)→ 扫描到下一个非段头的 `## ` 标题或文件末尾。
776
- // 段头 `## <repo> 仓变更` 是 h2 但属本章节的子分段,不应触发章节结束。
777
- const lines = content.slice(sectionMatch.index).split('\n')
778
- // 先扫一遍:本章节内是否含至少一个段头(决定 hasSegmentHeader / 走分段路径 vs 退化路径)
779
- let hasSegmentHeader = false
780
- const sectionLines = []
781
- for (let i = 0; i < lines.length; i++) {
782
- const line = lines[i]
783
- if (i > 0 && /^##\s/.test(line) && !REPO_SECTION_HEADER_RE.test(line)) {
784
- // 遇到非段头的 h2 标题(如 `## 7. 接口定义`)→ 主章节结束
785
- break
786
- }
787
- if (REPO_SECTION_HEADER_RE.test(line)) hasSegmentHeader = true
788
- sectionLines.push(line)
789
- }
790
-
791
- if (!hasSegmentHeader) {
792
- // 无段头 → 整章节归 main(等价原 parseFileChangeList 行为)。
793
- // keepSillyspecDocs=true:.sillyspec/docs/ 模块文档 = 交付物,与 apply 阶段
794
- // resolveApplyAllowSet 口径一致(债单 D-2)——design 声明的模块文档更新必须被 task 认领。
795
- const main = new Set(parseFileChangeList(designPath, { keepSillyspecDocs: true }))
796
- if (main.size > 0) byRepo.set('main', main)
797
- for (const p of main) allFiles.push(p)
798
- return { byRepo, hasSegmentHeader: false, allFiles }
799
- }
800
-
801
- // 有段头 → 按 repo 切片,每段构造临时 design 调 parseFileChangeList
802
- // 当前 repo:段头之前的内容(主章节标题到第一个段头之间)归 'main'
803
- let currentRepo = 'main'
804
- const segments = new Map() // repo -> 行数组(含表格/列表,不含段头本身)
805
- let beforeFirstHeader = [] // 段头之前的 main 段内容
806
- let seenHeader = false
807
- for (const line of sectionLines.slice(1)) { // 跳过主章节标题行(sectionLines[0])
808
- const hdr = line.match(REPO_SECTION_HEADER_RE)
809
- if (hdr) {
810
- currentRepo = hdr[1]
811
- seenHeader = true
812
- if (!segments.has(currentRepo)) segments.set(currentRepo, [])
813
- continue
814
- }
815
- if (!seenHeader) {
816
- beforeFirstHeader.push(line)
817
- } else {
818
- segments.get(currentRepo).push(line)
819
- }
820
- }
821
-
822
- // 段头之前的 main 段(若有内容)也要对账
823
- if (beforeFirstHeader.filter(l => l.trim()).length > 0) {
824
- segments.set('main', beforeFirstHeader)
825
- }
826
-
827
- const tmpDir = mkdtempSync(pJoin(tmpdir(), 'design-cov-seg-'))
828
- try {
829
- for (const [repo, segLines] of segments) {
830
- // 把段内容包成完整 design md(前置主章节标题,让 parseFileChangeList 识别章节起点)
831
- const virtualDesign = ['## 文件变更清单', '', ...segLines, ''].join('\n')
832
- const tmpPath = pJoin(tmpDir, `${repo}.md`)
833
- writeFileSync(tmpPath, virtualDesign)
834
- const segFiles = [...parseFileChangeList(tmpPath, { keepSillyspecDocs: true })]
835
- if (segFiles.length === 0) continue
836
- const set = byRepo.get(repo) || new Set()
837
- for (const p of segFiles) { set.add(p); allFiles.push(p) }
838
- byRepo.set(repo, set)
839
- }
840
- } finally {
841
- rmSync(tmpDir, { recursive: true, force: true })
842
- }
843
-
844
- return { byRepo, hasSegmentHeader: true, allFiles }
845
- }
846
-
847
- /**
848
- * design.md 文件变更清单 → tasks allowed_paths 覆盖对账
849
- *
850
- * 修复场景:design.md 声明要改某源码文件(如 access-guide UI),但没有任何 task 的
851
- * allowed_paths 覆盖它 → execute 子代理被 allowed_paths 锁死不能碰它 → UI 没改
852
- * (「页面还是错的」),而 verify 一路对照 task 卡片循环验证照样 PASS。
853
- *
854
- * 在 plan-postcheck(execute 前)确定性拦截:design 清单中每个源码文件必须被
855
- * 至少一个 task 的 allowed_paths 覆盖(前缀 / glob 容差匹配)。
856
- *
857
- * 跨仓分段对账(约束③ / D-014):design §6 支持 `## <repo> 仓变更` 段头按仓分段,
858
- * task allowed_paths 按 (repo, path) 二元组归属——跨仓 task 的 allowed_paths 只覆盖
859
- * 对应 repo 段的 design 清单,不与主仓段交叉误判。无段头时整章节归 main(零回归)。
860
- *
861
- * fail-open 边界(不阻断):design.md 不存在、无 task 卡片(none 级别)、
862
- * task 卡片均无 allowed_paths(由 validatePlanFeasibility 把关)。
863
- * 阻断边界:有 task 卡片但 design 缺清单章节(light/full 已生成 task → design 必有清单)、
864
- * 清单文件未被任何 task 的 allowed_paths 覆盖。
865
- *
866
- * @param {string} changeDir - 变更目录
867
- * @returns {{ ok: boolean, errors: string[], warnings: string[], designFiles: string[], uncovered: string[] }}
868
- */
869
- export function validateDesignFileCoverage(changeDir) {
870
- const errors = []
871
- const warnings = []
872
-
873
- const designPath = pJoin(changeDir, 'design.md')
874
- if (!existsSync(designPath)) {
875
- return { ok: true, errors, warnings, designFiles: [], uncovered: [] }
876
- }
877
-
878
- const tasksDir = pJoin(changeDir, 'tasks')
879
- const taskFiles = existsSync(tasksDir)
880
- ? readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))
881
- : []
882
-
883
- // 无 task 卡片(plan_level=none 或老变更)→ 无对账对象,fail-open
884
- if (taskFiles.length === 0) {
885
- return { ok: true, errors, warnings, designFiles: [], uncovered: [] }
886
- }
887
-
888
- // 按仓分段解析 design §6(约束③):段头 `## <repo> 仓变更` → 段内路径归该 repo;无段头 → 全 main
889
- const { byRepo: designByRepo, hasSegmentHeader, allFiles: designFiles } = parseDesignCoverageByRepo(designPath)
890
- // 两种断裂文案(缺清单章节 / 文件未覆盖)从 manifest 同源(plan.design-file-coverage.data)。
891
- const dcRule = getRule('plan.design-file-coverage')
892
- if (designFiles.length === 0) {
893
- // 走到 plan-postcheck 说明已生成 task 卡片(light/full),brainstorm 模板规定清单必填。
894
- // 无清单 = design↔execute 偏差温床(覆盖对账无从对起),阻断,不让它静默放过。
895
- errors.push(dcRule.data.messageMissingList)
896
- return { ok: false, errors, warnings, designFiles: [], uncovered: [] }
897
- }
898
-
899
- // task allowed_paths 也按 (repo, path) 二元组收集(与 pathOwners 同口径,约束③):
900
- // 跨仓 task 的 allowed_paths 只覆盖对应 repo 的 design 段,不与主仓段交叉误判。
901
- const taskAllowedByRepo = new Map() // repo -> string[]
902
- let totalAllowed = 0
903
- for (const file of taskFiles) {
904
- const content = readFileSync(pJoin(tasksDir, file), 'utf8')
905
- const repo = parseRepo(content) || 'main'
906
- const allowed = parseAllowedPaths(content)
907
- if (allowed.length === 0) continue
908
- totalAllowed += allowed.length
909
- const arr = taskAllowedByRepo.get(repo) || []
910
- arr.push(...allowed)
911
- taskAllowedByRepo.set(repo, arr)
912
- }
913
- if (totalAllowed === 0) {
914
- return { ok: true, errors, warnings, designFiles, uncovered: [] }
915
- }
916
-
917
- // 对账:design 的每条 (repo, path) 必须被同 repo 的 task allowed_paths 覆盖。
918
- // 无分段(单仓)时 byRepo 只含 main,taskAllowedByRepo 也只含 main → 退化原扁平对账(零回归)。
919
- const uncovered = []
920
- for (const [repo, paths] of designByRepo) {
921
- const allowed = taskAllowedByRepo.get(repo) || []
922
- for (const df of paths) {
923
- // 同 repo 无 task 声明 → 整段无覆盖;或有 task 但无 pathMatches → 未覆盖
924
- if (!allowed.some(ap => pathMatches(df, ap))) {
925
- uncovered.push(hasSegmentHeader ? `[${repo}] ${df}` : df)
926
- }
927
- }
928
- }
929
- if (uncovered.length > 0) {
930
- errors.push(
931
- dcRule.data.messageUncovered
932
- .replaceAll('${count}', uncovered.length)
933
- .replaceAll('${files}', uncovered.map(f => ` • ${f}`).join('\n'))
934
- )
935
- }
936
-
937
- return { ok: errors.length === 0, errors, warnings, designFiles, uncovered }
938
- }
939
-
940
- /**
941
- * Plan 可行性校验器(本地代码证明 execute 前置条件)
942
- * 检查 TaskCard 的完整性和可行性
943
- * @param {string} changeDir - 变更目录
944
- * @param {string} projectRoot - 项目根目录(用于检查 allowed_paths 是否存在)
945
- * @returns {{ ok: boolean, errors: string[], warnings: string[] }}
946
- */
947
- export function validatePlanFeasibility(changeDir, projectRoot = null) {
948
- const errors = []
949
- const warnings = []
950
-
951
- const tasksDir = pJoin(changeDir, 'tasks')
952
- if (!existsSync(tasksDir)) {
953
- return { ok: true, errors, warnings } // none/light 可能没有 tasks/
954
- }
955
-
956
- const taskFiles = readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f)).sort()
957
- if (taskFiles.length === 0) {
958
- return { ok: true, errors, warnings }
959
- }
960
-
961
- // task 卡片完整 schema 文案从 manifest 同源(plan.task-card-schema);${id} 随检查点取 ${file} / ${taskId || file} / ${taskId}。
962
- const fsRule = getRule('plan.task-card-schema')
963
- const allTaskIds = []
964
- const depMap = new Map()
965
-
966
- for (const file of taskFiles) {
967
- const content = readFileSync(pJoin(tasksDir, file), 'utf8')
968
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/)
969
- if (!fmMatch) {
970
- // 漏闭合 --- 高频坑细化:只报「缺少 YAML frontmatter」不具体,用户须逐轮试错。
971
- // 有开头 --- 无闭合 / 完全无 --- 分开报并附修复动作(manifest messageFrontmatter 保持
972
- // 基础句,细化文案内联——同 title_zh 内联先例)。骨架命令从源头保闭合 + LF。
973
- const firstLine = (content.split('\n')[0] || '').trim()
974
- errors.push(
975
- firstLine === '---'
976
- ? `${file}: frontmatter 未闭合——有开头 --- 但缺少结尾 ---。修复:补一行 --- 闭合(frontmatter 以 --- 行开始并以 --- 行结束),或 sillyspec taskcard <change> --task <task-id> 重新生成安全骨架后填充`
977
- : `${fsRule.data.messageFrontmatter.replaceAll('${id}', file)}——文件必须以 --- 行开始。修复:sillyspec taskcard <change> --task <task-id> 生成安全骨架后填充`
978
- )
979
- continue
980
- }
981
- const fm = fmMatch[1]
982
- const body = content.slice(fmMatch[0].length)
983
-
984
- // 1. 必要字段检查
985
- const taskId = (fm.match(/^id:\s*(.+)/m)?.[1] || '').trim()
986
- const title = (fm.match(/^title:\s*(.+)/m)?.[1] || '').trim()
987
- // 复用 parseAllowedPaths(认 inline [x] + 块式两种写法),与 blueprint consistency / design coverage
988
- // 三处统一,消除「feasibility 只认块式 → inline 写法被误报 allowed_paths 为空」的漂移(transcript 卡 3 轮根因)。
989
- const allowedPaths = parseAllowedPaths(content)
990
-
991
- if (!taskId) errors.push(fsRule.data.messageId.replaceAll('${id}', file))
992
- if (!title) errors.push(fsRule.data.messageTitle.replaceAll('${id}', file))
993
- // title_zh(中文标题)完整性:子代理常为压 plan.js 的 20~40 行硬上限合并 title/title_zh(静默丢失),
994
- // postcheck 不校验行数(那是 prompt 劝说)但强制 frontmatter 字段齐全(enforcement 优于放宽劝说)。
995
- // 无对应 manifest 文案,内联(其余字段文案走 fsRule.data.messageXxx)。prompt-control-debt plan-b。
996
- const titleZh = (fm.match(/^title_zh:\s*(.+)/m)?.[1] || '').trim()
997
- if (!titleZh) errors.push(`${taskId || file}: frontmatter 缺少 title_zh(中文标题)——不得为压行数合并/删除字段`)
998
- if (taskId) allTaskIds.push(taskId)
999
-
1000
- // 2. allowed_paths 不为空
1001
- if (allowedPaths.length === 0) {
1002
- errors.push(fsRule.data.messageAllowedPaths.replaceAll('${id}', taskId || file))
1003
- }
1004
-
1005
- // 3. allowed_paths 文件存在或父目录存在(仅在 projectRoot 提供时检查)
1006
- if (projectRoot && allowedPaths.length > 0) {
1007
- for (const p of allowedPaths) {
1008
- const fullPath = pJoin(projectRoot, p)
1009
- const parentDir = pJoin(fullPath, '..')
1010
- if (!existsSync(fullPath) && !existsSync(parentDir)) {
1011
- warnings.push(`${taskId}: allowed_paths 中的 ${p} 文件和父目录都不存在`)
1012
- }
1013
- }
1014
- }
1015
-
1016
- // 4. depends_on 引用存在
1017
- const dependsOn = parseDependsOn(content)
1018
- if (taskId) depMap.set(taskId, dependsOn)
1019
-
1020
- // 5. body/frontmatter 包含必要字段(TaskCard 格式中这些字段在 frontmatter 内)
1021
- const hasGoal = /^goal:/m.test(fm)
1022
- const hasImplementation = /implementation:/m.test(fm)
1023
- const hasAcceptance = /acceptance:/m.test(fm)
1024
- const hasVerify = /verify:/m.test(fm)
1025
- const hasConstraints = /constraints:/m.test(fm)
1026
-
1027
- if (!hasGoal) errors.push(fsRule.data.messageGoal.replaceAll('${id}', taskId || file))
1028
- if (!hasImplementation) errors.push(fsRule.data.messageImplementation.replaceAll('${id}', taskId || file))
1029
- if (!hasAcceptance) errors.push(fsRule.data.messageAcceptance.replaceAll('${id}', taskId || file))
1030
- if (!hasVerify) errors.push(fsRule.data.messageVerify.replaceAll('${id}', taskId || file))
1031
- if (!hasConstraints) errors.push(fsRule.data.messageConstraints.replaceAll('${id}', taskId || file))
1032
-
1033
- // 5b. 骨架占位符拦截(坑 taskcard-placeholder-slip,2026-08-24 用户实证:task 卡留成
1034
- // 空骨架、九字段「存在性」全过,直到人工审计才发现)。占位标记是 taskcard.js 生成的
1035
- // 封闭集合(TASKCARD_PLACEHOLDERS 同源导出),精确匹配;verify 字段的占位命令刻意
1036
- // 不拦(可能是真实 tsc 命令)。占位符视同缺字段,与 9 字段缺失同级 error。
1037
- // 先剥 HTML 注释再匹配——骨架尾部注释自身罗列了占位标记清单(填充指引),不剥会把
1038
- // 已填充卡的注释误判成占位残留。
1039
- const contentNoComments = content.replace(/<!--[\s\S]*?-->/g, '')
1040
- const placeholderHits = TASKCARD_PLACEHOLDERS.filter(p => contentNoComments.includes(p.marker))
1041
- if (placeholderHits.length > 0) {
1042
- errors.push(
1043
- (fsRule.data.messagePlaceholder || '${id}: task 卡仍是未填充的生成骨架')
1044
- .replaceAll('${id}', taskId || file)
1045
- .replaceAll('${fields}', placeholderHits.map(p => p.field).join('、'))
1046
- )
1047
- }
1048
-
1049
- // 6. acceptance best-effort 字段 grep(D-05 软约束,warning 不阻断)
1050
- // 从 acceptance 文本提取 snake_case/camelCase 标识符,grep allowed_paths 指向的源文件;
1051
- // 找不到 → warning(给 LLM 审查提线索,不阻断 execute)。宁漏不噪:只取 snake/camel,
1052
- // 正则天然避开命令(无 _ 或大写)/路径(无 /)/中文;glob allowed_path / 目录 / 不存在文件一律跳过。
1053
- if (projectRoot && hasAcceptance && allowedPaths.length > 0) {
1054
- let acceptanceText = ''
1055
- try {
1056
- const fmObj = jsYaml.load(fm) || {}
1057
- if (typeof fmObj.acceptance === 'string') acceptanceText = fmObj.acceptance
1058
- else if (Array.isArray(fmObj.acceptance)) acceptanceText = fmObj.acceptance.join('\n')
1059
- } catch {
1060
- // frontmatter 非法 YAML(feasibility 未对 fm 做 YAML 解析,可能字面合法但语义复杂)→ 跳过 best-effort
1061
- }
1062
- if (acceptanceText) {
1063
- const IDENT_RE = /(?<![A-Za-z])[a-z]+(?:_[a-z]+)+|(?<![A-Za-z])[a-z]+(?:[A-Z][a-z]+)+/g
1064
- const idents = [...new Set(acceptanceText.match(IDENT_RE) || [])]
1065
- if (idents.length > 0) {
1066
- const readableFiles = []
1067
- for (const ap of allowedPaths) {
1068
- if (ap.includes('*')) continue // glob,跳过(best-effort,不展开)
1069
- try {
1070
- readableFiles.push(readFileSync(pJoin(projectRoot, ap), 'utf8'))
1071
- } catch {
1072
- // 目录 / 不存在 / 不可读 → 跳过(feasibility 3 已对不存在文件提示 warning)
1073
- }
1074
- }
1075
- // 至少读到一个源文件才比对,避免「全没读到 → 全部标识符误报」噪声
1076
- if (readableFiles.length > 0) {
1077
- for (const ident of idents) {
1078
- if (!readableFiles.some(c => c.includes(ident))) {
1079
- warnings.push(`${taskId}: acceptance 提到 ${ident} 但 allowed_paths 源文件未命中`)
1080
- }
1081
- }
1082
- }
1083
- }
1084
- }
1085
- }
1086
- }
1087
-
1088
- // 4b. depends_on 引用存在性
1089
- for (const [taskId, deps] of depMap) {
1090
- for (const dep of deps) {
1091
- if (!depMap.has(dep)) {
1092
- errors.push(fsRule.data.messageDependsOnMissing.replaceAll('${id}', taskId).replaceAll('${dep}', dep))
1093
- }
1094
- }
1095
- }
1096
-
1097
- // 5b. depends_on 无环(topoSortWaves 已含循环检测)
1098
- const { error: topoError } = topoSortWaves(depMap)
1099
- if (topoError) {
1100
- errors.push(topoError)
1101
- }
1102
-
1103
- // 7. task id 连续性
1104
- if (allTaskIds.length > 0) {
1105
- const nums = allTaskIds.map(id => {
1106
- const m = id.match(/task-(\d+)/i)
1107
- return m ? parseInt(m[1], 10) : null
1108
- }).filter(n => n !== null).sort((a, b) => a - b)
1109
- // nums[0]!==1 时跳过 = 兼容旧变更编号不从 1 起(契约同 validatePlanForExecute 检查 3,
1110
- // test/plan-execute-contract.test.mjs Case 10 钉死,勿改)
1111
- if (nums.length > 0 && nums[0] === 1) {
1112
- for (let i = 0; i < nums.length; i++) {
1113
- if (nums[i] !== i + 1) {
1114
- errors.push(getRule('plan.task-id-continuity').failMessage.replaceAll('${expected}', String(i + 1).padStart(2, '0')).replaceAll('${actual}', String(nums[i]).padStart(2, '0')))
1115
- break
1116
- }
1117
- }
1118
- }
1119
- }
1120
-
1121
- // 9. plan.md 通过 validatePlanForExecute(延迟导入避免循环依赖)
1122
- // 这在 run.js 的 postcheck contract 中已检查,这里不重复
1123
-
1124
- return { ok: errors.length === 0, errors, warnings }
1125
- }
1126
-
1127
- /**
1128
- * Plan 产物校验:检查 plan.md 和 tasks/ 是否齐全
1129
- * @param {string} changeDir - 变更目录
1130
- * @returns {{ ok: boolean, errors: string[], warnings: string[], planExists: boolean, taskCount: number }}
1131
- */
1132
- export function validatePlanArtifacts(changeDir) {
1133
- const errors = []
1134
- const warnings = []
1135
-
1136
- const planPath = pJoin(changeDir, 'plan.md')
1137
- if (!existsSync(planPath)) {
1138
- return { ok: false, errors: ['plan.md 不存在'], warnings, planExists: false, taskCount: 0 }
1139
- }
1140
-
1141
- const tasksDir = pJoin(changeDir, 'tasks')
1142
- let taskCount = 0
1143
- if (existsSync(tasksDir)) {
1144
- taskCount = readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f)).length
1145
- } else {
1146
- warnings.push('tasks/ 目录不存在(plan_level=none 时可接受)')
1147
- }
1148
-
1149
- return { ok: true, errors, warnings, planExists: true, taskCount }
1150
- }
1151
-
1152
- // ═══════════════════════════════════════════════════════════════
1153
- // 执行入口(从 run.js 迁移)
1154
- // ═══════════════════════════════════════════════════════════════
1155
-
1156
- /**
1157
- * Plan postcheck 主函数:Wave 重排 + 一致性校验 + 产物确认
1158
- *
1159
- * @param {{ cwd: string, specRoot?: string, resolveChangeDir: Function, progress?: object }} context
1160
- * @throws {Error} 校验失败时抛出
1161
- */
1162
- export async function executePlanPostcheck(context) {
1163
- const { cwd, specRoot, resolveChangeDir, progress } = context
1164
-
1165
- const specDir = specRoot || pJoin(cwd, '.sillyspec')
1166
- const changesDir = pJoin(specDir, 'changes')
1167
- if (!existsSync(changesDir)) {
1168
- console.warn(' ⚠️ 未找到 changes 目录,跳过 postcheck')
1169
- return
1170
- }
1171
-
1172
- // 找到当前变更目录(progress 由调用方从 SQLite 读取并传入;.runtime/progress.json 已废弃)
1173
- let changeDir = null
1174
- if (progress) {
1175
- changeDir = resolveChangeDir(cwd, progress, specDir)
1176
- }
1177
- if (!changeDir) {
1178
- // 回退:找最新的变更目录
1179
- const dirs = readdirSync(changesDir)
1180
- .filter(d => existsSync(pJoin(changesDir, d, 'plan.md')))
1181
- .sort().reverse()
1182
- if (dirs.length > 0) changeDir = pJoin(changesDir, dirs[0])
1183
- }
1184
- if (!changeDir) {
1185
- console.warn(' ⚠️ 未找到当前变更目录,跳过 postcheck')
1186
- return
1187
- }
1188
-
1189
- console.log(` 📂 变更目录: ${changeDir}`)
1190
-
1191
- // ── 报错聚合(坑6③):六个检查全部跑完后统一输出全部失败项,一轮 --done 暴露全部问题,
1192
- // 不再「失败一个抛一个、修一个冒一个」的迭代盲盒。各检查相互独立(都只读 changeDir 产物),
1193
- // 前置检查失败不使后续检查失真——唯一例外是 tasks/ 目录缺失时后续检查都无意义,仍提前短路。
1194
- const failures = [] // { name, errors, hint }
1195
- const printSectionWarnings = (label, warnings) => {
1196
- if (warnings.length > 0) {
1197
- console.warn(`\n⚠️ ${label}警告(不阻断):`)
1198
- for (const w of warnings) console.warn(` - ${w}`)
1199
- }
1200
- }
1201
-
1202
- // ── 1. 一致性校验 ──
1203
- const consistency = validateBlueprintConsistency(changeDir)
1204
- if (consistency.errors.length > 0) {
1205
- failures.push({ name: '蓝图一致性校验', errors: consistency.errors, hint: '请修复上述问题后重新完成此步骤。' })
1206
- }
1207
- printSectionWarnings('蓝图一致性', consistency.warnings)
1208
-
1209
- // ── 1b. 可行性校验 ──
1210
- const feasibility = validatePlanFeasibility(changeDir, context.cwd)
1211
- if (feasibility.errors.length > 0) {
1212
- failures.push({ name: 'Plan 可行性校验', errors: feasibility.errors, hint: null })
1213
- }
1214
- printSectionWarnings('Plan 可行性', feasibility.warnings)
1215
-
1216
- // ── 1c. 跨任务契约校验 ──
1217
- // 对账 consumer.expects_from ↔ provider.provides,拦截「consumer 期望字段
1218
- // 但 provider 未承诺」的契约断裂(避免到 execute/verify 才暴露成 403/500)
1219
- const crossTask = validateCrossTaskContracts(changeDir)
1220
- if (crossTask.errors.length > 0) {
1221
- failures.push({
1222
- name: '跨任务契约校验(consumer 期望的字段未被 provider 承诺)',
1223
- errors: crossTask.errors,
1224
- hint: '修复方式:要么在 provider task 的 provides.fields 补上缺失字段,要么修正 consumer task 的 expects_from.needs(确认依赖是否真实)。',
1225
- })
1226
- }
1227
-
1228
- // ── 1c-b. TaskCard 命令存在性校验 ──
1229
- // TaskCard verify/implementation 的 `npm|pnpm|yarn run <script>` 必须在 package.json
1230
- // scripts 中存在(monorepo 子包感知——读 local.yaml modules 块定位)。
1231
- // invalid → error 硬阻断,避免 execute 子代理跑死命令(design D-04 / 问题 3)。
1232
- // modules 块可选:无块时仅查根 package.json(与 scan-postcheck 历史行为一致)。
1233
- const localYamlPath = pJoin(specDir, 'local.yaml')
1234
- let taskModules = null
1235
- if (existsSync(localYamlPath)) {
1236
- taskModules = parseLocalYamlModules(readFileSync(localYamlPath, 'utf8'))
1237
- }
1238
- const taskCmds = validateTaskCommands(changeDir, context.cwd, taskModules)
1239
- if (taskCmds.errors.length > 0) {
1240
- failures.push({
1241
- name: 'TaskCard 命令存在性校验(verify/implementation 的 npm/pnpm/yarn run <script> 不存在)',
1242
- errors: taskCmds.errors,
1243
- hint: '修复方式:要么在 package.json scripts 补上缺失命令(monorepo 注意子包路径),要么修正 TaskCard 的 verify/implementation(确认命令是否真实、是否需 cd 子包)。',
1244
- })
1245
- }
1246
-
1247
- // ── 1d. design 文件覆盖对账 ──
1248
- // design.md 清单中的每个源码文件必须被某 task 的 allowed_paths 覆盖,
1249
- // 否则 execute 子代理无权改它 → 漏改(典型表现:「页面还是错的」)。
1250
- const coverage = validateDesignFileCoverage(changeDir)
1251
- for (const w of coverage.warnings) console.warn(`\n ⚠️ ${w}`)
1252
- if (coverage.errors.length > 0) {
1253
- failures.push({ name: 'design.md 文件覆盖对账(清单中的文件未被任何 task 覆盖)', errors: coverage.errors, hint: null })
1254
- }
1255
- if (coverage.designFiles.length > 0 && coverage.uncovered.length === 0) {
1256
- console.log(` ✅ design.md ${coverage.designFiles.length} 个文件全部被 task allowed_paths 覆盖`)
1257
- }
1258
-
1259
- // ── 1e. 阶段完成产物校验(plan stage contract)──
1260
- // plan 完成 gate 还会跑 stage-contract.validatePlanOutputs;为免「postcheck 通过 →
1261
- // stage gate 又报 module-impact 缺失/entry-point-wiring 未覆盖」的修一层撞一层,
1262
- // 在此把 stage contract 的 error/warning 也聚合进本轮输出。
1263
- const { validatePlanOutputs } = await import('../stage-contract.js')
1264
- if (typeof validatePlanOutputs === 'function') {
1265
- const contract = validatePlanOutputs(context.cwd, basename(changeDir), { specRoot })
1266
- if (contract.errors.length > 0) {
1267
- failures.push({
1268
- name: 'plan 阶段产物契约校验(stage-contract validatePlanOutputs)',
1269
- errors: contract.errors,
1270
- hint: '修复方式:补缺失产物(如 module-impact.md)、在 design.md 明示不改理由、或修正 task allowed_paths 覆盖 design.md 提及的入口文件。',
1271
- })
1272
- }
1273
- if (contract.warnings.length > 0) {
1274
- for (const w of contract.warnings) {
1275
- console.warn(`\n ⚠️ ${w}`)
1276
- }
1277
- }
1278
- }
1279
-
1280
- // ── 聚合输出:一轮 --done 暴露全部失败项(坑6③)──
1281
- if (failures.length > 0) {
1282
- console.error(`\n❌ plan postcheck 失败(${failures.length} 类问题,已全部列出——一次修复后重跑,无需逐个迭代):`)
1283
- for (const f of failures) {
1284
- console.error(`\n 【${f.name}】`)
1285
- for (const err of f.errors) console.error(` - ${err}`)
1286
- if (f.hint) console.error(` ${f.hint}`)
1287
- }
1288
- throw new Error(`planPostcheck: ${failures.length} 组校验失败(${failures.map(f => f.name).join(';')})`)
1289
- }
1290
-
1291
- // ── 2. Wave 重排 ──
1292
- const tasksDir = pJoin(changeDir, 'tasks')
1293
- if (existsSync(tasksDir)) {
1294
- const taskFiles = readdirSync(tasksDir).filter(f => /^task-\d+\.md$/.test(f))
1295
- const depMap = collectTaskDepMap(tasksDir)
1296
-
1297
- const { waves, error: topoError } = topoSortWaves(depMap)
1298
- if (topoError) {
1299
- console.error(`\n❌ Wave 重排失败: ${topoError}`)
1300
- throw new Error('planPostcheck: ' + topoError)
1301
- }
1302
-
1303
- console.log('\n 📊 Wave 分组(基于 depends_on 拓扑排序):')
1304
- waves.forEach((wave, i) => {
1305
- console.log(` Wave ${i + 1}: ${wave.join(', ')}`)
1306
- })
1307
-
1308
- // 比较 plan.md 现有 Wave 分组 + 依赖方向硬校验(坑 wave-dep-direction-unchecked,
1309
- // 2026-08-24 用户反馈二期:主控手排 Wave 与拓扑比对只警告不阻断,而真正的正确性违规
1310
- // ——depends_on 落同 Wave / 后置 Wave——此前完全没有校验)
1311
- if (taskFiles.length > 0) {
1312
- const planPath = pJoin(changeDir, 'plan.md')
1313
- if (existsSync(planPath)) {
1314
- const planContent = readFileSync(planPath, 'utf8')
1315
- if (/##\s*Wave\s+\d/i.test(planContent)) {
1316
- const existingWaves = []
1317
- const lines = planContent.split('\n')
1318
- let currentWaveTasks = null
1319
- for (const line of lines) {
1320
- const wm = line.match(/^#+\s*Wave\s+(\d+)/i)
1321
- if (wm) {
1322
- if (currentWaveTasks) existingWaves.push(currentWaveTasks)
1323
- currentWaveTasks = []
1324
- continue
1325
- }
1326
- // 非 Wave 标题行(## 自检 等)退出当前 Wave 段,避免自检 checkbox
1327
- // 被混入 task 列表导致 Wave 结构比对误判。
1328
- if (/^#+\s/.test(line)) {
1329
- if (currentWaveTasks) existingWaves.push(currentWaveTasks)
1330
- currentWaveTasks = null
1331
- continue
1332
- }
1333
- // 2026-08-20-task-truth-unify:Wave 段下纯 ID 引用行(- task-NN);旧 checkbox 行同收。
1334
- // 编号补零对齐卡片口径(坑 wave-ref-unpadded,同 parseTaskWavesFromPlan)
1335
- const tm = line.match(/^[-*]\s+(?:\[[ x]\]\s*)?task-(\d+)\s*[::\s]*$/i)
1336
- || line.match(/^[-*]\s*\[[ x]\]\s*task-(\d+)/i)
1337
- if (tm && currentWaveTasks) {
1338
- currentWaveTasks.push(`task-${String(tm[1]).padStart(2, '0')}`)
1339
- }
1340
- }
1341
- if (currentWaveTasks) existingWaves.push(currentWaveTasks)
1342
-
1343
- // ── 依赖方向硬校验 ──
1344
- // Wave 契约(execute.js Wave 要点 1):同一 Wave 的子代理强制并行;有依赖的 task
1345
- // 必须落在其依赖的后置 Wave。同 Wave / 后置 Wave 引用都是正确性违规(并行破坏依赖
1346
- // / 顺序颠倒),硬拦;仅分组数差异(手工过度串行化)合法,保留下方 warning。
1347
- const waveOf = new Map()
1348
- existingWaves.forEach((ws, i) => { for (const t of ws) waveOf.set(t, i) })
1349
- const directionViolations = []
1350
- for (const [taskId, deps] of depMap) {
1351
- const w = waveOf.get(taskId)
1352
- if (w === undefined) continue // 卡片未列入任何 Wave → 由 validatePlanForExecute 覆盖校验兜底
1353
- for (const dep of deps) {
1354
- const dw = waveOf.get(dep)
1355
- if (dw === undefined) continue // 依赖不存在的 task → feasibility depends_on 引用校验兜底
1356
- if (dw === w) directionViolations.push(`${taskId} depends_on ${dep},但两者同在 Wave ${w + 1}(同 Wave 强制并行,依赖被破坏)`)
1357
- else if (dw > w) directionViolations.push(`${taskId} depends_on ${dep},但 ${dep} 在后置 Wave ${dw + 1}(顺序颠倒)`)
1358
- }
1359
- }
1360
- if (directionViolations.length > 0) {
1361
- console.error(`\n❌ Wave 依赖方向违规(${directionViolations.length} 处):`)
1362
- for (const v of directionViolations) console.error(` ${v}`)
1363
- console.error(' 解法:sillyspec plan-adopt-waves --change <变更名> 一键按 depends_on 拓扑重排 plan.md Wave 段,或手动调整分组')
1364
- throw new Error('planPostcheck: Wave 依赖方向违规(depends_on 同 Wave / 后置 Wave)——' + directionViolations.join(';'))
1365
- }
1366
-
1367
- const sameStructure = waves.length === existingWaves.length &&
1368
- waves.every((w, i) => {
1369
- const a = [...w].sort().join(',')
1370
- const b = [...(existingWaves[i] || [])].sort().join(',')
1371
- return a === b
1372
- })
1373
-
1374
- if (sameStructure) {
1375
- console.log(' ✅ Wave 分组与拓扑排序一致,无需更新 plan.md')
1376
- } else {
1377
- console.log(' ⚠️ Wave 分组与拓扑排序不一致(依赖方向已校验合法——手工比拓扑更细的串行化是安全做法,可保持现状)')
1378
- console.log(' 标准分组见上方 📊;如需对齐:sillyspec plan-adopt-waves --change <变更名>(重排 plan.md Wave 段并同步任务总表 W 列)')
1379
- }
1380
- }
1381
- }
1382
- }
1383
- }
1384
-
1385
- // ── 3. 产物确认 ──
1386
- const artifacts = validatePlanArtifacts(changeDir)
1387
- if (!artifacts.ok) {
1388
- for (const err of artifacts.errors) console.error(`❌ ${err}`)
1389
- throw new Error('planPostcheck: artifact validation failed')
1390
- }
1391
- console.log('\n ✅ plan.md 存在')
1392
-
1393
- if (artifacts.taskCount > 0) {
1394
- console.log(` ✅ tasks/ 目录有 ${artifacts.taskCount} 个 TaskCard 文件`)
1395
- }
1396
-
1397
- console.log('\n ✅ Plan postcheck 完成')
1398
- }