sillyspec 3.27.12 → 3.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1234) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +214 -214
  2. package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
  3. package/.claude/skills/sillyspec-quick/SKILL.md +116 -116
  4. package/package.json +1 -1
  5. package/src/agent-session-log.js +77 -10
  6. package/src/archive-delta.js +419 -0
  7. package/src/config-schema.js +2 -2
  8. package/src/contract-matrix.js +15 -2
  9. package/src/design-facts.js +354 -0
  10. package/src/docs-check.js +79 -8
  11. package/src/doctor-diagnostics.js +75 -3
  12. package/src/endpoint-baseline.js +109 -0
  13. package/src/endpoint-extractor.js +100 -24
  14. package/src/git-helper.js +31 -0
  15. package/src/index.js +248 -8
  16. package/src/machine-interface.js +63 -0
  17. package/src/modules.js +41 -12
  18. package/src/progress/change-registry.js +20 -0
  19. package/src/progress/consistency-doctor.js +124 -5
  20. package/src/progress/stage-machine.js +118 -2
  21. package/src/progress.js +6 -0
  22. package/src/quicklog.js +51 -0
  23. package/src/run/command.js +71 -2
  24. package/src/run/complete-handlers.js +84 -7
  25. package/src/run/complete.js +58 -5
  26. package/src/run/gates.js +333 -2
  27. package/src/run/prompt.js +70 -0
  28. package/src/run/quick-audit.js +98 -0
  29. package/src/run/scan-profile.js +98 -6
  30. package/src/run/shared.js +66 -1
  31. package/src/run/stage.js +25 -12
  32. package/src/scan-diff.js +54 -1
  33. package/src/scan-facts.js +173 -0
  34. package/src/scan-postcheck.js +110 -3
  35. package/src/spec-sync.js +210 -16
  36. package/src/stage-review.js +62 -3
  37. package/src/stages/archive.js +5 -5
  38. package/src/stages/brainstorm.js +10 -10
  39. package/src/stages/execute.js +21 -15
  40. package/src/stages/plan-postcheck.js +194 -1
  41. package/src/stages/plan.js +6 -2
  42. package/src/stages/scan.js +44 -102
  43. package/src/stages/verify.js +9 -7
  44. package/src/sync.js +122 -4
  45. package/src/task-review.js +51 -4
  46. package/src/taskcard.js +8 -1
  47. package/src/verify-postcheck.js +670 -10
  48. package/src/verify-probes.js +92 -10
  49. package/src/workflow.js +30 -0
  50. package/templates/agents-instruction.md +1 -1
  51. package/templates/prompts/taskcard-rules.md +5 -0
  52. package/templates/workflows/scan-docs.yaml +6 -0
  53. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  54. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  55. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  56. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  57. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  58. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  59. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  60. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  61. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +0 -57
  62. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +0 -177
  63. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  64. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  65. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  66. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  67. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  68. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +0 -64
  69. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +0 -54
  70. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  71. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  72. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +0 -2
  73. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +0 -20
  74. package/.claude/worktrees/sillyspec-data-model-research/README.md +0 -203
  75. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +0 -91
  76. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +0 -2
  77. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  78. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +0 -977
  79. package/.claude/worktrees/sillyspec-data-model-research/package.json +0 -39
  80. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  81. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  82. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  83. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +0 -16
  84. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  85. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +0 -836
  86. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +0 -256
  87. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +0 -25
  88. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +0 -95
  89. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +0 -679
  90. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +0 -526
  91. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +0 -357
  92. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +0 -803
  93. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +0 -290
  94. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +0 -270
  95. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +0 -65
  96. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +0 -109
  97. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +0 -202
  98. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +0 -88
  99. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +0 -328
  100. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +0 -97
  101. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +0 -480
  102. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +0 -20
  103. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +0 -55
  104. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +0 -381
  105. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +0 -517
  106. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +0 -155
  107. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +0 -245
  108. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +0 -246
  109. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +0 -121
  110. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +0 -825
  111. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +0 -393
  112. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +0 -107
  113. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +0 -1099
  114. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +0 -420
  115. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +0 -78
  116. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +0 -73
  117. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +0 -150
  118. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +0 -130
  119. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +0 -892
  120. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +0 -2798
  121. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +0 -626
  122. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +0 -231
  123. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +0 -128
  124. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +0 -104
  125. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +0 -543
  126. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +0 -127
  127. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +0 -166
  128. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +0 -222
  129. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +0 -580
  130. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +0 -336
  131. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +0 -355
  132. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +0 -36
  133. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +0 -594
  134. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +0 -265
  135. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +0 -1304
  136. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +0 -115
  137. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +0 -852
  138. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +0 -77
  139. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +0 -1595
  140. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +0 -1552
  141. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +0 -1259
  142. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +0 -156
  143. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +0 -1084
  144. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +0 -208
  145. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +0 -128
  146. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +0 -843
  147. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +0 -186
  148. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +0 -269
  149. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +0 -1562
  150. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +0 -584
  151. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +0 -23
  152. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +0 -388
  153. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +0 -512
  154. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +0 -95
  155. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +0 -414
  156. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +0 -597
  157. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +0 -62
  158. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +0 -50
  159. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +0 -358
  160. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +0 -171
  161. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +0 -550
  162. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +0 -889
  163. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +0 -597
  164. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +0 -199
  165. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +0 -236
  166. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +0 -617
  167. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +0 -145
  168. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +0 -540
  169. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +0 -1275
  170. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +0 -43
  171. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +0 -29
  172. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +0 -514
  173. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +0 -1344
  174. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +0 -650
  175. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +0 -167
  176. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +0 -608
  177. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +0 -64
  178. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +0 -246
  179. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +0 -1470
  180. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +0 -1498
  181. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +0 -210
  182. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +0 -1718
  183. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +0 -277
  184. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +0 -19
  185. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +0 -600
  186. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +0 -125
  187. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +0 -1446
  188. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +0 -576
  189. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +0 -1715
  190. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +0 -23
  191. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +0 -28
  192. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +0 -12
  193. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +0 -32
  194. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +0 -79
  195. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +0 -132
  196. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  197. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  198. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  199. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  200. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  201. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  202. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  203. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  204. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +0 -57
  205. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +0 -177
  206. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  207. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  208. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  209. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  210. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  211. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  212. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +0 -64
  213. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +0 -54
  214. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  215. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  216. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +0 -6
  217. package/.worktrees/2c37b1d7/.gitattributes +0 -2
  218. package/.worktrees/2c37b1d7/.husky/pre-push +0 -20
  219. package/.worktrees/2c37b1d7/README.md +0 -203
  220. package/.worktrees/2c37b1d7/SKILL.md +0 -91
  221. package/.worktrees/2c37b1d7/architecture-analysis.md +0 -448
  222. package/.worktrees/2c37b1d7/bin/sillyspec.js +0 -2
  223. package/.worktrees/2c37b1d7/eval/README.md +0 -86
  224. package/.worktrees/2c37b1d7/eval/eval.config.json +0 -28
  225. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +0 -63
  226. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +0 -27
  227. package/.worktrees/2c37b1d7/eval/lib/config.mjs +0 -82
  228. package/.worktrees/2c37b1d7/eval/lib/db.mjs +0 -76
  229. package/.worktrees/2c37b1d7/eval/lib/report.mjs +0 -120
  230. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +0 -157
  231. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +0 -73
  232. package/.worktrees/2c37b1d7/eval/lib/util.mjs +0 -107
  233. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +0 -30
  234. package/.worktrees/2c37b1d7/eval/run.mjs +0 -83
  235. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +0 -6
  236. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  237. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +0 -6
  238. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +0 -28
  239. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +0 -6
  240. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  241. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  242. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +0 -6
  243. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +0 -31
  244. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  245. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +0 -6
  246. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  247. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +0 -6
  248. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +0 -38
  249. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  250. package/.worktrees/2c37b1d7/package-lock.json +0 -977
  251. package/.worktrees/2c37b1d7/package.json +0 -41
  252. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  253. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  254. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  255. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +0 -16
  256. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  257. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +0 -836
  258. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +0 -256
  259. package/.worktrees/2c37b1d7/packages/dashboard/package.json +0 -25
  260. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +0 -95
  261. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +0 -679
  262. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +0 -526
  263. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +0 -357
  264. package/.worktrees/2c37b1d7/src/agent-session-log.js +0 -803
  265. package/.worktrees/2c37b1d7/src/change-list.js +0 -290
  266. package/.worktrees/2c37b1d7/src/change-risk-profile.js +0 -339
  267. package/.worktrees/2c37b1d7/src/check-primitives.js +0 -65
  268. package/.worktrees/2c37b1d7/src/classify-change.js +0 -109
  269. package/.worktrees/2c37b1d7/src/commit-suggest.js +0 -202
  270. package/.worktrees/2c37b1d7/src/config-cat.js +0 -88
  271. package/.worktrees/2c37b1d7/src/config-schema.js +0 -328
  272. package/.worktrees/2c37b1d7/src/constants.js +0 -97
  273. package/.worktrees/2c37b1d7/src/contract-matrix.js +0 -533
  274. package/.worktrees/2c37b1d7/src/datetime.js +0 -20
  275. package/.worktrees/2c37b1d7/src/db-engine.js +0 -55
  276. package/.worktrees/2c37b1d7/src/db.js +0 -381
  277. package/.worktrees/2c37b1d7/src/decision-distill.js +0 -517
  278. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +0 -155
  279. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +0 -245
  280. package/.worktrees/2c37b1d7/src/dispatch/probe.js +0 -246
  281. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +0 -121
  282. package/.worktrees/2c37b1d7/src/docs-check.js +0 -825
  283. package/.worktrees/2c37b1d7/src/docs-debt.js +0 -393
  284. package/.worktrees/2c37b1d7/src/docs-gate.js +0 -107
  285. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +0 -1099
  286. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +0 -409
  287. package/.worktrees/2c37b1d7/src/foreign-declared.js +0 -155
  288. package/.worktrees/2c37b1d7/src/fs-atomic.js +0 -73
  289. package/.worktrees/2c37b1d7/src/git-helper.js +0 -150
  290. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +0 -130
  291. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +0 -892
  292. package/.worktrees/2c37b1d7/src/index.js +0 -2854
  293. package/.worktrees/2c37b1d7/src/init.js +0 -626
  294. package/.worktrees/2c37b1d7/src/knowledge-match.js +0 -231
  295. package/.worktrees/2c37b1d7/src/local-detect.js +0 -128
  296. package/.worktrees/2c37b1d7/src/local-register.js +0 -104
  297. package/.worktrees/2c37b1d7/src/machine-interface.js +0 -543
  298. package/.worktrees/2c37b1d7/src/migrate.js +0 -127
  299. package/.worktrees/2c37b1d7/src/module-impact.js +0 -166
  300. package/.worktrees/2c37b1d7/src/module-resolve.js +0 -222
  301. package/.worktrees/2c37b1d7/src/modules.js +0 -580
  302. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +0 -126
  303. package/.worktrees/2c37b1d7/src/progress/change-registry.js +0 -336
  304. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +0 -355
  305. package/.worktrees/2c37b1d7/src/progress/shared.js +0 -36
  306. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +0 -594
  307. package/.worktrees/2c37b1d7/src/progress/step-store.js +0 -265
  308. package/.worktrees/2c37b1d7/src/progress.js +0 -1304
  309. package/.worktrees/2c37b1d7/src/quick-recommend.js +0 -115
  310. package/.worktrees/2c37b1d7/src/quicklog.js +0 -883
  311. package/.worktrees/2c37b1d7/src/review-tier.js +0 -77
  312. package/.worktrees/2c37b1d7/src/run/command.js +0 -1641
  313. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +0 -1552
  314. package/.worktrees/2c37b1d7/src/run/complete.js +0 -1259
  315. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +0 -156
  316. package/.worktrees/2c37b1d7/src/run/gates.js +0 -1111
  317. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +0 -208
  318. package/.worktrees/2c37b1d7/src/run/next.js +0 -128
  319. package/.worktrees/2c37b1d7/src/run/prompt.js +0 -843
  320. package/.worktrees/2c37b1d7/src/run/quick-audit.js +0 -186
  321. package/.worktrees/2c37b1d7/src/run/scan-profile.js +0 -269
  322. package/.worktrees/2c37b1d7/src/run/shared.js +0 -1562
  323. package/.worktrees/2c37b1d7/src/run/stage.js +0 -587
  324. package/.worktrees/2c37b1d7/src/run.js +0 -23
  325. package/.worktrees/2c37b1d7/src/scan-diff.js +0 -388
  326. package/.worktrees/2c37b1d7/src/scan-postcheck.js +0 -524
  327. package/.worktrees/2c37b1d7/src/scan-staleness.js +0 -95
  328. package/.worktrees/2c37b1d7/src/setup.js +0 -414
  329. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +0 -597
  330. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +0 -62
  331. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +0 -50
  332. package/.worktrees/2c37b1d7/src/spec-sync.js +0 -358
  333. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +0 -171
  334. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +0 -551
  335. package/.worktrees/2c37b1d7/src/stage-contract.js +0 -948
  336. package/.worktrees/2c37b1d7/src/stage-review.js +0 -597
  337. package/.worktrees/2c37b1d7/src/stages/archive.js +0 -199
  338. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +0 -285
  339. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +0 -624
  340. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +0 -145
  341. package/.worktrees/2c37b1d7/src/stages/doctor.js +0 -540
  342. package/.worktrees/2c37b1d7/src/stages/execute.js +0 -1277
  343. package/.worktrees/2c37b1d7/src/stages/explore.js +0 -43
  344. package/.worktrees/2c37b1d7/src/stages/index.js +0 -29
  345. package/.worktrees/2c37b1d7/src/stages/knowledge.js +0 -514
  346. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +0 -1398
  347. package/.worktrees/2c37b1d7/src/stages/plan.js +0 -655
  348. package/.worktrees/2c37b1d7/src/stages/quick.js +0 -167
  349. package/.worktrees/2c37b1d7/src/stages/scan.js +0 -608
  350. package/.worktrees/2c37b1d7/src/stages/status.js +0 -64
  351. package/.worktrees/2c37b1d7/src/stages/verify.js +0 -246
  352. package/.worktrees/2c37b1d7/src/sync.js +0 -1470
  353. package/.worktrees/2c37b1d7/src/task-review.js +0 -1498
  354. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +0 -21
  355. package/.worktrees/2c37b1d7/src/taskcard.js +0 -250
  356. package/.worktrees/2c37b1d7/src/verify-postcheck.js +0 -1718
  357. package/.worktrees/2c37b1d7/src/verify-probes.js +0 -327
  358. package/.worktrees/2c37b1d7/src/version.js +0 -19
  359. package/.worktrees/2c37b1d7/src/workflow.js +0 -600
  360. package/.worktrees/2c37b1d7/src/workspace.js +0 -125
  361. package/.worktrees/2c37b1d7/src/worktree-apply.js +0 -1611
  362. package/.worktrees/2c37b1d7/src/worktree-deps.js +0 -668
  363. package/.worktrees/2c37b1d7/src/worktree.js +0 -1849
  364. package/.worktrees/2c37b1d7/templates/claude-instruction.md +0 -23
  365. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +0 -29
  366. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +0 -12
  367. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +0 -32
  368. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +0 -79
  369. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +0 -132
  370. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  371. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  372. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  373. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  374. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  375. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  376. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  377. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  378. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +0 -57
  379. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +0 -177
  380. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  381. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  382. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  383. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  384. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  385. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +0 -64
  386. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +0 -54
  387. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  388. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  389. package/.worktrees/542c4415/.gitattributes +0 -2
  390. package/.worktrees/542c4415/.husky/pre-push +0 -20
  391. package/.worktrees/542c4415/README.md +0 -203
  392. package/.worktrees/542c4415/SKILL.md +0 -91
  393. package/.worktrees/542c4415/architecture-analysis.md +0 -448
  394. package/.worktrees/542c4415/bin/sillyspec.js +0 -2
  395. package/.worktrees/542c4415/eval/README.md +0 -86
  396. package/.worktrees/542c4415/eval/eval.config.json +0 -28
  397. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +0 -63
  398. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +0 -27
  399. package/.worktrees/542c4415/eval/lib/config.mjs +0 -82
  400. package/.worktrees/542c4415/eval/lib/db.mjs +0 -76
  401. package/.worktrees/542c4415/eval/lib/report.mjs +0 -120
  402. package/.worktrees/542c4415/eval/lib/runner.mjs +0 -157
  403. package/.worktrees/542c4415/eval/lib/tasks.mjs +0 -73
  404. package/.worktrees/542c4415/eval/lib/util.mjs +0 -107
  405. package/.worktrees/542c4415/eval/lib/workdir.mjs +0 -30
  406. package/.worktrees/542c4415/eval/run.mjs +0 -83
  407. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +0 -6
  408. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  409. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +0 -6
  410. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +0 -28
  411. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +0 -6
  412. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  413. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  414. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +0 -6
  415. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +0 -31
  416. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  417. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +0 -6
  418. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  419. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +0 -6
  420. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +0 -38
  421. package/.worktrees/542c4415/logo.jpg +0 -0
  422. package/.worktrees/542c4415/package-lock.json +0 -977
  423. package/.worktrees/542c4415/package.json +0 -41
  424. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  425. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  426. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  427. package/.worktrees/542c4415/packages/dashboard/dist/index.html +0 -16
  428. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  429. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +0 -836
  430. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +0 -256
  431. package/.worktrees/542c4415/packages/dashboard/package.json +0 -25
  432. package/.worktrees/542c4415/packages/dashboard/server/executor.js +0 -95
  433. package/.worktrees/542c4415/packages/dashboard/server/index.js +0 -679
  434. package/.worktrees/542c4415/packages/dashboard/server/parser.js +0 -526
  435. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +0 -357
  436. package/.worktrees/542c4415/src/agent-session-log.js +0 -803
  437. package/.worktrees/542c4415/src/change-list.js +0 -290
  438. package/.worktrees/542c4415/src/change-risk-profile.js +0 -339
  439. package/.worktrees/542c4415/src/check-primitives.js +0 -65
  440. package/.worktrees/542c4415/src/classify-change.js +0 -109
  441. package/.worktrees/542c4415/src/commit-suggest.js +0 -202
  442. package/.worktrees/542c4415/src/config-cat.js +0 -88
  443. package/.worktrees/542c4415/src/config-schema.js +0 -328
  444. package/.worktrees/542c4415/src/constants.js +0 -97
  445. package/.worktrees/542c4415/src/contract-matrix.js +0 -533
  446. package/.worktrees/542c4415/src/datetime.js +0 -20
  447. package/.worktrees/542c4415/src/db-engine.js +0 -55
  448. package/.worktrees/542c4415/src/db.js +0 -381
  449. package/.worktrees/542c4415/src/decision-distill.js +0 -517
  450. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +0 -155
  451. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +0 -245
  452. package/.worktrees/542c4415/src/dispatch/probe.js +0 -246
  453. package/.worktrees/542c4415/src/dispatch/strategy.js +0 -121
  454. package/.worktrees/542c4415/src/docs-check.js +0 -825
  455. package/.worktrees/542c4415/src/docs-debt.js +0 -393
  456. package/.worktrees/542c4415/src/docs-gate.js +0 -107
  457. package/.worktrees/542c4415/src/doctor-diagnostics.js +0 -1099
  458. package/.worktrees/542c4415/src/endpoint-extractor.js +0 -409
  459. package/.worktrees/542c4415/src/foreign-declared.js +0 -155
  460. package/.worktrees/542c4415/src/fs-atomic.js +0 -73
  461. package/.worktrees/542c4415/src/git-helper.js +0 -150
  462. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +0 -130
  463. package/.worktrees/542c4415/src/hooks/worktree-guard.js +0 -892
  464. package/.worktrees/542c4415/src/index.js +0 -2854
  465. package/.worktrees/542c4415/src/init.js +0 -626
  466. package/.worktrees/542c4415/src/knowledge-match.js +0 -231
  467. package/.worktrees/542c4415/src/local-detect.js +0 -128
  468. package/.worktrees/542c4415/src/local-register.js +0 -104
  469. package/.worktrees/542c4415/src/machine-interface.js +0 -543
  470. package/.worktrees/542c4415/src/migrate.js +0 -127
  471. package/.worktrees/542c4415/src/module-impact.js +0 -166
  472. package/.worktrees/542c4415/src/module-resolve.js +0 -222
  473. package/.worktrees/542c4415/src/modules.js +0 -580
  474. package/.worktrees/542c4415/src/plan-adopt-waves.js +0 -126
  475. package/.worktrees/542c4415/src/progress/change-registry.js +0 -336
  476. package/.worktrees/542c4415/src/progress/consistency-doctor.js +0 -355
  477. package/.worktrees/542c4415/src/progress/shared.js +0 -36
  478. package/.worktrees/542c4415/src/progress/stage-machine.js +0 -594
  479. package/.worktrees/542c4415/src/progress/step-store.js +0 -265
  480. package/.worktrees/542c4415/src/progress.js +0 -1304
  481. package/.worktrees/542c4415/src/quick-recommend.js +0 -115
  482. package/.worktrees/542c4415/src/quicklog.js +0 -883
  483. package/.worktrees/542c4415/src/review-tier.js +0 -77
  484. package/.worktrees/542c4415/src/run/command.js +0 -1641
  485. package/.worktrees/542c4415/src/run/complete-handlers.js +0 -1552
  486. package/.worktrees/542c4415/src/run/complete.js +0 -1259
  487. package/.worktrees/542c4415/src/run/concurrent-detect.js +0 -156
  488. package/.worktrees/542c4415/src/run/gates.js +0 -1111
  489. package/.worktrees/542c4415/src/run/multi-repo-context.js +0 -208
  490. package/.worktrees/542c4415/src/run/next.js +0 -128
  491. package/.worktrees/542c4415/src/run/prompt.js +0 -843
  492. package/.worktrees/542c4415/src/run/quick-audit.js +0 -186
  493. package/.worktrees/542c4415/src/run/scan-profile.js +0 -269
  494. package/.worktrees/542c4415/src/run/shared.js +0 -1562
  495. package/.worktrees/542c4415/src/run/stage.js +0 -587
  496. package/.worktrees/542c4415/src/run.js +0 -23
  497. package/.worktrees/542c4415/src/scan-diff.js +0 -388
  498. package/.worktrees/542c4415/src/scan-postcheck.js +0 -524
  499. package/.worktrees/542c4415/src/scan-staleness.js +0 -95
  500. package/.worktrees/542c4415/src/setup.js +0 -414
  501. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +0 -597
  502. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +0 -62
  503. package/.worktrees/542c4415/src/spec-dir-typo.js +0 -50
  504. package/.worktrees/542c4415/src/spec-sync.js +0 -358
  505. package/.worktrees/542c4415/src/stage-contract-engine.js +0 -171
  506. package/.worktrees/542c4415/src/stage-contract-spec.js +0 -551
  507. package/.worktrees/542c4415/src/stage-contract.js +0 -948
  508. package/.worktrees/542c4415/src/stage-review.js +0 -597
  509. package/.worktrees/542c4415/src/stages/archive.js +0 -199
  510. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +0 -285
  511. package/.worktrees/542c4415/src/stages/brainstorm.js +0 -624
  512. package/.worktrees/542c4415/src/stages/cmd-existence.js +0 -145
  513. package/.worktrees/542c4415/src/stages/doctor.js +0 -540
  514. package/.worktrees/542c4415/src/stages/execute.js +0 -1277
  515. package/.worktrees/542c4415/src/stages/explore.js +0 -43
  516. package/.worktrees/542c4415/src/stages/index.js +0 -29
  517. package/.worktrees/542c4415/src/stages/knowledge.js +0 -514
  518. package/.worktrees/542c4415/src/stages/plan-postcheck.js +0 -1398
  519. package/.worktrees/542c4415/src/stages/plan.js +0 -655
  520. package/.worktrees/542c4415/src/stages/quick.js +0 -167
  521. package/.worktrees/542c4415/src/stages/scan.js +0 -608
  522. package/.worktrees/542c4415/src/stages/status.js +0 -64
  523. package/.worktrees/542c4415/src/stages/verify.js +0 -246
  524. package/.worktrees/542c4415/src/sync.js +0 -1470
  525. package/.worktrees/542c4415/src/task-review.js +0 -1498
  526. package/.worktrees/542c4415/src/taskcard-placeholders.js +0 -21
  527. package/.worktrees/542c4415/src/taskcard.js +0 -250
  528. package/.worktrees/542c4415/src/verify-postcheck.js +0 -1718
  529. package/.worktrees/542c4415/src/verify-probes.js +0 -327
  530. package/.worktrees/542c4415/src/version.js +0 -19
  531. package/.worktrees/542c4415/src/workflow.js +0 -600
  532. package/.worktrees/542c4415/src/workspace.js +0 -125
  533. package/.worktrees/542c4415/src/worktree-apply.js +0 -1611
  534. package/.worktrees/542c4415/src/worktree-deps.js +0 -668
  535. package/.worktrees/542c4415/src/worktree.js +0 -1849
  536. package/.worktrees/542c4415/templates/claude-instruction.md +0 -23
  537. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +0 -29
  538. package/.worktrees/542c4415/templates/prompts/testcase-design.md +0 -12
  539. package/.worktrees/542c4415/templates/prompts/verify-probes.md +0 -32
  540. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +0 -79
  541. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +0 -132
  542. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  543. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  544. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  545. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  546. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  547. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  548. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  549. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  550. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +0 -57
  551. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +0 -177
  552. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  553. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  554. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  555. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  556. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  557. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  558. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +0 -64
  559. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +0 -54
  560. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  561. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  562. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +0 -6
  563. package/.worktrees/8d2d0392/.gitattributes +0 -2
  564. package/.worktrees/8d2d0392/.husky/pre-push +0 -20
  565. package/.worktrees/8d2d0392/README.md +0 -203
  566. package/.worktrees/8d2d0392/SKILL.md +0 -91
  567. package/.worktrees/8d2d0392/architecture-analysis.md +0 -448
  568. package/.worktrees/8d2d0392/bin/sillyspec.js +0 -2
  569. package/.worktrees/8d2d0392/eval/README.md +0 -86
  570. package/.worktrees/8d2d0392/eval/eval.config.json +0 -28
  571. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +0 -63
  572. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +0 -27
  573. package/.worktrees/8d2d0392/eval/lib/config.mjs +0 -82
  574. package/.worktrees/8d2d0392/eval/lib/db.mjs +0 -76
  575. package/.worktrees/8d2d0392/eval/lib/report.mjs +0 -120
  576. package/.worktrees/8d2d0392/eval/lib/runner.mjs +0 -157
  577. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +0 -73
  578. package/.worktrees/8d2d0392/eval/lib/util.mjs +0 -107
  579. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +0 -30
  580. package/.worktrees/8d2d0392/eval/run.mjs +0 -83
  581. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +0 -6
  582. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  583. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +0 -6
  584. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +0 -28
  585. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +0 -6
  586. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  587. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  588. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +0 -6
  589. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +0 -31
  590. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  591. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +0 -6
  592. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  593. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +0 -6
  594. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +0 -38
  595. package/.worktrees/8d2d0392/logo.jpg +0 -0
  596. package/.worktrees/8d2d0392/package-lock.json +0 -977
  597. package/.worktrees/8d2d0392/package.json +0 -41
  598. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  599. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  600. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  601. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +0 -16
  602. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  603. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +0 -836
  604. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +0 -256
  605. package/.worktrees/8d2d0392/packages/dashboard/package.json +0 -25
  606. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +0 -95
  607. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +0 -679
  608. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +0 -526
  609. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +0 -357
  610. package/.worktrees/8d2d0392/src/agent-session-log.js +0 -803
  611. package/.worktrees/8d2d0392/src/change-list.js +0 -290
  612. package/.worktrees/8d2d0392/src/change-risk-profile.js +0 -339
  613. package/.worktrees/8d2d0392/src/check-primitives.js +0 -65
  614. package/.worktrees/8d2d0392/src/classify-change.js +0 -109
  615. package/.worktrees/8d2d0392/src/commit-suggest.js +0 -202
  616. package/.worktrees/8d2d0392/src/config-cat.js +0 -88
  617. package/.worktrees/8d2d0392/src/config-schema.js +0 -328
  618. package/.worktrees/8d2d0392/src/constants.js +0 -97
  619. package/.worktrees/8d2d0392/src/contract-matrix.js +0 -533
  620. package/.worktrees/8d2d0392/src/datetime.js +0 -20
  621. package/.worktrees/8d2d0392/src/db-engine.js +0 -55
  622. package/.worktrees/8d2d0392/src/db.js +0 -381
  623. package/.worktrees/8d2d0392/src/decision-distill.js +0 -517
  624. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +0 -155
  625. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +0 -245
  626. package/.worktrees/8d2d0392/src/dispatch/probe.js +0 -246
  627. package/.worktrees/8d2d0392/src/dispatch/strategy.js +0 -121
  628. package/.worktrees/8d2d0392/src/docs-check.js +0 -825
  629. package/.worktrees/8d2d0392/src/docs-debt.js +0 -393
  630. package/.worktrees/8d2d0392/src/docs-gate.js +0 -107
  631. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +0 -1099
  632. package/.worktrees/8d2d0392/src/endpoint-extractor.js +0 -409
  633. package/.worktrees/8d2d0392/src/foreign-declared.js +0 -78
  634. package/.worktrees/8d2d0392/src/fs-atomic.js +0 -73
  635. package/.worktrees/8d2d0392/src/git-helper.js +0 -150
  636. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +0 -130
  637. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +0 -892
  638. package/.worktrees/8d2d0392/src/index.js +0 -2854
  639. package/.worktrees/8d2d0392/src/init.js +0 -626
  640. package/.worktrees/8d2d0392/src/knowledge-match.js +0 -231
  641. package/.worktrees/8d2d0392/src/local-detect.js +0 -128
  642. package/.worktrees/8d2d0392/src/local-register.js +0 -104
  643. package/.worktrees/8d2d0392/src/machine-interface.js +0 -543
  644. package/.worktrees/8d2d0392/src/migrate.js +0 -127
  645. package/.worktrees/8d2d0392/src/module-impact.js +0 -166
  646. package/.worktrees/8d2d0392/src/module-resolve.js +0 -222
  647. package/.worktrees/8d2d0392/src/modules.js +0 -580
  648. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +0 -126
  649. package/.worktrees/8d2d0392/src/progress/change-registry.js +0 -336
  650. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +0 -355
  651. package/.worktrees/8d2d0392/src/progress/shared.js +0 -36
  652. package/.worktrees/8d2d0392/src/progress/stage-machine.js +0 -594
  653. package/.worktrees/8d2d0392/src/progress/step-store.js +0 -265
  654. package/.worktrees/8d2d0392/src/progress.js +0 -1304
  655. package/.worktrees/8d2d0392/src/quick-recommend.js +0 -115
  656. package/.worktrees/8d2d0392/src/quicklog.js +0 -883
  657. package/.worktrees/8d2d0392/src/review-tier.js +0 -77
  658. package/.worktrees/8d2d0392/src/run/command.js +0 -1641
  659. package/.worktrees/8d2d0392/src/run/complete-handlers.js +0 -1552
  660. package/.worktrees/8d2d0392/src/run/complete.js +0 -1259
  661. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +0 -156
  662. package/.worktrees/8d2d0392/src/run/gates.js +0 -1094
  663. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +0 -208
  664. package/.worktrees/8d2d0392/src/run/next.js +0 -128
  665. package/.worktrees/8d2d0392/src/run/prompt.js +0 -843
  666. package/.worktrees/8d2d0392/src/run/quick-audit.js +0 -186
  667. package/.worktrees/8d2d0392/src/run/scan-profile.js +0 -269
  668. package/.worktrees/8d2d0392/src/run/shared.js +0 -1562
  669. package/.worktrees/8d2d0392/src/run/stage.js +0 -587
  670. package/.worktrees/8d2d0392/src/run.js +0 -23
  671. package/.worktrees/8d2d0392/src/scan-diff.js +0 -388
  672. package/.worktrees/8d2d0392/src/scan-postcheck.js +0 -524
  673. package/.worktrees/8d2d0392/src/scan-staleness.js +0 -95
  674. package/.worktrees/8d2d0392/src/setup.js +0 -414
  675. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +0 -597
  676. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +0 -62
  677. package/.worktrees/8d2d0392/src/spec-dir-typo.js +0 -50
  678. package/.worktrees/8d2d0392/src/spec-sync.js +0 -358
  679. package/.worktrees/8d2d0392/src/stage-contract-engine.js +0 -171
  680. package/.worktrees/8d2d0392/src/stage-contract-spec.js +0 -551
  681. package/.worktrees/8d2d0392/src/stage-contract.js +0 -948
  682. package/.worktrees/8d2d0392/src/stage-review.js +0 -597
  683. package/.worktrees/8d2d0392/src/stages/archive.js +0 -199
  684. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +0 -285
  685. package/.worktrees/8d2d0392/src/stages/brainstorm.js +0 -624
  686. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +0 -145
  687. package/.worktrees/8d2d0392/src/stages/doctor.js +0 -540
  688. package/.worktrees/8d2d0392/src/stages/execute.js +0 -1277
  689. package/.worktrees/8d2d0392/src/stages/explore.js +0 -43
  690. package/.worktrees/8d2d0392/src/stages/index.js +0 -29
  691. package/.worktrees/8d2d0392/src/stages/knowledge.js +0 -514
  692. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +0 -1398
  693. package/.worktrees/8d2d0392/src/stages/plan.js +0 -651
  694. package/.worktrees/8d2d0392/src/stages/quick.js +0 -167
  695. package/.worktrees/8d2d0392/src/stages/scan.js +0 -608
  696. package/.worktrees/8d2d0392/src/stages/status.js +0 -64
  697. package/.worktrees/8d2d0392/src/stages/verify.js +0 -246
  698. package/.worktrees/8d2d0392/src/sync.js +0 -1470
  699. package/.worktrees/8d2d0392/src/task-review.js +0 -1498
  700. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +0 -21
  701. package/.worktrees/8d2d0392/src/taskcard.js +0 -217
  702. package/.worktrees/8d2d0392/src/verify-postcheck.js +0 -1718
  703. package/.worktrees/8d2d0392/src/verify-probes.js +0 -327
  704. package/.worktrees/8d2d0392/src/version.js +0 -19
  705. package/.worktrees/8d2d0392/src/workflow.js +0 -600
  706. package/.worktrees/8d2d0392/src/workspace.js +0 -125
  707. package/.worktrees/8d2d0392/src/worktree-apply.js +0 -1611
  708. package/.worktrees/8d2d0392/src/worktree-deps.js +0 -576
  709. package/.worktrees/8d2d0392/src/worktree.js +0 -1838
  710. package/.worktrees/8d2d0392/templates/claude-instruction.md +0 -23
  711. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +0 -29
  712. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +0 -12
  713. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +0 -32
  714. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +0 -79
  715. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +0 -132
  716. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  717. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  718. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  719. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  720. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  721. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  722. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  723. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  724. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +0 -57
  725. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +0 -177
  726. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  727. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  728. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  729. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  730. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  731. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +0 -64
  732. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +0 -54
  733. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  734. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  735. package/.worktrees/c1eae35e/.gitattributes +0 -2
  736. package/.worktrees/c1eae35e/.husky/pre-push +0 -20
  737. package/.worktrees/c1eae35e/README.md +0 -203
  738. package/.worktrees/c1eae35e/SKILL.md +0 -91
  739. package/.worktrees/c1eae35e/architecture-analysis.md +0 -448
  740. package/.worktrees/c1eae35e/bin/sillyspec.js +0 -2
  741. package/.worktrees/c1eae35e/eval/README.md +0 -86
  742. package/.worktrees/c1eae35e/eval/eval.config.json +0 -28
  743. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +0 -63
  744. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +0 -27
  745. package/.worktrees/c1eae35e/eval/lib/config.mjs +0 -82
  746. package/.worktrees/c1eae35e/eval/lib/db.mjs +0 -76
  747. package/.worktrees/c1eae35e/eval/lib/report.mjs +0 -120
  748. package/.worktrees/c1eae35e/eval/lib/runner.mjs +0 -157
  749. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +0 -73
  750. package/.worktrees/c1eae35e/eval/lib/util.mjs +0 -107
  751. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +0 -30
  752. package/.worktrees/c1eae35e/eval/run.mjs +0 -83
  753. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +0 -6
  754. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  755. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +0 -6
  756. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +0 -28
  757. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +0 -6
  758. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  759. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  760. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +0 -6
  761. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +0 -31
  762. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  763. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +0 -6
  764. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  765. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +0 -6
  766. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +0 -38
  767. package/.worktrees/c1eae35e/logo.jpg +0 -0
  768. package/.worktrees/c1eae35e/package-lock.json +0 -977
  769. package/.worktrees/c1eae35e/package.json +0 -41
  770. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  771. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  772. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  773. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +0 -16
  774. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  775. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +0 -836
  776. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +0 -256
  777. package/.worktrees/c1eae35e/packages/dashboard/package.json +0 -25
  778. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +0 -95
  779. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +0 -679
  780. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +0 -526
  781. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +0 -357
  782. package/.worktrees/c1eae35e/src/agent-session-log.js +0 -803
  783. package/.worktrees/c1eae35e/src/change-list.js +0 -290
  784. package/.worktrees/c1eae35e/src/change-risk-profile.js +0 -339
  785. package/.worktrees/c1eae35e/src/check-primitives.js +0 -65
  786. package/.worktrees/c1eae35e/src/classify-change.js +0 -109
  787. package/.worktrees/c1eae35e/src/commit-suggest.js +0 -202
  788. package/.worktrees/c1eae35e/src/config-cat.js +0 -88
  789. package/.worktrees/c1eae35e/src/config-schema.js +0 -328
  790. package/.worktrees/c1eae35e/src/constants.js +0 -97
  791. package/.worktrees/c1eae35e/src/contract-matrix.js +0 -533
  792. package/.worktrees/c1eae35e/src/datetime.js +0 -20
  793. package/.worktrees/c1eae35e/src/db-engine.js +0 -55
  794. package/.worktrees/c1eae35e/src/db.js +0 -381
  795. package/.worktrees/c1eae35e/src/decision-distill.js +0 -517
  796. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +0 -155
  797. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +0 -245
  798. package/.worktrees/c1eae35e/src/dispatch/probe.js +0 -246
  799. package/.worktrees/c1eae35e/src/dispatch/strategy.js +0 -121
  800. package/.worktrees/c1eae35e/src/docs-check.js +0 -825
  801. package/.worktrees/c1eae35e/src/docs-debt.js +0 -393
  802. package/.worktrees/c1eae35e/src/docs-gate.js +0 -107
  803. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +0 -1099
  804. package/.worktrees/c1eae35e/src/endpoint-extractor.js +0 -409
  805. package/.worktrees/c1eae35e/src/foreign-declared.js +0 -155
  806. package/.worktrees/c1eae35e/src/fs-atomic.js +0 -73
  807. package/.worktrees/c1eae35e/src/git-helper.js +0 -150
  808. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +0 -130
  809. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +0 -892
  810. package/.worktrees/c1eae35e/src/index.js +0 -2854
  811. package/.worktrees/c1eae35e/src/init.js +0 -626
  812. package/.worktrees/c1eae35e/src/knowledge-match.js +0 -231
  813. package/.worktrees/c1eae35e/src/local-detect.js +0 -128
  814. package/.worktrees/c1eae35e/src/local-register.js +0 -104
  815. package/.worktrees/c1eae35e/src/machine-interface.js +0 -543
  816. package/.worktrees/c1eae35e/src/migrate.js +0 -127
  817. package/.worktrees/c1eae35e/src/module-impact.js +0 -166
  818. package/.worktrees/c1eae35e/src/module-resolve.js +0 -222
  819. package/.worktrees/c1eae35e/src/modules.js +0 -580
  820. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +0 -126
  821. package/.worktrees/c1eae35e/src/progress/change-registry.js +0 -336
  822. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +0 -355
  823. package/.worktrees/c1eae35e/src/progress/shared.js +0 -36
  824. package/.worktrees/c1eae35e/src/progress/stage-machine.js +0 -594
  825. package/.worktrees/c1eae35e/src/progress/step-store.js +0 -265
  826. package/.worktrees/c1eae35e/src/progress.js +0 -1304
  827. package/.worktrees/c1eae35e/src/quick-recommend.js +0 -115
  828. package/.worktrees/c1eae35e/src/quicklog.js +0 -883
  829. package/.worktrees/c1eae35e/src/review-tier.js +0 -77
  830. package/.worktrees/c1eae35e/src/run/command.js +0 -1641
  831. package/.worktrees/c1eae35e/src/run/complete-handlers.js +0 -1552
  832. package/.worktrees/c1eae35e/src/run/complete.js +0 -1259
  833. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +0 -156
  834. package/.worktrees/c1eae35e/src/run/gates.js +0 -1111
  835. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +0 -208
  836. package/.worktrees/c1eae35e/src/run/next.js +0 -128
  837. package/.worktrees/c1eae35e/src/run/prompt.js +0 -843
  838. package/.worktrees/c1eae35e/src/run/quick-audit.js +0 -186
  839. package/.worktrees/c1eae35e/src/run/scan-profile.js +0 -269
  840. package/.worktrees/c1eae35e/src/run/shared.js +0 -1562
  841. package/.worktrees/c1eae35e/src/run/stage.js +0 -587
  842. package/.worktrees/c1eae35e/src/run.js +0 -23
  843. package/.worktrees/c1eae35e/src/scan-diff.js +0 -388
  844. package/.worktrees/c1eae35e/src/scan-postcheck.js +0 -524
  845. package/.worktrees/c1eae35e/src/scan-staleness.js +0 -95
  846. package/.worktrees/c1eae35e/src/setup.js +0 -414
  847. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +0 -597
  848. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +0 -62
  849. package/.worktrees/c1eae35e/src/spec-dir-typo.js +0 -50
  850. package/.worktrees/c1eae35e/src/spec-sync.js +0 -358
  851. package/.worktrees/c1eae35e/src/stage-contract-engine.js +0 -171
  852. package/.worktrees/c1eae35e/src/stage-contract-spec.js +0 -551
  853. package/.worktrees/c1eae35e/src/stage-contract.js +0 -948
  854. package/.worktrees/c1eae35e/src/stage-review.js +0 -597
  855. package/.worktrees/c1eae35e/src/stages/archive.js +0 -199
  856. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +0 -285
  857. package/.worktrees/c1eae35e/src/stages/brainstorm.js +0 -624
  858. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +0 -145
  859. package/.worktrees/c1eae35e/src/stages/doctor.js +0 -540
  860. package/.worktrees/c1eae35e/src/stages/execute.js +0 -1277
  861. package/.worktrees/c1eae35e/src/stages/explore.js +0 -43
  862. package/.worktrees/c1eae35e/src/stages/index.js +0 -29
  863. package/.worktrees/c1eae35e/src/stages/knowledge.js +0 -514
  864. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +0 -1398
  865. package/.worktrees/c1eae35e/src/stages/plan.js +0 -655
  866. package/.worktrees/c1eae35e/src/stages/quick.js +0 -167
  867. package/.worktrees/c1eae35e/src/stages/scan.js +0 -608
  868. package/.worktrees/c1eae35e/src/stages/status.js +0 -64
  869. package/.worktrees/c1eae35e/src/stages/verify.js +0 -246
  870. package/.worktrees/c1eae35e/src/sync.js +0 -1470
  871. package/.worktrees/c1eae35e/src/task-review.js +0 -1498
  872. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +0 -21
  873. package/.worktrees/c1eae35e/src/taskcard.js +0 -250
  874. package/.worktrees/c1eae35e/src/verify-postcheck.js +0 -1718
  875. package/.worktrees/c1eae35e/src/verify-probes.js +0 -327
  876. package/.worktrees/c1eae35e/src/version.js +0 -19
  877. package/.worktrees/c1eae35e/src/workflow.js +0 -600
  878. package/.worktrees/c1eae35e/src/workspace.js +0 -125
  879. package/.worktrees/c1eae35e/src/worktree-apply.js +0 -1611
  880. package/.worktrees/c1eae35e/src/worktree-deps.js +0 -668
  881. package/.worktrees/c1eae35e/src/worktree.js +0 -1849
  882. package/.worktrees/c1eae35e/templates/claude-instruction.md +0 -23
  883. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +0 -29
  884. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +0 -12
  885. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +0 -32
  886. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +0 -79
  887. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +0 -132
  888. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  889. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  890. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  891. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  892. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  893. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  894. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  895. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  896. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +0 -57
  897. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +0 -177
  898. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  899. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  900. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  901. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  902. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  903. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  904. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +0 -64
  905. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +0 -54
  906. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  907. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  908. package/.worktrees/dafc71ad/.gitattributes +0 -2
  909. package/.worktrees/dafc71ad/.husky/pre-push +0 -20
  910. package/.worktrees/dafc71ad/README.md +0 -203
  911. package/.worktrees/dafc71ad/SKILL.md +0 -91
  912. package/.worktrees/dafc71ad/analysis.md +0 -366
  913. package/.worktrees/dafc71ad/architecture-analysis.md +0 -448
  914. package/.worktrees/dafc71ad/bin/sillyspec.js +0 -2
  915. package/.worktrees/dafc71ad/eval/README.md +0 -86
  916. package/.worktrees/dafc71ad/eval/eval.config.json +0 -28
  917. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +0 -63
  918. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +0 -27
  919. package/.worktrees/dafc71ad/eval/lib/config.mjs +0 -82
  920. package/.worktrees/dafc71ad/eval/lib/db.mjs +0 -76
  921. package/.worktrees/dafc71ad/eval/lib/report.mjs +0 -120
  922. package/.worktrees/dafc71ad/eval/lib/runner.mjs +0 -157
  923. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +0 -73
  924. package/.worktrees/dafc71ad/eval/lib/util.mjs +0 -107
  925. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +0 -30
  926. package/.worktrees/dafc71ad/eval/run.mjs +0 -83
  927. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +0 -6
  928. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  929. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +0 -6
  930. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +0 -28
  931. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +0 -6
  932. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  933. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  934. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +0 -6
  935. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +0 -31
  936. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  937. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +0 -6
  938. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  939. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +0 -6
  940. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +0 -38
  941. package/.worktrees/dafc71ad/logo.jpg +0 -0
  942. package/.worktrees/dafc71ad/package-lock.json +0 -977
  943. package/.worktrees/dafc71ad/package.json +0 -41
  944. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  945. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  946. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  947. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +0 -16
  948. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  949. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +0 -836
  950. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +0 -256
  951. package/.worktrees/dafc71ad/packages/dashboard/package.json +0 -25
  952. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +0 -95
  953. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +0 -679
  954. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +0 -526
  955. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +0 -357
  956. package/.worktrees/dafc71ad/src/agent-session-log.js +0 -803
  957. package/.worktrees/dafc71ad/src/change-list.js +0 -290
  958. package/.worktrees/dafc71ad/src/change-risk-profile.js +0 -339
  959. package/.worktrees/dafc71ad/src/check-primitives.js +0 -65
  960. package/.worktrees/dafc71ad/src/classify-change.js +0 -109
  961. package/.worktrees/dafc71ad/src/commit-suggest.js +0 -202
  962. package/.worktrees/dafc71ad/src/config-cat.js +0 -88
  963. package/.worktrees/dafc71ad/src/config-schema.js +0 -328
  964. package/.worktrees/dafc71ad/src/constants.js +0 -97
  965. package/.worktrees/dafc71ad/src/contract-matrix.js +0 -533
  966. package/.worktrees/dafc71ad/src/datetime.js +0 -20
  967. package/.worktrees/dafc71ad/src/db-engine.js +0 -55
  968. package/.worktrees/dafc71ad/src/db.js +0 -381
  969. package/.worktrees/dafc71ad/src/decision-distill.js +0 -517
  970. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +0 -155
  971. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +0 -245
  972. package/.worktrees/dafc71ad/src/dispatch/probe.js +0 -246
  973. package/.worktrees/dafc71ad/src/dispatch/strategy.js +0 -121
  974. package/.worktrees/dafc71ad/src/docs-check.js +0 -825
  975. package/.worktrees/dafc71ad/src/docs-debt.js +0 -393
  976. package/.worktrees/dafc71ad/src/docs-gate.js +0 -107
  977. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +0 -1099
  978. package/.worktrees/dafc71ad/src/endpoint-extractor.js +0 -409
  979. package/.worktrees/dafc71ad/src/foreign-declared.js +0 -155
  980. package/.worktrees/dafc71ad/src/fs-atomic.js +0 -73
  981. package/.worktrees/dafc71ad/src/git-helper.js +0 -150
  982. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +0 -130
  983. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +0 -892
  984. package/.worktrees/dafc71ad/src/index.js +0 -2854
  985. package/.worktrees/dafc71ad/src/init.js +0 -626
  986. package/.worktrees/dafc71ad/src/knowledge-match.js +0 -231
  987. package/.worktrees/dafc71ad/src/local-detect.js +0 -128
  988. package/.worktrees/dafc71ad/src/local-register.js +0 -104
  989. package/.worktrees/dafc71ad/src/machine-interface.js +0 -543
  990. package/.worktrees/dafc71ad/src/migrate.js +0 -127
  991. package/.worktrees/dafc71ad/src/module-impact.js +0 -166
  992. package/.worktrees/dafc71ad/src/module-resolve.js +0 -222
  993. package/.worktrees/dafc71ad/src/modules.js +0 -580
  994. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +0 -126
  995. package/.worktrees/dafc71ad/src/progress/change-registry.js +0 -336
  996. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +0 -355
  997. package/.worktrees/dafc71ad/src/progress/shared.js +0 -36
  998. package/.worktrees/dafc71ad/src/progress/stage-machine.js +0 -594
  999. package/.worktrees/dafc71ad/src/progress/step-store.js +0 -265
  1000. package/.worktrees/dafc71ad/src/progress.js +0 -1304
  1001. package/.worktrees/dafc71ad/src/quick-recommend.js +0 -115
  1002. package/.worktrees/dafc71ad/src/quicklog.js +0 -883
  1003. package/.worktrees/dafc71ad/src/review-tier.js +0 -77
  1004. package/.worktrees/dafc71ad/src/run/command.js +0 -1641
  1005. package/.worktrees/dafc71ad/src/run/complete-handlers.js +0 -1552
  1006. package/.worktrees/dafc71ad/src/run/complete.js +0 -1259
  1007. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +0 -156
  1008. package/.worktrees/dafc71ad/src/run/gates.js +0 -1111
  1009. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +0 -208
  1010. package/.worktrees/dafc71ad/src/run/next.js +0 -128
  1011. package/.worktrees/dafc71ad/src/run/prompt.js +0 -843
  1012. package/.worktrees/dafc71ad/src/run/quick-audit.js +0 -186
  1013. package/.worktrees/dafc71ad/src/run/scan-profile.js +0 -269
  1014. package/.worktrees/dafc71ad/src/run/shared.js +0 -1562
  1015. package/.worktrees/dafc71ad/src/run/stage.js +0 -587
  1016. package/.worktrees/dafc71ad/src/run.js +0 -23
  1017. package/.worktrees/dafc71ad/src/scan-diff.js +0 -388
  1018. package/.worktrees/dafc71ad/src/scan-postcheck.js +0 -524
  1019. package/.worktrees/dafc71ad/src/scan-staleness.js +0 -95
  1020. package/.worktrees/dafc71ad/src/setup.js +0 -414
  1021. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +0 -597
  1022. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +0 -62
  1023. package/.worktrees/dafc71ad/src/spec-dir-typo.js +0 -50
  1024. package/.worktrees/dafc71ad/src/spec-sync.js +0 -358
  1025. package/.worktrees/dafc71ad/src/stage-contract-engine.js +0 -171
  1026. package/.worktrees/dafc71ad/src/stage-contract-spec.js +0 -551
  1027. package/.worktrees/dafc71ad/src/stage-contract.js +0 -948
  1028. package/.worktrees/dafc71ad/src/stage-review.js +0 -597
  1029. package/.worktrees/dafc71ad/src/stages/archive.js +0 -199
  1030. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +0 -285
  1031. package/.worktrees/dafc71ad/src/stages/brainstorm.js +0 -624
  1032. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +0 -145
  1033. package/.worktrees/dafc71ad/src/stages/doctor.js +0 -540
  1034. package/.worktrees/dafc71ad/src/stages/execute.js +0 -1277
  1035. package/.worktrees/dafc71ad/src/stages/explore.js +0 -43
  1036. package/.worktrees/dafc71ad/src/stages/index.js +0 -29
  1037. package/.worktrees/dafc71ad/src/stages/knowledge.js +0 -514
  1038. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +0 -1398
  1039. package/.worktrees/dafc71ad/src/stages/plan.js +0 -655
  1040. package/.worktrees/dafc71ad/src/stages/quick.js +0 -167
  1041. package/.worktrees/dafc71ad/src/stages/scan.js +0 -608
  1042. package/.worktrees/dafc71ad/src/stages/status.js +0 -64
  1043. package/.worktrees/dafc71ad/src/stages/verify.js +0 -246
  1044. package/.worktrees/dafc71ad/src/sync.js +0 -1470
  1045. package/.worktrees/dafc71ad/src/task-review.js +0 -1498
  1046. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +0 -21
  1047. package/.worktrees/dafc71ad/src/taskcard.js +0 -250
  1048. package/.worktrees/dafc71ad/src/verify-postcheck.js +0 -1718
  1049. package/.worktrees/dafc71ad/src/verify-probes.js +0 -327
  1050. package/.worktrees/dafc71ad/src/version.js +0 -19
  1051. package/.worktrees/dafc71ad/src/workflow.js +0 -600
  1052. package/.worktrees/dafc71ad/src/workspace.js +0 -125
  1053. package/.worktrees/dafc71ad/src/worktree-apply.js +0 -1611
  1054. package/.worktrees/dafc71ad/src/worktree-deps.js +0 -668
  1055. package/.worktrees/dafc71ad/src/worktree.js +0 -1849
  1056. package/.worktrees/dafc71ad/templates/claude-instruction.md +0 -23
  1057. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +0 -29
  1058. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +0 -12
  1059. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +0 -32
  1060. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +0 -79
  1061. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +0 -132
  1062. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +0 -87
  1063. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +0 -93
  1064. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +0 -114
  1065. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +0 -67
  1066. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +0 -47
  1067. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +0 -76
  1068. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +0 -214
  1069. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +0 -102
  1070. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +0 -57
  1071. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +0 -177
  1072. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +0 -270
  1073. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +0 -156
  1074. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +0 -87
  1075. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +0 -116
  1076. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +0 -70
  1077. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +0 -79
  1078. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +0 -64
  1079. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +0 -54
  1080. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +0 -87
  1081. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +0 -175
  1082. package/.worktrees/e58fcc4c/.gitattributes +0 -2
  1083. package/.worktrees/e58fcc4c/.husky/pre-push +0 -20
  1084. package/.worktrees/e58fcc4c/README.md +0 -203
  1085. package/.worktrees/e58fcc4c/SKILL.md +0 -91
  1086. package/.worktrees/e58fcc4c/architecture-analysis.md +0 -503
  1087. package/.worktrees/e58fcc4c/bin/sillyspec.js +0 -2
  1088. package/.worktrees/e58fcc4c/eval/README.md +0 -86
  1089. package/.worktrees/e58fcc4c/eval/eval.config.json +0 -28
  1090. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +0 -63
  1091. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +0 -27
  1092. package/.worktrees/e58fcc4c/eval/lib/config.mjs +0 -82
  1093. package/.worktrees/e58fcc4c/eval/lib/db.mjs +0 -76
  1094. package/.worktrees/e58fcc4c/eval/lib/report.mjs +0 -120
  1095. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +0 -157
  1096. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +0 -73
  1097. package/.worktrees/e58fcc4c/eval/lib/util.mjs +0 -107
  1098. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +0 -30
  1099. package/.worktrees/e58fcc4c/eval/run.mjs +0 -83
  1100. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +0 -6
  1101. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +0 -26
  1102. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +0 -6
  1103. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +0 -28
  1104. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +0 -6
  1105. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +0 -4
  1106. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +0 -30
  1107. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +0 -6
  1108. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +0 -31
  1109. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +0 -5
  1110. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +0 -6
  1111. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +0 -36
  1112. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +0 -6
  1113. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +0 -38
  1114. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  1115. package/.worktrees/e58fcc4c/package-lock.json +0 -977
  1116. package/.worktrees/e58fcc4c/package.json +0 -41
  1117. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +0 -7446
  1118. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +0 -1
  1119. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  1120. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +0 -16
  1121. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  1122. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +0 -836
  1123. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +0 -256
  1124. package/.worktrees/e58fcc4c/packages/dashboard/package.json +0 -25
  1125. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +0 -95
  1126. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +0 -679
  1127. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +0 -526
  1128. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +0 -357
  1129. package/.worktrees/e58fcc4c/src/agent-session-log.js +0 -803
  1130. package/.worktrees/e58fcc4c/src/change-list.js +0 -290
  1131. package/.worktrees/e58fcc4c/src/change-risk-profile.js +0 -339
  1132. package/.worktrees/e58fcc4c/src/check-primitives.js +0 -65
  1133. package/.worktrees/e58fcc4c/src/classify-change.js +0 -109
  1134. package/.worktrees/e58fcc4c/src/commit-suggest.js +0 -202
  1135. package/.worktrees/e58fcc4c/src/config-cat.js +0 -88
  1136. package/.worktrees/e58fcc4c/src/config-schema.js +0 -328
  1137. package/.worktrees/e58fcc4c/src/constants.js +0 -97
  1138. package/.worktrees/e58fcc4c/src/contract-matrix.js +0 -533
  1139. package/.worktrees/e58fcc4c/src/datetime.js +0 -20
  1140. package/.worktrees/e58fcc4c/src/db-engine.js +0 -55
  1141. package/.worktrees/e58fcc4c/src/db.js +0 -381
  1142. package/.worktrees/e58fcc4c/src/decision-distill.js +0 -517
  1143. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +0 -155
  1144. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +0 -245
  1145. package/.worktrees/e58fcc4c/src/dispatch/probe.js +0 -246
  1146. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +0 -121
  1147. package/.worktrees/e58fcc4c/src/docs-check.js +0 -825
  1148. package/.worktrees/e58fcc4c/src/docs-debt.js +0 -393
  1149. package/.worktrees/e58fcc4c/src/docs-gate.js +0 -107
  1150. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +0 -1099
  1151. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +0 -409
  1152. package/.worktrees/e58fcc4c/src/foreign-declared.js +0 -155
  1153. package/.worktrees/e58fcc4c/src/fs-atomic.js +0 -73
  1154. package/.worktrees/e58fcc4c/src/git-helper.js +0 -150
  1155. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +0 -130
  1156. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +0 -892
  1157. package/.worktrees/e58fcc4c/src/index.js +0 -2854
  1158. package/.worktrees/e58fcc4c/src/init.js +0 -626
  1159. package/.worktrees/e58fcc4c/src/knowledge-match.js +0 -231
  1160. package/.worktrees/e58fcc4c/src/local-detect.js +0 -128
  1161. package/.worktrees/e58fcc4c/src/local-register.js +0 -104
  1162. package/.worktrees/e58fcc4c/src/machine-interface.js +0 -543
  1163. package/.worktrees/e58fcc4c/src/migrate.js +0 -127
  1164. package/.worktrees/e58fcc4c/src/module-impact.js +0 -166
  1165. package/.worktrees/e58fcc4c/src/module-resolve.js +0 -222
  1166. package/.worktrees/e58fcc4c/src/modules.js +0 -580
  1167. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +0 -126
  1168. package/.worktrees/e58fcc4c/src/progress/change-registry.js +0 -336
  1169. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +0 -355
  1170. package/.worktrees/e58fcc4c/src/progress/shared.js +0 -36
  1171. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +0 -594
  1172. package/.worktrees/e58fcc4c/src/progress/step-store.js +0 -265
  1173. package/.worktrees/e58fcc4c/src/progress.js +0 -1304
  1174. package/.worktrees/e58fcc4c/src/quick-recommend.js +0 -115
  1175. package/.worktrees/e58fcc4c/src/quicklog.js +0 -883
  1176. package/.worktrees/e58fcc4c/src/review-tier.js +0 -77
  1177. package/.worktrees/e58fcc4c/src/run/command.js +0 -1641
  1178. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +0 -1552
  1179. package/.worktrees/e58fcc4c/src/run/complete.js +0 -1259
  1180. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +0 -156
  1181. package/.worktrees/e58fcc4c/src/run/gates.js +0 -1111
  1182. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +0 -208
  1183. package/.worktrees/e58fcc4c/src/run/next.js +0 -128
  1184. package/.worktrees/e58fcc4c/src/run/prompt.js +0 -843
  1185. package/.worktrees/e58fcc4c/src/run/quick-audit.js +0 -186
  1186. package/.worktrees/e58fcc4c/src/run/scan-profile.js +0 -269
  1187. package/.worktrees/e58fcc4c/src/run/shared.js +0 -1562
  1188. package/.worktrees/e58fcc4c/src/run/stage.js +0 -587
  1189. package/.worktrees/e58fcc4c/src/run.js +0 -23
  1190. package/.worktrees/e58fcc4c/src/scan-diff.js +0 -388
  1191. package/.worktrees/e58fcc4c/src/scan-postcheck.js +0 -524
  1192. package/.worktrees/e58fcc4c/src/scan-staleness.js +0 -95
  1193. package/.worktrees/e58fcc4c/src/setup.js +0 -414
  1194. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +0 -597
  1195. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +0 -62
  1196. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +0 -50
  1197. package/.worktrees/e58fcc4c/src/spec-sync.js +0 -358
  1198. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +0 -171
  1199. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +0 -551
  1200. package/.worktrees/e58fcc4c/src/stage-contract.js +0 -948
  1201. package/.worktrees/e58fcc4c/src/stage-review.js +0 -597
  1202. package/.worktrees/e58fcc4c/src/stages/archive.js +0 -199
  1203. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +0 -285
  1204. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +0 -624
  1205. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +0 -145
  1206. package/.worktrees/e58fcc4c/src/stages/doctor.js +0 -540
  1207. package/.worktrees/e58fcc4c/src/stages/execute.js +0 -1277
  1208. package/.worktrees/e58fcc4c/src/stages/explore.js +0 -43
  1209. package/.worktrees/e58fcc4c/src/stages/index.js +0 -29
  1210. package/.worktrees/e58fcc4c/src/stages/knowledge.js +0 -514
  1211. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +0 -1398
  1212. package/.worktrees/e58fcc4c/src/stages/plan.js +0 -655
  1213. package/.worktrees/e58fcc4c/src/stages/quick.js +0 -167
  1214. package/.worktrees/e58fcc4c/src/stages/scan.js +0 -608
  1215. package/.worktrees/e58fcc4c/src/stages/status.js +0 -64
  1216. package/.worktrees/e58fcc4c/src/stages/verify.js +0 -246
  1217. package/.worktrees/e58fcc4c/src/sync.js +0 -1470
  1218. package/.worktrees/e58fcc4c/src/task-review.js +0 -1498
  1219. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +0 -21
  1220. package/.worktrees/e58fcc4c/src/taskcard.js +0 -250
  1221. package/.worktrees/e58fcc4c/src/verify-postcheck.js +0 -1718
  1222. package/.worktrees/e58fcc4c/src/verify-probes.js +0 -327
  1223. package/.worktrees/e58fcc4c/src/version.js +0 -19
  1224. package/.worktrees/e58fcc4c/src/workflow.js +0 -600
  1225. package/.worktrees/e58fcc4c/src/workspace.js +0 -125
  1226. package/.worktrees/e58fcc4c/src/worktree-apply.js +0 -1611
  1227. package/.worktrees/e58fcc4c/src/worktree-deps.js +0 -668
  1228. package/.worktrees/e58fcc4c/src/worktree.js +0 -1849
  1229. package/.worktrees/e58fcc4c/templates/claude-instruction.md +0 -23
  1230. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +0 -29
  1231. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +0 -12
  1232. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +0 -32
  1233. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +0 -79
  1234. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +0 -132
@@ -1,1470 +0,0 @@
1
- /**
2
- * SillySpec SyncManager — SillyHub 平台同步模块
3
- *
4
- * 独立于 ProgressManager,由 run.js 和 index.js 调用。
5
- * Best effort:所有网络失败 console.warn,不抛错,不阻塞主流程。
6
- *
7
- * 配置来源:.sillyspec/local.yaml 中的 platform 段
8
- * HTTP 请求:Node.js 原生 fetch(Node 22+)
9
- */
10
-
11
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, unlinkSync, chmodSync } from 'fs';
12
- import { writeAtomicSync } from './fs-atomic.js';
13
- import { join } from 'path';
14
- import { resolvePlatformSpecDir } from './progress.js';
15
- import { safeGit } from './git-helper.js';
16
- import { openDatabase } from './db-engine.js';
17
- import { PLATFORM_MANAGED_FILENAME } from './run/shared.js';
18
- import { syncSpecTree } from './spec-sync.js';
19
-
20
- // sync 是 best-effort(网络失败只 warn):平台指针失效时不抛,跳过平台、回退本地。
21
- function safePlatformSpecDir(cwd) {
22
- try {
23
- return resolvePlatformSpecDir(cwd);
24
- } catch (e) {
25
- console.warn(`[sync] 平台指针不可用,跳过平台同步:${String(e.message).split('\n')[0]}`);
26
- return undefined;
27
- }
28
- }
29
-
30
- const LOCAL_YAML = '.sillyspec/local.yaml';
31
- const CHANGES_DIR = '.sillyspec/changes';
32
- const REQUEST_TIMEOUT_MS = 10_000;
33
-
34
- // 未连接平台是本地独立用户的合法默认状态。sync / checkApproval 由 run 流程在后台 best-effort
35
- // 触发(每步完成、execute 阶段启动);syncDocuments 仅由手动 `sillyspec platform sync-docs`
36
- // 命令触发(index.js sync-docs 分支),run 流程不自动推文档。未连接时默认静默跳过——不每步
37
- // 催连平台制造噪音(本地用户根本不需要平台)。需要排查同步行为时设 SILLYSPEC_DEBUG_SYNC=1。
38
- function debugLog(msg) {
39
- if (process.env.SILLYSPEC_DEBUG_SYNC) console.warn(msg)
40
- }
41
-
42
- /** 四件套文档文件名 */
43
- const DOCUMENT_FILES = ['proposal.md', 'design.md', 'requirements.md', 'tasks.md'];
44
-
45
- // ── YAML 辅助 ──
46
-
47
- /**
48
- * 简易 YAML 读取(解析为扁平 obj),供 _getPlatform / status 只读用。
49
- * 与 worktree-guard.js 的 parseSimpleYaml 保持一致的轻量风格。
50
- *
51
- * 写入侧(connect/disconnect)**不再**走 parse→modify→write 有损往返——
52
- * readLocalYaml/parseSimpleYaml 丢注释(:85 跳 # 行)、丢数组/深嵌套(只认一层 key:value),
53
- * round-trip 会清空用户手填的注释与其他段。改为 readLocalYamlRaw + replaceTopLevelSection
54
- * 文本级定向替换 platform 段,原文件注释/空行/其他段/数组/深嵌套/CRLF 字节级保留。
55
- */
56
- function readLocalYaml(cwd) {
57
- const p = join(cwd, LOCAL_YAML);
58
- if (!existsSync(p)) return {};
59
- try {
60
- return parseSimpleYaml(readFileSync(p, 'utf8'));
61
- } catch {
62
- return {};
63
- }
64
- }
65
-
66
- /** 读 local.yaml 原始文本(保留注释/换行/结构),不存在返回 ''。供 connect/disconnect 文本级改写。 */
67
- function readLocalYamlRaw(cwd) {
68
- const p = join(cwd, LOCAL_YAML);
69
- if (!existsSync(p)) return '';
70
- try {
71
- return readFileSync(p, 'utf8');
72
- } catch {
73
- return '';
74
- }
75
- }
76
-
77
- /**
78
- * 定位顶层 YAML 段(如 platform:/mcp:)的行范围 [start, end)。
79
- * 段 = key 行(行首非空白 + 以 'name:' 开头)+ 后续连续缩进行(以空格/tab 开头)。
80
- * 遇空行/注释/下一个顶层 key 即段结束——这些行不属于本段,保留不动。
81
- * split('\n')/join('\n') 操作:CRLF 下 '\r' 留在行尾,重组原样还原(Windows 兼容,CLAUDE.md #13)。
82
- * @param {string} text
83
- * @param {string} name - 段名(不含冒号,如 'platform')
84
- * @returns {{start: number, end: number} | null} 不存在返回 null
85
- */
86
- function findTopLevelSectionRange(text, name) {
87
- const lines = text.split('\n');
88
- const prefix = `${name}:`;
89
- let start = -1;
90
- for (let i = 0; i < lines.length; i++) {
91
- const line = lines[i];
92
- // 顶层 key 行:行首非空白(排除缩进子段)+ 以 'name:' 开头
93
- if (/^\S/.test(line) && line.startsWith(prefix)) {
94
- start = i;
95
- break;
96
- }
97
- }
98
- if (start === -1) return null;
99
- let end = start + 1;
100
- while (end < lines.length && /^[ \t]/.test(lines[end])) {
101
- end++;
102
- }
103
- return { start, end };
104
- }
105
-
106
- /**
107
- * 文本级定向替换/删除/追加一个顶层 YAML 段,保留文件其余所有字节
108
- * (注释/空行/其他段/数组/深嵌套/CRLF 全保留)。
109
- * @param {string} text - 原始文件文本
110
- * @param {string} name - 段名(不含冒号)
111
- * @param {string|null} body - 段体(不含 key 行);null=删除该段;string=替换或追加
112
- * @returns {string} 新文本
113
- */
114
- function replaceTopLevelSection(text, name, body) {
115
- const lines = text.split('\n');
116
- const range = findTopLevelSectionRange(text, name);
117
- if (range) {
118
- const before = lines.slice(0, range.start);
119
- const after = lines.slice(range.end);
120
- if (body === null) {
121
- return [...before, ...after].join('\n');
122
- }
123
- const sectionLines = [`${name}:`, ...body.split('\n')];
124
- return [...before, ...sectionLines, ...after].join('\n');
125
- }
126
- // 段不存在
127
- if (body === null) return text; // 删不存在的段,原样返回
128
- // 追加:去尾换行后加空行分隔 + 新段;空文件直接起段
129
- const stripped = text.replace(/(\r?\n)+$/, '');
130
- if (stripped === '') {
131
- return `${name}:\n${body}\n`;
132
- }
133
- return `${stripped}\n\n${name}:\n${body}\n`;
134
- }
135
-
136
- /** 文本级写 local.yaml(保留传入 text 的注释/结构);确保 .sillyspec 目录存在。
137
- * 原子写(fs-atomic 契约:local.yaml 被 hook/probe 等其他进程并发读,裸 writeFileSync 的
138
- * 写入窗口可读到半截文件 → mcp 段解析失败回退 env → 误判 no-config 降级)。 */
139
- function writeLocalYamlRaw(cwd, text) {
140
- const dir = join(cwd, '.sillyspec');
141
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
142
- const yamlPath = join(cwd, LOCAL_YAML);
143
- writeAtomicSync(yamlPath, text, 'utf8');
144
- // 体检 SEC-04:local.yaml 含明文 token,收紧为仅属主可读写。POSIX chmod 0600 生效;
145
- // Windows 上 Node chmod 只映射只读位(近似 no-op),属可接受 best-effort
146
- try { chmodSync(yamlPath, 0o600); } catch { /* chmod 失败不阻断连接流程 */ }
147
- }
148
-
149
- function parseSimpleYaml(content) {
150
- // 剥 YAML 双/单引号包裹(connect 写侧 yamlStr 加引号防 # : 注入,读侧对称剥;无引号值零影响)
151
- const unquote = (v) => {
152
- if (v.length >= 2 && ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'")))) {
153
- return v.slice(1, -1);
154
- }
155
- return v;
156
- };
157
- const result = {};
158
- let currentSection = null;
159
- for (const line of content.split('\n')) {
160
- const trimmed = line.trim();
161
- if (!trimmed || trimmed.startsWith('#')) continue;
162
- // 用原始 line(非 trimmed)判断缩进:trimmed 已去前导空格,startsWith(' ') 恒 false
163
- // 会导致缩进子段(如 platform 下 url/token)被误判为 root 行、section 恒为空 {}
164
- if (!line.startsWith(' ')) {
165
- const m = trimmed.match(/^(\S+)\s*:\s*(.*)$/);
166
- if (m) {
167
- const key = m[1];
168
- const val = unquote(m[2].trim());
169
- if (val) {
170
- result[key] = val;
171
- currentSection = null;
172
- } else {
173
- result[key] = {};
174
- currentSection = key;
175
- }
176
- }
177
- } else if (currentSection) {
178
- const m = trimmed.match(/^(\S+)\s*:\s*(.*)$/);
179
- if (m && result[currentSection] && typeof result[currentSection] === 'object') {
180
- result[currentSection][m[1]] = unquote(m[2].trim());
181
- }
182
- }
183
- }
184
- return result;
185
- }
186
-
187
- /**
188
- * 解析推送者身份(user):区分多用户,供 push 时 X-SillySpec-User 标识(design D-004)。
189
- * 优先级:显式参数 > git user.name(与 quicklog / prompt <git-user> 同口径)> process.env.USER
190
- * (Unix)/ USERNAME(Windows)。Best effort:全失败返回 null,调用方据此决定是否写 user 字段
191
- * (缺字段等价于「未知推送者」,平台侧自行兜底,不报错)。
192
- */
193
- function resolvePlatformUser(cwd, explicitUser) {
194
- if (typeof explicitUser === 'string' && explicitUser.trim()) {
195
- return explicitUser.trim();
196
- }
197
- // 回退 1:git user.name(safeGit 失败返回 null,不抛)
198
- const gitUser = safeGit(cwd, ['config', 'user.name']).value;
199
- if (gitUser) return gitUser;
200
- // 回退 2:环境变量(USER=Unix / USERNAME=Windows;跨平台兼容 CLAUDE.md #13)
201
- return process.env.USER || process.env.USERNAME || null;
202
- }
203
-
204
- // ── HTTP 辅助 ──
205
-
206
- // HUB-09:单请求超时与外部 signal 合并——自动同步熔断(run/shared.js trigger* 的 race)
207
- // 触发 abort 时在飞 fetch 被真实取消,而不是熔断后任由请求自行完成(平台可能已接受,
208
- // 客户端却当作超时放弃;spec 树推送无 base_ts 自愈兜底)。AbortSignal.any 需 Node ≥20.3。
209
- function combineSignals(external) {
210
- const timeoutSignal = AbortSignal.timeout(REQUEST_TIMEOUT_MS);
211
- return external ? AbortSignal.any([timeoutSignal, external]) : timeoutSignal;
212
- }
213
-
214
- async function fetchJson(url, options = {}) {
215
- const signal = combineSignals(options.signal);
216
- try {
217
- const res = await fetch(url, { ...options, signal });
218
- if (!res.ok) {
219
- const text = await res.text().catch(() => '');
220
- console.warn(`[sync] ${options.method || 'GET'} ${url} → ${res.status} ${text.slice(0, 200)}`);
221
- return null;
222
- }
223
- const ct = res.headers.get('content-type') || '';
224
- if (ct.includes('application/json')) {
225
- return res.json();
226
- }
227
- return null;
228
- } catch (err) {
229
- if (err.name === 'AbortError') {
230
- console.warn(`[sync] ${url} 请求超时/中断 (${REQUEST_TIMEOUT_MS}ms 上限或外部熔断)`);
231
- } else {
232
- console.warn(`[sync] ${url} 请求失败: ${err.message}`);
233
- }
234
- return null;
235
- }
236
- }
237
-
238
- /**
239
- * 带状态码的 fetch:不吞非 2xx(fetchJson 在 !res.ok 时返回 null 丢状态,无法区分 409 冲突)。
240
- * 返回 { ok, status, body }:body 尽力 JSON.parse(平台冲突响应带 progress JSON,读回给调用方)。
241
- * 仅 sync() 的 progress POST 使用(识别 base_ts 乐观锁冲突,D-015 / task-09);其余调用仍走 fetchJson。
242
- */
243
- async function fetchJsonWithStatus(url, options = {}) {
244
- const signal = combineSignals(options.signal);
245
- try {
246
- const res = await fetch(url, { ...options, signal });
247
- const text = await res.text().catch(() => '');
248
- let body = null;
249
- if (text) {
250
- try { body = JSON.parse(text); } catch { body = null; }
251
- }
252
- if (!res.ok) {
253
- console.warn(`[sync] ${options.method || 'GET'} ${url} → ${res.status} ${text.slice(0, 200)}`);
254
- }
255
- return { ok: res.ok, status: res.status, body };
256
- } catch (err) {
257
- if (err.name === 'AbortError') {
258
- console.warn(`[sync] ${url} 请求超时/中断 (${REQUEST_TIMEOUT_MS}ms 上限或外部熔断)`);
259
- } else {
260
- console.warn(`[sync] ${url} 请求失败: ${err.message}`);
261
- }
262
- return { ok: false, status: 0, body: null };
263
- }
264
- }
265
-
266
- // ── SyncManager ──
267
-
268
- export class SyncManager {
269
- constructor(cwd) {
270
- this.cwd = cwd;
271
- // 归档尾声静默化旗标(坑 post-archive-sync-noise):sync() 探测到已归档时置位,
272
- // 链内 syncDocuments 的「变更不存在」降 debug(每次 sync 调用重置)
273
- this._suppressDocsMissingWarn = false;
274
- }
275
-
276
- /**
277
- * 连接 SillyHub 平台。
278
- * 保存配置到 .sillyspec/local.yaml,发送 ping 验证连接。
279
- * @param {string} url - 平台地址
280
- * @param {string} token - 认证 token
281
- * @param {string} [user] - 推送者身份(可空,回退 git user.name / env,见 resolvePlatformUser)
282
- */
283
- async connect(url, token, user) {
284
- if (!token) {
285
- // 体检 HUB-02:falsy token 不允许 connect——health ping 无鉴权会"连接成功",
286
- // 但 local.yaml 会落盘字符串 "undefined",后续所有同步持续 401
287
- console.error('[sync] 缺少 token,拒绝连接(请在平台获取 token 后带 --token 重试)');
288
- return false;
289
- }
290
- // 验证连接
291
- const normalizedUrl = url.replace(/\/+$/, '');
292
- // 体检 SEC-04:非 https 且非本机回环时 Bearer token 明文上线——MCP client 侧
293
- // (sillyhub-mcp/client.js 构造器)早有同款 warn,sync 侧此前完全静默
294
- if (!/^https:\/\//i.test(normalizedUrl) && !/^http:\/\/(localhost|127\.0\.0\.1|\[::1\])(:|\/|$)/i.test(normalizedUrl)) {
295
- console.warn(`[sync] platform.url 非 https(${normalizedUrl.slice(0, 60)}),同步 token 将明文传输——请确认为受控内网环境`);
296
- }
297
- const healthUrl = `${normalizedUrl}/api/health`;
298
- const result = await fetchJson(healthUrl);
299
- if (result === null) {
300
- console.warn(`[sync] 平台连接验证失败: ${url}`);
301
- return;
302
- }
303
- console.log(`[sync] 平台连接成功: ${url}`);
304
-
305
- // 换发 workspace-scoped 同步 token(task-09 / D-005@v1):用传入 user 级 token
306
- // (shk_live_ / JWT)作 Bearer + 本地 root_path(connect 的 cwd,与平台
307
- // Workspace.root_path 绑定值等值匹配)调 resolve-by-root-path。成功取 shpsync_
308
- // 覆盖 token 写入 platform 段;404(root_path 未绑)/403(无 WORKSPACE_WRITE)/断网
309
- // 均降级沿用原 token 继续(best-effort 不阻断 connect)。
310
- let effectiveToken = token;
311
- const resolveUrl = `${normalizedUrl}/api/workspaces/resolve-by-root-path`;
312
- const resolved = await fetchJson(resolveUrl, {
313
- method: 'POST',
314
- headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
315
- body: JSON.stringify({ root_path: this.cwd }),
316
- });
317
- if (resolved && resolved.token && resolved.token.startsWith('shpsync_')) {
318
- effectiveToken = resolved.token;
319
- console.log(
320
- `[sync] 已换发 workspace-scoped 同步 token (workspace: ${resolved.workspace_id})`
321
- );
322
- } else {
323
- console.warn(
324
- '[sync] 换发 workspace-scoped token 失败(404/403/断网),沿用原 token 继续'
325
- );
326
- }
327
-
328
- // 解析推送者身份(D-004):显式 > git user.name > env;全失败留空不写 user 字段
329
- const resolvedUser = resolvePlatformUser(this.cwd, user);
330
-
331
- // 文本级改写 local.yaml:定向替换 platform 段,原文件注释/其他段/数组/深嵌套/CRLF 字节级保留
332
- // (旧 read-modify-write 经 parseSimpleYaml 丢注释+丢非扁平结构,round-trip 清空用户手填内容)。
333
- // YAML 值加引号:token/url 含 # : 或首尾空白时裸写会破坏段结构或注入额外键(shpsync_ token
334
- // 当前不含这些字符,防御性包裹零成本;parseSimpleYaml 读侧剥引号兼容)
335
- const yamlStr = (v) => JSON.stringify(String(v));
336
- const platformEntries = [
337
- ` url: ${yamlStr(normalizedUrl)}`,
338
- ` token: ${yamlStr(effectiveToken)}`,
339
- ` last_connected: ${yamlStr(new Date().toISOString())}`,
340
- ];
341
- if (resolvedUser) {
342
- platformEntries.push(` user: ${yamlStr(resolvedUser)}`);
343
- }
344
- let text = readLocalYamlRaw(this.cwd);
345
- text = replaceTopLevelSection(text, 'platform', platformEntries.join('\n'));
346
- // mcp 段同源假设(design §7.4):url 复用 platform 的 url;token 用原始 user 级 token
347
- // (非换发的 effectiveToken——MCP 派发需 user 级权限,platform 段才是最小权限的 shpsync_)。
348
- // 用户已手填 mcp 段则保留不覆盖(R-09,文本级检测)
349
- if (findTopLevelSectionRange(text, 'mcp') === null) {
350
- text = replaceTopLevelSection(text, 'mcp', ` url: ${yamlStr(normalizedUrl)}\n token: ${yamlStr(token)}`);
351
- }
352
- writeLocalYamlRaw(this.cwd, text);
353
- }
354
-
355
- /**
356
- * 断开平台连接(三清,D-C@v2)。
357
- * 1. 从 local.yaml 删除 platform 配置段;
358
- * 2. 删恢复指针 <cwd>/.sillyspec-platform.json;
359
- * 3. 删平台接管声明 <cwd>/.sillyspec-platform-managed。
360
- * 不删后两者则"disconnect 后恢复本地模式"不可达(指针健在时 resolvePlatformSpecDir
361
- * 仍解析平台 specRoot;声明健在时指针缺失会 fail-closed)。
362
- */
363
- disconnect() {
364
- const p = join(this.cwd, LOCAL_YAML);
365
- if (existsSync(p)) {
366
- const text = readFileSync(p, 'utf8');
367
- if (findTopLevelSectionRange(text, 'platform') !== null) {
368
- // 文本级删除 platform 段,保留注释/其他段/数组/深嵌套/CRLF
369
- const newText = replaceTopLevelSection(text, 'platform', null);
370
- if (newText.trim() === '') {
371
- // 删段后纯空白(无任何段也无注释)→ 删除整个文件;注释算内容,有注释则保留
372
- try { unlinkSync(p); } catch { /* best effort */ }
373
- } else {
374
- writeAtomicSync(p, newText, 'utf8');
375
- }
376
- }
377
- }
378
- // 三清之二/三:指针 + 接管声明(disconnect 是声明的唯一退出路径——design.md §5.4)。
379
- // HUB-12 有意不清 .sillyspec-platform-cleaned marker:它防的是「重新接入平台时 init
380
- // 重复做残留清理」——disconnect 后重连若清掉 marker,init 会对现在装着本地数据的
381
- // .sillyspec 再跑一次平台残留清理(误删风险)。marker 跨 disconnect 存活是保护语义。
382
- let cleaned = [];
383
- for (const f of ['.sillyspec-platform.json', PLATFORM_MANAGED_FILENAME]) {
384
- const fp = join(this.cwd, f);
385
- if (existsSync(fp)) {
386
- try { unlinkSync(fp); cleaned.push(f); } catch { /* best effort */ }
387
- }
388
- }
389
- if (cleaned.length > 0) console.log(`[sync] 已清理平台指针与接管声明: ${cleaned.join(', ')}`);
390
- console.log('[sync] 已断开连接');
391
- }
392
-
393
- /**
394
- * 增量同步变更的 progress 状态到平台。
395
- * 读取 ProgressManager.serializeForSync() 的六表 JSON,POST 到平台。
396
- * 元字段(user/base_ts/pushed_at)走 HTTP header,body 保持裸 JSON(D-015,sillyhub 老版零回归)。
397
- * 同步完成后更新 changes 表的 platform_last_sync 字段;409 冲突读回平台最新 JSON(task-12 完整冲突处理)。
398
- *
399
- * push 409 自竞态自愈(坑 2026-08-19-platform-sync-base-ts-silent-conflict 根治侧):
400
- * 同机多进程(CLI + daemon)并发 push 时,B 进程持旧 base_ts POST 撞 A 进程刚推完的 409——
401
- * 但 A 的成功回填就写在本机共享 DB。409 时 fresh 重读 DB:base_ts 已 ≥ 平台 409 回执 ts
402
- * ⇒ 赢者是自己人 → 刷新 base_ts 重试一次即收敛,不再落冲突文件卡死人工 resolve。
403
- * 外来推送(他机/他用户)不可能推进本机 DB 的 base_ts → 走原冲突路径,无误放行。
404
- */
405
- async sync(changeName, opts = {}) {
406
- const { fromResolve = false } = opts;
407
- const platform = this._getPlatform();
408
- if (!platform) {
409
- debugLog('[sync] 未连接平台(本地合法状态);如需平台同步:sillyspec platform connect');
410
- return { synced: 0, errors: ['未连接平台'] };
411
- }
412
-
413
- if (!changeName) {
414
- console.warn('[sync] sync 需要指定变更名称 (changeName)');
415
- return { synced: 0, errors: ['未指定变更名称'] };
416
- }
417
-
418
- // 冲突降噪(坑 sync-conflict-banner-spam,2026-08-23 实证:push 冲突落 sync-conflict 文件后,
419
- // 每步完成的 triggerSync 都会再 push 再 409 再打全幅双线横幅——「已卡死不会自愈」连环刷屏,
420
- // 观感像致命错误。冲突文件本身就代表「待人工三选一的未决状态」,文件在 = 用户已被告知,
421
- // 后续自动同步单行提示即可(可见但不吓人);resolve 后文件删除,推送自动恢复。fromResolve
422
- // (keep-local 自动重推)不在此列——resolve 流程刚删冲突文件,它需要真实 push 判定平台态。
423
- if (!fromResolve) {
424
- const pendingConflict = this.readConflictFile(changeName);
425
- if (pendingConflict) {
426
- console.warn(`⚠️ [sync] 变更 ${changeName} 存在未决平台冲突,跳过自动推送。处理:sillyspec platform resolve ${changeName} --keep-local | --take-platform | --abort`);
427
- return { synced: 0, errors: [`conflict pending: ${changeName}`], conflict: true, suppressed: true };
428
- }
429
- }
430
-
431
- // 检查变更目录是否存在(归档后目录已移走但 DB 仍有最终状态需推平台,serializeForSync 从
432
- // DB 读不依赖文件系统目录)。归档终态探测(坑 post-archive-sync-noise,2026-08-21 实证:
433
- // 归档尾声连打「目录不存在/变更不存在」warn,观感像出错):确认已归档(changes/archive/
434
- // 有实体 或 DB status='archived')时降为一行 info 措辞——正常时序不是告警。
435
- const changeDir = join(this.cwd, CHANGES_DIR, changeName);
436
- let archivedQuietly = false;
437
- if (!existsSync(changeDir)) {
438
- archivedQuietly = existsSync(join(this.cwd, CHANGES_DIR, 'archive', changeName))
439
- || this._isChangeArchivedInDb(changeName);
440
- if (archivedQuietly) {
441
- console.log(`[sync] 变更已归档(目录在 archive/),继续从 DB 推送最终状态: ${changeName}`);
442
- } else {
443
- console.warn(`[sync] 变更目录不存在(可能是已归档,继续从 DB 同步最终状态): ${changeName}`);
444
- }
445
- }
446
- // 透传给本次 sync 链内的 syncDocuments(best-effort 四件套直推:归档后目录已移走,
447
- // 其「变更不存在」warn 属正常时序,静默化)
448
- this._suppressDocsMissingWarn = archivedQuietly;
449
-
450
- const MAX_PUSH_ATTEMPTS = 2;
451
- for (let attempt = 1; attempt <= MAX_PUSH_ATTEMPTS; attempt++) {
452
- // 读取 progress 数据(serializeForSync 六表裸 JSON,task-02 / D-005@v2,替代 read() 聚合视图)。
453
- // 每次 attempt 重新 serialize:自愈重试时本地 DB 可能已被并发进程推进,base_ts/内容都要刷新
454
- let progressData;
455
- try {
456
- const { ProgressManager } = await import('./progress.js');
457
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
458
- progressData = pm.serializeForSync(this.cwd, changeName);
459
- } catch (err) {
460
- console.warn(`[sync] 读取 progress 失败 (${changeName}): ${err.message}`);
461
- return { synced: 0, errors: [`读取 progress 失败: ${err.message}`] };
462
- }
463
- if (progressData === null) {
464
- console.warn(`[sync] 变更无进度数据 (无活跃进度): ${changeName}`);
465
- return { synced: 0, errors: [`变更无进度数据: ${changeName}`] };
466
- }
467
-
468
- // 元字段走 HTTP header(D-015 / task-09):body 保持裸六表 JSON,sillyhub 老版忽略 header 零回归
469
- const headers = {
470
- 'Content-Type': 'application/json',
471
- Authorization: `Bearer ${platform.token}`,
472
- };
473
- const pushedAt = new Date().toISOString();
474
- // 推送者身份(task-08):local.yaml platform.user 显式配置优先,缺省回退
475
- // resolvePlatformUser(git user.name > env USER/USERNAME,与 connect 写入侧同口径)。
476
- // 修 last_pusher 空:此前仅 platform.user 配置时发送,本地直跑场景 local.yaml
477
- // 常无 user 字段 → header 缺失 → 平台 last_pusher 恒空(2026-08-19 坑文档改进点 4)。
478
- const pushUser = platform.user || resolvePlatformUser(this.cwd) || null;
479
- if (pushUser) headers['X-SillySpec-User'] = pushUser;
480
- const baseTs = progressData.changes && progressData.changes[0] && progressData.changes[0].last_synced_platform_ts;
481
- if (baseTs) headers['X-SillySpec-Base-Ts'] = baseTs; // base_ts 乐观锁(NULL=首次同步不设,平台接受首次 push)
482
- headers['X-SillySpec-Pushed-At'] = pushedAt; // 平台存 last_pushed_at,作下次其他用户 push 的 base_ts 比对基准
483
-
484
- // POST 到平台(带状态码版本:识别 409 冲突,读回平台最新 JSON)。changeName encode 对齐 pull(:673)
485
- const syncUrl = `${platform.url}/api/changes/${encodeURIComponent(changeName)}/progress`;
486
- const res = await fetchJsonWithStatus(syncUrl, {
487
- method: 'POST',
488
- headers,
489
- body: JSON.stringify(progressData),
490
- signal: opts.signal, // HUB-09:熔断 abort 传到底层请求
491
- });
492
-
493
- if (res.ok) {
494
- // 更新 platform_last_sync + 推进 base_ts(ql-20260818-008:值优先平台回执 last_pushed_at,
495
- // 缺省用本次 pushedAt——服务器 _apply 存的就是客户端 X-SillySpec-Pushed-At 原值,回写一致。
496
- // 修复前该列从不写,下次 push 永不带 X-SillySpec-Base-Ts、pull 脏度检测恒 false)
497
- // 回填加固:共享 SQLite 并发(daemon+CLI)下 WAL 忙窗口可能偶发失败——重试一次,
498
- // 仍失败打醒目 warn(base_ts 停留在旧值,下次 push 会 409,届时自竞态自愈会收敛)
499
- let backfilled = false;
500
- for (let bt = 1; bt <= 2 && !backfilled; bt++) {
501
- try {
502
- const { ProgressManager } = await import('./progress.js');
503
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
504
- const ackTs = res.body && typeof res.body.last_pushed_at === 'string' ? res.body.last_pushed_at : pushedAt;
505
- pm._updatePlatformLastSync(this.cwd, changeName, ackTs);
506
- backfilled = true;
507
- } catch (err) {
508
- if (bt === 2) {
509
- console.warn(`⚠️ [sync] base_ts 回填失败(下次 push 可能 409,自愈机制会处理): ${err.message}`);
510
- } else {
511
- await new Promise((r) => setTimeout(r, 200));
512
- }
513
- }
514
- }
515
-
516
- console.log(`[sync] 已同步变更: ${changeName}`);
517
-
518
- // 2026-08-16-auto-sync-from-repo:进度上行成功后顺带推四件套文档(best-effort)。
519
- // 根因:run 流程此前只推进度不推文档(本文件头注释),本地直跑 sillyspec 的产出
520
- // 文档永远不自动到平台(变更中心"进度到了文档没到")。生产者直连,不依赖 daemon
521
- // 缓存链路。失败仅 debugLog——文档同步失败不得影响进度上行的返回值与流程;
522
- // 四件套全缺失时 syncDocuments 内部已有跳过(syncedCount===0 提前返回,不调端点)。
523
- try {
524
- await this.syncDocuments(changeName, { signal: opts.signal });
525
- } catch (err) {
526
- debugLog(`[sync] 文档同步失败(不影响进度): ${changeName}: ${err.message}`);
527
- }
528
-
529
- // 2026-08-17-spec-file-incremental-sync:进度上行+文档直推成功后顺带推整个 spec 树
530
- // (plan.md、tasks/、module-impact.md 等),让变更中心文件树自动更新。
531
- // 无 daemon 时 CLI 短进程无本地清单缓存,以服务器清单为锚做增量 diff。
532
- // 树根与进度锚点同源(safePlatformSpecDir,平台模式 → specRoot):此前硬编码
533
- // cwd/.sillyspec,平台模式下该目录只有 local.yaml(被 walk 排除)→ 本地树恒空
534
- // → 服务器清单全量 delete(BUG-01,computeSpecOps 护栏为第二道防线)。
535
- try {
536
- await syncSpecTree(safePlatformSpecDir(this.cwd) || join(this.cwd, '.sillyspec'), this._getPlatform(), changeName, { signal: opts.signal });
537
- } catch (err) {
538
- debugLog(`[sync] spec 树增量同步失败(不影响进度): ${changeName}: ${err.message}`);
539
- }
540
-
541
- return { synced: 1, errors: [] };
542
- }
543
-
544
- if (res.status !== 409) {
545
- return { synced: 0, errors: [`同步请求失败: ${changeName}`] };
546
- }
547
-
548
- // ── 409 = base_ts 乐观锁冲突(平台已有更新)──
549
- // 平台 409 响应 { conflict:true, platform_progress, last_pushed_at },platform_progress 即平台最新 progress JSON
550
- const platformProgress = res.body && res.body.platform_progress ? res.body.platform_progress : res.body;
551
- const platformLastPushedAt = (res.body && res.body.last_pushed_at) || null;
552
-
553
- // 自竞态自愈:fresh 重读本机 DB base_ts,若已被并发进程回填到 ≥ 平台 409 回执 ts,
554
- // 说明赢者是本机自己人——刷新 base_ts 重试一次即收敛,不落冲突文件(外来推送不可能
555
- // 推进本机 DB 的 base_ts,不满足条件自然落回下方真冲突分支,零误放行)
556
- if (attempt < MAX_PUSH_ATTEMPTS && await this._localBaseTsCovers(changeName, platformLastPushedAt)) {
557
- console.warn(`⚠️ [sync] push 409 自竞态判定:本机并发推送已回填 base_ts(平台 ts=${platformLastPushedAt}),刷新后自动重试`);
558
- continue;
559
- }
560
-
561
- // push 侧内容一致自愈(坑 push-409-foreign-noise,2026-08-23 实证:他机/部署重推了内容
562
- // 相同的进度——pull 侧已有 _progressContentEquals 自愈(坑 pull-deploy-noise-conflict),
563
- // push 409 路径没有:外来噪声形态落真冲突 + 横幅 + 人工 resolve,而内容其实零分歧)。
564
- // 409 回执的 platform_progress 与本次待推内容过同一比对(忽略时间戳列),一致 → 平台
565
- // 「更新」只是噪声重推,本地无可丢失 → 跳过本次推送 + base_ts 推进到平台 ts(与
566
- // resolve --keep-local 同语义,自动闭环),不落冲突文件。内容不同 → 真分歧,维持原判。
567
- try {
568
- if (platformProgress && this._progressContentEquals(progressData, platformProgress)) {
569
- try {
570
- const { ProgressManager } = await import('./progress.js');
571
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
572
- pm._ensureDB(this.cwd).getDb().prepare(
573
- 'UPDATE changes SET last_synced_platform_ts = MAX(?, COALESCE(last_synced_platform_ts, ?)) WHERE name = ?'
574
- ).run(platformLastPushedAt || pushedAt, platformLastPushedAt || pushedAt, changeName);
575
- } catch {}
576
- console.warn(`⚠️ [sync] push 409 内容一致自愈: 平台 ts=${platformLastPushedAt} 为外来噪声重推(六表内容与本地一致),base_ts 已推进,不落冲突文件`);
577
- return { synced: 1, errors: [], selfHealed: true, reason: 'push 409 平台内容与本地一致(外来噪声重推),base_ts 已推进' };
578
- }
579
- } catch { /* 比对失败维持原判(fail-closed 到真冲突分支) */ }
580
-
581
- // resolve --keep-local 的自动重推再撞 409:不落新冲突文件、不打「已卡死」横幅——
582
- // 原 conflict 已按用户裁决处理完(base_ts 已推进),此刻的 409 只是「平台在用户裁决期间
583
- // 又动了」;立即落新文件会破坏「keep-local 清冲突文件回 clean」的生命周期契约(冲突文件
584
- // 代表待人工三选一的未决状态,而用户刚做完选择)。下次常规同步会按新 base 重新判定,
585
- // 真有新分歧自然再进 conflict 态。
586
- if (fromResolve) {
587
- console.warn(`⚠️ [sync] keep-local 自动重推被拒(平台又有更新,ts=${platformLastPushedAt});base_ts 已推进,下次常规同步将重新判定`);
588
- return { synced: 0, errors: [`keep-local 自动重推被拒: ${changeName}`], conflict: true, platform_progress: platformProgress, suppressedConflictFile: true };
589
- }
590
-
591
- // 醒目冲突横幅(坑 2026-08-19-platform-sync-base-ts-silent-conflict 改进点 2):
592
- // 此前仅单行 warn,冲突文件静默落 .runtime——同步已卡死但 Agent/用户无从察觉,
593
- // 平台页面永久停在旧阶段。横幅明确告知「已卡死 + 卡死原因 + 恢复命令」,不能只落文件。
594
- console.warn('');
595
- console.warn('⚠️⚠️⚠️════════════════════════════════════════════════════');
596
- console.warn(`⚠️ 平台同步冲突:变更「${changeName}」推送被拒(base_ts 过期,平台已有更新)`);
597
- console.warn('⚠️ 该变更的自动同步已暂停,等待人工 resolve 恢复(期间不再重复刷本横幅,后续自动同步单行提示):');
598
- console.warn(`⚠️ 1. sillyspec platform status # 查看未决冲突`);
599
- console.warn(`⚠️ 2. sillyspec platform resolve ${changeName} --keep-local | --take-platform | --abort`);
600
- console.warn(`⚠️ 3. sillyspec platform sync --change ${changeName}`);
601
- console.warn('⚠️⚠️⚠️════════════════════════════════════════════════════');
602
- // 本地脏度(progressData 是 serializeForSync 输出,changes[0] 含 last_local_modified_ts)
603
- const localModified = (progressData.changes && progressData.changes[0] && progressData.changes[0].last_local_modified_ts) || null;
604
- // 写冲突文件(task-12 / D-002):base_ts=本次 push 的 base,强制提示走 resolve
605
- const conflictPath = this._writeConflictFile(changeName, {
606
- base_ts: baseTs || null,
607
- local_modified_ts: localModified,
608
- platform_last_pushed_at: platformLastPushedAt,
609
- platform_progress: platformProgress,
610
- });
611
- console.warn(`⚠️ 冲突详情已落盘: ${conflictPath}`);
612
- return { synced: 0, errors: [`冲突: ${changeName}`], conflict: true, platform_progress: platformProgress, conflictPath };
613
- }
614
-
615
- // 循环耗尽(自愈重试后仍 409——两次都撞且第二次非自竞态;理论上第二次会落上方真冲突分支返回,
616
- // 此行只作结构兜底)
617
- return { synced: 0, errors: [`同步重试耗尽(仍冲突): ${changeName}`] };
618
- }
619
-
620
- /**
621
- * 自竞态判定辅助:fresh 读本地 DB 的 last_synced_platform_ts(base_ts),判断它是否已覆盖
622
- * 平台 409 回执的 last_pushed_at(字符串字典序比较,契约 §4.2——ISO 8601 字典序 == 时间序)。
623
- * 已覆盖 ⇒ 打赢 409 的推送来自本机并发进程(其成功回填写的就是这个共享 DB)。
624
- * @param {string} changeName
625
- * @param {string|null} platformTs 409 回执 last_pushed_at
626
- * @returns {Promise<boolean>}
627
- */
628
- async _localBaseTsCovers(changeName, platformTs) {
629
- if (!platformTs) return false;
630
- try {
631
- const { ProgressManager } = await import('./progress.js');
632
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
633
- const row = pm._ensureDB(this.cwd).getDb().prepare(
634
- 'SELECT last_synced_platform_ts FROM changes WHERE name = ?'
635
- ).get(changeName);
636
- const localTs = row && row.last_synced_platform_ts;
637
- if (!localTs) return false;
638
- return localTs >= platformTs;
639
- } catch {
640
- return false; // 读失败按非自竞态处理(fail-closed 到真冲突分支)
641
- }
642
- }
643
-
644
- /**
645
- * 同步四件套文档到平台(全量同步)。
646
- * POST {url}/api/changes/{changeName}/documents
647
- * @param {string} changeName
648
- * @param {{manual?: boolean}} [opts] - manual=true 手动 sync-docs 命令路径(四件套缺失打 warn);
649
- * 默认自动路径(sync() 顺带推)四件套缺失是流程早期正常状态,降 debug 不噪音(ql-20260818-008)
650
- */
651
- async syncDocuments(changeName, opts = {}) {
652
- const { manual = false } = opts;
653
- const platform = this._getPlatform();
654
- if (!platform) {
655
- debugLog('[sync] 未连接平台(本地合法状态);如需平台同步:sillyspec platform connect');
656
- return { synced: 0, errors: ['未连接平台'] };
657
- }
658
-
659
- if (!changeName) {
660
- console.warn('[sync] syncDocuments 需要指定变更名称 (changeName)');
661
- return { synced: 0, errors: ['未指定变更名称'] };
662
- }
663
-
664
- // 树根与进度/spec 树同源(safePlatformSpecDir,BUG-01 同族):此前硬编码 cwd/.sillyspec/changes,
665
- // 平台模式(specRoot 指向外部)下路径不存在 → syncDocuments 恒报「变更不存在」且调用方不查
666
- // 返回值 → 文档在平台模式下静默永不同步。
667
- const changeDir = join(safePlatformSpecDir(this.cwd) || join(this.cwd, '.sillyspec'), 'changes', changeName);
668
- if (!existsSync(changeDir)) {
669
- // 归档尾声静默化(坑 post-archive-sync-noise):sync() 链内调用(_suppressDocsMissingWarn
670
- // 置位,目录已移 archive/ 的正常时序)降为 debug;独立调用(手动 sync-docs)保留 warn
671
- if (this._suppressDocsMissingWarn) {
672
- debugLog(`[sync] 四件套目录不存在(变更已归档,跳过文档直推): ${changeName}`);
673
- return { synced: 0, errors: [] };
674
- }
675
- console.warn(`[sync] 变更不存在: ${changeName}`);
676
- return { synced: 0, errors: [`变更不存在: ${changeName}`] };
677
- }
678
-
679
- const documents = {};
680
- let syncedCount = 0;
681
- const errors = [];
682
-
683
- for (const docFile of DOCUMENT_FILES) {
684
- const docPath = join(changeDir, docFile);
685
- if (existsSync(docPath)) {
686
- try {
687
- documents[docFile] = readFileSync(docPath, 'utf8');
688
- syncedCount++;
689
- } catch (err) {
690
- errors.push(`读取 ${docFile} 失败: ${err.message}`);
691
- }
692
- }
693
- }
694
-
695
- if (syncedCount === 0) {
696
- // ql-20260818-008:四件套缺失在流程早期是正常状态(brainstorm 中途 design/proposal 还没写),
697
- // 自动路径降 debug——原 warn「未找到可同步的文档」不说只找四件套,曾让用户误判同步逻辑错了;
698
- // 手动 platform sync-docs 是显式意图,保留 warn 但说清范围。
699
- if (manual) {
700
- console.warn(`[sync] 未找到可同步的四件套文档(proposal/design/requirements/tasks.md): ${changeName}`);
701
- } else {
702
- debugLog(`[sync] 四件套尚未生成,跳过文档直推: ${changeName}`);
703
- }
704
- return { synced: 0, errors: [...errors, '无可用文档'] };
705
- }
706
-
707
- const docUrl = `${platform.url}/api/changes/${encodeURIComponent(changeName)}/documents`;
708
- const result = await fetchJson(docUrl, {
709
- method: 'POST',
710
- headers: {
711
- 'Content-Type': 'application/json',
712
- Authorization: `Bearer ${platform.token}`,
713
- },
714
- body: JSON.stringify(documents),
715
- signal: opts.signal, // HUB-09:熔断 abort 传到底层请求
716
- });
717
-
718
- if (!result) {
719
- return { synced: 0, errors: [...errors, '文档同步请求失败'] };
720
- }
721
-
722
- console.log(`[sync] 已同步 ${syncedCount} 个文档: ${changeName}`);
723
- return { synced: syncedCount, errors };
724
- }
725
-
726
- /**
727
- * 检查变更的审批状态。
728
- * GET {url}/api/changes/{changeName}/approval
729
- * 返回 { status: 'pending'|'approved'|'rejected', reason?: string }
730
- */
731
- async checkApproval(changeName) {
732
- const platform = this._getPlatform();
733
- if (!platform) {
734
- debugLog('[sync] 未连接平台(本地合法状态);如需平台同步:sillyspec platform connect');
735
- return { status: 'pending', reason: '未连接平台' };
736
- }
737
-
738
- if (!changeName) {
739
- console.warn('[sync] checkApproval 需要指定变更名称 (changeName)');
740
- return { status: 'pending', reason: '未指定变更名称' };
741
- }
742
-
743
- const approvalUrl = `${platform.url}/api/changes/${encodeURIComponent(changeName)}/approval`;
744
- const result = await fetchJson(approvalUrl, {
745
- headers: { Authorization: `Bearer ${platform.token}` },
746
- });
747
-
748
- if (!result) {
749
- console.warn(`[sync] 检查审批状态失败: ${changeName}`);
750
- return { status: 'unknown', reason: '请求失败(404/断网/超时),无法核实审批状态' };
751
- }
752
-
753
- // 更新本地 approvals 表
754
- try {
755
- const { ProgressManager } = await import('./progress.js');
756
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
757
- pm._updateApprovalStatus(this.cwd, changeName, result.status, result.reason);
758
- } catch (err) {
759
- console.warn(`[sync] 更新本地审批状态失败: ${err.message}`);
760
- }
761
-
762
- if (result.status === 'rejected') {
763
- console.warn(`[sync] 审批被拒绝 (${changeName}): ${result.reason || '无原因'}`);
764
- }
765
-
766
- return result;
767
- }
768
-
769
- /**
770
- * 查看同步状态。
771
- * 读取 local.yaml 中的 platform 配置,返回连接信息。
772
- */
773
- status() {
774
- const config = readLocalYaml(this.cwd);
775
- const platform = config.platform;
776
- if (!platform) {
777
- return { connected: false };
778
- }
779
- return {
780
- connected: true,
781
- url: platform.url,
782
- lastSync: platform.last_connected || null,
783
- };
784
- }
785
-
786
- /** 获取当前平台配置,未连接返回 null */
787
- _getPlatform() {
788
- const config = readLocalYaml(this.cwd);
789
- return config.platform || null;
790
- }
791
-
792
- /**
793
- * DB 侧归档态探测(坑 post-archive-sync-noise):changes 表 status='archived' 即真。
794
- * 只读直查(node:sqlite,不经 ProgressManager——sync 是短进程,惰性 import 无收益且
795
- * 本调用点在同步代码段);DB 不存在/无行/读失败 → false(保守退回普通 warn 措辞)。
796
- * @param {string} changeName
797
- * @returns {boolean}
798
- */
799
- _isChangeArchivedInDb(changeName) {
800
- try {
801
- const dbPath = join(safePlatformSpecDir(this.cwd) || join(this.cwd, '.sillyspec'), '.runtime', 'sillyspec.db');
802
- if (!existsSync(dbPath)) return false;
803
- const db = openDatabase(dbPath, { readOnly: true });
804
- try {
805
- const row = db.prepare("SELECT status FROM changes WHERE name = ?").get(changeName);
806
- return row?.status === 'archived';
807
- } finally { try { db.close() } catch {} }
808
- } catch { return false }
809
- }
810
-
811
- /**
812
- * 写冲突文件 .runtime/sync-conflict-<change>.json(task-12 / D-002 / D-008 / D-010 / FR-05)。
813
- * push 409 与 pull 本地脏度双向冲突命中时调用,强制提示用户走 platform resolve 三选一。
814
- * 绝不字段级 auto-merge;文件在 .runtime 下不入版本控制(gitignore)。
815
- * @param {string} changeName
816
- * @param {{base_ts?: string|null, local_modified_ts?: string|null, platform_last_pushed_at?: string|null, platform_progress?: object|null}} info
817
- * @returns {string|null} 冲突文件路径(specDir 不可达返回 null)
818
- */
819
- /**
820
- * 六表内容比对(坑 pull-deploy-noise-conflict 自愈用):本地 serializeForSync 快照与平台
821
- * 拉回的 JSON 逐表深度比对,忽略时间戳/同步元数据列(last_active/last_synced_platform_ts/
822
- * last_local_modified_ts/started_at/completed_at/pushed_at/checked_at/completed_at 等——部署
823
- * 噪声重推会刷新这些列但内容不变)。任一实质差异 → false。
824
- * @param {object} local - serializeForSync 输出
825
- * @param {object} platform - 平台 GET progress JSON(serializeForSync 同构)
826
- * @returns {boolean}
827
- */
828
- _progressContentEquals(local, platform) {
829
- try {
830
- const IGNORE_KEYS = new Set([
831
- 'last_active', 'last_synced_platform_ts', 'last_local_modified_ts',
832
- 'started_at', 'completed_at', 'pushed_at', 'last_pushed_at', 'created_at',
833
- 'deps_checked_at', 'checked_at', 'waited_at', 'completedat',
834
- ]);
835
- const strip = (v) => {
836
- if (Array.isArray(v)) return v.map(strip);
837
- if (v && typeof v === 'object') {
838
- const out = {};
839
- // sort 必须按 key 字符串比较(坑 content-equals-sort-typeerror,2026-08-23 实证:
840
- // 默认比较器把 [key, value] 元素转字符串,serializeForSync 输出的 project 字段是
841
- // null-prototype 对象(不可转原始值)→ sort 抛 TypeError 被下方 catch 吞成恒 false
842
- // ——pull/push 两侧内容一致自愈形同虚设,部署噪声全部落真冲突人工 resolve)。
843
- const entries = Object.entries(v).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
844
- for (const [k, val] of entries) {
845
- if (IGNORE_KEYS.has(k)) continue;
846
- out[k] = strip(val);
847
- }
848
- return out;
849
- }
850
- return v;
851
- };
852
- return JSON.stringify(strip(local)) === JSON.stringify(strip(platform));
853
- } catch { return false }
854
- }
855
-
856
- _writeConflictFile(changeName, info = {}) {
857
- const specDir = safePlatformSpecDir(this.cwd);
858
- if (!specDir) return null;
859
- const runtimeDir = join(specDir, '.runtime');
860
- if (!existsSync(runtimeDir)) mkdirSync(runtimeDir, { recursive: true });
861
- const conflictPath = join(runtimeDir, `sync-conflict-${changeName}.json`);
862
- const payload = {
863
- change: changeName,
864
- base_ts: info.base_ts ?? null,
865
- local_modified_ts: info.local_modified_ts ?? null,
866
- platform_last_pushed_at: info.platform_last_pushed_at ?? null,
867
- created_at: new Date().toISOString(),
868
- // 额外存平台最新 progress JSON,供 resolve --take-platform 直接 import(无需再 pull)
869
- platform_progress: info.platform_progress ?? null,
870
- };
871
- writeFileSync(conflictPath, JSON.stringify(payload, null, 2) + '\n', 'utf8');
872
- return conflictPath;
873
- }
874
-
875
- /**
876
- * 读取冲突文件(task-13 resolve / task-14 status 用)。
877
- * @returns {object|null} 冲突文件内容;无文件返回 null
878
- */
879
- readConflictFile(changeName) {
880
- const specDir = safePlatformSpecDir(this.cwd);
881
- if (!specDir) return null;
882
- const conflictPath = join(specDir, '.runtime', `sync-conflict-${changeName}.json`);
883
- if (!existsSync(conflictPath)) return null;
884
- try {
885
- return JSON.parse(readFileSync(conflictPath, 'utf8'));
886
- } catch {
887
- return null;
888
- }
889
- }
890
-
891
- // ── HUB-08:spec 树冲突文件(spec-sync-conflict-<change>.json,由 spec-sync.js 写入)──
892
-
893
- /** 读取 spec 树冲突文件;无/损坏返回 null */
894
- readSpecConflictFile(changeName) {
895
- const specDir = safePlatformSpecDir(this.cwd);
896
- if (!specDir) return null;
897
- const p = join(specDir, '.runtime', `spec-sync-conflict-${changeName}.json`);
898
- if (!existsSync(p)) return null;
899
- try {
900
- return JSON.parse(readFileSync(p, 'utf8'));
901
- } catch {
902
- return null;
903
- }
904
- }
905
-
906
- /** 删除 spec 树冲突文件 */
907
- clearSpecConflictFile(changeName) {
908
- const specDir = safePlatformSpecDir(this.cwd);
909
- if (!specDir) return false;
910
- const p = join(specDir, '.runtime', `spec-sync-conflict-${changeName}.json`);
911
- if (!existsSync(p)) return false;
912
- try { unlinkSync(p); return true; }
913
- catch { return false; }
914
- }
915
-
916
- /**
917
- * 删除冲突文件(resolve 完成后清理,task-13 用)。
918
- * @returns {boolean} 是否删除(文件不存在返回 false)
919
- */
920
- clearConflictFile(changeName) {
921
- const specDir = safePlatformSpecDir(this.cwd);
922
- if (!specDir) return false;
923
- const conflictPath = join(specDir, '.runtime', `sync-conflict-${changeName}.json`);
924
- if (!existsSync(conflictPath)) return false;
925
- try { unlinkSync(conflictPath); return true; }
926
- catch { return false; }
927
- }
928
-
929
- /**
930
- * 两级 pull 第一级:轻量 change 列表(design §7 / D-001 / D-006 / task-06 / FR-01 / FR-03)。
931
- * GET {url}/api/changes → [{ name, current_stage, last_pushed_at, last_pusher }](兼容 { changes: [...] } 包裹)。
932
- * CLI 比对本地决定哪些 change 需更新,控制 pull 性能(不每次全量拉单 change JSON)。
933
- * Best Effort:未连接 / 网络失败 console.warn 不抛,返回 PullListResult { ok, changes, reason? }。
934
- * @returns {Promise<{ok: boolean, changes: Array<object>, reason?: string}>}
935
- */
936
- async pullList() {
937
- const platform = this._getPlatform();
938
- if (!platform) {
939
- debugLog('[sync] 未连接平台(本地合法状态);pullList 跳过');
940
- return { ok: false, changes: [], reason: '未连接平台' };
941
- }
942
-
943
- const listUrl = `${platform.url}/api/changes`;
944
- const result = await fetchJson(listUrl, {
945
- headers: { Authorization: `Bearer ${platform.token}` },
946
- });
947
-
948
- if (result === null) {
949
- console.warn(`[sync] 拉取变更列表失败: ${listUrl}`);
950
- return { ok: false, changes: [], reason: '拉取变更列表失败' };
951
- }
952
-
953
- // 兼容两种响应形态:裸数组 / { changes: [...] } 包裹(sillyhub 后端实际 API 而定)
954
- const changes = Array.isArray(result) ? result : (Array.isArray(result.changes) ? result.changes : []);
955
- return { ok: true, changes, reason: undefined };
956
- }
957
-
958
- /**
959
- * 两级 pull 第二级:按需拉平台单 change 完整 JSON 并 import 重建本地 DB 行(design §7 / D-001 / D-006 / D-014 / task-07 / FR-01 / FR-03 / FR-09)。
960
- * GET {url}/api/changes/{name}/progress → 平台权威 JSON(serializeForSync 六表 + 顶层 last_pushed_at)。
961
- * 本地脏度比对:last_local_modified_ts > last_synced_platform_ts(本地有未同步改动)且 平台 last_pushed_at 更新 → 冲突,不 import 返回 conflict:true(task-12 负责写 sync-conflict 文件)。
962
- * 无冲突 → import() 重建 DB 行;import 后本地 base_ts/脏度重置为 pushed_at(D-013)。
963
- * Best Effort:未连接 / 网络失败 / 404 console.warn 不抛,返回 PullResult { ok, imported, conflict, reason? }。
964
- * @param {string} changeName
965
- * @param {{force?: boolean, skipIfLocalDirty?: boolean}} [opts] - force 跳过本地脏度冲突检测直接
966
- * import(task-12 resolve --take-platform 用);skipIfLocalDirty 自动注入点(triggerPull/
967
- * triggerPullActiveChange)专用保守守卫——本地有未同步改动时跳过 import(ql-20260818-008)
968
- * @returns {Promise<{ok: boolean, imported: boolean, conflict: boolean, reason?: string}>}
969
- */
970
- async pull(changeName, opts = {}) {
971
- const { force = false, skipIfLocalDirty = false } = opts;
972
- const platform = this._getPlatform();
973
- if (!platform) {
974
- debugLog('[sync] 未连接平台(本地合法状态);pull 跳过');
975
- return { ok: false, imported: false, conflict: false, reason: '未连接平台' };
976
- }
977
- if (!changeName) {
978
- console.warn('[sync] pull 需要指定变更名称 (changeName)');
979
- return { ok: false, imported: false, conflict: false, reason: '未指定变更名称' };
980
- }
981
-
982
- // 1. GET 平台完整 progress JSON
983
- const progressUrl = `${platform.url}/api/changes/${encodeURIComponent(changeName)}/progress`;
984
- const result = await fetchJson(progressUrl, {
985
- headers: { Authorization: `Bearer ${platform.token}` },
986
- signal: opts.signal, // HUB-09:熔断 abort 传到底层请求
987
- });
988
- if (result === null) {
989
- // sillyhub 未就绪 / 404 / 网络失败均 fetchJson 返回 null → Best Effort 降级
990
- console.warn(`[sync] 拉取变更进度失败: ${changeName}(sillyhub 未就绪或变更不存在)`);
991
- return { ok: false, imported: false, conflict: false, reason: '拉取变更进度失败' };
992
- }
993
-
994
- // 平台响应:serializeForSync 六表 + 顶层 last_pushed_at(兼容 { progress: {...} } 包裹)
995
- const platformProgress = (result && result.project && result.changes) ? result : (result.progress || result);
996
- const platformPushedAt = (result && result.last_pushed_at) || null;
997
-
998
- // 2. 本地脏度比对(非 force 时):本地脏 AND 平台更新 → 冲突
999
- if (!force) {
1000
- let localLastModified = null;
1001
- let localLastSynced = null;
1002
- try {
1003
- const { ProgressManager } = await import('./progress.js');
1004
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
1005
- const row = pm._ensureDB(this.cwd).getDb().prepare(
1006
- 'SELECT last_local_modified_ts, last_synced_platform_ts FROM changes WHERE name = ?'
1007
- ).get(changeName);
1008
- if (row) {
1009
- localLastModified = row.last_local_modified_ts;
1010
- localLastSynced = row.last_synced_platform_ts;
1011
- }
1012
- } catch (err) {
1013
- console.warn(`[sync] 读取本地脏度失败 (${changeName}): ${err.message}`);
1014
- }
1015
- let localDirty = localLastModified && localLastSynced && localLastModified > localLastSynced;
1016
- let platformNewer = platformPushedAt && (!localLastSynced || platformPushedAt > localLastSynced);
1017
- // 自竞态防御(坑 2026-08-19-platform-sync-base-ts-silent-conflict 改进点 3):
1018
- // 判冲突用的 localLastSynced 若落后于本进程刚完成的 push 回填(另一连接 3ms 前推完、
1019
- // 本 pull 在其回填写库前读了旧值),会把自己刚写的 platformPushedAt 误判为「平台有更新」
1020
- // → 卡死。重读一次 DB:期间 push 回填已落库则 base_ts 已推进(>= platformPushedAt),
1021
- // platformNewer 翻 false,冲突自愈。重读仍旧则真冲突,维持原判。
1022
- if (localDirty && platformNewer) {
1023
- try {
1024
- const { ProgressManager } = await import('./progress.js');
1025
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
1026
- const fresh = pm._ensureDB(this.cwd).getDb().prepare(
1027
- 'SELECT last_synced_platform_ts FROM changes WHERE name = ?'
1028
- ).get(changeName);
1029
- if (fresh && fresh.last_synced_platform_ts) {
1030
- localLastSynced = fresh.last_synced_platform_ts;
1031
- platformNewer = platformPushedAt && platformPushedAt > localLastSynced;
1032
- if (!platformNewer) {
1033
- debugLog(`[sync] pull 自竞态解除: base_ts 已被本进程 push 回填推进到 ${localLastSynced},平台 ts ${platformPushedAt} 非更新`);
1034
- }
1035
- }
1036
- } catch { /* 重读失败维持原判(fail-closed 到真冲突分支) */ }
1037
- }
1038
- // ── 内容一致自愈(坑 pull-deploy-noise-conflict,2026-08-22 实证:并行会话部署扰动——
1039
- // 他机 push 了内容相同的进度(如重启/重部署触发重推),本地脏 + 平台 ts 更新 → 拉冲突落
1040
- // sync-conflict 文件需人工 resolve,但内容其实无分歧。比对平台 JSON 与本地 serializeForSync
1041
- // 的六表内容(忽略时间戳列),一致 → 跳过 import(本地为准)+ base_ts 推进到平台 ts——
1042
- // 与 resolve --keep-local 同语义,自动闭环。内容不同 → 真冲突,维持原判。
1043
- if (localDirty && platformNewer && platformProgress) {
1044
- try {
1045
- const { ProgressManager } = await import('./progress.js');
1046
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
1047
- const localSnapshot = pm.serializeForSync(this.cwd, changeName);
1048
- if (localSnapshot && this._progressContentEquals(localSnapshot, platformProgress)) {
1049
- try {
1050
- const db = pm._ensureDB(this.cwd).getDb();
1051
- db.prepare(
1052
- 'UPDATE changes SET last_synced_platform_ts = MAX(?, COALESCE(last_synced_platform_ts, ?)) WHERE name = ?'
1053
- ).run(platformPushedAt, platformPushedAt, changeName);
1054
- } catch {}
1055
- debugLog(`[sync] pull 内容一致自愈: 平台 ts ${platformPushedAt} 为部署噪声重推(六表内容与本地一致),base_ts 已推进,不落冲突文件`);
1056
- return { ok: true, imported: false, conflict: false, reason: '平台重推内容与本地一致(部署噪声),base_ts 已推进' };
1057
- }
1058
- } catch { /* 比对失败维持原判(fail-closed 到真冲突分支) */ }
1059
- }
1060
- if (localDirty && platformNewer) {
1061
- console.warn('');
1062
- console.warn('⚠️⚠️⚠️════════════════════════════════════════════════════');
1063
- console.warn(`⚠️ 平台同步冲突:变更「${changeName}」pull 判定冲突(本地有未同步改动且平台已更新,base_ts 过期)`);
1064
- console.warn('⚠️ 该变更的自动同步已暂停,等待人工 resolve 恢复(推送侧后续自动同步单行提示,不再重复刷本横幅):');
1065
- console.warn(`⚠️ 1. sillyspec platform status # 查看未决冲突`);
1066
- console.warn(`⚠️ 2. sillyspec platform resolve ${changeName} --keep-local | --take-platform | --abort`);
1067
- console.warn(`⚠️ 3. sillyspec platform sync --change ${changeName}`);
1068
- console.warn('⚠️⚠️⚠️════════════════════════════════════════════════════');
1069
- // 写冲突文件(task-12 / D-002):强制提示,绝不 auto-merge
1070
- const conflictPath = this._writeConflictFile(changeName, {
1071
- base_ts: localLastSynced,
1072
- local_modified_ts: localLastModified,
1073
- platform_last_pushed_at: platformPushedAt,
1074
- platform_progress: platformProgress,
1075
- });
1076
- console.warn(`⚠️ 冲突详情已落盘: ${conflictPath}`); // HUB-12d:真实落点(平台模式在 specRoot/.runtime),勿硬编码
1077
- return { ok: false, imported: false, conflict: true, reason: `冲突: ${changeName} 本地脏且平台更新`, conflictPath };
1078
- }
1079
- // ql-20260818-008:自动注入点(triggerPull/triggerPullActiveChange)保守守卫——本地有未同步
1080
- // 改动时跳过 import。原逻辑只拦「本地脏 且 平台更新」的真冲突,「本地领先」(本地脏、平台更旧)
1081
- // 仍会 import 平台旧快照覆盖本地新进度(数据丢失)。手动 platform pull 不传该 flag,语义不变。
1082
- if (skipIfLocalDirty && localDirty) {
1083
- debugLog(`[sync] pull 跳过(本地有未同步改动,防平台旧快照覆盖): ${changeName}`);
1084
- return { ok: false, imported: false, conflict: false, reason: '本地有未同步改动,自动 pull 跳过' };
1085
- }
1086
- }
1087
-
1088
- // 3. 无冲突(或 force)→ import 平台 JSON 重建本地 DB 行
1089
- try {
1090
- const { ProgressManager } = await import('./progress.js');
1091
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
1092
- const importInput = { ...platformProgress, pushed_at: platformPushedAt || new Date().toISOString() };
1093
- pm.import(this.cwd, importInput, changeName);
1094
- console.log(`[sync] 已拉取变更进度: ${changeName}`);
1095
- return { ok: true, imported: true, conflict: false, reason: undefined };
1096
- } catch (err) {
1097
- console.warn(`[sync] import 失败 (${changeName}): ${err.message}`);
1098
- return { ok: false, imported: false, conflict: false, reason: `import 失败: ${err.message}` };
1099
- }
1100
- }
1101
-
1102
- /**
1103
- * 冲突解决三选一(task-13 / D-002 / D-010 / D-013 / FR-05)。
1104
- * 读 task-12 写的 sync-conflict-<change>.json,按 mode 处理后必清冲突文件防累积(R-04 / constraints)。
1105
- *
1106
- * 三种语义(design 生命周期契约表):
1107
- * - keep-local:本地 DB 不变,仅把 last_synced_platform_ts(base_ts)推进到平台 last_pushed_at
1108
- * (表示「已知平台最新,本地为准」),用户后续手动 platform sync push 本地。
1109
- * - take-platform:用冲突文件存的 platform_progress 调 import() 覆盖本地(保隔离状态,D-013 重置脏度)。
1110
- * - abort:本地 DB 与 base_ts 均不变,仅清冲突文件(放弃本次同步)。
1111
- *
1112
- * 无冲突文件 → ok:false resolved:false(index.js 据此提示「无可解决冲突」)。
1113
- * 绝不字段级 auto-merge(D-002)。
1114
- * @param {string} changeName
1115
- * @param {'keep-local'|'take-platform'|'abort'} mode
1116
- * @returns {Promise<{ok: boolean, resolved: boolean, mode?: string, reason: string}>}
1117
- */
1118
- async resolve(changeName, mode) {
1119
- const cf = this.readConflictFile(changeName);
1120
- const specCf = this.readSpecConflictFile(changeName);
1121
- if (!cf && !specCf) {
1122
- return { ok: false, resolved: false, reason: `无可解决冲突: ${changeName}(无 sync-conflict / spec-sync-conflict 文件)` };
1123
- }
1124
- const platformPushedAt = (cf && cf.platform_last_pushed_at) || null;
1125
-
1126
- // HUB-08:resolve 同时管辖进度冲突(sync-conflict-*)与 spec 树冲突(spec-sync-conflict-*),
1127
- // 各自产出 outcome 后合并返回;abort 统一清两类标记。
1128
- let progressOutcome = null;
1129
- if (mode === 'keep-local' && cf) {
1130
- // base_ts 推进到平台最新 last_pushed_at;本地 DB 不 import(用户本地为准,后续手动 push)。
1131
- // MAX() 单调防回退(坑 2026-08-19-resolve-keep-local-base-ts-rollback):冲突文件是历史快照,
1132
- // 其 platform_last_pushed_at 可能早于 DB 已由后续成功 push 回填的 base_ts——无条件覆盖会把
1133
- // base_ts 拉回过去,下次 sync 立即撞 409 再落冲突文件(恢复时实测二轮才收敛)。
1134
- // COALESCE 防 NULL:SQLite 标量 MAX(x, NULL) 恒 NULL,首同步前 base_ts NULL 应直取平台 ts。
1135
- try {
1136
- const { ProgressManager } = await import('./progress.js');
1137
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
1138
- const db = pm._ensureDB(this.cwd).getDb();
1139
- // 参数侧同样 COALESCE(坑 keep-local-base-ts-null-param):SQLite 标量 MAX() 任一参数
1140
- // 为 NULL 即返回 NULL——冲突文件 platform_last_pushed_at 为 null 时 MAX(NULL, 旧值)
1141
- // 会把已回填的 base_ts 清空,恰好违背本注释的单调防回退意图。
1142
- db.prepare('UPDATE changes SET last_synced_platform_ts = MAX(COALESCE(?, last_synced_platform_ts), COALESCE(last_synced_platform_ts, ?)) WHERE name = ?')
1143
- .run(platformPushedAt, platformPushedAt, changeName);
1144
- } catch (err) {
1145
- return { ok: false, resolved: false, reason: `keep-local 更新 base_ts 失败: ${err.message}` };
1146
- }
1147
- this.clearConflictFile(changeName);
1148
- // 自动重推闭环(坑 2026-08-19-platform-sync-base-ts-silent-conflict 收尾侧):keep-local 语义 =
1149
- // 本地为准,必然收尾是把本地推上平台。此前停在「后续请手动 platform sync」——忘了推,
1150
- // 期间他人再推 → 下次自动同步又 409 落冲突文件(「冲突再现」的根源之一)。resolve 成功即
1151
- // 自动 push 一次闭环;真撞上外来更新时软提示(fromResolve 抑制新冲突文件——冲突文件代表
1152
- // 待人工三选一的未决状态,用户刚做完选择,下次常规同步按新 base 重新判定)。
1153
- let repush = null;
1154
- try {
1155
- repush = await this.sync(changeName, { fromResolve: true });
1156
- } catch (err) {
1157
- debugLog(`[sync] keep-local 自动重推异常(不阻断 resolve 结果): ${changeName}: ${err.message}`);
1158
- }
1159
- if (repush && repush.synced === 1) {
1160
- progressOutcome = { ok: true, resolved: true, reason: '保留本地,并已自动推送平台——冲突闭环,无需再手动 sync' };
1161
- } else if (repush && repush.conflict) {
1162
- progressOutcome = { ok: true, resolved: true, reason: '保留本地,base_ts 已推进;自动重推被拒(平台在裁决期间又有更新),下次常规同步将重新判定' };
1163
- } else {
1164
- progressOutcome = { ok: true, resolved: true, reason: '保留本地,base_ts 已推进;自动重推未成功(未连接/网络),请手动 sillyspec platform sync --change ' + changeName };
1165
- }
1166
- }
1167
-
1168
- if (mode === 'take-platform' && cf) {
1169
- // 用冲突文件的 platform_progress 调 import 覆盖本地(保隔离:import 不覆盖 isolation_*)。
1170
- // fail-closed(坑 take-platform-empty-import):缺 platform_progress 时必须直接返回——
1171
- // { ...null } 展开为 {},import 会照常跑完整事务(DELETE stages 后按空 JSON 重建 =
1172
- // 清空本地进度),返回值却报 ok:false「未执行」,用户以为无事发生实则数据已丢。
1173
- if (!cf.platform_progress) {
1174
- return { ok: false, resolved: false, reason: '冲突文件缺 platform_progress,无法 take-platform(建议先 platform pull)' };
1175
- }
1176
- try {
1177
- const { ProgressManager } = await import('./progress.js');
1178
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
1179
- pm.import(this.cwd, { ...cf.platform_progress, pushed_at: platformPushedAt || new Date().toISOString() }, changeName);
1180
- } catch (err) {
1181
- progressOutcome = { ok: false, resolved: false, reason: `take-platform import 失败: ${err.message}` };
1182
- }
1183
- if (progressOutcome === null) {
1184
- this.clearConflictFile(changeName);
1185
- progressOutcome = { ok: true, resolved: true, reason: '已用平台进度覆盖本地' };
1186
- }
1187
- }
1188
-
1189
- // ── spec 树冲突处置(HUB-08)──
1190
- let specOutcome = null;
1191
- if (specCf && mode === 'keep-local') {
1192
- // keep-local = 本地胜出:重新 GET 清单重定 base 后 POST 本地内容(last-writer-wins),
1193
- // 成功清冲突文件闭环;仍冲突(平台又有更新)保留文件待下次裁决
1194
- try {
1195
- const r = await syncSpecTree(safePlatformSpecDir(this.cwd) || join(this.cwd, '.sillyspec'), this._getPlatform(), changeName);
1196
- if (!r.conflict) {
1197
- this.clearSpecConflictFile(changeName);
1198
- specOutcome = { ok: true, resolved: true, reason: 'spec 树已以本地为准重定基线重推,冲突闭环' };
1199
- } else {
1200
- specOutcome = { ok: true, resolved: false, reason: 'spec 树重推仍冲突(平台在裁决期间又有更新),冲突文件保留待下次裁决' };
1201
- }
1202
- } catch (err) {
1203
- specOutcome = { ok: false, resolved: false, reason: `spec 树重推异常: ${err.message}` };
1204
- }
1205
- } else if (specCf && mode === 'take-platform') {
1206
- // fail-closed:平台无文件下载端点,无法把服务器内容写回本地——明确报错指路,不清文件
1207
- specOutcome = { ok: false, resolved: false, reason: 'spec 树冲突不支持 take-platform(平台无文件下载端点,无法把服务器内容写回本地):请手动对齐本地文件后跑 --keep-local' };
1208
- }
1209
-
1210
- // ── abort:两类标记一并清(本地 DB 与文件均不变,下次 push/pull 重新检测)──
1211
- if (mode === 'abort') {
1212
- if (cf) this.clearConflictFile(changeName);
1213
- if (specCf) this.clearSpecConflictFile(changeName);
1214
- return { ok: true, resolved: true, mode: 'abort', reason: '放弃本次同步,本地不变' };
1215
- }
1216
-
1217
- if (mode !== 'keep-local' && mode !== 'take-platform') {
1218
- return { ok: false, resolved: false, reason: `未知 resolve 模式: ${mode}(--keep-local / --take-platform / --abort)` };
1219
- }
1220
-
1221
- // ── 合并两类冲突的处置结果 ──
1222
- const outcomes = [progressOutcome, specOutcome].filter(Boolean);
1223
- if (outcomes.length === 0) {
1224
- return { ok: false, resolved: false, reason: `无可解决冲突: ${changeName}` };
1225
- }
1226
- return {
1227
- ok: outcomes.every((o) => o.ok),
1228
- resolved: outcomes.every((o) => o.resolved),
1229
- mode,
1230
- reason: outcomes.map((o) => o.reason).join(';'),
1231
- };
1232
- }
1233
-
1234
- /**
1235
- * 扫描 .runtime/sync-conflict-*.json 列出未决冲突(task-14 / D-002 / D-010 / FR-05)。
1236
- * 只读 + 容错:损坏文件跳过不崩(constraints)。供 collectStatus / platform status 展示。
1237
- * @returns {Array<{change: string, created_at: string|null, path: string}>}
1238
- */
1239
- listConflictFiles() {
1240
- const specDir = safePlatformSpecDir(this.cwd);
1241
- if (!specDir) return [];
1242
- const runtimeDir = join(specDir, '.runtime');
1243
- if (!existsSync(runtimeDir)) return [];
1244
- let files = [];
1245
- try { files = readdirSync(runtimeDir); }
1246
- catch { return []; }
1247
- const conflicts = [];
1248
- // HUB-08:同时扫描进度冲突(sync-conflict-*)与 spec 树冲突(spec-sync-conflict-*),
1249
- // type 字段供 status 展示与 resolve 分流
1250
- for (const f of files) {
1251
- let prefix = null;
1252
- if (f.startsWith('sync-conflict-') && f.endsWith('.json')) prefix = 'sync-conflict-';
1253
- else if (f.startsWith('spec-sync-conflict-') && f.endsWith('.json')) prefix = 'spec-sync-conflict-';
1254
- else continue;
1255
- const type = prefix === 'sync-conflict-' ? 'progress' : 'spec-tree';
1256
- const filePath = join(runtimeDir, f);
1257
- try {
1258
- const cf = JSON.parse(readFileSync(filePath, 'utf8'));
1259
- conflicts.push({
1260
- change: cf.change || f.replace(/^spec-sync-conflict-|^sync-conflict-/, '').replace(/\.json$/, ''),
1261
- created_at: cf.created_at || null,
1262
- path: filePath,
1263
- type,
1264
- });
1265
- } catch {
1266
- // 损坏文件跳过不崩(constraints:容错)
1267
- }
1268
- }
1269
- return conflicts;
1270
- }
1271
-
1272
- /**
1273
- * 扩展 status(task-14 / FR-05):连接信息 + 落后标记 + 未决冲突列表。
1274
- * 只读展示,不修改任何进度(constraints)。未连接返回 base.status(connected:false,behind/conflicts 空)。
1275
- * 连接时调 pullList(轻量 GET)拿平台各 change last_pushed_at,比对本地 last_synced_platform_ts
1276
- * 标记本地可能落后;扫描 sync-conflict-*.json 列未决冲突。网络失败 listFailed=true 不崩。
1277
- * @returns {Promise<{connected: boolean, url?: string, lastSync?: string|null, behind: Array<object>, conflicts: Array<object>, listFailed: boolean}>}
1278
- */
1279
- async collectStatus() {
1280
- const base = this.status();
1281
- if (!base.connected) {
1282
- return { ...base, behind: [], conflicts: [], listFailed: false };
1283
- }
1284
- const behind = [];
1285
- let listFailed = false;
1286
- const list = await this.pullList();
1287
- if (list.ok) {
1288
- for (const ch of list.changes) {
1289
- const name = typeof ch === 'string' ? ch : ch.name;
1290
- if (!name) continue;
1291
- const platformPushedAt = (typeof ch === 'object' && (ch.last_pushed_at || ch.last_active)) || null;
1292
- if (!platformPushedAt) continue;
1293
- let localSynced = null;
1294
- try {
1295
- const { ProgressManager } = await import('./progress.js');
1296
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(this.cwd) });
1297
- const row = pm._ensureDB(this.cwd).getDb().prepare('SELECT last_synced_platform_ts FROM changes WHERE name = ?').get(name);
1298
- if (row) localSynced = row.last_synced_platform_ts;
1299
- } catch {
1300
- // 本地无该 change 记录 / DB 不可达 → 不算落后,跳过
1301
- }
1302
- // 仅本地有同步基准(last_synced_platform_ts)且平台更新晚于本地 → 落后
1303
- if (localSynced && platformPushedAt > localSynced) {
1304
- behind.push({ name, local_synced: localSynced, platform_pushed_at: platformPushedAt });
1305
- }
1306
- }
1307
- } else {
1308
- listFailed = true;
1309
- }
1310
- const conflicts = this.listConflictFiles();
1311
- return { ...base, behind, conflicts, listFailed };
1312
- }
1313
- }
1314
-
1315
- // ── CLI 入口函数 ──
1316
-
1317
- /**
1318
- * 便捷函数导出 — 供 index.js 直接调用(platform 子命令分发生在 index.js case 'platform')。
1319
- * HUB-10:原此处另有内嵌 syncModule(args) CLI 分发死代码(全仓零调用、参数形态/子命令面与
1320
- * index.js 实际分叉——位置参数 token、缺 pull/resolve/pointer、多余 approval/check-approval),
1321
- * 误导维护者改错地方,已删除。
1322
- */
1323
- export async function connect(url, token, cwd) {
1324
- return new SyncManager(cwd).connect(url, token);
1325
- }
1326
-
1327
- export async function disconnect(cwd) {
1328
- return new SyncManager(cwd).disconnect();
1329
- }
1330
-
1331
- export async function sync(changeName, cwd, opts) {
1332
- return new SyncManager(cwd).sync(changeName, opts);
1333
- }
1334
-
1335
- // manual=true:本导出对应 CLI platform sync-docs 手动命令(index.js platform 分支唯一调用方),
1336
- // 四件套缺失打 warn;sync() 内的自动顺带推走 SyncManager 实例方法默认 auto(ql-20260818-008)
1337
- export async function syncDocuments(changeName, cwd) {
1338
- return new SyncManager(cwd).syncDocuments(changeName, { manual: true });
1339
- }
1340
-
1341
- export async function checkApproval(changeName, cwd) {
1342
- return new SyncManager(cwd).checkApproval(changeName);
1343
- }
1344
-
1345
- // task-11 / D-006 / D-009 / FR-03:手动 pull 便捷导出(index.js platform pull 子命令用,
1346
- // 与自动 triggerPull 共用 SyncManager.pull 实例方法,行为一致)
1347
- export async function pull(changeName, opts, cwd) {
1348
- return new SyncManager(cwd).pull(changeName, opts);
1349
- }
1350
-
1351
- // 两级 pull 第一级(轻量 change 列表),platform pull 无 --change 时先拉列表再按需 pull
1352
- export async function pullList(cwd) {
1353
- return new SyncManager(cwd).pullList();
1354
- }
1355
-
1356
- // task-13 / D-002 / D-010 / D-013 / FR-05:冲突解决三选一(index.js platform resolve 子命令用)
1357
- export async function resolve(changeName, mode, cwd) {
1358
- return new SyncManager(cwd).resolve(changeName, mode);
1359
- }
1360
-
1361
- // task-14 / FR-05:扩展 status(连接信息 + 落后标记 + 未决冲突列表),index.js platform status 用
1362
- export async function collectStatus(cwd) {
1363
- return new SyncManager(cwd).collectStatus();
1364
- }
1365
-
1366
- // 未决冲突文件列表便捷导出(index.js platform resolve 参数解析/报错兜底用,只读)
1367
- export function listConflictFiles(cwd) {
1368
- return new SyncManager(cwd).listConflictFiles();
1369
- }
1370
-
1371
- // ql-20260818-011:quick 会话专用 spec 树同步入口。quick-<hex8> 会话按设计无
1372
- // changes/<name>/ 实体目录,progress/四件套上行对它是孤儿数据(平台变更中心按磁盘
1373
- // change_key join 永不命中),但 spec 树增量(QUICKLOG/模块文档的上行通道)以服务器
1374
- // 清单为锚做全树 diff,与变更目录无关——triggerSync 对 quick 会话降级只调本函数,
1375
- // 不走 sync()(后者第二道 existsSync 门会以「变更不存在」提前 return)。
1376
- // 未连接平台 → {synced: 0} 静默(本地合法状态,与 syncSpecTree 内部口径一致)。
1377
- export async function syncSpecTreeOnly(changeName, cwd, opts = {}) {
1378
- const sm = new SyncManager(cwd);
1379
- const platform = sm._getPlatform();
1380
- if (!platform) return { synced: 0 };
1381
- // 树根与 sync() 内链式推送同源(BUG-01:平台模式必须锚 specRoot,防本地空树触发全量 delete)
1382
- return syncSpecTree(safePlatformSpecDir(cwd) || join(cwd, '.sillyspec'), platform, changeName, { signal: opts.signal });
1383
- }
1384
-
1385
- // TBD-hub-api: approve/reject 端点路径与请求体以 SillyHub 仓库实际 API 为准;
1386
- // 对齐时只改本函数(_submitApproval),无需动 approve/reject 入口。
1387
- /**
1388
- * 向平台提交审批决定(approve/reject 共用)。
1389
- *
1390
- * 显式用户/daemon 动作:网络/平台失败必须可见(decisions.md D-006@v1)——
1391
- * 与 best-effort 的 sync 不同,此处失败打 error 并置 process.exitCode = 1。
1392
- *
1393
- * @param {string} cwd - 工作目录
1394
- * @param {string} changeName - 变更名称
1395
- * @param {'approved'|'rejected'} decision - 审批决定
1396
- * @param {string|null} reason - rejected 时的原因(approved 时忽略)
1397
- * @returns {Promise<boolean>} 是否成功
1398
- */
1399
- async function _submitApproval(cwd, changeName, decision, reason = null) {
1400
- const sm = new SyncManager(cwd);
1401
- const platform = sm._getPlatform();
1402
- if (!platform) {
1403
- console.error('❌ 未连接平台,请先 sillyspec platform connect');
1404
- process.exitCode = 1;
1405
- return false;
1406
- }
1407
-
1408
- if (!changeName) {
1409
- console.error('❌ 审批需要指定变更名称 (changeName)');
1410
- process.exitCode = 1;
1411
- return false;
1412
- }
1413
-
1414
- // TBD-hub-api: 端点路径/body 以 SillyHub 实际 API 为准,对齐时只改此处
1415
- const approvalUrl = `${platform.url}/api/changes/${encodeURIComponent(changeName)}/approval`;
1416
- const body = decision === 'rejected'
1417
- ? { decision: 'rejected', reason }
1418
- : { decision: 'approved' };
1419
-
1420
- const result = await fetchJson(approvalUrl, {
1421
- method: 'POST',
1422
- headers: {
1423
- 'Content-Type': 'application/json',
1424
- Authorization: `Bearer ${platform.token}`,
1425
- },
1426
- body: JSON.stringify(body),
1427
- });
1428
-
1429
- // fetchJson 在非 2xx / 网络错 / 超时 / 非 JSON 时返回 null
1430
- if (result === null) {
1431
- console.error(`❌ 审批请求失败 (${changeName} → ${decision}),详情见上方 [sync] 警告`);
1432
- process.exitCode = 1;
1433
- return false;
1434
- }
1435
-
1436
- // HTTP 成功后更新本地 approvals 表(HTTP 已成功是主要目标,落库失败只 warn 不阻断)
1437
- try {
1438
- const { ProgressManager } = await import('./progress.js');
1439
- const pm = new ProgressManager({ specDir: safePlatformSpecDir(cwd) });
1440
- pm._updateApprovalStatus(cwd, changeName, decision, reason);
1441
- } catch (err) {
1442
- console.warn(`[sync] 更新本地审批状态失败 (${changeName}): ${err.message}`);
1443
- }
1444
-
1445
- if (decision === 'approved') {
1446
- console.log(`✅ 已批准变更 ${changeName}`);
1447
- } else {
1448
- console.log(`✅ 已拒绝变更 ${changeName}${reason ? `(原因: ${reason})` : ''}`);
1449
- }
1450
- return true;
1451
- }
1452
-
1453
- export async function approve(changeName, cwd) {
1454
- return _submitApproval(cwd, changeName, 'approved');
1455
- }
1456
-
1457
- export async function reject(changeName, reason, cwd) {
1458
- return _submitApproval(cwd, changeName, 'rejected', reason);
1459
- }
1460
-
1461
- export async function status(cwd) {
1462
- const sm = new SyncManager(cwd);
1463
- const st = sm.status();
1464
- if (!st.connected) {
1465
- console.log('平台: 未连接');
1466
- } else {
1467
- console.log(`平台: ${st.url}`);
1468
- console.log(`上次连接: ${st.lastSync || '未知'}`);
1469
- }
1470
- }