dsh-compound-engineering 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -2
  3. package/README.zh.md +161 -0
  4. package/cordis.patch.yml +6 -0
  5. package/lib/frontmatter.js +167 -0
  6. package/lib/index.js +46 -0
  7. package/lib/provider.js +201 -0
  8. package/package.json +62 -4
  9. package/skills/CODING_STANDARDS.md +68 -0
  10. package/skills/ce-babysit-pr/SKILL.md +59 -0
  11. package/skills/ce-babysit-pr/references/branch-currency.md +22 -0
  12. package/skills/ce-babysit-pr/references/envelope.md +44 -0
  13. package/skills/ce-babysit-pr/references/pipeline.md +15 -0
  14. package/skills/ce-babysit-pr/references/report.md +20 -0
  15. package/skills/ce-babysit-pr/references/settle.md +37 -0
  16. package/skills/ce-babysit-pr/references/setup.md +33 -0
  17. package/skills/ce-babysit-pr/references/stack-commands.md +39 -0
  18. package/skills/ce-babysit-pr/references/stack.md +43 -0
  19. package/skills/ce-babysit-pr/references/tick.md +102 -0
  20. package/skills/ce-babysit-pr/references/watch-loop.md +222 -0
  21. package/skills/ce-babysit-pr/scripts/pr-snapshot +3656 -0
  22. package/skills/ce-bakeoff/SKILL.md +48 -0
  23. package/skills/ce-bakeoff/references/candidates.md +37 -0
  24. package/skills/ce-bakeoff/references/judging.md +19 -0
  25. package/skills/ce-bakeoff/references/output.md +11 -0
  26. package/skills/ce-bakeoff/references/verification.md +15 -0
  27. package/skills/ce-brainstorm/SKILL.md +69 -0
  28. package/skills/ce-brainstorm/references/agents/slack-researcher.md +127 -0
  29. package/skills/ce-brainstorm/references/approaches.md +57 -0
  30. package/skills/ce-brainstorm/references/bakeoff.md +9 -0
  31. package/skills/ce-brainstorm/references/blindspot-pass.md +70 -0
  32. package/skills/ce-brainstorm/references/brainstorm-sections.md +458 -0
  33. package/skills/ce-brainstorm/references/dialogue.md +89 -0
  34. package/skills/ce-brainstorm/references/handoff.md +187 -0
  35. package/skills/ce-brainstorm/references/html-rendering.md +638 -0
  36. package/skills/ce-brainstorm/references/interaction-rules.md +33 -0
  37. package/skills/ce-brainstorm/references/markdown-rendering.md +242 -0
  38. package/skills/ce-brainstorm/references/model-tiers.md +13 -0
  39. package/skills/ce-brainstorm/references/output-mode.md +26 -0
  40. package/skills/ce-brainstorm/references/phase-0.md +104 -0
  41. package/skills/ce-brainstorm/references/plan-write.md +32 -0
  42. package/skills/ce-brainstorm/references/product-pressure-test.md +42 -0
  43. package/skills/ce-brainstorm/references/reasoning-elevation.md +124 -0
  44. package/skills/ce-brainstorm/references/settled-decisions.md +45 -0
  45. package/skills/ce-brainstorm/references/synthesis-summary.md +149 -0
  46. package/skills/ce-brainstorm/references/universal-brainstorming.md +72 -0
  47. package/skills/ce-brainstorm/references/verdict-routing.md +26 -0
  48. package/skills/ce-brainstorm/references/visual-probes.md +164 -0
  49. package/skills/ce-brainstorm/scripts/elevation-dispatch.sh +288 -0
  50. package/skills/ce-brainstorm/scripts/light-webserver.js +1275 -0
  51. package/skills/ce-brainstorm/scripts/packs-resolve.py +737 -0
  52. package/skills/ce-brainstorm/scripts/peer-job-runner.py +2594 -0
  53. package/skills/ce-code-review/SKILL.md +40 -0
  54. package/skills/ce-code-review/references/action-class-rubric.md +67 -0
  55. package/skills/ce-code-review/references/cross-model-recovery.md +38 -0
  56. package/skills/ce-code-review/references/cross-model-review.md +191 -0
  57. package/skills/ce-code-review/references/depth-paths.md +32 -0
  58. package/skills/ce-code-review/references/diff-scope.md +59 -0
  59. package/skills/ce-code-review/references/dispatch-reviewers.md +135 -0
  60. package/skills/ce-code-review/references/findings-schema.json +125 -0
  61. package/skills/ce-code-review/references/finish-input.md +118 -0
  62. package/skills/ce-code-review/references/finish-review.md +202 -0
  63. package/skills/ce-code-review/references/intent-and-plan.md +73 -0
  64. package/skills/ce-code-review/references/modes-and-output.md +156 -0
  65. package/skills/ce-code-review/references/persona-catalog.md +66 -0
  66. package/skills/ce-code-review/references/personas/adversarial-reviewer.md +111 -0
  67. package/skills/ce-code-review/references/personas/agent-native-reviewer.md +173 -0
  68. package/skills/ce-code-review/references/personas/api-contract-reviewer.md +44 -0
  69. package/skills/ce-code-review/references/personas/correctness-reviewer.md +48 -0
  70. package/skills/ce-code-review/references/personas/data-migration-reviewer.md +111 -0
  71. package/skills/ce-code-review/references/personas/deployment-verification-agent.md +157 -0
  72. package/skills/ce-code-review/references/personas/julik-frontend-races-reviewer.md +45 -0
  73. package/skills/ce-code-review/references/personas/learnings-researcher.md +260 -0
  74. package/skills/ce-code-review/references/personas/maintainability-reviewer.md +85 -0
  75. package/skills/ce-code-review/references/personas/performance-reviewer.md +45 -0
  76. package/skills/ce-code-review/references/personas/previous-comments-reviewer.md +59 -0
  77. package/skills/ce-code-review/references/personas/project-standards-reviewer.md +77 -0
  78. package/skills/ce-code-review/references/personas/reliability-reviewer.md +49 -0
  79. package/skills/ce-code-review/references/personas/security-reviewer.md +50 -0
  80. package/skills/ce-code-review/references/personas/swift-ios-reviewer.md +99 -0
  81. package/skills/ce-code-review/references/personas/testing-reviewer.md +51 -0
  82. package/skills/ce-code-review/references/review-output-template.md +172 -0
  83. package/skills/ce-code-review/references/scope.md +176 -0
  84. package/skills/ce-code-review/references/select-and-route.md +93 -0
  85. package/skills/ce-code-review/references/subagent-template.md +206 -0
  86. package/skills/ce-code-review/references/validator-batch-template.md +67 -0
  87. package/skills/ce-code-review/scripts/cross-model-adversarial-review.sh +1275 -0
  88. package/skills/ce-code-review/scripts/findings-mechanics.py +274 -0
  89. package/skills/ce-code-review/scripts/packs-resolve.py +737 -0
  90. package/skills/ce-code-review/scripts/peer-job-runner.py +2594 -0
  91. package/skills/ce-code-review/scripts/review-scope.py +419 -0
  92. package/skills/ce-code-review/scripts/run-log.py +280 -0
  93. package/skills/ce-commit/SKILL.md +60 -0
  94. package/skills/ce-commit-push-pr/SKILL.md +69 -0
  95. package/skills/ce-commit-push-pr/references/apply-and-handoff.md +79 -0
  96. package/skills/ce-commit-push-pr/references/branch-creation.md +47 -0
  97. package/skills/ce-commit-push-pr/references/commit-and-push.md +26 -0
  98. package/skills/ce-commit-push-pr/references/compose.md +29 -0
  99. package/skills/ce-commit-push-pr/references/context.md +42 -0
  100. package/skills/ce-commit-push-pr/references/gh-stack-cli.md +83 -0
  101. package/skills/ce-commit-push-pr/references/pr-description-writing.md +208 -0
  102. package/skills/ce-commit-push-pr/references/stack-submit.md +81 -0
  103. package/skills/ce-compound/SKILL.md +79 -0
  104. package/skills/ce-compound/assets/resolution-template.md +96 -0
  105. package/skills/ce-compound/references/agents/best-practices-researcher.md +115 -0
  106. package/skills/ce-compound/references/agents/data-integrity-guardian.md +68 -0
  107. package/skills/ce-compound/references/agents/framework-docs-researcher.md +93 -0
  108. package/skills/ce-compound/references/agents/pattern-recognition-specialist.md +55 -0
  109. package/skills/ce-compound/references/agents/performance-oracle.md +108 -0
  110. package/skills/ce-compound/references/agents/security-sentinel.md +91 -0
  111. package/skills/ce-compound/references/agents/session-historian.md +82 -0
  112. package/skills/ce-compound/references/assembly.md +127 -0
  113. package/skills/ce-compound/references/concepts-vocabulary.md +98 -0
  114. package/skills/ce-compound/references/enhancement.md +42 -0
  115. package/skills/ce-compound/references/grounding-validation.md +89 -0
  116. package/skills/ce-compound/references/lightweight.md +56 -0
  117. package/skills/ce-compound/references/modes.md +13 -0
  118. package/skills/ce-compound/references/refresh-and-discoverability.md +96 -0
  119. package/skills/ce-compound/references/report.md +115 -0
  120. package/skills/ce-compound/references/research.md +144 -0
  121. package/skills/ce-compound/references/schema.yaml +236 -0
  122. package/skills/ce-compound/references/session-history.md +73 -0
  123. package/skills/ce-compound/references/yaml-schema.md +130 -0
  124. package/skills/ce-compound/scripts/packs-resolve.py +737 -0
  125. package/skills/ce-compound/scripts/session-history/__pycache__/dsh_session.cpython-314.pyc +0 -0
  126. package/skills/ce-compound/scripts/session-history/discover-sessions.sh +290 -0
  127. package/skills/ce-compound/scripts/session-history/discover_dsh.py +123 -0
  128. package/skills/ce-compound/scripts/session-history/dsh_session.py +225 -0
  129. package/skills/ce-compound/scripts/session-history/extract-errors.py +178 -0
  130. package/skills/ce-compound/scripts/session-history/extract-metadata.py +301 -0
  131. package/skills/ce-compound/scripts/session-history/extract-skeleton.py +346 -0
  132. package/skills/ce-compound/scripts/validate-doc-claims.py +497 -0
  133. package/skills/ce-compound/scripts/validate-frontmatter.py +137 -0
  134. package/skills/ce-compound-refresh/SKILL.md +88 -0
  135. package/skills/ce-compound-refresh/assets/resolution-template.md +96 -0
  136. package/skills/ce-compound-refresh/references/classify.md +42 -0
  137. package/skills/ce-compound-refresh/references/commit.md +7 -0
  138. package/skills/ce-compound-refresh/references/concepts-vocabulary.md +116 -0
  139. package/skills/ce-compound-refresh/references/discoverability.md +15 -0
  140. package/skills/ce-compound-refresh/references/investigate.md +23 -0
  141. package/skills/ce-compound-refresh/references/modes.md +27 -0
  142. package/skills/ce-compound-refresh/references/per-action-flows.md +142 -0
  143. package/skills/ce-compound-refresh/references/report.md +23 -0
  144. package/skills/ce-compound-refresh/references/schema.yaml +236 -0
  145. package/skills/ce-compound-refresh/references/scope.md +18 -0
  146. package/skills/ce-compound-refresh/references/worth-audit.md +35 -0
  147. package/skills/ce-compound-refresh/references/yaml-schema.md +130 -0
  148. package/skills/ce-compound-refresh/scripts/validate-doc-claims.py +497 -0
  149. package/skills/ce-compound-refresh/scripts/validate-frontmatter.py +137 -0
  150. package/skills/ce-debug/SKILL.md +122 -0
  151. package/skills/ce-debug/references/anti-patterns.md +91 -0
  152. package/skills/ce-debug/references/defense-in-depth.md +39 -0
  153. package/skills/ce-debug/references/fix.md +21 -0
  154. package/skills/ce-debug/references/investigate.md +114 -0
  155. package/skills/ce-debug/references/investigation-techniques.md +384 -0
  156. package/skills/ce-debug/references/pipeline-mode.md +78 -0
  157. package/skills/ce-debug/references/post-fix-handoff.md +60 -0
  158. package/skills/ce-debug/references/return-to-caller.md +57 -0
  159. package/skills/ce-doc-review/SKILL.md +75 -0
  160. package/skills/ce-doc-review/references/bulk-preview.md +146 -0
  161. package/skills/ce-doc-review/references/cross-model-review.md +207 -0
  162. package/skills/ce-doc-review/references/decision-primer.md +47 -0
  163. package/skills/ce-doc-review/references/dispatch.md +56 -0
  164. package/skills/ce-doc-review/references/document-intake.md +44 -0
  165. package/skills/ce-doc-review/references/findings-schema.json +85 -0
  166. package/skills/ce-doc-review/references/modes.md +20 -0
  167. package/skills/ce-doc-review/references/open-questions-defer.md +158 -0
  168. package/skills/ce-doc-review/references/persona-selection.md +41 -0
  169. package/skills/ce-doc-review/references/personas/adversarial-document-reviewer.md +109 -0
  170. package/skills/ce-doc-review/references/personas/coherence-reviewer.md +69 -0
  171. package/skills/ce-doc-review/references/personas/design-lens-reviewer.md +48 -0
  172. package/skills/ce-doc-review/references/personas/feasibility-reviewer.md +50 -0
  173. package/skills/ce-doc-review/references/personas/product-lens-reviewer.md +85 -0
  174. package/skills/ce-doc-review/references/personas/scope-guardian-reviewer.md +83 -0
  175. package/skills/ce-doc-review/references/personas/security-lens-reviewer.md +41 -0
  176. package/skills/ce-doc-review/references/personas/whole-doc-reviewer.md +25 -0
  177. package/skills/ce-doc-review/references/rendering-floor.md +175 -0
  178. package/skills/ce-doc-review/references/review-output-template.md +123 -0
  179. package/skills/ce-doc-review/references/subagent-template.md +188 -0
  180. package/skills/ce-doc-review/references/synthesis-and-presentation.md +350 -0
  181. package/skills/ce-doc-review/references/walkthrough.md +347 -0
  182. package/skills/ce-doc-review/scripts/cross-model-doc-review.sh +1270 -0
  183. package/skills/ce-doc-review/scripts/packs-resolve.py +737 -0
  184. package/skills/ce-doc-review/scripts/peer-job-runner.py +2594 -0
  185. package/skills/ce-dogfood/SKILL.md +66 -0
  186. package/skills/ce-dogfood/agents/openai.yaml +2 -0
  187. package/skills/ce-dogfood/references/dogfood-report-template.md +97 -0
  188. package/skills/ce-dogfood/references/phases.md +167 -0
  189. package/skills/ce-dogfood/references/test-matrix-taxonomy.md +62 -0
  190. package/skills/ce-dogfood/scripts/packs-resolve.py +737 -0
  191. package/skills/ce-explain/SKILL.md +81 -0
  192. package/skills/ce-explain/references/agents/behavior-trace-scout.md +19 -0
  193. package/skills/ce-explain/references/agents/work-recap-scout.md +23 -0
  194. package/skills/ce-explain/references/check-in.md +18 -0
  195. package/skills/ce-explain/references/destinations.md +35 -0
  196. package/skills/ce-explain/references/explainer-html.md +29 -0
  197. package/skills/ce-explain/references/explainer-markdown.md +24 -0
  198. package/skills/ce-explain/references/intake.md +50 -0
  199. package/skills/ce-explain/references/orchestration.md +46 -0
  200. package/skills/ce-handoff/SKILL.md +54 -0
  201. package/skills/ce-handoff/references/create.md +88 -0
  202. package/skills/ce-handoff/references/resume.md +46 -0
  203. package/skills/ce-ideate/SKILL.md +75 -0
  204. package/skills/ce-ideate/references/agents/issue-intelligence-analyst.md +166 -0
  205. package/skills/ce-ideate/references/agents/learnings-researcher.md +247 -0
  206. package/skills/ce-ideate/references/agents/slack-researcher.md +127 -0
  207. package/skills/ce-ideate/references/agents/web-researcher.md +121 -0
  208. package/skills/ce-ideate/references/decomposition.md +39 -0
  209. package/skills/ce-ideate/references/divergent-ideation.md +112 -0
  210. package/skills/ce-ideate/references/grounding.md +138 -0
  211. package/skills/ce-ideate/references/html-rendering.md +638 -0
  212. package/skills/ce-ideate/references/ideation-sections.md +191 -0
  213. package/skills/ce-ideate/references/issue-intelligence.md +44 -0
  214. package/skills/ce-ideate/references/markdown-rendering.md +242 -0
  215. package/skills/ce-ideate/references/output-mode.md +34 -0
  216. package/skills/ce-ideate/references/post-ideation-workflow.md +169 -0
  217. package/skills/ce-ideate/references/scope-gates.md +148 -0
  218. package/skills/ce-ideate/references/universal-ideation.md +119 -0
  219. package/skills/ce-ideate/references/user-research-artifacts.md +28 -0
  220. package/skills/ce-ideate/references/web-research-cache.md +56 -0
  221. package/skills/ce-noslop/SKILL.md +45 -0
  222. package/skills/ce-noslop/references/patterns.md +61 -0
  223. package/skills/ce-noslop/references/terminology.md +3 -0
  224. package/skills/ce-optimize/SKILL.md +64 -0
  225. package/skills/ce-optimize/references/agents/learnings-researcher.md +247 -0
  226. package/skills/ce-optimize/references/agents/repo-research-analyst.md +258 -0
  227. package/skills/ce-optimize/references/example-expensive-benchmark-spec.yaml +88 -0
  228. package/skills/ce-optimize/references/example-hard-spec.yaml +64 -0
  229. package/skills/ce-optimize/references/example-judge-spec.yaml +83 -0
  230. package/skills/ce-optimize/references/example-text-target-spec.yaml +80 -0
  231. package/skills/ce-optimize/references/experiment-log-schema.yaml +563 -0
  232. package/skills/ce-optimize/references/experiment-prompt-template.md +143 -0
  233. package/skills/ce-optimize/references/judge-prompt-template.md +117 -0
  234. package/skills/ce-optimize/references/loop.md +286 -0
  235. package/skills/ce-optimize/references/measurement.md +168 -0
  236. package/skills/ce-optimize/references/optimize-spec-schema.yaml +570 -0
  237. package/skills/ce-optimize/references/persistence.md +93 -0
  238. package/skills/ce-optimize/references/spec.md +107 -0
  239. package/skills/ce-optimize/references/text-targets.md +51 -0
  240. package/skills/ce-optimize/references/usage-guide.md +147 -0
  241. package/skills/ce-optimize/references/wrap-up.md +54 -0
  242. package/skills/ce-optimize/scripts/decide.mjs +676 -0
  243. package/skills/ce-optimize/scripts/experiment-worktree.sh +330 -0
  244. package/skills/ce-optimize/scripts/measure.sh +140 -0
  245. package/skills/ce-optimize/scripts/parallel-probe.sh +134 -0
  246. package/skills/ce-plan/SKILL.md +60 -0
  247. package/skills/ce-plan/references/agents/agent-native-planning-strategist.md +66 -0
  248. package/skills/ce-plan/references/agents/architecture-strategist.md +46 -0
  249. package/skills/ce-plan/references/agents/best-practices-researcher.md +118 -0
  250. package/skills/ce-plan/references/agents/data-integrity-guardian.md +68 -0
  251. package/skills/ce-plan/references/agents/framework-docs-researcher.md +97 -0
  252. package/skills/ce-plan/references/agents/git-history-analyzer.md +40 -0
  253. package/skills/ce-plan/references/agents/learnings-researcher.md +268 -0
  254. package/skills/ce-plan/references/agents/pattern-recognition-specialist.md +55 -0
  255. package/skills/ce-plan/references/agents/performance-oracle.md +108 -0
  256. package/skills/ce-plan/references/agents/repo-research-analyst.md +262 -0
  257. package/skills/ce-plan/references/agents/security-sentinel.md +91 -0
  258. package/skills/ce-plan/references/agents/slack-researcher.md +131 -0
  259. package/skills/ce-plan/references/agents/spec-flow-analyzer.md +84 -0
  260. package/skills/ce-plan/references/agents/web-researcher.md +125 -0
  261. package/skills/ce-plan/references/approach-altitude.md +55 -0
  262. package/skills/ce-plan/references/bakeoff.md +9 -0
  263. package/skills/ce-plan/references/deepening-workflow.md +263 -0
  264. package/skills/ce-plan/references/final-review.md +134 -0
  265. package/skills/ce-plan/references/html-rendering.md +638 -0
  266. package/skills/ce-plan/references/intake.md +158 -0
  267. package/skills/ce-plan/references/markdown-rendering.md +242 -0
  268. package/skills/ce-plan/references/output-contracts.md +29 -0
  269. package/skills/ce-plan/references/output-mode.md +45 -0
  270. package/skills/ce-plan/references/plan-handoff.md +116 -0
  271. package/skills/ce-plan/references/plan-sections.md +489 -0
  272. package/skills/ce-plan/references/reasoning-elevation.md +124 -0
  273. package/skills/ce-plan/references/research.md +211 -0
  274. package/skills/ce-plan/references/resume.md +61 -0
  275. package/skills/ce-plan/references/settled-decisions.md +45 -0
  276. package/skills/ce-plan/references/structure.md +207 -0
  277. package/skills/ce-plan/references/synthesis-summary.md +260 -0
  278. package/skills/ce-plan/references/universal-planning.md +170 -0
  279. package/skills/ce-plan/scripts/elevation-dispatch.sh +288 -0
  280. package/skills/ce-plan/scripts/packs-resolve.py +737 -0
  281. package/skills/ce-plan/scripts/peer-job-runner.py +2594 -0
  282. package/skills/ce-polish/SKILL.md +22 -0
  283. package/skills/ce-polish/agents/openai.yaml +2 -0
  284. package/skills/ce-polish/references/dev-server-astro.md +58 -0
  285. package/skills/ce-polish/references/dev-server-detection.md +40 -0
  286. package/skills/ce-polish/references/dev-server-next.md +61 -0
  287. package/skills/ce-polish/references/dev-server-nuxt.md +58 -0
  288. package/skills/ce-polish/references/dev-server-procfile.md +59 -0
  289. package/skills/ce-polish/references/dev-server-rails.md +50 -0
  290. package/skills/ce-polish/references/dev-server-remix.md +58 -0
  291. package/skills/ce-polish/references/dev-server-sveltekit.md +58 -0
  292. package/skills/ce-polish/references/dev-server-vite.md +48 -0
  293. package/skills/ce-polish/references/install-riffrec.md +35 -0
  294. package/skills/ce-polish/references/launch-json-schema.md +177 -0
  295. package/skills/ce-polish/references/live-loop.md +98 -0
  296. package/skills/ce-polish/references/live-remote.md +35 -0
  297. package/skills/ce-polish/references/live-start.md +93 -0
  298. package/skills/ce-polish/references/live-stream-contract.md +253 -0
  299. package/skills/ce-polish/references/run.md +67 -0
  300. package/skills/ce-polish/scripts/detect-project-type.sh +277 -0
  301. package/skills/ce-polish/scripts/detect-riffrec.sh +225 -0
  302. package/skills/ce-polish/scripts/live-endpoint.js +2841 -0
  303. package/skills/ce-polish/scripts/read-launch-json.sh +117 -0
  304. package/skills/ce-polish/scripts/resolve-package-manager.sh +95 -0
  305. package/skills/ce-polish/scripts/resolve-port.sh +307 -0
  306. package/skills/ce-pov/SKILL.md +64 -0
  307. package/skills/ce-pov/references/agents/external-evidence-researcher.md +26 -0
  308. package/skills/ce-pov/references/agents/pov-peer.md +43 -0
  309. package/skills/ce-pov/references/agents/precedent-activity-scout.md +21 -0
  310. package/skills/ce-pov/references/agents/project-grounding-scout.md +32 -0
  311. package/skills/ce-pov/references/boundaries.md +36 -0
  312. package/skills/ce-pov/references/cross-model-panel.md +596 -0
  313. package/skills/ce-pov/references/followup.md +9 -0
  314. package/skills/ce-pov/references/grounding.md +47 -0
  315. package/skills/ce-pov/references/intake.md +61 -0
  316. package/skills/ce-pov/references/invocation.md +47 -0
  317. package/skills/ce-pov/references/method.md +68 -0
  318. package/skills/ce-pov/references/pov-schema.json +56 -0
  319. package/skills/ce-pov/references/report.md +7 -0
  320. package/skills/ce-pov/scripts/cross-model-pov.sh +1110 -0
  321. package/skills/ce-pov/scripts/peer-job-runner.py +2594 -0
  322. package/skills/ce-product-pulse/SKILL.md +81 -0
  323. package/skills/ce-product-pulse/agents/openai.yaml +2 -0
  324. package/skills/ce-product-pulse/references/config.md +20 -0
  325. package/skills/ce-product-pulse/references/interview.md +260 -0
  326. package/skills/ce-product-pulse/references/report-template.md +89 -0
  327. package/skills/ce-product-pulse/references/run.md +46 -0
  328. package/skills/ce-product-pulse/references/setup.md +43 -0
  329. package/skills/ce-promote/SKILL.md +90 -0
  330. package/skills/ce-promote/agents/openai.yaml +2 -0
  331. package/skills/ce-promote/references/spiral-cli.md +149 -0
  332. package/skills/ce-proof/SKILL.md +65 -0
  333. package/skills/ce-proof/references/api.md +176 -0
  334. package/skills/ce-proof/references/workflows.md +124 -0
  335. package/skills/ce-prototype/SKILL.md +59 -0
  336. package/skills/ce-prototype/assets/annotate.css +206 -0
  337. package/skills/ce-prototype/assets/annotate.js +837 -0
  338. package/skills/ce-prototype/references/annotation-loop.md +32 -0
  339. package/skills/ce-prototype/references/build.md +39 -0
  340. package/skills/ce-prototype/references/craft-floor.md +43 -0
  341. package/skills/ce-prototype/references/preview.md +118 -0
  342. package/skills/ce-prototype/references/scoping.md +38 -0
  343. package/skills/ce-prototype/references/write-back.md +37 -0
  344. package/skills/ce-prototype/scripts/light-webserver.js +1275 -0
  345. package/skills/ce-resolve-pr-feedback/SKILL.md +60 -0
  346. package/skills/ce-resolve-pr-feedback/references/agents/pr-comment-resolver.md +59 -0
  347. package/skills/ce-resolve-pr-feedback/references/evaluation-rubric.md +141 -0
  348. package/skills/ce-resolve-pr-feedback/references/full-mode.md +336 -0
  349. package/skills/ce-resolve-pr-feedback/references/pipeline-mode.md +23 -0
  350. package/skills/ce-resolve-pr-feedback/references/resume.md +60 -0
  351. package/skills/ce-resolve-pr-feedback/references/return-to-caller.md +111 -0
  352. package/skills/ce-resolve-pr-feedback/references/targeted-mode.md +48 -0
  353. package/skills/ce-resolve-pr-feedback/scripts/get-pr-comments +176 -0
  354. package/skills/ce-resolve-pr-feedback/scripts/get-thread-for-comment +84 -0
  355. package/skills/ce-resolve-pr-feedback/scripts/pending-feedback.py +287 -0
  356. package/skills/ce-resolve-pr-feedback/scripts/reply-to-pr-thread +57 -0
  357. package/skills/ce-resolve-pr-feedback/scripts/resolve-pr-thread +23 -0
  358. package/skills/ce-retune/SKILL.md +42 -0
  359. package/skills/ce-retune/agents/openai.yaml +2 -0
  360. package/skills/ce-retune/references/baseline-mining.md +122 -0
  361. package/skills/ce-retune/references/corpus-audit.md +128 -0
  362. package/skills/ce-retune/references/cut-passes.md +129 -0
  363. package/skills/ce-retune/references/halt-taxonomy.md +123 -0
  364. package/skills/ce-retune/references/noise-floor.md +131 -0
  365. package/skills/ce-retune/references/workflow-shapes.md +73 -0
  366. package/skills/ce-riffrec-feedback-analysis/SKILL.md +33 -0
  367. package/skills/ce-riffrec-feedback-analysis/references/analyzer.md +18 -0
  368. package/skills/ce-riffrec-feedback-analysis/references/compound-engineering-feedback-format.md +116 -0
  369. package/skills/ce-riffrec-feedback-analysis/references/extensive-analysis.md +98 -0
  370. package/skills/ce-riffrec-feedback-analysis/references/install-riffrec.md +27 -0
  371. package/skills/ce-riffrec-feedback-analysis/references/quick-bug-report.md +38 -0
  372. package/skills/ce-riffrec-feedback-analysis/scripts/analyze_riffrec_zip.py +1306 -0
  373. package/skills/ce-setup/SKILL.md +103 -0
  374. package/skills/ce-setup/agents/openai.yaml +2 -0
  375. package/skills/ce-setup/assets/compounding-directive.md +11 -0
  376. package/skills/ce-setup/assets/noslop-directive.md +7 -0
  377. package/skills/ce-setup/assets/pack-rule-template.md +11 -0
  378. package/skills/ce-setup/references/acpx-cache-warm.md +14 -0
  379. package/skills/ce-setup/references/config-template.yaml +210 -0
  380. package/skills/ce-setup/references/legacy-codex-tool-map.md +15 -0
  381. package/skills/ce-setup/references/pack-scaffold.md +45 -0
  382. package/skills/ce-setup/references/repo-fixes.md +121 -0
  383. package/skills/ce-setup/scripts/check-health +929 -0
  384. package/skills/ce-setup/scripts/packs-resolve.py +737 -0
  385. package/skills/ce-simplify-code/SKILL.md +76 -0
  386. package/skills/ce-simplify-code/references/personas/code-quality-reviewer.md +17 -0
  387. package/skills/ce-simplify-code/references/personas/code-reuse-reviewer.md +7 -0
  388. package/skills/ce-simplify-code/references/personas/comment-reviewer.md +24 -0
  389. package/skills/ce-simplify-code/references/personas/efficiency-reviewer.md +11 -0
  390. package/skills/ce-simplify-code/references/personas/test-value-reviewer.md +23 -0
  391. package/skills/ce-simplify-code/references/reviewer-dispatch.md +11 -0
  392. package/skills/ce-simplify-code/references/standalone-report.md +25 -0
  393. package/skills/ce-strategy/SKILL.md +61 -0
  394. package/skills/ce-strategy/references/grounding.md +22 -0
  395. package/skills/ce-strategy/references/interview.md +179 -0
  396. package/skills/ce-strategy/references/strategy-template.md +94 -0
  397. package/skills/ce-strategy/references/update-run.md +33 -0
  398. package/skills/ce-sweep/SKILL.md +93 -0
  399. package/skills/ce-sweep/agents/openai.yaml +2 -0
  400. package/skills/ce-sweep/references/agents/media-analyzer.md +54 -0
  401. package/skills/ce-sweep/references/interview.md +208 -0
  402. package/skills/ce-sweep/references/model-tiers.md +13 -0
  403. package/skills/ce-sweep/references/plan-template.md +62 -0
  404. package/skills/ce-sweep/references/run.md +126 -0
  405. package/skills/ce-sweep/references/sources/email.md +57 -0
  406. package/skills/ce-sweep/references/sources/github-issues.md +59 -0
  407. package/skills/ce-sweep/references/sources/slack.md +61 -0
  408. package/skills/ce-sweep/references/state-schema.md +157 -0
  409. package/skills/ce-sweep/references/subagent-template.md +60 -0
  410. package/skills/ce-sweep/scripts/analyze_riffrec_zip.py +1306 -0
  411. package/skills/ce-sweep/scripts/sweep-state.py +793 -0
  412. package/skills/ce-test-browser/SKILL.md +50 -0
  413. package/skills/ce-test-browser/references/agent-browser-driver.md +47 -0
  414. package/skills/ce-test-browser/references/pipeline-orchestration.md +45 -0
  415. package/skills/ce-test-browser/references/route-and-report.md +129 -0
  416. package/skills/ce-test-browser/scripts/resolve-port.sh +41 -0
  417. package/skills/ce-test-xcode/SKILL.md +26 -0
  418. package/skills/ce-test-xcode/agents/openai.yaml +2 -0
  419. package/skills/ce-test-xcode/references/setup-and-build.md +32 -0
  420. package/skills/ce-test-xcode/references/test-and-report.md +64 -0
  421. package/skills/ce-work/SKILL.md +62 -0
  422. package/skills/ce-work/references/agents/figma-design-sync.md +27 -0
  423. package/skills/ce-work/references/agents/implementation-worker.md +17 -0
  424. package/skills/ce-work/references/cross-model-execution.md +191 -0
  425. package/skills/ce-work/references/execution-engines.md +64 -0
  426. package/skills/ce-work/references/execution-strategy.md +73 -0
  427. package/skills/ce-work/references/implementation-loop.md +107 -0
  428. package/skills/ce-work/references/implementation-result-schema.json +52 -0
  429. package/skills/ce-work/references/input-triage.md +50 -0
  430. package/skills/ce-work/references/non-code-execution.md +23 -0
  431. package/skills/ce-work/references/return-to-caller.md +33 -0
  432. package/skills/ce-work/references/review-findings-followup.md +82 -0
  433. package/skills/ce-work/references/shipping-workflow.md +89 -0
  434. package/skills/ce-work/references/tracker-defer.md +150 -0
  435. package/skills/ce-work/references/work-intake.md +51 -0
  436. package/skills/ce-work/references/workspace-setup.md +27 -0
  437. package/skills/ce-work/scripts/__pycache__/unit_workspace_jobs.cpython-314.pyc +0 -0
  438. package/skills/ce-work/scripts/__pycache__/unit_workspace_state.cpython-314.pyc +0 -0
  439. package/skills/ce-work/scripts/cross-model-work.sh +1385 -0
  440. package/skills/ce-work/scripts/peer-job-runner.py +2594 -0
  441. package/skills/ce-work/scripts/unit-workspace.py +215 -0
  442. package/skills/ce-work/scripts/unit_workspace_ignored.py +93 -0
  443. package/skills/ce-work/scripts/unit_workspace_integration.py +677 -0
  444. package/skills/ce-work/scripts/unit_workspace_jobs.py +1216 -0
  445. package/skills/ce-work/scripts/unit_workspace_lifecycle.py +981 -0
  446. package/skills/ce-work/scripts/unit_workspace_state.py +1379 -0
  447. package/skills/ce-work/scripts/unit_workspace_transaction.py +612 -0
  448. package/skills/ce-worktree/SKILL.md +54 -0
  449. package/skills/lfg/SKILL.md +59 -0
  450. package/skills/lfg/references/debug-return.md +25 -0
  451. package/skills/lfg/references/intake.md +30 -0
  452. package/skills/lfg/references/next-work-handoff.md +96 -0
  453. package/skills/lfg/references/plan-brief.md +36 -0
  454. package/skills/lfg/references/review-followup.md +78 -0
  455. package/skills/lfg/references/shipping.md +65 -0
  456. package/skills/lfg/references/stage-routing.md +49 -0
  457. package/skills/lfg/references/task-visibility.md +11 -0
  458. package/skills/lfg/references/tracker-defer.md +150 -0
  459. package/skills/lfg/references/work-return.md +27 -0
  460. package/skills/wtf/SKILL.md +33 -0
  461. package/skills/wtf/agents/openai.yaml +2 -0
@@ -0,0 +1,676 @@
1
+ #!/usr/bin/env node
2
+ // Decide keep / revert / inconclusive / censored / degenerate for one
3
+ // candidate against the current best. Owns multi-objective eligibility,
4
+ // noise-aware comparison, and the measurement-ladder next step.
5
+ //
6
+ // Usage:
7
+ // node decide.mjs # JSON on stdin
8
+ // node decide.mjs <input.json>
9
+ //
10
+ // A spec with no `objectives` and no `ladder` reproduces the legacy
11
+ // single-primary + absolute noise_threshold rule, except that a delta
12
+ // inside the threshold is `inconclusive` rather than a silent revert.
13
+ //
14
+ // Input: { spec, baseline, candidate, holdout? }. `holdout` is a second
15
+ // { baseline, candidate } snapshot pair from the held-out set. When the spec
16
+ // configures a holdout and the pair is absent, a would-be keep returns
17
+ // `next_measurement: "holdout"` instead of keeping. When either snapshot
18
+ // carries a `cases` object, the output lists `regressions` (report only).
19
+
20
+ export function median(values) {
21
+ if (!values.length) return null
22
+ const sorted = [...values].sort((a, b) => a - b)
23
+ const mid = Math.floor(sorted.length / 2)
24
+ return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]
25
+ }
26
+
27
+ function parseCheck(check) {
28
+ const match = String(check).trim().match(/^(>=|<=|==|!=|>|<)\s*(.+)$/)
29
+ if (!match) {
30
+ throw new Error(`invalid gate check: ${check}`)
31
+ }
32
+ return { op: match[1], threshold: Number(match[2]) }
33
+ }
34
+
35
+ export function gatePasses(value, check) {
36
+ const { op, threshold } = parseCheck(check)
37
+ const n = finiteNumber(value)
38
+ if (n == null || !Number.isFinite(threshold)) return false
39
+ switch (op) {
40
+ case ">=":
41
+ return n >= threshold
42
+ case "<=":
43
+ return n <= threshold
44
+ case ">":
45
+ return n > threshold
46
+ case "<":
47
+ return n < threshold
48
+ case "==":
49
+ return n === threshold
50
+ case "!=":
51
+ return n !== threshold
52
+ default:
53
+ return false
54
+ }
55
+ }
56
+
57
+ function signedDelta(baseline, candidate, direction) {
58
+ return direction === "minimize" ? baseline - candidate : candidate - baseline
59
+ }
60
+
61
+ function finiteNumber(value) {
62
+ if (value == null || value === "") return null
63
+ const n = typeof value === "number" ? value : Number(value)
64
+ return Number.isFinite(n) ? n : null
65
+ }
66
+
67
+ function firstNonNegativeNumber(values, fallback) {
68
+ for (const value of values) {
69
+ const n = finiteNumber(value)
70
+ if (n != null && n >= 0) return n
71
+ }
72
+ return fallback
73
+ }
74
+
75
+ function positiveInteger(value, fallback) {
76
+ const n = typeof value === "number" ? value : Number(value)
77
+ if (!Number.isInteger(n) || n < 1) return fallback
78
+ return n
79
+ }
80
+
81
+ function verdictFromSigned(delta, threshold) {
82
+ if (delta > threshold) return "improved"
83
+ if (delta < -threshold) return "regressed"
84
+ return "inconclusive"
85
+ }
86
+
87
+ function closedResult(fields) {
88
+ return {
89
+ eligible: false,
90
+ next_measurement: "none",
91
+ target_reached: false,
92
+ improved_objectives: [],
93
+ violated_objectives: [],
94
+ comparisons: {},
95
+ primary_delta: null,
96
+ rank_score: 0,
97
+ regressions: [],
98
+ holdout: null,
99
+ ...fields,
100
+ }
101
+ }
102
+
103
+ function casePassed(value) {
104
+ return value === true || value === 1 || value === "1" || value === "true" || value === "pass"
105
+ }
106
+
107
+ // Cases the reference passed and the candidate fails. Report only: this never
108
+ // changes the decision, and a missing `cases` object on either side yields [].
109
+ export function regressions(baseline, candidate) {
110
+ const before = baseline?.cases
111
+ const after = candidate?.cases
112
+ if (!before || typeof before !== "object" || !after || typeof after !== "object") return []
113
+ return Object.keys(before)
114
+ .filter((id) => casePassed(before[id]) && id in after && !casePassed(after[id]))
115
+ .sort()
116
+ }
117
+
118
+ function holdoutConfigured(spec) {
119
+ if (spec.measurement?.holdout?.command) return true
120
+ const seed = spec.judge?.confirmation_seed
121
+ if (seed == null) return false
122
+ return spec.primary?.type === "judge" && seed !== (spec.judge?.sample_seed ?? 42)
123
+ }
124
+
125
+ function configuredAggregation(value) {
126
+ return value === "mean" || value === "min" || value === "max" ? value : "median"
127
+ }
128
+
129
+ function aggregateSamples(samples, method) {
130
+ if (!samples.length) return null
131
+ if (method === "mean") return samples.reduce((sum, value) => sum + value, 0) / samples.length
132
+ if (method === "min") return Math.min(...samples)
133
+ if (method === "max") return Math.max(...samples)
134
+ return median(samples)
135
+ }
136
+
137
+ function valueBundle(raw, aggregation = "median") {
138
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
139
+ const samples = Array.isArray(raw.samples) ? raw.samples.map(finiteNumber) : []
140
+ if (samples.some((n) => n == null)) return { aggregate: null, samples: [] }
141
+ const aggregate = samples.length
142
+ ? aggregateSamples(samples, aggregation)
143
+ : finiteNumber(raw.aggregate)
144
+ return { aggregate: aggregate ?? null, samples }
145
+ }
146
+ if (raw != null && typeof raw !== "object") {
147
+ const n = finiteNumber(raw)
148
+ return n == null ? { aggregate: null, samples: [] } : { aggregate: n, samples: [] }
149
+ }
150
+ return null
151
+ }
152
+
153
+ function metricBundle(source, name, aggregation, type) {
154
+ if (!source) return null
155
+ const containers =
156
+ type === "judge"
157
+ ? [source.judge?.[name], source.metrics?.[name], source.diagnostics?.[name], source.gates?.[name]]
158
+ : [source.metrics?.[name], source.judge?.[name], source.diagnostics?.[name], source.gates?.[name]]
159
+ for (const raw of containers) {
160
+ if (raw === undefined) continue
161
+ return valueBundle(raw, aggregation)
162
+ }
163
+ return null
164
+ }
165
+
166
+ function normalizeSpec(spec) {
167
+ const metric = spec.metric ?? {}
168
+ const measurement = spec.measurement ?? {}
169
+ const stability = spec.stability ?? measurement.stability ?? {}
170
+ const primary = spec.primary ?? metric.primary ?? {}
171
+ const judge = spec.judge ?? metric.judge
172
+ const comparison = spec.comparison ?? stability.comparison
173
+ return {
174
+ ...spec,
175
+ primary,
176
+ objectives: spec.objectives ?? metric.objectives,
177
+ degenerate_gates: spec.degenerate_gates ?? metric.degenerate_gates,
178
+ judge,
179
+ comparison,
180
+ ladder: spec.ladder ?? stability.ladder ?? {},
181
+ stability_mode: spec.stability_mode ?? stability.mode,
182
+ aggregation: configuredAggregation(spec.aggregation ?? stability.aggregation),
183
+ repeat_count: spec.repeat_count ?? stability.repeat_count,
184
+ noise_threshold: spec.noise_threshold ?? stability.noise_threshold,
185
+ minimum_improvement:
186
+ spec.minimum_improvement ?? comparison?.minimum_improvement ?? judge?.minimum_improvement,
187
+ measurement,
188
+ stability,
189
+ }
190
+ }
191
+
192
+ function comparisonDefaults(spec) {
193
+ const stability = spec.stability ?? spec.measurement?.stability ?? {}
194
+ const comparison = spec.comparison ?? stability.comparison ?? {}
195
+ const usesJudge = spec.primary?.type === "judge" || spec.judge != null
196
+ return {
197
+ method: comparison.method ?? "absolute",
198
+ noise_threshold: firstNonNegativeNumber(
199
+ [comparison.noise_threshold, spec.noise_threshold, stability.noise_threshold],
200
+ 0.02,
201
+ ),
202
+ relative_threshold: firstNonNegativeNumber([comparison.relative_threshold], 0.05),
203
+ minimum_improvement: firstNonNegativeNumber(
204
+ [comparison.minimum_improvement, spec.minimum_improvement, spec.judge?.minimum_improvement],
205
+ usesJudge ? 0.3 : null,
206
+ ),
207
+ }
208
+ }
209
+
210
+ function requiredObjectives(spec) {
211
+ const primary = spec.primary ?? {}
212
+ const listed = Array.isArray(spec.objectives) ? spec.objectives : []
213
+ const extras = listed
214
+ .map((objective) => ({
215
+ name: objective.name,
216
+ direction: objective.direction ?? primary.direction ?? "maximize",
217
+ role: objective.role ?? "required",
218
+ type: objective.type ?? "hard",
219
+ target: objective.target ?? null,
220
+ max_regression: objective.max_regression ?? null,
221
+ }))
222
+ .filter((objective) => objective.role !== "secondary")
223
+ if (!primary.name) return extras
224
+ const listedPrimary = extras.find((objective) => objective.name === primary.name)
225
+ return [
226
+ {
227
+ name: primary.name,
228
+ direction: primary.direction ?? listedPrimary?.direction ?? "maximize",
229
+ role: "required",
230
+ type: primary.type ?? listedPrimary?.type ?? "hard",
231
+ target: primary.target ?? listedPrimary?.target ?? null,
232
+ max_regression: listedPrimary?.max_regression ?? primary.max_regression ?? null,
233
+ },
234
+ ...extras.filter((objective) => objective.name !== primary.name),
235
+ ]
236
+ }
237
+
238
+ export function compareObjective({
239
+ baselineValue,
240
+ candidateValue,
241
+ baselineSamples,
242
+ candidateSamples,
243
+ direction,
244
+ type,
245
+ comparison,
246
+ maxRegression,
247
+ }) {
248
+ const delta = signedDelta(baselineValue, candidateValue, direction)
249
+ const denom = Math.abs(baselineValue)
250
+ const relative = denom > 0 ? delta / denom : 0
251
+ const absThreshold =
252
+ type === "judge" && comparison.minimum_improvement != null
253
+ ? comparison.minimum_improvement
254
+ : comparison.noise_threshold
255
+ const relativeThreshold = comparison.relative_threshold
256
+
257
+ let verdict
258
+ if ((comparison.method === "relative" || comparison.method === "paired") && denom <= 0) {
259
+ verdict = "inconclusive"
260
+ } else if (comparison.method === "relative") {
261
+ verdict = verdictFromSigned(relative, relativeThreshold)
262
+ } else if (comparison.method === "paired") {
263
+ const baseSamples = baselineSamples?.filter((n) => n != null) ?? []
264
+ const candSamples = candidateSamples?.filter((n) => n != null) ?? []
265
+ const threshold = relativeThreshold * denom
266
+ if (!baseSamples.length || !candSamples.length) {
267
+ verdict =
268
+ type === "judge"
269
+ ? verdictFromSigned(delta, absThreshold)
270
+ : verdictFromSigned(delta, threshold) === "regressed"
271
+ ? "regressed"
272
+ : "inconclusive"
273
+ } else if (candSamples.length > baseSamples.length) {
274
+ verdict = "inconclusive"
275
+ } else {
276
+ const diffs = candSamples.map((value, index) =>
277
+ signedDelta(baseSamples[index], value, direction),
278
+ )
279
+ const lo = Math.min(...diffs)
280
+ const hi = Math.max(...diffs)
281
+ if (verdictFromSigned(lo, threshold) === "improved") verdict = "improved"
282
+ else if (verdictFromSigned(hi, threshold) === "regressed") verdict = "regressed"
283
+ else verdict = "inconclusive"
284
+ }
285
+ } else {
286
+ verdict = verdictFromSigned(delta, absThreshold)
287
+ }
288
+
289
+ if (
290
+ type === "judge" &&
291
+ comparison.minimum_improvement != null &&
292
+ verdict === "improved" &&
293
+ delta <= comparison.minimum_improvement
294
+ ) {
295
+ verdict = "inconclusive"
296
+ }
297
+
298
+ let violated = verdict === "regressed"
299
+ if (maxRegression && verdict !== "improved") {
300
+ const rawBound = Number(maxRegression.value)
301
+ if (Number.isFinite(rawBound) && rawBound >= 0) {
302
+ const bound = maxRegression.type === "relative" ? rawBound * denom : rawBound
303
+ violated = -delta > bound
304
+ if (violated) verdict = "regressed"
305
+ }
306
+ }
307
+
308
+ return { verdict, delta, relative, violated }
309
+ }
310
+
311
+ function evaluateGates(spec, candidate) {
312
+ const gates = Array.isArray(spec.degenerate_gates) ? spec.degenerate_gates : []
313
+ const values = candidate?.gates ?? {}
314
+ const failures = []
315
+ for (const gate of gates) {
316
+ if (!gatePasses(values[gate.name], gate.check)) {
317
+ failures.push(gate.name)
318
+ }
319
+ }
320
+ return failures
321
+ }
322
+
323
+ function futilityBound(futility, baselineValue, direction) {
324
+ const factor = finiteNumber(futility.worse_factor ?? 1.2)
325
+ const baseline = finiteNumber(baselineValue)
326
+ if (factor == null || factor <= 1 || baseline == null || baseline <= 0) return null
327
+ return direction === "minimize" ? baseline * factor : baseline / factor
328
+ }
329
+
330
+ function isFutile({
331
+ ladder,
332
+ direction,
333
+ baselineValue,
334
+ candidateValue,
335
+ elapsedSeconds,
336
+ sampleCount,
337
+ enabled,
338
+ }) {
339
+ const futility = ladder.futility
340
+ if (!enabled || futility == null || typeof futility !== "object") return false
341
+
342
+ const afterElapsed = finiteNumber(futility.after_elapsed_seconds)
343
+ if (
344
+ afterElapsed != null &&
345
+ afterElapsed > 0 &&
346
+ elapsedSeconds != null &&
347
+ Number(elapsedSeconds) >= afterElapsed &&
348
+ signedDelta(baselineValue, candidateValue, direction) <= 0
349
+ ) {
350
+ return true
351
+ }
352
+
353
+ const bound = futilityBound(futility, baselineValue, direction)
354
+ if (bound == null || candidateValue == null) return false
355
+ const worse = signedDelta(bound, candidateValue, direction) <= 0
356
+ return worse && (sampleCount ?? 1) <= (ladder.exploratory_pairs ?? 1)
357
+ }
358
+
359
+ function compareRequired({
360
+ required,
361
+ comparison,
362
+ aggregation,
363
+ baseline,
364
+ candidate,
365
+ ladderEnabled,
366
+ confirmationRepeats,
367
+ }) {
368
+ const comparisons = {}
369
+ const improved = []
370
+ const violated = []
371
+ const missing = []
372
+ const incompleteBaselines = []
373
+ const candidateBundles = {}
374
+ const baselineBundles = {}
375
+
376
+ for (const objective of required) {
377
+ const base = metricBundle(baseline, objective.name, aggregation, objective.type)
378
+ const cand = metricBundle(candidate, objective.name, aggregation, objective.type)
379
+ baselineBundles[objective.name] = base
380
+ candidateBundles[objective.name] = cand
381
+ if (!base || base.aggregate == null || !cand || cand.aggregate == null) {
382
+ missing.push(objective.name)
383
+ continue
384
+ }
385
+ if (comparison.method === "paired" && base.samples.length && cand.samples.length) {
386
+ const requiredSamples = Math.max(cand.samples.length, ladderEnabled ? confirmationRepeats : 1)
387
+ if (base.samples.length < requiredSamples) {
388
+ incompleteBaselines.push(
389
+ `${objective.name} (${base.samples.length} observed, ${requiredSamples} required)`,
390
+ )
391
+ continue
392
+ }
393
+ }
394
+ const result = compareObjective({
395
+ baselineValue: base.aggregate,
396
+ candidateValue: cand.aggregate,
397
+ baselineSamples: base.samples,
398
+ candidateSamples: cand.samples,
399
+ direction: objective.direction,
400
+ type: objective.type,
401
+ comparison,
402
+ maxRegression: objective.max_regression,
403
+ })
404
+ comparisons[objective.name] = result
405
+ if (result.verdict === "improved") improved.push({ name: objective.name, ...result })
406
+ if (result.violated) violated.push(objective.name)
407
+ }
408
+
409
+ return { comparisons, improved, violated, missing, incompleteBaselines, candidateBundles, baselineBundles }
410
+ }
411
+
412
+ // The held-out pair is scored with the same gates, objectives, and thresholds
413
+ // as the selection pair. It confirms a keep; it never selects. A holdout that
414
+ // does not improve an objective the selection improved withholds the keep.
415
+ function confirmHoldout({ spec, holdout, required, comparison, aggregation, selectionImproved }) {
416
+ const gateFailures = evaluateGates(spec, holdout.candidate)
417
+ if (gateFailures.length) {
418
+ return {
419
+ comparisons: {},
420
+ improved_objectives: [],
421
+ violated_objectives: gateFailures,
422
+ agrees: false,
423
+ decision: "degenerate",
424
+ reason: `holdout degenerate gate failed: ${gateFailures.join(", ")}`,
425
+ }
426
+ }
427
+ const compared = compareRequired({
428
+ required,
429
+ comparison,
430
+ aggregation,
431
+ baseline: holdout.baseline ?? {},
432
+ candidate: holdout.candidate ?? {},
433
+ ladderEnabled: false,
434
+ confirmationRepeats: 1,
435
+ })
436
+ const summary = {
437
+ comparisons: compared.comparisons,
438
+ improved_objectives: compared.improved.map((item) => item.name),
439
+ violated_objectives: compared.violated,
440
+ }
441
+ if (compared.missing.length) {
442
+ return {
443
+ ...summary,
444
+ agrees: false,
445
+ decision: "error",
446
+ reason: `holdout missing required metric: ${compared.missing.join(", ")}`,
447
+ }
448
+ }
449
+ if (compared.incompleteBaselines.length) {
450
+ return {
451
+ ...summary,
452
+ agrees: false,
453
+ decision: "error",
454
+ reason: `holdout has insufficient paired baseline samples: ${compared.incompleteBaselines.join(", ")}`,
455
+ }
456
+ }
457
+ if (compared.violated.length) {
458
+ return {
459
+ ...summary,
460
+ agrees: false,
461
+ decision: "revert",
462
+ reason: `holdout regressed ${compared.violated.join(", ")}`,
463
+ }
464
+ }
465
+ if (!compared.improved.some((item) => selectionImproved.includes(item.name))) {
466
+ return {
467
+ ...summary,
468
+ agrees: false,
469
+ decision: "inconclusive",
470
+ reason: `holdout did not confirm the selection gain in ${selectionImproved.join(", ")}`,
471
+ }
472
+ }
473
+ return { ...summary, agrees: true, decision: "keep", reason: null }
474
+ }
475
+
476
+ function rankScore(primaryComparison, improved) {
477
+ if (primaryComparison?.verdict === "improved") return primaryComparison.relative ?? 0
478
+ if (!improved.length) return primaryComparison?.relative ?? 0
479
+ return Math.max(...improved.map((item) => item.relative ?? 0))
480
+ }
481
+
482
+ export function decide(input) {
483
+ const spec = normalizeSpec(input.spec ?? {})
484
+ const baseline = input.baseline ?? {}
485
+ const candidate = input.candidate ?? {}
486
+ const primary = spec.primary ?? {}
487
+ if (!primary.name) {
488
+ return closedResult({ decision: "error", reason: "missing primary metric" })
489
+ }
490
+ const comparison = comparisonDefaults(spec)
491
+ const required = requiredObjectives(spec)
492
+ const ladder = spec.ladder ?? {}
493
+ const ladderEnabled = Boolean(ladder.enabled || spec.stability_mode === "ladder")
494
+ const exploratoryPairs = positiveInteger(ladder.exploratory_pairs, 1)
495
+ let confirmationRepeats = positiveInteger(ladder.confirmation_repeats ?? spec.repeat_count, 5)
496
+ if (confirmationRepeats < exploratoryPairs) confirmationRepeats = exploratoryPairs
497
+
498
+ if (candidate.smoke_passed === false) {
499
+ return closedResult({ decision: "degenerate", reason: "smoke test failed" })
500
+ }
501
+
502
+ const gateFailures = evaluateGates(spec, candidate)
503
+ if (gateFailures.length) {
504
+ return closedResult({
505
+ decision: "degenerate",
506
+ violated_objectives: gateFailures,
507
+ reason: `degenerate gate failed: ${gateFailures.join(", ")}`,
508
+ })
509
+ }
510
+
511
+ const aggregation = spec.aggregation ?? "median"
512
+ const compared = compareRequired({
513
+ required,
514
+ comparison,
515
+ aggregation,
516
+ baseline,
517
+ candidate,
518
+ ladderEnabled,
519
+ confirmationRepeats,
520
+ })
521
+ const { comparisons, improved, violated, missing, incompleteBaselines, candidateBundles, baselineBundles } =
522
+ compared
523
+
524
+ if (missing.length) {
525
+ return closedResult({
526
+ decision: "error",
527
+ comparisons,
528
+ reason: `missing required metric: ${missing.join(", ")}`,
529
+ })
530
+ }
531
+
532
+ if (incompleteBaselines.length) {
533
+ // Ladder next steps collect candidate samples; they cannot repair the baseline.
534
+ return closedResult({
535
+ decision: "error",
536
+ comparisons,
537
+ reason: `insufficient paired baseline samples: ${incompleteBaselines.join(", ")}`,
538
+ })
539
+ }
540
+
541
+ const primaryBundle =
542
+ candidateBundles[primary.name] ?? metricBundle(candidate, primary.name, aggregation, primary.type)
543
+ const baselinePrimary =
544
+ baselineBundles[primary.name] ?? metricBundle(baseline, primary.name, aggregation, primary.type)
545
+ const primaryComparison = comparisons[primary.name] ?? null
546
+ const eligible = improved.length > 0 && violated.length === 0
547
+ const improvedNames = improved.map((item) => item.name)
548
+ const stillContending = required.some(
549
+ (objective) => comparisons[objective.name]?.verdict === "inconclusive",
550
+ )
551
+ const sampleCount = Math.min(
552
+ ...required.map((objective) => {
553
+ const fromSamples = candidateBundles[objective.name]?.samples?.length
554
+ if (Number.isInteger(fromSamples) && fromSamples > 0) return fromSamples
555
+ return positiveInteger(candidate.sample_count, 1)
556
+ }),
557
+ )
558
+
559
+ if (
560
+ !eligible &&
561
+ !stillContending &&
562
+ isFutile({
563
+ ladder,
564
+ direction: primary.direction,
565
+ baselineValue: baselinePrimary?.aggregate,
566
+ candidateValue: primaryBundle?.aggregate,
567
+ elapsedSeconds: candidate.elapsed_seconds,
568
+ sampleCount,
569
+ enabled: ladderEnabled,
570
+ })
571
+ ) {
572
+ return closedResult({
573
+ decision: "censored",
574
+ improved_objectives: improvedNames,
575
+ violated_objectives: violated,
576
+ comparisons,
577
+ primary_delta: primaryComparison?.delta ?? null,
578
+ reason: "noncompetitive under the predeclared futility bound",
579
+ })
580
+ }
581
+
582
+ const withTargets = required.filter((objective) => objective.target != null)
583
+ const targetReached =
584
+ withTargets.length > 0 &&
585
+ withTargets.every((objective) => {
586
+ const value = candidateBundles[objective.name]?.aggregate
587
+ if (value == null) return false
588
+ return signedDelta(objective.target, value, objective.direction) >= 0
589
+ })
590
+
591
+ let decision
592
+ if (eligible) decision = "keep"
593
+ else if (violated.length) decision = "revert"
594
+ else if (stillContending) decision = "inconclusive"
595
+ else decision = "revert"
596
+
597
+ let nextMeasurement = "none"
598
+ if (ladderEnabled && ladder.smoke_command && candidate.smoke_passed == null) {
599
+ nextMeasurement = "smoke"
600
+ } else if (ladderEnabled && (decision === "keep" || decision === "inconclusive")) {
601
+ const confirming = decision === "keep"
602
+ const sampleBudget = confirming
603
+ ? confirmationRepeats
604
+ : Math.min(exploratoryPairs + 1, confirmationRepeats)
605
+ if (sampleCount < sampleBudget) {
606
+ if (confirming) decision = "promising"
607
+ if (sampleCount < exploratoryPairs) nextMeasurement = "exploratory"
608
+ else nextMeasurement = confirming ? "confirm" : "add_sample"
609
+ }
610
+ }
611
+
612
+ let reason = "no required objective improved"
613
+ if (eligible) {
614
+ reason = `improved ${improvedNames.join(", ")} without violating other required objectives`
615
+ } else if (decision === "inconclusive") {
616
+ reason = "delta inside the comparison threshold"
617
+ } else if (violated.length) {
618
+ reason = `violated ${violated.join(", ")}`
619
+ }
620
+
621
+ // A holdout is scored only once the selection comparison would keep.
622
+ let holdout = null
623
+ let keepEligible = eligible
624
+ if (decision === "keep" && nextMeasurement === "none" && holdoutConfigured(spec)) {
625
+ if (input.holdout == null) {
626
+ decision = "promising"
627
+ nextMeasurement = "holdout"
628
+ reason = "selection comparison would keep; held-out confirmation still missing"
629
+ } else {
630
+ holdout = confirmHoldout({
631
+ spec,
632
+ holdout: input.holdout,
633
+ required,
634
+ comparison,
635
+ aggregation,
636
+ selectionImproved: improvedNames,
637
+ })
638
+ if (!holdout.agrees) {
639
+ decision = holdout.decision
640
+ keepEligible = false
641
+ reason = holdout.reason
642
+ }
643
+ }
644
+ }
645
+
646
+ return {
647
+ decision,
648
+ eligible: keepEligible,
649
+ next_measurement: nextMeasurement,
650
+ target_reached: targetReached,
651
+ improved_objectives: improvedNames,
652
+ violated_objectives: violated,
653
+ comparisons,
654
+ primary_delta: primaryComparison?.delta ?? null,
655
+ rank_score: rankScore(primaryComparison, improved),
656
+ regressions: regressions(baseline, candidate),
657
+ holdout,
658
+ reason,
659
+ }
660
+ }
661
+
662
+ function isCli(argv = process.argv) {
663
+ const entry = argv[1] ?? ""
664
+ return entry.endsWith("decide.mjs")
665
+ }
666
+
667
+ async function runCli(argv = process.argv, io = process) {
668
+ const { readFileSync } = await import("node:fs")
669
+ const source = argv[2] && argv[2] !== "-" ? argv[2] : 0
670
+ const input = JSON.parse(readFileSync(source, "utf8"))
671
+ io.stdout.write(`${JSON.stringify(decide(input), null, 2)}\n`)
672
+ }
673
+
674
+ if (isCli()) {
675
+ await runCli()
676
+ }