sillyspec 3.27.2 → 3.27.6

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 (398) hide show
  1. package/.claude/skills/sillyspec-execute/SKILL.md +8 -0
  2. package/.claude/skills/sillyspec-quick/SKILL.md +2 -1
  3. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  4. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  5. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  6. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  7. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  8. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  9. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  10. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  11. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-export/SKILL.md +57 -0
  12. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-init/SKILL.md +177 -0
  13. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  14. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  15. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  16. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  17. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  18. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-state/SKILL.md +64 -0
  19. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-status/SKILL.md +54 -0
  20. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  21. package/.claude/worktrees/sillyspec-data-model-research/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  22. package/.claude/worktrees/sillyspec-data-model-research/.gitattributes +2 -0
  23. package/.claude/worktrees/sillyspec-data-model-research/.husky/pre-push +20 -0
  24. package/.claude/worktrees/sillyspec-data-model-research/README.md +203 -0
  25. package/.claude/worktrees/sillyspec-data-model-research/SKILL.md +91 -0
  26. package/.claude/worktrees/sillyspec-data-model-research/bin/sillyspec.js +2 -0
  27. package/.claude/worktrees/sillyspec-data-model-research/logo.jpg +0 -0
  28. package/.claude/worktrees/sillyspec-data-model-research/package-lock.json +977 -0
  29. package/.claude/worktrees/sillyspec-data-model-research/package.json +39 -0
  30. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  31. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  32. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/favicon.jpg +0 -0
  33. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/index.html +16 -0
  34. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/logo.jpg +0 -0
  35. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-dashboard.html +836 -0
  36. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/dist/prototype-overview.html +256 -0
  37. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/package.json +25 -0
  38. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/executor.js +95 -0
  39. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/index.js +679 -0
  40. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/parser.js +526 -0
  41. package/.claude/worktrees/sillyspec-data-model-research/packages/dashboard/server/watcher.js +357 -0
  42. package/.claude/worktrees/sillyspec-data-model-research/src/agent-session-log.js +803 -0
  43. package/.claude/worktrees/sillyspec-data-model-research/src/change-list.js +290 -0
  44. package/.claude/worktrees/sillyspec-data-model-research/src/change-risk-profile.js +270 -0
  45. package/.claude/worktrees/sillyspec-data-model-research/src/check-primitives.js +65 -0
  46. package/.claude/worktrees/sillyspec-data-model-research/src/classify-change.js +109 -0
  47. package/.claude/worktrees/sillyspec-data-model-research/src/commit-suggest.js +202 -0
  48. package/.claude/worktrees/sillyspec-data-model-research/src/config-cat.js +88 -0
  49. package/.claude/worktrees/sillyspec-data-model-research/src/config-schema.js +328 -0
  50. package/.claude/worktrees/sillyspec-data-model-research/src/constants.js +97 -0
  51. package/.claude/worktrees/sillyspec-data-model-research/src/contract-matrix.js +480 -0
  52. package/.claude/worktrees/sillyspec-data-model-research/src/datetime.js +20 -0
  53. package/.claude/worktrees/sillyspec-data-model-research/src/db-engine.js +55 -0
  54. package/.claude/worktrees/sillyspec-data-model-research/src/db.js +381 -0
  55. package/.claude/worktrees/sillyspec-data-model-research/src/decision-distill.js +517 -0
  56. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/local-agent.js +155 -0
  57. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/backends/sillyhub-mcp.js +245 -0
  58. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/probe.js +246 -0
  59. package/.claude/worktrees/sillyspec-data-model-research/src/dispatch/strategy.js +121 -0
  60. package/.claude/worktrees/sillyspec-data-model-research/src/docs-check.js +825 -0
  61. package/.claude/worktrees/sillyspec-data-model-research/src/docs-debt.js +393 -0
  62. package/.claude/worktrees/sillyspec-data-model-research/src/docs-gate.js +107 -0
  63. package/.claude/worktrees/sillyspec-data-model-research/src/doctor-diagnostics.js +1099 -0
  64. package/.claude/worktrees/sillyspec-data-model-research/src/endpoint-extractor.js +420 -0
  65. package/.claude/worktrees/sillyspec-data-model-research/src/foreign-declared.js +78 -0
  66. package/.claude/worktrees/sillyspec-data-model-research/src/fs-atomic.js +73 -0
  67. package/.claude/worktrees/sillyspec-data-model-research/src/git-helper.js +150 -0
  68. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/claude-pre-tool-use.cjs +130 -0
  69. package/.claude/worktrees/sillyspec-data-model-research/src/hooks/worktree-guard.js +892 -0
  70. package/.claude/worktrees/sillyspec-data-model-research/src/index.js +2798 -0
  71. package/.claude/worktrees/sillyspec-data-model-research/src/init.js +626 -0
  72. package/.claude/worktrees/sillyspec-data-model-research/src/knowledge-match.js +231 -0
  73. package/.claude/worktrees/sillyspec-data-model-research/src/local-detect.js +128 -0
  74. package/.claude/worktrees/sillyspec-data-model-research/src/local-register.js +104 -0
  75. package/.claude/worktrees/sillyspec-data-model-research/src/machine-interface.js +543 -0
  76. package/.claude/worktrees/sillyspec-data-model-research/src/migrate.js +127 -0
  77. package/.claude/worktrees/sillyspec-data-model-research/src/module-impact.js +166 -0
  78. package/.claude/worktrees/sillyspec-data-model-research/src/module-resolve.js +222 -0
  79. package/.claude/worktrees/sillyspec-data-model-research/src/modules.js +580 -0
  80. package/.claude/worktrees/sillyspec-data-model-research/src/progress/change-registry.js +336 -0
  81. package/.claude/worktrees/sillyspec-data-model-research/src/progress/consistency-doctor.js +355 -0
  82. package/.claude/worktrees/sillyspec-data-model-research/src/progress/shared.js +36 -0
  83. package/.claude/worktrees/sillyspec-data-model-research/src/progress/stage-machine.js +594 -0
  84. package/.claude/worktrees/sillyspec-data-model-research/src/progress/step-store.js +265 -0
  85. package/.claude/worktrees/sillyspec-data-model-research/src/progress.js +1304 -0
  86. package/.claude/worktrees/sillyspec-data-model-research/src/quick-recommend.js +115 -0
  87. package/.claude/worktrees/sillyspec-data-model-research/src/quicklog.js +852 -0
  88. package/.claude/worktrees/sillyspec-data-model-research/src/review-tier.js +77 -0
  89. package/.claude/worktrees/sillyspec-data-model-research/src/run/command.js +1595 -0
  90. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete-handlers.js +1552 -0
  91. package/.claude/worktrees/sillyspec-data-model-research/src/run/complete.js +1259 -0
  92. package/.claude/worktrees/sillyspec-data-model-research/src/run/concurrent-detect.js +156 -0
  93. package/.claude/worktrees/sillyspec-data-model-research/src/run/gates.js +1084 -0
  94. package/.claude/worktrees/sillyspec-data-model-research/src/run/multi-repo-context.js +208 -0
  95. package/.claude/worktrees/sillyspec-data-model-research/src/run/next.js +128 -0
  96. package/.claude/worktrees/sillyspec-data-model-research/src/run/prompt.js +843 -0
  97. package/.claude/worktrees/sillyspec-data-model-research/src/run/quick-audit.js +186 -0
  98. package/.claude/worktrees/sillyspec-data-model-research/src/run/scan-profile.js +269 -0
  99. package/.claude/worktrees/sillyspec-data-model-research/src/run/shared.js +1562 -0
  100. package/.claude/worktrees/sillyspec-data-model-research/src/run/stage.js +584 -0
  101. package/.claude/worktrees/sillyspec-data-model-research/src/run.js +23 -0
  102. package/.claude/worktrees/sillyspec-data-model-research/src/scan-diff.js +388 -0
  103. package/.claude/worktrees/sillyspec-data-model-research/src/scan-postcheck.js +512 -0
  104. package/.claude/worktrees/sillyspec-data-model-research/src/scan-staleness.js +95 -0
  105. package/.claude/worktrees/sillyspec-data-model-research/src/setup.js +414 -0
  106. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/client.js +597 -0
  107. package/.claude/worktrees/sillyspec-data-model-research/src/sillyhub-mcp/config.js +62 -0
  108. package/.claude/worktrees/sillyspec-data-model-research/src/spec-dir-typo.js +50 -0
  109. package/.claude/worktrees/sillyspec-data-model-research/src/spec-sync.js +358 -0
  110. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-engine.js +171 -0
  111. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract-spec.js +550 -0
  112. package/.claude/worktrees/sillyspec-data-model-research/src/stage-contract.js +889 -0
  113. package/.claude/worktrees/sillyspec-data-model-research/src/stage-review.js +597 -0
  114. package/.claude/worktrees/sillyspec-data-model-research/src/stages/archive.js +199 -0
  115. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm-auto.js +236 -0
  116. package/.claude/worktrees/sillyspec-data-model-research/src/stages/brainstorm.js +617 -0
  117. package/.claude/worktrees/sillyspec-data-model-research/src/stages/cmd-existence.js +145 -0
  118. package/.claude/worktrees/sillyspec-data-model-research/src/stages/doctor.js +540 -0
  119. package/.claude/worktrees/sillyspec-data-model-research/src/stages/execute.js +1275 -0
  120. package/.claude/worktrees/sillyspec-data-model-research/src/stages/explore.js +43 -0
  121. package/.claude/worktrees/sillyspec-data-model-research/src/stages/index.js +29 -0
  122. package/.claude/worktrees/sillyspec-data-model-research/src/stages/knowledge.js +514 -0
  123. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan-postcheck.js +1344 -0
  124. package/.claude/worktrees/sillyspec-data-model-research/src/stages/plan.js +650 -0
  125. package/.claude/worktrees/sillyspec-data-model-research/src/stages/quick.js +167 -0
  126. package/.claude/worktrees/sillyspec-data-model-research/src/stages/scan.js +608 -0
  127. package/.claude/worktrees/sillyspec-data-model-research/src/stages/status.js +64 -0
  128. package/.claude/worktrees/sillyspec-data-model-research/src/stages/verify.js +246 -0
  129. package/.claude/worktrees/sillyspec-data-model-research/src/sync.js +1470 -0
  130. package/.claude/worktrees/sillyspec-data-model-research/src/task-review.js +1498 -0
  131. package/.claude/worktrees/sillyspec-data-model-research/src/taskcard.js +210 -0
  132. package/.claude/worktrees/sillyspec-data-model-research/src/verify-postcheck.js +1718 -0
  133. package/.claude/worktrees/sillyspec-data-model-research/src/verify-probes.js +277 -0
  134. package/.claude/worktrees/sillyspec-data-model-research/src/version.js +19 -0
  135. package/.claude/worktrees/sillyspec-data-model-research/src/workflow.js +600 -0
  136. package/.claude/worktrees/sillyspec-data-model-research/src/workspace.js +125 -0
  137. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-apply.js +1446 -0
  138. package/.claude/worktrees/sillyspec-data-model-research/src/worktree-deps.js +576 -0
  139. package/.claude/worktrees/sillyspec-data-model-research/src/worktree.js +1715 -0
  140. package/.claude/worktrees/sillyspec-data-model-research/templates/claude-instruction.md +23 -0
  141. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/taskcard-rules.md +28 -0
  142. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/testcase-design.md +12 -0
  143. package/.claude/worktrees/sillyspec-data-model-research/templates/prompts/verify-probes.md +32 -0
  144. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/archive-impact.yaml +79 -0
  145. package/.claude/worktrees/sillyspec-data-model-research/templates/workflows/scan-docs.yaml +132 -0
  146. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  147. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  148. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  149. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  150. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  151. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  152. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  153. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  154. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +57 -0
  155. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +177 -0
  156. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  157. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  158. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  159. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  160. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  161. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  162. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +64 -0
  163. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +54 -0
  164. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  165. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  166. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +6 -0
  167. package/.worktrees/8d2d0392/.gitattributes +2 -0
  168. package/.worktrees/8d2d0392/.husky/pre-push +20 -0
  169. package/.worktrees/8d2d0392/README.md +203 -0
  170. package/.worktrees/8d2d0392/SKILL.md +91 -0
  171. package/.worktrees/8d2d0392/architecture-analysis.md +448 -0
  172. package/.worktrees/8d2d0392/bin/sillyspec.js +2 -0
  173. package/.worktrees/8d2d0392/eval/README.md +86 -0
  174. package/.worktrees/8d2d0392/eval/eval.config.json +28 -0
  175. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +63 -0
  176. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +27 -0
  177. package/.worktrees/8d2d0392/eval/lib/config.mjs +82 -0
  178. package/.worktrees/8d2d0392/eval/lib/db.mjs +76 -0
  179. package/.worktrees/8d2d0392/eval/lib/report.mjs +120 -0
  180. package/.worktrees/8d2d0392/eval/lib/runner.mjs +157 -0
  181. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +73 -0
  182. package/.worktrees/8d2d0392/eval/lib/util.mjs +107 -0
  183. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +30 -0
  184. package/.worktrees/8d2d0392/eval/run.mjs +83 -0
  185. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +6 -0
  186. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  187. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +6 -0
  188. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +28 -0
  189. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +6 -0
  190. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  191. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  192. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +6 -0
  193. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +31 -0
  194. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  195. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +6 -0
  196. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  197. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +6 -0
  198. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +38 -0
  199. package/.worktrees/8d2d0392/logo.jpg +0 -0
  200. package/.worktrees/8d2d0392/package-lock.json +977 -0
  201. package/.worktrees/8d2d0392/package.json +41 -0
  202. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  203. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  204. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  205. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +16 -0
  206. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  207. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +836 -0
  208. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +256 -0
  209. package/.worktrees/8d2d0392/packages/dashboard/package.json +25 -0
  210. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +95 -0
  211. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +679 -0
  212. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +526 -0
  213. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +357 -0
  214. package/.worktrees/8d2d0392/src/agent-session-log.js +803 -0
  215. package/.worktrees/8d2d0392/src/change-list.js +290 -0
  216. package/.worktrees/8d2d0392/src/change-risk-profile.js +339 -0
  217. package/.worktrees/8d2d0392/src/check-primitives.js +65 -0
  218. package/.worktrees/8d2d0392/src/classify-change.js +109 -0
  219. package/.worktrees/8d2d0392/src/commit-suggest.js +202 -0
  220. package/.worktrees/8d2d0392/src/config-cat.js +88 -0
  221. package/.worktrees/8d2d0392/src/config-schema.js +328 -0
  222. package/.worktrees/8d2d0392/src/constants.js +97 -0
  223. package/.worktrees/8d2d0392/src/contract-matrix.js +533 -0
  224. package/.worktrees/8d2d0392/src/datetime.js +20 -0
  225. package/.worktrees/8d2d0392/src/db-engine.js +55 -0
  226. package/.worktrees/8d2d0392/src/db.js +381 -0
  227. package/.worktrees/8d2d0392/src/decision-distill.js +517 -0
  228. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +155 -0
  229. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +245 -0
  230. package/.worktrees/8d2d0392/src/dispatch/probe.js +246 -0
  231. package/.worktrees/8d2d0392/src/dispatch/strategy.js +121 -0
  232. package/.worktrees/8d2d0392/src/docs-check.js +825 -0
  233. package/.worktrees/8d2d0392/src/docs-debt.js +393 -0
  234. package/.worktrees/8d2d0392/src/docs-gate.js +107 -0
  235. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +1099 -0
  236. package/.worktrees/8d2d0392/src/endpoint-extractor.js +409 -0
  237. package/.worktrees/8d2d0392/src/foreign-declared.js +78 -0
  238. package/.worktrees/8d2d0392/src/fs-atomic.js +73 -0
  239. package/.worktrees/8d2d0392/src/git-helper.js +150 -0
  240. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +130 -0
  241. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +892 -0
  242. package/.worktrees/8d2d0392/src/index.js +2854 -0
  243. package/.worktrees/8d2d0392/src/init.js +626 -0
  244. package/.worktrees/8d2d0392/src/knowledge-match.js +231 -0
  245. package/.worktrees/8d2d0392/src/local-detect.js +128 -0
  246. package/.worktrees/8d2d0392/src/local-register.js +104 -0
  247. package/.worktrees/8d2d0392/src/machine-interface.js +543 -0
  248. package/.worktrees/8d2d0392/src/migrate.js +127 -0
  249. package/.worktrees/8d2d0392/src/module-impact.js +166 -0
  250. package/.worktrees/8d2d0392/src/module-resolve.js +222 -0
  251. package/.worktrees/8d2d0392/src/modules.js +580 -0
  252. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +126 -0
  253. package/.worktrees/8d2d0392/src/progress/change-registry.js +336 -0
  254. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +355 -0
  255. package/.worktrees/8d2d0392/src/progress/shared.js +36 -0
  256. package/.worktrees/8d2d0392/src/progress/stage-machine.js +594 -0
  257. package/.worktrees/8d2d0392/src/progress/step-store.js +265 -0
  258. package/.worktrees/8d2d0392/src/progress.js +1304 -0
  259. package/.worktrees/8d2d0392/src/quick-recommend.js +115 -0
  260. package/.worktrees/8d2d0392/src/quicklog.js +883 -0
  261. package/.worktrees/8d2d0392/src/review-tier.js +77 -0
  262. package/.worktrees/8d2d0392/src/run/command.js +1641 -0
  263. package/.worktrees/8d2d0392/src/run/complete-handlers.js +1552 -0
  264. package/.worktrees/8d2d0392/src/run/complete.js +1259 -0
  265. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +156 -0
  266. package/.worktrees/8d2d0392/src/run/gates.js +1094 -0
  267. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +208 -0
  268. package/.worktrees/8d2d0392/src/run/next.js +128 -0
  269. package/.worktrees/8d2d0392/src/run/prompt.js +843 -0
  270. package/.worktrees/8d2d0392/src/run/quick-audit.js +186 -0
  271. package/.worktrees/8d2d0392/src/run/scan-profile.js +269 -0
  272. package/.worktrees/8d2d0392/src/run/shared.js +1562 -0
  273. package/.worktrees/8d2d0392/src/run/stage.js +587 -0
  274. package/.worktrees/8d2d0392/src/run.js +23 -0
  275. package/.worktrees/8d2d0392/src/scan-diff.js +388 -0
  276. package/.worktrees/8d2d0392/src/scan-postcheck.js +524 -0
  277. package/.worktrees/8d2d0392/src/scan-staleness.js +95 -0
  278. package/.worktrees/8d2d0392/src/setup.js +414 -0
  279. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +597 -0
  280. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +62 -0
  281. package/.worktrees/8d2d0392/src/spec-dir-typo.js +50 -0
  282. package/.worktrees/8d2d0392/src/spec-sync.js +358 -0
  283. package/.worktrees/8d2d0392/src/stage-contract-engine.js +171 -0
  284. package/.worktrees/8d2d0392/src/stage-contract-spec.js +551 -0
  285. package/.worktrees/8d2d0392/src/stage-contract.js +948 -0
  286. package/.worktrees/8d2d0392/src/stage-review.js +597 -0
  287. package/.worktrees/8d2d0392/src/stages/archive.js +199 -0
  288. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +285 -0
  289. package/.worktrees/8d2d0392/src/stages/brainstorm.js +624 -0
  290. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +145 -0
  291. package/.worktrees/8d2d0392/src/stages/doctor.js +540 -0
  292. package/.worktrees/8d2d0392/src/stages/execute.js +1277 -0
  293. package/.worktrees/8d2d0392/src/stages/explore.js +43 -0
  294. package/.worktrees/8d2d0392/src/stages/index.js +29 -0
  295. package/.worktrees/8d2d0392/src/stages/knowledge.js +514 -0
  296. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +1398 -0
  297. package/.worktrees/8d2d0392/src/stages/plan.js +651 -0
  298. package/.worktrees/8d2d0392/src/stages/quick.js +167 -0
  299. package/.worktrees/8d2d0392/src/stages/scan.js +608 -0
  300. package/.worktrees/8d2d0392/src/stages/status.js +64 -0
  301. package/.worktrees/8d2d0392/src/stages/verify.js +246 -0
  302. package/.worktrees/8d2d0392/src/sync.js +1470 -0
  303. package/.worktrees/8d2d0392/src/task-review.js +1498 -0
  304. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +21 -0
  305. package/.worktrees/8d2d0392/src/taskcard.js +217 -0
  306. package/.worktrees/8d2d0392/src/verify-postcheck.js +1718 -0
  307. package/.worktrees/8d2d0392/src/verify-probes.js +327 -0
  308. package/.worktrees/8d2d0392/src/version.js +19 -0
  309. package/.worktrees/8d2d0392/src/workflow.js +600 -0
  310. package/.worktrees/8d2d0392/src/workspace.js +125 -0
  311. package/.worktrees/8d2d0392/src/worktree-apply.js +1611 -0
  312. package/.worktrees/8d2d0392/src/worktree-deps.js +576 -0
  313. package/.worktrees/8d2d0392/src/worktree.js +1838 -0
  314. package/.worktrees/8d2d0392/templates/claude-instruction.md +23 -0
  315. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +29 -0
  316. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +12 -0
  317. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +32 -0
  318. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +79 -0
  319. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +132 -0
  320. package/architecture-analysis.md +448 -0
  321. package/eval/README.md +86 -0
  322. package/eval/eval.config.json +28 -0
  323. package/eval/lib/adapters/cli.mjs +63 -0
  324. package/eval/lib/adapters/dryrun.mjs +27 -0
  325. package/eval/lib/config.mjs +82 -0
  326. package/eval/lib/db.mjs +76 -0
  327. package/eval/lib/report.mjs +120 -0
  328. package/eval/lib/runner.mjs +157 -0
  329. package/eval/lib/tasks.mjs +73 -0
  330. package/eval/lib/util.mjs +107 -0
  331. package/eval/lib/workdir.mjs +30 -0
  332. package/eval/run.mjs +83 -0
  333. package/eval/tasks/001-slugify/files/package.json +6 -0
  334. package/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  335. package/eval/tasks/001-slugify/task.json +6 -0
  336. package/eval/tasks/001-slugify/verify.mjs +28 -0
  337. package/eval/tasks/002-each-day/files/package.json +6 -0
  338. package/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  339. package/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  340. package/eval/tasks/002-each-day/task.json +6 -0
  341. package/eval/tasks/002-each-day/verify.mjs +31 -0
  342. package/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  343. package/eval/tasks/003-word-report/files/package.json +6 -0
  344. package/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  345. package/eval/tasks/003-word-report/task.json +6 -0
  346. package/eval/tasks/003-word-report/verify.mjs +38 -0
  347. package/package.json +4 -2
  348. package/src/agent-session-log.js +45 -5
  349. package/src/change-risk-profile.js +83 -14
  350. package/src/config-schema.js +18 -3
  351. package/src/contract-matrix.js +90 -29
  352. package/src/datetime.js +20 -0
  353. package/src/decision-distill.js +517 -0
  354. package/src/dispatch/backends/local-agent.js +4 -4
  355. package/src/docs-check.js +227 -0
  356. package/src/docs-debt.js +187 -24
  357. package/src/doctor-diagnostics.js +102 -2
  358. package/src/endpoint-extractor.js +41 -52
  359. package/src/foreign-declared.js +155 -0
  360. package/src/index.js +95 -13
  361. package/src/init.js +9 -7
  362. package/src/knowledge-match.js +107 -6
  363. package/src/local-register.js +7 -1
  364. package/src/module-resolve.js +12 -1
  365. package/src/modules.js +2 -1
  366. package/src/plan-adopt-waves.js +126 -0
  367. package/src/quicklog.js +50 -4
  368. package/src/run/command.js +124 -44
  369. package/src/run/complete-handlers.js +48 -19
  370. package/src/run/complete.js +5 -2
  371. package/src/run/gates.js +104 -22
  372. package/src/run/prompt.js +84 -42
  373. package/src/run/quick-audit.js +11 -0
  374. package/src/run/shared.js +152 -10
  375. package/src/run/stage.js +8 -5
  376. package/src/run.js +2 -2
  377. package/src/scan-postcheck.js +30 -17
  378. package/src/stage-contract-spec.js +3 -2
  379. package/src/stage-contract.js +68 -4
  380. package/src/stages/archive.js +53 -12
  381. package/src/stages/brainstorm-auto.js +50 -1
  382. package/src/stages/brainstorm.js +13 -0
  383. package/src/stages/doctor.js +157 -1
  384. package/src/stages/execute.js +32 -6
  385. package/src/stages/plan-postcheck.js +76 -17
  386. package/src/stages/plan.js +9 -4
  387. package/src/stages/quick.js +6 -1
  388. package/src/stages/verify.js +32 -15
  389. package/src/sync.js +41 -3
  390. package/src/task-review.js +2 -2
  391. package/src/taskcard-placeholders.js +21 -0
  392. package/src/taskcard.js +43 -1
  393. package/src/verify-postcheck.js +315 -13
  394. package/src/verify-probes.js +73 -10
  395. package/src/worktree-apply.js +569 -227
  396. package/src/worktree-deps.js +150 -1
  397. package/src/worktree.js +285 -77
  398. package/templates/prompts/taskcard-rules.md +2 -1
@@ -0,0 +1,186 @@
1
+ /**
2
+ * run/quick-audit.js(W6 Step2 从 run.js 抽出)。
3
+ *
4
+ * quick 审计结论打印 + quick 多变更关联选择(自洽,不依赖 run.js 闭包)。
5
+ * 安全锚:run.js 始终 barrel,本模块函数 run.js import 回来;无 test 直接 import,无需 re-export。
6
+ *
7
+ * 路径修正(相对 src/run/):
8
+ * - resolveQuickLinkedChanges 的 quick-recommend.js 动态 import './quick-recommend.js' → '../quick-recommend.js'
9
+ * - 脏文件信号改用 safeGit(带 safe.directory,Q3);不再 import execSync
10
+ * - parsePorcelainPath 从 ./shared.js 重 import;checkbox 改交互分支内动态 import——
11
+ * 本模块被 command.js 静态 import,顶部静态拉 @inquirer/prompts 会进**每条** run 命令
12
+ * 启动路径(实测冷加载 100-150ms),而 checkbox 仅"≥2 活跃变更 + TTY"分支用到
13
+ */
14
+ import { parsePorcelainPath, safeGit } from './shared.js'
15
+
16
+ /**
17
+ * 打印 quick 完成审计结论(按 review.status 输出 SAFE/WARNING/BLOCKED)。
18
+ */
19
+ export function printQuickAuditReview(review) {
20
+ if (review.status === 'blocked') {
21
+ console.error(`\n🚫 quick 变更边界审计 — BLOCKED:`)
22
+ for (const r of review.reasons) {
23
+ console.error(` - ${r}`)
24
+ }
25
+ console.error(`\n quick 已停止:请恢复/拆分这些变更,或重新运行 quick 并显式声明范围。`)
26
+ // 解锁咒语须在 BLOCKED 分支也给出 —— 原只在 confirm/review 分支打印,
27
+ // 普通 --done 走这里只看到「恢复/拆分」反方向指引,正确解法(带 flag 重跑)根本不出现。
28
+ // 删除:默认 fail-closed(高危操作),但 --allow-delete 显式 opt-in 可解锁(对称 --allow-new)。
29
+ if (review.deletedFiles && review.deletedFiles.length > 0) {
30
+ console.error(`\n ⛔ 本次含删除文件 ${review.deletedFiles.length} 个:${review.deletedFiles.join(', ')}`)
31
+ console.error(` 删除是破坏性操作默认 fail-closed,确认删除这些文件请带 --allow-delete 显式解锁:`)
32
+ console.error(` sillyspec run quick --done --allow-delete --change <id> --output "..."`)
33
+ console.error(` (--force-baseline / --allow-new 不能解锁删除;不确认请 git restore 撤回删除后再 --done,或走完整流程 execute 由 review 把关)`)
34
+ } else {
35
+ console.error(` 如确认接受这些变更,重新运行 --done 时带上对应 flag 即可解锁:`)
36
+ console.error(` sillyspec run quick --done --force-baseline --allow-new --change <id> --output "..."`)
37
+ console.error(` (--force-baseline 覆盖受保护/危险文件如 src/run.js;--allow-new 允许新增文件;--allow-delete 允许删除文件)`)
38
+ // 两套开关明示(坑 files-flag-not-unlock-protected,2026-08-22 实证:模块文档被判危险
39
+ // 文件,追加 --files 边界不解锁仍被拦——「追加边界」与「解锁拦截」是两套开关,交互上易误解
40
+ // 前者能解决后者)。命中危险文件 reason 时点名:--files 只改归属口径(哪些文件计入本
41
+ // 会话),不改变危险判定;受保护/危险文件的放行开关唯 --force-baseline。
42
+ if (review.reasons.some(r => r.startsWith('危险文件变更'))) {
43
+ console.error(` ⛔ 注意:追加 --files 边界不会解锁受保护/危险文件的拦截(两套开关——--files 只声明哪些文件计入本会话,不改变危险判定)。改这类文件必须 --force-baseline。`)
44
+ }
45
+ }
46
+ } else if (review.status === 'warning') {
47
+ console.warn(`\n⚠️ quick 变更边界审计 — WARNING:`)
48
+ for (const r of review.reasons) {
49
+ console.warn(` - ${r}`)
50
+ }
51
+ } else {
52
+ // 区分「本轮新增」(changedFiles,已扣前序 baseline)vs「累计暂存」(stagedTotal,全部未提交)。
53
+ // 仅当存在前序 baseline 残留(累计 > 本轮新增)时才追加括注,避免普通场景冗余。
54
+ const stagedTotal = typeof review.stagedTotal === 'number' ? review.stagedTotal : review.changedFiles.length
55
+ if (stagedTotal > review.changedFiles.length) {
56
+ console.log(`\n✅ quick 变更边界审计 — SAFE (本轮新增变更 ${review.changedFiles.length} 个文件;累计暂存 ${stagedTotal} 个,含前序 baseline ${stagedTotal - review.changedFiles.length} 个未计入本轮)`)
57
+ } else {
58
+ console.log(`\n✅ quick 变更边界审计 — SAFE (本轮新增变更 ${review.changedFiles.length} 个文件)`)
59
+ }
60
+ }
61
+ // 关联变更遗留放行提示(坑 linked-change-leftover-false-block,独立于三态都打——放行可见
62
+ // 可审计,不静默):这些文件属关联变更目录但不在本会话归属(启动后出现的他者遗留),
63
+ // 已剔除出本会话文件行,由关联变更自己的流程收尾。
64
+ if (Array.isArray(review.linkedChangeLeftovers) && review.linkedChangeLeftovers.length > 0) {
65
+ console.warn(`
66
+ 🧹 关联变更目录检测到 ${review.linkedChangeLeftovers.length} 个遗留脏文件(他者/上个 session 残留,非本会话改动)——已放行不计入本会话:`)
67
+ for (const f of review.linkedChangeLeftovers) console.warn(` - ${f}`)
68
+ console.warn(` 它们归关联变更自己的流程管;若确系本会话需要改,用 --files 显式声明归属。`)
69
+ }
70
+
71
+ // 他者会话声明豁免提示(坑 foreign-session-declared-false-block,独立于三态都打——放行可见
72
+ // 可审计,不静默,与上块同哲学):多 agent 并发时并行 quick 会话 --files 已声明的文件在本会话
73
+ // 窗口内出现——不属本会话,已退栈归该会话审计,本会话无需 --force-baseline。
74
+ if (Array.isArray(review.foreignSessionDeclared) && review.foreignSessionDeclared.length > 0) {
75
+ console.warn(`
76
+ 🔗 ${review.foreignSessionDeclared.length} 个文件已由其他 active quick 会话声明——已剔除出本会话审计,归该会话边界管:`)
77
+ for (const x of review.foreignSessionDeclared) console.warn(` - ${x.file} ← ${(x.sessions || []).join(', ')}`)
78
+ console.warn(` 并发下无需 --force-baseline:这些文件不属本会话。若确系本会话改动,恢复会话时 --files 追加声明归属(sillyspec run quick --files <file> --change <本会话ID>);`)
79
+ console.warn(` 他者会话若为崩溃残留(超 7 天未收尾),sillyspec run quick --cancel --change <他者会话ID> 清理后声明即失效。`)
80
+ }
81
+
82
+ // D-8 文档欠账显性化(advisory,独立于 status 三态都打):改了源码没动文档 → 一行欠账标记。
83
+ // 不阻断、不解锁、纯显性化——累积欠账可事后审计 QUICKLOG reasons 追溯。
84
+ if (review.docSyncHint && review.docSyncHint.touchedSource > 0 && review.docSyncHint.docFiles.length === 0) {
85
+ console.warn(`\n📝 文档欠账标记(D-8):本次 ${review.docSyncHint.touchedSource} 个源码文件改动未同步任何模块文档。`)
86
+ // O-1(docs-signals-o12):模块归属——从"改了 N 文件"到"欠在哪"(matchFilesToModules 纯函数,map 缺失时空数组降级)
87
+ if (Array.isArray(review.docSyncHint.modules) && review.docSyncHint.modules.length > 0) {
88
+ console.warn(` 涉及模块:${review.docSyncHint.modules.map(m => m.id).join(' · ')}(模块卡待同步,execute 场景详见 [docs-debt] 块)`)
89
+ }
90
+ console.warn(` quick 不强制文档同步,欠账已随本条 QUICKLOG「审计:」行落盘(可事后追溯)。若改动触及接口/契约,建议顺手同步模块文档。`)
91
+ }
92
+ if (review.docsCheckHint && review.docsCheckHint.invalid > 0) {
93
+ console.warn(`\n📎 文档引用失效(docs check):本次改动的文档含 ${review.docsCheckHint.invalid}/${review.docsCheckHint.total} 处失效 file:line 引用。`)
94
+ console.warn(` 行号漂移 → 更新到当前源码;文件删改名 → 更新引用路径。跑 sillyspec docs check 可看完整清单。`)
95
+ console.warn(` 引用格式:\`src/foo.js:42\`(或 42-48)+ 同行反引号代码符号(如 \`runDocsCheck\`)——符号可让 --suggest 给出候选行号。`)
96
+ }
97
+ // task-03: 活文档引用真失效提示(advisory 不阻断,不改 status 三态判定)——方向与上方互补:
98
+ // 上方查「本次改的文档」,这里查「本次改的 src 被活文档(platform-interface-map 等)引用」。
99
+ // 2026-08-18 精度对齐:只渲染真失效引用(drift.invalid,auditQuickCompletion 已跑 runDocsCheck
100
+ // 分层校验),行号锚未真断时零输出——不再「被引用即提示」误报。
101
+ if (review.docsCheckHint && review.docsCheckHint.livingDocDrift) {
102
+ const drift = review.docsCheckHint.livingDocDrift
103
+ const invalid = Array.isArray(drift.invalid) ? drift.invalid : []
104
+ const total = typeof drift.total === 'number' ? drift.total : drift.files.length
105
+ if (invalid.length > 0) {
106
+ console.warn(`\n📎 活文档引用真失效:${drift.files.length}/${total} 个改动 src 文件被 ${drift.docs.join('、')} 引用,其中 ${invalid.length} 处引用校验失败:`)
107
+ for (const x of invalid.slice(0, 8)) {
108
+ console.warn(` - ${x.doc}:${x.docLine} \`${x.ref}\` → ${x.reason}`)
109
+ }
110
+ if (invalid.length > 8) console.warn(` … 共 ${invalid.length} 处,跑 sillyspec docs check 看全量与建议行号`)
111
+ else console.warn(` 行号漂移 → 更新到当前源码;跑 sillyspec docs check 可看建议行号。`)
112
+ }
113
+ }
114
+ }
115
+
116
+ /**
117
+ * quick 阶段多变更交互式选择关联变更。
118
+ * - 0 活跃变更 → [](仅记 QUICKLOG,不关联)
119
+ * - 1 活跃变更 → 默认关联它(保持现状友好,不弹交互)
120
+ * - ≥2 活跃变更 + 交互 → checkbox 多选(推荐项默认勾,空选 = 不关联)
121
+ * - ≥2 活跃变更 + 非交互 → [](不关联)+ 提示用 --change a,b
122
+ */
123
+ export async function resolveQuickLinkedChanges({ pm, cwd, specDir, quickFiles, taskDescription, nonInteractive }) {
124
+ let activeChanges = []
125
+ try {
126
+ activeChanges = pm.listChanges(cwd)
127
+ } catch {
128
+ activeChanges = []
129
+ }
130
+ if (activeChanges.length === 0) return []
131
+ if (activeChanges.length === 1) return [activeChanges[0]]
132
+
133
+ if (nonInteractive || !process.stdin.isTTY) {
134
+ console.log('💡 非交互环境,已默认不关联变更;如需关联请用 --change a,b')
135
+ return []
136
+ }
137
+
138
+ // 脏文件(推荐信号之一)。safeGit 带 safe.directory,避免 linked worktree/容器/挂载点下裸
139
+ // `git status` 抛错致推荐信号静默丢失(multi-agent-review Q3 同类)。推荐非关键路径,失败回退 []。
140
+ // trim:false:porcelain 首行前导空格是状态码,trim 会削掉致 parsePorcelainPath 丢首字符。
141
+ let baselineFiles = []
142
+ const statusResult = safeGit(cwd, ['status', '--porcelain'], { trim: false })
143
+ if (!statusResult.error) {
144
+ baselineFiles = (statusResult.value || '').split('\n').filter(Boolean)
145
+ .map(l => parsePorcelainPath(l))
146
+ .filter(Boolean)
147
+ .filter(f => !f.startsWith('.sillyspec/'))
148
+ }
149
+
150
+ // 推荐打分(脏文件 + 任务描述双信号)
151
+ let recommendations = []
152
+ try {
153
+ // quick-recommend.js 在 src/,本模块在 src/run/ → 退一层(真环依赖,保留动态 import)
154
+ const { recommendChanges } = await import('../quick-recommend.js')
155
+ recommendations = recommendChanges({ activeChanges, specDir, baselineFiles, quickFiles, taskDescription })
156
+ } catch {
157
+ recommendations = activeChanges.map(name => ({ name, score: 0, reasons: [] }))
158
+ }
159
+ const scoreMap = new Map(recommendations.map(r => [r.name, r.score]))
160
+ const reasonMap = new Map(recommendations.map(r => [r.name, r.reasons]))
161
+ const recommendedSet = new Set(recommendations.filter(r => r.score > 0).map(r => r.name))
162
+
163
+ // 按推荐分降序展示
164
+ const ordered = [...activeChanges].sort((a, b) =>
165
+ (scoreMap.get(b) || 0) - (scoreMap.get(a) || 0) || a.localeCompare(b))
166
+
167
+ const choices = ordered.map(name => {
168
+ const reasons = reasonMap.get(name) || []
169
+ const isRec = recommendedSet.has(name)
170
+ return {
171
+ name: `${isRec ? '⭐ ' : ' '}${name}`,
172
+ value: name,
173
+ description: reasons.length > 0 ? reasons.join(';') : '无推荐信号',
174
+ checked: isRec,
175
+ }
176
+ })
177
+
178
+ console.log('🔗 检测到多个活跃变更,选择本次 quick 关联哪些(可多选;不勾选任何项 = 仅记 QUICKLOG,不关联变更)')
179
+ if (recommendedSet.size > 0) {
180
+ console.log(' ⭐ = 基于脏文件/任务描述推荐,已默认勾选')
181
+ }
182
+ // 动态 import:@inquirer/prompts 只在本交互分支加载,不进 run 命令通用启动路径
183
+ const { checkbox } = await import('@inquirer/prompts')
184
+ const selected = await checkbox({ message: '关联变更(空格切换,回车确认)', choices })
185
+ return selected
186
+ }
@@ -0,0 +1,269 @@
1
+ /**
2
+ * run/scan-profile.js(W6 Step2 从 run.js 抽出)。
3
+ *
4
+ * scan profile 数据生成 + quick scan CLI preflight/postcheck(自洽,不依赖 run.js 闭包)。
5
+ * 安全锚:run.js 始终 barrel,本模块函数 run.js import 回来;无 test 直接 import,无需 re-export。
6
+ *
7
+ * 路径修正(相对 src/run/):
8
+ * - executeScanPostcheck 的 scan-postcheck.js 动态 import './scan-postcheck.js' → '../scan-postcheck.js'
9
+ * - executeScanPostcheck 原冗余动态 import('fs'/'path'/'child_process') 删除,改顶部静态(execSync 实际未直接用,纯遗留)
10
+ */
11
+ import { join, basename, extname } from 'node:path'
12
+ import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync } from 'node:fs'
13
+ import { safeGit } from './shared.js'
14
+
15
+ /**
16
+ * 估算源码规模(文件数 + 字节数)—— 跨平台 Node 遍历,替代 Unix `find`(原生 Windows 无 find,
17
+ * 原 find 失效会让所有 Windows 项目永远 fallback 到 standard profile)。
18
+ * 扩展名限定源码后缀;skipDirs 排除依赖/构建产物/覆盖率等非源码目录;maxFiles 封顶避免超大仓库遍历过久
19
+ * (超限时 fileCount 已远超 quick/standard 阈值,不影响 profile 判定);maxDepth 兜底防极深嵌套产物。
20
+ */
21
+ export function estimateSourceSize(cwd, maxFiles = 5000, maxDepth = 6) {
22
+ const sourceExts = new Set(['.js','.ts','.tsx','.py','.java','.go','.rs','.rb','.php','.c','.cpp','.h','.jsx','.vue','.svelte'])
23
+ // skipDirs:排除依赖、版本控制、构建产物、覆盖率、临时目录等非源码目录。
24
+ // 原清单只排了 node_modules/.git/dist/build 等,漏了 .next/.nuxt/coverage/.svelte-kit 等构建产物,
25
+ // 导致带构建产物的小项目被产物里的海量 .js 拉高 fileCount/sourceBytes → 误判 deep。
26
+ const skipDirs = new Set([
27
+ 'node_modules', '.git', 'dist', 'build', 'out', 'target',
28
+ '__pycache__', '.venv', 'venv',
29
+ '.next', '.nuxt', '.output', '.svelte-kit', '.astro', '.turbo', '.parcel-cache',
30
+ 'coverage', '.nyc_output', '.vitest', '.cache',
31
+ 'vendor', 'bower_components',
32
+ 'dist-types',
33
+ '.sillyspec', '.claude',
34
+ 'tmp', 'temp', '.tmp', 'logs',
35
+ ])
36
+ let fileCount = 0
37
+ let sourceBytes = 0
38
+ // stack 存 [dir, depth]:maxDepth 兜底,防极深嵌套的产物/生成目录在 skipDirs 漏网时被全遍历。
39
+ const stack = [[cwd, 0]]
40
+ while (stack.length) {
41
+ const [dir, depth] = stack.pop()
42
+ let entries
43
+ try { entries = readdirSync(dir, { withFileTypes: true }) }
44
+ catch { continue }
45
+ for (const e of entries) {
46
+ if (e.isDirectory()) {
47
+ if (!skipDirs.has(e.name) && depth < maxDepth) stack.push([join(dir, e.name), depth + 1])
48
+ } else if (e.isFile() && sourceExts.has(extname(e.name))) {
49
+ fileCount++
50
+ try { sourceBytes += statSync(join(dir, e.name)).size } catch {}
51
+ if (fileCount >= maxFiles) return { fileCount, sourceBytes }
52
+ }
53
+ }
54
+ }
55
+ return { fileCount, sourceBytes }
56
+ }
57
+
58
+ /**
59
+ * 根据 project 规模计算 scan profile
60
+ * quick: fileCount≤30 && sourceBytes≤80KB && projectCount≤3 → 3 步,0 子代理,5 份文档
61
+ * standard: fileCount≤200 && sourceBytes≤800KB → 压缩步骤,最多 1 子代理
62
+ * deep: 大项目或 --deep → 完整流程
63
+ */
64
+ export function computeScanProfile(cwd, platformOpts) {
65
+ // 显式 profile flag 优先于自动判定(三档互斥由 command.js 检测;此处取首个命中即可)
66
+ const flags = process.argv.slice(2)
67
+ if (flags.includes('--quick')) {
68
+ return { mode: 'quick', reason: '用户指定 --quick', maxAgentCalls: 0, maxDocs: 5 }
69
+ }
70
+ if (flags.includes('--standard')) {
71
+ return { mode: 'standard', reason: '用户指定 --standard', maxAgentCalls: 1, maxDocs: 8 }
72
+ }
73
+ if (flags.includes('--deep')) {
74
+ return { mode: 'deep', reason: '用户指定 --deep', maxAgentCalls: 4, maxDocs: 99 }
75
+ }
76
+
77
+ const specDir = platformOpts?.specRoot || join(cwd, '.sillyspec')
78
+ const projectsDir = join(specDir, 'projects')
79
+ let projectCount = 1
80
+ try {
81
+ if (existsSync(projectsDir)) {
82
+ projectCount = readdirSync(projectsDir).filter(f => f.endsWith('.yaml')).length
83
+ }
84
+ } catch {}
85
+
86
+ // 快速估算源码规模(Node 遍历,跨平台;原 Unix find 在原生 Windows 上失效会永远 fallback standard)
87
+ let fileCount = 0
88
+ let sourceBytes = 0
89
+ try {
90
+ const est = estimateSourceSize(cwd)
91
+ fileCount = est.fileCount
92
+ sourceBytes = est.sourceBytes
93
+ } catch {
94
+ // 遍历异常时假设中等规模
95
+ return { mode: 'standard', reason: '无法估算项目规模', maxAgentCalls: 1, maxDocs: 8 }
96
+ }
97
+
98
+ if (fileCount <= 30 && sourceBytes <= 80_000 && projectCount <= 3) {
99
+ return { mode: 'quick', reason: `${fileCount} 源文件, ${Math.round(sourceBytes / 1024)}KB`, maxAgentCalls: 0, maxDocs: 5, _fileCount: fileCount, _sourceBytes: sourceBytes, _projectCount: projectCount }
100
+ }
101
+ if (fileCount <= 200 && sourceBytes <= 800_000) {
102
+ return { mode: 'standard', reason: `${fileCount} 源文件, ${Math.round(sourceBytes / 1024)}KB`, maxAgentCalls: 1, maxDocs: 8, _fileCount: fileCount, _sourceBytes: sourceBytes, _projectCount: projectCount }
103
+ }
104
+ return { mode: 'deep', reason: `${fileCount} 源文件, ${Math.round(sourceBytes / 1024)}KB`, maxAgentCalls: 4, maxDocs: 99, _fileCount: fileCount, _sourceBytes: sourceBytes, _projectCount: projectCount }
105
+ }
106
+
107
+ /**
108
+ * quick 档 3 步表构建(唯一真相):applyScanProfileSteps(首进程裁剪)与 getStageSteps
109
+ * (后续进程重取定义)共用。此前 quick 步骤表只在首进程 applyScanProfileSteps 里内联构建,
110
+ * getStageSteps('scan') 恒返回 11 步注册表 → 同进程 outputStep 用注册表 defSteps[1] 渲染错位
111
+ * prompt;跨进程 ensureStageSteps 见 3 vs 11 触发长度漂移重播种,quick 已完成步丢失、
112
+ * agent 从未做过的注册表步骤被 --done(坑 scan-quick-profile-step-mismatch)。
113
+ */
114
+ export function buildQuickScanSteps() {
115
+ return [
116
+ {
117
+ name: '项目概览(自动探测)',
118
+ status: 'pending',
119
+ noAI: true,
120
+ _cliAction: 'scanPreflight',
121
+ prompt: '',
122
+ outputHint: 'preflight 结果',
123
+ optional: false
124
+ },
125
+ {
126
+ name: '生成核心文档',
127
+ status: 'pending',
128
+ prompt: `## Quick Scan — 核心文档生成
129
+
130
+ 当前为 quick profile(小项目自动判定 或 用户显式 --quick),一次性生成核心文档用于快速接入。
131
+
132
+ ### 操作
133
+ 1. 读取项目结构和关键文件(package.json / pyproject.toml / README / 入口文件)
134
+ 2. 生成以下 4 份文档并写入 \`{DOCS_ROOT}/scan/\`:
135
+ - **PROJECT.md** — 项目简介、技术栈、模块划分
136
+ - **ARCHITECTURE.md** — 架构概览、模块关系、技术决策
137
+ - **CONVENTIONS.md** — 代码风格、框架隐形规则
138
+ - **STRUCTURE.md** — 目录树 + 模块说明
139
+ 3. 如发现子项目,注册到 \`{PROJECTS_ROOT}/\` 下
140
+
141
+ 每份文档 frontmatter 必须包含:\`author\`、\`created_at\`、\`scan_depth: quick\`(标记快速接入的浅层版本;后续深度扫描 --deep 会识别此标记并覆盖升级为完整文档)。
142
+
143
+ ### ⛔ 硬约束
144
+ - **严禁使用子代理(Agent/Task 工具)。** 所有文档在一个 turn 内完成。
145
+ - 不要搜索 .sillyspec/ .claude/ .git/ node_modules/ dist/ build/
146
+ - --output 只需要列出生成的文件名,不要写长篇总结
147
+
148
+ ### 输出
149
+ 生成的文件列表`,
150
+ outputHint: '文件列表',
151
+ optional: false
152
+ },
153
+ {
154
+ // 名字与注册表末步一致(按名匹配/迁移语义);prompt 清空、noAI postcheck 自动执行
155
+ name: '自检和提交',
156
+ status: 'pending',
157
+ prompt: '',
158
+ outputHint: '结果',
159
+ optional: false,
160
+ noAI: true,
161
+ _cliAction: 'scanPostcheck'
162
+ }
163
+ ]
164
+ }
165
+
166
+ /**
167
+ * 根据 scanProfile 裁剪步骤
168
+ * quick: 3 步 — CLI preflight / AI generate / CLI postcheck
169
+ * standard: 跳过续扫检测(4), 跳过可选步骤(9)
170
+ */
171
+ export function applyScanProfileSteps(stageData, profile, cwd, platformOpts) {
172
+ const steps = stageData.steps
173
+ const mode = profile.mode
174
+
175
+ if (mode === 'quick') {
176
+ // 3 步表构建抽至 buildQuickScanSteps(getStageSteps 同源复用,防跨进程 3 vs 11 漂移)
177
+ stageData.steps = buildQuickScanSteps()
178
+ return
179
+ }
180
+
181
+ if (mode === 'standard') {
182
+ // 跳过 Step 4(断点续扫检测),跳过 Step 9(flows+glossary,可选)
183
+ const skipNames = ['断点续扫检测', '生成业务流程和术语表(可选)']
184
+ for (const step of stageData.steps) {
185
+ if (skipNames.includes(step.name) && step.status === 'pending') {
186
+ step.status = 'skipped'
187
+ step.skippedAt = new Date().toLocaleString('zh-CN', { hour12: false })
188
+ }
189
+ }
190
+ }
191
+ }
192
+
193
+ /**
194
+ * CLI-only: quick scan preflight
195
+ * 收集项目快照,打印 summary,不调 AI
196
+ */
197
+ export async function executeScanPreflight(cwd, platformOpts, scanProfile) {
198
+ const specBase = platformOpts?.specRoot || join(cwd, '.sillyspec')
199
+ const projectName = basename(cwd)
200
+ console.log(` 📁 项目: ${projectName}`)
201
+ console.log(` 📊 Profile: ${scanProfile.mode} (${scanProfile.reason})`)
202
+ // 快速列出顶层结构(readdirSync 跨平台,避免 spawn shell + 5 个 grep 进程)
203
+ try {
204
+ const skip = new Set(['node_modules', '.git', '.sillyspec', '.claude'])
205
+ const dirNames = readdirSync(cwd, { withFileTypes: true })
206
+ .filter(d => d.isDirectory() && !skip.has(d.name) && !d.name.startsWith('.'))
207
+ .slice(0, 20)
208
+ .map(d => d.name)
209
+ if (dirNames.length) {
210
+ console.log(` 📂 目录: ${dirNames.join(', ')}`)
211
+ }
212
+ } catch {}
213
+ console.log(` ✅ Preflight 完成,准备生成核心文档\n`)
214
+ }
215
+
216
+ /**
217
+ * CLI-only: quick scan postcheck
218
+ * 执行文件存在性 + manifest 检查,不调 AI
219
+ */
220
+ export async function executeScanPostcheck(cwd, platformOpts, scanProfile) {
221
+ // scan-postcheck.js 在 src/,本模块在 src/run/ → 退一层(真环依赖,保留动态 import)
222
+ const { runScanPostCheck, printScanPostCheckResult } = await import('../scan-postcheck.js')
223
+ const specDir = platformOpts?.specRoot || null
224
+ const result = runScanPostCheck({
225
+ cwd,
226
+ specDir,
227
+ scanMeta: {
228
+ projectListParsed: true,
229
+ manifestWritten: undefined,
230
+ },
231
+ })
232
+ printScanPostCheckResult(result)
233
+ // 写 manifest(如果还没写)
234
+ if (platformOpts?.specRoot) {
235
+ try {
236
+ const manifestDir = platformOpts.specRoot
237
+ let sourceCommit = null
238
+ let sourceCommitError = null
239
+ try {
240
+ const gitResult = safeGit(cwd, ['rev-parse', 'HEAD'])
241
+ sourceCommit = gitResult.value
242
+ sourceCommitError = gitResult.error
243
+ } catch (e) {
244
+ sourceCommitError = e.message
245
+ }
246
+ mkdirSync(manifestDir, { recursive: true })
247
+ const manifest = {
248
+ scan_profile: {
249
+ mode: scanProfile.mode,
250
+ file_count: scanProfile._fileCount || 0,
251
+ source_bytes: scanProfile._sourceBytes || 0,
252
+ project_count: scanProfile._projectCount || 0,
253
+ reason: scanProfile.reason,
254
+ },
255
+ workspace_id: platformOpts.workspaceId || null,
256
+ scan_run_id: platformOpts.scanRunId || null,
257
+ source_commit: sourceCommit,
258
+ source_commit_error: sourceCommit === null ? (sourceCommitError || 'unknown') : undefined,
259
+ generated_at: new Date().toISOString(),
260
+ schema_version: 2,
261
+ }
262
+ const manifestPath = join(manifestDir, 'manifest.json')
263
+ writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n')
264
+ console.log(` 📄 manifest.json 已写入: ${manifestPath}`)
265
+ } catch (e) {
266
+ console.warn(` ⚠️ manifest 写入失败: ${e.message}`)
267
+ }
268
+ }
269
+ }