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,419 @@
1
+ #!/usr/bin/env python3
2
+ """Compute fail-closed, deterministic scope facts for ce-code-review.
3
+
4
+ The helper never awards lite. It reports counts, path classes, and floors
5
+ the skill's Review depth gate reads. `hard_block_full` forces the full
6
+ spine: a path class the script can name, a file it could not count, or a
7
+ change whose executable non-test lines reach the full floor. Below that
8
+ floor, size is a fact the gate reads, never a decision; the agent judges
9
+ consequence.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import argparse
15
+ import functools
16
+ import json
17
+ import os
18
+ import re
19
+ import subprocess
20
+ import sys
21
+ from pathlib import Path
22
+
23
+
24
+ CODE_EXTENSIONS = {
25
+ ".rb", ".py", ".js", ".mjs", ".cjs", ".jsx", ".ts", ".tsx", ".go", ".rs",
26
+ ".java", ".swift", ".kt", ".c", ".cc", ".cpp", ".cs", ".php",
27
+ ".ex", ".exs", ".scala",
28
+ ".sh", ".bash", ".zsh", ".fish", ".ps1", ".pl", ".pm", ".lua", ".dart",
29
+ ".vue", ".svelte",
30
+ }
31
+
32
+ SIGNAL_PATTERNS = {
33
+ "migrations": re.compile(
34
+ r"db/migrate/|schema\.(rb|sql)|/migrations?/|alembic|flyway|liquibase",
35
+ re.I,
36
+ ),
37
+ "frontend": re.compile(
38
+ r"\.(tsx|jsx|vue|svelte|css|scss|html|erb|haml)$|/components?/|stimulus|turbo",
39
+ re.I,
40
+ ),
41
+ "api": re.compile(
42
+ r"/(routes?|controllers?|api|serializers?|graphql)/|\.proto$|openapi|swagger",
43
+ re.I,
44
+ ),
45
+ "swift-ios": re.compile(r"\.(swift|kt|pbxproj|xcconfig|entitlements)$", re.I),
46
+ }
47
+
48
+ # Classes the script can name from paths alone. These force full; they do not
49
+ # award lite.
50
+ HARD_BLOCK_PATTERNS = {
51
+ "migrations": SIGNAL_PATTERNS["migrations"],
52
+ }
53
+
54
+ # Silent-pass guards the script can name from paths alone. These forbid lite
55
+ # (the change needs the adversarial read the focused path carries) but do not
56
+ # force full; consequence still decides focused versus full. Silent-pass guards
57
+ # outside these paths are the agent's question.
58
+ SILENT_PASS_PATTERNS = {
59
+ "ci": re.compile(
60
+ r"(^|/)\.github/workflows/|(^|/)\.gitlab-ci\.yml$|(^|/)\.gitlab-ci/"
61
+ r"|(^|/)Jenkinsfile$|(^|/)\.circleci/|(^|/)\.buildkite/",
62
+ re.I,
63
+ ),
64
+ }
65
+
66
+ # Executable non-test changed lines at or above this run the full spine; it
67
+ # matches the maintainability reviewer's trigger. Below it, consequence decides.
68
+ # Whole-file deletions never count toward it: they band separately, and that
69
+ # band can forbid lite but never forces full.
70
+ FULL_EXEC_LINE_MIN = 200
71
+
72
+ # Conventions recognized: tests?/spec/__tests__ directories; a .test./.spec.
73
+ # suffix; a test_*.py / conftest.py Python prefix; and a case-sensitive
74
+ # Test/Tests/Spec class-file suffix (Java/C#/Scala/Swift/Kotlin), so that
75
+ # Contest.java or Manifest.cs stays production code.
76
+ TEST_PATTERN = re.compile(
77
+ r"(^|/)(tests?|spec|__tests__)/"
78
+ r"|(^|/)[^/]+[._-](test|spec)\.[^/]+$"
79
+ r"|(^|/)(test_[^/]+|conftest)\.[^/]+$"
80
+ r"|(?-i:(^|/)[^/]+(Test|Tests|Spec)\.(java|kt|scala|swift|cs)$)",
81
+ re.I,
82
+ )
83
+ AGENT_SURFACE_PATTERN = re.compile(
84
+ r"(^|/)(skills?|agents?|prompts?|tools?|mcp|commands?)(/|$)|SKILL\.md$|"
85
+ r"(^|/)(AGENTS|CLAUDE|GEMINI)\.md$|\.cursor/|\.codex-plugin/|\.claude-plugin/",
86
+ re.I,
87
+ )
88
+
89
+
90
+ def git(*args: str) -> subprocess.CompletedProcess[str]:
91
+ return subprocess.run(
92
+ ["git", *args], capture_output=True, text=True, check=False
93
+ )
94
+
95
+
96
+ def valid_commit(ref: str | None) -> bool:
97
+ if not ref:
98
+ return False
99
+ return git("rev-parse", "--verify", "--quiet", f"{ref}^{{commit}}").returncode == 0
100
+
101
+
102
+ def unique_merge_base(base: str, head: str) -> str | None:
103
+ result = git("merge-base", "--all", base, head)
104
+ candidates = [line for line in result.stdout.splitlines() if line]
105
+ if result.returncode != 0 or len(candidates) != 1:
106
+ return None
107
+ return candidates[0]
108
+
109
+
110
+ DEFAULT_DOCS_ROOT = "docs"
111
+
112
+
113
+ def normalize_docs_root(docs_root: str | None) -> str:
114
+ """Fall back to the default root for an unset, empty, or unsubstituted value.
115
+
116
+ The calling skill substitutes a resolved path for the ``<root>`` placeholder
117
+ before invoking this script. If that substitution is missing — the value is
118
+ empty, or still contains angle brackets (a literal ``<root>``) — treat it as
119
+ unset and use the default ``docs``, which is exactly the block's unset
120
+ behavior. This keeps the common default-config case correct even when the
121
+ caller forgets to substitute.
122
+ """
123
+ if not docs_root or "<" in docs_root or ">" in docs_root:
124
+ return DEFAULT_DOCS_ROOT
125
+ return docs_root
126
+
127
+
128
+ @functools.lru_cache(maxsize=None)
129
+ def repo_root() -> Path:
130
+ """The repository root, matching how docs_root is resolved everywhere else.
131
+
132
+ docs_root is repo-relative (``<repo-root>/<docs_root>``), so the corpus
133
+ check must resolve against the git toplevel, not the current working
134
+ directory. ce-code-review can run from a subdirectory (``git diff`` still
135
+ works there), where ``Path.cwd()`` would join docs_root under the subdir and
136
+ wrongly report the corpus absent. Fall back to cwd when git can't answer.
137
+ """
138
+ result = git("rev-parse", "--show-toplevel")
139
+ if result.returncode == 0 and result.stdout.strip():
140
+ return Path(result.stdout.strip()).resolve()
141
+ return Path.cwd().resolve()
142
+
143
+
144
+ def has_learnings_corpus(docs_root: str | None) -> bool:
145
+ """Whether a `<docs_root>/solutions` learnings corpus exists.
146
+
147
+ docs_root is the artifact root resolved by the calling skill (default
148
+ ``docs``). Guard it the way the skill-prose rule does: normalize an
149
+ unset/placeholder value to the default, and treat a value that is absolute
150
+ or escapes the repository as absent rather than probing an out-of-repo path.
151
+ """
152
+ docs_root = normalize_docs_root(docs_root)
153
+ if os.path.isabs(docs_root):
154
+ return False
155
+ repo = repo_root()
156
+ candidate = (repo / docs_root / "solutions").resolve()
157
+ if repo not in candidate.parents and candidate != repo:
158
+ return False
159
+ return candidate.is_dir()
160
+
161
+
162
+ PACKS_RESOLVER = Path(__file__).resolve().parent / "packs-resolve.py"
163
+ # Parse-only mode does no git or cache work, so this bound only guards against a
164
+ # wedged interpreter; the helper is meant to be cheap and must never hang scope.
165
+ PACKS_RESOLVER_TIMEOUT = 30.0
166
+
167
+
168
+ def declared_packs() -> tuple[bool | None, int]:
169
+ """Whether the local CE config declares Compound Packs, from the config alone.
170
+
171
+ Runs the sibling resolver in `--declared-only` mode, which parses the
172
+ `packs:` list from both CE config layers and shape-checks each entry with no
173
+ git or cache work. Its `declared` is true when any entry parsed or the block
174
+ is malformed -- a broken declaration is still one the learnings pass must
175
+ surface in Coverage. ``None`` means the helper could not tell (resolver
176
+ missing, crashed, timed out, or answered without `declared`); the caller
177
+ then falls closed to reading the config's `packs:` key itself. The second
178
+ value keeps the `pack_roots` output slot and is always 0: nothing resolves
179
+ here.
180
+ """
181
+ if not PACKS_RESOLVER.is_file():
182
+ return None, 0
183
+ try:
184
+ proc = subprocess.run(
185
+ [sys.executable, str(PACKS_RESOLVER), "--declared-only"],
186
+ capture_output=True,
187
+ text=True,
188
+ check=False,
189
+ cwd=repo_root(),
190
+ timeout=PACKS_RESOLVER_TIMEOUT,
191
+ )
192
+ except (OSError, subprocess.TimeoutExpired):
193
+ return None, 0
194
+ if proc.returncode != 0:
195
+ return None, 0
196
+ try:
197
+ data = json.loads(proc.stdout)
198
+ except ValueError:
199
+ return None, 0
200
+ declared = data.get("declared") if isinstance(data, dict) else None
201
+ if not isinstance(declared, bool):
202
+ return None, 0
203
+ return declared, 0
204
+
205
+
206
+ def repo_signals(docs_root: str | None, local_scope: bool) -> dict[str, object]:
207
+ """Facts about the repo, not the diff: present in every result shape.
208
+
209
+ `declared_packs` describes the local checkout's config, which is not the
210
+ reviewed tree's config in remote scope, so it is evaluated only when
211
+ `local_scope` is true and reported as ``None`` otherwise.
212
+ """
213
+ learnings_corpus = has_learnings_corpus(docs_root)
214
+ declared, pack_roots = declared_packs() if local_scope else (None, 0)
215
+ return {
216
+ "has_learnings_corpus": learnings_corpus,
217
+ "declared_packs": declared,
218
+ "pack_roots": pack_roots,
219
+ }
220
+
221
+
222
+ def fail_closed(reason: str, signals: dict[str, object]) -> dict[str, object]:
223
+ return {
224
+ "status": "unknown",
225
+ "reason": reason,
226
+ "exec_lines": None,
227
+ "exec_nontest_lines": None,
228
+ "unclassified_lines": {},
229
+ "changed_lines": None,
230
+ "uncounted_files": 1,
231
+ "changed_files": [],
232
+ "signals": [],
233
+ "hard_block_classes": ["unknown-scope"],
234
+ "hard_block_full": True,
235
+ "silent_pass_classes": [],
236
+ "size_band": "unknown",
237
+ "deleted_files": [],
238
+ "deleted_exec_nontest_lines": None,
239
+ "deleted_band": "unknown",
240
+ "test_files_changed": False,
241
+ "agent_surface": False,
242
+ **signals,
243
+ }
244
+
245
+
246
+ def size_band_for(exec_nontest_lines: int | None) -> str:
247
+ """Band the executable non-test lines: `large` is a full-spine floor.
248
+
249
+ Sources the extension list cannot name are not banded; they are reported
250
+ in `unclassified_lines` for the gate's consequence judgment.
251
+ """
252
+ if exec_nontest_lines is None:
253
+ return "unknown"
254
+ if exec_nontest_lines >= FULL_EXEC_LINE_MIN:
255
+ return "large"
256
+ return "small"
257
+
258
+
259
+ def deleted_band_for(deleted_files: list[str], deleted_exec_nontest_lines: int) -> str:
260
+ if not deleted_files:
261
+ return "none"
262
+ if deleted_exec_nontest_lines >= FULL_EXEC_LINE_MIN:
263
+ return "large"
264
+ return "small"
265
+
266
+
267
+ def matching_classes(
268
+ files: list[str], patterns: dict[str, re.Pattern[str]]
269
+ ) -> list[str]:
270
+ return [
271
+ name
272
+ for name, pattern in patterns.items()
273
+ if any(pattern.search(file) for file in files)
274
+ ]
275
+
276
+
277
+ def numstat_path(name: str) -> str:
278
+ """Return the destination path from a `git diff --numstat` rename display name."""
279
+ if " => " not in name:
280
+ return name
281
+ if "{" in name and "}" in name:
282
+ prefix, rest = name.split("{", 1)
283
+ old_new, suffix = rest.split("}", 1)
284
+ _, new = old_new.split(" => ", 1)
285
+ # A collapsed segment (`a/{b => }/c`) leaves an empty side, so the
286
+ # rebuilt path would carry `//` and miss every path-class pattern.
287
+ return re.sub(r"/{2,}", "/", f"{prefix}{new}{suffix}")
288
+ _, new = name.split(" => ", 1)
289
+ return new
290
+
291
+
292
+ def main() -> int:
293
+ parser = argparse.ArgumentParser()
294
+ parser.add_argument("--base", required=True)
295
+ parser.add_argument("--head")
296
+ parser.add_argument("--docs-root", default="docs")
297
+ args = parser.parse_args()
298
+
299
+ # Remote scope (pr-remote / branch-remote) always passes --head, even when a
300
+ # best-effort fetch left it empty; the local config is not that tree's config.
301
+ repo = repo_signals(args.docs_root, local_scope=args.head is None)
302
+
303
+ if not valid_commit(args.base):
304
+ print(json.dumps(fail_closed("invalid base endpoint", repo), sort_keys=True))
305
+ return 0
306
+ if args.head is not None and not valid_commit(args.head):
307
+ print(json.dumps(fail_closed("invalid head endpoint", repo), sort_keys=True))
308
+ return 0
309
+
310
+ diff_args = [args.base]
311
+ if args.head:
312
+ merge_base = unique_merge_base(args.base, args.head)
313
+ if merge_base is None:
314
+ print(json.dumps(fail_closed("merge base unavailable or ambiguous", repo), sort_keys=True))
315
+ return 0
316
+ diff_args = [merge_base, args.head]
317
+
318
+ # Unquoted non-ASCII paths keep extension checks and manifest paths usable.
319
+ numstat = git("-c", "core.quotePath=false", "diff", "--numstat", *diff_args)
320
+ raw = git("-c", "core.quotePath=false", "diff", "--raw", *diff_args)
321
+ if numstat.returncode != 0 or raw.returncode != 0:
322
+ print(json.dumps(fail_closed("git diff failed", repo), sort_keys=True))
323
+ return 0
324
+
325
+ executable_mode_paths: set[str] = set()
326
+ deleted_paths: set[str] = set()
327
+ for line in raw.stdout.splitlines():
328
+ if "\t" not in line:
329
+ continue
330
+ meta, path_field = line.split("\t", 1)
331
+ fields = meta.lstrip(":").split(" ")
332
+ if len(fields) < 2:
333
+ continue
334
+ if fields[-1] == "D":
335
+ deleted_paths.add(path_field)
336
+ old_mode, new_mode = fields[0], fields[1]
337
+ mode = old_mode if new_mode == "000000" else new_mode
338
+ if not mode.endswith("755"):
339
+ continue
340
+ for path in path_field.split("\t"):
341
+ executable_mode_paths.add(path)
342
+
343
+ files: list[str] = []
344
+ executable_lines = 0
345
+ executable_nontest_lines = 0
346
+ unclassified_lines: dict[str, int] = {}
347
+ changed_lines = 0
348
+ uncounted = 0
349
+ deleted_files: list[str] = []
350
+ deleted_exec_nontest_lines = 0
351
+ for line in numstat.stdout.splitlines():
352
+ parts = line.split("\t")
353
+ if len(parts) < 3:
354
+ continue
355
+ added, deleted, name = parts[0], parts[1], parts[2]
356
+ resolved_name = numstat_path(name)
357
+ files.append(resolved_name)
358
+ ext = Path(resolved_name).suffix.lower()
359
+ is_exec = ext in CODE_EXTENSIONS or resolved_name in executable_mode_paths
360
+ is_test = bool(TEST_PATTERN.search(resolved_name))
361
+ if resolved_name in deleted_paths:
362
+ deleted_files.append(resolved_name)
363
+ if deleted.isdigit():
364
+ changed_lines += int(deleted)
365
+ if is_exec and not is_test:
366
+ deleted_exec_nontest_lines += int(deleted)
367
+ continue
368
+ if added == "-" or deleted == "-":
369
+ uncounted += 1
370
+ continue
371
+ try:
372
+ total = int(added) + int(deleted)
373
+ except ValueError:
374
+ uncounted += 1
375
+ continue
376
+ changed_lines += total
377
+ if is_exec:
378
+ executable_lines += total
379
+ if not is_test:
380
+ executable_nontest_lines += total
381
+ elif not is_test:
382
+ unclassified_lines[ext] = unclassified_lines.get(ext, 0) + total
383
+
384
+ files.sort()
385
+ deleted_files.sort()
386
+ signals = matching_classes(files, SIGNAL_PATTERNS)
387
+ hard_block_classes = matching_classes(files, HARD_BLOCK_PATTERNS)
388
+ silent_pass_classes = matching_classes(files, SILENT_PASS_PATTERNS)
389
+ if uncounted:
390
+ hard_block_classes.append("uncounted")
391
+ band = size_band_for(executable_nontest_lines)
392
+
393
+ result = {
394
+ "status": "complete",
395
+ "reason": None,
396
+ "exec_lines": executable_lines,
397
+ "exec_nontest_lines": executable_nontest_lines,
398
+ "unclassified_lines": unclassified_lines,
399
+ "changed_lines": changed_lines,
400
+ "uncounted_files": uncounted,
401
+ "changed_files": files,
402
+ "signals": signals,
403
+ "hard_block_classes": hard_block_classes,
404
+ "hard_block_full": bool(hard_block_classes) or band != "small",
405
+ "silent_pass_classes": silent_pass_classes,
406
+ "size_band": band,
407
+ "deleted_files": deleted_files,
408
+ "deleted_exec_nontest_lines": deleted_exec_nontest_lines,
409
+ "deleted_band": deleted_band_for(deleted_files, deleted_exec_nontest_lines),
410
+ "test_files_changed": any(TEST_PATTERN.search(file) for file in files),
411
+ "agent_surface": any(AGENT_SURFACE_PATTERN.search(file) for file in files),
412
+ **repo,
413
+ }
414
+ print(json.dumps(result, sort_keys=True))
415
+ return 0
416
+
417
+
418
+ if __name__ == "__main__":
419
+ raise SystemExit(main())
@@ -0,0 +1,280 @@
1
+ #!/usr/bin/env python3
2
+ """Record what a ce-code-review run cost, stage by stage.
3
+
4
+ `event` appends one JSON line per stage boundary to `<run-dir>/stages.jsonl`
5
+ as the run progresses, so a killed run still leaves parseable partial data.
6
+ `summarize` folds those lines, the run directory's artifact bytes, and any
7
+ peer usage file into a `cost` object merged into `<run-dir>/metadata.json`
8
+ without touching the fields already there. Neither subcommand ever fails
9
+ the run: an error leaves `cost.status` as `unavailable` with the reason.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import argparse
15
+ import json
16
+ import os
17
+ import sys
18
+ from datetime import datetime, timezone
19
+ from pathlib import Path
20
+
21
+ STAGES_FILE = "stages.jsonl"
22
+ METADATA_FILE = "metadata.json"
23
+ # Stages whose end marks the receipt being written; a run with one of these
24
+ # ended and no dangling start is complete.
25
+ RECEIPT_STAGES = {"report", "receipt"}
26
+ # The job directory holds detached-runner state, not review output.
27
+ EXCLUDED_DIRS = {"jobs"}
28
+ # Stages that produce candidates; merge and validate only filter them, so
29
+ # their counts stay per stage and never enter the total.
30
+ PRODUCING_STAGES = {"review", "peer", "dispatch"}
31
+
32
+
33
+ def now_iso() -> str:
34
+ return datetime.now(timezone.utc).isoformat()
35
+
36
+
37
+ def parse_iso(value: str) -> datetime | None:
38
+ try:
39
+ return datetime.fromisoformat(value)
40
+ except (TypeError, ValueError):
41
+ return None
42
+
43
+
44
+ def host_from_env() -> str:
45
+ """The same attestation the cross-model reference uses, host only."""
46
+ env = os.environ
47
+ seen = [
48
+ host
49
+ for host, present in (
50
+ ("claude", env.get("CLAUDECODE") == "1"),
51
+ ("codex", any(env.get(k) for k in ("CODEX_SANDBOX", "CODEX_SANDBOX_NETWORK_DISABLED", "CODEX_SESSION_ID", "CODEX_THREAD_ID", "CODEX_CI"))),
52
+ ("grok", env.get("GROK_AGENT") == "1" or bool(env.get("GROK_SESSION_ID"))),
53
+ )
54
+ if present
55
+ ]
56
+ if env.get("OMPCODE"):
57
+ return "omp"
58
+ if len(seen) == 1:
59
+ return seen[0]
60
+ if seen:
61
+ return "unknown"
62
+ if env.get("CURSOR_AGENT") or env.get("CURSOR_CONVERSATION_ID"):
63
+ return "cursor"
64
+ if env.get("OPENCODE_TERMINAL"):
65
+ return "opencode"
66
+ return "unknown"
67
+
68
+
69
+ def parse_facts(items: list[str] | None) -> dict[str, object]:
70
+ facts: dict[str, object] = {}
71
+ for item in items or []:
72
+ key, sep, raw = item.partition("=")
73
+ if not sep or not key:
74
+ continue
75
+ try:
76
+ facts[key] = json.loads(raw)
77
+ except ValueError:
78
+ facts[key] = raw
79
+ return facts
80
+
81
+
82
+ def append_line(run_dir: Path, record: dict[str, object]) -> None:
83
+ run_dir.mkdir(parents=True, exist_ok=True)
84
+ line = json.dumps(record, sort_keys=True) + "\n"
85
+ with (run_dir / STAGES_FILE).open("a", encoding="utf-8") as handle:
86
+ handle.write(line)
87
+ handle.flush()
88
+
89
+
90
+ def cmd_event(args: argparse.Namespace) -> int:
91
+ run_dir = Path(args.run_dir)
92
+ if not args.end and not args.start:
93
+ print("run-log event: nothing to record; pass --end and/or --start", file=sys.stderr)
94
+ return 0
95
+ ts = now_iso()
96
+ extras: dict[str, object] = {}
97
+ if args.reviewers is not None:
98
+ extras["reviewers"] = args.reviewers
99
+ if args.candidates is not None:
100
+ extras["candidates"] = args.candidates
101
+ if args.tokens is not None:
102
+ extras["tokens"] = args.tokens
103
+ if args.note:
104
+ extras["note"] = args.note
105
+ facts = parse_facts(args.fact)
106
+ if facts:
107
+ extras["facts"] = facts
108
+ written = []
109
+ if args.end:
110
+ record = {"ts": ts, "stage": args.end, "phase": "end", **extras}
111
+ append_line(run_dir, record)
112
+ written.append(record)
113
+ if args.start:
114
+ record = {"ts": ts, "stage": args.start, "phase": "start"}
115
+ # Facts and counts describe the stage that just ended; a lone --start
116
+ # carries them so the scope stage can record its helper facts.
117
+ if not args.end:
118
+ record.update(extras)
119
+ append_line(run_dir, record)
120
+ written.append(record)
121
+ print(json.dumps({"written": written}, sort_keys=True))
122
+ return 0
123
+
124
+
125
+ def read_events(run_dir: Path) -> tuple[list[dict[str, object]], int]:
126
+ path = run_dir / STAGES_FILE
127
+ if not path.is_file():
128
+ raise FileNotFoundError(str(path))
129
+ events: list[dict[str, object]] = []
130
+ truncated = 0
131
+ with path.open("r", encoding="utf-8") as handle:
132
+ for raw in handle:
133
+ line = raw.strip()
134
+ if not line:
135
+ continue
136
+ try:
137
+ parsed = json.loads(line)
138
+ except ValueError:
139
+ truncated += 1
140
+ continue
141
+ if isinstance(parsed, dict) and "stage" in parsed and "phase" in parsed:
142
+ events.append(parsed)
143
+ else:
144
+ truncated += 1
145
+ return events, truncated
146
+
147
+
148
+ def artifact_bytes(run_dir: Path) -> int:
149
+ total = 0
150
+ for root, dirs, files in os.walk(run_dir):
151
+ dirs[:] = [d for d in dirs if d not in EXCLUDED_DIRS]
152
+ for name in files:
153
+ try:
154
+ total += (Path(root) / name).stat().st_size
155
+ except OSError:
156
+ continue
157
+ return total
158
+
159
+
160
+ def peer_usage(run_dir: Path) -> dict[str, object] | None:
161
+ for path in sorted(run_dir.glob("adversarial-*-usage.json")):
162
+ try:
163
+ data = json.loads(path.read_text(encoding="utf-8"))
164
+ except (OSError, ValueError):
165
+ continue
166
+ if isinstance(data, dict):
167
+ provider = path.name[len("adversarial-"):-len("-usage.json")]
168
+ return {"provider": provider, **data}
169
+ return None
170
+
171
+
172
+ def build_cost(run_dir: Path) -> dict[str, object]:
173
+ events, truncated = read_events(run_dir)
174
+ stages: list[dict[str, object]] = []
175
+ order: list[str] = []
176
+ open_starts: dict[str, dict[str, object]] = {}
177
+ by_name: dict[str, dict[str, object]] = {}
178
+ scope_facts: dict[str, object] = {}
179
+ for event in events:
180
+ name = str(event["stage"])
181
+ if name not in by_name:
182
+ by_name[name] = {"stage": name}
183
+ order.append(name)
184
+ entry = by_name[name]
185
+ if event["phase"] == "start":
186
+ open_starts[name] = event
187
+ entry["started_at"] = event.get("ts")
188
+ elif event["phase"] == "end":
189
+ entry["ended_at"] = event.get("ts")
190
+ start = open_starts.pop(name, None)
191
+ if start is not None:
192
+ t0, t1 = parse_iso(str(start.get("ts"))), parse_iso(str(event.get("ts")))
193
+ if t0 and t1:
194
+ entry["elapsed_seconds"] = round((t1 - t0).total_seconds(), 3)
195
+ for key in ("reviewers", "candidates", "tokens", "note"):
196
+ if key in event:
197
+ entry[key] = event[key]
198
+ facts = event.get("facts")
199
+ if isinstance(facts, dict):
200
+ entry.setdefault("facts", {}).update(facts)
201
+ if name == "scope":
202
+ scope_facts.update(facts)
203
+ stages = [by_name[name] for name in order]
204
+ dangling = sorted(open_starts)
205
+ receipt_done = any(s.get("ended_at") for s in stages if s["stage"] in RECEIPT_STAGES)
206
+ status = "complete" if receipt_done and not dangling else "partial"
207
+ totals = {
208
+ "elapsed_seconds": round(sum(float(s.get("elapsed_seconds", 0) or 0) for s in stages), 3),
209
+ "reviewers": sum(int(s.get("reviewers", 0) or 0) for s in stages),
210
+ "candidates": sum(int(s.get("candidates", 0) or 0) for s in stages if s["stage"] in PRODUCING_STAGES),
211
+ "tokens": sum(int(s.get("tokens", 0) or 0) for s in stages if "tokens" in s),
212
+ "artifact_bytes": artifact_bytes(run_dir),
213
+ }
214
+ if not any("tokens" in s for s in stages):
215
+ del totals["tokens"]
216
+ cost: dict[str, object] = {
217
+ "status": status,
218
+ "host": host_from_env(),
219
+ "stages": stages,
220
+ "totals": totals,
221
+ "truncated_events": truncated,
222
+ }
223
+ if dangling:
224
+ cost["dangling_stages"] = dangling
225
+ if scope_facts:
226
+ cost["scope"] = scope_facts
227
+ peer = peer_usage(run_dir)
228
+ if peer is not None:
229
+ cost["peer"] = peer
230
+ return cost
231
+
232
+
233
+ def cmd_summarize(args: argparse.Namespace) -> int:
234
+ run_dir = Path(args.run_dir)
235
+ try:
236
+ cost = build_cost(run_dir)
237
+ except FileNotFoundError as exc:
238
+ cost = {"status": "unavailable", "reason": f"no stage log: {exc}"}
239
+ except OSError as exc:
240
+ cost = {"status": "unavailable", "reason": str(exc)}
241
+ metadata_path = run_dir / METADATA_FILE
242
+ metadata: dict[str, object] = {}
243
+ if metadata_path.is_file():
244
+ try:
245
+ loaded = json.loads(metadata_path.read_text(encoding="utf-8"))
246
+ if isinstance(loaded, dict):
247
+ metadata = loaded
248
+ except (OSError, ValueError):
249
+ cost.setdefault("notes", []).append("metadata.json was unreadable and was rewritten")
250
+ metadata["cost"] = cost
251
+ run_dir.mkdir(parents=True, exist_ok=True)
252
+ tmp = metadata_path.with_suffix(".json.tmp")
253
+ tmp.write_text(json.dumps(metadata, indent=2, sort_keys=True) + "\n", encoding="utf-8")
254
+ os.replace(tmp, metadata_path)
255
+ print(json.dumps({"status": cost.get("status"), "metadata": str(metadata_path)}, sort_keys=True))
256
+ return 0
257
+
258
+
259
+ def main() -> int:
260
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
261
+ sub = parser.add_subparsers(dest="command", required=True)
262
+ ev = sub.add_parser("event", help="record a stage boundary")
263
+ ev.add_argument("--run-dir", required=True)
264
+ ev.add_argument("--end", help="stage that just ended")
265
+ ev.add_argument("--start", help="stage that starts now")
266
+ ev.add_argument("--reviewers", type=int)
267
+ ev.add_argument("--candidates", type=int)
268
+ ev.add_argument("--tokens", type=int)
269
+ ev.add_argument("--note")
270
+ ev.add_argument("--fact", action="append", help="key=value (value parsed as JSON when possible)")
271
+ ev.set_defaults(func=cmd_event)
272
+ sm = sub.add_parser("summarize", help="fold the stage log into metadata.json")
273
+ sm.add_argument("--run-dir", required=True)
274
+ sm.set_defaults(func=cmd_summarize)
275
+ args = parser.parse_args()
276
+ return args.func(args)
277
+
278
+
279
+ if __name__ == "__main__":
280
+ raise SystemExit(main())