sillyspec 3.27.5 → 3.27.7

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 (1101) hide show
  1. package/.claude/skills/sillyspec-archive/SKILL.md +87 -87
  2. package/.claude/skills/sillyspec-auto/SKILL.md +93 -93
  3. package/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -114
  4. package/.claude/skills/sillyspec-commit/SKILL.md +67 -67
  5. package/.claude/skills/sillyspec-continue/SKILL.md +47 -47
  6. package/.claude/skills/sillyspec-doctor/SKILL.md +76 -76
  7. package/.claude/skills/sillyspec-execute/SKILL.md +214 -214
  8. package/.claude/skills/sillyspec-explore/SKILL.md +102 -102
  9. package/.claude/skills/sillyspec-export/SKILL.md +57 -57
  10. package/.claude/skills/sillyspec-init/SKILL.md +177 -177
  11. package/.claude/skills/sillyspec-knowledge/SKILL.md +269 -269
  12. package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
  13. package/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  14. package/.claude/skills/sillyspec-quick/SKILL.md +116 -116
  15. package/.claude/skills/sillyspec-resume/SKILL.md +70 -70
  16. package/.claude/skills/sillyspec-scan/SKILL.md +79 -79
  17. package/.claude/skills/sillyspec-state/SKILL.md +64 -64
  18. package/.claude/skills/sillyspec-status/SKILL.md +54 -54
  19. package/.claude/skills/sillyspec-verify/SKILL.md +87 -87
  20. package/.claude/skills/sillyspec-workspace/SKILL.md +175 -175
  21. package/.claude/skills/verify-per-user/SKILL.md +6 -0
  22. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  23. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  24. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  25. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  26. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  27. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  28. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  29. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  30. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-export/SKILL.md +57 -0
  31. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-init/SKILL.md +177 -0
  32. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  33. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  34. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  35. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  36. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  37. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  38. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-state/SKILL.md +64 -0
  39. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-status/SKILL.md +54 -0
  40. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  41. package/.worktrees/2c37b1d7/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  42. package/.worktrees/2c37b1d7/.claude/skills/verify-per-user/SKILL.md +6 -0
  43. package/.worktrees/2c37b1d7/.gitattributes +2 -0
  44. package/.worktrees/2c37b1d7/.husky/pre-push +20 -0
  45. package/.worktrees/2c37b1d7/README.md +203 -0
  46. package/.worktrees/2c37b1d7/SKILL.md +91 -0
  47. package/.worktrees/2c37b1d7/architecture-analysis.md +448 -0
  48. package/.worktrees/2c37b1d7/bin/sillyspec.js +2 -0
  49. package/.worktrees/2c37b1d7/eval/README.md +86 -0
  50. package/.worktrees/2c37b1d7/eval/eval.config.json +28 -0
  51. package/.worktrees/2c37b1d7/eval/lib/adapters/cli.mjs +63 -0
  52. package/.worktrees/2c37b1d7/eval/lib/adapters/dryrun.mjs +27 -0
  53. package/.worktrees/2c37b1d7/eval/lib/config.mjs +82 -0
  54. package/.worktrees/2c37b1d7/eval/lib/db.mjs +76 -0
  55. package/.worktrees/2c37b1d7/eval/lib/report.mjs +120 -0
  56. package/.worktrees/2c37b1d7/eval/lib/runner.mjs +157 -0
  57. package/.worktrees/2c37b1d7/eval/lib/tasks.mjs +73 -0
  58. package/.worktrees/2c37b1d7/eval/lib/util.mjs +107 -0
  59. package/.worktrees/2c37b1d7/eval/lib/workdir.mjs +30 -0
  60. package/.worktrees/2c37b1d7/eval/run.mjs +83 -0
  61. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/files/package.json +6 -0
  62. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  63. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/task.json +6 -0
  64. package/.worktrees/2c37b1d7/eval/tasks/001-slugify/verify.mjs +28 -0
  65. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/package.json +6 -0
  66. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  67. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  68. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/task.json +6 -0
  69. package/.worktrees/2c37b1d7/eval/tasks/002-each-day/verify.mjs +31 -0
  70. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  71. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/files/package.json +6 -0
  72. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  73. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/task.json +6 -0
  74. package/.worktrees/2c37b1d7/eval/tasks/003-word-report/verify.mjs +38 -0
  75. package/.worktrees/2c37b1d7/logo.jpg +0 -0
  76. package/.worktrees/2c37b1d7/package-lock.json +977 -0
  77. package/.worktrees/2c37b1d7/package.json +41 -0
  78. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  79. package/.worktrees/2c37b1d7/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  80. package/.worktrees/2c37b1d7/packages/dashboard/dist/favicon.jpg +0 -0
  81. package/.worktrees/2c37b1d7/packages/dashboard/dist/index.html +16 -0
  82. package/.worktrees/2c37b1d7/packages/dashboard/dist/logo.jpg +0 -0
  83. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-dashboard.html +836 -0
  84. package/.worktrees/2c37b1d7/packages/dashboard/dist/prototype-overview.html +256 -0
  85. package/.worktrees/2c37b1d7/packages/dashboard/package.json +25 -0
  86. package/.worktrees/2c37b1d7/packages/dashboard/server/executor.js +95 -0
  87. package/.worktrees/2c37b1d7/packages/dashboard/server/index.js +679 -0
  88. package/.worktrees/2c37b1d7/packages/dashboard/server/parser.js +526 -0
  89. package/.worktrees/2c37b1d7/packages/dashboard/server/watcher.js +357 -0
  90. package/.worktrees/2c37b1d7/src/agent-session-log.js +803 -0
  91. package/.worktrees/2c37b1d7/src/change-list.js +290 -0
  92. package/.worktrees/2c37b1d7/src/change-risk-profile.js +339 -0
  93. package/.worktrees/2c37b1d7/src/check-primitives.js +65 -0
  94. package/.worktrees/2c37b1d7/src/classify-change.js +109 -0
  95. package/.worktrees/2c37b1d7/src/commit-suggest.js +202 -0
  96. package/.worktrees/2c37b1d7/src/config-cat.js +88 -0
  97. package/.worktrees/2c37b1d7/src/config-schema.js +328 -0
  98. package/.worktrees/2c37b1d7/src/constants.js +97 -0
  99. package/.worktrees/2c37b1d7/src/contract-matrix.js +533 -0
  100. package/.worktrees/2c37b1d7/src/datetime.js +20 -0
  101. package/.worktrees/2c37b1d7/src/db-engine.js +55 -0
  102. package/.worktrees/2c37b1d7/src/db.js +381 -0
  103. package/.worktrees/2c37b1d7/src/decision-distill.js +517 -0
  104. package/.worktrees/2c37b1d7/src/dispatch/backends/local-agent.js +155 -0
  105. package/.worktrees/2c37b1d7/src/dispatch/backends/sillyhub-mcp.js +245 -0
  106. package/.worktrees/2c37b1d7/src/dispatch/probe.js +246 -0
  107. package/.worktrees/2c37b1d7/src/dispatch/strategy.js +121 -0
  108. package/.worktrees/2c37b1d7/src/docs-check.js +825 -0
  109. package/.worktrees/2c37b1d7/src/docs-debt.js +393 -0
  110. package/.worktrees/2c37b1d7/src/docs-gate.js +107 -0
  111. package/.worktrees/2c37b1d7/src/doctor-diagnostics.js +1099 -0
  112. package/.worktrees/2c37b1d7/src/endpoint-extractor.js +409 -0
  113. package/.worktrees/2c37b1d7/src/foreign-declared.js +155 -0
  114. package/.worktrees/2c37b1d7/src/fs-atomic.js +73 -0
  115. package/.worktrees/2c37b1d7/src/git-helper.js +150 -0
  116. package/.worktrees/2c37b1d7/src/hooks/claude-pre-tool-use.cjs +130 -0
  117. package/.worktrees/2c37b1d7/src/hooks/worktree-guard.js +892 -0
  118. package/.worktrees/2c37b1d7/src/index.js +2854 -0
  119. package/.worktrees/2c37b1d7/src/init.js +626 -0
  120. package/.worktrees/2c37b1d7/src/knowledge-match.js +231 -0
  121. package/.worktrees/2c37b1d7/src/local-detect.js +128 -0
  122. package/.worktrees/2c37b1d7/src/local-register.js +104 -0
  123. package/.worktrees/2c37b1d7/src/machine-interface.js +543 -0
  124. package/.worktrees/2c37b1d7/src/migrate.js +127 -0
  125. package/.worktrees/2c37b1d7/src/module-impact.js +166 -0
  126. package/.worktrees/2c37b1d7/src/module-resolve.js +222 -0
  127. package/.worktrees/2c37b1d7/src/modules.js +580 -0
  128. package/.worktrees/2c37b1d7/src/plan-adopt-waves.js +126 -0
  129. package/.worktrees/2c37b1d7/src/progress/change-registry.js +336 -0
  130. package/.worktrees/2c37b1d7/src/progress/consistency-doctor.js +355 -0
  131. package/.worktrees/2c37b1d7/src/progress/shared.js +36 -0
  132. package/.worktrees/2c37b1d7/src/progress/stage-machine.js +594 -0
  133. package/.worktrees/2c37b1d7/src/progress/step-store.js +265 -0
  134. package/.worktrees/2c37b1d7/src/progress.js +1304 -0
  135. package/.worktrees/2c37b1d7/src/quick-recommend.js +115 -0
  136. package/.worktrees/2c37b1d7/src/quicklog.js +883 -0
  137. package/.worktrees/2c37b1d7/src/review-tier.js +77 -0
  138. package/.worktrees/2c37b1d7/src/run/command.js +1641 -0
  139. package/.worktrees/2c37b1d7/src/run/complete-handlers.js +1552 -0
  140. package/.worktrees/2c37b1d7/src/run/complete.js +1259 -0
  141. package/.worktrees/2c37b1d7/src/run/concurrent-detect.js +156 -0
  142. package/.worktrees/2c37b1d7/src/run/gates.js +1111 -0
  143. package/.worktrees/2c37b1d7/src/run/multi-repo-context.js +208 -0
  144. package/.worktrees/2c37b1d7/src/run/next.js +128 -0
  145. package/.worktrees/2c37b1d7/src/run/prompt.js +843 -0
  146. package/.worktrees/2c37b1d7/src/run/quick-audit.js +186 -0
  147. package/.worktrees/2c37b1d7/src/run/scan-profile.js +269 -0
  148. package/.worktrees/2c37b1d7/src/run/shared.js +1562 -0
  149. package/.worktrees/2c37b1d7/src/run/stage.js +587 -0
  150. package/.worktrees/2c37b1d7/src/run.js +23 -0
  151. package/.worktrees/2c37b1d7/src/scan-diff.js +388 -0
  152. package/.worktrees/2c37b1d7/src/scan-postcheck.js +524 -0
  153. package/.worktrees/2c37b1d7/src/scan-staleness.js +95 -0
  154. package/.worktrees/2c37b1d7/src/setup.js +414 -0
  155. package/.worktrees/2c37b1d7/src/sillyhub-mcp/client.js +597 -0
  156. package/.worktrees/2c37b1d7/src/sillyhub-mcp/config.js +62 -0
  157. package/.worktrees/2c37b1d7/src/spec-dir-typo.js +50 -0
  158. package/.worktrees/2c37b1d7/src/spec-sync.js +358 -0
  159. package/.worktrees/2c37b1d7/src/stage-contract-engine.js +171 -0
  160. package/.worktrees/2c37b1d7/src/stage-contract-spec.js +551 -0
  161. package/.worktrees/2c37b1d7/src/stage-contract.js +948 -0
  162. package/.worktrees/2c37b1d7/src/stage-review.js +597 -0
  163. package/.worktrees/2c37b1d7/src/stages/archive.js +199 -0
  164. package/.worktrees/2c37b1d7/src/stages/brainstorm-auto.js +285 -0
  165. package/.worktrees/2c37b1d7/src/stages/brainstorm.js +624 -0
  166. package/.worktrees/2c37b1d7/src/stages/cmd-existence.js +145 -0
  167. package/.worktrees/2c37b1d7/src/stages/doctor.js +540 -0
  168. package/.worktrees/2c37b1d7/src/stages/execute.js +1277 -0
  169. package/.worktrees/2c37b1d7/src/stages/explore.js +43 -0
  170. package/.worktrees/2c37b1d7/src/stages/index.js +29 -0
  171. package/.worktrees/2c37b1d7/src/stages/knowledge.js +514 -0
  172. package/.worktrees/2c37b1d7/src/stages/plan-postcheck.js +1398 -0
  173. package/.worktrees/2c37b1d7/src/stages/plan.js +655 -0
  174. package/.worktrees/2c37b1d7/src/stages/quick.js +167 -0
  175. package/.worktrees/2c37b1d7/src/stages/scan.js +608 -0
  176. package/.worktrees/2c37b1d7/src/stages/status.js +64 -0
  177. package/.worktrees/2c37b1d7/src/stages/verify.js +246 -0
  178. package/.worktrees/2c37b1d7/src/sync.js +1470 -0
  179. package/.worktrees/2c37b1d7/src/task-review.js +1498 -0
  180. package/.worktrees/2c37b1d7/src/taskcard-placeholders.js +21 -0
  181. package/.worktrees/2c37b1d7/src/taskcard.js +250 -0
  182. package/.worktrees/2c37b1d7/src/verify-postcheck.js +1718 -0
  183. package/.worktrees/2c37b1d7/src/verify-probes.js +327 -0
  184. package/.worktrees/2c37b1d7/src/version.js +19 -0
  185. package/.worktrees/2c37b1d7/src/workflow.js +600 -0
  186. package/.worktrees/2c37b1d7/src/workspace.js +125 -0
  187. package/.worktrees/2c37b1d7/src/worktree-apply.js +1611 -0
  188. package/.worktrees/2c37b1d7/src/worktree-deps.js +668 -0
  189. package/.worktrees/2c37b1d7/src/worktree.js +1849 -0
  190. package/.worktrees/2c37b1d7/templates/claude-instruction.md +23 -0
  191. package/.worktrees/2c37b1d7/templates/prompts/taskcard-rules.md +29 -0
  192. package/.worktrees/2c37b1d7/templates/prompts/testcase-design.md +12 -0
  193. package/.worktrees/2c37b1d7/templates/prompts/verify-probes.md +32 -0
  194. package/.worktrees/2c37b1d7/templates/workflows/archive-impact.yaml +79 -0
  195. package/.worktrees/2c37b1d7/templates/workflows/scan-docs.yaml +132 -0
  196. package/.worktrees/542c4415/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  197. package/.worktrees/542c4415/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  198. package/.worktrees/542c4415/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  199. package/.worktrees/542c4415/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  200. package/.worktrees/542c4415/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  201. package/.worktrees/542c4415/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  202. package/.worktrees/542c4415/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  203. package/.worktrees/542c4415/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  204. package/.worktrees/542c4415/.claude/skills/sillyspec-export/SKILL.md +57 -0
  205. package/.worktrees/542c4415/.claude/skills/sillyspec-init/SKILL.md +177 -0
  206. package/.worktrees/542c4415/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  207. package/.worktrees/542c4415/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  208. package/.worktrees/542c4415/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  209. package/.worktrees/542c4415/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  210. package/.worktrees/542c4415/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  211. package/.worktrees/542c4415/.claude/skills/sillyspec-state/SKILL.md +64 -0
  212. package/.worktrees/542c4415/.claude/skills/sillyspec-status/SKILL.md +54 -0
  213. package/.worktrees/542c4415/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  214. package/.worktrees/542c4415/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  215. package/.worktrees/542c4415/.gitattributes +2 -0
  216. package/.worktrees/542c4415/.husky/pre-push +20 -0
  217. package/.worktrees/542c4415/README.md +203 -0
  218. package/.worktrees/542c4415/SKILL.md +91 -0
  219. package/.worktrees/542c4415/architecture-analysis.md +448 -0
  220. package/.worktrees/542c4415/bin/sillyspec.js +2 -0
  221. package/.worktrees/542c4415/eval/README.md +86 -0
  222. package/.worktrees/542c4415/eval/eval.config.json +28 -0
  223. package/.worktrees/542c4415/eval/lib/adapters/cli.mjs +63 -0
  224. package/.worktrees/542c4415/eval/lib/adapters/dryrun.mjs +27 -0
  225. package/.worktrees/542c4415/eval/lib/config.mjs +82 -0
  226. package/.worktrees/542c4415/eval/lib/db.mjs +76 -0
  227. package/.worktrees/542c4415/eval/lib/report.mjs +120 -0
  228. package/.worktrees/542c4415/eval/lib/runner.mjs +157 -0
  229. package/.worktrees/542c4415/eval/lib/tasks.mjs +73 -0
  230. package/.worktrees/542c4415/eval/lib/util.mjs +107 -0
  231. package/.worktrees/542c4415/eval/lib/workdir.mjs +30 -0
  232. package/.worktrees/542c4415/eval/run.mjs +83 -0
  233. package/.worktrees/542c4415/eval/tasks/001-slugify/files/package.json +6 -0
  234. package/.worktrees/542c4415/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  235. package/.worktrees/542c4415/eval/tasks/001-slugify/task.json +6 -0
  236. package/.worktrees/542c4415/eval/tasks/001-slugify/verify.mjs +28 -0
  237. package/.worktrees/542c4415/eval/tasks/002-each-day/files/package.json +6 -0
  238. package/.worktrees/542c4415/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  239. package/.worktrees/542c4415/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  240. package/.worktrees/542c4415/eval/tasks/002-each-day/task.json +6 -0
  241. package/.worktrees/542c4415/eval/tasks/002-each-day/verify.mjs +31 -0
  242. package/.worktrees/542c4415/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  243. package/.worktrees/542c4415/eval/tasks/003-word-report/files/package.json +6 -0
  244. package/.worktrees/542c4415/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  245. package/.worktrees/542c4415/eval/tasks/003-word-report/task.json +6 -0
  246. package/.worktrees/542c4415/eval/tasks/003-word-report/verify.mjs +38 -0
  247. package/.worktrees/542c4415/logo.jpg +0 -0
  248. package/.worktrees/542c4415/package-lock.json +977 -0
  249. package/.worktrees/542c4415/package.json +41 -0
  250. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  251. package/.worktrees/542c4415/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  252. package/.worktrees/542c4415/packages/dashboard/dist/favicon.jpg +0 -0
  253. package/.worktrees/542c4415/packages/dashboard/dist/index.html +16 -0
  254. package/.worktrees/542c4415/packages/dashboard/dist/logo.jpg +0 -0
  255. package/.worktrees/542c4415/packages/dashboard/dist/prototype-dashboard.html +836 -0
  256. package/.worktrees/542c4415/packages/dashboard/dist/prototype-overview.html +256 -0
  257. package/.worktrees/542c4415/packages/dashboard/package.json +25 -0
  258. package/.worktrees/542c4415/packages/dashboard/server/executor.js +95 -0
  259. package/.worktrees/542c4415/packages/dashboard/server/index.js +679 -0
  260. package/.worktrees/542c4415/packages/dashboard/server/parser.js +526 -0
  261. package/.worktrees/542c4415/packages/dashboard/server/watcher.js +357 -0
  262. package/.worktrees/542c4415/src/agent-session-log.js +803 -0
  263. package/.worktrees/542c4415/src/change-list.js +290 -0
  264. package/.worktrees/542c4415/src/change-risk-profile.js +339 -0
  265. package/.worktrees/542c4415/src/check-primitives.js +65 -0
  266. package/.worktrees/542c4415/src/classify-change.js +109 -0
  267. package/.worktrees/542c4415/src/commit-suggest.js +202 -0
  268. package/.worktrees/542c4415/src/config-cat.js +88 -0
  269. package/.worktrees/542c4415/src/config-schema.js +328 -0
  270. package/.worktrees/542c4415/src/constants.js +97 -0
  271. package/.worktrees/542c4415/src/contract-matrix.js +533 -0
  272. package/.worktrees/542c4415/src/datetime.js +20 -0
  273. package/.worktrees/542c4415/src/db-engine.js +55 -0
  274. package/.worktrees/542c4415/src/db.js +381 -0
  275. package/.worktrees/542c4415/src/decision-distill.js +517 -0
  276. package/.worktrees/542c4415/src/dispatch/backends/local-agent.js +155 -0
  277. package/.worktrees/542c4415/src/dispatch/backends/sillyhub-mcp.js +245 -0
  278. package/.worktrees/542c4415/src/dispatch/probe.js +246 -0
  279. package/.worktrees/542c4415/src/dispatch/strategy.js +121 -0
  280. package/.worktrees/542c4415/src/docs-check.js +825 -0
  281. package/.worktrees/542c4415/src/docs-debt.js +393 -0
  282. package/.worktrees/542c4415/src/docs-gate.js +107 -0
  283. package/.worktrees/542c4415/src/doctor-diagnostics.js +1099 -0
  284. package/.worktrees/542c4415/src/endpoint-extractor.js +409 -0
  285. package/.worktrees/542c4415/src/foreign-declared.js +155 -0
  286. package/.worktrees/542c4415/src/fs-atomic.js +73 -0
  287. package/.worktrees/542c4415/src/git-helper.js +150 -0
  288. package/.worktrees/542c4415/src/hooks/claude-pre-tool-use.cjs +130 -0
  289. package/.worktrees/542c4415/src/hooks/worktree-guard.js +892 -0
  290. package/.worktrees/542c4415/src/index.js +2854 -0
  291. package/.worktrees/542c4415/src/init.js +626 -0
  292. package/.worktrees/542c4415/src/knowledge-match.js +231 -0
  293. package/.worktrees/542c4415/src/local-detect.js +128 -0
  294. package/.worktrees/542c4415/src/local-register.js +104 -0
  295. package/.worktrees/542c4415/src/machine-interface.js +543 -0
  296. package/.worktrees/542c4415/src/migrate.js +127 -0
  297. package/.worktrees/542c4415/src/module-impact.js +166 -0
  298. package/.worktrees/542c4415/src/module-resolve.js +222 -0
  299. package/.worktrees/542c4415/src/modules.js +580 -0
  300. package/.worktrees/542c4415/src/plan-adopt-waves.js +126 -0
  301. package/.worktrees/542c4415/src/progress/change-registry.js +336 -0
  302. package/.worktrees/542c4415/src/progress/consistency-doctor.js +355 -0
  303. package/.worktrees/542c4415/src/progress/shared.js +36 -0
  304. package/.worktrees/542c4415/src/progress/stage-machine.js +594 -0
  305. package/.worktrees/542c4415/src/progress/step-store.js +265 -0
  306. package/.worktrees/542c4415/src/progress.js +1304 -0
  307. package/.worktrees/542c4415/src/quick-recommend.js +115 -0
  308. package/.worktrees/542c4415/src/quicklog.js +883 -0
  309. package/.worktrees/542c4415/src/review-tier.js +77 -0
  310. package/.worktrees/542c4415/src/run/command.js +1641 -0
  311. package/.worktrees/542c4415/src/run/complete-handlers.js +1552 -0
  312. package/.worktrees/542c4415/src/run/complete.js +1259 -0
  313. package/.worktrees/542c4415/src/run/concurrent-detect.js +156 -0
  314. package/.worktrees/542c4415/src/run/gates.js +1111 -0
  315. package/.worktrees/542c4415/src/run/multi-repo-context.js +208 -0
  316. package/.worktrees/542c4415/src/run/next.js +128 -0
  317. package/.worktrees/542c4415/src/run/prompt.js +843 -0
  318. package/.worktrees/542c4415/src/run/quick-audit.js +186 -0
  319. package/.worktrees/542c4415/src/run/scan-profile.js +269 -0
  320. package/.worktrees/542c4415/src/run/shared.js +1562 -0
  321. package/.worktrees/542c4415/src/run/stage.js +587 -0
  322. package/.worktrees/542c4415/src/run.js +23 -0
  323. package/.worktrees/542c4415/src/scan-diff.js +388 -0
  324. package/.worktrees/542c4415/src/scan-postcheck.js +524 -0
  325. package/.worktrees/542c4415/src/scan-staleness.js +95 -0
  326. package/.worktrees/542c4415/src/setup.js +414 -0
  327. package/.worktrees/542c4415/src/sillyhub-mcp/client.js +597 -0
  328. package/.worktrees/542c4415/src/sillyhub-mcp/config.js +62 -0
  329. package/.worktrees/542c4415/src/spec-dir-typo.js +50 -0
  330. package/.worktrees/542c4415/src/spec-sync.js +358 -0
  331. package/.worktrees/542c4415/src/stage-contract-engine.js +171 -0
  332. package/.worktrees/542c4415/src/stage-contract-spec.js +551 -0
  333. package/.worktrees/542c4415/src/stage-contract.js +948 -0
  334. package/.worktrees/542c4415/src/stage-review.js +597 -0
  335. package/.worktrees/542c4415/src/stages/archive.js +199 -0
  336. package/.worktrees/542c4415/src/stages/brainstorm-auto.js +285 -0
  337. package/.worktrees/542c4415/src/stages/brainstorm.js +624 -0
  338. package/.worktrees/542c4415/src/stages/cmd-existence.js +145 -0
  339. package/.worktrees/542c4415/src/stages/doctor.js +540 -0
  340. package/.worktrees/542c4415/src/stages/execute.js +1277 -0
  341. package/.worktrees/542c4415/src/stages/explore.js +43 -0
  342. package/.worktrees/542c4415/src/stages/index.js +29 -0
  343. package/.worktrees/542c4415/src/stages/knowledge.js +514 -0
  344. package/.worktrees/542c4415/src/stages/plan-postcheck.js +1398 -0
  345. package/.worktrees/542c4415/src/stages/plan.js +655 -0
  346. package/.worktrees/542c4415/src/stages/quick.js +167 -0
  347. package/.worktrees/542c4415/src/stages/scan.js +608 -0
  348. package/.worktrees/542c4415/src/stages/status.js +64 -0
  349. package/.worktrees/542c4415/src/stages/verify.js +246 -0
  350. package/.worktrees/542c4415/src/sync.js +1470 -0
  351. package/.worktrees/542c4415/src/task-review.js +1498 -0
  352. package/.worktrees/542c4415/src/taskcard-placeholders.js +21 -0
  353. package/.worktrees/542c4415/src/taskcard.js +250 -0
  354. package/.worktrees/542c4415/src/verify-postcheck.js +1718 -0
  355. package/.worktrees/542c4415/src/verify-probes.js +327 -0
  356. package/.worktrees/542c4415/src/version.js +19 -0
  357. package/.worktrees/542c4415/src/workflow.js +600 -0
  358. package/.worktrees/542c4415/src/workspace.js +125 -0
  359. package/.worktrees/542c4415/src/worktree-apply.js +1611 -0
  360. package/.worktrees/542c4415/src/worktree-deps.js +668 -0
  361. package/.worktrees/542c4415/src/worktree.js +1849 -0
  362. package/.worktrees/542c4415/templates/claude-instruction.md +23 -0
  363. package/.worktrees/542c4415/templates/prompts/taskcard-rules.md +29 -0
  364. package/.worktrees/542c4415/templates/prompts/testcase-design.md +12 -0
  365. package/.worktrees/542c4415/templates/prompts/verify-probes.md +32 -0
  366. package/.worktrees/542c4415/templates/workflows/archive-impact.yaml +79 -0
  367. package/.worktrees/542c4415/templates/workflows/scan-docs.yaml +132 -0
  368. package/.worktrees/8d2d0392/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  369. package/.worktrees/8d2d0392/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  370. package/.worktrees/8d2d0392/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  371. package/.worktrees/8d2d0392/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  372. package/.worktrees/8d2d0392/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  373. package/.worktrees/8d2d0392/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  374. package/.worktrees/8d2d0392/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  375. package/.worktrees/8d2d0392/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  376. package/.worktrees/8d2d0392/.claude/skills/sillyspec-export/SKILL.md +57 -0
  377. package/.worktrees/8d2d0392/.claude/skills/sillyspec-init/SKILL.md +177 -0
  378. package/.worktrees/8d2d0392/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  379. package/.worktrees/8d2d0392/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  380. package/.worktrees/8d2d0392/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  381. package/.worktrees/8d2d0392/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  382. package/.worktrees/8d2d0392/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  383. package/.worktrees/8d2d0392/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  384. package/.worktrees/8d2d0392/.claude/skills/sillyspec-state/SKILL.md +64 -0
  385. package/.worktrees/8d2d0392/.claude/skills/sillyspec-status/SKILL.md +54 -0
  386. package/.worktrees/8d2d0392/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  387. package/.worktrees/8d2d0392/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  388. package/.worktrees/8d2d0392/.claude/skills/verify-per-user/SKILL.md +6 -0
  389. package/.worktrees/8d2d0392/.gitattributes +2 -0
  390. package/.worktrees/8d2d0392/.husky/pre-push +20 -0
  391. package/.worktrees/8d2d0392/README.md +203 -0
  392. package/.worktrees/8d2d0392/SKILL.md +91 -0
  393. package/.worktrees/8d2d0392/architecture-analysis.md +448 -0
  394. package/.worktrees/8d2d0392/bin/sillyspec.js +2 -0
  395. package/.worktrees/8d2d0392/eval/README.md +86 -0
  396. package/.worktrees/8d2d0392/eval/eval.config.json +28 -0
  397. package/.worktrees/8d2d0392/eval/lib/adapters/cli.mjs +63 -0
  398. package/.worktrees/8d2d0392/eval/lib/adapters/dryrun.mjs +27 -0
  399. package/.worktrees/8d2d0392/eval/lib/config.mjs +82 -0
  400. package/.worktrees/8d2d0392/eval/lib/db.mjs +76 -0
  401. package/.worktrees/8d2d0392/eval/lib/report.mjs +120 -0
  402. package/.worktrees/8d2d0392/eval/lib/runner.mjs +157 -0
  403. package/.worktrees/8d2d0392/eval/lib/tasks.mjs +73 -0
  404. package/.worktrees/8d2d0392/eval/lib/util.mjs +107 -0
  405. package/.worktrees/8d2d0392/eval/lib/workdir.mjs +30 -0
  406. package/.worktrees/8d2d0392/eval/run.mjs +83 -0
  407. package/.worktrees/8d2d0392/eval/tasks/001-slugify/files/package.json +6 -0
  408. package/.worktrees/8d2d0392/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  409. package/.worktrees/8d2d0392/eval/tasks/001-slugify/task.json +6 -0
  410. package/.worktrees/8d2d0392/eval/tasks/001-slugify/verify.mjs +28 -0
  411. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/package.json +6 -0
  412. package/.worktrees/8d2d0392/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  413. package/.worktrees/8d2d0392/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  414. package/.worktrees/8d2d0392/eval/tasks/002-each-day/task.json +6 -0
  415. package/.worktrees/8d2d0392/eval/tasks/002-each-day/verify.mjs +31 -0
  416. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  417. package/.worktrees/8d2d0392/eval/tasks/003-word-report/files/package.json +6 -0
  418. package/.worktrees/8d2d0392/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  419. package/.worktrees/8d2d0392/eval/tasks/003-word-report/task.json +6 -0
  420. package/.worktrees/8d2d0392/eval/tasks/003-word-report/verify.mjs +38 -0
  421. package/.worktrees/8d2d0392/logo.jpg +0 -0
  422. package/.worktrees/8d2d0392/package-lock.json +977 -0
  423. package/.worktrees/8d2d0392/package.json +41 -0
  424. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  425. package/.worktrees/8d2d0392/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  426. package/.worktrees/8d2d0392/packages/dashboard/dist/favicon.jpg +0 -0
  427. package/.worktrees/8d2d0392/packages/dashboard/dist/index.html +16 -0
  428. package/.worktrees/8d2d0392/packages/dashboard/dist/logo.jpg +0 -0
  429. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-dashboard.html +836 -0
  430. package/.worktrees/8d2d0392/packages/dashboard/dist/prototype-overview.html +256 -0
  431. package/.worktrees/8d2d0392/packages/dashboard/package.json +25 -0
  432. package/.worktrees/8d2d0392/packages/dashboard/server/executor.js +95 -0
  433. package/.worktrees/8d2d0392/packages/dashboard/server/index.js +679 -0
  434. package/.worktrees/8d2d0392/packages/dashboard/server/parser.js +526 -0
  435. package/.worktrees/8d2d0392/packages/dashboard/server/watcher.js +357 -0
  436. package/.worktrees/8d2d0392/src/agent-session-log.js +803 -0
  437. package/.worktrees/8d2d0392/src/change-list.js +290 -0
  438. package/.worktrees/8d2d0392/src/change-risk-profile.js +339 -0
  439. package/.worktrees/8d2d0392/src/check-primitives.js +65 -0
  440. package/.worktrees/8d2d0392/src/classify-change.js +109 -0
  441. package/.worktrees/8d2d0392/src/commit-suggest.js +202 -0
  442. package/.worktrees/8d2d0392/src/config-cat.js +88 -0
  443. package/.worktrees/8d2d0392/src/config-schema.js +328 -0
  444. package/.worktrees/8d2d0392/src/constants.js +97 -0
  445. package/.worktrees/8d2d0392/src/contract-matrix.js +533 -0
  446. package/.worktrees/8d2d0392/src/datetime.js +20 -0
  447. package/.worktrees/8d2d0392/src/db-engine.js +55 -0
  448. package/.worktrees/8d2d0392/src/db.js +381 -0
  449. package/.worktrees/8d2d0392/src/decision-distill.js +517 -0
  450. package/.worktrees/8d2d0392/src/dispatch/backends/local-agent.js +155 -0
  451. package/.worktrees/8d2d0392/src/dispatch/backends/sillyhub-mcp.js +245 -0
  452. package/.worktrees/8d2d0392/src/dispatch/probe.js +246 -0
  453. package/.worktrees/8d2d0392/src/dispatch/strategy.js +121 -0
  454. package/.worktrees/8d2d0392/src/docs-check.js +825 -0
  455. package/.worktrees/8d2d0392/src/docs-debt.js +393 -0
  456. package/.worktrees/8d2d0392/src/docs-gate.js +107 -0
  457. package/.worktrees/8d2d0392/src/doctor-diagnostics.js +1099 -0
  458. package/.worktrees/8d2d0392/src/endpoint-extractor.js +409 -0
  459. package/.worktrees/8d2d0392/src/foreign-declared.js +78 -0
  460. package/.worktrees/8d2d0392/src/fs-atomic.js +73 -0
  461. package/.worktrees/8d2d0392/src/git-helper.js +150 -0
  462. package/.worktrees/8d2d0392/src/hooks/claude-pre-tool-use.cjs +130 -0
  463. package/.worktrees/8d2d0392/src/hooks/worktree-guard.js +892 -0
  464. package/.worktrees/8d2d0392/src/index.js +2854 -0
  465. package/.worktrees/8d2d0392/src/init.js +626 -0
  466. package/.worktrees/8d2d0392/src/knowledge-match.js +231 -0
  467. package/.worktrees/8d2d0392/src/local-detect.js +128 -0
  468. package/.worktrees/8d2d0392/src/local-register.js +104 -0
  469. package/.worktrees/8d2d0392/src/machine-interface.js +543 -0
  470. package/.worktrees/8d2d0392/src/migrate.js +127 -0
  471. package/.worktrees/8d2d0392/src/module-impact.js +166 -0
  472. package/.worktrees/8d2d0392/src/module-resolve.js +222 -0
  473. package/.worktrees/8d2d0392/src/modules.js +580 -0
  474. package/.worktrees/8d2d0392/src/plan-adopt-waves.js +126 -0
  475. package/.worktrees/8d2d0392/src/progress/change-registry.js +336 -0
  476. package/.worktrees/8d2d0392/src/progress/consistency-doctor.js +355 -0
  477. package/.worktrees/8d2d0392/src/progress/shared.js +36 -0
  478. package/.worktrees/8d2d0392/src/progress/stage-machine.js +594 -0
  479. package/.worktrees/8d2d0392/src/progress/step-store.js +265 -0
  480. package/.worktrees/8d2d0392/src/progress.js +1304 -0
  481. package/.worktrees/8d2d0392/src/quick-recommend.js +115 -0
  482. package/.worktrees/8d2d0392/src/quicklog.js +883 -0
  483. package/.worktrees/8d2d0392/src/review-tier.js +77 -0
  484. package/.worktrees/8d2d0392/src/run/command.js +1641 -0
  485. package/.worktrees/8d2d0392/src/run/complete-handlers.js +1552 -0
  486. package/.worktrees/8d2d0392/src/run/complete.js +1259 -0
  487. package/.worktrees/8d2d0392/src/run/concurrent-detect.js +156 -0
  488. package/.worktrees/8d2d0392/src/run/gates.js +1094 -0
  489. package/.worktrees/8d2d0392/src/run/multi-repo-context.js +208 -0
  490. package/.worktrees/8d2d0392/src/run/next.js +128 -0
  491. package/.worktrees/8d2d0392/src/run/prompt.js +843 -0
  492. package/.worktrees/8d2d0392/src/run/quick-audit.js +186 -0
  493. package/.worktrees/8d2d0392/src/run/scan-profile.js +269 -0
  494. package/.worktrees/8d2d0392/src/run/shared.js +1562 -0
  495. package/.worktrees/8d2d0392/src/run/stage.js +587 -0
  496. package/.worktrees/8d2d0392/src/run.js +23 -0
  497. package/.worktrees/8d2d0392/src/scan-diff.js +388 -0
  498. package/.worktrees/8d2d0392/src/scan-postcheck.js +524 -0
  499. package/.worktrees/8d2d0392/src/scan-staleness.js +95 -0
  500. package/.worktrees/8d2d0392/src/setup.js +414 -0
  501. package/.worktrees/8d2d0392/src/sillyhub-mcp/client.js +597 -0
  502. package/.worktrees/8d2d0392/src/sillyhub-mcp/config.js +62 -0
  503. package/.worktrees/8d2d0392/src/spec-dir-typo.js +50 -0
  504. package/.worktrees/8d2d0392/src/spec-sync.js +358 -0
  505. package/.worktrees/8d2d0392/src/stage-contract-engine.js +171 -0
  506. package/.worktrees/8d2d0392/src/stage-contract-spec.js +551 -0
  507. package/.worktrees/8d2d0392/src/stage-contract.js +948 -0
  508. package/.worktrees/8d2d0392/src/stage-review.js +597 -0
  509. package/.worktrees/8d2d0392/src/stages/archive.js +199 -0
  510. package/.worktrees/8d2d0392/src/stages/brainstorm-auto.js +285 -0
  511. package/.worktrees/8d2d0392/src/stages/brainstorm.js +624 -0
  512. package/.worktrees/8d2d0392/src/stages/cmd-existence.js +145 -0
  513. package/.worktrees/8d2d0392/src/stages/doctor.js +540 -0
  514. package/.worktrees/8d2d0392/src/stages/execute.js +1277 -0
  515. package/.worktrees/8d2d0392/src/stages/explore.js +43 -0
  516. package/.worktrees/8d2d0392/src/stages/index.js +29 -0
  517. package/.worktrees/8d2d0392/src/stages/knowledge.js +514 -0
  518. package/.worktrees/8d2d0392/src/stages/plan-postcheck.js +1398 -0
  519. package/.worktrees/8d2d0392/src/stages/plan.js +651 -0
  520. package/.worktrees/8d2d0392/src/stages/quick.js +167 -0
  521. package/.worktrees/8d2d0392/src/stages/scan.js +608 -0
  522. package/.worktrees/8d2d0392/src/stages/status.js +64 -0
  523. package/.worktrees/8d2d0392/src/stages/verify.js +246 -0
  524. package/.worktrees/8d2d0392/src/sync.js +1470 -0
  525. package/.worktrees/8d2d0392/src/task-review.js +1498 -0
  526. package/.worktrees/8d2d0392/src/taskcard-placeholders.js +21 -0
  527. package/.worktrees/8d2d0392/src/taskcard.js +217 -0
  528. package/.worktrees/8d2d0392/src/verify-postcheck.js +1718 -0
  529. package/.worktrees/8d2d0392/src/verify-probes.js +327 -0
  530. package/.worktrees/8d2d0392/src/version.js +19 -0
  531. package/.worktrees/8d2d0392/src/workflow.js +600 -0
  532. package/.worktrees/8d2d0392/src/workspace.js +125 -0
  533. package/.worktrees/8d2d0392/src/worktree-apply.js +1611 -0
  534. package/.worktrees/8d2d0392/src/worktree-deps.js +576 -0
  535. package/.worktrees/8d2d0392/src/worktree.js +1838 -0
  536. package/.worktrees/8d2d0392/templates/claude-instruction.md +23 -0
  537. package/.worktrees/8d2d0392/templates/prompts/taskcard-rules.md +29 -0
  538. package/.worktrees/8d2d0392/templates/prompts/testcase-design.md +12 -0
  539. package/.worktrees/8d2d0392/templates/prompts/verify-probes.md +32 -0
  540. package/.worktrees/8d2d0392/templates/workflows/archive-impact.yaml +79 -0
  541. package/.worktrees/8d2d0392/templates/workflows/scan-docs.yaml +132 -0
  542. package/.worktrees/c1eae35e/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  543. package/.worktrees/c1eae35e/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  544. package/.worktrees/c1eae35e/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  545. package/.worktrees/c1eae35e/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  546. package/.worktrees/c1eae35e/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  547. package/.worktrees/c1eae35e/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  548. package/.worktrees/c1eae35e/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  549. package/.worktrees/c1eae35e/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  550. package/.worktrees/c1eae35e/.claude/skills/sillyspec-export/SKILL.md +57 -0
  551. package/.worktrees/c1eae35e/.claude/skills/sillyspec-init/SKILL.md +177 -0
  552. package/.worktrees/c1eae35e/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  553. package/.worktrees/c1eae35e/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  554. package/.worktrees/c1eae35e/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  555. package/.worktrees/c1eae35e/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  556. package/.worktrees/c1eae35e/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  557. package/.worktrees/c1eae35e/.claude/skills/sillyspec-state/SKILL.md +64 -0
  558. package/.worktrees/c1eae35e/.claude/skills/sillyspec-status/SKILL.md +54 -0
  559. package/.worktrees/c1eae35e/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  560. package/.worktrees/c1eae35e/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  561. package/.worktrees/c1eae35e/.gitattributes +2 -0
  562. package/.worktrees/c1eae35e/.husky/pre-push +20 -0
  563. package/.worktrees/c1eae35e/README.md +203 -0
  564. package/.worktrees/c1eae35e/SKILL.md +91 -0
  565. package/.worktrees/c1eae35e/architecture-analysis.md +448 -0
  566. package/.worktrees/c1eae35e/bin/sillyspec.js +2 -0
  567. package/.worktrees/c1eae35e/eval/README.md +86 -0
  568. package/.worktrees/c1eae35e/eval/eval.config.json +28 -0
  569. package/.worktrees/c1eae35e/eval/lib/adapters/cli.mjs +63 -0
  570. package/.worktrees/c1eae35e/eval/lib/adapters/dryrun.mjs +27 -0
  571. package/.worktrees/c1eae35e/eval/lib/config.mjs +82 -0
  572. package/.worktrees/c1eae35e/eval/lib/db.mjs +76 -0
  573. package/.worktrees/c1eae35e/eval/lib/report.mjs +120 -0
  574. package/.worktrees/c1eae35e/eval/lib/runner.mjs +157 -0
  575. package/.worktrees/c1eae35e/eval/lib/tasks.mjs +73 -0
  576. package/.worktrees/c1eae35e/eval/lib/util.mjs +107 -0
  577. package/.worktrees/c1eae35e/eval/lib/workdir.mjs +30 -0
  578. package/.worktrees/c1eae35e/eval/run.mjs +83 -0
  579. package/.worktrees/c1eae35e/eval/tasks/001-slugify/files/package.json +6 -0
  580. package/.worktrees/c1eae35e/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  581. package/.worktrees/c1eae35e/eval/tasks/001-slugify/task.json +6 -0
  582. package/.worktrees/c1eae35e/eval/tasks/001-slugify/verify.mjs +28 -0
  583. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/package.json +6 -0
  584. package/.worktrees/c1eae35e/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  585. package/.worktrees/c1eae35e/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  586. package/.worktrees/c1eae35e/eval/tasks/002-each-day/task.json +6 -0
  587. package/.worktrees/c1eae35e/eval/tasks/002-each-day/verify.mjs +31 -0
  588. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  589. package/.worktrees/c1eae35e/eval/tasks/003-word-report/files/package.json +6 -0
  590. package/.worktrees/c1eae35e/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  591. package/.worktrees/c1eae35e/eval/tasks/003-word-report/task.json +6 -0
  592. package/.worktrees/c1eae35e/eval/tasks/003-word-report/verify.mjs +38 -0
  593. package/.worktrees/c1eae35e/logo.jpg +0 -0
  594. package/.worktrees/c1eae35e/package-lock.json +977 -0
  595. package/.worktrees/c1eae35e/package.json +41 -0
  596. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  597. package/.worktrees/c1eae35e/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  598. package/.worktrees/c1eae35e/packages/dashboard/dist/favicon.jpg +0 -0
  599. package/.worktrees/c1eae35e/packages/dashboard/dist/index.html +16 -0
  600. package/.worktrees/c1eae35e/packages/dashboard/dist/logo.jpg +0 -0
  601. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-dashboard.html +836 -0
  602. package/.worktrees/c1eae35e/packages/dashboard/dist/prototype-overview.html +256 -0
  603. package/.worktrees/c1eae35e/packages/dashboard/package.json +25 -0
  604. package/.worktrees/c1eae35e/packages/dashboard/server/executor.js +95 -0
  605. package/.worktrees/c1eae35e/packages/dashboard/server/index.js +679 -0
  606. package/.worktrees/c1eae35e/packages/dashboard/server/parser.js +526 -0
  607. package/.worktrees/c1eae35e/packages/dashboard/server/watcher.js +357 -0
  608. package/.worktrees/c1eae35e/src/agent-session-log.js +803 -0
  609. package/.worktrees/c1eae35e/src/change-list.js +290 -0
  610. package/.worktrees/c1eae35e/src/change-risk-profile.js +339 -0
  611. package/.worktrees/c1eae35e/src/check-primitives.js +65 -0
  612. package/.worktrees/c1eae35e/src/classify-change.js +109 -0
  613. package/.worktrees/c1eae35e/src/commit-suggest.js +202 -0
  614. package/.worktrees/c1eae35e/src/config-cat.js +88 -0
  615. package/.worktrees/c1eae35e/src/config-schema.js +328 -0
  616. package/.worktrees/c1eae35e/src/constants.js +97 -0
  617. package/.worktrees/c1eae35e/src/contract-matrix.js +533 -0
  618. package/.worktrees/c1eae35e/src/datetime.js +20 -0
  619. package/.worktrees/c1eae35e/src/db-engine.js +55 -0
  620. package/.worktrees/c1eae35e/src/db.js +381 -0
  621. package/.worktrees/c1eae35e/src/decision-distill.js +517 -0
  622. package/.worktrees/c1eae35e/src/dispatch/backends/local-agent.js +155 -0
  623. package/.worktrees/c1eae35e/src/dispatch/backends/sillyhub-mcp.js +245 -0
  624. package/.worktrees/c1eae35e/src/dispatch/probe.js +246 -0
  625. package/.worktrees/c1eae35e/src/dispatch/strategy.js +121 -0
  626. package/.worktrees/c1eae35e/src/docs-check.js +825 -0
  627. package/.worktrees/c1eae35e/src/docs-debt.js +393 -0
  628. package/.worktrees/c1eae35e/src/docs-gate.js +107 -0
  629. package/.worktrees/c1eae35e/src/doctor-diagnostics.js +1099 -0
  630. package/.worktrees/c1eae35e/src/endpoint-extractor.js +409 -0
  631. package/.worktrees/c1eae35e/src/foreign-declared.js +155 -0
  632. package/.worktrees/c1eae35e/src/fs-atomic.js +73 -0
  633. package/.worktrees/c1eae35e/src/git-helper.js +150 -0
  634. package/.worktrees/c1eae35e/src/hooks/claude-pre-tool-use.cjs +130 -0
  635. package/.worktrees/c1eae35e/src/hooks/worktree-guard.js +892 -0
  636. package/.worktrees/c1eae35e/src/index.js +2854 -0
  637. package/.worktrees/c1eae35e/src/init.js +626 -0
  638. package/.worktrees/c1eae35e/src/knowledge-match.js +231 -0
  639. package/.worktrees/c1eae35e/src/local-detect.js +128 -0
  640. package/.worktrees/c1eae35e/src/local-register.js +104 -0
  641. package/.worktrees/c1eae35e/src/machine-interface.js +543 -0
  642. package/.worktrees/c1eae35e/src/migrate.js +127 -0
  643. package/.worktrees/c1eae35e/src/module-impact.js +166 -0
  644. package/.worktrees/c1eae35e/src/module-resolve.js +222 -0
  645. package/.worktrees/c1eae35e/src/modules.js +580 -0
  646. package/.worktrees/c1eae35e/src/plan-adopt-waves.js +126 -0
  647. package/.worktrees/c1eae35e/src/progress/change-registry.js +336 -0
  648. package/.worktrees/c1eae35e/src/progress/consistency-doctor.js +355 -0
  649. package/.worktrees/c1eae35e/src/progress/shared.js +36 -0
  650. package/.worktrees/c1eae35e/src/progress/stage-machine.js +594 -0
  651. package/.worktrees/c1eae35e/src/progress/step-store.js +265 -0
  652. package/.worktrees/c1eae35e/src/progress.js +1304 -0
  653. package/.worktrees/c1eae35e/src/quick-recommend.js +115 -0
  654. package/.worktrees/c1eae35e/src/quicklog.js +883 -0
  655. package/.worktrees/c1eae35e/src/review-tier.js +77 -0
  656. package/.worktrees/c1eae35e/src/run/command.js +1641 -0
  657. package/.worktrees/c1eae35e/src/run/complete-handlers.js +1552 -0
  658. package/.worktrees/c1eae35e/src/run/complete.js +1259 -0
  659. package/.worktrees/c1eae35e/src/run/concurrent-detect.js +156 -0
  660. package/.worktrees/c1eae35e/src/run/gates.js +1111 -0
  661. package/.worktrees/c1eae35e/src/run/multi-repo-context.js +208 -0
  662. package/.worktrees/c1eae35e/src/run/next.js +128 -0
  663. package/.worktrees/c1eae35e/src/run/prompt.js +843 -0
  664. package/.worktrees/c1eae35e/src/run/quick-audit.js +186 -0
  665. package/.worktrees/c1eae35e/src/run/scan-profile.js +269 -0
  666. package/.worktrees/c1eae35e/src/run/shared.js +1562 -0
  667. package/.worktrees/c1eae35e/src/run/stage.js +587 -0
  668. package/.worktrees/c1eae35e/src/run.js +23 -0
  669. package/.worktrees/c1eae35e/src/scan-diff.js +388 -0
  670. package/.worktrees/c1eae35e/src/scan-postcheck.js +524 -0
  671. package/.worktrees/c1eae35e/src/scan-staleness.js +95 -0
  672. package/.worktrees/c1eae35e/src/setup.js +414 -0
  673. package/.worktrees/c1eae35e/src/sillyhub-mcp/client.js +597 -0
  674. package/.worktrees/c1eae35e/src/sillyhub-mcp/config.js +62 -0
  675. package/.worktrees/c1eae35e/src/spec-dir-typo.js +50 -0
  676. package/.worktrees/c1eae35e/src/spec-sync.js +358 -0
  677. package/.worktrees/c1eae35e/src/stage-contract-engine.js +171 -0
  678. package/.worktrees/c1eae35e/src/stage-contract-spec.js +551 -0
  679. package/.worktrees/c1eae35e/src/stage-contract.js +948 -0
  680. package/.worktrees/c1eae35e/src/stage-review.js +597 -0
  681. package/.worktrees/c1eae35e/src/stages/archive.js +199 -0
  682. package/.worktrees/c1eae35e/src/stages/brainstorm-auto.js +285 -0
  683. package/.worktrees/c1eae35e/src/stages/brainstorm.js +624 -0
  684. package/.worktrees/c1eae35e/src/stages/cmd-existence.js +145 -0
  685. package/.worktrees/c1eae35e/src/stages/doctor.js +540 -0
  686. package/.worktrees/c1eae35e/src/stages/execute.js +1277 -0
  687. package/.worktrees/c1eae35e/src/stages/explore.js +43 -0
  688. package/.worktrees/c1eae35e/src/stages/index.js +29 -0
  689. package/.worktrees/c1eae35e/src/stages/knowledge.js +514 -0
  690. package/.worktrees/c1eae35e/src/stages/plan-postcheck.js +1398 -0
  691. package/.worktrees/c1eae35e/src/stages/plan.js +655 -0
  692. package/.worktrees/c1eae35e/src/stages/quick.js +167 -0
  693. package/.worktrees/c1eae35e/src/stages/scan.js +608 -0
  694. package/.worktrees/c1eae35e/src/stages/status.js +64 -0
  695. package/.worktrees/c1eae35e/src/stages/verify.js +246 -0
  696. package/.worktrees/c1eae35e/src/sync.js +1470 -0
  697. package/.worktrees/c1eae35e/src/task-review.js +1498 -0
  698. package/.worktrees/c1eae35e/src/taskcard-placeholders.js +21 -0
  699. package/.worktrees/c1eae35e/src/taskcard.js +250 -0
  700. package/.worktrees/c1eae35e/src/verify-postcheck.js +1718 -0
  701. package/.worktrees/c1eae35e/src/verify-probes.js +327 -0
  702. package/.worktrees/c1eae35e/src/version.js +19 -0
  703. package/.worktrees/c1eae35e/src/workflow.js +600 -0
  704. package/.worktrees/c1eae35e/src/workspace.js +125 -0
  705. package/.worktrees/c1eae35e/src/worktree-apply.js +1611 -0
  706. package/.worktrees/c1eae35e/src/worktree-deps.js +668 -0
  707. package/.worktrees/c1eae35e/src/worktree.js +1849 -0
  708. package/.worktrees/c1eae35e/templates/claude-instruction.md +23 -0
  709. package/.worktrees/c1eae35e/templates/prompts/taskcard-rules.md +29 -0
  710. package/.worktrees/c1eae35e/templates/prompts/testcase-design.md +12 -0
  711. package/.worktrees/c1eae35e/templates/prompts/verify-probes.md +32 -0
  712. package/.worktrees/c1eae35e/templates/workflows/archive-impact.yaml +79 -0
  713. package/.worktrees/c1eae35e/templates/workflows/scan-docs.yaml +132 -0
  714. package/.worktrees/dafc71ad/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  715. package/.worktrees/dafc71ad/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  716. package/.worktrees/dafc71ad/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  717. package/.worktrees/dafc71ad/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  718. package/.worktrees/dafc71ad/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  719. package/.worktrees/dafc71ad/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  720. package/.worktrees/dafc71ad/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  721. package/.worktrees/dafc71ad/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  722. package/.worktrees/dafc71ad/.claude/skills/sillyspec-export/SKILL.md +57 -0
  723. package/.worktrees/dafc71ad/.claude/skills/sillyspec-init/SKILL.md +177 -0
  724. package/.worktrees/dafc71ad/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  725. package/.worktrees/dafc71ad/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  726. package/.worktrees/dafc71ad/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  727. package/.worktrees/dafc71ad/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  728. package/.worktrees/dafc71ad/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  729. package/.worktrees/dafc71ad/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  730. package/.worktrees/dafc71ad/.claude/skills/sillyspec-state/SKILL.md +64 -0
  731. package/.worktrees/dafc71ad/.claude/skills/sillyspec-status/SKILL.md +54 -0
  732. package/.worktrees/dafc71ad/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  733. package/.worktrees/dafc71ad/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  734. package/.worktrees/dafc71ad/.gitattributes +2 -0
  735. package/.worktrees/dafc71ad/.husky/pre-push +20 -0
  736. package/.worktrees/dafc71ad/README.md +203 -0
  737. package/.worktrees/dafc71ad/SKILL.md +91 -0
  738. package/.worktrees/dafc71ad/analysis.md +366 -0
  739. package/.worktrees/dafc71ad/architecture-analysis.md +448 -0
  740. package/.worktrees/dafc71ad/bin/sillyspec.js +2 -0
  741. package/.worktrees/dafc71ad/eval/README.md +86 -0
  742. package/.worktrees/dafc71ad/eval/eval.config.json +28 -0
  743. package/.worktrees/dafc71ad/eval/lib/adapters/cli.mjs +63 -0
  744. package/.worktrees/dafc71ad/eval/lib/adapters/dryrun.mjs +27 -0
  745. package/.worktrees/dafc71ad/eval/lib/config.mjs +82 -0
  746. package/.worktrees/dafc71ad/eval/lib/db.mjs +76 -0
  747. package/.worktrees/dafc71ad/eval/lib/report.mjs +120 -0
  748. package/.worktrees/dafc71ad/eval/lib/runner.mjs +157 -0
  749. package/.worktrees/dafc71ad/eval/lib/tasks.mjs +73 -0
  750. package/.worktrees/dafc71ad/eval/lib/util.mjs +107 -0
  751. package/.worktrees/dafc71ad/eval/lib/workdir.mjs +30 -0
  752. package/.worktrees/dafc71ad/eval/run.mjs +83 -0
  753. package/.worktrees/dafc71ad/eval/tasks/001-slugify/files/package.json +6 -0
  754. package/.worktrees/dafc71ad/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  755. package/.worktrees/dafc71ad/eval/tasks/001-slugify/task.json +6 -0
  756. package/.worktrees/dafc71ad/eval/tasks/001-slugify/verify.mjs +28 -0
  757. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/package.json +6 -0
  758. package/.worktrees/dafc71ad/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  759. package/.worktrees/dafc71ad/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  760. package/.worktrees/dafc71ad/eval/tasks/002-each-day/task.json +6 -0
  761. package/.worktrees/dafc71ad/eval/tasks/002-each-day/verify.mjs +31 -0
  762. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  763. package/.worktrees/dafc71ad/eval/tasks/003-word-report/files/package.json +6 -0
  764. package/.worktrees/dafc71ad/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  765. package/.worktrees/dafc71ad/eval/tasks/003-word-report/task.json +6 -0
  766. package/.worktrees/dafc71ad/eval/tasks/003-word-report/verify.mjs +38 -0
  767. package/.worktrees/dafc71ad/logo.jpg +0 -0
  768. package/.worktrees/dafc71ad/package-lock.json +977 -0
  769. package/.worktrees/dafc71ad/package.json +41 -0
  770. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  771. package/.worktrees/dafc71ad/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  772. package/.worktrees/dafc71ad/packages/dashboard/dist/favicon.jpg +0 -0
  773. package/.worktrees/dafc71ad/packages/dashboard/dist/index.html +16 -0
  774. package/.worktrees/dafc71ad/packages/dashboard/dist/logo.jpg +0 -0
  775. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-dashboard.html +836 -0
  776. package/.worktrees/dafc71ad/packages/dashboard/dist/prototype-overview.html +256 -0
  777. package/.worktrees/dafc71ad/packages/dashboard/package.json +25 -0
  778. package/.worktrees/dafc71ad/packages/dashboard/server/executor.js +95 -0
  779. package/.worktrees/dafc71ad/packages/dashboard/server/index.js +679 -0
  780. package/.worktrees/dafc71ad/packages/dashboard/server/parser.js +526 -0
  781. package/.worktrees/dafc71ad/packages/dashboard/server/watcher.js +357 -0
  782. package/.worktrees/dafc71ad/src/agent-session-log.js +803 -0
  783. package/.worktrees/dafc71ad/src/change-list.js +290 -0
  784. package/.worktrees/dafc71ad/src/change-risk-profile.js +339 -0
  785. package/.worktrees/dafc71ad/src/check-primitives.js +65 -0
  786. package/.worktrees/dafc71ad/src/classify-change.js +109 -0
  787. package/.worktrees/dafc71ad/src/commit-suggest.js +202 -0
  788. package/.worktrees/dafc71ad/src/config-cat.js +88 -0
  789. package/.worktrees/dafc71ad/src/config-schema.js +328 -0
  790. package/.worktrees/dafc71ad/src/constants.js +97 -0
  791. package/.worktrees/dafc71ad/src/contract-matrix.js +533 -0
  792. package/.worktrees/dafc71ad/src/datetime.js +20 -0
  793. package/.worktrees/dafc71ad/src/db-engine.js +55 -0
  794. package/.worktrees/dafc71ad/src/db.js +381 -0
  795. package/.worktrees/dafc71ad/src/decision-distill.js +517 -0
  796. package/.worktrees/dafc71ad/src/dispatch/backends/local-agent.js +155 -0
  797. package/.worktrees/dafc71ad/src/dispatch/backends/sillyhub-mcp.js +245 -0
  798. package/.worktrees/dafc71ad/src/dispatch/probe.js +246 -0
  799. package/.worktrees/dafc71ad/src/dispatch/strategy.js +121 -0
  800. package/.worktrees/dafc71ad/src/docs-check.js +825 -0
  801. package/.worktrees/dafc71ad/src/docs-debt.js +393 -0
  802. package/.worktrees/dafc71ad/src/docs-gate.js +107 -0
  803. package/.worktrees/dafc71ad/src/doctor-diagnostics.js +1099 -0
  804. package/.worktrees/dafc71ad/src/endpoint-extractor.js +409 -0
  805. package/.worktrees/dafc71ad/src/foreign-declared.js +155 -0
  806. package/.worktrees/dafc71ad/src/fs-atomic.js +73 -0
  807. package/.worktrees/dafc71ad/src/git-helper.js +150 -0
  808. package/.worktrees/dafc71ad/src/hooks/claude-pre-tool-use.cjs +130 -0
  809. package/.worktrees/dafc71ad/src/hooks/worktree-guard.js +892 -0
  810. package/.worktrees/dafc71ad/src/index.js +2854 -0
  811. package/.worktrees/dafc71ad/src/init.js +626 -0
  812. package/.worktrees/dafc71ad/src/knowledge-match.js +231 -0
  813. package/.worktrees/dafc71ad/src/local-detect.js +128 -0
  814. package/.worktrees/dafc71ad/src/local-register.js +104 -0
  815. package/.worktrees/dafc71ad/src/machine-interface.js +543 -0
  816. package/.worktrees/dafc71ad/src/migrate.js +127 -0
  817. package/.worktrees/dafc71ad/src/module-impact.js +166 -0
  818. package/.worktrees/dafc71ad/src/module-resolve.js +222 -0
  819. package/.worktrees/dafc71ad/src/modules.js +580 -0
  820. package/.worktrees/dafc71ad/src/plan-adopt-waves.js +126 -0
  821. package/.worktrees/dafc71ad/src/progress/change-registry.js +336 -0
  822. package/.worktrees/dafc71ad/src/progress/consistency-doctor.js +355 -0
  823. package/.worktrees/dafc71ad/src/progress/shared.js +36 -0
  824. package/.worktrees/dafc71ad/src/progress/stage-machine.js +594 -0
  825. package/.worktrees/dafc71ad/src/progress/step-store.js +265 -0
  826. package/.worktrees/dafc71ad/src/progress.js +1304 -0
  827. package/.worktrees/dafc71ad/src/quick-recommend.js +115 -0
  828. package/.worktrees/dafc71ad/src/quicklog.js +883 -0
  829. package/.worktrees/dafc71ad/src/review-tier.js +77 -0
  830. package/.worktrees/dafc71ad/src/run/command.js +1641 -0
  831. package/.worktrees/dafc71ad/src/run/complete-handlers.js +1552 -0
  832. package/.worktrees/dafc71ad/src/run/complete.js +1259 -0
  833. package/.worktrees/dafc71ad/src/run/concurrent-detect.js +156 -0
  834. package/.worktrees/dafc71ad/src/run/gates.js +1111 -0
  835. package/.worktrees/dafc71ad/src/run/multi-repo-context.js +208 -0
  836. package/.worktrees/dafc71ad/src/run/next.js +128 -0
  837. package/.worktrees/dafc71ad/src/run/prompt.js +843 -0
  838. package/.worktrees/dafc71ad/src/run/quick-audit.js +186 -0
  839. package/.worktrees/dafc71ad/src/run/scan-profile.js +269 -0
  840. package/.worktrees/dafc71ad/src/run/shared.js +1562 -0
  841. package/.worktrees/dafc71ad/src/run/stage.js +587 -0
  842. package/.worktrees/dafc71ad/src/run.js +23 -0
  843. package/.worktrees/dafc71ad/src/scan-diff.js +388 -0
  844. package/.worktrees/dafc71ad/src/scan-postcheck.js +524 -0
  845. package/.worktrees/dafc71ad/src/scan-staleness.js +95 -0
  846. package/.worktrees/dafc71ad/src/setup.js +414 -0
  847. package/.worktrees/dafc71ad/src/sillyhub-mcp/client.js +597 -0
  848. package/.worktrees/dafc71ad/src/sillyhub-mcp/config.js +62 -0
  849. package/.worktrees/dafc71ad/src/spec-dir-typo.js +50 -0
  850. package/.worktrees/dafc71ad/src/spec-sync.js +358 -0
  851. package/.worktrees/dafc71ad/src/stage-contract-engine.js +171 -0
  852. package/.worktrees/dafc71ad/src/stage-contract-spec.js +551 -0
  853. package/.worktrees/dafc71ad/src/stage-contract.js +948 -0
  854. package/.worktrees/dafc71ad/src/stage-review.js +597 -0
  855. package/.worktrees/dafc71ad/src/stages/archive.js +199 -0
  856. package/.worktrees/dafc71ad/src/stages/brainstorm-auto.js +285 -0
  857. package/.worktrees/dafc71ad/src/stages/brainstorm.js +624 -0
  858. package/.worktrees/dafc71ad/src/stages/cmd-existence.js +145 -0
  859. package/.worktrees/dafc71ad/src/stages/doctor.js +540 -0
  860. package/.worktrees/dafc71ad/src/stages/execute.js +1277 -0
  861. package/.worktrees/dafc71ad/src/stages/explore.js +43 -0
  862. package/.worktrees/dafc71ad/src/stages/index.js +29 -0
  863. package/.worktrees/dafc71ad/src/stages/knowledge.js +514 -0
  864. package/.worktrees/dafc71ad/src/stages/plan-postcheck.js +1398 -0
  865. package/.worktrees/dafc71ad/src/stages/plan.js +655 -0
  866. package/.worktrees/dafc71ad/src/stages/quick.js +167 -0
  867. package/.worktrees/dafc71ad/src/stages/scan.js +608 -0
  868. package/.worktrees/dafc71ad/src/stages/status.js +64 -0
  869. package/.worktrees/dafc71ad/src/stages/verify.js +246 -0
  870. package/.worktrees/dafc71ad/src/sync.js +1470 -0
  871. package/.worktrees/dafc71ad/src/task-review.js +1498 -0
  872. package/.worktrees/dafc71ad/src/taskcard-placeholders.js +21 -0
  873. package/.worktrees/dafc71ad/src/taskcard.js +250 -0
  874. package/.worktrees/dafc71ad/src/verify-postcheck.js +1718 -0
  875. package/.worktrees/dafc71ad/src/verify-probes.js +327 -0
  876. package/.worktrees/dafc71ad/src/version.js +19 -0
  877. package/.worktrees/dafc71ad/src/workflow.js +600 -0
  878. package/.worktrees/dafc71ad/src/workspace.js +125 -0
  879. package/.worktrees/dafc71ad/src/worktree-apply.js +1611 -0
  880. package/.worktrees/dafc71ad/src/worktree-deps.js +668 -0
  881. package/.worktrees/dafc71ad/src/worktree.js +1849 -0
  882. package/.worktrees/dafc71ad/templates/claude-instruction.md +23 -0
  883. package/.worktrees/dafc71ad/templates/prompts/taskcard-rules.md +29 -0
  884. package/.worktrees/dafc71ad/templates/prompts/testcase-design.md +12 -0
  885. package/.worktrees/dafc71ad/templates/prompts/verify-probes.md +32 -0
  886. package/.worktrees/dafc71ad/templates/workflows/archive-impact.yaml +79 -0
  887. package/.worktrees/dafc71ad/templates/workflows/scan-docs.yaml +132 -0
  888. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-archive/SKILL.md +87 -0
  889. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-auto/SKILL.md +93 -0
  890. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -0
  891. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-commit/SKILL.md +67 -0
  892. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-continue/SKILL.md +47 -0
  893. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-doctor/SKILL.md +76 -0
  894. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-execute/SKILL.md +214 -0
  895. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-explore/SKILL.md +102 -0
  896. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-export/SKILL.md +57 -0
  897. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-init/SKILL.md +177 -0
  898. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-knowledge/SKILL.md +270 -0
  899. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-plan/SKILL.md +156 -0
  900. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-propose/SKILL.md +87 -0
  901. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-quick/SKILL.md +116 -0
  902. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-resume/SKILL.md +70 -0
  903. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-scan/SKILL.md +79 -0
  904. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-state/SKILL.md +64 -0
  905. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-status/SKILL.md +54 -0
  906. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-verify/SKILL.md +87 -0
  907. package/.worktrees/e58fcc4c/.claude/skills/sillyspec-workspace/SKILL.md +175 -0
  908. package/.worktrees/e58fcc4c/.gitattributes +2 -0
  909. package/.worktrees/e58fcc4c/.husky/pre-push +20 -0
  910. package/.worktrees/e58fcc4c/README.md +203 -0
  911. package/.worktrees/e58fcc4c/SKILL.md +91 -0
  912. package/.worktrees/e58fcc4c/architecture-analysis.md +503 -0
  913. package/.worktrees/e58fcc4c/bin/sillyspec.js +2 -0
  914. package/.worktrees/e58fcc4c/eval/README.md +86 -0
  915. package/.worktrees/e58fcc4c/eval/eval.config.json +28 -0
  916. package/.worktrees/e58fcc4c/eval/lib/adapters/cli.mjs +63 -0
  917. package/.worktrees/e58fcc4c/eval/lib/adapters/dryrun.mjs +27 -0
  918. package/.worktrees/e58fcc4c/eval/lib/config.mjs +82 -0
  919. package/.worktrees/e58fcc4c/eval/lib/db.mjs +76 -0
  920. package/.worktrees/e58fcc4c/eval/lib/report.mjs +120 -0
  921. package/.worktrees/e58fcc4c/eval/lib/runner.mjs +157 -0
  922. package/.worktrees/e58fcc4c/eval/lib/tasks.mjs +73 -0
  923. package/.worktrees/e58fcc4c/eval/lib/util.mjs +107 -0
  924. package/.worktrees/e58fcc4c/eval/lib/workdir.mjs +30 -0
  925. package/.worktrees/e58fcc4c/eval/run.mjs +83 -0
  926. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/files/package.json +6 -0
  927. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/solution/src/slugify.mjs +26 -0
  928. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/task.json +6 -0
  929. package/.worktrees/e58fcc4c/eval/tasks/001-slugify/verify.mjs +28 -0
  930. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/package.json +6 -0
  931. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/files/src/dates.mjs +4 -0
  932. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/solution/src/dates.mjs +30 -0
  933. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/task.json +6 -0
  934. package/.worktrees/e58fcc4c/eval/tasks/002-each-day/verify.mjs +31 -0
  935. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/data/notes.txt +5 -0
  936. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/files/package.json +6 -0
  937. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/solution/bin/report.mjs +36 -0
  938. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/task.json +6 -0
  939. package/.worktrees/e58fcc4c/eval/tasks/003-word-report/verify.mjs +38 -0
  940. package/.worktrees/e58fcc4c/logo.jpg +0 -0
  941. package/.worktrees/e58fcc4c/package-lock.json +977 -0
  942. package/.worktrees/e58fcc4c/package.json +41 -0
  943. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -0
  944. package/.worktrees/e58fcc4c/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -0
  945. package/.worktrees/e58fcc4c/packages/dashboard/dist/favicon.jpg +0 -0
  946. package/.worktrees/e58fcc4c/packages/dashboard/dist/index.html +16 -0
  947. package/.worktrees/e58fcc4c/packages/dashboard/dist/logo.jpg +0 -0
  948. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-dashboard.html +836 -0
  949. package/.worktrees/e58fcc4c/packages/dashboard/dist/prototype-overview.html +256 -0
  950. package/.worktrees/e58fcc4c/packages/dashboard/package.json +25 -0
  951. package/.worktrees/e58fcc4c/packages/dashboard/server/executor.js +95 -0
  952. package/.worktrees/e58fcc4c/packages/dashboard/server/index.js +679 -0
  953. package/.worktrees/e58fcc4c/packages/dashboard/server/parser.js +526 -0
  954. package/.worktrees/e58fcc4c/packages/dashboard/server/watcher.js +357 -0
  955. package/.worktrees/e58fcc4c/src/agent-session-log.js +803 -0
  956. package/.worktrees/e58fcc4c/src/change-list.js +290 -0
  957. package/.worktrees/e58fcc4c/src/change-risk-profile.js +339 -0
  958. package/.worktrees/e58fcc4c/src/check-primitives.js +65 -0
  959. package/.worktrees/e58fcc4c/src/classify-change.js +109 -0
  960. package/.worktrees/e58fcc4c/src/commit-suggest.js +202 -0
  961. package/.worktrees/e58fcc4c/src/config-cat.js +88 -0
  962. package/.worktrees/e58fcc4c/src/config-schema.js +328 -0
  963. package/.worktrees/e58fcc4c/src/constants.js +97 -0
  964. package/.worktrees/e58fcc4c/src/contract-matrix.js +533 -0
  965. package/.worktrees/e58fcc4c/src/datetime.js +20 -0
  966. package/.worktrees/e58fcc4c/src/db-engine.js +55 -0
  967. package/.worktrees/e58fcc4c/src/db.js +381 -0
  968. package/.worktrees/e58fcc4c/src/decision-distill.js +517 -0
  969. package/.worktrees/e58fcc4c/src/dispatch/backends/local-agent.js +155 -0
  970. package/.worktrees/e58fcc4c/src/dispatch/backends/sillyhub-mcp.js +245 -0
  971. package/.worktrees/e58fcc4c/src/dispatch/probe.js +246 -0
  972. package/.worktrees/e58fcc4c/src/dispatch/strategy.js +121 -0
  973. package/.worktrees/e58fcc4c/src/docs-check.js +825 -0
  974. package/.worktrees/e58fcc4c/src/docs-debt.js +393 -0
  975. package/.worktrees/e58fcc4c/src/docs-gate.js +107 -0
  976. package/.worktrees/e58fcc4c/src/doctor-diagnostics.js +1099 -0
  977. package/.worktrees/e58fcc4c/src/endpoint-extractor.js +409 -0
  978. package/.worktrees/e58fcc4c/src/foreign-declared.js +155 -0
  979. package/.worktrees/e58fcc4c/src/fs-atomic.js +73 -0
  980. package/.worktrees/e58fcc4c/src/git-helper.js +150 -0
  981. package/.worktrees/e58fcc4c/src/hooks/claude-pre-tool-use.cjs +130 -0
  982. package/.worktrees/e58fcc4c/src/hooks/worktree-guard.js +892 -0
  983. package/.worktrees/e58fcc4c/src/index.js +2854 -0
  984. package/.worktrees/e58fcc4c/src/init.js +626 -0
  985. package/.worktrees/e58fcc4c/src/knowledge-match.js +231 -0
  986. package/.worktrees/e58fcc4c/src/local-detect.js +128 -0
  987. package/.worktrees/e58fcc4c/src/local-register.js +104 -0
  988. package/.worktrees/e58fcc4c/src/machine-interface.js +543 -0
  989. package/.worktrees/e58fcc4c/src/migrate.js +127 -0
  990. package/.worktrees/e58fcc4c/src/module-impact.js +166 -0
  991. package/.worktrees/e58fcc4c/src/module-resolve.js +222 -0
  992. package/.worktrees/e58fcc4c/src/modules.js +580 -0
  993. package/.worktrees/e58fcc4c/src/plan-adopt-waves.js +126 -0
  994. package/.worktrees/e58fcc4c/src/progress/change-registry.js +336 -0
  995. package/.worktrees/e58fcc4c/src/progress/consistency-doctor.js +355 -0
  996. package/.worktrees/e58fcc4c/src/progress/shared.js +36 -0
  997. package/.worktrees/e58fcc4c/src/progress/stage-machine.js +594 -0
  998. package/.worktrees/e58fcc4c/src/progress/step-store.js +265 -0
  999. package/.worktrees/e58fcc4c/src/progress.js +1304 -0
  1000. package/.worktrees/e58fcc4c/src/quick-recommend.js +115 -0
  1001. package/.worktrees/e58fcc4c/src/quicklog.js +883 -0
  1002. package/.worktrees/e58fcc4c/src/review-tier.js +77 -0
  1003. package/.worktrees/e58fcc4c/src/run/command.js +1641 -0
  1004. package/.worktrees/e58fcc4c/src/run/complete-handlers.js +1552 -0
  1005. package/.worktrees/e58fcc4c/src/run/complete.js +1259 -0
  1006. package/.worktrees/e58fcc4c/src/run/concurrent-detect.js +156 -0
  1007. package/.worktrees/e58fcc4c/src/run/gates.js +1111 -0
  1008. package/.worktrees/e58fcc4c/src/run/multi-repo-context.js +208 -0
  1009. package/.worktrees/e58fcc4c/src/run/next.js +128 -0
  1010. package/.worktrees/e58fcc4c/src/run/prompt.js +843 -0
  1011. package/.worktrees/e58fcc4c/src/run/quick-audit.js +186 -0
  1012. package/.worktrees/e58fcc4c/src/run/scan-profile.js +269 -0
  1013. package/.worktrees/e58fcc4c/src/run/shared.js +1562 -0
  1014. package/.worktrees/e58fcc4c/src/run/stage.js +587 -0
  1015. package/.worktrees/e58fcc4c/src/run.js +23 -0
  1016. package/.worktrees/e58fcc4c/src/scan-diff.js +388 -0
  1017. package/.worktrees/e58fcc4c/src/scan-postcheck.js +524 -0
  1018. package/.worktrees/e58fcc4c/src/scan-staleness.js +95 -0
  1019. package/.worktrees/e58fcc4c/src/setup.js +414 -0
  1020. package/.worktrees/e58fcc4c/src/sillyhub-mcp/client.js +597 -0
  1021. package/.worktrees/e58fcc4c/src/sillyhub-mcp/config.js +62 -0
  1022. package/.worktrees/e58fcc4c/src/spec-dir-typo.js +50 -0
  1023. package/.worktrees/e58fcc4c/src/spec-sync.js +358 -0
  1024. package/.worktrees/e58fcc4c/src/stage-contract-engine.js +171 -0
  1025. package/.worktrees/e58fcc4c/src/stage-contract-spec.js +551 -0
  1026. package/.worktrees/e58fcc4c/src/stage-contract.js +948 -0
  1027. package/.worktrees/e58fcc4c/src/stage-review.js +597 -0
  1028. package/.worktrees/e58fcc4c/src/stages/archive.js +199 -0
  1029. package/.worktrees/e58fcc4c/src/stages/brainstorm-auto.js +285 -0
  1030. package/.worktrees/e58fcc4c/src/stages/brainstorm.js +624 -0
  1031. package/.worktrees/e58fcc4c/src/stages/cmd-existence.js +145 -0
  1032. package/.worktrees/e58fcc4c/src/stages/doctor.js +540 -0
  1033. package/.worktrees/e58fcc4c/src/stages/execute.js +1277 -0
  1034. package/.worktrees/e58fcc4c/src/stages/explore.js +43 -0
  1035. package/.worktrees/e58fcc4c/src/stages/index.js +29 -0
  1036. package/.worktrees/e58fcc4c/src/stages/knowledge.js +514 -0
  1037. package/.worktrees/e58fcc4c/src/stages/plan-postcheck.js +1398 -0
  1038. package/.worktrees/e58fcc4c/src/stages/plan.js +655 -0
  1039. package/.worktrees/e58fcc4c/src/stages/quick.js +167 -0
  1040. package/.worktrees/e58fcc4c/src/stages/scan.js +608 -0
  1041. package/.worktrees/e58fcc4c/src/stages/status.js +64 -0
  1042. package/.worktrees/e58fcc4c/src/stages/verify.js +246 -0
  1043. package/.worktrees/e58fcc4c/src/sync.js +1470 -0
  1044. package/.worktrees/e58fcc4c/src/task-review.js +1498 -0
  1045. package/.worktrees/e58fcc4c/src/taskcard-placeholders.js +21 -0
  1046. package/.worktrees/e58fcc4c/src/taskcard.js +250 -0
  1047. package/.worktrees/e58fcc4c/src/verify-postcheck.js +1718 -0
  1048. package/.worktrees/e58fcc4c/src/verify-probes.js +327 -0
  1049. package/.worktrees/e58fcc4c/src/version.js +19 -0
  1050. package/.worktrees/e58fcc4c/src/workflow.js +600 -0
  1051. package/.worktrees/e58fcc4c/src/workspace.js +125 -0
  1052. package/.worktrees/e58fcc4c/src/worktree-apply.js +1611 -0
  1053. package/.worktrees/e58fcc4c/src/worktree-deps.js +668 -0
  1054. package/.worktrees/e58fcc4c/src/worktree.js +1849 -0
  1055. package/.worktrees/e58fcc4c/templates/claude-instruction.md +23 -0
  1056. package/.worktrees/e58fcc4c/templates/prompts/taskcard-rules.md +29 -0
  1057. package/.worktrees/e58fcc4c/templates/prompts/testcase-design.md +12 -0
  1058. package/.worktrees/e58fcc4c/templates/prompts/verify-probes.md +32 -0
  1059. package/.worktrees/e58fcc4c/templates/workflows/archive-impact.yaml +79 -0
  1060. package/.worktrees/e58fcc4c/templates/workflows/scan-docs.yaml +132 -0
  1061. package/architecture-analysis.md +448 -0
  1062. package/package.json +1 -1
  1063. package/src/contract-matrix.js +7 -4
  1064. package/src/endpoint-extractor.js +41 -52
  1065. package/src/foreign-declared.js +88 -5
  1066. package/src/fs-atomic.js +20 -3
  1067. package/src/hooks/worktree-guard.js +9 -3
  1068. package/src/index.js +36 -19
  1069. package/src/module-impact.js +1 -1
  1070. package/src/modules.js +23 -21
  1071. package/src/progress/stage-machine.js +23 -0
  1072. package/src/progress.js +38 -2
  1073. package/src/quicklog.js +7 -5
  1074. package/src/run/command.js +7 -6
  1075. package/src/run/complete-handlers.js +6 -2
  1076. package/src/run/complete.js +33 -20
  1077. package/src/run/gates.js +31 -4
  1078. package/src/run/next.js +4 -3
  1079. package/src/run/prompt.js +66 -6
  1080. package/src/run/scan-profile.js +1 -0
  1081. package/src/run/shared.js +11 -5
  1082. package/src/run/stage.js +15 -12
  1083. package/src/scan-diff.js +4 -2
  1084. package/src/stage-contract-spec.js +1 -1
  1085. package/src/stage-contract.js +16 -8
  1086. package/src/stages/brainstorm-auto.js +43 -1
  1087. package/src/stages/brainstorm.js +24 -8
  1088. package/src/stages/execute.js +36 -9
  1089. package/src/stages/knowledge.js +18 -5
  1090. package/src/stages/plan-postcheck.js +63 -7
  1091. package/src/stages/plan.js +13 -6
  1092. package/src/stages/verify.js +1 -1
  1093. package/src/sync.js +27 -11
  1094. package/src/task-review.js +5 -3
  1095. package/src/taskcard.js +35 -0
  1096. package/src/verify-postcheck.js +24 -13
  1097. package/src/verify-probes.js +39 -13
  1098. package/src/worktree-apply.js +481 -292
  1099. package/src/worktree-deps.js +93 -1
  1100. package/src/worktree.js +91 -21
  1101. package/templates/prompts/taskcard-rules.md +1 -1
@@ -0,0 +1,825 @@
1
+ /**
2
+ * docs-check — 文档行号引用校验核心(change: 2026-08-15-docs-check-productize)
3
+ *
4
+ * 从 dogfood 私有测试 test/doc-ref-check.test.mjs 抽离产品化(design D-001~D-008):
5
+ * 层1 存在性(所有引用必查):文件存在 + 行号 ≥1 且 ≤ 总行数(范围引用查 end)
6
+ * 层2 关键词断言(keywordAssert 可配,缺省开):引用所在文档行内的反引号代码符号 token,
7
+ * 断言源文件 [start-2, end+5] 窗口(实现期口径,非对称——文档行号常指向块起始行
8
+ * 而 token 在体首几行)内含任一 token。多候选宽容:裸文件名多命中时任一候选全过即通过。
9
+ *
10
+ * 纯函数(collectDocRefs/looksLikeCodeSymbol/validateRefLines/extractExpectedTokensFromLine)
11
+ * 无 fs 依赖可单测;resolveCandidates/walkGlob/runDocsCheck 是 IO 面。
12
+ * 校验链路只读(不修改任何被校验文件);applyFixes 是唯一写回面(--fix 显式触发,design §9:
13
+ * 文档非多进程竞争的运行时文件,普通 writeFileSync);纯 Node 内置模块零依赖(D-008:glob 手写 walker,
14
+ * 仅「目录递归」「目录单层」「字面路径」三形态);Windows 路径归一化;兼容 CRLF/LF。
15
+ */
16
+ import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'node:fs'
17
+ import { join } from 'node:path'
18
+ import jsYaml from 'js-yaml'
19
+ import { parseModuleMapSimple } from './modules.js'
20
+
21
+ /** 提取 file.js:line / file.js:start-end 引用(.js/.mjs,反引号包裹与裸文本均命中,全文扫描 D-006)。
22
+ * repo:// 前缀(2026-08-20):跨仓引用显式标记——`repo://<仓库名>/<路径>.js:行`。
23
+ * 不同设备兄弟仓库位置不同,未配映射时默认跳过本地校验(防跨设备误报);
24
+ * 在本机 .sillyspec/local.yaml 的 docs-check.cross_repo_roots 配
25
+ * `<仓库名>: <本机绝对路径>` 后,走与本地引用完全相同的层1(行号边界)+ 层2(关键词窗口)校验。
26
+ * 正则组:1=仓库名(可选),2=文件,3=start,4=end。 */
27
+ const REF_RE = /(?:repo:\/\/([A-Za-z0-9_.\-]+)\/)?([A-Za-z0-9_.\-\/]+\.(?:js|mjs)):(\d+)(?:-(\d+))?/g
28
+
29
+ /** 缺省扫描范围:docs/ + .sillyspec/docs/(scan/modules 产物同是文档,失效即该暴露;2026-08-16 用户裁决改缺省,见 doc-consistency-debt.md §八) */
30
+ const DEFAULT_DOC_PATHS = ['docs/**/*.md', '.sillyspec/docs/**/*.md']
31
+
32
+ /**
33
+ * 读 local.yaml 的 docs-check 段(best-effort,绝不抛;缺文件/无段 → 全缺省)。
34
+ * @param {string} projectRoot 源码仓根(local.yaml 在 <root>/.sillyspec/local.yaml)
35
+ * @returns {{ paths?: string[], skip: string[], keywordAssert: boolean, crossRepoRoots: Record<string, string> }}
36
+ */
37
+ export function readDocsCheckConfig(projectRoot) {
38
+ const fallback = { paths: null, skip: [], keywordAssert: true, crossRepoRoots: {} }
39
+ try {
40
+ const p = join(projectRoot, '.sillyspec', 'local.yaml')
41
+ if (!existsSync(p)) return fallback
42
+ const doc = jsYaml.load(readFileSync(p, 'utf8'))
43
+ if (!doc || typeof doc !== 'object') return fallback
44
+ const dc = doc['docs-check']
45
+ if (!dc || typeof dc !== 'object') return fallback
46
+ const crr = dc['cross_repo_roots']
47
+ return {
48
+ paths: Array.isArray(dc.paths) ? dc.paths.filter(s => typeof s === 'string') : null,
49
+ skip: Array.isArray(dc.skip) ? dc.skip.filter(s => typeof s === 'string') : [],
50
+ keywordAssert: typeof dc.keywordAssert === 'boolean' ? dc.keywordAssert : true,
51
+ // repo://<name> → 本机仓库根(每台设备各自配;local.yaml 是 gitignored,绝对路径不入库)
52
+ crossRepoRoots: crr && typeof crr === 'object' && !Array.isArray(crr)
53
+ ? Object.fromEntries(
54
+ Object.entries(crr).filter(([, v]) => typeof v === 'string' && v.trim() !== ''),
55
+ )
56
+ : {},
57
+ }
58
+ } catch {
59
+ return fallback
60
+ }
61
+ }
62
+
63
+ /** 配置错误(glob 形态不支持等)→ CLI exit 2 */
64
+ export class DocsCheckConfigError extends Error {}
65
+
66
+ /**
67
+ * 纯函数:从 markdown 全文提取全部 file:line 引用。
68
+ * @param {string} md 文档全文
69
+ * @returns {Array<{ ref, file, start, end, docLine }>} docLine 为 1-based 文档行号
70
+ */
71
+ export function collectDocRefs(md) {
72
+ if (!md || typeof md !== 'string') return []
73
+ const refs = []
74
+ const re = new RegExp(REF_RE.source, 'g')
75
+ // 行号单遍计算:regex match 天然按 index 升序,游标只前进——原逐引用
76
+ // slice(0,m.index).split() 是 O(引用数 × 文档长度),长文档×多引用退化明显
77
+ let line = 1
78
+ let cursor = 0
79
+ let m
80
+ while ((m = re.exec(md)) !== null) {
81
+ for (let i = cursor; i < m.index; i++) {
82
+ if (md.charCodeAt(i) === 10) line++ // '\n'(\r\n 也以 \n 计数,1-based 行号不受影响)
83
+ }
84
+ cursor = m.index
85
+ refs.push({
86
+ ref: m[0],
87
+ repo: m[1] !== undefined ? m[1] : null,
88
+ file: m[2],
89
+ start: parseInt(m[3], 10),
90
+ end: m[4] !== undefined ? parseInt(m[4], 10) : parseInt(m[3], 10),
91
+ docLine: line,
92
+ })
93
+ }
94
+ return refs
95
+ }
96
+
97
+ /**
98
+ * 纯函数:判定 token 是否「像代码符号」:首字符字母/_/$,且含大写字母/下划线/点/$ 之一。
99
+ * 纯小写英文单词(local/platform/abort)→ false(自然语言,跳过断言防误报)。
100
+ */
101
+ export function looksLikeCodeSymbol(token) {
102
+ if (!/^[A-Za-z_$][A-Za-z0-9_$.]*$/.test(token)) return false
103
+ return /[A-Z_$.]/.test(token)
104
+ }
105
+
106
+ /**
107
+ * 纯函数:层1 行号边界校验。
108
+ * @param {number} totalLines 源文件总行数
109
+ * @param {number} start 1-based 起始行
110
+ * @param {number} end 1-based 结束行(单行引用 = start)
111
+ * @returns {{ ok: boolean, reasons: string[] }}
112
+ */
113
+ export function validateRefLines(totalLines, start, end) {
114
+ const reasons = []
115
+ if (start < 1 || start > totalLines) reasons.push(`行号超界(start=${start} > 总行数 ${totalLines})`)
116
+ if (end < start || end > totalLines) reasons.push(`范围 end=${end} 超界(总行数 ${totalLines})`)
117
+ return { ok: reasons.length === 0, reasons }
118
+ }
119
+
120
+ /**
121
+ * 纯函数:层2 token 提取——引用所在的文档行内所有反引号 token 中的代码符号。
122
+ * token 归一:①剥函数括号(getDispatchMode());②点分名拆段(syncMod.checkApproval → 两段)。
123
+ * 空数组 = 纯位置引用,跳过层2。
124
+ * @param {string} line 引用所在的文档行全文
125
+ * @returns {string[]} token 列表
126
+ */
127
+ export function extractExpectedTokensFromLine(line) {
128
+ if (!line || typeof line !== 'string') return []
129
+ const tokens = new Set()
130
+ for (const mm of line.matchAll(/`([^`\n]{1,60})`/g)) {
131
+ const t = mm[1].split('(')[0].trim()
132
+ if (!looksLikeCodeSymbol(t)) continue
133
+ tokens.add(t)
134
+ if (t.includes('.')) {
135
+ for (const seg of t.split('.')) {
136
+ if (looksLikeCodeSymbol(seg)) tokens.add(seg)
137
+ }
138
+ }
139
+ }
140
+ return [...tokens]
141
+ }
142
+
143
+ /** 递归收集 dir 下与 baseName 同名的文件(相对 dir 的 POSIX 路径数组;排除 node_modules/.git)。
144
+ * treeCache 给定时按 baseName 复用全树扫描结果(N 条裸名引用同一文件免 N 次 walk) */
145
+ function findInTree(dir, baseName, rel = '', treeCache = null) {
146
+ if (treeCache && rel === '') {
147
+ const hit = treeCache.get(baseName)
148
+ if (hit) return hit
149
+ const result = findInTree(dir, baseName, '', null)
150
+ treeCache.set(baseName, result)
151
+ return result
152
+ }
153
+ const out = []
154
+ let entries
155
+ try { entries = readdirSync(dir, { withFileTypes: true }) } catch { return out }
156
+ for (const e of entries) {
157
+ if (e.name === 'node_modules' || e.name === '.git') continue
158
+ const relPath = rel ? `${rel}/${e.name}` : e.name
159
+ if (e.isDirectory()) out.push(...findInTree(join(dir, e.name), baseName, relPath))
160
+ else if (e.name === baseName) out.push(relPath)
161
+ }
162
+ return out
163
+ }
164
+
165
+ /**
166
+ * 解析引用文件 → 候选绝对路径数组。文档写法三种混用(首跑实证):
167
+ * ①仓库根相对(src/sync.js / docs/...)→ 直拼;②src/ 内部相对(dispatch/probe.js)→
168
+ * src/ 前缀重试;③裸中缀(backends/sillyhub-mcp.js)→ src/ 树内按路径后缀匹配。
169
+ * 空数组 = 不存在。treeCache(Map basename→findInTree 结果)给定时透传复用全树扫描。
170
+ */
171
+ export function resolveCandidates(projectRoot, refFile, treeCache = null) {
172
+ if (refFile.includes('/')) {
173
+ const direct = join(projectRoot, refFile)
174
+ if (existsSync(direct)) return [direct]
175
+ const inSrc = join(projectRoot, 'src', refFile)
176
+ if (existsSync(inSrc)) return [inSrc]
177
+ const slash = refFile.lastIndexOf('/')
178
+ const baseName = slash === -1 ? refFile : refFile.slice(slash + 1)
179
+ return findInTree(join(projectRoot, 'src'), baseName, '', treeCache)
180
+ .filter((rel) => ('src/' + rel).endsWith('/' + refFile) || 'src/' + rel === 'src/' + refFile)
181
+ .map((rel) => join(projectRoot, 'src', rel))
182
+ }
183
+ return findInTree(join(projectRoot, 'src'), refFile, '', treeCache).map((rel) => join(projectRoot, 'src', rel))
184
+ }
185
+
186
+ /** 读文件行数组(CRLF/LF 归一:split(/\r?\n/),层2 只做子串查找不污染原文)。
187
+ * linesCache 给定时按绝对路径复用(同文件被 N 条引用消费免 N 次读盘+split) */
188
+ function readLines(absPath, linesCache = null) {
189
+ if (linesCache) {
190
+ if (linesCache.has(absPath)) return linesCache.get(absPath)
191
+ const lines = readLines(absPath)
192
+ linesCache.set(absPath, lines)
193
+ return lines
194
+ }
195
+ try { return readFileSync(absPath, 'utf8').split(/\r?\n/) } catch { return null }
196
+ }
197
+
198
+ /** 简单通配匹配(skip 排除用,仅 * 单段) */
199
+ function matchSimple(text, pattern) {
200
+ const parts = pattern.split('*')
201
+ let idx = 0
202
+ for (let i = 0; i < parts.length; i++) {
203
+ if (parts[i] === '') continue
204
+ const found = text.indexOf(parts[i], idx)
205
+ if (found === -1) return false
206
+ if (i === 0 && found !== 0) return false
207
+ idx = found + parts[i].length
208
+ }
209
+ return true
210
+ }
211
+
212
+ /**
213
+ * glob walker(D-008:手写不引依赖)。仅支持三形态:
214
+ * - `dir/「递归」*.ext` 递归收集(maxDepth 12 兜底防符号链接环)
215
+ * - `dir/*.ext` 单层
216
+ * - 字面路径直传(存在才返回)
217
+ * 其他形态(?、{a,b}、多层 * 混合等)抛 DocsCheckConfigError → CLI exit 2。
218
+ * @param {string} projectRoot 锚点(平台模式也锚源码仓根,design §3.3)
219
+ * @param {string} pattern glob 模式
220
+ * @param {string[]} skip 排除 glob(前缀或单 * 简单匹配)
221
+ * @returns {string[]} 命中文件的 POSIX 相对路径
222
+ */
223
+ export function walkGlob(projectRoot, pattern, skip = []) {
224
+ const norm = (p) => p.replace(/\\/g, '/')
225
+ const isSkipped = (rel) => skip.some((s) => {
226
+ const sn = norm(s).replace(/\/$/, '')
227
+ return rel === sn || rel.startsWith(sn + '/') ||
228
+ (sn.includes('*') && matchSimple(rel, sn))
229
+ })
230
+ const matchExt = (name, ext) => name.endsWith(ext)
231
+ // 形态 0:**/*.ext(根级递归,无 base 前缀——B11b:原被形态 2 误解析为字面目录 `**` 静默 0 命中)
232
+ let m0 = norm(pattern).match(/^\*\*\/\*(\.[A-Za-z0-9]+)$/)
233
+ if (m0) {
234
+ const [, ext] = m0
235
+ const out = []
236
+ const rec = (dir, rel, depth) => {
237
+ if (depth > 12) return
238
+ let entries
239
+ try { entries = readdirSync(dir, { withFileTypes: true }) } catch { return }
240
+ for (const e of entries) {
241
+ if (e.name === 'node_modules' || e.name === '.git') continue
242
+ const relPath = rel ? `${rel}/${e.name}` : e.name
243
+ if (isSkipped(relPath)) continue
244
+ if (e.isDirectory()) rec(join(dir, e.name), relPath, depth + 1)
245
+ else if (matchExt(e.name, ext)) out.push(relPath)
246
+ }
247
+ }
248
+ rec(projectRoot, '', 0)
249
+ return out
250
+ }
251
+ // 形态 1:**/*.ext
252
+ let m = norm(pattern).match(/^(.+?)\/\*\*\/\*(\.[A-Za-z0-9]+)$/)
253
+ if (m) {
254
+ const [, baseDir, ext] = m
255
+ const out = []
256
+ const rec = (dir, rel, depth) => {
257
+ if (depth > 12) return
258
+ let entries
259
+ try { entries = readdirSync(dir, { withFileTypes: true }) } catch { return }
260
+ for (const e of entries) {
261
+ if (e.name === 'node_modules' || e.name === '.git') continue
262
+ const relPath = rel ? `${rel}/${e.name}` : e.name
263
+ if (isSkipped(relPath)) continue
264
+ if (e.isDirectory()) rec(join(dir, e.name), relPath, depth + 1)
265
+ else if (matchExt(e.name, ext)) out.push(relPath)
266
+ }
267
+ }
268
+ rec(join(projectRoot, baseDir), baseDir, 0)
269
+ return out
270
+ }
271
+ // 形态 2:dir/*.ext(单层)
272
+ m = norm(pattern).match(/^(.+?)\/\*(\.[A-Za-z0-9]+)$/)
273
+ if (m) {
274
+ const [, baseDir, ext] = m
275
+ const out = []
276
+ let entries
277
+ try { entries = readdirSync(join(projectRoot, baseDir), { withFileTypes: true }) } catch { return out }
278
+ for (const e of entries) {
279
+ if (!e.isFile()) continue
280
+ const relPath = `${baseDir}/${e.name}`
281
+ if (isSkipped(relPath)) continue
282
+ if (matchExt(e.name, ext)) out.push(relPath)
283
+ }
284
+ return out
285
+ }
286
+ // 形态 3:字面路径(不含任何通配元字符才直传;含 ?、{ }、[ ] 等不支持形态落 error)
287
+ if (!/[*?{}\[\]]/.test(pattern)) {
288
+ const abs = join(projectRoot, pattern)
289
+ if (!existsSync(abs)) return []
290
+ // B11b:目录字面量抛配置错误(原直传 readFileSync 撞 EISDIR 裸崩 exit 1;契约应 exit 2)
291
+ if (statSync(abs).isDirectory()) {
292
+ throw new DocsCheckConfigError(`路径是目录不是文档:${pattern}(文档路径应为 .md 文件或 glob 形态 **/*.ext / dir/**/*.ext / dir/*.ext)`)
293
+ }
294
+ return [norm(pattern)]
295
+ }
296
+ throw new DocsCheckConfigError(`不支持的 glob 形态:${pattern}(当前仅支持 dir/**/*.ext、dir/*.ext、字面路径)`)
297
+ }
298
+
299
+ /** 候选路径 → 相对 projectRoot 显示(失败信息用;Windows 反斜杠归一) */
300
+ function relDisplay(absPath, projectRoot) {
301
+ return absPath
302
+ .replace(/\\/g, '/')
303
+ .replace(projectRoot.replace(/\\/g, '/') + '/', '')
304
+ }
305
+
306
+ /**
307
+ * IO 入口:跑一次完整校验。
308
+ * @param {{ projectRoot: string, docs?: string[], paths?: string[], skip?: string[], keywordAssert?: boolean, crossRepoRoots?: Record<string, string> }} opts
309
+ * projectRoot 源码仓根(候选解析与 glob 的锚点,平台模式也传源码仓根)
310
+ * docs 显式文档相对路径列表(优先于 paths glob 展开结果)
311
+ * crossRepoRoots repo://<仓库名> → 本机仓库根映射(未映射的跨仓引用跳过不计失效)
312
+ * @returns {{ ok: boolean, total: number, invalid: Array<{doc, docLine, ref, reason, suggest?: number[], fix: {fixable: boolean, newLine?: number, reason: string}}>, warnings: string[], kwChecked: number, crossRepoSkipped: number }}
313
+ * @throws {DocsCheckConfigError} glob 形态不支持
314
+ */
315
+ export function runDocsCheck(opts) {
316
+ // paths/docs 显式传 null(readDocsCheckConfig 无 local.yaml 段时的回退值)须落回缺省 glob,
317
+ // 解构默认值只挡 undefined 不挡 null——docs-check 无配置裸跑曾因此 null.flatMap 崩溃。
318
+ const {
319
+ projectRoot, docs = null, paths: rawPaths = DEFAULT_DOC_PATHS, skip = [],
320
+ keywordAssert = true, crossRepoRoots = {},
321
+ } = opts || {}
322
+ const paths = Array.isArray(rawPaths) && rawPaths.length > 0 ? rawPaths : DEFAULT_DOC_PATHS
323
+ const warnings = []
324
+ if (keywordAssert === false) warnings.push('关键词断言已关闭(keywordAssert=false),仅做存在性校验')
325
+ const docFiles = docs && docs.length > 0
326
+ ? docs
327
+ : [...new Set(paths.flatMap((p) => walkGlob(projectRoot, p, skip)))].sort()
328
+
329
+ const invalid = []
330
+ let total = 0
331
+ let kwChecked = 0
332
+ // repo:// 跨仓引用:未配映射被跳过的数量(不计入 total/invalid,跨设备零误报)
333
+ let crossRepoSkipped = 0
334
+ // per-call 缓存:裸名引用的 src/ 全树扫描结果 + 候选文件行数组——100 文档 × 10 裸名引用
335
+ // 此前 = 1000 次全树 walk + 同文件 N 次重读(2026-08-21 性能审查 PERF-5)。仅本次调用
336
+ // 生命周期内有效,不跨调用(防测试流程中途改树后读到陈旧结果)
337
+ const treeCache = new Map()
338
+ const linesCache = new Map()
339
+
340
+ for (const docRel of docFiles) {
341
+ const docAbs = join(projectRoot, docRel)
342
+ if (!existsSync(docAbs)) {
343
+ invalid.push({
344
+ doc: docRel, docLine: 0, ref: '', reason: '文档不存在',
345
+ fix: { fixable: false, reason: '文档不存在,无法自动定位' },
346
+ })
347
+ continue
348
+ }
349
+ const md = readFileSync(docAbs, 'utf8')
350
+ const refs = collectDocRefs(md)
351
+ const mdLines = md.split(/\r?\n/)
352
+
353
+ for (const r of refs) {
354
+ // repo:// 跨仓引用:未配映射 → 跳过(不同设备仓库位置不同,不按本仓解析误报);
355
+ // 配了映射 → 以映射根为唯一候选,走与本地引用相同的层1+层2 校验。
356
+ let candidates
357
+ if (r.repo) {
358
+ const repoRoot = crossRepoRoots && typeof crossRepoRoots[r.repo] === 'string'
359
+ ? crossRepoRoots[r.repo]
360
+ : null
361
+ if (!repoRoot) {
362
+ crossRepoSkipped++
363
+ continue
364
+ }
365
+ const abs = join(repoRoot, r.file)
366
+ if (!existsSync(abs)) {
367
+ total++
368
+ invalid.push({
369
+ doc: docRel, docLine: r.docLine, ref: r.ref,
370
+ reason: `跨仓 repo://${r.repo} → 文件不存在(cross_repo_roots 映射根:${repoRoot})`,
371
+ fix: { fixable: false, reason: '跨仓引用无法自动定位' },
372
+ })
373
+ continue
374
+ }
375
+ candidates = [abs]
376
+ } else {
377
+ candidates = resolveCandidates(projectRoot, r.file, treeCache)
378
+ }
379
+ total++
380
+ if (candidates.length === 0) {
381
+ invalid.push({
382
+ doc: docRel, docLine: r.docLine, ref: r.ref,
383
+ reason: '文件不存在(含 / 按仓库根解析;裸文件名在 src/ 递归)',
384
+ fix: { fixable: false, reason: '文件不存在,无法自动定位' },
385
+ })
386
+ continue
387
+ }
388
+ // 多候选宽容:逐候选跑层1+层2,任一全过即通过
389
+ const tokens = keywordAssert
390
+ ? extractExpectedTokensFromLine(mdLines[r.docLine - 1] || '')
391
+ : []
392
+ const candidateFails = []
393
+ let passedAny = false
394
+ for (const candAbs of candidates) {
395
+ const lines = readLines(candAbs, linesCache)
396
+ if (lines === null) { candidateFails.push(`${relDisplay(candAbs, projectRoot)}: 读取失败`); continue }
397
+ const v = validateRefLines(lines.length, r.start, r.end)
398
+ // 层2:token 任一在 [start-2, end+5] 窗口命中即过
399
+ let kwOk = true
400
+ if (tokens.length > 0) {
401
+ const from = Math.max(0, r.start - 2)
402
+ const to = Math.min(lines.length, r.end + 5)
403
+ const window = lines.slice(from, to).join('\n')
404
+ kwOk = tokens.some((t) => window.includes(t))
405
+ }
406
+ if (v.ok && kwOk) { passedAny = true; break }
407
+ const reasons = [...v.reasons]
408
+ if (!kwOk) reasons.push(`关键词缺失:期望任一「${tokens.join(' / ')}」在 [start-2, end+5] 窗口内`)
409
+ candidateFails.push(`${relDisplay(candAbs, projectRoot)}: ${reasons.join(';')}`)
410
+ }
411
+ if (tokens.length > 0) kwChecked++
412
+ if (!passedAny) {
413
+ // 跨仓校验失败的 reason 加 repo:// 前缀,用户一眼区分「改外部仓引用」还是「改本仓引用」
414
+ const repoPrefix = r.repo ? `跨仓 repo://${r.repo} → ` : ''
415
+ invalid.push({
416
+ doc: docRel, docLine: r.docLine, ref: r.ref,
417
+ reason: repoPrefix + (candidateFails.length > 1 ? `多候选全失败 → ${candidateFails.join(' | ')}` : candidateFails[0]),
418
+ // 建议行号(--suggest):token 在首个候选文件的全量命中行,供人工确认改锚——不自动改文件
419
+ suggest: suggestLines(candidates, tokens, linesCache),
420
+ // 修复分类(--fix 判定依据):全量候选 token 命中打分——唯一命中或选优严格领先可自动重锚
421
+ fix: classifyFix(candidates, tokens, r.start, linesCache),
422
+ })
423
+ }
424
+ }
425
+ }
426
+
427
+ return { ok: invalid.length === 0, total, invalid, warnings, kwChecked, crossRepoSkipped }
428
+ }
429
+
430
+ /**
431
+ * 建议行号计算(--suggest):对失效引用,在候选文件里找 token 全量命中行。
432
+ * 无 token(纯行号断言)时返回空数组——没有符号线索无法定位,只能人工看。
433
+ */
434
+ function suggestLines(candidates, tokens, linesCache = null) {
435
+ if (tokens.length === 0) return []
436
+ try {
437
+ const lines = readLines(candidates[0], linesCache)
438
+ if (lines === null) return []
439
+ const out = []
440
+ lines.forEach((l, i) => { if (tokens.some((t) => l.includes(t))) out.push(i + 1) })
441
+ return out.slice(0, 8)
442
+ } catch { return [] }
443
+ }
444
+
445
+ /**
446
+ * 修复分类(--fix 判定依据):对 resolveCandidates 全量候选跑 token 命中统计,跨候选合并行号后——
447
+ * 唯一命中 → fixable=true + newLine(自动重锚唯一解);
448
+ * 多命中 → 打分选优(2026-08-21 docs-ref-auto-pick,替代 D-006 一律人工):top1 严格优于
449
+ * top2(分数差 > 0)自动重锚,同分仍人工。实证:一次大改 34 处漂移只有 2 处唯一命中,
450
+ * 32 处人工逐个挑——多命中不代表歧义,行号漂移多为单次编辑的单调位移。
451
+ * 打分信号(全部来自现有数据,不新增 IO):
452
+ * - 距离:|命中行 - 文档旧行号|(权重封顶 400)——最近的命中大概率是原锚点漂移后的位置
453
+ * - 定义行模式 +50:function/const/let/class/def/export 关键词**紧跟** token(引用锚通常指
454
+ * 定义起始行而非调用点;「keyword 后 60 字符内出现」的宽松口径会把调用点误判为定义)
455
+ * - 注释行 -30(// * # -- 开头)
456
+ * - 含最长 token(点分整串)+10,优于只含拆段
457
+ * 与 suggestLines 的差异:suggest 只查首个候选(candidates[0]),本函数查全量候选(design §12 自审存疑 +
458
+ * R-01——多候选同名文件场景下防止定位到另一文件的同名符号)。合并口径按「去重后的行号集合」:
459
+ * 重锚写回的目标是行号,多个候选命中同一行号仍是唯一改写目标。
460
+ * 纯增量分类,不参与层1/层2 判定(D-004 兼容红线)。
461
+ * @param {string[]} candidates resolveCandidates 返回的全量候选绝对路径
462
+ * @param {string[]} tokens 层2 提取的期望 token(keywordAssert=false 时为空数组)
463
+ * @param {number|null} [refStart] 文档引用的旧行号(打分用距离信号;范围引用取 start)
464
+ * @returns {{ fixable: boolean, newLine?: number, reason: string }}
465
+ */
466
+ function escapeReLocal(s) {
467
+ return String(s).replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
468
+ }
469
+
470
+ function classifyFix(candidates, tokens, refStart = null, linesCache = null) {
471
+ if (tokens.length === 0) {
472
+ return { fixable: false, reason: '无 token 符号线索(纯位置引用或关键词断言关闭),无法自动定位' }
473
+ }
474
+ const longest = tokens.reduce((a, b) => (b.length > a.length ? b : a), '')
475
+ const defToken = longest.includes('.') ? longest.split('.').pop() : longest
476
+ const defRe = new RegExp(`(?:export\\s+)?(?:async\\s+)?(?:function|const|let|class|def)\\s+${escapeReLocal(defToken)}\\b`)
477
+ const byLine = new Map()
478
+ for (const candAbs of candidates) {
479
+ const lines = readLines(candAbs, linesCache)
480
+ if (lines === null) continue
481
+ lines.forEach((l, i) => {
482
+ if (!tokens.some((t) => l.includes(t))) return
483
+ const lineNo = i + 1
484
+ let score = 0
485
+ if (/^(\/\/|\*|#|--)/.test(l.trim())) score -= 30
486
+ if (defRe.test(l)) score += 50
487
+ if (l.includes(longest)) score += 10
488
+ if (refStart != null && Number.isFinite(refStart)) score -= Math.min(Math.abs(lineNo - refStart), 400)
489
+ // 同一行跨候选取最高分(合并口径不变:重锚目标是行号)
490
+ if (score > (byLine.get(lineNo) ?? -Infinity)) byLine.set(lineNo, score)
491
+ })
492
+ }
493
+ if (byLine.size === 0) {
494
+ return { fixable: false, reason: 'token 在全量候选文件零命中,无法自动定位' }
495
+ }
496
+ if (byLine.size === 1) {
497
+ return { fixable: true, newLine: [...byLine.keys()][0], reason: 'token 在全量候选唯一命中,可自动重锚' }
498
+ }
499
+ const ranked = [...byLine.entries()].sort((a, b) => (b[1] - a[1]) || (a[0] - b[0]))
500
+ const [topLine, topScore] = ranked[0]
501
+ const [runLine, runScore] = ranked[1]
502
+ if (topScore > runScore) {
503
+ return {
504
+ fixable: true,
505
+ newLine: topLine,
506
+ reason: `多命中自动选优:picked=${topLine}(${topScore} 分)runnerUp=${runLine}(${runScore} 分,严格落后才自动改)`,
507
+ }
508
+ }
509
+ const shown = ranked.slice(0, 8).map(([l]) => l).join('、') + (ranked.length > 8 ? '…' : '')
510
+ return { fixable: false, reason: `token 多处命中且最优两行同分(候选行号:${shown}),歧义需人工确认(D-006 保守默认)` }
511
+ }
512
+
513
+ /**
514
+ * 将可确定性修复的失效引用写回文档(--fix 消费面,design §7 接口逐字)。
515
+ * 纯机械定点替换:按 docLine + ref 串在该行内的字符偏移替换为 newRef,不解析行号语义、
516
+ * 不改引用文件名与 token(D-003:ref/newRef 一致性由调用方保证);候选定位全部依赖调用方
517
+ * 传入(不读 local.yaml 不解析配置)。范围引用(src/a.js:3-8)newRef 同样由调用方给全串。
518
+ * 同一行多个 fix 按行内偏移从后往前(降序)替换,防前序替换挤偏后序偏移(R-04);
519
+ * 其余字节不动:行内容只动命中片段,行结束符按原文(\r\n / \n 整文件统一口径)原样 join(R-05)。
520
+ * @param {string} projectRoot 源码仓根(doc 相对路径的锚点)
521
+ * @param {Array<{doc: string, docLine: number, ref: string, newRef: string}>} fixes
522
+ * doc 为相对 projectRoot 的文档路径;ref 旧引用串(如 src/a.js:6),newRef 新引用串(如 src/a.js:1)
523
+ * @param {{dryRun?: boolean}} opts dryRun 为真时不写盘仅返回将应用列表
524
+ * @returns {{applied: number, skipped: Array<{ref: string, reason: string}>}}
525
+ * dryRun 时 applied 为「将应用」计数;skipped 条目含 ref 与可读 reason(文档不存在/docLine 越界/
526
+ * 行内找不到 ref 串),跳过不中断批量
527
+ */
528
+ export function applyFixes(projectRoot, fixes, opts = {}) {
529
+ const dryRun = opts.dryRun === true
530
+ let applied = 0
531
+ const skipped = []
532
+ if (!Array.isArray(fixes) || fixes.length === 0) return { applied, skipped }
533
+
534
+ // 按 doc 分组,每文档一次读改写(design §9:普通 writeFileSync,文档非运行时竞争文件)
535
+ const byDoc = new Map()
536
+ for (const f of fixes) {
537
+ if (!f || typeof f !== 'object' || typeof f.doc !== 'string' || typeof f.docLine !== 'number' ||
538
+ typeof f.ref !== 'string' || typeof f.newRef !== 'string') {
539
+ skipped.push({ ref: f && typeof f.ref === 'string' ? f.ref : '(条目缺失)', reason: 'fix 条目字段不完整(doc/docLine/ref/newRef)' })
540
+ continue
541
+ }
542
+ if (!byDoc.has(f.doc)) byDoc.set(f.doc, [])
543
+ byDoc.get(f.doc).push(f)
544
+ }
545
+
546
+ for (const [docRel, docFixes] of byDoc) {
547
+ const docAbs = join(projectRoot, docRel)
548
+ if (!existsSync(docAbs)) {
549
+ for (const f of docFixes) skipped.push({ ref: f.ref, reason: `文档不存在:${docRel}` })
550
+ continue
551
+ }
552
+ const raw = readFileSync(docAbs, 'utf8')
553
+ // 行结束符检测整文件统一口径(R-05):原文含 \r\n 则 CRLF join,否则 LF——与 readLines 归一逻辑一致
554
+ const eol = raw.includes('\r\n') ? '\r\n' : '\n'
555
+ const lines = raw.split(/\r?\n/)
556
+ let dirty = false
557
+
558
+ // 同一 docLine 的多 fix 按行内偏移从后往前替换(R-04):先按 docLine 分组,
559
+ // 组内按 ref 在该行内的命中偏移降序逐个定点替换
560
+ const byLine = new Map()
561
+ for (const f of docFixes) {
562
+ if (!byLine.has(f.docLine)) byLine.set(f.docLine, [])
563
+ byLine.get(f.docLine).push(f)
564
+ }
565
+ for (const [docLine, lineFixes] of byLine) {
566
+ if (!Number.isInteger(docLine) || docLine < 1 || docLine > lines.length) {
567
+ for (const f of lineFixes) skipped.push({ ref: f.ref, reason: `docLine=${docLine} 越界(文档共 ${lines.length} 行)` })
568
+ continue
569
+ }
570
+ const li = docLine - 1
571
+ const located = []
572
+ let cursor = 0
573
+ for (const f of lineFixes) {
574
+ // 找不到 ref 串、或两次命中同一偏移(重复 fix),该条目跳过不中断批量
575
+ const at = lines[li].indexOf(f.ref, cursor)
576
+ if (at === -1) {
577
+ skipped.push({ ref: f.ref, reason: `docLine=${docLine} 行内未找到引用串` })
578
+ } else {
579
+ located.push({ at, f })
580
+ cursor = at + f.ref.length
581
+ }
582
+ }
583
+ located.sort((a, b) => b.at - a.at) // 降序:后位先替换,前序替换不挤偏后序偏移
584
+ let line = lines[li]
585
+ for (const { at, f } of located) {
586
+ line = line.slice(0, at) + f.newRef + line.slice(at + f.ref.length)
587
+ applied++
588
+ }
589
+ if (located.length > 0) {
590
+ lines[li] = line
591
+ dirty = true
592
+ }
593
+ }
594
+
595
+ if (dirty && !dryRun) writeFileSync(docAbs, lines.join(eol))
596
+ }
597
+
598
+ return { applied, skipped }
599
+ }
600
+
601
+ // ---------------------------------------------------------------------------
602
+ // 决策规则族(advisory,change: 2026-08-23-adopt-harness-practices task-05,FR-06 / D-003@v1)
603
+ //
604
+ // 校验对象:knowledge/decisions/<模块域>.md 的 D-xxx@vN 条目(producer = decision-distill
605
+ // 归档提炼,条目字段行 状态/锚点/最近确认 是本处的机械解析契约)。两项规则:
606
+ // 1) 锚点校验:implemented 条目「锚点:src/…」路径存在性(锚点:未记录 → 补录提示,非失效);
607
+ // 2) behind 复核:锚定模块源码在「最近确认」commit 后的前进数超阈值 → 决策待复核提示
608
+ // (computeModuleBehind 复用 docs-debt 既有 git 口径,C-10)。
609
+ // 铁律(docs-consistency 模块卡):advisory 只 warn 不进 runDocsCheck 的 invalid 阻断链——
610
+ // ok/invalid 判定与 docs gate 阻断行为不受影响;校验链路只读零写盘;无 decisions 库 /
611
+ // 无超阈 → findings 空(无信号零输出)。豁免走 known_failures 新键 decisions.* 命名空间
612
+ // (C-17:条目级语义键匹配,不复用 docs-gate 的 baseline ratchet)。
613
+ // ---------------------------------------------------------------------------
614
+
615
+ /** behind 复核缺省阈值(local.yaml decisions.behind_threshold 可调;schema 注册归 task-11,
616
+ * 本处读键按「存在则读、不存在用缺省」容错,不依赖 schema 注册)。dogfood 校准前取 10。 */
617
+ export const DECISIONS_DEFAULT_BEHIND_THRESHOLD = 10
618
+
619
+ /**
620
+ * known_failures 键提取——读法逐字对齐 verify-postcheck.extractKnownFailures(块式 + 流式,
621
+ * 剥引号/行内注释,CRLF 归一;注释互指防两处口径漂移)。此处独立复刻不 import
622
+ * verify-postcheck(重模块静态依赖;本模块仅消费 decisions.* 前缀键,见 isDecisionExempt)。
623
+ * @param {string} yamlText local.yaml 全文
624
+ * @returns {string[]} 键列表;无声明返回 []
625
+ */
626
+ function extractKnownFailureKeys(yamlText) {
627
+ if (!yamlText) return []
628
+ const yaml = String(yamlText).replace(/\r\n?/g, '\n')
629
+ const inline = yaml.match(/^known_failures:\s*\[([^\]]*)\]\s*(?:#.*)?$/m)
630
+ if (inline) {
631
+ return inline[1].split(',').map(s => s.trim().replace(/^['"]|['"]$/g, '')).filter(Boolean)
632
+ }
633
+ const block = yaml.match(/^known_failures:\s*\n((?:[ \t]+-[ \t].+\n?)+)/m)
634
+ if (block) {
635
+ return (block[1].match(/^[ \t]+-[ \t]+(.+)/gm) || [])
636
+ .map(s => s.replace(/^[ \t]+-[ \t]+/, '').trim().replace(/^['"]|['"]$/g, '').replace(/#.*$/, '').trim())
637
+ .filter(Boolean)
638
+ }
639
+ return []
640
+ }
641
+
642
+ /**
643
+ * 读 local.yaml 的决策规则配置(best-effort 绝不抛;读取模式与 readDocsCheckConfig 一致:
644
+ * 缺文件/无段 → 全缺省)。decisions.behind_threshold 存在则读(数值校验),不存在用缺省 10
645
+ * ——schema 注册(config-schema.js)归 task-11,本处不依赖。
646
+ * @param {string} projectRoot 源码仓根(local.yaml 在 <root>/.sillyspec/local.yaml)
647
+ * @returns {{ behindThreshold: number, knownFailures: string[] }}
648
+ */
649
+ export function readDecisionRulesConfig(projectRoot) {
650
+ const fallback = { behindThreshold: DECISIONS_DEFAULT_BEHIND_THRESHOLD, knownFailures: [] }
651
+ try {
652
+ const p = join(projectRoot, '.sillyspec', 'local.yaml')
653
+ if (!existsSync(p)) return fallback
654
+ const raw = readFileSync(p, 'utf8')
655
+ const knownFailures = extractKnownFailureKeys(raw)
656
+ const doc = jsYaml.load(raw)
657
+ if (!doc || typeof doc !== 'object') return { ...fallback, knownFailures }
658
+ const d = doc['decisions']
659
+ if (!d || typeof d !== 'object' || Array.isArray(d)) return { ...fallback, knownFailures }
660
+ const t = d['behind_threshold']
661
+ return {
662
+ behindThreshold: typeof t === 'number' && Number.isFinite(t) && t > 0 ? t : fallback.behindThreshold,
663
+ knownFailures,
664
+ }
665
+ } catch {
666
+ return fallback
667
+ }
668
+ }
669
+
670
+ /** 豁免键匹配(本变更范围先支持键匹配,非子串):规则级 `decisions.<id>.<kind>` 精确命中,
671
+ * 或条目级 `decisions.<id>` 伞形命中(一条豁免该决策全部规则)。无 decisions. 前缀的键不参与。 */
672
+ function isDecisionExempt(knownFailures, entryId, kind) {
673
+ const ruleKey = `decisions.${entryId}.${kind}`
674
+ const entryKey = `decisions.${entryId}`
675
+ return knownFailures.some(k => k === ruleKey || k === entryKey)
676
+ }
677
+
678
+ /**
679
+ * 纯函数:解析 knowledge/decisions/<域>.md 的 D-xxx@vN 条目(与 decision-distill.renderBlockLines
680
+ * 的写入契约对偶:producer=decision-distill → consumer=本规则族;字段行非列表项,顶层
681
+ * 「状态:/锚点:/最近确认:」标签精确匹配,防误吞正文)。旧格式字段缺失容错为 null。
682
+ * @param {string} md 域文件全文
683
+ * @returns {Array<{ id: string, title: string, status: string|null, anchor: string|null, lastConfirmed: string|null }>}
684
+ */
685
+ export function parseDecisionEntries(md) {
686
+ const entries = []
687
+ let cur = null
688
+ const flush = () => { if (cur) entries.push(cur) }
689
+ for (const line of String(md || '').replace(/\r\n?/g, '\n').split('\n')) {
690
+ const h = line.match(/^##\s+(D-\d+)(?:@v(\d+))?\s*(.*)$/)
691
+ if (h) {
692
+ flush()
693
+ const version = h[2] ? parseInt(h[2], 10) : 1
694
+ cur = { id: `${h[1]}@v${version}`, title: h[3].trim(), status: null, anchor: null, lastConfirmed: null }
695
+ continue
696
+ }
697
+ if (!cur) continue
698
+ const f = line.match(/^(状态|锚点|最近确认)\s*[::]\s*(.*)$/)
699
+ if (!f) continue
700
+ if (f[1] === '状态') cur.status = f[2].trim().split(/[\s((]/)[0] || null
701
+ else if (f[1] === '锚点') cur.anchor = f[2].trim()
702
+ else cur.lastConfirmed = f[2].trim()
703
+ }
704
+ flush()
705
+ return entries
706
+ }
707
+
708
+ /** 锚点值 → 源码路径:剥「:行号 / :行号-行号 / :符号」后缀(锚点契约 `<src 路径>:<行号或符号>`;
709
+ * 旧条目可能只写路径)。「未记录」/空 → null(补录提示路径,非失效)。
710
+ * export(2026-08-24-decision-touch-cli-drift task-01):docs-debt.computeDecisionTouches
711
+ * 复用同一剥离口径(勿复刻正则防两处漂移);仅加关键字,行为不变。 */
712
+ export function anchorFilePath(anchor) {
713
+ const a = String(anchor || '').trim()
714
+ if (!a || a === '未记录') return null
715
+ return a.replace(/:(?:\d+(?:-\d+)?|[A-Za-z_$][A-Za-z0-9_$]*)$/, '').replace(/\\/g, '/') || null
716
+ }
717
+
718
+ /** specBase/docs 下任一项目的 modules/_module-map.yaml 尽力发现(对齐
719
+ * decision-distill.discoverModuleIndex 口径:首个命中;失败 → null,域模块源码集退化为锚点文件兜底)。 */
720
+ function discoverModuleMapIndex(specBase) {
721
+ try {
722
+ const docsDir = join(specBase, 'docs')
723
+ if (!existsSync(docsDir)) return null
724
+ for (const d of readdirSync(docsDir, { withFileTypes: true })) {
725
+ if (!d.isDirectory()) continue
726
+ const mapPath = join(docsDir, d.name, 'modules', '_module-map.yaml')
727
+ if (existsSync(mapPath)) return parseModuleMapSimple(readFileSync(mapPath, 'utf8'))
728
+ }
729
+ } catch { /* 尽力而为,失败归 null */ }
730
+ return null
731
+ }
732
+
733
+ /**
734
+ * IO 入口(advisory):跑一次决策规则族。只产出 findings(warn 语义),不进 runDocsCheck 的
735
+ * invalid 阻断链、不写任何文件——无 decisions 库 / 无信号 → findings 空(零输出)。
736
+ * computeModuleBehind 经动态 import 取自 docs-debt(本模块被 docs-debt 静态 import,静态互引
737
+ * 成 ESM 环——对齐 run/shared.js 对 docs-debt 的动态 import 先例)。
738
+ * @param {{ projectRoot: string, specBase?: string, behindThreshold?: number, knownFailures?: string[], moduleIndex?: object|null }} opts
739
+ * projectRoot 源码仓根(锚点解析与 git 锚);specBase 缺省 = <projectRoot>/.sillyspec;
740
+ * behindThreshold / knownFailures 缺省读 local.yaml(decisions.behind_threshold / known_failures);
741
+ * moduleIndex 缺省按 specBase/docs 下任一项目的 modules/_module-map.yaml 尽力发现
742
+ * @returns {Promise<{ empty: boolean, domains: number, entries: number, implemented: number,
743
+ * threshold: number, findings: Array<{ id: string, domain: string, file: string,
744
+ * kind: 'anchor'|'behind', behind?: number|null, threshold?: number, anchor?: string|null,
745
+ * message: string }>, exempted: Array<{ key: string, id: string, kind: string }> }>}
746
+ * empty=true = decisions 库不存在(冷启动,R-02 由 doctor 层提示);exempted 为经
747
+ * known_failures decisions.* 键豁免的条目(披露不隐藏)
748
+ */
749
+ export async function runDecisionRules(opts) {
750
+ const { projectRoot, specBase, behindThreshold = null, knownFailures = null, moduleIndex = null } = opts || {}
751
+ const emptyResult = (threshold) => ({ empty: true, domains: 0, entries: 0, implemented: 0, threshold, findings: [], exempted: [] })
752
+ if (!projectRoot) return emptyResult(DECISIONS_DEFAULT_BEHIND_THRESHOLD)
753
+
754
+ const cfg = readDecisionRulesConfig(projectRoot)
755
+ const threshold = typeof behindThreshold === 'number' && Number.isFinite(behindThreshold) && behindThreshold > 0
756
+ ? behindThreshold
757
+ : cfg.behindThreshold
758
+ const failures = Array.isArray(knownFailures) ? knownFailures : cfg.knownFailures
759
+
760
+ const kb = specBase || join(projectRoot, '.sillyspec')
761
+ const decisionsDir = join(kb, 'knowledge', 'decisions')
762
+ let domainFiles = []
763
+ try {
764
+ domainFiles = readdirSync(decisionsDir).filter(f => f.endsWith('.md')).sort()
765
+ } catch {
766
+ return emptyResult(threshold) // 库不存在 → 零信号(doctor 层另行提示空库)
767
+ }
768
+
769
+ // 模块域 → 源码路径集(module-map paths∪core_files;未命中 map 的域退化为锚点文件兜底)
770
+ const mapIndex = moduleIndex || discoverModuleMapIndex(kb)
771
+ const flatIndex = mapIndex && mapIndex.modules ? mapIndex.modules : mapIndex
772
+ const { computeModuleBehind } = await import('./docs-debt.js')
773
+
774
+ const findings = []
775
+ const exempted = []
776
+ let entriesTotal = 0
777
+ let implementedTotal = 0
778
+ const treeCache = new Map() // resolveCandidates 全树扫描复用(同 docs check 主链路口径)
779
+
780
+ const emit = (id, domain, file, kind, extra, message) => {
781
+ if (isDecisionExempt(failures, id, kind)) {
782
+ exempted.push({ key: `decisions.${id}.${kind}`, id, kind })
783
+ return
784
+ }
785
+ findings.push({ id, domain, file, kind, ...extra, message })
786
+ }
787
+
788
+ for (const f of domainFiles) {
789
+ const domain = f.replace(/\.md$/, '')
790
+ const rel = `knowledge/decisions/${f}`
791
+ let entries
792
+ try { entries = parseDecisionEntries(readFileSync(join(decisionsDir, f), 'utf8')) } catch { continue }
793
+ for (const e of entries) {
794
+ entriesTotal++
795
+ if ((e.status || '').toLowerCase() !== 'implemented') continue // rejected/未知状态不做锚点与 behind 校验
796
+ implementedTotal++
797
+ const anchorPath = anchorFilePath(e.anchor)
798
+ // 规则 1:锚点存在性(未记录 → 补录提示;路径不存在 → 失效提示)
799
+ if (!anchorPath) {
800
+ emit(e.id, domain, rel, 'anchor', { anchor: e.anchor || null },
801
+ `「${e.id}」锚点未记录(${rel})——旧格式条目,补「锚点:src/…」后可机械校验(advisory)`)
802
+ } else if (resolveCandidates(projectRoot, anchorPath, treeCache).length === 0) {
803
+ emit(e.id, domain, rel, 'anchor', { anchor: e.anchor },
804
+ `「${e.id}」锚点文件不存在:${anchorPath}(${rel})——决策落点已漂移,人工复核(advisory)`)
805
+ }
806
+ // 规则 2:behind 复核(「最近确认」后锚定模块源码前进数超阈值 → 决策待复核;
807
+ // 「最近确认」未记录/域无源码集(无 map 无锚点)→ 无法计算,静默跳过——advisory 不产噪声)
808
+ if (!e.lastConfirmed || !/^[0-9a-f]{4,40}$/i.test(e.lastConfirmed)) continue
809
+ let srcPaths = null
810
+ const m = flatIndex && typeof flatIndex === 'object' ? flatIndex[domain] : null
811
+ if (m) srcPaths = [...(Array.isArray(m.paths) ? m.paths : []), ...(Array.isArray(m.core_files) ? m.core_files : [])]
812
+ if ((!srcPaths || srcPaths.length === 0) && anchorPath) srcPaths = [anchorPath]
813
+ if (!srcPaths || srcPaths.length === 0) continue
814
+ const { behind } = computeModuleBehind(domain, e.lastConfirmed, { projectRoot, srcPaths })
815
+ if (behind !== null && behind > threshold) {
816
+ emit(e.id, domain, rel, 'behind', { behind, threshold },
817
+ `「${e.id}」决策待复核:锚定模块 ${domain} 在最近确认 ${e.lastConfirmed} 后源码已前进 ${behind} commit,超阈值 ${threshold}(${rel})——复核后更新「最近确认」`)
818
+ }
819
+ }
820
+ }
821
+
822
+ findings.sort((a, b) => a.file.localeCompare(b.file) || a.id.localeCompare(b.id))
823
+ exempted.sort((a, b) => a.key.localeCompare(b.key))
824
+ return { empty: false, domains: domainFiles.length, entries: entriesTotal, implemented: implementedTotal, threshold, findings, exempted }
825
+ }