dsh-compound-engineering 0.0.0-stage → 0.1.1

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,929 @@
1
+ #!/usr/bin/env bash
2
+ # Compound Engineering environment health check.
3
+ # Reports optional tool capabilities and repo-local config safety in one pass.
4
+
5
+ set -o pipefail
6
+
7
+ # =====================================================
8
+ # Optional capability config
9
+ # =====================================================
10
+ # Format: name|install_cmd|url|capability
11
+
12
+ deps=(
13
+ "agent-browser|CI=true npm install -g agent-browser --no-audit --no-fund --loglevel=error && agent-browser install|https://github.com/vercel-labs/agent-browser|browser testing and dogfood QA"
14
+ "gh|NONINTERACTIVE=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install -q gh|https://cli.github.com|GitHub PR, issue, and review workflows"
15
+ "jq|NONINTERACTIVE=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install -q jq|https://jqlang.github.io/jq/|JSON inspection in shell-based workflows"
16
+ "ast-grep|NONINTERACTIVE=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install -q ast-grep|https://ast-grep.github.io|syntax-aware structural code search"
17
+ "ffmpeg|NONINTERACTIVE=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install -q ffmpeg|https://ffmpeg.org/download.html|media chunking and screenshot extraction for Riffrec analysis"
18
+ )
19
+
20
+ # Cross-model peers run `npx acpx@<pin>`, which launches the codex and claude
21
+ # adapters below. The version must match ACPX_VERSION in the peer workers; the
22
+ # adapter specs are the ranges that acpx version launches. One line each: the
23
+ # pin-bump canary rewrites them in place.
24
+ ACPX_VERSION="0.21.0"
25
+ ACPX_ADAPTER_SPECS="@agentclientprotocol/codex-acp@^1.1.5 @agentclientprotocol/claude-agent-acp@^0.81.2"
26
+
27
+ # =====================================================
28
+ # Args
29
+ # =====================================================
30
+
31
+ plugin_version=""
32
+ warm_acpx="no"
33
+ while [ $# -gt 0 ]; do
34
+ case "$1" in
35
+ --version) [ -n "$2" ] && plugin_version="$2" && shift 2 || shift ;;
36
+ --warm-acpx) warm_acpx="yes"; shift ;;
37
+ *) shift ;;
38
+ esac
39
+ done
40
+
41
+ # =====================================================
42
+ # Helpers
43
+ # =====================================================
44
+
45
+ ok() { echo " 🟢 $1"; }
46
+ warn() { echo " 🟡 $1"; }
47
+ skip() { echo " ➖ $1"; }
48
+ detail() { echo " $1"; }
49
+ section() { echo ""; echo " $1"; }
50
+
51
+ # Read one top-level scalar from the repo's flat local-config convention. This is
52
+ # intentionally not a general YAML parser: comments and absent/empty keys are
53
+ # ignored, surrounding quotes are removed, and values are never evaluated.
54
+ read_flat_config_value() {
55
+ local config_file="$1"
56
+ local config_key="$2"
57
+ local value
58
+ value=$(awk -v key="$config_key" '
59
+ $0 ~ "^" key "[[:space:]]*:" {
60
+ sub("^" key "[[:space:]]*:[[:space:]]*", "")
61
+ sub(/[[:space:]]+#.*$/, "")
62
+ sub(/^[[:space:]]+/, "")
63
+ sub(/[[:space:]]+$/, "")
64
+ print
65
+ exit
66
+ }
67
+ ' "$config_file")
68
+
69
+ case "$value" in
70
+ \"*\") value=${value#\"}; value=${value%\"} ;;
71
+ \'*\') value=${value#\'}; value=${value%\'} ;;
72
+ esac
73
+ printf '%s' "$value"
74
+ }
75
+
76
+ # Resolve the symlink-followed absolute path of $1 without relying on `realpath -m`
77
+ # (absent on stock macOS/BSD). Resolves the existing prefix with `cd`/`pwd -P`,
78
+ # then re-appends any not-yet-created tail — enough to catch a symlink in the
79
+ # existing portion escaping the repository, which is the only way a relative
80
+ # value can escape.
81
+ resolve_real_best_effort() {
82
+ local target="$1" tail="" existing base
83
+ existing="$target"
84
+ while [ ! -e "$existing" ] && [ "$existing" != "/" ] && [ "$existing" != "." ] && [ "$existing" != "$(dirname "$existing")" ]; do
85
+ tail="/$(basename "$existing")$tail"
86
+ existing="$(dirname "$existing")"
87
+ done
88
+ if [ -d "$existing" ]; then
89
+ base="$(cd "$existing" 2>/dev/null && pwd -P)" || return 1
90
+ elif [ -e "$existing" ]; then
91
+ base="$(cd "$(dirname "$existing")" 2>/dev/null && pwd -P)/$(basename "$existing")" || return 1
92
+ else
93
+ return 1
94
+ fi
95
+ printf '%s' "${base}${tail}"
96
+ }
97
+
98
+ # Resolve docs_root from tracked config.yaml only. A docs_root in
99
+ # config.local.yaml is ignored. Unset -> default root `docs`. A configured
100
+ # value is validated and rejected (never silently defaulted) when it is
101
+ # absolute, escapes the repository via path or symlink, resolves to the repo
102
+ # root or inside .git/, or names an existing non-directory. Sets
103
+ # docs_root_status (default|configured|invalid), docs_root_value,
104
+ # docs_root_source, docs_root_error, and docs_root_local_ignored.
105
+ resolve_docs_root() {
106
+ local repo_root="$1"
107
+ local local_cfg="$repo_root/.compound-engineering/config.local.yaml"
108
+ local tracked_cfg="$repo_root/.compound-engineering/config.yaml"
109
+ local value="" source="" repo_real real local_docs probe
110
+
111
+ docs_root_error=""
112
+ docs_root_local_ignored=""
113
+ if [ -f "$local_cfg" ]; then
114
+ local_docs=$(read_flat_config_value "$local_cfg" "docs_root")
115
+ [ -n "$local_docs" ] && docs_root_local_ignored="$local_docs"
116
+ fi
117
+ if [ -f "$tracked_cfg" ]; then
118
+ value=$(read_flat_config_value "$tracked_cfg" "docs_root")
119
+ [ -n "$value" ] && source="config.yaml"
120
+ fi
121
+
122
+ if [ -z "$value" ]; then
123
+ docs_root_status="default"; docs_root_value="docs"; docs_root_source="default"; return
124
+ fi
125
+
126
+ docs_root_value="$value"; docs_root_source="$source"; docs_root_status="invalid"
127
+ case "$value" in
128
+ /*) docs_root_error="absolute paths are not allowed; use a repo-relative path"; return ;;
129
+ esac
130
+ # Reject any `..` path component up front. resolve_real_best_effort only
131
+ # collapses `..` within the existing prefix (via cd/pwd -P); a `..` that
132
+ # traverses a not-yet-created segment would otherwise survive literally and
133
+ # escape the repo, hit the repo root, or reach .git/ while still string-prefix
134
+ # matching. A legitimate repo-relative artifact root never needs `..`.
135
+ case "/$value/" in
136
+ */../*) docs_root_error="path traversal ('..') is not allowed; use a plain repo-relative path"; return ;;
137
+ esac
138
+ repo_real="$(cd "$repo_root" 2>/dev/null && pwd -P)" || { docs_root_error="could not resolve the repository root"; return; }
139
+ real="$(resolve_real_best_effort "$repo_root/$value")" || { docs_root_error="could not resolve the path"; return; }
140
+ case "$real/" in
141
+ "$repo_real/"*) ;;
142
+ *) docs_root_error="resolves outside the repository ($real)"; return ;;
143
+ esac
144
+ [ "$real" = "$repo_real" ] && { docs_root_error="resolves to the repository root itself"; return; }
145
+ case "$real/" in
146
+ "$repo_real/.git/"*) docs_root_error="resolves inside .git/"; return ;;
147
+ esac
148
+ if [ -e "$real" ] && [ ! -d "$real" ]; then
149
+ docs_root_error="names an existing non-directory"; return
150
+ fi
151
+ # Reject when an intermediate component is an existing non-directory (e.g.
152
+ # `afile/nested` where `afile` is a file): the leaf-only check above passes
153
+ # because `$real` itself does not exist, but `mkdir -p` would fail. Walk up to
154
+ # the deepest existing ancestor and require it be a directory.
155
+ probe="$real"
156
+ while [ ! -e "$probe" ] && [ "$probe" != "/" ] && [ "$probe" != "$(dirname "$probe")" ]; do
157
+ probe="$(dirname "$probe")"
158
+ done
159
+ if [ -e "$probe" ] && [ ! -d "$probe" ]; then
160
+ docs_root_error="an intermediate path component is not a directory"; return
161
+ fi
162
+ docs_root_status="configured"
163
+ }
164
+
165
+ # Report whether a retired top-level key is still present without interpreting
166
+ # its value. Detection is intentionally separate from routing so legacy scalar
167
+ # settings can receive a migration diagnostic without remaining supported.
168
+ has_flat_config_key() {
169
+ local config_file="$1"
170
+ local config_key="$2"
171
+ awk -v key="$config_key" '
172
+ $0 ~ "^" key "[[:space:]]*:" { found = 1 }
173
+ END { exit(found ? 0 : 1) }
174
+ ' "$config_file"
175
+ }
176
+
177
+ # First non-empty ordinary scalar across local then tracked. Empty/commented
178
+ # local continues to tracked. Sets ordinary_value and ordinary_source.
179
+ resolve_ordinary_scalar() {
180
+ local local_file="$1"
181
+ local tracked_file="$2"
182
+ local config_key="$3"
183
+ local value=""
184
+ ordinary_value=""
185
+ ordinary_source=""
186
+ if [ -f "$local_file" ]; then
187
+ value=$(read_flat_config_value "$local_file" "$config_key")
188
+ if [ -n "$value" ]; then
189
+ ordinary_value="$value"
190
+ ordinary_source="config.local.yaml"
191
+ return
192
+ fi
193
+ fi
194
+ if [ -f "$tracked_file" ]; then
195
+ value=$(read_flat_config_value "$tracked_file" "$config_key")
196
+ if [ -n "$value" ]; then
197
+ ordinary_value="$value"
198
+ ordinary_source="config.yaml"
199
+ fi
200
+ fi
201
+ }
202
+
203
+ # Present list/map key (including `[]`) wins that layer. Sets
204
+ # structured_file, or empty when neither layer sets the key.
205
+ resolve_structured_layer() {
206
+ local local_file="$1"
207
+ local tracked_file="$2"
208
+ local config_key="$3"
209
+ structured_file=""
210
+ if [ -f "$local_file" ] && has_flat_config_key "$local_file" "$config_key"; then
211
+ structured_file="$local_file"
212
+ return
213
+ fi
214
+ if [ -f "$tracked_file" ] && has_flat_config_key "$tracked_file" "$config_key"; then
215
+ structured_file="$tracked_file"
216
+ fi
217
+ }
218
+
219
+ # Read the narrow YAML sequence used by work_engine_preferences. The local
220
+ # config remains human-authored YAML, but setup health needs only this one
221
+ # deterministic shape rather than a general parser.
222
+ read_work_engine_preferences() {
223
+ local config_file="$1"
224
+ awk '
225
+ function trim(value) {
226
+ sub(/^[[:space:]]+/, "", value)
227
+ sub(/[[:space:]]+$/, "", value)
228
+ return value
229
+ }
230
+ function scalar(value) {
231
+ sub(/[[:space:]]+#.*$/, "", value)
232
+ value = trim(value)
233
+ if (value ~ /^".*"$/ || value ~ /^\047.*\047$/) {
234
+ value = substr(value, 2, length(value) - 2)
235
+ }
236
+ return value
237
+ }
238
+ function emit_item() {
239
+ if (!have_item) return
240
+ if (harness == "" && model != "") {
241
+ print "ERROR\tmodel \047" model "\047 has no harness in work_engine_preferences"
242
+ } else if (harness == "") {
243
+ print "ERROR\tempty item in work_engine_preferences"
244
+ } else {
245
+ print "ITEM\t" harness "\t" (model == "" ? "default" : model)
246
+ }
247
+ have_item = 0
248
+ harness = ""
249
+ model = ""
250
+ }
251
+ /^[^[:space:]#-][^:]*[[:space:]]*:/ {
252
+ if (active) {
253
+ emit_item()
254
+ active = 0
255
+ }
256
+ }
257
+ /^work_engine_preferences[[:space:]]*:/ {
258
+ active = 1
259
+ next
260
+ }
261
+ active {
262
+ line = $0
263
+ if (line ~ /^[[:space:]]*($|#)/) next
264
+ if (line ~ /^[[:space:]]*-[[:space:]]*harness[[:space:]]*:/) {
265
+ emit_item()
266
+ sub(/^[[:space:]]*-[[:space:]]*harness[[:space:]]*:[[:space:]]*/, "", line)
267
+ harness = scalar(line)
268
+ have_item = 1
269
+ next
270
+ }
271
+ if (line ~ /^[[:space:]]*-[[:space:]]*model[[:space:]]*:/) {
272
+ emit_item()
273
+ sub(/^[[:space:]]*-[[:space:]]*model[[:space:]]*:[[:space:]]*/, "", line)
274
+ model = scalar(line)
275
+ have_item = 1
276
+ next
277
+ }
278
+ if (line ~ /^[[:space:]]+model[[:space:]]*:/) {
279
+ sub(/^[[:space:]]+model[[:space:]]*:[[:space:]]*/, "", line)
280
+ model = scalar(line)
281
+ if (!have_item) have_item = 1
282
+ next
283
+ }
284
+ if (line ~ /^[[:space:]]+harness[[:space:]]*:/) {
285
+ sub(/^[[:space:]]+harness[[:space:]]*:[[:space:]]*/, "", line)
286
+ harness = scalar(line)
287
+ if (!have_item) have_item = 1
288
+ next
289
+ }
290
+ print "ERROR\tunsupported work_engine_preferences entry: " trim(line)
291
+ }
292
+ END {
293
+ if (active) emit_item()
294
+ }
295
+ ' "$config_file"
296
+ }
297
+
298
+ # Emits KEY<TAB>harness<TAB>effort per map entry, or ERROR when the value is not
299
+ # a map. An entry is exactly `harness: token`, optionally quoted, because an
300
+ # effort must be a plain token; this is the data contract, not a YAML parser.
301
+ # Only Antigravity's levels are checked here: its three thinking levels are
302
+ # fixed, while other harnesses' levels belong to the ce-work adapter.
303
+ read_work_engine_effort_keys() {
304
+ local config_file="$1"
305
+ awk '
306
+ function emit_entry(entry) {
307
+ sub(/[[:space:]]+#.*$/, "", entry)
308
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", entry)
309
+ # A key or value is a bare token or one wrapped in a matching quote pair.
310
+ token = "[A-Za-z0-9][A-Za-z0-9_-]*"
311
+ quoted = "(" token "|\"" token "\"|\047" token "\047)"
312
+ if (entry !~ ("^" quoted "[[:space:]]*:[[:space:]]*" quoted "$")) not_a_map()
313
+ gsub(/["\047]/, "", entry)
314
+ key = entry
315
+ sub(/[[:space:]]*:.*$/, "", key)
316
+ sub(/^[^:]*:[[:space:]]*/, "", entry)
317
+ print "KEY\t" key "\t" entry
318
+ entries++
319
+ }
320
+ function not_a_map() {
321
+ print "ERROR"
322
+ reported = 1
323
+ exit
324
+ }
325
+ # A block that ends with no entries is a null value, not the explicit empty map {}.
326
+ function close_block() {
327
+ if (active && !entries) not_a_map()
328
+ active = 0
329
+ }
330
+ /^[^[:space:]#-][^:]*[[:space:]]*:/ { close_block() }
331
+ /^work_engine_effort[[:space:]]*:/ {
332
+ active = 1
333
+ entries = 0
334
+ line = $0
335
+ sub(/^work_engine_effort[[:space:]]*:/, "", line)
336
+ sub(/[[:space:]]+#.*$/, "", line)
337
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
338
+ if (line == "") next
339
+ if (line !~ /^\{.*\}$/) not_a_map()
340
+ line = substr(line, 2, length(line) - 2)
341
+ count = split(line, pairs, ",")
342
+ for (i = 1; i <= count; i++) {
343
+ if (pairs[i] ~ /^[[:space:]]*$/) {
344
+ if (i < count) not_a_map()
345
+ continue
346
+ }
347
+ emit_entry(pairs[i])
348
+ }
349
+ active = 0
350
+ next
351
+ }
352
+ active {
353
+ line = $0
354
+ if (line ~ /^[[:space:]]*($|#)/) next
355
+ if (line !~ /^[[:space:]]/) not_a_map()
356
+ emit_entry(line)
357
+ }
358
+ END { if (!reported) close_block() }
359
+ ' "$config_file"
360
+ }
361
+
362
+ # Same prerequisite the peer workers check before launching acpx. Sets
363
+ # node_version and, when unmet, node_problem.
364
+ check_node_prerequisite() {
365
+ local major minor
366
+ node_version=""; node_problem=""
367
+ if ! command -v node >/dev/null 2>&1; then
368
+ node_problem="node not found; cross-model peers need Node 22.13 or newer"; return 1
369
+ fi
370
+ node_version="$(node -p 'process.versions.node' 2>/dev/null | tr -d '\r')"
371
+ node_version="${node_version#v}"
372
+ major="${node_version%%.*}"; minor="${node_version#*.}"; minor="${minor%%.*}"
373
+ case "$major$minor" in
374
+ ''|*[!0-9]*) node_problem="cannot read the Node version; cross-model peers need Node 22.13 or newer"; return 1 ;;
375
+ esac
376
+ if [ "$major" -lt 22 ] || { [ "$major" -eq 22 ] && [ "$minor" -lt 13 ]; }; then
377
+ node_problem="Node $node_version is too old; cross-model peers need Node 22.13 or newer"; return 1
378
+ fi
379
+ if ! command -v npx >/dev/null 2>&1; then
380
+ node_problem="npx not found; cross-model peers run acpx through npx"; return 1
381
+ fi
382
+ }
383
+
384
+ # Installs each pinned package into npx's cache under the same key a later
385
+ # `npx -y <spec>` uses, then runs `node --version` instead of the package, so the
386
+ # package itself never starts. npm still runs its install lifecycle scripts, as
387
+ # it would on a first peer run.
388
+ if [ "$warm_acpx" = "yes" ]; then
389
+ echo ""
390
+ if ! check_node_prerequisite; then
391
+ warn "Cannot warm the npm cache: $node_problem"
392
+ echo ""
393
+ exit 1
394
+ fi
395
+ warm_failed=0
396
+ # Run from an empty directory, as the peer workers do: npx resolves packages
397
+ # from its working directory's node_modules and .npmrc first.
398
+ warm_dir="$(mktemp -d "${TMPDIR:-/tmp}/ce-acpx-warm-XXXXXX")" || { warn "Cannot warm the npm cache: no temporary directory"; echo ""; exit 1; }
399
+ for spec in "acpx@$ACPX_VERSION" $ACPX_ADAPTER_SPECS; do
400
+ if (cd "$warm_dir" && npx --yes --package="$spec" -- node --version >/dev/null); then
401
+ ok "cached $spec"
402
+ else
403
+ warn "could not fetch $spec"
404
+ warm_failed=1
405
+ fi
406
+ done
407
+ rmdir "$warm_dir" 2>/dev/null
408
+ echo ""
409
+ exit "$warm_failed"
410
+ fi
411
+
412
+ has_brew=$(command -v brew >/dev/null 2>&1 && echo "yes" || echo "no")
413
+ in_repo=$(git rev-parse --is-inside-work-tree >/dev/null 2>&1 && echo "yes" || echo "no")
414
+
415
+ # Retired Bun-era Codex tool map (#1099). The block is present only when a
416
+ # standalone BEGIN line is followed by a standalone END line.
417
+ has_codex_tool_map() {
418
+ awk '
419
+ { sub(/\r$/, "") }
420
+ $0 == "<!-- BEGIN COMPOUND CODEX TOOL MAP -->" { seen = 1 }
421
+ seen && $0 == "<!-- END COMPOUND CODEX TOOL MAP -->" { found = 1; exit }
422
+ END { exit found ? 0 : 1 }
423
+ ' "$1"
424
+ }
425
+
426
+ codex_agents_file="${CODEX_HOME:-$HOME/.codex}/AGENTS.md"
427
+ legacy_codex_map="no"
428
+ if [ -f "$codex_agents_file" ] && has_codex_tool_map "$codex_agents_file"; then
429
+ legacy_codex_map="yes"
430
+ fi
431
+
432
+ # =====================================================
433
+ # Check optional capabilities
434
+ # =====================================================
435
+
436
+ capability_ok=0
437
+ capability_total=0
438
+ capability_missing=0
439
+ results=()
440
+
441
+ for entry in "${deps[@]}"; do
442
+ IFS='|' read -r name install_cmd url capability < <(printf '%s\n' "$entry")
443
+ capability_total=$((capability_total + 1))
444
+ if command -v "$name" >/dev/null 2>&1; then
445
+ capability_ok=$((capability_ok + 1))
446
+ results+=("$name|ok|$install_cmd|$url|$capability")
447
+ else
448
+ capability_missing=$((capability_missing + 1))
449
+ results+=("$name|missing|$install_cmd|$url|$capability")
450
+ fi
451
+ done
452
+
453
+ capability_total=$((capability_total + 1))
454
+ if check_node_prerequisite; then
455
+ capability_ok=$((capability_ok + 1))
456
+ node_row="ok"
457
+ else
458
+ capability_missing=$((capability_missing + 1))
459
+ node_row="missing"
460
+ fi
461
+
462
+ # =====================================================
463
+ # Project checks (repo only)
464
+ # =====================================================
465
+
466
+ legacy_cfg="skip"
467
+ repo_cfg_gitignore="skip"
468
+ scratch_gitignore="skip"
469
+ local_cfg="skip"
470
+ example_cfg="skip"
471
+ retired_keys=()
472
+ work_engine_cfg="skip"
473
+ work_engine_detail=""
474
+ work_engine_preferences_note=""
475
+ work_engine_preferences_note_level="detail"
476
+ work_engine_migration_note=""
477
+ docs_root_status="skip"
478
+ docs_root_value=""
479
+ docs_root_source=""
480
+ docs_root_error=""
481
+ docs_root_local_ignored=""
482
+ tracked_cfg="skip"
483
+ project_issues=0
484
+ antigravity_configured="no"
485
+
486
+ if [ "$in_repo" = "yes" ]; then
487
+ repo_root=$(git rev-parse --show-toplevel 2>/dev/null)
488
+ local_config_path="$repo_root/.compound-engineering/config.local.yaml"
489
+ tracked_config_path="$repo_root/.compound-engineering/config.yaml"
490
+ resolve_docs_root "$repo_root"
491
+ [ "$docs_root_status" = "invalid" ] && project_issues=$((project_issues + 1))
492
+ legacy_cfg="missing"
493
+ [ -f "$repo_root/compound-engineering.local.md" ] && legacy_cfg="present"
494
+
495
+ local_cfg="missing"
496
+ if [ -e "$local_config_path" ]; then
497
+ local_cfg="present"
498
+ if git check-ignore -q "$local_config_path" 2>/dev/null; then
499
+ repo_cfg_gitignore="ok"
500
+ else
501
+ repo_cfg_gitignore="missing"
502
+ fi
503
+ fi
504
+
505
+ # Trailing slash is load-bearing: without it an existing directory-only rule
506
+ # is missed before the directory exists, and a configured repo reads as bare.
507
+ scratch_gitignore="missing"
508
+ if git -C "$repo_root" check-ignore -q .context/compound-engineering/ 2>/dev/null; then
509
+ scratch_gitignore="ok"
510
+ fi
511
+
512
+ tracked_cfg="missing"
513
+ [ -f "$tracked_config_path" ] && tracked_cfg="present"
514
+
515
+ resolve_ordinary_scalar "$local_config_path" "$tracked_config_path" "cross_model_peer"
516
+ [ "$ordinary_value" = "antigravity" ] && antigravity_configured="yes"
517
+
518
+ resolve_ordinary_scalar "$local_config_path" "$tracked_config_path" "work_engine_mode"
519
+ work_engine_mode="$ordinary_value"
520
+ case "$work_engine_mode" in
521
+ ""|off|prefer|require) ;;
522
+ *)
523
+ if [ "$ordinary_source" = "config.local.yaml" ]; then
524
+ if [ -f "$tracked_config_path" ]; then
525
+ work_engine_mode=$(read_flat_config_value "$tracked_config_path" "work_engine_mode")
526
+ else
527
+ work_engine_mode=""
528
+ fi
529
+ fi
530
+ ;;
531
+ esac
532
+
533
+ resolve_structured_layer "$local_config_path" "$tracked_config_path" "work_engine_preferences"
534
+ work_engine_preferences_count=0
535
+ work_engine_preferences_detail=""
536
+ work_engine_preferences_error=""
537
+ retired_work_engine_keys=""
538
+ for retired_key in work_engine_target work_engine_model; do
539
+ if { [ -f "$local_config_path" ] && has_flat_config_key "$local_config_path" "$retired_key"; } || \
540
+ { [ -f "$tracked_config_path" ] && has_flat_config_key "$tracked_config_path" "$retired_key"; }; then
541
+ if [ -n "$retired_work_engine_keys" ]; then
542
+ retired_work_engine_keys="${retired_work_engine_keys}, ${retired_key}"
543
+ else
544
+ retired_work_engine_keys="$retired_key"
545
+ fi
546
+ fi
547
+ done
548
+ if [ -n "$retired_work_engine_keys" ]; then
549
+ work_engine_migration_note="retired config key(s) ${retired_work_engine_keys} detected; migrate routing to work_engine_preferences entries with harness and optional model fields, then remove the retired keys"
550
+ project_issues=$((project_issues + 1))
551
+ fi
552
+ if [ -n "$structured_file" ]; then
553
+ while IFS=$'\t' read -r preference_kind preference_harness preference_model; do
554
+ case "$preference_kind" in
555
+ ITEM)
556
+ work_engine_preferences_count=$((work_engine_preferences_count + 1))
557
+ case "$preference_harness" in
558
+ codex|claude|grok|cursor|opencode) ;;
559
+ antigravity) antigravity_configured="yes" ;;
560
+ *)
561
+ [ -z "$work_engine_preferences_error" ] && work_engine_preferences_error="invalid harness '$preference_harness' in work_engine_preferences"
562
+ ;;
563
+ esac
564
+ if [ "$preference_model" != "default" ]; then
565
+ case "$preference_model" in
566
+ [A-Za-z0-9]*)
567
+ case "$preference_model" in
568
+ *[!A-Za-z0-9._:/-]*)
569
+ [ -z "$work_engine_preferences_error" ] && work_engine_preferences_error="invalid model '$preference_model' in work_engine_preferences"
570
+ ;;
571
+ esac
572
+ ;;
573
+ *)
574
+ [ -z "$work_engine_preferences_error" ] && work_engine_preferences_error="invalid model '$preference_model' in work_engine_preferences"
575
+ ;;
576
+ esac
577
+ fi
578
+ preference_display="${preference_harness}@${preference_model}"
579
+ if [ -n "$work_engine_preferences_detail" ]; then
580
+ work_engine_preferences_detail="${work_engine_preferences_detail}, ${preference_display}"
581
+ else
582
+ work_engine_preferences_detail="$preference_display"
583
+ fi
584
+ ;;
585
+ ERROR)
586
+ [ -z "$work_engine_preferences_error" ] && work_engine_preferences_error="$preference_harness"
587
+ ;;
588
+ esac
589
+ done < <(read_work_engine_preferences "$structured_file")
590
+ fi
591
+
592
+ work_engine_effort_notes=()
593
+ resolve_structured_layer "$local_config_path" "$tracked_config_path" "work_engine_effort"
594
+ if [ -n "$structured_file" ]; then
595
+ while IFS=$'\t' read -r effort_kind effort_harness effort_value; do
596
+ case "$effort_kind:$effort_harness" in
597
+ ERROR:*) effort_problem="is not a map of harness to effort; ce-work ignores the value and keeps each harness default" ;;
598
+ KEY:cursor) effort_problem="names 'cursor', which takes no effort; ce-work treats Cursor entries as unavailable while it is set" ;;
599
+ KEY:codex|KEY:claude|KEY:grok|KEY:opencode) continue ;;
600
+ KEY:antigravity)
601
+ case "$effort_value" in low|medium|high) continue ;; esac
602
+ effort_problem="sets antigravity to '${effort_value}'; Antigravity takes low, medium, or high, so ce-work treats Antigravity entries as unavailable while it is set" ;;
603
+ KEY:*) effort_problem="names unknown harness '${effort_harness}'; ce-work ignores that entry" ;;
604
+ *) continue ;;
605
+ esac
606
+ work_engine_effort_notes+=("work_engine_effort in $(basename "$structured_file") ${effort_problem}")
607
+ done < <(read_work_engine_effort_keys "$structured_file")
608
+ fi
609
+
610
+ case "$work_engine_mode" in
611
+ ""|off)
612
+ work_engine_cfg="native"
613
+ if [ -n "$work_engine_mode" ]; then
614
+ work_engine_detail="standing preference is off"
615
+ else
616
+ work_engine_detail="setting is commented or missing"
617
+ fi
618
+ if [ -n "$work_engine_preferences_error" ]; then
619
+ work_engine_preferences_note="invalid dormant work_engine_preferences: ${work_engine_preferences_error}"
620
+ work_engine_preferences_note_level="warn"
621
+ project_issues=$((project_issues + 1))
622
+ elif [ "$work_engine_preferences_count" -gt 0 ]; then
623
+ work_engine_preferences_note="ordered preferences ignored while standing mode is off"
624
+ fi
625
+ ;;
626
+ prefer|require)
627
+ if [ -n "$work_engine_preferences_error" ]; then
628
+ work_engine_cfg="unavailable"
629
+ work_engine_detail="$work_engine_preferences_error"
630
+ project_issues=$((project_issues + 1))
631
+ elif [ "$work_engine_preferences_count" -eq 0 ] && [ -n "$retired_work_engine_keys" ]; then
632
+ work_engine_cfg="unavailable"
633
+ work_engine_detail="$work_engine_mode cannot use retired scalar routing; migrate ${retired_work_engine_keys} to work_engine_preferences"
634
+ elif [ "$work_engine_preferences_count" -eq 0 ]; then
635
+ work_engine_cfg="unavailable"
636
+ work_engine_detail="$work_engine_mode requires work_engine_preferences"
637
+ project_issues=$((project_issues + 1))
638
+ else
639
+ work_engine_cfg="$work_engine_mode"
640
+ work_engine_detail="$work_engine_preferences_detail"
641
+ fi
642
+ ;;
643
+ *)
644
+ work_engine_cfg="invalid"
645
+ work_engine_detail="invalid mode '$work_engine_mode' ignored; native is the default"
646
+ project_issues=$((project_issues + 1))
647
+ ;;
648
+ esac
649
+
650
+ script_dir="$(cd "$(dirname "$0")" && pwd)"
651
+ template="$script_dir/../references/config-template.yaml"
652
+ example="$repo_root/.compound-engineering/config.example.yaml"
653
+ if [ ! -f "$example" ]; then
654
+ example_cfg="missing"
655
+ elif [ -f "$template" ] && ! diff -q "$template" "$example" >/dev/null 2>&1; then
656
+ example_cfg="outdated"
657
+ else
658
+ example_cfg="ok"
659
+ fi
660
+
661
+ # Retired keys set as ACTIVE (non-commented) in either layer. A
662
+ # commented `# plan_use_fable:` line does not match `^[[:space:]]*<key>:`.
663
+ for cfg_file in "$local_config_path" "$tracked_config_path"; do
664
+ [ -f "$cfg_file" ] || continue
665
+ for key in plan_use_fable brainstorm_use_fable fable_nudge; do
666
+ if grep -Eq "^[[:space:]]*${key}[[:space:]]*:" "$cfg_file" 2>/dev/null; then
667
+ already=""
668
+ for seen in "${retired_keys[@]}"; do
669
+ [ "$seen" = "$key" ] && already=1
670
+ done
671
+ [ -z "$already" ] && retired_keys+=("$key")
672
+ fi
673
+ done
674
+ done
675
+ fi
676
+
677
+ # Same runtime and helper the peer workers resolve before launching the
678
+ # antigravity route. Reported only when the user configured it or installed it.
679
+ antigravity_row="skip"
680
+ antigravity_problem=""
681
+ antigravity_runtime="$(command -v agy_acp_server.par 2>/dev/null)"
682
+ if [ "$antigravity_configured" = "yes" ] || [ -n "$antigravity_runtime" ]; then
683
+ capability_total=$((capability_total + 1))
684
+ antigravity_helper="${ANTIGRAVITY_HARNESS_PATH:-$(dirname "${antigravity_runtime:-.}")/localharness_external}"
685
+ if [ -z "$antigravity_runtime" ]; then
686
+ antigravity_problem="agy_acp_server.par not found on PATH; install Antigravity's ACP runtime"
687
+ elif [ ! -x "$antigravity_helper" ]; then
688
+ antigravity_problem="localharness_external not found at ${antigravity_helper}; install it from the same release as the runtime"
689
+ fi
690
+ if [ -z "$antigravity_problem" ]; then
691
+ capability_ok=$((capability_ok + 1))
692
+ antigravity_row="ok"
693
+ else
694
+ capability_missing=$((capability_missing + 1))
695
+ antigravity_row="missing"
696
+ fi
697
+ fi
698
+
699
+ # =====================================================
700
+ # Output
701
+ # =====================================================
702
+
703
+ echo ""
704
+ if [ -n "$plugin_version" ]; then
705
+ ok "Plugin version v${plugin_version}"
706
+ fi
707
+
708
+ section "Optional capabilities ${capability_ok}/${capability_total}"
709
+
710
+ for result in "${results[@]}"; do
711
+ IFS='|' read -r name status install_cmd url capability < <(printf '%s\n' "$result")
712
+ if [ "$status" = "ok" ]; then
713
+ ok "$name -- $capability"
714
+ else
715
+ warn "$name -- unavailable: $capability"
716
+ if [[ "$install_cmd" == *"brew install"* ]] && [ "$has_brew" != "yes" ]; then
717
+ detail "$url"
718
+ else
719
+ detail "$install_cmd"
720
+ detail "$url"
721
+ fi
722
+ fi
723
+ done
724
+
725
+ if [ "$node_row" = "ok" ]; then
726
+ ok "node -- cross-model peers (Node $node_version, npx)"
727
+ else
728
+ warn "node -- unavailable: cross-model peers"
729
+ detail "$node_problem"
730
+ detail "https://nodejs.org/en/download"
731
+ fi
732
+
733
+ if [ "$antigravity_row" = "ok" ]; then
734
+ ok "antigravity -- Gemini cross-model peer (runtime and helper found)"
735
+ elif [ "$antigravity_row" = "missing" ]; then
736
+ warn "antigravity -- unavailable: Gemini cross-model peer"
737
+ detail "$antigravity_problem"
738
+ detail "https://github.com/agentclientprotocol/registry/blob/main/antigravity-acp/agent.json"
739
+ fi
740
+
741
+ if [ "$legacy_codex_map" = "yes" ]; then
742
+ section "Codex instructions"
743
+ warn "Legacy Compound Codex tool map in ${codex_agents_file}"
744
+ detail "Retired block from a pre-native Bun install; one line tells Codex to collapse subagent dispatch."
745
+ detail "Remove it -- see this skill's references/legacy-codex-tool-map.md"
746
+ fi
747
+
748
+ if [ "$in_repo" = "yes" ]; then
749
+ section "Project config"
750
+
751
+ if [ "$legacy_cfg" = "present" ]; then
752
+ warn "Obsolete compound-engineering.local.md exists"
753
+ project_issues=$((project_issues + 1))
754
+ else
755
+ ok "No obsolete compound-engineering.local.md"
756
+ fi
757
+
758
+ if [ "$tracked_cfg" = "present" ]; then
759
+ ok ".compound-engineering/config.yaml exists"
760
+ else
761
+ skip "No repo config yet (.compound-engineering/config.yaml)"
762
+ fi
763
+
764
+ if [ "$local_cfg" = "present" ]; then
765
+ ok ".compound-engineering/config.local.yaml exists"
766
+ if [ "$repo_cfg_gitignore" = "ok" ]; then
767
+ ok "Local config is gitignored"
768
+ else
769
+ warn "Local config is not safely gitignored"
770
+ project_issues=$((project_issues + 1))
771
+ fi
772
+ else
773
+ skip "No local override yet (.compound-engineering/config.local.yaml)"
774
+ fi
775
+
776
+ if [ "$scratch_gitignore" = "ok" ]; then
777
+ ok "CE scratch space is gitignored"
778
+ else
779
+ skip "CE scratch space is not gitignored"
780
+ detail "Skills that keep local scratch write it under .context/compound-engineering/"
781
+ fi
782
+
783
+ if [ "$docs_root_status" = "default" ]; then
784
+ ok "Artifact root: docs/ (default — docs_root not set)"
785
+ elif [ "$docs_root_status" = "configured" ]; then
786
+ ok "Artifact root: ${docs_root_value}/ (from ${docs_root_source})"
787
+ elif [ "$docs_root_status" = "invalid" ]; then
788
+ warn "Invalid docs_root '${docs_root_value}' in ${docs_root_source}: ${docs_root_error}"
789
+ detail "CE artifacts will not be written until docs_root is corrected or removed."
790
+ fi
791
+ if [ -n "$docs_root_local_ignored" ]; then
792
+ skip "Local docs_root '${docs_root_local_ignored}' is ignored; set docs_root only in config.yaml"
793
+ fi
794
+
795
+ if [ "$work_engine_cfg" = "native" ]; then
796
+ ok "CE Work implementation engine: native (${work_engine_detail})"
797
+ if [ -n "$work_engine_preferences_note" ]; then
798
+ if [ "$work_engine_preferences_note_level" = "warn" ]; then
799
+ warn "$work_engine_preferences_note"
800
+ else
801
+ detail "$work_engine_preferences_note"
802
+ fi
803
+ fi
804
+ elif [ "$work_engine_cfg" = "prefer" ] || [ "$work_engine_cfg" = "require" ]; then
805
+ ok "CE Work implementation engine: ${work_engine_cfg} -> ${work_engine_detail}"
806
+ elif [ "$work_engine_cfg" = "unavailable" ]; then
807
+ warn "CE Work implementation engine unavailable: ${work_engine_detail}"
808
+ elif [ "$work_engine_cfg" = "invalid" ]; then
809
+ warn "CE Work implementation engine: ${work_engine_detail}"
810
+ fi
811
+ [ -n "$work_engine_migration_note" ] && warn "$work_engine_migration_note"
812
+ for effort_note in ${work_engine_effort_notes[@]+"${work_engine_effort_notes[@]}"}; do
813
+ warn "$effort_note"
814
+ project_issues=$((project_issues + 1))
815
+ done
816
+
817
+ if [ "$example_cfg" = "ok" ]; then
818
+ ok "Example config is current"
819
+ elif [ "$example_cfg" = "missing" ]; then
820
+ warn "Example config missing (.compound-engineering/config.example.yaml)"
821
+ project_issues=$((project_issues + 1))
822
+ elif [ "$example_cfg" = "outdated" ]; then
823
+ warn "Example config outdated (new settings available)"
824
+ project_issues=$((project_issues + 1))
825
+ fi
826
+
827
+ for key in "${retired_keys[@]}"; do
828
+ case "$key" in
829
+ plan_use_fable) warn "Retired config key '$key' — removed; use 'plan_model' instead" ;;
830
+ brainstorm_use_fable) warn "Retired config key '$key' — removed; use 'brainstorm_model' instead" ;;
831
+ fable_nudge) warn "Retired config key '$key' — removed; model elevation is always available" ;;
832
+ esac
833
+ project_issues=$((project_issues + 1))
834
+ done
835
+ # --- Compound Packs (packs: config key) -------------------------------------
836
+ section "Compound Packs"
837
+ packs_python="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"
838
+ packs_resolver="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/packs-resolve.py"
839
+ if [ -z "$packs_python" ]; then
840
+ skip "No Python interpreter found; pack health not checked"
841
+ elif [ ! -f "$packs_resolver" ]; then
842
+ skip "packs-resolve.py not found beside check-health; pack health not checked"
843
+ else
844
+ packs_json="$("$packs_python" "$packs_resolver" 2>/dev/null)"
845
+ if [ -z "$packs_json" ]; then
846
+ warn "packs-resolve.py failed to run"
847
+ project_issues=$((project_issues + 1))
848
+ else
849
+ packs_report="$(printf '%s' "$packs_json" | "$packs_python" -c '
850
+ import json, os, re, subprocess, sys
851
+ data = json.load(sys.stdin)
852
+ roots, errors, warns = data.get("roots", []), data.get("errors", []), data.get("warnings", [])
853
+ if not roots and not errors and not warns:
854
+ print("SKIP\tNo packs configured")
855
+ for r in roots:
856
+ line = "OK\tpack " + r["id"]
857
+ url, ref = r.get("url"), r.get("ref")
858
+ if url and ref:
859
+ line += " (" + ref + ")"
860
+ # Only a full commit id is immutable. A branch tip advances and a tag can
861
+ # be force-moved upstream, so for either compare the cached HEAD with the
862
+ # remote target of that name -- the peeled commit for an annotated tag,
863
+ # which is why the ls-remote asks for `<tag>^{}` too.
864
+ if not re.fullmatch(r"[0-9a-f]{40}|[0-9a-f]{64}", ref):
865
+ try:
866
+ genv = dict(os.environ)
867
+ genv["GIT_TERMINAL_PROMPT"] = "0"
868
+ genv.setdefault("GIT_ASKPASS", "true")
869
+ _ssh = genv.get("GIT_SSH_COMMAND") or "ssh"
870
+ if "BatchMode" not in _ssh:
871
+ genv["GIT_SSH_COMMAND"] = _ssh + " -o BatchMode=yes"
872
+ names = ["refs/tags/" + ref + "^{}", "refs/tags/" + ref, "refs/heads/" + ref]
873
+ remote = subprocess.run(["git", "ls-remote", "--end-of-options", url, *names],
874
+ capture_output=True, text=True, timeout=10, env=genv)
875
+ targets = {}
876
+ for row in remote.stdout.splitlines() if remote.returncode == 0 else []:
877
+ sha, _, name = row.partition("\t")
878
+ if name:
879
+ targets[name] = sha
880
+ rsha = next((targets[n] for n in names if n in targets), "")
881
+ local = subprocess.run(["git", "-C", r["dir"], "rev-parse", "HEAD"], capture_output=True, text=True, timeout=10)
882
+ lsha = local.stdout.strip() if local.returncode == 0 else ""
883
+ if rsha and lsha and rsha != lsha:
884
+ line += " -- cached resolution is behind upstream"
885
+ except Exception:
886
+ pass # offline or slow remote: silently skip the drift note
887
+ # Subdirectories are storage, so rule-shaped files there are a note on the
888
+ # OK line, never a warning: the author may keep drafts and evidence with frontmatter.
889
+ nested = r.get("nested_rule_shaped", 0)
890
+ if nested:
891
+ line += " -- " + str(nested) + " rule-shaped file(s) in subfolders kept as storage"
892
+ print(line)
893
+ for w in warns:
894
+ print("WARN\t" + w)
895
+ for e in errors:
896
+ print("ERROR\t" + e)
897
+ ')"
898
+ while IFS=$'\t' read -r kind msg; do
899
+ [ -z "$kind" ] && continue
900
+ case "$kind" in
901
+ OK) ok "$msg" ;;
902
+ SKIP) skip "$msg" ;;
903
+ WARN) warn "$msg" ;;
904
+ ERROR) warn "Pack config error: $msg"; project_issues=$((project_issues + 1)) ;;
905
+ esac
906
+ done < <(printf '%s\n' "$packs_report")
907
+ fi
908
+ fi
909
+ else
910
+ section "Project config"
911
+ skip "Not inside a git repository"
912
+ fi
913
+
914
+ echo ""
915
+ if [ "$project_issues" -eq 0 ]; then
916
+ echo " ✅ Project config healthy. Optional capabilities available: ${capability_ok}/${capability_total}"
917
+ else
918
+ echo " ⚠️ ${project_issues} project issue(s) found. Optional capabilities available: ${capability_ok}/${capability_total}"
919
+ fi
920
+
921
+ if [ "$legacy_codex_map" = "yes" ]; then
922
+ echo " Environment: the legacy Codex tool map above still needs attention."
923
+ fi
924
+
925
+ if [ "$capability_missing" -gt 0 ]; then
926
+ echo " Missing optional tools do not block setup; install them only for the workflows you use."
927
+ fi
928
+
929
+ echo ""