sillyspec 3.27.11 → 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 (1219) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +1 -1
  2. package/README.md +3 -2
  3. package/package.json +1 -1
  4. package/src/agent-session-log.js +77 -10
  5. package/src/change-delete.js +181 -0
  6. package/src/config-schema.js +2 -2
  7. package/src/contract-matrix.js +15 -2
  8. package/src/docs-check.js +126 -0
  9. package/src/doctor-diagnostics.js +64 -1
  10. package/src/endpoint-extractor.js +107 -28
  11. package/src/index.js +208 -13
  12. package/src/init.js +104 -27
  13. package/src/machine-interface.js +63 -0
  14. package/src/module-changelog.js +116 -0
  15. package/src/progress/change-registry.js +28 -0
  16. package/src/progress/shared.js +6 -0
  17. package/src/progress/stage-machine.js +191 -9
  18. package/src/progress.js +6 -0
  19. package/src/run/command.js +26 -1
  20. package/src/run/complete-handlers.js +42 -4
  21. package/src/run/complete.js +12 -4
  22. package/src/run/prompt.js +12 -1
  23. package/src/run/quick-audit.js +98 -0
  24. package/src/run/shared.js +86 -0
  25. package/src/run/stage.js +18 -11
  26. package/src/spec-sync.js +191 -14
  27. package/src/stages/archive.js +5 -0
  28. package/src/stages/execute.js +7 -2
  29. package/src/sync.js +575 -21
  30. package/src/task-review.js +51 -4
  31. package/src/verify-postcheck.js +60 -8
  32. package/src/verify-probes.js +3 -0
  33. package/src/workflow.js +4 -0
  34. package/src/worktree-apply.js +4 -4
  35. package/src/worktree.js +6 -4
  36. package/{.worktrees/542c4415/templates/claude-instruction.md → templates/agents-instruction.md} +2 -2
  37. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  38. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  39. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  40. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  41. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  42. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  43. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  44. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  45. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +0 -57
  46. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +0 -177
  47. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  48. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  49. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  50. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  51. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  52. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +0 -64
  53. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +0 -54
  54. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  55. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  56. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +0 -2
  57. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +0 -20
  58. package/.claude/worktrees/sillyspec-data-model-research/README.md +0 -203
  59. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +0 -91
  60. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +0 -2
  61. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  62. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +0 -977
  63. package/.claude/worktrees/sillyspec-data-model-research/package.json +0 -39
  64. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  65. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  66. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  67. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +0 -16
  68. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  69. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +0 -836
  70. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +0 -256
  71. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +0 -25
  72. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +0 -95
  73. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +0 -679
  74. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +0 -526
  75. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +0 -357
  76. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +0 -803
  77. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +0 -290
  78. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +0 -270
  79. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +0 -65
  80. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +0 -109
  81. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +0 -202
  82. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +0 -88
  83. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +0 -328
  84. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +0 -97
  85. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +0 -480
  86. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +0 -20
  87. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +0 -55
  88. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +0 -381
  89. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +0 -517
  90. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +0 -155
  91. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +0 -245
  92. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +0 -246
  93. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +0 -121
  94. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +0 -825
  95. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +0 -393
  96. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +0 -107
  97. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +0 -1099
  98. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +0 -420
  99. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +0 -78
  100. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +0 -73
  101. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +0 -150
  102. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +0 -130
  103. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +0 -892
  104. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +0 -2798
  105. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +0 -626
  106. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +0 -231
  107. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +0 -128
  108. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +0 -104
  109. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +0 -543
  110. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +0 -127
  111. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +0 -166
  112. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +0 -222
  113. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +0 -580
  114. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +0 -336
  115. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +0 -355
  116. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +0 -36
  117. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +0 -594
  118. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +0 -265
  119. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +0 -1304
  120. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +0 -115
  121. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +0 -852
  122. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +0 -77
  123. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +0 -1595
  124. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +0 -1552
  125. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +0 -1259
  126. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +0 -156
  127. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +0 -1084
  128. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +0 -208
  129. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +0 -128
  130. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +0 -843
  131. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +0 -186
  132. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +0 -269
  133. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +0 -1562
  134. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +0 -584
  135. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +0 -23
  136. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +0 -388
  137. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +0 -512
  138. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +0 -95
  139. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +0 -414
  140. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +0 -597
  141. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +0 -62
  142. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +0 -50
  143. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +0 -358
  144. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +0 -171
  145. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +0 -550
  146. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +0 -889
  147. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +0 -597
  148. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +0 -199
  149. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +0 -236
  150. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +0 -617
  151. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +0 -145
  152. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +0 -540
  153. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +0 -1275
  154. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +0 -43
  155. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +0 -29
  156. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +0 -514
  157. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +0 -1344
  158. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +0 -650
  159. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +0 -167
  160. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +0 -608
  161. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +0 -64
  162. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +0 -246
  163. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +0 -1470
  164. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +0 -1498
  165. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +0 -210
  166. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +0 -1718
  167. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +0 -277
  168. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +0 -19
  169. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +0 -600
  170. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +0 -125
  171. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +0 -1446
  172. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +0 -576
  173. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +0 -1715
  174. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +0 -23
  175. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +0 -28
  176. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +0 -12
  177. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +0 -32
  178. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +0 -79
  179. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +0 -132
  180. package/.npmrc-temp +0 -1
  181. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  182. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  183. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  184. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  185. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  186. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  187. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  188. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  189. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +0 -57
  190. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +0 -177
  191. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  192. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  193. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  194. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  195. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  196. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  197. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +0 -64
  198. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +0 -54
  199. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  200. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  201. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +0 -6
  202. package/.worktrees/2c37b1d7/.gitattributes +0 -2
  203. package/.worktrees/2c37b1d7/.husky/pre-push +0 -20
  204. package/.worktrees/2c37b1d7/README.md +0 -203
  205. package/.worktrees/2c37b1d7/SKILL.md +0 -91
  206. package/.worktrees/2c37b1d7/architecture-analysis.md +0 -448
  207. package/.worktrees/2c37b1d7/bin/sillyspec.js +0 -2
  208. package/.worktrees/2c37b1d7/eval/README.md +0 -86
  209. package/.worktrees/2c37b1d7/eval/eval.config.json +0 -28
  210. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +0 -63
  211. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +0 -27
  212. package/.worktrees/2c37b1d7/eval/lib/config.mjs +0 -82
  213. package/.worktrees/2c37b1d7/eval/lib/db.mjs +0 -76
  214. package/.worktrees/2c37b1d7/eval/lib/report.mjs +0 -120
  215. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +0 -157
  216. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +0 -73
  217. package/.worktrees/2c37b1d7/eval/lib/util.mjs +0 -107
  218. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +0 -30
  219. package/.worktrees/2c37b1d7/eval/run.mjs +0 -83
  220. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +0 -6
  221. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  222. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +0 -6
  223. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +0 -28
  224. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +0 -6
  225. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  226. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  227. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +0 -6
  228. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +0 -31
  229. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  230. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +0 -6
  231. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  232. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +0 -6
  233. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +0 -38
  234. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  235. package/.worktrees/2c37b1d7/package-lock.json +0 -977
  236. package/.worktrees/2c37b1d7/package.json +0 -41
  237. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  238. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  239. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  240. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +0 -16
  241. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  242. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +0 -836
  243. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +0 -256
  244. package/.worktrees/2c37b1d7/packages/dashboard/package.json +0 -25
  245. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +0 -95
  246. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +0 -679
  247. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +0 -526
  248. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +0 -357
  249. package/.worktrees/2c37b1d7/src/agent-session-log.js +0 -803
  250. package/.worktrees/2c37b1d7/src/change-list.js +0 -290
  251. package/.worktrees/2c37b1d7/src/change-risk-profile.js +0 -339
  252. package/.worktrees/2c37b1d7/src/check-primitives.js +0 -65
  253. package/.worktrees/2c37b1d7/src/classify-change.js +0 -109
  254. package/.worktrees/2c37b1d7/src/commit-suggest.js +0 -202
  255. package/.worktrees/2c37b1d7/src/config-cat.js +0 -88
  256. package/.worktrees/2c37b1d7/src/config-schema.js +0 -328
  257. package/.worktrees/2c37b1d7/src/constants.js +0 -97
  258. package/.worktrees/2c37b1d7/src/contract-matrix.js +0 -533
  259. package/.worktrees/2c37b1d7/src/datetime.js +0 -20
  260. package/.worktrees/2c37b1d7/src/db-engine.js +0 -55
  261. package/.worktrees/2c37b1d7/src/db.js +0 -381
  262. package/.worktrees/2c37b1d7/src/decision-distill.js +0 -517
  263. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +0 -155
  264. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +0 -245
  265. package/.worktrees/2c37b1d7/src/dispatch/probe.js +0 -246
  266. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +0 -121
  267. package/.worktrees/2c37b1d7/src/docs-check.js +0 -825
  268. package/.worktrees/2c37b1d7/src/docs-debt.js +0 -393
  269. package/.worktrees/2c37b1d7/src/docs-gate.js +0 -107
  270. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +0 -1099
  271. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +0 -409
  272. package/.worktrees/2c37b1d7/src/foreign-declared.js +0 -155
  273. package/.worktrees/2c37b1d7/src/fs-atomic.js +0 -73
  274. package/.worktrees/2c37b1d7/src/git-helper.js +0 -150
  275. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +0 -130
  276. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +0 -892
  277. package/.worktrees/2c37b1d7/src/index.js +0 -2854
  278. package/.worktrees/2c37b1d7/src/init.js +0 -626
  279. package/.worktrees/2c37b1d7/src/knowledge-match.js +0 -231
  280. package/.worktrees/2c37b1d7/src/local-detect.js +0 -128
  281. package/.worktrees/2c37b1d7/src/local-register.js +0 -104
  282. package/.worktrees/2c37b1d7/src/machine-interface.js +0 -543
  283. package/.worktrees/2c37b1d7/src/migrate.js +0 -127
  284. package/.worktrees/2c37b1d7/src/module-impact.js +0 -166
  285. package/.worktrees/2c37b1d7/src/module-resolve.js +0 -222
  286. package/.worktrees/2c37b1d7/src/modules.js +0 -580
  287. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +0 -126
  288. package/.worktrees/2c37b1d7/src/progress/change-registry.js +0 -336
  289. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +0 -355
  290. package/.worktrees/2c37b1d7/src/progress/shared.js +0 -36
  291. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +0 -594
  292. package/.worktrees/2c37b1d7/src/progress/step-store.js +0 -265
  293. package/.worktrees/2c37b1d7/src/progress.js +0 -1304
  294. package/.worktrees/2c37b1d7/src/quick-recommend.js +0 -115
  295. package/.worktrees/2c37b1d7/src/quicklog.js +0 -883
  296. package/.worktrees/2c37b1d7/src/review-tier.js +0 -77
  297. package/.worktrees/2c37b1d7/src/run/command.js +0 -1641
  298. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +0 -1552
  299. package/.worktrees/2c37b1d7/src/run/complete.js +0 -1259
  300. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +0 -156
  301. package/.worktrees/2c37b1d7/src/run/gates.js +0 -1111
  302. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +0 -208
  303. package/.worktrees/2c37b1d7/src/run/next.js +0 -128
  304. package/.worktrees/2c37b1d7/src/run/prompt.js +0 -843
  305. package/.worktrees/2c37b1d7/src/run/quick-audit.js +0 -186
  306. package/.worktrees/2c37b1d7/src/run/scan-profile.js +0 -269
  307. package/.worktrees/2c37b1d7/src/run/shared.js +0 -1562
  308. package/.worktrees/2c37b1d7/src/run/stage.js +0 -587
  309. package/.worktrees/2c37b1d7/src/run.js +0 -23
  310. package/.worktrees/2c37b1d7/src/scan-diff.js +0 -388
  311. package/.worktrees/2c37b1d7/src/scan-postcheck.js +0 -524
  312. package/.worktrees/2c37b1d7/src/scan-staleness.js +0 -95
  313. package/.worktrees/2c37b1d7/src/setup.js +0 -414
  314. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +0 -597
  315. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +0 -62
  316. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +0 -50
  317. package/.worktrees/2c37b1d7/src/spec-sync.js +0 -358
  318. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +0 -171
  319. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +0 -551
  320. package/.worktrees/2c37b1d7/src/stage-contract.js +0 -948
  321. package/.worktrees/2c37b1d7/src/stage-review.js +0 -597
  322. package/.worktrees/2c37b1d7/src/stages/archive.js +0 -199
  323. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +0 -285
  324. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +0 -624
  325. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +0 -145
  326. package/.worktrees/2c37b1d7/src/stages/doctor.js +0 -540
  327. package/.worktrees/2c37b1d7/src/stages/execute.js +0 -1277
  328. package/.worktrees/2c37b1d7/src/stages/explore.js +0 -43
  329. package/.worktrees/2c37b1d7/src/stages/index.js +0 -29
  330. package/.worktrees/2c37b1d7/src/stages/knowledge.js +0 -514
  331. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +0 -1398
  332. package/.worktrees/2c37b1d7/src/stages/plan.js +0 -655
  333. package/.worktrees/2c37b1d7/src/stages/quick.js +0 -167
  334. package/.worktrees/2c37b1d7/src/stages/scan.js +0 -608
  335. package/.worktrees/2c37b1d7/src/stages/status.js +0 -64
  336. package/.worktrees/2c37b1d7/src/stages/verify.js +0 -246
  337. package/.worktrees/2c37b1d7/src/sync.js +0 -1470
  338. package/.worktrees/2c37b1d7/src/task-review.js +0 -1498
  339. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +0 -21
  340. package/.worktrees/2c37b1d7/src/taskcard.js +0 -250
  341. package/.worktrees/2c37b1d7/src/verify-postcheck.js +0 -1718
  342. package/.worktrees/2c37b1d7/src/verify-probes.js +0 -327
  343. package/.worktrees/2c37b1d7/src/version.js +0 -19
  344. package/.worktrees/2c37b1d7/src/workflow.js +0 -600
  345. package/.worktrees/2c37b1d7/src/workspace.js +0 -125
  346. package/.worktrees/2c37b1d7/src/worktree-apply.js +0 -1611
  347. package/.worktrees/2c37b1d7/src/worktree-deps.js +0 -668
  348. package/.worktrees/2c37b1d7/src/worktree.js +0 -1849
  349. package/.worktrees/2c37b1d7/templates/claude-instruction.md +0 -23
  350. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +0 -29
  351. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +0 -12
  352. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +0 -32
  353. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +0 -79
  354. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +0 -132
  355. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  356. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  357. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  358. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  359. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  360. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  361. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  362. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  363. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +0 -57
  364. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +0 -177
  365. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  366. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  367. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  368. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  369. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  370. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +0 -64
  371. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +0 -54
  372. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  373. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  374. package/.worktrees/542c4415/.gitattributes +0 -2
  375. package/.worktrees/542c4415/.husky/pre-push +0 -20
  376. package/.worktrees/542c4415/README.md +0 -203
  377. package/.worktrees/542c4415/SKILL.md +0 -91
  378. package/.worktrees/542c4415/architecture-analysis.md +0 -448
  379. package/.worktrees/542c4415/bin/sillyspec.js +0 -2
  380. package/.worktrees/542c4415/eval/README.md +0 -86
  381. package/.worktrees/542c4415/eval/eval.config.json +0 -28
  382. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +0 -63
  383. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +0 -27
  384. package/.worktrees/542c4415/eval/lib/config.mjs +0 -82
  385. package/.worktrees/542c4415/eval/lib/db.mjs +0 -76
  386. package/.worktrees/542c4415/eval/lib/report.mjs +0 -120
  387. package/.worktrees/542c4415/eval/lib/runner.mjs +0 -157
  388. package/.worktrees/542c4415/eval/lib/tasks.mjs +0 -73
  389. package/.worktrees/542c4415/eval/lib/util.mjs +0 -107
  390. package/.worktrees/542c4415/eval/lib/workdir.mjs +0 -30
  391. package/.worktrees/542c4415/eval/run.mjs +0 -83
  392. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +0 -6
  393. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  394. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +0 -6
  395. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +0 -28
  396. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +0 -6
  397. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  398. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  399. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +0 -6
  400. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +0 -31
  401. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  402. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +0 -6
  403. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  404. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +0 -6
  405. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +0 -38
  406. package/.worktrees/542c4415/logo.jpg +0 -0
  407. package/.worktrees/542c4415/package-lock.json +0 -977
  408. package/.worktrees/542c4415/package.json +0 -41
  409. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  410. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  411. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  412. package/.worktrees/542c4415/packages/dashboard/dist/index.html +0 -16
  413. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  414. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +0 -836
  415. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +0 -256
  416. package/.worktrees/542c4415/packages/dashboard/package.json +0 -25
  417. package/.worktrees/542c4415/packages/dashboard/server/executor.js +0 -95
  418. package/.worktrees/542c4415/packages/dashboard/server/index.js +0 -679
  419. package/.worktrees/542c4415/packages/dashboard/server/parser.js +0 -526
  420. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +0 -357
  421. package/.worktrees/542c4415/src/agent-session-log.js +0 -803
  422. package/.worktrees/542c4415/src/change-list.js +0 -290
  423. package/.worktrees/542c4415/src/change-risk-profile.js +0 -339
  424. package/.worktrees/542c4415/src/check-primitives.js +0 -65
  425. package/.worktrees/542c4415/src/classify-change.js +0 -109
  426. package/.worktrees/542c4415/src/commit-suggest.js +0 -202
  427. package/.worktrees/542c4415/src/config-cat.js +0 -88
  428. package/.worktrees/542c4415/src/config-schema.js +0 -328
  429. package/.worktrees/542c4415/src/constants.js +0 -97
  430. package/.worktrees/542c4415/src/contract-matrix.js +0 -533
  431. package/.worktrees/542c4415/src/datetime.js +0 -20
  432. package/.worktrees/542c4415/src/db-engine.js +0 -55
  433. package/.worktrees/542c4415/src/db.js +0 -381
  434. package/.worktrees/542c4415/src/decision-distill.js +0 -517
  435. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +0 -155
  436. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +0 -245
  437. package/.worktrees/542c4415/src/dispatch/probe.js +0 -246
  438. package/.worktrees/542c4415/src/dispatch/strategy.js +0 -121
  439. package/.worktrees/542c4415/src/docs-check.js +0 -825
  440. package/.worktrees/542c4415/src/docs-debt.js +0 -393
  441. package/.worktrees/542c4415/src/docs-gate.js +0 -107
  442. package/.worktrees/542c4415/src/doctor-diagnostics.js +0 -1099
  443. package/.worktrees/542c4415/src/endpoint-extractor.js +0 -409
  444. package/.worktrees/542c4415/src/foreign-declared.js +0 -155
  445. package/.worktrees/542c4415/src/fs-atomic.js +0 -73
  446. package/.worktrees/542c4415/src/git-helper.js +0 -150
  447. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +0 -130
  448. package/.worktrees/542c4415/src/hooks/worktree-guard.js +0 -892
  449. package/.worktrees/542c4415/src/index.js +0 -2854
  450. package/.worktrees/542c4415/src/init.js +0 -626
  451. package/.worktrees/542c4415/src/knowledge-match.js +0 -231
  452. package/.worktrees/542c4415/src/local-detect.js +0 -128
  453. package/.worktrees/542c4415/src/local-register.js +0 -104
  454. package/.worktrees/542c4415/src/machine-interface.js +0 -543
  455. package/.worktrees/542c4415/src/migrate.js +0 -127
  456. package/.worktrees/542c4415/src/module-impact.js +0 -166
  457. package/.worktrees/542c4415/src/module-resolve.js +0 -222
  458. package/.worktrees/542c4415/src/modules.js +0 -580
  459. package/.worktrees/542c4415/src/plan-adopt-waves.js +0 -126
  460. package/.worktrees/542c4415/src/progress/change-registry.js +0 -336
  461. package/.worktrees/542c4415/src/progress/consistency-doctor.js +0 -355
  462. package/.worktrees/542c4415/src/progress/shared.js +0 -36
  463. package/.worktrees/542c4415/src/progress/stage-machine.js +0 -594
  464. package/.worktrees/542c4415/src/progress/step-store.js +0 -265
  465. package/.worktrees/542c4415/src/progress.js +0 -1304
  466. package/.worktrees/542c4415/src/quick-recommend.js +0 -115
  467. package/.worktrees/542c4415/src/quicklog.js +0 -883
  468. package/.worktrees/542c4415/src/review-tier.js +0 -77
  469. package/.worktrees/542c4415/src/run/command.js +0 -1641
  470. package/.worktrees/542c4415/src/run/complete-handlers.js +0 -1552
  471. package/.worktrees/542c4415/src/run/complete.js +0 -1259
  472. package/.worktrees/542c4415/src/run/concurrent-detect.js +0 -156
  473. package/.worktrees/542c4415/src/run/gates.js +0 -1111
  474. package/.worktrees/542c4415/src/run/multi-repo-context.js +0 -208
  475. package/.worktrees/542c4415/src/run/next.js +0 -128
  476. package/.worktrees/542c4415/src/run/prompt.js +0 -843
  477. package/.worktrees/542c4415/src/run/quick-audit.js +0 -186
  478. package/.worktrees/542c4415/src/run/scan-profile.js +0 -269
  479. package/.worktrees/542c4415/src/run/shared.js +0 -1562
  480. package/.worktrees/542c4415/src/run/stage.js +0 -587
  481. package/.worktrees/542c4415/src/run.js +0 -23
  482. package/.worktrees/542c4415/src/scan-diff.js +0 -388
  483. package/.worktrees/542c4415/src/scan-postcheck.js +0 -524
  484. package/.worktrees/542c4415/src/scan-staleness.js +0 -95
  485. package/.worktrees/542c4415/src/setup.js +0 -414
  486. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +0 -597
  487. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +0 -62
  488. package/.worktrees/542c4415/src/spec-dir-typo.js +0 -50
  489. package/.worktrees/542c4415/src/spec-sync.js +0 -358
  490. package/.worktrees/542c4415/src/stage-contract-engine.js +0 -171
  491. package/.worktrees/542c4415/src/stage-contract-spec.js +0 -551
  492. package/.worktrees/542c4415/src/stage-contract.js +0 -948
  493. package/.worktrees/542c4415/src/stage-review.js +0 -597
  494. package/.worktrees/542c4415/src/stages/archive.js +0 -199
  495. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +0 -285
  496. package/.worktrees/542c4415/src/stages/brainstorm.js +0 -624
  497. package/.worktrees/542c4415/src/stages/cmd-existence.js +0 -145
  498. package/.worktrees/542c4415/src/stages/doctor.js +0 -540
  499. package/.worktrees/542c4415/src/stages/execute.js +0 -1277
  500. package/.worktrees/542c4415/src/stages/explore.js +0 -43
  501. package/.worktrees/542c4415/src/stages/index.js +0 -29
  502. package/.worktrees/542c4415/src/stages/knowledge.js +0 -514
  503. package/.worktrees/542c4415/src/stages/plan-postcheck.js +0 -1398
  504. package/.worktrees/542c4415/src/stages/plan.js +0 -655
  505. package/.worktrees/542c4415/src/stages/quick.js +0 -167
  506. package/.worktrees/542c4415/src/stages/scan.js +0 -608
  507. package/.worktrees/542c4415/src/stages/status.js +0 -64
  508. package/.worktrees/542c4415/src/stages/verify.js +0 -246
  509. package/.worktrees/542c4415/src/sync.js +0 -1470
  510. package/.worktrees/542c4415/src/task-review.js +0 -1498
  511. package/.worktrees/542c4415/src/taskcard-placeholders.js +0 -21
  512. package/.worktrees/542c4415/src/taskcard.js +0 -250
  513. package/.worktrees/542c4415/src/verify-postcheck.js +0 -1718
  514. package/.worktrees/542c4415/src/verify-probes.js +0 -327
  515. package/.worktrees/542c4415/src/version.js +0 -19
  516. package/.worktrees/542c4415/src/workflow.js +0 -600
  517. package/.worktrees/542c4415/src/workspace.js +0 -125
  518. package/.worktrees/542c4415/src/worktree-apply.js +0 -1611
  519. package/.worktrees/542c4415/src/worktree-deps.js +0 -668
  520. package/.worktrees/542c4415/src/worktree.js +0 -1849
  521. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +0 -29
  522. package/.worktrees/542c4415/templates/prompts/testcase-design.md +0 -12
  523. package/.worktrees/542c4415/templates/prompts/verify-probes.md +0 -32
  524. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +0 -79
  525. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +0 -132
  526. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  527. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  528. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  529. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  530. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  531. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  532. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  533. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  534. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +0 -57
  535. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +0 -177
  536. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  537. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  538. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  539. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  540. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  541. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  542. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +0 -64
  543. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +0 -54
  544. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  545. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  546. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +0 -6
  547. package/.worktrees/8d2d0392/.gitattributes +0 -2
  548. package/.worktrees/8d2d0392/.husky/pre-push +0 -20
  549. package/.worktrees/8d2d0392/README.md +0 -203
  550. package/.worktrees/8d2d0392/SKILL.md +0 -91
  551. package/.worktrees/8d2d0392/architecture-analysis.md +0 -448
  552. package/.worktrees/8d2d0392/bin/sillyspec.js +0 -2
  553. package/.worktrees/8d2d0392/eval/README.md +0 -86
  554. package/.worktrees/8d2d0392/eval/eval.config.json +0 -28
  555. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +0 -63
  556. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +0 -27
  557. package/.worktrees/8d2d0392/eval/lib/config.mjs +0 -82
  558. package/.worktrees/8d2d0392/eval/lib/db.mjs +0 -76
  559. package/.worktrees/8d2d0392/eval/lib/report.mjs +0 -120
  560. package/.worktrees/8d2d0392/eval/lib/runner.mjs +0 -157
  561. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +0 -73
  562. package/.worktrees/8d2d0392/eval/lib/util.mjs +0 -107
  563. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +0 -30
  564. package/.worktrees/8d2d0392/eval/run.mjs +0 -83
  565. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +0 -6
  566. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  567. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +0 -6
  568. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +0 -28
  569. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +0 -6
  570. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  571. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  572. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +0 -6
  573. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +0 -31
  574. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  575. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +0 -6
  576. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  577. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +0 -6
  578. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +0 -38
  579. package/.worktrees/8d2d0392/logo.jpg +0 -0
  580. package/.worktrees/8d2d0392/package-lock.json +0 -977
  581. package/.worktrees/8d2d0392/package.json +0 -41
  582. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  583. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  584. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  585. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +0 -16
  586. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  587. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +0 -836
  588. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +0 -256
  589. package/.worktrees/8d2d0392/packages/dashboard/package.json +0 -25
  590. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +0 -95
  591. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +0 -679
  592. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +0 -526
  593. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +0 -357
  594. package/.worktrees/8d2d0392/src/agent-session-log.js +0 -803
  595. package/.worktrees/8d2d0392/src/change-list.js +0 -290
  596. package/.worktrees/8d2d0392/src/change-risk-profile.js +0 -339
  597. package/.worktrees/8d2d0392/src/check-primitives.js +0 -65
  598. package/.worktrees/8d2d0392/src/classify-change.js +0 -109
  599. package/.worktrees/8d2d0392/src/commit-suggest.js +0 -202
  600. package/.worktrees/8d2d0392/src/config-cat.js +0 -88
  601. package/.worktrees/8d2d0392/src/config-schema.js +0 -328
  602. package/.worktrees/8d2d0392/src/constants.js +0 -97
  603. package/.worktrees/8d2d0392/src/contract-matrix.js +0 -533
  604. package/.worktrees/8d2d0392/src/datetime.js +0 -20
  605. package/.worktrees/8d2d0392/src/db-engine.js +0 -55
  606. package/.worktrees/8d2d0392/src/db.js +0 -381
  607. package/.worktrees/8d2d0392/src/decision-distill.js +0 -517
  608. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +0 -155
  609. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +0 -245
  610. package/.worktrees/8d2d0392/src/dispatch/probe.js +0 -246
  611. package/.worktrees/8d2d0392/src/dispatch/strategy.js +0 -121
  612. package/.worktrees/8d2d0392/src/docs-check.js +0 -825
  613. package/.worktrees/8d2d0392/src/docs-debt.js +0 -393
  614. package/.worktrees/8d2d0392/src/docs-gate.js +0 -107
  615. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +0 -1099
  616. package/.worktrees/8d2d0392/src/endpoint-extractor.js +0 -409
  617. package/.worktrees/8d2d0392/src/foreign-declared.js +0 -78
  618. package/.worktrees/8d2d0392/src/fs-atomic.js +0 -73
  619. package/.worktrees/8d2d0392/src/git-helper.js +0 -150
  620. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +0 -130
  621. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +0 -892
  622. package/.worktrees/8d2d0392/src/index.js +0 -2854
  623. package/.worktrees/8d2d0392/src/init.js +0 -626
  624. package/.worktrees/8d2d0392/src/knowledge-match.js +0 -231
  625. package/.worktrees/8d2d0392/src/local-detect.js +0 -128
  626. package/.worktrees/8d2d0392/src/local-register.js +0 -104
  627. package/.worktrees/8d2d0392/src/machine-interface.js +0 -543
  628. package/.worktrees/8d2d0392/src/migrate.js +0 -127
  629. package/.worktrees/8d2d0392/src/module-impact.js +0 -166
  630. package/.worktrees/8d2d0392/src/module-resolve.js +0 -222
  631. package/.worktrees/8d2d0392/src/modules.js +0 -580
  632. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +0 -126
  633. package/.worktrees/8d2d0392/src/progress/change-registry.js +0 -336
  634. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +0 -355
  635. package/.worktrees/8d2d0392/src/progress/shared.js +0 -36
  636. package/.worktrees/8d2d0392/src/progress/stage-machine.js +0 -594
  637. package/.worktrees/8d2d0392/src/progress/step-store.js +0 -265
  638. package/.worktrees/8d2d0392/src/progress.js +0 -1304
  639. package/.worktrees/8d2d0392/src/quick-recommend.js +0 -115
  640. package/.worktrees/8d2d0392/src/quicklog.js +0 -883
  641. package/.worktrees/8d2d0392/src/review-tier.js +0 -77
  642. package/.worktrees/8d2d0392/src/run/command.js +0 -1641
  643. package/.worktrees/8d2d0392/src/run/complete-handlers.js +0 -1552
  644. package/.worktrees/8d2d0392/src/run/complete.js +0 -1259
  645. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +0 -156
  646. package/.worktrees/8d2d0392/src/run/gates.js +0 -1094
  647. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +0 -208
  648. package/.worktrees/8d2d0392/src/run/next.js +0 -128
  649. package/.worktrees/8d2d0392/src/run/prompt.js +0 -843
  650. package/.worktrees/8d2d0392/src/run/quick-audit.js +0 -186
  651. package/.worktrees/8d2d0392/src/run/scan-profile.js +0 -269
  652. package/.worktrees/8d2d0392/src/run/shared.js +0 -1562
  653. package/.worktrees/8d2d0392/src/run/stage.js +0 -587
  654. package/.worktrees/8d2d0392/src/run.js +0 -23
  655. package/.worktrees/8d2d0392/src/scan-diff.js +0 -388
  656. package/.worktrees/8d2d0392/src/scan-postcheck.js +0 -524
  657. package/.worktrees/8d2d0392/src/scan-staleness.js +0 -95
  658. package/.worktrees/8d2d0392/src/setup.js +0 -414
  659. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +0 -597
  660. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +0 -62
  661. package/.worktrees/8d2d0392/src/spec-dir-typo.js +0 -50
  662. package/.worktrees/8d2d0392/src/spec-sync.js +0 -358
  663. package/.worktrees/8d2d0392/src/stage-contract-engine.js +0 -171
  664. package/.worktrees/8d2d0392/src/stage-contract-spec.js +0 -551
  665. package/.worktrees/8d2d0392/src/stage-contract.js +0 -948
  666. package/.worktrees/8d2d0392/src/stage-review.js +0 -597
  667. package/.worktrees/8d2d0392/src/stages/archive.js +0 -199
  668. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +0 -285
  669. package/.worktrees/8d2d0392/src/stages/brainstorm.js +0 -624
  670. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +0 -145
  671. package/.worktrees/8d2d0392/src/stages/doctor.js +0 -540
  672. package/.worktrees/8d2d0392/src/stages/execute.js +0 -1277
  673. package/.worktrees/8d2d0392/src/stages/explore.js +0 -43
  674. package/.worktrees/8d2d0392/src/stages/index.js +0 -29
  675. package/.worktrees/8d2d0392/src/stages/knowledge.js +0 -514
  676. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +0 -1398
  677. package/.worktrees/8d2d0392/src/stages/plan.js +0 -651
  678. package/.worktrees/8d2d0392/src/stages/quick.js +0 -167
  679. package/.worktrees/8d2d0392/src/stages/scan.js +0 -608
  680. package/.worktrees/8d2d0392/src/stages/status.js +0 -64
  681. package/.worktrees/8d2d0392/src/stages/verify.js +0 -246
  682. package/.worktrees/8d2d0392/src/sync.js +0 -1470
  683. package/.worktrees/8d2d0392/src/task-review.js +0 -1498
  684. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +0 -21
  685. package/.worktrees/8d2d0392/src/taskcard.js +0 -217
  686. package/.worktrees/8d2d0392/src/verify-postcheck.js +0 -1718
  687. package/.worktrees/8d2d0392/src/verify-probes.js +0 -327
  688. package/.worktrees/8d2d0392/src/version.js +0 -19
  689. package/.worktrees/8d2d0392/src/workflow.js +0 -600
  690. package/.worktrees/8d2d0392/src/workspace.js +0 -125
  691. package/.worktrees/8d2d0392/src/worktree-apply.js +0 -1611
  692. package/.worktrees/8d2d0392/src/worktree-deps.js +0 -576
  693. package/.worktrees/8d2d0392/src/worktree.js +0 -1838
  694. package/.worktrees/8d2d0392/templates/claude-instruction.md +0 -23
  695. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +0 -29
  696. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +0 -12
  697. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +0 -32
  698. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +0 -79
  699. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +0 -132
  700. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  701. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  702. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  703. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  704. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  705. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  706. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  707. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  708. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +0 -57
  709. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +0 -177
  710. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  711. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  712. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  713. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  714. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  715. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +0 -64
  716. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +0 -54
  717. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  718. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  719. package/.worktrees/c1eae35e/.gitattributes +0 -2
  720. package/.worktrees/c1eae35e/.husky/pre-push +0 -20
  721. package/.worktrees/c1eae35e/README.md +0 -203
  722. package/.worktrees/c1eae35e/SKILL.md +0 -91
  723. package/.worktrees/c1eae35e/architecture-analysis.md +0 -448
  724. package/.worktrees/c1eae35e/bin/sillyspec.js +0 -2
  725. package/.worktrees/c1eae35e/eval/README.md +0 -86
  726. package/.worktrees/c1eae35e/eval/eval.config.json +0 -28
  727. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +0 -63
  728. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +0 -27
  729. package/.worktrees/c1eae35e/eval/lib/config.mjs +0 -82
  730. package/.worktrees/c1eae35e/eval/lib/db.mjs +0 -76
  731. package/.worktrees/c1eae35e/eval/lib/report.mjs +0 -120
  732. package/.worktrees/c1eae35e/eval/lib/runner.mjs +0 -157
  733. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +0 -73
  734. package/.worktrees/c1eae35e/eval/lib/util.mjs +0 -107
  735. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +0 -30
  736. package/.worktrees/c1eae35e/eval/run.mjs +0 -83
  737. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +0 -6
  738. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  739. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +0 -6
  740. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +0 -28
  741. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +0 -6
  742. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  743. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  744. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +0 -6
  745. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +0 -31
  746. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  747. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +0 -6
  748. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  749. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +0 -6
  750. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +0 -38
  751. package/.worktrees/c1eae35e/logo.jpg +0 -0
  752. package/.worktrees/c1eae35e/package-lock.json +0 -977
  753. package/.worktrees/c1eae35e/package.json +0 -41
  754. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  755. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  756. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  757. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +0 -16
  758. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  759. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +0 -836
  760. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +0 -256
  761. package/.worktrees/c1eae35e/packages/dashboard/package.json +0 -25
  762. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +0 -95
  763. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +0 -679
  764. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +0 -526
  765. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +0 -357
  766. package/.worktrees/c1eae35e/src/agent-session-log.js +0 -803
  767. package/.worktrees/c1eae35e/src/change-list.js +0 -290
  768. package/.worktrees/c1eae35e/src/change-risk-profile.js +0 -339
  769. package/.worktrees/c1eae35e/src/check-primitives.js +0 -65
  770. package/.worktrees/c1eae35e/src/classify-change.js +0 -109
  771. package/.worktrees/c1eae35e/src/commit-suggest.js +0 -202
  772. package/.worktrees/c1eae35e/src/config-cat.js +0 -88
  773. package/.worktrees/c1eae35e/src/config-schema.js +0 -328
  774. package/.worktrees/c1eae35e/src/constants.js +0 -97
  775. package/.worktrees/c1eae35e/src/contract-matrix.js +0 -533
  776. package/.worktrees/c1eae35e/src/datetime.js +0 -20
  777. package/.worktrees/c1eae35e/src/db-engine.js +0 -55
  778. package/.worktrees/c1eae35e/src/db.js +0 -381
  779. package/.worktrees/c1eae35e/src/decision-distill.js +0 -517
  780. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +0 -155
  781. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +0 -245
  782. package/.worktrees/c1eae35e/src/dispatch/probe.js +0 -246
  783. package/.worktrees/c1eae35e/src/dispatch/strategy.js +0 -121
  784. package/.worktrees/c1eae35e/src/docs-check.js +0 -825
  785. package/.worktrees/c1eae35e/src/docs-debt.js +0 -393
  786. package/.worktrees/c1eae35e/src/docs-gate.js +0 -107
  787. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +0 -1099
  788. package/.worktrees/c1eae35e/src/endpoint-extractor.js +0 -409
  789. package/.worktrees/c1eae35e/src/foreign-declared.js +0 -155
  790. package/.worktrees/c1eae35e/src/fs-atomic.js +0 -73
  791. package/.worktrees/c1eae35e/src/git-helper.js +0 -150
  792. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +0 -130
  793. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +0 -892
  794. package/.worktrees/c1eae35e/src/index.js +0 -2854
  795. package/.worktrees/c1eae35e/src/init.js +0 -626
  796. package/.worktrees/c1eae35e/src/knowledge-match.js +0 -231
  797. package/.worktrees/c1eae35e/src/local-detect.js +0 -128
  798. package/.worktrees/c1eae35e/src/local-register.js +0 -104
  799. package/.worktrees/c1eae35e/src/machine-interface.js +0 -543
  800. package/.worktrees/c1eae35e/src/migrate.js +0 -127
  801. package/.worktrees/c1eae35e/src/module-impact.js +0 -166
  802. package/.worktrees/c1eae35e/src/module-resolve.js +0 -222
  803. package/.worktrees/c1eae35e/src/modules.js +0 -580
  804. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +0 -126
  805. package/.worktrees/c1eae35e/src/progress/change-registry.js +0 -336
  806. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +0 -355
  807. package/.worktrees/c1eae35e/src/progress/shared.js +0 -36
  808. package/.worktrees/c1eae35e/src/progress/stage-machine.js +0 -594
  809. package/.worktrees/c1eae35e/src/progress/step-store.js +0 -265
  810. package/.worktrees/c1eae35e/src/progress.js +0 -1304
  811. package/.worktrees/c1eae35e/src/quick-recommend.js +0 -115
  812. package/.worktrees/c1eae35e/src/quicklog.js +0 -883
  813. package/.worktrees/c1eae35e/src/review-tier.js +0 -77
  814. package/.worktrees/c1eae35e/src/run/command.js +0 -1641
  815. package/.worktrees/c1eae35e/src/run/complete-handlers.js +0 -1552
  816. package/.worktrees/c1eae35e/src/run/complete.js +0 -1259
  817. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +0 -156
  818. package/.worktrees/c1eae35e/src/run/gates.js +0 -1111
  819. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +0 -208
  820. package/.worktrees/c1eae35e/src/run/next.js +0 -128
  821. package/.worktrees/c1eae35e/src/run/prompt.js +0 -843
  822. package/.worktrees/c1eae35e/src/run/quick-audit.js +0 -186
  823. package/.worktrees/c1eae35e/src/run/scan-profile.js +0 -269
  824. package/.worktrees/c1eae35e/src/run/shared.js +0 -1562
  825. package/.worktrees/c1eae35e/src/run/stage.js +0 -587
  826. package/.worktrees/c1eae35e/src/run.js +0 -23
  827. package/.worktrees/c1eae35e/src/scan-diff.js +0 -388
  828. package/.worktrees/c1eae35e/src/scan-postcheck.js +0 -524
  829. package/.worktrees/c1eae35e/src/scan-staleness.js +0 -95
  830. package/.worktrees/c1eae35e/src/setup.js +0 -414
  831. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +0 -597
  832. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +0 -62
  833. package/.worktrees/c1eae35e/src/spec-dir-typo.js +0 -50
  834. package/.worktrees/c1eae35e/src/spec-sync.js +0 -358
  835. package/.worktrees/c1eae35e/src/stage-contract-engine.js +0 -171
  836. package/.worktrees/c1eae35e/src/stage-contract-spec.js +0 -551
  837. package/.worktrees/c1eae35e/src/stage-contract.js +0 -948
  838. package/.worktrees/c1eae35e/src/stage-review.js +0 -597
  839. package/.worktrees/c1eae35e/src/stages/archive.js +0 -199
  840. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +0 -285
  841. package/.worktrees/c1eae35e/src/stages/brainstorm.js +0 -624
  842. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +0 -145
  843. package/.worktrees/c1eae35e/src/stages/doctor.js +0 -540
  844. package/.worktrees/c1eae35e/src/stages/execute.js +0 -1277
  845. package/.worktrees/c1eae35e/src/stages/explore.js +0 -43
  846. package/.worktrees/c1eae35e/src/stages/index.js +0 -29
  847. package/.worktrees/c1eae35e/src/stages/knowledge.js +0 -514
  848. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +0 -1398
  849. package/.worktrees/c1eae35e/src/stages/plan.js +0 -655
  850. package/.worktrees/c1eae35e/src/stages/quick.js +0 -167
  851. package/.worktrees/c1eae35e/src/stages/scan.js +0 -608
  852. package/.worktrees/c1eae35e/src/stages/status.js +0 -64
  853. package/.worktrees/c1eae35e/src/stages/verify.js +0 -246
  854. package/.worktrees/c1eae35e/src/sync.js +0 -1470
  855. package/.worktrees/c1eae35e/src/task-review.js +0 -1498
  856. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +0 -21
  857. package/.worktrees/c1eae35e/src/taskcard.js +0 -250
  858. package/.worktrees/c1eae35e/src/verify-postcheck.js +0 -1718
  859. package/.worktrees/c1eae35e/src/verify-probes.js +0 -327
  860. package/.worktrees/c1eae35e/src/version.js +0 -19
  861. package/.worktrees/c1eae35e/src/workflow.js +0 -600
  862. package/.worktrees/c1eae35e/src/workspace.js +0 -125
  863. package/.worktrees/c1eae35e/src/worktree-apply.js +0 -1611
  864. package/.worktrees/c1eae35e/src/worktree-deps.js +0 -668
  865. package/.worktrees/c1eae35e/src/worktree.js +0 -1849
  866. package/.worktrees/c1eae35e/templates/claude-instruction.md +0 -23
  867. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +0 -29
  868. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +0 -12
  869. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +0 -32
  870. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +0 -79
  871. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +0 -132
  872. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  873. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  874. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  875. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  876. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  877. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  878. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  879. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  880. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +0 -57
  881. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +0 -177
  882. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  883. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  884. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  885. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  886. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  887. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  888. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +0 -64
  889. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +0 -54
  890. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  891. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  892. package/.worktrees/dafc71ad/.gitattributes +0 -2
  893. package/.worktrees/dafc71ad/.husky/pre-push +0 -20
  894. package/.worktrees/dafc71ad/README.md +0 -203
  895. package/.worktrees/dafc71ad/SKILL.md +0 -91
  896. package/.worktrees/dafc71ad/analysis.md +0 -366
  897. package/.worktrees/dafc71ad/architecture-analysis.md +0 -448
  898. package/.worktrees/dafc71ad/bin/sillyspec.js +0 -2
  899. package/.worktrees/dafc71ad/eval/README.md +0 -86
  900. package/.worktrees/dafc71ad/eval/eval.config.json +0 -28
  901. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +0 -63
  902. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +0 -27
  903. package/.worktrees/dafc71ad/eval/lib/config.mjs +0 -82
  904. package/.worktrees/dafc71ad/eval/lib/db.mjs +0 -76
  905. package/.worktrees/dafc71ad/eval/lib/report.mjs +0 -120
  906. package/.worktrees/dafc71ad/eval/lib/runner.mjs +0 -157
  907. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +0 -73
  908. package/.worktrees/dafc71ad/eval/lib/util.mjs +0 -107
  909. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +0 -30
  910. package/.worktrees/dafc71ad/eval/run.mjs +0 -83
  911. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +0 -6
  912. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  913. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +0 -6
  914. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +0 -28
  915. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +0 -6
  916. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  917. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  918. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +0 -6
  919. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +0 -31
  920. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  921. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +0 -6
  922. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  923. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +0 -6
  924. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +0 -38
  925. package/.worktrees/dafc71ad/logo.jpg +0 -0
  926. package/.worktrees/dafc71ad/package-lock.json +0 -977
  927. package/.worktrees/dafc71ad/package.json +0 -41
  928. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  929. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  930. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  931. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +0 -16
  932. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  933. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +0 -836
  934. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +0 -256
  935. package/.worktrees/dafc71ad/packages/dashboard/package.json +0 -25
  936. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +0 -95
  937. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +0 -679
  938. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +0 -526
  939. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +0 -357
  940. package/.worktrees/dafc71ad/src/agent-session-log.js +0 -803
  941. package/.worktrees/dafc71ad/src/change-list.js +0 -290
  942. package/.worktrees/dafc71ad/src/change-risk-profile.js +0 -339
  943. package/.worktrees/dafc71ad/src/check-primitives.js +0 -65
  944. package/.worktrees/dafc71ad/src/classify-change.js +0 -109
  945. package/.worktrees/dafc71ad/src/commit-suggest.js +0 -202
  946. package/.worktrees/dafc71ad/src/config-cat.js +0 -88
  947. package/.worktrees/dafc71ad/src/config-schema.js +0 -328
  948. package/.worktrees/dafc71ad/src/constants.js +0 -97
  949. package/.worktrees/dafc71ad/src/contract-matrix.js +0 -533
  950. package/.worktrees/dafc71ad/src/datetime.js +0 -20
  951. package/.worktrees/dafc71ad/src/db-engine.js +0 -55
  952. package/.worktrees/dafc71ad/src/db.js +0 -381
  953. package/.worktrees/dafc71ad/src/decision-distill.js +0 -517
  954. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +0 -155
  955. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +0 -245
  956. package/.worktrees/dafc71ad/src/dispatch/probe.js +0 -246
  957. package/.worktrees/dafc71ad/src/dispatch/strategy.js +0 -121
  958. package/.worktrees/dafc71ad/src/docs-check.js +0 -825
  959. package/.worktrees/dafc71ad/src/docs-debt.js +0 -393
  960. package/.worktrees/dafc71ad/src/docs-gate.js +0 -107
  961. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +0 -1099
  962. package/.worktrees/dafc71ad/src/endpoint-extractor.js +0 -409
  963. package/.worktrees/dafc71ad/src/foreign-declared.js +0 -155
  964. package/.worktrees/dafc71ad/src/fs-atomic.js +0 -73
  965. package/.worktrees/dafc71ad/src/git-helper.js +0 -150
  966. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +0 -130
  967. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +0 -892
  968. package/.worktrees/dafc71ad/src/index.js +0 -2854
  969. package/.worktrees/dafc71ad/src/init.js +0 -626
  970. package/.worktrees/dafc71ad/src/knowledge-match.js +0 -231
  971. package/.worktrees/dafc71ad/src/local-detect.js +0 -128
  972. package/.worktrees/dafc71ad/src/local-register.js +0 -104
  973. package/.worktrees/dafc71ad/src/machine-interface.js +0 -543
  974. package/.worktrees/dafc71ad/src/migrate.js +0 -127
  975. package/.worktrees/dafc71ad/src/module-impact.js +0 -166
  976. package/.worktrees/dafc71ad/src/module-resolve.js +0 -222
  977. package/.worktrees/dafc71ad/src/modules.js +0 -580
  978. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +0 -126
  979. package/.worktrees/dafc71ad/src/progress/change-registry.js +0 -336
  980. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +0 -355
  981. package/.worktrees/dafc71ad/src/progress/shared.js +0 -36
  982. package/.worktrees/dafc71ad/src/progress/stage-machine.js +0 -594
  983. package/.worktrees/dafc71ad/src/progress/step-store.js +0 -265
  984. package/.worktrees/dafc71ad/src/progress.js +0 -1304
  985. package/.worktrees/dafc71ad/src/quick-recommend.js +0 -115
  986. package/.worktrees/dafc71ad/src/quicklog.js +0 -883
  987. package/.worktrees/dafc71ad/src/review-tier.js +0 -77
  988. package/.worktrees/dafc71ad/src/run/command.js +0 -1641
  989. package/.worktrees/dafc71ad/src/run/complete-handlers.js +0 -1552
  990. package/.worktrees/dafc71ad/src/run/complete.js +0 -1259
  991. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +0 -156
  992. package/.worktrees/dafc71ad/src/run/gates.js +0 -1111
  993. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +0 -208
  994. package/.worktrees/dafc71ad/src/run/next.js +0 -128
  995. package/.worktrees/dafc71ad/src/run/prompt.js +0 -843
  996. package/.worktrees/dafc71ad/src/run/quick-audit.js +0 -186
  997. package/.worktrees/dafc71ad/src/run/scan-profile.js +0 -269
  998. package/.worktrees/dafc71ad/src/run/shared.js +0 -1562
  999. package/.worktrees/dafc71ad/src/run/stage.js +0 -587
  1000. package/.worktrees/dafc71ad/src/run.js +0 -23
  1001. package/.worktrees/dafc71ad/src/scan-diff.js +0 -388
  1002. package/.worktrees/dafc71ad/src/scan-postcheck.js +0 -524
  1003. package/.worktrees/dafc71ad/src/scan-staleness.js +0 -95
  1004. package/.worktrees/dafc71ad/src/setup.js +0 -414
  1005. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +0 -597
  1006. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +0 -62
  1007. package/.worktrees/dafc71ad/src/spec-dir-typo.js +0 -50
  1008. package/.worktrees/dafc71ad/src/spec-sync.js +0 -358
  1009. package/.worktrees/dafc71ad/src/stage-contract-engine.js +0 -171
  1010. package/.worktrees/dafc71ad/src/stage-contract-spec.js +0 -551
  1011. package/.worktrees/dafc71ad/src/stage-contract.js +0 -948
  1012. package/.worktrees/dafc71ad/src/stage-review.js +0 -597
  1013. package/.worktrees/dafc71ad/src/stages/archive.js +0 -199
  1014. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +0 -285
  1015. package/.worktrees/dafc71ad/src/stages/brainstorm.js +0 -624
  1016. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +0 -145
  1017. package/.worktrees/dafc71ad/src/stages/doctor.js +0 -540
  1018. package/.worktrees/dafc71ad/src/stages/execute.js +0 -1277
  1019. package/.worktrees/dafc71ad/src/stages/explore.js +0 -43
  1020. package/.worktrees/dafc71ad/src/stages/index.js +0 -29
  1021. package/.worktrees/dafc71ad/src/stages/knowledge.js +0 -514
  1022. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +0 -1398
  1023. package/.worktrees/dafc71ad/src/stages/plan.js +0 -655
  1024. package/.worktrees/dafc71ad/src/stages/quick.js +0 -167
  1025. package/.worktrees/dafc71ad/src/stages/scan.js +0 -608
  1026. package/.worktrees/dafc71ad/src/stages/status.js +0 -64
  1027. package/.worktrees/dafc71ad/src/stages/verify.js +0 -246
  1028. package/.worktrees/dafc71ad/src/sync.js +0 -1470
  1029. package/.worktrees/dafc71ad/src/task-review.js +0 -1498
  1030. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +0 -21
  1031. package/.worktrees/dafc71ad/src/taskcard.js +0 -250
  1032. package/.worktrees/dafc71ad/src/verify-postcheck.js +0 -1718
  1033. package/.worktrees/dafc71ad/src/verify-probes.js +0 -327
  1034. package/.worktrees/dafc71ad/src/version.js +0 -19
  1035. package/.worktrees/dafc71ad/src/workflow.js +0 -600
  1036. package/.worktrees/dafc71ad/src/workspace.js +0 -125
  1037. package/.worktrees/dafc71ad/src/worktree-apply.js +0 -1611
  1038. package/.worktrees/dafc71ad/src/worktree-deps.js +0 -668
  1039. package/.worktrees/dafc71ad/src/worktree.js +0 -1849
  1040. package/.worktrees/dafc71ad/templates/claude-instruction.md +0 -23
  1041. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +0 -29
  1042. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +0 -12
  1043. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +0 -32
  1044. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +0 -79
  1045. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +0 -132
  1046. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  1047. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  1048. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  1049. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  1050. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  1051. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  1052. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  1053. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  1054. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +0 -57
  1055. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +0 -177
  1056. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  1057. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  1058. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  1059. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  1060. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  1061. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  1062. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +0 -64
  1063. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +0 -54
  1064. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  1065. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  1066. package/.worktrees/e58fcc4c/.gitattributes +0 -2
  1067. package/.worktrees/e58fcc4c/.husky/pre-push +0 -20
  1068. package/.worktrees/e58fcc4c/README.md +0 -203
  1069. package/.worktrees/e58fcc4c/SKILL.md +0 -91
  1070. package/.worktrees/e58fcc4c/architecture-analysis.md +0 -503
  1071. package/.worktrees/e58fcc4c/bin/sillyspec.js +0 -2
  1072. package/.worktrees/e58fcc4c/eval/README.md +0 -86
  1073. package/.worktrees/e58fcc4c/eval/eval.config.json +0 -28
  1074. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +0 -63
  1075. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +0 -27
  1076. package/.worktrees/e58fcc4c/eval/lib/config.mjs +0 -82
  1077. package/.worktrees/e58fcc4c/eval/lib/db.mjs +0 -76
  1078. package/.worktrees/e58fcc4c/eval/lib/report.mjs +0 -120
  1079. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +0 -157
  1080. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +0 -73
  1081. package/.worktrees/e58fcc4c/eval/lib/util.mjs +0 -107
  1082. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +0 -30
  1083. package/.worktrees/e58fcc4c/eval/run.mjs +0 -83
  1084. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +0 -6
  1085. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  1086. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +0 -6
  1087. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +0 -28
  1088. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +0 -6
  1089. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  1090. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  1091. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +0 -6
  1092. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +0 -31
  1093. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  1094. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +0 -6
  1095. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  1096. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +0 -6
  1097. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +0 -38
  1098. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  1099. package/.worktrees/e58fcc4c/package-lock.json +0 -977
  1100. package/.worktrees/e58fcc4c/package.json +0 -41
  1101. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  1102. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  1103. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  1104. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +0 -16
  1105. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  1106. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +0 -836
  1107. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +0 -256
  1108. package/.worktrees/e58fcc4c/packages/dashboard/package.json +0 -25
  1109. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +0 -95
  1110. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +0 -679
  1111. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +0 -526
  1112. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +0 -357
  1113. package/.worktrees/e58fcc4c/src/agent-session-log.js +0 -803
  1114. package/.worktrees/e58fcc4c/src/change-list.js +0 -290
  1115. package/.worktrees/e58fcc4c/src/change-risk-profile.js +0 -339
  1116. package/.worktrees/e58fcc4c/src/check-primitives.js +0 -65
  1117. package/.worktrees/e58fcc4c/src/classify-change.js +0 -109
  1118. package/.worktrees/e58fcc4c/src/commit-suggest.js +0 -202
  1119. package/.worktrees/e58fcc4c/src/config-cat.js +0 -88
  1120. package/.worktrees/e58fcc4c/src/config-schema.js +0 -328
  1121. package/.worktrees/e58fcc4c/src/constants.js +0 -97
  1122. package/.worktrees/e58fcc4c/src/contract-matrix.js +0 -533
  1123. package/.worktrees/e58fcc4c/src/datetime.js +0 -20
  1124. package/.worktrees/e58fcc4c/src/db-engine.js +0 -55
  1125. package/.worktrees/e58fcc4c/src/db.js +0 -381
  1126. package/.worktrees/e58fcc4c/src/decision-distill.js +0 -517
  1127. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +0 -155
  1128. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +0 -245
  1129. package/.worktrees/e58fcc4c/src/dispatch/probe.js +0 -246
  1130. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +0 -121
  1131. package/.worktrees/e58fcc4c/src/docs-check.js +0 -825
  1132. package/.worktrees/e58fcc4c/src/docs-debt.js +0 -393
  1133. package/.worktrees/e58fcc4c/src/docs-gate.js +0 -107
  1134. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +0 -1099
  1135. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +0 -409
  1136. package/.worktrees/e58fcc4c/src/foreign-declared.js +0 -155
  1137. package/.worktrees/e58fcc4c/src/fs-atomic.js +0 -73
  1138. package/.worktrees/e58fcc4c/src/git-helper.js +0 -150
  1139. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +0 -130
  1140. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +0 -892
  1141. package/.worktrees/e58fcc4c/src/index.js +0 -2854
  1142. package/.worktrees/e58fcc4c/src/init.js +0 -626
  1143. package/.worktrees/e58fcc4c/src/knowledge-match.js +0 -231
  1144. package/.worktrees/e58fcc4c/src/local-detect.js +0 -128
  1145. package/.worktrees/e58fcc4c/src/local-register.js +0 -104
  1146. package/.worktrees/e58fcc4c/src/machine-interface.js +0 -543
  1147. package/.worktrees/e58fcc4c/src/migrate.js +0 -127
  1148. package/.worktrees/e58fcc4c/src/module-impact.js +0 -166
  1149. package/.worktrees/e58fcc4c/src/module-resolve.js +0 -222
  1150. package/.worktrees/e58fcc4c/src/modules.js +0 -580
  1151. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +0 -126
  1152. package/.worktrees/e58fcc4c/src/progress/change-registry.js +0 -336
  1153. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +0 -355
  1154. package/.worktrees/e58fcc4c/src/progress/shared.js +0 -36
  1155. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +0 -594
  1156. package/.worktrees/e58fcc4c/src/progress/step-store.js +0 -265
  1157. package/.worktrees/e58fcc4c/src/progress.js +0 -1304
  1158. package/.worktrees/e58fcc4c/src/quick-recommend.js +0 -115
  1159. package/.worktrees/e58fcc4c/src/quicklog.js +0 -883
  1160. package/.worktrees/e58fcc4c/src/review-tier.js +0 -77
  1161. package/.worktrees/e58fcc4c/src/run/command.js +0 -1641
  1162. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +0 -1552
  1163. package/.worktrees/e58fcc4c/src/run/complete.js +0 -1259
  1164. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +0 -156
  1165. package/.worktrees/e58fcc4c/src/run/gates.js +0 -1111
  1166. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +0 -208
  1167. package/.worktrees/e58fcc4c/src/run/next.js +0 -128
  1168. package/.worktrees/e58fcc4c/src/run/prompt.js +0 -843
  1169. package/.worktrees/e58fcc4c/src/run/quick-audit.js +0 -186
  1170. package/.worktrees/e58fcc4c/src/run/scan-profile.js +0 -269
  1171. package/.worktrees/e58fcc4c/src/run/shared.js +0 -1562
  1172. package/.worktrees/e58fcc4c/src/run/stage.js +0 -587
  1173. package/.worktrees/e58fcc4c/src/run.js +0 -23
  1174. package/.worktrees/e58fcc4c/src/scan-diff.js +0 -388
  1175. package/.worktrees/e58fcc4c/src/scan-postcheck.js +0 -524
  1176. package/.worktrees/e58fcc4c/src/scan-staleness.js +0 -95
  1177. package/.worktrees/e58fcc4c/src/setup.js +0 -414
  1178. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +0 -597
  1179. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +0 -62
  1180. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +0 -50
  1181. package/.worktrees/e58fcc4c/src/spec-sync.js +0 -358
  1182. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +0 -171
  1183. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +0 -551
  1184. package/.worktrees/e58fcc4c/src/stage-contract.js +0 -948
  1185. package/.worktrees/e58fcc4c/src/stage-review.js +0 -597
  1186. package/.worktrees/e58fcc4c/src/stages/archive.js +0 -199
  1187. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +0 -285
  1188. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +0 -624
  1189. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +0 -145
  1190. package/.worktrees/e58fcc4c/src/stages/doctor.js +0 -540
  1191. package/.worktrees/e58fcc4c/src/stages/execute.js +0 -1277
  1192. package/.worktrees/e58fcc4c/src/stages/explore.js +0 -43
  1193. package/.worktrees/e58fcc4c/src/stages/index.js +0 -29
  1194. package/.worktrees/e58fcc4c/src/stages/knowledge.js +0 -514
  1195. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +0 -1398
  1196. package/.worktrees/e58fcc4c/src/stages/plan.js +0 -655
  1197. package/.worktrees/e58fcc4c/src/stages/quick.js +0 -167
  1198. package/.worktrees/e58fcc4c/src/stages/scan.js +0 -608
  1199. package/.worktrees/e58fcc4c/src/stages/status.js +0 -64
  1200. package/.worktrees/e58fcc4c/src/stages/verify.js +0 -246
  1201. package/.worktrees/e58fcc4c/src/sync.js +0 -1470
  1202. package/.worktrees/e58fcc4c/src/task-review.js +0 -1498
  1203. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +0 -21
  1204. package/.worktrees/e58fcc4c/src/taskcard.js +0 -250
  1205. package/.worktrees/e58fcc4c/src/verify-postcheck.js +0 -1718
  1206. package/.worktrees/e58fcc4c/src/verify-probes.js +0 -327
  1207. package/.worktrees/e58fcc4c/src/version.js +0 -19
  1208. package/.worktrees/e58fcc4c/src/workflow.js +0 -600
  1209. package/.worktrees/e58fcc4c/src/workspace.js +0 -125
  1210. package/.worktrees/e58fcc4c/src/worktree-apply.js +0 -1611
  1211. package/.worktrees/e58fcc4c/src/worktree-deps.js +0 -668
  1212. package/.worktrees/e58fcc4c/src/worktree.js +0 -1849
  1213. package/.worktrees/e58fcc4c/templates/claude-instruction.md +0 -23
  1214. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +0 -29
  1215. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +0 -12
  1216. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +0 -32
  1217. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +0 -79
  1218. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +0 -132
  1219. package/templates/claude-instruction.md +0 -23
@@ -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
- }