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
@@ -13,6 +13,17 @@ import { execSync } from 'child_process'
13
13
 
14
14
  // ─── Provider: 扫描后端 router 注册的端点 ───────────────────────────────
15
15
 
16
+ /**
17
+ * matchIndex → 装饰器/路由起始行号(全文匹配配套;1-based)。
18
+ * 坑 endpoint-multiline-decorator-miss(2026-08-24 用户实证):三框架提取器原为逐行匹配,
19
+ * 多行装饰器(`@router.get(\n "/path",\n response_model=…)` 等)路径不在装饰器行 → 端点
20
+ * 静默漏 → endpoints.json artifact 与 live 扫描双失真 → probe5 missingBackend 误报(11 个
21
+ * 存量端点)。装饰器匹配改为全文正则(`\s*` 天然跨换行),行号取起始行。
22
+ */
23
+ function lineOfIndex(content, index) {
24
+ return content.slice(0, index).split('\n').length
25
+ }
26
+
16
27
  /**
17
28
  * 从单个文件提取 FastAPI router 端点
18
29
  * 支持 APIRouter(prefix=...) 和 @router.get/post/put/delete/patch("/path")
@@ -25,7 +36,7 @@ export function extractFastApiEndpoints(filePath) {
25
36
  const lines = content.split('\n')
26
37
  const endpoints = []
27
38
 
28
- // 1. 提取 router prefix
39
+ // 1. 提取 router prefix(逐行,同文件近似——维持原行为)
29
40
  let routerPrefix = ''
30
41
  for (const line of lines) {
31
42
  const prefixMatch = line.match(/(?:APIRouter|router)\s*\(\s*(?:prefix\s*=\s*)?["'`]([^"'`]+)["'`]/)
@@ -35,40 +46,17 @@ export function extractFastApiEndpoints(filePath) {
35
46
  }
36
47
  }
37
48
 
38
- // 2. 提取 @router.method("/path") 或分散式定义
39
- // FastAPI 支持两种写法:
40
- // a) @router.get("/path", ...) 下一行 def func():
41
- // b) @router.get 下一行 ("/path", ...)
42
- for (let i = 0; i < lines.length; i++) {
43
- const line = lines[i]
44
- const decoratorMatch = line.match(
45
- /@(?:router|api_router)\.(get|post|put|delete|patch)\s*\(\s*["'`]([^"'`]+)["'`]/
46
- )
47
- if (decoratorMatch) {
48
- const method = decoratorMatch[1].toUpperCase()
49
- const rawPath = decoratorMatch[2]
50
- endpoints.push({
51
- method,
52
- path: routerPrefix + rawPath,
53
- source: filePath,
54
- line: i + 1,
55
- })
56
- continue
57
- }
58
- // 分散式: @router.get\n ("/path",
59
- const splitMatch = line.match(/@(?:router|api_router)\.(get|post|put|delete|patch)\s*$/)
60
- if (splitMatch && i + 1 < lines.length) {
61
- const nextLine = lines[i + 1]
62
- const pathMatch = nextLine.match(/\(\s*["'`]([^"'`]+)["'`]/)
63
- if (pathMatch) {
64
- endpoints.push({
65
- method: splitMatch[1].toUpperCase(),
66
- path: routerPrefix + pathMatch[1],
67
- source: filePath,
68
- line: i + 1,
69
- })
70
- }
71
- }
49
+ // 2. 装饰器全文匹配:单行 `@router.get("/path")`、分散式 `@router.get\n("/path")`、
50
+ // 多行参数 `@router.get(\n "/path",\n response_model=…)` 三态合一(\s* 跨换行)
51
+ const decoratorRe = /@(?:router|api_router)\.(get|post|put|delete|patch)\s*\(\s*["'`]([^"'`]+)["'`]/g
52
+ let m
53
+ while ((m = decoratorRe.exec(content)) !== null) {
54
+ endpoints.push({
55
+ method: m[1].toUpperCase(),
56
+ path: routerPrefix + m[2],
57
+ source: filePath,
58
+ line: lineOfIndex(content, m.index),
59
+ })
72
60
  }
73
61
 
74
62
  return endpoints
@@ -94,16 +82,18 @@ export function extractExpressEndpoints(filePath) {
94
82
  if (useMatch) routerPrefix = useMatch[1]
95
83
  }
96
84
 
85
+ // 路由全文匹配(坑 endpoint-multiline-decorator-miss:`router.get(\n "/path",\n handler)` 同病)
86
+ const routeRe = /\b(?:app|router)\.(get|post|put|delete|patch)\s*\(\s*["'`]([^"'`]+)["'`]/gi
87
+ let m
88
+ while ((m = routeRe.exec(content)) !== null) {
89
+ endpoints.push({ method: m[1].toUpperCase(), path: routerPrefix + m[2], source: filePath, line: lineOfIndex(content, m.index) })
90
+ }
91
+
92
+ // 链式 .route(path).get(h).put(h) —— 同行所有 method 配上 path(跨行链式不扩面,维持逐行)
97
93
  for (let i = 0; i < lines.length; i++) {
98
94
  const line = lines[i]
99
- const m = line.match(/\b(?:app|router)\.(get|post|put|delete|patch)\s*\(\s*["'`]([^"'`]+)["'`]/i)
100
- if (m) {
101
- endpoints.push({ method: m[1].toUpperCase(), path: routerPrefix + m[2], source: filePath, line: i + 1 })
102
- continue
103
- }
104
95
  const routeChain = line.match(/\.route\s*\(\s*["'`]([^"'`]+)["'`]/)
105
96
  if (routeChain) {
106
- // 链式 .route(path).get(h).put(h) —— 同行所有 method 配上 path
107
97
  const chainPath = routerPrefix + routeChain[1]
108
98
  for (const mm of line.matchAll(/\.(get|post|put|delete|patch)\s*\(/gi)) {
109
99
  endpoints.push({ method: mm[1].toUpperCase(), path: chainPath, source: filePath, line: i + 1 })
@@ -135,17 +125,16 @@ export function extractSpringEndpoints(filePath) {
135
125
 
136
126
  const methodMap = { get: 'GET', post: 'POST', put: 'PUT', delete: 'DELETE', patch: 'PATCH' }
137
127
 
138
- for (let i = 0; i < lines.length; i++) {
139
- const line = lines[i]
140
- const shortMatch = line.match(/@(Get|Post|Put|Delete|Patch)Mapping\s*\(\s*(?:value\s*=\s*)?["'`]([^"'`]+)["'`]/i)
141
- if (shortMatch) {
142
- endpoints.push({ method: methodMap[shortMatch[1].toLowerCase()], path: classPrefix + shortMatch[2], source: filePath, line: i + 1 })
143
- continue
144
- }
145
- const oldMatch = line.match(/@RequestMapping\s*\(\s*(?:value\s*=\s*)?["'`]([^"'`]+)["'`][^)]*?method\s*=\s*RequestMethod\.(\w+)/i)
146
- if (oldMatch) {
147
- endpoints.push({ method: oldMatch[2].toUpperCase(), path: classPrefix + oldMatch[1], source: filePath, line: i + 1 })
148
- }
128
+ // 短形式全文匹配(坑 endpoint-multiline-decorator-miss:`@GetMapping(\n "/path"\n)` 同病)
129
+ const shortRe = /@(Get|Post|Put|Delete|Patch)Mapping\s*\(\s*(?:value\s*=\s*)?["'`]([^"'`]+)["'`]/gi
130
+ let m
131
+ while ((m = shortRe.exec(content)) !== null) {
132
+ endpoints.push({ method: methodMap[m[1].toLowerCase()], path: classPrefix + m[2], source: filePath, line: lineOfIndex(content, m.index) })
133
+ }
134
+ // 旧形式全文匹配([^)]*? 字符类可跨行,`@RequestMapping(\n value="/p",\n method=…)` 随全文化一并覆盖)
135
+ const oldRe = /@RequestMapping\s*\(\s*(?:value\s*=\s*)?["'`]([^"'`]+)["'`][^)]*?method\s*=\s*RequestMethod\.(\w+)/gi
136
+ while ((m = oldRe.exec(content)) !== null) {
137
+ endpoints.push({ method: m[2].toUpperCase(), path: classPrefix + m[1], source: filePath, line: lineOfIndex(content, m.index) })
149
138
  }
150
139
 
151
140
  return endpoints
@@ -0,0 +1,155 @@
1
+ /**
2
+ * 他者会话显式声明文件集(坑 verify-reconcile-foreign-wip,2026-08-23 实证:verify 实测
3
+ * 对账在主仓共享工作区取 git diff,无 meta 回退时把并行会话在途 WIP 全量算进本变更——误
4
+ * 命中他者模块跑他者测试 / 他者删除进本变更删除对账误报)。
5
+ *
6
+ * 归属口径与坑 35(quick 审计豁免,run/shared 的 collectOtherQuickSessionDeclarations)
7
+ * 同款:只认**显式声明**——其他 quick 会话 guard.allowedFiles + 其他变更 design §6 清单;
8
+ * 无主文件保留参与判定(fail-closed,不放松「未声明删除/越界」的抓取底线)。
9
+ *
10
+ * 独立零环模块:被 verify-postcheck / verify-probes / contract-matrix 共用(verify-
11
+ * postcheck import contract-matrix,parity 侧不能反向 import verify-postcheck)。
12
+ */
13
+ import { existsSync, readFileSync, readdirSync } from 'fs'
14
+ import { join } from 'path'
15
+ import { parseFileChangeListDetailed } from './change-list.js'
16
+ import { safeGit, unquoteGitPath } from './git-helper.js'
17
+
18
+ /**
19
+ * 主仓未提交文件集(staged + unstaged + untracked,rename 取新路径)。
20
+ * 活性判定的事实源:他者声明的文件若已不在未提交集,说明其工作已 apply+commit(或从未发生),
21
+ * 声明随之失效(坑 foreign-declared-stale-noise,2026-08-25 实证:并行会话 pathspec 重叠期
22
+ * execute/verify 每轮重复刷「已排除 N 个并行会话声明的文件」,其中大量是对方早已 apply+commit
23
+ * 的存量声明——design §6 清单与残留 quick guard 不随 commit 自动失效,纯噪音)。
24
+ * @param {string} cwd 项目根
25
+ * @returns {Set<string>|null} null = git 调用失败(调用方 fail-closed 不过滤)
26
+ */
27
+ function getMainDirtySet(cwd) {
28
+ const r = safeGit(cwd, ['status', '--porcelain', '--untracked-files=all'], { trim: false })
29
+ if (r.value === null) return null
30
+ const set = new Set()
31
+ for (const line of r.value.split('\n')) {
32
+ if (!line.trim()) continue
33
+ let p = line.slice(3).trim()
34
+ const arrow = p.lastIndexOf(' -> ')
35
+ if (arrow !== -1) p = p.slice(arrow + 4)
36
+ if (p.startsWith('"') && p.endsWith('"')) p = unquoteGitPath(p.slice(1, -1))
37
+ p = p.replace(/\\/g, '/')
38
+ if (p) set.add(p)
39
+ }
40
+ return set
41
+ }
42
+
43
+ /**
44
+ * 变更 worktree 活性速查(.runtime/worktrees/<change>/meta.json)。
45
+ * isolated=true:有存活隔离 worktree(meta 在、非 in-place、worktreePath 目录在)——
46
+ * 其 WIP 在 worktree 内主仓 porcelain 不可见,整份 design 声明按在途处理。
47
+ * @returns {Map<string, { isolated: boolean }>|null} null = 读取失败(fail-closed)
48
+ */
49
+ function loadWorktreeLiveness(specBase) {
50
+ const map = new Map()
51
+ try {
52
+ const dir = join(specBase, '.runtime', 'worktrees')
53
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
54
+ if (!e.isDirectory()) continue
55
+ try {
56
+ const meta = JSON.parse(readFileSync(join(dir, e.name, 'meta.json'), 'utf8'))
57
+ const isolated = Boolean(meta && meta.mode !== 'in-place-fallback'
58
+ && meta.worktreePath && existsSync(meta.worktreePath))
59
+ map.set(meta.changeName || e.name, { isolated })
60
+ } catch { /* 单条损坏跳过(该变更走主仓 dirty 判定) */ }
61
+ }
62
+ } catch { return null }
63
+ return map
64
+ }
65
+
66
+ /**
67
+ * 他者声明活性收敛:声明只在「工作仍在途」时有效,已 apply+commit 的存量声明自动失效。
68
+ * - quick 会话(主仓直接改):文件仍在主仓未提交集才算在途
69
+ * - 变更:有存活隔离 worktree → 整份声明在途;否则与 quick 同口径看主仓未提交集
70
+ * 判定所需事实读不出来(git/meta 失败)→ 一律保留(fail-closed,不放大放行面)。
71
+ * @param {Map<string, string[]>} foreign collectForeignDeclaredFiles 的原始结果(原地收敛)
72
+ */
73
+ function filterStaleForeignDeclarations(foreign, cwd, specBase) {
74
+ if (foreign.size === 0) return
75
+ const dirty = getMainDirtySet(cwd)
76
+ const worktrees = loadWorktreeLiveness(specBase)
77
+ if (dirty === null && worktrees === null) return // 两个事实源全失败 → 原样保留
78
+ for (const [file, owners] of [...foreign.entries()]) {
79
+ const live = owners.filter(owner => {
80
+ if (!owner.startsWith('quick-')) {
81
+ const wt = worktrees ? worktrees.get(owner) : undefined
82
+ if (wt && wt.isolated) return true // 隔离 worktree 在途,声明整份有效
83
+ }
84
+ // quick 会话 / 无存活 worktree 的变更:看主仓未提交集;dirty 集不可用则保守保留
85
+ return dirty === null ? true : dirty.has(file)
86
+ })
87
+ if (live.length === 0) foreign.delete(file)
88
+ else if (live.length < owners.length) foreign.set(file, live)
89
+ }
90
+ }
91
+
92
+ /**
93
+ * @param {string} cwd 项目根
94
+ * @param {string|null} currentChangeName 本变更名(quick 会话名或 change 名,排除自身)
95
+ * @returns {Map<string, string[]>} file → 声明者列表(quick-<hex> 或变更名)
96
+ */
97
+ export function collectForeignDeclaredFiles(cwd, currentChangeName) {
98
+ const foreign = new Map()
99
+ const add = (file, owner) => {
100
+ const f = String(file || '').replace(/\\/g, '/')
101
+ if (!f) return
102
+ if (!foreign.has(f)) foreign.set(f, [])
103
+ if (!foreign.get(f).includes(owner)) foreign.get(f).push(owner)
104
+ }
105
+ const specBase = join(cwd, '.sillyspec')
106
+ try {
107
+ // ① 其他 quick 会话的 --files 显式声明(guard.json)
108
+ const sessionsDir = join(specBase, '.runtime', 'quick-sessions')
109
+ let sessionDirs = []
110
+ try { sessionDirs = readdirSync(sessionsDir, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name) } catch {}
111
+ for (const sid of sessionDirs) {
112
+ if (sid === currentChangeName) continue
113
+ try {
114
+ const guard = JSON.parse(readFileSync(join(sessionsDir, sid, 'guard.json'), 'utf8'))
115
+ for (const f of Array.isArray(guard.allowedFiles) ? guard.allowedFiles : []) add(f, sid)
116
+ } catch { /* 损坏/缺失跳过 */ }
117
+ }
118
+ // ② 其他变更的 design §6 清单(目录在即视为在途变更;archive/ 下不算)
119
+ const changesDir = join(specBase, 'changes')
120
+ let changeDirs = []
121
+ try { changeDirs = readdirSync(changesDir, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name) } catch {}
122
+ for (const cn of changeDirs) {
123
+ if (cn === currentChangeName || cn === 'archive') continue
124
+ const designPath = join(changesDir, cn, 'design.md')
125
+ if (!existsSync(designPath)) continue
126
+ try {
127
+ for (const e of parseFileChangeListDetailed(designPath)) add(e.path, cn)
128
+ } catch { /* 清单解析失败跳过该变更 */ }
129
+ }
130
+ } catch { /* 整体异常 → 空集(等价不过滤,回到原行为) */ }
131
+ // 活性收敛(坑 foreign-declared-stale-noise):已 apply+commit 的他者声明不再产生排除噪音
132
+ try { filterStaleForeignDeclarations(foreign, cwd, specBase) } catch { /* 收敛失败 → 原样保留(fail-closed) */ }
133
+ return foreign
134
+ }
135
+
136
+ /**
137
+ * 按他者声明集切分 diff 文件(collectForeignDeclaredFiles 的消费端快捷封装)。
138
+ * @param {string} cwd 项目根
139
+ * @param {string|null} currentChangeName 本变更名
140
+ * @param {string[]|null} diffFiles 待切分文件列表(null 透传,保持调用方 null 语义)
141
+ * @returns {{ own: string[]|null, foreign: Array<{file: string, owners: string[]}> }}
142
+ */
143
+ export function splitOwnVsForeignDiffFiles(cwd, currentChangeName, diffFiles) {
144
+ if (!Array.isArray(diffFiles)) return { own: diffFiles, foreign: [] }
145
+ const foreignMap = collectForeignDeclaredFiles(cwd, currentChangeName)
146
+ if (foreignMap.size === 0) return { own: diffFiles, foreign: [] }
147
+ const own = []
148
+ const foreign = []
149
+ for (const f of diffFiles) {
150
+ const owners = foreignMap.get(String(f).replace(/\\/g, '/'))
151
+ if (owners) foreign.push({ file: f, owners })
152
+ else own.push(f)
153
+ }
154
+ return { own, foreign }
155
+ }
package/src/index.js CHANGED
@@ -100,6 +100,7 @@ SillySpec CLI — 规范驱动开发工具包
100
100
  sillyspec module-impact --change <name> 生成 module-impact.md 骨架(文件×模块归属按 module-map 预填 + 未匹配清单)
101
101
  sillyspec endpoints extract --change <name> [--task task-NN] [--dir <dir>|--files <a.py,b.js>] 静态扫描路由装饰器生成 endpoints.json
102
102
  sillyspec scan-fix-headers [--project <名>] scan 文档补 author/created_at header(幂等)
103
+ sillyspec plan-adopt-waves --change <名> [--dry-run] plan.md Wave 段一键重排为 depends_on 拓扑分组(同步任务总表 W 列,幂等)
103
104
  sillyspec workspace add <名> <路径> [--role] [--repo] | remove <名> | status 多项目工作区登记与状态探测
104
105
  sillyspec scan-fix-leak --spec-dir <specRoot> source_root 误写产物搬到平台 specRoot(污染一键修复)
105
106
  sillyspec run quick --cancel --change <会话ID> [--ql <ql-id>] 取消误启动的 quick 会话(QUICKLOG 翻已取消 + 挂载行移除)
@@ -778,15 +779,22 @@ async function main() {
778
779
  process.exit(2);
779
780
  }
780
781
  assertSafeChangeName(vpChange, '--change 变更名');
781
- const { runVerifyProbes, renderVerifyProbesReport, generateVerifyResultSkeleton } = await import('./verify-probes.js');
782
- const vpResult = runVerifyProbes({ cwd: dir, changeName: vpChange, specDir });
782
+ const { runVerifyProbes, renderVerifyProbesReport, generateVerifyResultSkeleton, resolveVerifyProbesSpecBase } = await import('./verify-probes.js');
783
+ // spec 根统一走漂移锚定(坑 worktree-spec-artifact-misplace):在 worktree 内跑时锚回主仓,
784
+ // 探针读取与 --init 骨架都落主仓——与 plan/execute/verify/archive 的 command.js 守卫同口径。
785
+ // resolvePlatformSpecDir 仍先调(保留平台接管 fail-closed 检查副作用),但仅 pointer 存在时
786
+ // 才把它的返回值当平台根——无 pointer 时它回退 resolveSpecDir(cwd),会返回 worktree 副本
787
+ // 根,当作 platformBase 传入会让锚定被跳过(骨架落回副本)。
788
+ const vpResolved = resolvePlatformSpecDir(dir, specDir);
789
+ const vpPlatformBase = existsSync(join(dir, '.sillyspec-platform.json')) ? vpResolved : null;
790
+ const vpSpecBase = resolveVerifyProbesSpecBase(dir, specDir, vpPlatformBase);
791
+ const vpResult = runVerifyProbes({ cwd: dir, changeName: vpChange, specDir: vpSpecBase });
783
792
  if (json) {
784
793
  console.log(JSON.stringify({ command: 'verify-probes', change: vpChange, ...vpResult }, null, 2));
785
794
  break;
786
795
  }
787
796
  console.log(renderVerifyProbesReport(vpResult));
788
797
  if (vpInit) {
789
- const vpSpecBase = resolvePlatformSpecDir(dir, specDir) || join(dir, '.sillyspec');
790
798
  const vpReportPath = join(vpSpecBase, 'changes', vpChange, 'verify-result.md');
791
799
  if (existsSync(vpReportPath)) {
792
800
  console.log(`\nℹ️ verify-result.md 已存在,不覆盖: ${vpReportPath}`);
@@ -797,6 +805,52 @@ async function main() {
797
805
  }
798
806
  break;
799
807
  }
808
+ case 'plan-adopt-waves': {
809
+ // plan.md Wave 段一键重排(坑 wave-manual-mismatch-noise,2026-08-24 用户反馈二期):
810
+ // 手排 Wave 与拓扑比对不一致需手改;依赖方向硬拦(plan-postcheck)落地后给一条零手写出路。
811
+ // depMap 与 postcheck 同源(collectTaskDepMap)→ topoSortWaves → 重写 Wave 段 + 同步任务总表 W 列。
812
+ const pawChangeIdx = args.indexOf('--change');
813
+ const pawChange = pawChangeIdx >= 0 && args[pawChangeIdx + 1] ? args[pawChangeIdx + 1] : null;
814
+ const pawDryRun = args.includes('--dry-run');
815
+ if (!pawChange) {
816
+ console.error('用法: sillyspec plan-adopt-waves --change <name> [--dry-run] [--json] [--spec-dir <path>]\n 把 plan.md 的 Wave 段一键重排为 depends_on 拓扑分组(同步任务总表 W 列;--dry-run 只看不写)');
817
+ process.exit(2);
818
+ }
819
+ assertSafeChangeName(pawChange, '--change 变更名');
820
+ const { adoptPlanWaves } = await import('./plan-adopt-waves.js');
821
+ const pawSpecBase = resolvePlatformSpecDir(dir, specDir) || join(dir, '.sillyspec');
822
+ const pawResult = adoptPlanWaves({ changeDir: join(pawSpecBase, 'changes', pawChange), dryRun: pawDryRun });
823
+ if (json) {
824
+ console.log(JSON.stringify({ command: 'plan-adopt-waves', change: pawChange, ...pawResult }, null, 2));
825
+ break;
826
+ }
827
+ if (!pawResult.ok) {
828
+ console.error(`❌ ${pawResult.error}`);
829
+ process.exit(1);
830
+ }
831
+ console.log('📊 拓扑分组(depends_on):');
832
+ pawResult.waves.forEach((wave, i) => {
833
+ console.log(` Wave ${i + 1}: ${wave.join(', ')}`);
834
+ });
835
+ if (pawDryRun) {
836
+ console.log(`\n👁️ dry-run——将写入 ${pawResult.planPath} 的 Wave 段预览:`);
837
+ for (const l of pawResult.waveBlock) console.log(` ${l}`);
838
+ } else {
839
+ console.log(`\n✅ plan.md Wave 段已重排: ${pawResult.planPath}(任务总表 W 列更新 ${pawResult.tableRowsUpdated} 行${pawResult.tableRowsSkipped > 0 ? `,${pawResult.tableRowsSkipped} 行非模板格式未改` : ''};行尾统一 LF)`);
840
+ }
841
+ if (pawResult.postcheck) {
842
+ const pc = pawResult.postcheck;
843
+ if ((pc.errors || []).length > 0) {
844
+ console.warn(`⚠️ 重排后 blueprint 一致性问题(topo 只看依赖不看文件重叠——同 Wave 共享路径需手动拆分或补 depends_on):`);
845
+ for (const e of pc.errors.slice(0, 10)) console.warn(` ${e}`);
846
+ if (pc.errors.length > 10) console.warn(` …等共 ${pc.errors.length} 条`);
847
+ } else {
848
+ console.log('✅ 重排后 blueprint 一致性校验通过(无同 Wave 共享路径冲突)');
849
+ }
850
+ for (const w of (pc.warnings || []).slice(0, 5)) console.warn(`⚠️ ${w}`);
851
+ }
852
+ break;
853
+ }
800
854
  case 'module-impact': {
801
855
  // archive 模块影响矩阵骨架(2026-08-21 审计第三批 D3):文件×模块归属按 _module-map.yaml
802
856
  // paths 前缀匹配预填(机械),影响类型/review 标记留 <!--TODO-->(语义)。已存在不覆盖。
@@ -1499,8 +1553,8 @@ async function main() {
1499
1553
  SillySpec worktree — git worktree 隔离管理
1500
1554
 
1501
1555
  用法:
1502
- sillyspec worktree create <change-name> [--base <branch>] 创建隔离 worktree
1503
- sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge] 校验并应用变更到主工作区
1556
+ sillyspec worktree create <change-name> [--base <branch>] [--adopt-branch] 创建隔离 worktree(--adopt-branch:收编既有同名分支为工作分支,分支现状作 baseline)
1557
+ sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge] [--skip-overlap] [--stash-dirty] 校验并应用变更到主工作区(--stash-dirty:主仓在途改动自动 stash→apply→恢复,SHA 兜底可审计)
1504
1558
  sillyspec worktree assess <change-name> 风险审计 + 自动 apply
1505
1559
  sillyspec worktree diff <change-name> [--base <commit>] 查看 worktree 相对 base 的变更
1506
1560
  sillyspec worktree list 列出所有活跃 worktree
@@ -1518,7 +1572,7 @@ SillySpec worktree — git worktree 隔离管理
1518
1572
  switch (wtSubCmd) {
1519
1573
  case 'create': {
1520
1574
  if (!wtName) {
1521
- console.error('❌ 用法: sillyspec worktree create <change-name> [--base <branch>]');
1575
+ console.error('❌ 用法: sillyspec worktree create <change-name> [--base <branch>] [--adopt-branch]');
1522
1576
  process.exit(1);
1523
1577
  }
1524
1578
  // F6 路径穿越消毒:worktree 名用于分支名 + worktree 目录,含 ../ 会逃出 .sillyspec/worktrees/。
@@ -1526,8 +1580,9 @@ SillySpec worktree — git worktree 隔离管理
1526
1580
  catch (e) { console.error(`❌ ${e.message}`); process.exit(2); }
1527
1581
  const baseIdx = args.indexOf('--base');
1528
1582
  const base = baseIdx >= 0 && args[baseIdx + 1] ? args[baseIdx + 1] : undefined;
1583
+ const adoptBranch = args.includes('--adopt-branch'); // 收编既有同名分支为工作分支(坑 worktree-user-branch-conflict)
1529
1584
  try {
1530
- const info = wm.create(wtName, { base });
1585
+ const info = wm.create(wtName, { base, adoptBranch });
1531
1586
  console.log(`✅ worktree 已创建`);
1532
1587
  console.log(` 分支: ${info.branch}`);
1533
1588
  console.log(` 路径: ${info.worktreePath}`);
@@ -1547,11 +1602,13 @@ SillySpec worktree — git worktree 隔离管理
1547
1602
  }
1548
1603
  case 'apply': {
1549
1604
  if (!wtName) {
1550
- console.error('❌ 用法: sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge]');
1605
+ console.error('❌ 用法: sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge] [--skip-overlap] [--stash-dirty]');
1551
1606
  process.exit(1);
1552
1607
  }
1553
1608
  const checkOnly = args.includes('--check-only');
1554
1609
  const merge = args.includes('--merge');
1610
+ const skipOverlap = args.includes('--skip-overlap');
1611
+ const stashDirty = args.includes('--stash-dirty');
1555
1612
 
1556
1613
  // 解析 --base 参数(默认 merge-base)
1557
1614
  let base = 'merge-base';
@@ -1565,7 +1622,7 @@ SillySpec worktree — git worktree 隔离管理
1565
1622
  base = baseVal;
1566
1623
  }
1567
1624
 
1568
- const { applyWorktree } = await import('./worktree-apply.js');
1625
+ const { applyWorktree, withMainRepoLock } = await import('./worktree-apply.js');
1569
1626
  // W3 task-09:apply 链路构造 ctx(D-013),让 task-05 applyWorktree 按 ctx 区分主仓 A5 / 跨仓 no-op。
1570
1627
  // 跨仓 apply=no-op(G1 D-009):校验 review.head 是跨仓真实 commit + 跳过 wm.cleanup。
1571
1628
  // ctx 构造 fail-closed(约束②)——跨仓配置错时 apply 必须阻断(走错仓=数据所有权事故),不降级。
@@ -1577,7 +1634,17 @@ SillySpec worktree — git worktree 隔离管理
1577
1634
  console.error(`❌ apply 失败:跨仓 MultiRepoContext 构造失败(${e.message})`);
1578
1635
  process.exit(1);
1579
1636
  }
1580
- const result = applyWorktree(wtName, { cwd: dir, checkOnly, merge, base, ctx: _applyCtx });
1637
+ // 主仓 apply 互斥锁(坑 main-apply-no-mutex):真 apply(非 checkOnly)在锁内跑——
1638
+ // apply 链(rollback/merge/cleanup)直接改主仓工作区,两会话并发互踩会互相清文件。
1639
+ let result;
1640
+ try {
1641
+ result = checkOnly
1642
+ ? applyWorktree(wtName, { cwd: dir, checkOnly, merge, base, ctx: _applyCtx, skipOverlap, stashDirty })
1643
+ : await withMainRepoLock(dir, wtName, 'apply', () => applyWorktree(wtName, { cwd: dir, checkOnly, merge, base, ctx: _applyCtx, skipOverlap, stashDirty }));
1644
+ } catch (lockErr) {
1645
+ console.error(`❌ ${lockErr.message}`);
1646
+ process.exit(1);
1647
+ }
1581
1648
 
1582
1649
  if (result.errors.length > 0) {
1583
1650
  console.error(`❌ 校验失败:`);
@@ -1685,8 +1752,15 @@ SillySpec worktree — git worktree 隔离管理
1685
1752
  console.log('');
1686
1753
  if (assessment.decision === 'SAFE' || assessment.decision === 'WARNING') {
1687
1754
  console.log('Action: auto-applying...');
1688
- const { applyWorktree } = await import('./worktree-apply.js');
1689
- const applyResult = applyWorktree(wtName, { cwd: dir, ctx: _assessCtx });
1755
+ const { applyWorktree, withMainRepoLock } = await import('./worktree-apply.js');
1756
+ // 主仓互斥锁(与手动 apply 同款):自动 apply 同样改主仓工作区,必须互斥
1757
+ let applyResult;
1758
+ try {
1759
+ applyResult = await withMainRepoLock(dir, wtName, 'assess-auto-apply', () => applyWorktree(wtName, { cwd: dir, ctx: _assessCtx }));
1760
+ } catch (lockErr) {
1761
+ console.error(`❌ 自动 apply 未执行:${lockErr.message}`);
1762
+ break;
1763
+ }
1690
1764
  if (applyResult.errors.length > 0) {
1691
1765
  console.error('❌ apply 失败:', applyResult.errors.join('; '));
1692
1766
  } else {
@@ -1785,7 +1859,10 @@ SillySpec worktree — git worktree 隔离管理
1785
1859
  }
1786
1860
  const forceFlag = args.includes('--force');
1787
1861
  try {
1788
- const result = wm.cleanup(wtName, { force: forceFlag });
1862
+ // 主仓互斥锁(坑 main-repo-no-mutex 二批):cleanup 删 worktree 注册表/分支/目录,
1863
+ // 与并行会话的 apply/cleanup 互踩会互相清——与其他写主仓操作共用一把 main-repo.lock
1864
+ const { withMainRepoLock } = await import('./worktree-apply.js');
1865
+ const result = await withMainRepoLock(dir, wtName, 'worktree-cleanup', () => wm.cleanup(wtName, { force: forceFlag }));
1789
1866
  if (result.result === 'cleaned' || result.result === 'force-cleaned') {
1790
1867
  console.log(`✅ worktree 已清理: ${wtName} (mode: ${result.mode})`);
1791
1868
  if (result.details?.length > 0) {
@@ -1798,6 +1875,11 @@ SillySpec worktree — git worktree 隔离管理
1798
1875
  console.log(` 原因: in-place 模式没有隔离目录需要清理`);
1799
1876
  } else if (result.result === 'blocked') {
1800
1877
  console.error(`🚫 拒绝清理:有未落主仓交付变更,请先 sillyspec worktree apply ${wtName} 或 --force`);
1878
+ } else if (result.result === 'partial') {
1879
+ // 坑 ghost-dir-junction-pierce:partial 残留此前落进 else 打成「未找到」,用户误以为
1880
+ // 干净、人工 rm -rf 穿透 junction——必须明示残留 + 安全清理指引
1881
+ console.warn(`⚠️ 部分清理(残留:${(result.residual || []).join('; ') || 'worktree 目录'})`);
1882
+ console.warn(` Windows 手动清理勿 rm -rf(穿透 node_modules junction 删主仓依赖):先 cmd /c rmdir "<worktree>\\node_modules" 解链再删,或 sillyspec worktree doctor --fix`);
1801
1883
  } else {
1802
1884
  console.log(`ℹ️ worktree 未找到: ${wtName}`);
1803
1885
  }
package/src/init.js CHANGED
@@ -23,6 +23,9 @@ const __dirname = dirname(__filename);
23
23
  // 详见 docs/sillyspec/runtime-cleanup-destroys-worktree-meta.md
24
24
  //
25
25
  // 策略:白名单保留权威状态,逐项删除可重建的缓存子项;未知子项默认保留(安全侧倾斜)。
26
+ // local.yaml 同样保留:gitignored 凭据文件(平台 init lease 第 5 步下发 / local detect /
27
+ // platform connect 写入,含用户手调 mcp 段),删除即永久丢失无法从 git 找回。本函数曾把它
28
+ // 当非权威残留整删,与 platformMode 跳过清理的保护语义自相矛盾,2026-08-23 起不再删。
26
29
  const RUNTIME_KEEP = new Set([
27
30
  'worktrees', // worktree 目录 + meta.json(worktree.js:17)
28
31
  'sillyspec.db', // SQLite 进度库(权威状态源,progress.js:7)
@@ -33,15 +36,14 @@ const RUNTIME_KEEP = new Set([
33
36
 
34
37
  /**
35
38
  * 清理 .sillyspec/ 下的运行时残留,保留权威状态。
36
- * 同时清理 local.yaml、codebase/(这些非权威,整删安全)。
39
+ * 同时清理 codebase/(非权威,整删安全)。local.yaml 受保护不删——
40
+ * 平台 init 下发的凭据配置,见上方策略注释。
37
41
  * @param {string} legacyDir - 源码目录的 .sillyspec/ 路径
38
42
  */
39
43
  export function cleanupRuntimeResidue(legacyDir) {
40
- // local.yaml、codebase/ 非权威,整删
41
- for (const residue of ['local.yaml', 'codebase']) {
42
- const p = join(legacyDir, residue);
43
- if (existsSync(p)) { try { rmSync(p, { recursive: true, force: true }) } catch {} }
44
- }
44
+ // codebase/ 非权威,整删;local.yaml 是凭据配置,保留
45
+ const codebasePath = join(legacyDir, 'codebase');
46
+ if (existsSync(codebasePath)) { try { rmSync(codebasePath, { recursive: true, force: true }) } catch {} }
45
47
  // .runtime/ 逐项清理,白名单保留
46
48
  const runtimeDir = join(legacyDir, '.runtime');
47
49
  if (existsSync(runtimeDir)) {
@@ -251,7 +253,7 @@ function doInstall(projectDir, tools, subprojects = [], specDir = null, options
251
253
  // 真实资产存在:拒绝整体删除,仅清理运行时残留
252
254
  console.error('❌ [sillyspec] 拒绝删除源码目录的 .sillyspec/:检测到真实资产(changes/、projects/ 或 sillyspec.db)。');
253
255
  console.error(' 该项目似乎本身就用 SillySpec 管理。如需改用外部 spec 目录,请先手动迁移/备份。');
254
- console.error(' 本次仅清理运行时残留(.runtime/ 缓存、local.yaml、codebase/),保留 worktrees 与进度状态。');
256
+ console.error(' 本次仅清理运行时残留(.runtime/ 缓存、codebase/),保留 local.yaml、worktrees 与进度状态。');
255
257
  cleanupRuntimeResidue(legacyDir);
256
258
  } else {
257
259
  // 无真实资产:确属旧版本残留,安全删除