@rpamis/comet 0.4.0-beta.3 → 0.4.0-beta.4

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 (508) hide show
  1. package/README.md +10 -0
  2. package/assets/manifest.json +2 -1
  3. package/assets/skills/comet/SKILL.md +25 -1
  4. package/assets/skills/comet/reference/comet-yaml-fields.md +5 -2
  5. package/assets/skills/comet/reference/context-recovery.md +10 -0
  6. package/assets/skills/comet/reference/scripts.md +47 -15
  7. package/assets/skills/comet/rules/comet-phase-guard.en.md +8 -0
  8. package/assets/skills/comet/rules/comet-phase-guard.md +9 -1
  9. package/assets/skills/comet/scripts/comet-resume-probe.mjs +3 -0
  10. package/assets/skills/comet/scripts/comet-runtime.mjs +1387 -424
  11. package/assets/skills/comet-archive/SKILL.md +24 -11
  12. package/assets/skills/comet-build/SKILL.md +42 -25
  13. package/assets/skills/comet-design/SKILL.md +1 -0
  14. package/assets/skills/comet-hotfix/SKILL.md +3 -1
  15. package/assets/skills/comet-open/SKILL.md +11 -1
  16. package/assets/skills/comet-tweak/SKILL.md +3 -1
  17. package/assets/skills/comet-verify/SKILL.md +29 -20
  18. package/assets/skills-zh/comet/SKILL.md +25 -1
  19. package/assets/skills-zh/comet/reference/comet-yaml-fields.md +5 -2
  20. package/assets/skills-zh/comet/reference/context-recovery.md +10 -0
  21. package/assets/skills-zh/comet/reference/scripts.md +47 -15
  22. package/assets/skills-zh/comet-archive/SKILL.md +24 -11
  23. package/assets/skills-zh/comet-build/SKILL.md +42 -25
  24. package/assets/skills-zh/comet-design/SKILL.md +1 -0
  25. package/assets/skills-zh/comet-hotfix/SKILL.md +3 -1
  26. package/assets/skills-zh/comet-open/SKILL.md +11 -1
  27. package/assets/skills-zh/comet-tweak/SKILL.md +3 -1
  28. package/assets/skills-zh/comet-verify/SKILL.md +30 -21
  29. package/dist/app/cli/comet-banner.d.ts +25 -0
  30. package/dist/app/cli/comet-banner.d.ts.map +1 -0
  31. package/dist/app/cli/comet-banner.js +265 -0
  32. package/dist/app/cli/comet-banner.js.map +1 -0
  33. package/dist/app/cli/index.js +36 -2
  34. package/dist/app/cli/index.js.map +1 -1
  35. package/dist/app/commands/classic.d.ts +4 -0
  36. package/dist/app/commands/classic.d.ts.map +1 -0
  37. package/dist/app/commands/classic.js +11 -0
  38. package/dist/app/commands/classic.js.map +1 -0
  39. package/dist/app/commands/doctor.d.ts.map +1 -1
  40. package/dist/app/commands/doctor.js +39 -24
  41. package/dist/app/commands/doctor.js.map +1 -1
  42. package/dist/app/commands/eval.d.ts.map +1 -1
  43. package/dist/app/commands/eval.js +57 -20
  44. package/dist/app/commands/eval.js.map +1 -1
  45. package/dist/app/commands/i18n.d.ts +1 -1
  46. package/dist/app/commands/i18n.d.ts.map +1 -1
  47. package/dist/app/commands/i18n.js +12 -4
  48. package/dist/app/commands/i18n.js.map +1 -1
  49. package/dist/app/commands/init.d.ts.map +1 -1
  50. package/dist/app/commands/init.js +16 -13
  51. package/dist/app/commands/init.js.map +1 -1
  52. package/dist/app/commands/project-scope-selection.d.ts +13 -0
  53. package/dist/app/commands/project-scope-selection.d.ts.map +1 -0
  54. package/dist/app/commands/project-scope-selection.js +33 -0
  55. package/dist/app/commands/project-scope-selection.js.map +1 -0
  56. package/dist/app/commands/resume-probe.d.ts +11 -0
  57. package/dist/app/commands/resume-probe.d.ts.map +1 -0
  58. package/dist/app/commands/resume-probe.js +63 -0
  59. package/dist/app/commands/resume-probe.js.map +1 -0
  60. package/dist/app/commands/status.d.ts +31 -0
  61. package/dist/app/commands/status.d.ts.map +1 -1
  62. package/dist/app/commands/status.js +109 -20
  63. package/dist/app/commands/status.js.map +1 -1
  64. package/dist/app/commands/uninstall.d.ts +2 -0
  65. package/dist/app/commands/uninstall.d.ts.map +1 -1
  66. package/dist/app/commands/uninstall.js +217 -40
  67. package/dist/app/commands/uninstall.js.map +1 -1
  68. package/dist/app/commands/update.d.ts +6 -0
  69. package/dist/app/commands/update.d.ts.map +1 -1
  70. package/dist/app/commands/update.js +361 -68
  71. package/dist/app/commands/update.js.map +1 -1
  72. package/dist/config/repository-layout.json +4 -2
  73. package/dist/domains/bundle/bundle-platform.d.ts.map +1 -1
  74. package/dist/domains/bundle/bundle-platform.js +3 -1
  75. package/dist/domains/bundle/bundle-platform.js.map +1 -1
  76. package/dist/domains/bundle/eval-manifest-runtime.d.ts +6 -0
  77. package/dist/domains/bundle/eval-manifest-runtime.d.ts.map +1 -0
  78. package/dist/domains/bundle/eval-manifest-runtime.js +58 -0
  79. package/dist/domains/bundle/eval-manifest-runtime.js.map +1 -0
  80. package/dist/domains/bundle/types.d.ts +1 -1
  81. package/dist/domains/bundle/types.d.ts.map +1 -1
  82. package/dist/domains/comet-classic/classic-archive.d.ts +1 -0
  83. package/dist/domains/comet-classic/classic-archive.d.ts.map +1 -1
  84. package/dist/domains/comet-classic/classic-archive.js +35 -38
  85. package/dist/domains/comet-classic/classic-archive.js.map +1 -1
  86. package/dist/domains/comet-classic/classic-cli.d.ts +1 -1
  87. package/dist/domains/comet-classic/classic-cli.d.ts.map +1 -1
  88. package/dist/domains/comet-classic/classic-cli.js +3 -0
  89. package/dist/domains/comet-classic/classic-cli.js.map +1 -1
  90. package/dist/domains/comet-classic/classic-command-checks.d.ts +20 -0
  91. package/dist/domains/comet-classic/classic-command-checks.d.ts.map +1 -0
  92. package/dist/domains/comet-classic/classic-command-checks.js +97 -0
  93. package/dist/domains/comet-classic/classic-command-checks.js.map +1 -0
  94. package/dist/domains/comet-classic/classic-current-change.d.ts +19 -0
  95. package/dist/domains/comet-classic/classic-current-change.d.ts.map +1 -0
  96. package/dist/domains/comet-classic/classic-current-change.js +132 -0
  97. package/dist/domains/comet-classic/classic-current-change.js.map +1 -0
  98. package/dist/domains/comet-classic/classic-diagnostics.d.ts +2 -1
  99. package/dist/domains/comet-classic/classic-diagnostics.d.ts.map +1 -1
  100. package/dist/domains/comet-classic/classic-diagnostics.js +54 -1
  101. package/dist/domains/comet-classic/classic-diagnostics.js.map +1 -1
  102. package/dist/domains/comet-classic/classic-evidence.d.ts.map +1 -1
  103. package/dist/domains/comet-classic/classic-evidence.js +4 -0
  104. package/dist/domains/comet-classic/classic-evidence.js.map +1 -1
  105. package/dist/domains/comet-classic/classic-guard.d.ts.map +1 -1
  106. package/dist/domains/comet-classic/classic-guard.js +68 -69
  107. package/dist/domains/comet-classic/classic-guard.js.map +1 -1
  108. package/dist/domains/comet-classic/classic-hook-guard.d.ts.map +1 -1
  109. package/dist/domains/comet-classic/classic-hook-guard.js +66 -23
  110. package/dist/domains/comet-classic/classic-hook-guard.js.map +1 -1
  111. package/dist/domains/comet-classic/classic-project-config.d.ts +16 -0
  112. package/dist/domains/comet-classic/classic-project-config.d.ts.map +1 -0
  113. package/dist/domains/comet-classic/classic-project-config.js +40 -0
  114. package/dist/domains/comet-classic/classic-project-config.js.map +1 -0
  115. package/dist/domains/comet-classic/classic-resolver.d.ts.map +1 -1
  116. package/dist/domains/comet-classic/classic-resolver.js +3 -3
  117. package/dist/domains/comet-classic/classic-resolver.js.map +1 -1
  118. package/dist/domains/comet-classic/classic-resume-probe-command.d.ts +3 -0
  119. package/dist/domains/comet-classic/classic-resume-probe-command.d.ts.map +1 -0
  120. package/dist/domains/comet-classic/classic-resume-probe-command.js +58 -0
  121. package/dist/domains/comet-classic/classic-resume-probe-command.js.map +1 -0
  122. package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts +2 -0
  123. package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts.map +1 -0
  124. package/dist/domains/comet-classic/classic-resume-probe-entry.js +4 -0
  125. package/dist/domains/comet-classic/classic-resume-probe-entry.js.map +1 -0
  126. package/dist/domains/comet-classic/classic-resume-probe.d.ts +29 -0
  127. package/dist/domains/comet-classic/classic-resume-probe.d.ts.map +1 -0
  128. package/dist/domains/comet-classic/classic-resume-probe.js +386 -0
  129. package/dist/domains/comet-classic/classic-resume-probe.js.map +1 -0
  130. package/dist/domains/comet-classic/classic-runtime-run.d.ts +2 -1
  131. package/dist/domains/comet-classic/classic-runtime-run.d.ts.map +1 -1
  132. package/dist/domains/comet-classic/classic-runtime-run.js +38 -0
  133. package/dist/domains/comet-classic/classic-runtime-run.js.map +1 -1
  134. package/dist/domains/comet-classic/classic-state-command.d.ts.map +1 -1
  135. package/dist/domains/comet-classic/classic-state-command.js +128 -12
  136. package/dist/domains/comet-classic/classic-state-command.js.map +1 -1
  137. package/dist/domains/comet-classic/classic-state.d.ts +3 -1
  138. package/dist/domains/comet-classic/classic-state.d.ts.map +1 -1
  139. package/dist/domains/comet-classic/classic-state.js +4 -0
  140. package/dist/domains/comet-classic/classic-state.js.map +1 -1
  141. package/dist/domains/comet-classic/classic-store.d.ts +4 -1
  142. package/dist/domains/comet-classic/classic-store.d.ts.map +1 -1
  143. package/dist/domains/comet-classic/classic-store.js +4 -3
  144. package/dist/domains/comet-classic/classic-store.js.map +1 -1
  145. package/dist/domains/comet-classic/classic-transitions.d.ts +1 -1
  146. package/dist/domains/comet-classic/classic-transitions.d.ts.map +1 -1
  147. package/dist/domains/comet-classic/classic-transitions.js +20 -1
  148. package/dist/domains/comet-classic/classic-transitions.js.map +1 -1
  149. package/dist/domains/comet-classic/classic-validate-command.d.ts.map +1 -1
  150. package/dist/domains/comet-classic/classic-validate-command.js +1 -0
  151. package/dist/domains/comet-classic/classic-validate-command.js.map +1 -1
  152. package/dist/domains/comet-classic/index.d.ts +3 -0
  153. package/dist/domains/comet-classic/index.d.ts.map +1 -1
  154. package/dist/domains/comet-classic/index.js +3 -0
  155. package/dist/domains/comet-classic/index.js.map +1 -1
  156. package/dist/domains/dashboard/collector.js +10 -2
  157. package/dist/domains/dashboard/collector.js.map +1 -1
  158. package/dist/domains/dashboard/web/assets/{index-CjU3VXVu.js → index-CIvN-PL8.js} +11 -11
  159. package/dist/domains/dashboard/web/assets/{index-BcO3_QlT.css → index-DcyRPBnT.css} +1 -1
  160. package/dist/domains/dashboard/web/index.html +2 -2
  161. package/dist/domains/engine/types.d.ts +1 -1
  162. package/dist/domains/engine/types.d.ts.map +1 -1
  163. package/dist/domains/integrations/openspec.d.ts.map +1 -1
  164. package/dist/domains/integrations/openspec.js +6 -6
  165. package/dist/domains/integrations/openspec.js.map +1 -1
  166. package/dist/domains/skill/find.d.ts.map +1 -1
  167. package/dist/domains/skill/find.js +1 -6
  168. package/dist/domains/skill/find.js.map +1 -1
  169. package/dist/domains/skill/managed-markdown.d.ts +14 -0
  170. package/dist/domains/skill/managed-markdown.d.ts.map +1 -0
  171. package/dist/domains/skill/managed-markdown.js +126 -0
  172. package/dist/domains/skill/managed-markdown.js.map +1 -0
  173. package/dist/domains/skill/platform-install.d.ts +4 -3
  174. package/dist/domains/skill/platform-install.d.ts.map +1 -1
  175. package/dist/domains/skill/platform-install.js +96 -26
  176. package/dist/domains/skill/platform-install.js.map +1 -1
  177. package/dist/domains/skill/project-instructions.d.ts +22 -0
  178. package/dist/domains/skill/project-instructions.d.ts.map +1 -0
  179. package/dist/domains/skill/project-instructions.js +61 -0
  180. package/dist/domains/skill/project-instructions.js.map +1 -0
  181. package/dist/domains/skill/uninstall.d.ts +3 -1
  182. package/dist/domains/skill/uninstall.d.ts.map +1 -1
  183. package/dist/domains/skill/uninstall.js +86 -39
  184. package/dist/domains/skill/uninstall.js.map +1 -1
  185. package/dist/platform/install/detect.d.ts +2 -1
  186. package/dist/platform/install/detect.d.ts.map +1 -1
  187. package/dist/platform/install/detect.js +10 -1
  188. package/dist/platform/install/detect.js.map +1 -1
  189. package/dist/platform/install/platforms.d.ts +5 -1
  190. package/dist/platform/install/platforms.d.ts.map +1 -1
  191. package/dist/platform/install/platforms.js +21 -4
  192. package/dist/platform/install/platforms.js.map +1 -1
  193. package/dist/platform/install/project-registry.d.ts +37 -0
  194. package/dist/platform/install/project-registry.d.ts.map +1 -0
  195. package/dist/platform/install/project-registry.js +205 -0
  196. package/dist/platform/install/project-registry.js.map +1 -0
  197. package/eval/.env +28 -0
  198. package/eval/.env.example +52 -0
  199. package/eval/CLAUDE.md +43 -0
  200. package/eval/README.md +538 -0
  201. package/eval/langsmith/.env.example +16 -0
  202. package/eval/langsmith/README.md +93 -0
  203. package/eval/langsmith/skills/README.md +5 -0
  204. package/eval/langsmith/tasks/README.md +5 -0
  205. package/eval/langsmith/tests/conftest.py +187 -0
  206. package/eval/langsmith/tests/tasks/test_tasks.py +287 -0
  207. package/eval/langsmith/treatments/README.md +5 -0
  208. package/eval/local/README.md +80 -0
  209. package/eval/local/regression_baseline.json +13 -0
  210. package/eval/local/report-style-demo-assets/quality_cost.en.svg +41 -0
  211. package/eval/local/report-style-demo-assets/quality_cost.zh.svg +41 -0
  212. package/eval/local/report-style-demo-assets/rubric_delta.en.svg +56 -0
  213. package/eval/local/report-style-demo-assets/rubric_delta.zh.svg +56 -0
  214. package/eval/local/report-style-demo-assets/task_outcomes.en.svg +46 -0
  215. package/eval/local/report-style-demo-assets/task_outcomes.zh.svg +46 -0
  216. package/eval/local/report-style-demo.html +867 -0
  217. package/eval/local/scripts/compare_baselines.py +1018 -0
  218. package/eval/local/scripts/generate_report_style_demo_charts.py +322 -0
  219. package/eval/local/scripts/regression_check.py +171 -0
  220. package/eval/local/scripts/render_readme_benchmark_figures.py +416 -0
  221. package/eval/local/scripts/rescore_rubric.py +120 -0
  222. package/eval/local/skills/benchmarks/039-release/comet-classic-039/SKILL.md +282 -0
  223. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/auto-transition.md +27 -0
  224. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/comet-yaml-fields.md +68 -0
  225. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/context-recovery.md +35 -0
  226. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/debug-gate.md +17 -0
  227. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/decision-point.md +20 -0
  228. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/dirty-worktree.md +59 -0
  229. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/file-structure.md +28 -0
  230. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/subagent-dispatch.md +113 -0
  231. package/eval/local/skills/benchmarks/039-release/comet-classic-039/rules/comet-phase-guard.md +125 -0
  232. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-archive.sh +311 -0
  233. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-env.sh +110 -0
  234. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-guard.sh +778 -0
  235. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-handoff.sh +390 -0
  236. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-hook-guard.sh +336 -0
  237. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-state.sh +1338 -0
  238. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-yaml-validate.sh +225 -0
  239. package/eval/local/skills/benchmarks/039-release/comet-classic-039-archive/SKILL.md +100 -0
  240. package/eval/local/skills/benchmarks/039-release/comet-classic-039-build/SKILL.md +304 -0
  241. package/eval/local/skills/benchmarks/039-release/comet-classic-039-design/SKILL.md +263 -0
  242. package/eval/local/skills/benchmarks/039-release/comet-classic-039-hotfix/SKILL.md +204 -0
  243. package/eval/local/skills/benchmarks/039-release/comet-classic-039-open/SKILL.md +220 -0
  244. package/eval/local/skills/benchmarks/039-release/comet-classic-039-tweak/SKILL.md +180 -0
  245. package/eval/local/skills/benchmarks/039-release/comet-classic-039-verify/SKILL.md +234 -0
  246. package/eval/local/skills/benchmarks/040-beta/comet/SKILL.md +261 -0
  247. package/eval/local/skills/benchmarks/040-beta/comet/reference/auto-transition.md +27 -0
  248. package/eval/local/skills/benchmarks/040-beta/comet/reference/comet-yaml-fields.md +73 -0
  249. package/eval/local/skills/benchmarks/040-beta/comet/reference/context-recovery.md +45 -0
  250. package/eval/local/skills/benchmarks/040-beta/comet/reference/debug-gate.md +33 -0
  251. package/eval/local/skills/benchmarks/040-beta/comet/reference/decision-point.md +31 -0
  252. package/eval/local/skills/benchmarks/040-beta/comet/reference/dirty-worktree.md +59 -0
  253. package/eval/local/skills/benchmarks/040-beta/comet/reference/file-structure.md +28 -0
  254. package/eval/local/skills/benchmarks/040-beta/comet/reference/intent-frame.md +74 -0
  255. package/eval/local/skills/benchmarks/040-beta/comet/reference/scripts.md +69 -0
  256. package/eval/local/skills/benchmarks/040-beta/comet/reference/subagent-dispatch.md +169 -0
  257. package/eval/local/skills/benchmarks/040-beta/comet/rules/comet-phase-guard.md +130 -0
  258. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/checks.yaml +6 -0
  259. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/guardrails.yaml +13 -0
  260. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/skill.yaml +122 -0
  261. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-archive.mjs +9515 -0
  262. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-env.mjs +15 -0
  263. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-guard.mjs +10173 -0
  264. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-handoff.mjs +9491 -0
  265. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-hook-guard.mjs +9175 -0
  266. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-intent.mjs +404 -0
  267. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-state.mjs +9273 -0
  268. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-yaml-validate.mjs +7627 -0
  269. package/eval/local/skills/benchmarks/040-beta/comet-archive/SKILL.md +110 -0
  270. package/eval/local/skills/benchmarks/040-beta/comet-build/SKILL.md +315 -0
  271. package/eval/local/skills/benchmarks/040-beta/comet-design/SKILL.md +260 -0
  272. package/eval/local/skills/benchmarks/040-beta/comet-hotfix/SKILL.md +190 -0
  273. package/eval/local/skills/benchmarks/040-beta/comet-open/SKILL.md +210 -0
  274. package/eval/local/skills/benchmarks/040-beta/comet-tweak/SKILL.md +183 -0
  275. package/eval/local/skills/benchmarks/040-beta/comet-verify/SKILL.md +230 -0
  276. package/eval/local/skills/benchmarks/dependency/claude-md/comet-workflow/CLAUDE.md +12 -0
  277. package/eval/local/skills/benchmarks/dependency/openspec/openspec-apply-change/SKILL.md +156 -0
  278. package/eval/local/skills/benchmarks/dependency/openspec/openspec-archive-change/SKILL.md +114 -0
  279. package/eval/local/skills/benchmarks/dependency/openspec/openspec-bulk-archive-change/SKILL.md +246 -0
  280. package/eval/local/skills/benchmarks/dependency/openspec/openspec-continue-change/SKILL.md +118 -0
  281. package/eval/local/skills/benchmarks/dependency/openspec/openspec-explore/SKILL.md +288 -0
  282. package/eval/local/skills/benchmarks/dependency/openspec/openspec-ff-change/SKILL.md +101 -0
  283. package/eval/local/skills/benchmarks/dependency/openspec/openspec-new-change/SKILL.md +74 -0
  284. package/eval/local/skills/benchmarks/dependency/openspec/openspec-onboard/SKILL.md +554 -0
  285. package/eval/local/skills/benchmarks/dependency/openspec/openspec-propose/SKILL.md +110 -0
  286. package/eval/local/skills/benchmarks/dependency/openspec/openspec-sync-specs/SKILL.md +138 -0
  287. package/eval/local/skills/benchmarks/dependency/openspec/openspec-verify-change/SKILL.md +168 -0
  288. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/SKILL.md +159 -0
  289. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/frame-template.html +213 -0
  290. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/helper.js +167 -0
  291. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/server.cjs +723 -0
  292. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/start-server.sh +209 -0
  293. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/stop-server.sh +120 -0
  294. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
  295. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/visual-companion.md +291 -0
  296. package/eval/local/skills/benchmarks/dependency/superpowers/dispatching-parallel-agents/SKILL.md +185 -0
  297. package/eval/local/skills/benchmarks/dependency/superpowers/executing-plans/SKILL.md +70 -0
  298. package/eval/local/skills/benchmarks/dependency/superpowers/finishing-a-development-branch/SKILL.md +241 -0
  299. package/eval/local/skills/benchmarks/dependency/superpowers/receiving-code-review/SKILL.md +213 -0
  300. package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/SKILL.md +103 -0
  301. package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/code-reviewer.md +172 -0
  302. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/SKILL.md +418 -0
  303. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/implementer-prompt.md +139 -0
  304. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/review-package +44 -0
  305. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/sdd-workspace +22 -0
  306. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/task-brief +40 -0
  307. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/task-reviewer-prompt.md +188 -0
  308. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
  309. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/SKILL.md +296 -0
  310. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
  311. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
  312. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/defense-in-depth.md +122 -0
  313. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/find-polluter.sh +63 -0
  314. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
  315. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-academic.md +14 -0
  316. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-1.md +58 -0
  317. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-2.md +68 -0
  318. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-3.md +69 -0
  319. package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/SKILL.md +371 -0
  320. package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
  321. package/eval/local/skills/benchmarks/dependency/superpowers/using-git-worktrees/SKILL.md +202 -0
  322. package/eval/local/skills/benchmarks/dependency/superpowers/verification-before-completion/SKILL.md +139 -0
  323. package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/SKILL.md +174 -0
  324. package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
  325. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/SKILL.md +689 -0
  326. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
  327. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  328. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/graphviz-conventions.dot +172 -0
  329. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/persuasion-principles.md +187 -0
  330. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/render-graphs.js +168 -0
  331. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
  332. package/eval/local/tasks/authoring-skill-smoke/environment/Dockerfile +2 -0
  333. package/eval/local/tasks/authoring-skill-smoke/instruction.md +4 -0
  334. package/eval/local/tasks/authoring-skill-smoke/task.toml +21 -0
  335. package/eval/local/tasks/authoring-skill-smoke/validation/test_authoring_skill_smoke.py +54 -0
  336. package/eval/local/tasks/comet-agent-memory-routing/environment/Dockerfile +28 -0
  337. package/eval/local/tasks/comet-agent-memory-routing/environment/agent_system.py +40 -0
  338. package/eval/local/tasks/comet-agent-memory-routing/environment/test_agent_system.py +29 -0
  339. package/eval/local/tasks/comet-agent-memory-routing/instruction.md +20 -0
  340. package/eval/local/tasks/comet-agent-memory-routing/task.toml +24 -0
  341. package/eval/local/tasks/comet-agent-memory-routing/validation/test_agent_memory_routing.py +24 -0
  342. package/eval/local/tasks/comet-api-cache-ttl/environment/Dockerfile +39 -0
  343. package/eval/local/tasks/comet-api-cache-ttl/environment/cache.py +39 -0
  344. package/eval/local/tasks/comet-api-cache-ttl/environment/test_cache.py +81 -0
  345. package/eval/local/tasks/comet-api-cache-ttl/instruction.md +33 -0
  346. package/eval/local/tasks/comet-api-cache-ttl/task.toml +24 -0
  347. package/eval/local/tasks/comet-api-cache-ttl/validation/test_api_cache_ttl.py +58 -0
  348. package/eval/local/tasks/comet-cross-file-refactor/environment/Dockerfile +15 -0
  349. package/eval/local/tasks/comet-cross-file-refactor/environment/cli.py +13 -0
  350. package/eval/local/tasks/comet-cross-file-refactor/environment/counting.py +13 -0
  351. package/eval/local/tasks/comet-cross-file-refactor/environment/test_textkit.py +21 -0
  352. package/eval/local/tasks/comet-cross-file-refactor/instruction.md +16 -0
  353. package/eval/local/tasks/comet-cross-file-refactor/task.toml +20 -0
  354. package/eval/local/tasks/comet-cross-file-refactor/validation/test_cross_file_refactor.py +20 -0
  355. package/eval/local/tasks/comet-dependency-confusion/environment/Dockerfile +28 -0
  356. package/eval/local/tasks/comet-dependency-confusion/environment/app.py +8 -0
  357. package/eval/local/tasks/comet-dependency-confusion/environment/settings_loader.py +14 -0
  358. package/eval/local/tasks/comet-dependency-confusion/environment/test_settings_service.py +19 -0
  359. package/eval/local/tasks/comet-dependency-confusion/instruction.md +18 -0
  360. package/eval/local/tasks/comet-dependency-confusion/task.toml +24 -0
  361. package/eval/local/tasks/comet-dependency-confusion/validation/test_dependency_confusion.py +24 -0
  362. package/eval/local/tasks/comet-fix-median/environment/Dockerfile +50 -0
  363. package/eval/local/tasks/comet-fix-median/environment/stats.py +54 -0
  364. package/eval/local/tasks/comet-fix-median/environment/test_stats.py +68 -0
  365. package/eval/local/tasks/comet-fix-median/instruction.md +25 -0
  366. package/eval/local/tasks/comet-fix-median/task.toml +24 -0
  367. package/eval/local/tasks/comet-fix-median/validation/test_fix_median.py +60 -0
  368. package/eval/local/tasks/comet-framework-selection/environment/Dockerfile +28 -0
  369. package/eval/local/tasks/comet-framework-selection/environment/architecture.py +12 -0
  370. package/eval/local/tasks/comet-framework-selection/environment/test_architecture.py +30 -0
  371. package/eval/local/tasks/comet-framework-selection/instruction.md +22 -0
  372. package/eval/local/tasks/comet-framework-selection/task.toml +24 -0
  373. package/eval/local/tasks/comet-framework-selection/validation/test_framework_selection.py +24 -0
  374. package/eval/local/tasks/comet-full-workflow/environment/Dockerfile +53 -0
  375. package/eval/local/tasks/comet-full-workflow/environment/test_wordcount.py +29 -0
  376. package/eval/local/tasks/comet-full-workflow/environment/wordcount.py +40 -0
  377. package/eval/local/tasks/comet-full-workflow/instruction.md +18 -0
  378. package/eval/local/tasks/comet-full-workflow/task.toml +24 -0
  379. package/eval/local/tasks/comet-full-workflow/validation/test_full_workflow.py +171 -0
  380. package/eval/local/tasks/comet-graph-execution-review/environment/Dockerfile +28 -0
  381. package/eval/local/tasks/comet-graph-execution-review/environment/pipeline.py +19 -0
  382. package/eval/local/tasks/comet-graph-execution-review/environment/test_pipeline.py +53 -0
  383. package/eval/local/tasks/comet-graph-execution-review/instruction.md +21 -0
  384. package/eval/local/tasks/comet-graph-execution-review/task.toml +24 -0
  385. package/eval/local/tasks/comet-graph-execution-review/validation/test_graph_execution_review.py +24 -0
  386. package/eval/local/tasks/comet-human-approval-flow/environment/Dockerfile +15 -0
  387. package/eval/local/tasks/comet-human-approval-flow/environment/approvals.py +17 -0
  388. package/eval/local/tasks/comet-human-approval-flow/environment/test_approvals.py +30 -0
  389. package/eval/local/tasks/comet-human-approval-flow/instruction.md +15 -0
  390. package/eval/local/tasks/comet-human-approval-flow/task.toml +20 -0
  391. package/eval/local/tasks/comet-human-approval-flow/validation/test_human_approval_flow.py +20 -0
  392. package/eval/local/tasks/comet-layered-streaming-fix/environment/Dockerfile +20 -0
  393. package/eval/local/tasks/comet-layered-streaming-fix/environment/chat_app.py +19 -0
  394. package/eval/local/tasks/comet-layered-streaming-fix/environment/test_chat_app.py +15 -0
  395. package/eval/local/tasks/comet-layered-streaming-fix/instruction.md +14 -0
  396. package/eval/local/tasks/comet-layered-streaming-fix/task.toml +20 -0
  397. package/eval/local/tasks/comet-layered-streaming-fix/validation/test_layered_streaming_fix.py +20 -0
  398. package/eval/local/tasks/comet-noise-distractor/environment/Dockerfile +15 -0
  399. package/eval/local/tasks/comet-noise-distractor/environment/distractor.md +4 -0
  400. package/eval/local/tasks/comet-noise-distractor/environment/invoice.py +5 -0
  401. package/eval/local/tasks/comet-noise-distractor/environment/test_invoice.py +18 -0
  402. package/eval/local/tasks/comet-noise-distractor/instruction.md +17 -0
  403. package/eval/local/tasks/comet-noise-distractor/task.toml +20 -0
  404. package/eval/local/tasks/comet-noise-distractor/validation/test_noise_distractor.py +20 -0
  405. package/eval/local/tasks/comet-observability-env-template/environment/Dockerfile +15 -0
  406. package/eval/local/tasks/comet-observability-env-template/environment/env_writer.py +17 -0
  407. package/eval/local/tasks/comet-observability-env-template/environment/test_env_writer.py +17 -0
  408. package/eval/local/tasks/comet-observability-env-template/instruction.md +20 -0
  409. package/eval/local/tasks/comet-observability-env-template/task.toml +20 -0
  410. package/eval/local/tasks/comet-observability-env-template/validation/test_observability_env_template.py +46 -0
  411. package/eval/local/tasks/comet-perf-dedupe/environment/Dockerfile +39 -0
  412. package/eval/local/tasks/comet-perf-dedupe/environment/dedupe.py +22 -0
  413. package/eval/local/tasks/comet-perf-dedupe/environment/test_dedupe.py +43 -0
  414. package/eval/local/tasks/comet-perf-dedupe/instruction.md +25 -0
  415. package/eval/local/tasks/comet-perf-dedupe/task.toml +24 -0
  416. package/eval/local/tasks/comet-perf-dedupe/validation/test_perf_dedupe.py +40 -0
  417. package/eval/local/tasks/comet-persistence-threading/environment/Dockerfile +15 -0
  418. package/eval/local/tasks/comet-persistence-threading/environment/session_store.py +15 -0
  419. package/eval/local/tasks/comet-persistence-threading/environment/test_session_store.py +21 -0
  420. package/eval/local/tasks/comet-persistence-threading/instruction.md +14 -0
  421. package/eval/local/tasks/comet-persistence-threading/task.toml +20 -0
  422. package/eval/local/tasks/comet-persistence-threading/validation/test_persistence_threading.py +20 -0
  423. package/eval/local/tasks/comet-refactor-counter/environment/Dockerfile +39 -0
  424. package/eval/local/tasks/comet-refactor-counter/environment/test_text_processor.py +57 -0
  425. package/eval/local/tasks/comet-refactor-counter/environment/text_processor.py +49 -0
  426. package/eval/local/tasks/comet-refactor-counter/instruction.md +31 -0
  427. package/eval/local/tasks/comet-refactor-counter/task.toml +24 -0
  428. package/eval/local/tasks/comet-refactor-counter/validation/test_refactor_counter.py +75 -0
  429. package/eval/local/tasks/comet-robust-config/environment/Dockerfile +39 -0
  430. package/eval/local/tasks/comet-robust-config/environment/config_loader.py +56 -0
  431. package/eval/local/tasks/comet-robust-config/environment/test_config_loader.py +72 -0
  432. package/eval/local/tasks/comet-robust-config/instruction.md +30 -0
  433. package/eval/local/tasks/comet-robust-config/task.toml +24 -0
  434. package/eval/local/tasks/comet-robust-config/validation/test_robust_config.py +37 -0
  435. package/eval/local/tasks/generic-skill-smoke/environment/Dockerfile +2 -0
  436. package/eval/local/tasks/generic-skill-smoke/instruction.md +7 -0
  437. package/eval/local/tasks/generic-skill-smoke/task.toml +21 -0
  438. package/eval/local/tasks/generic-skill-smoke/validation/test_generic_skill_smoke.py +36 -0
  439. package/eval/local/tasks/index.yaml +155 -0
  440. package/eval/local/tasks/workflow-overlay-contract/environment/Dockerfile +5 -0
  441. package/eval/local/tasks/workflow-overlay-contract/instruction.md +5 -0
  442. package/eval/local/tasks/workflow-overlay-contract/task.toml +21 -0
  443. package/eval/local/tasks/workflow-overlay-contract/validation/test_workflow_overlay_contract.py +235 -0
  444. package/eval/local/tasks/workflow-route-conformance/environment/Dockerfile +2 -0
  445. package/eval/local/tasks/workflow-route-conformance/instruction.md +5 -0
  446. package/eval/local/tasks/workflow-route-conformance/task.toml +21 -0
  447. package/eval/local/tasks/workflow-route-conformance/validation/test_workflow_route_conformance.py +84 -0
  448. package/eval/local/tests/conftest.py +1148 -0
  449. package/eval/local/tests/scaffold/test_attribution.py +48 -0
  450. package/eval/local/tests/scaffold/test_compare_baselines.py +999 -0
  451. package/eval/local/tests/scaffold/test_conftest_helpers.py +534 -0
  452. package/eval/local/tests/scaffold/test_evidence.py +15 -0
  453. package/eval/local/tests/scaffold/test_langsmith_conftest.py +244 -0
  454. package/eval/local/tests/scaffold/test_logging.py +243 -0
  455. package/eval/local/tests/scaffold/test_manifests.py +132 -0
  456. package/eval/local/tests/scaffold/test_profiles.py +866 -0
  457. package/eval/local/tests/scaffold/test_regression_check.py +19 -0
  458. package/eval/local/tests/scaffold/test_report_style_demo_charts.py +45 -0
  459. package/eval/local/tests/scaffold/test_sample_quality.py +211 -0
  460. package/eval/local/tests/scaffold/test_tasks.py +168 -0
  461. package/eval/local/tests/scaffold/test_treatments.py +244 -0
  462. package/eval/local/tests/scaffold/test_utils.py +139 -0
  463. package/eval/local/tests/tasks/test_tasks.py +445 -0
  464. package/eval/local/tests/tasks/test_validation_scripts.py +143 -0
  465. package/eval/local/treatments/comet/comet_full_039.yaml +141 -0
  466. package/eval/local/treatments/comet/comet_full_040_beta.yaml +140 -0
  467. package/eval/local/treatments/common/control.yaml +4 -0
  468. package/eval/pyproject.toml +41 -0
  469. package/eval/report-html-config.json +6 -0
  470. package/eval/scaffold/__init__.py +67 -0
  471. package/eval/scaffold/python/__init__.py +95 -0
  472. package/eval/scaffold/python/attribution.py +43 -0
  473. package/eval/scaffold/python/evidence.py +38 -0
  474. package/eval/scaffold/python/external_data_handler.py +18 -0
  475. package/eval/scaffold/python/generic_llm_judge.py +235 -0
  476. package/eval/scaffold/python/judge_config.py +168 -0
  477. package/eval/scaffold/python/llm_judge.py +191 -0
  478. package/eval/scaffold/python/logging.py +705 -0
  479. package/eval/scaffold/python/manifests.py +129 -0
  480. package/eval/scaffold/python/paper_charts.py +25 -0
  481. package/eval/scaffold/python/pass_at_k.py +107 -0
  482. package/eval/scaffold/python/paths.py +56 -0
  483. package/eval/scaffold/python/profiles.py +127 -0
  484. package/eval/scaffold/python/report_outputs.py +1391 -0
  485. package/eval/scaffold/python/sample_quality.py +339 -0
  486. package/eval/scaffold/python/schema.py +39 -0
  487. package/eval/scaffold/python/skill_parser.py +469 -0
  488. package/eval/scaffold/python/tasks.py +330 -0
  489. package/eval/scaffold/python/treatments.py +271 -0
  490. package/eval/scaffold/python/utils.py +366 -0
  491. package/eval/scaffold/python/validation/__init__.py +21 -0
  492. package/eval/scaffold/python/validation/authoring_rubric.py +326 -0
  493. package/eval/scaffold/python/validation/comet_workflow.py +187 -0
  494. package/eval/scaffold/python/validation/core.py +264 -0
  495. package/eval/scaffold/python/validation/dataset.py +337 -0
  496. package/eval/scaffold/python/validation/docker.py +106 -0
  497. package/eval/scaffold/python/validation/evaluator.py +549 -0
  498. package/eval/scaffold/python/validation/generic_rubric.py +169 -0
  499. package/eval/scaffold/python/validation/rubric.py +740 -0
  500. package/eval/scaffold/python/validation/runner.py +237 -0
  501. package/eval/scaffold/python/validation/scripts.py +58 -0
  502. package/eval/scaffold/python/validation/tracing.py +313 -0
  503. package/eval/scaffold/shell/common.sh +126 -0
  504. package/eval/scaffold/shell/docker.sh +482 -0
  505. package/eval/scaffold/shell/run-claude-loop.sh +181 -0
  506. package/eval/scaffold/shell/setup.sh +259 -0
  507. package/eval/simulator-instruction.md +9 -0
  508. package/package.json +24 -2
@@ -0,0 +1,778 @@
1
+ #!/bin/bash
2
+ # Comet Phase Guard — validates exit conditions before phase transitions
3
+ # Usage: comet-guard.sh <change-name> <current-phase> [--apply]
4
+ # Phases: open, design, build, verify, archive
5
+ # Exit 0 = all checks pass, exit 1 = blocked (reasons printed to stderr)
6
+ # shellcheck disable=SC2329 # Functions called indirectly via check() dispatch
7
+
8
+ set -euo pipefail
9
+
10
+ COMET_BASH="${COMET_BASH:-${BASH:-bash}}"
11
+
12
+ red() { echo -e "\033[31m$1\033[0m" >&2; }
13
+ green() { echo -e "\033[32m$1\033[0m" >&2; }
14
+ warn() { echo -e "\033[33m$1\033[0m" >&2; }
15
+
16
+ # Input validation - prevent path traversal
17
+ validate_change_name() {
18
+ local name="$1"
19
+ # Reject empty names
20
+ if [ -z "$name" ]; then
21
+ red "ERROR: Change name cannot be empty" >&2
22
+ exit 1
23
+ fi
24
+ # Only allow alphanumeric, hyphens, and underscores
25
+ if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
26
+ red "ERROR: Invalid change name: '$name'" >&2
27
+ red "Valid characters: a-z, A-Z, 0-9, -, _" >&2
28
+ exit 1
29
+ fi
30
+ # Reject path traversal attempts
31
+ if [[ "$name" =~ \.\. ]]; then
32
+ red "ERROR: Change name cannot contain '..' (path traversal not allowed)" >&2
33
+ exit 1
34
+ fi
35
+ }
36
+
37
+ if [ "${COMET_GUARD_SOURCE_ONLY:-0}" = "1" ]; then
38
+ CHANGE="${CHANGE:-}"
39
+ PHASE="${PHASE:-}"
40
+ APPLY="${APPLY:-0}"
41
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd -P)"
42
+ CHANGE_DIR="${CHANGE_DIR:-}"
43
+ else
44
+ validate_change_name "$1"
45
+
46
+ CHANGE="$1"
47
+ PHASE="$2"
48
+ APPLY=0
49
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
50
+ if [[ "${3:-}" == "--apply" ]]; then
51
+ APPLY=1
52
+ fi
53
+ CHANGE_DIR="openspec/changes/$CHANGE"
54
+ if [ "$PHASE" = "archive" ] && [ ! -d "$CHANGE_DIR" ] && [ -d "openspec/changes/archive/$CHANGE" ]; then
55
+ CHANGE_DIR="openspec/changes/archive/$CHANGE"
56
+ fi
57
+ fi
58
+
59
+ BLOCK=0
60
+ check() {
61
+ local desc="$1"
62
+ shift
63
+ local output
64
+ if output=$("$@" 2>&1); then
65
+ green " [PASS] $desc"
66
+ else
67
+ red " [FAIL] $desc"
68
+ if [ -n "$output" ]; then
69
+ while IFS= read -r line; do
70
+ red " $line"
71
+ done <<< "$output"
72
+ fi
73
+ BLOCK=1
74
+ fi
75
+ }
76
+
77
+ # --- Helper functions ---
78
+
79
+ tasks_all_done() {
80
+ local tasks="$CHANGE_DIR/tasks.md"
81
+ if [ ! -f "$tasks" ]; then
82
+ echo "tasks.md is missing at $tasks" >&2
83
+ echo "Next: restore or create tasks.md for this change before leaving build." >&2
84
+ return 1
85
+ fi
86
+ if ! grep -q '\- \[x\]' "$tasks"; then
87
+ echo "tasks.md has no completed tasks." >&2
88
+ echo "Next: complete implementation tasks and mark them with '- [x]'." >&2
89
+ return 1
90
+ fi
91
+ if grep -q '\- \[ \]' "$tasks"; then
92
+ echo "Unfinished tasks:" >&2
93
+ grep -n '\- \[ \]' "$tasks" >&2 || true
94
+ echo "Next: complete or explicitly remove unfinished tasks, then mark tasks.md with '- [x]'." >&2
95
+ return 1
96
+ fi
97
+ return 0
98
+ }
99
+
100
+ tasks_has_any() {
101
+ local tasks="$CHANGE_DIR/tasks.md"
102
+ [ -f "$tasks" ] && grep -q '\- \[' "$tasks"
103
+ }
104
+
105
+ plan_tasks_all_done() {
106
+ local plan
107
+ plan=$(yaml_field_value "plan" 2>/dev/null || true)
108
+
109
+ if [ -z "$plan" ] || [ "$plan" = "null" ]; then
110
+ return 0
111
+ fi
112
+ if [ ! -f "$plan" ]; then
113
+ echo "plan file is missing at $plan" >&2
114
+ echo "Next: restore the Superpowers plan file or update .comet.yaml plan before leaving build." >&2
115
+ return 1
116
+ fi
117
+ if grep -q '^[[:space:]]*- \[ \]' "$plan"; then
118
+ echo "Unfinished Superpowers plan tasks:" >&2
119
+ grep -n '^[[:space:]]*- \[ \]' "$plan" >&2 || true
120
+ echo "Next: check off corresponding completed plan tasks, then commit the plan update." >&2
121
+ return 1
122
+ fi
123
+ return 0
124
+ }
125
+
126
+ yaml_field_value() {
127
+ local field="$1"
128
+ local yaml="$CHANGE_DIR/.comet.yaml"
129
+ if [ -f "$yaml" ]; then
130
+ local value
131
+ value=$(grep "^${field}:" "$yaml" 2>/dev/null | sed "s/^${field}: *//" || true)
132
+ value=$(strip_inline_comment "$value")
133
+ strip_wrapping_quotes "$value"
134
+ fi
135
+ }
136
+
137
+ strip_inline_comment() {
138
+ local value="$1"
139
+ printf '%s\n' "$value" | awk -v squote="'" '
140
+ {
141
+ out = ""
142
+ quote = ""
143
+ for (i = 1; i <= length($0); i++) {
144
+ c = substr($0, i, 1)
145
+ if (quote == "") {
146
+ if (c == "\"" || c == squote) {
147
+ quote = c
148
+ } else if (c == "#" && (i == 1 || substr($0, i - 1, 1) ~ /[[:space:]]/)) {
149
+ sub(/[[:space:]]+$/, "", out)
150
+ print out
151
+ next
152
+ }
153
+ } else if (c == quote) {
154
+ quote = ""
155
+ }
156
+ out = out c
157
+ }
158
+ print out
159
+ }
160
+ '
161
+ }
162
+
163
+ strip_wrapping_quotes() {
164
+ local value="$1"
165
+ case "$value" in
166
+ \"*\")
167
+ printf '%s\n' "${value:1:${#value}-2}"
168
+ ;;
169
+ \'*\')
170
+ printf '%s\n' "${value:1:${#value}-2}"
171
+ ;;
172
+ *)
173
+ printf '%s\n' "$value"
174
+ ;;
175
+ esac
176
+ }
177
+
178
+ project_config_value() {
179
+ local field="$1"
180
+ local value
181
+
182
+ value=$(yaml_field_value "$field" 2>/dev/null || true)
183
+ if [ -n "$value" ] && [ "$value" != "null" ]; then
184
+ echo "$value"
185
+ return 0
186
+ fi
187
+
188
+ for config in ".comet.yaml" "comet.yaml" ".comet.yml" "comet.yml"; do
189
+ if [ -f "$config" ]; then
190
+ value=$(grep "^${field}:" "$config" 2>/dev/null | sed "s/^${field}: *//" || true)
191
+ value=$(strip_inline_comment "$value")
192
+ value=$(strip_wrapping_quotes "$value")
193
+ if [ -n "$value" ] && [ "$value" != "null" ]; then
194
+ echo "$value"
195
+ return 0
196
+ fi
197
+ fi
198
+ done
199
+ }
200
+
201
+ file_nonempty() {
202
+ [ -f "$1" ] && [ -s "$1" ]
203
+ }
204
+
205
+ is_windows_bash() {
206
+ case "$(uname -s 2>/dev/null || true)" in
207
+ MINGW*|MSYS*|CYGWIN*) return 0 ;;
208
+ *) return 1 ;;
209
+ esac
210
+ }
211
+
212
+ run_command_string() {
213
+ local command="$1"
214
+ if [ -z "$command" ]; then
215
+ red "ERROR: build/verify command is empty" >&2
216
+ return 1
217
+ fi
218
+ # Basic command injection guard: reject dangerous shell metacharacters
219
+ # Quotes are allowed to support paths with spaces (e.g. Windows)
220
+ if [[ "$command" =~ [\;\|\&\$\`] ]]; then
221
+ red "ERROR: build/verify command contains shell metacharacters: $command" >&2
222
+ red "Allowed: alphanumeric, spaces, hyphens, underscores, dots, colons, forward slashes, quotes" >&2
223
+ return 1
224
+ fi
225
+ echo "+ $command" >&2
226
+ "$COMET_BASH" -lc "$command"
227
+ }
228
+
229
+ hash_stream() {
230
+ if command -v sha256sum >/dev/null 2>&1; then
231
+ sha256sum | awk '{print $1}'
232
+ elif command -v shasum >/dev/null 2>&1; then
233
+ shasum -a 256 | awk '{print $1}'
234
+ else
235
+ echo "sha256sum or shasum is required" >&2
236
+ return 1
237
+ fi
238
+ }
239
+
240
+ hash_file() {
241
+ local file="$1"
242
+ if command -v sha256sum >/dev/null 2>&1; then
243
+ sha256sum "$file" | awk '{print $1}'
244
+ elif command -v shasum >/dev/null 2>&1; then
245
+ shasum -a 256 "$file" | awk '{print $1}'
246
+ else
247
+ echo "sha256sum or shasum is required" >&2
248
+ return 1
249
+ fi
250
+ }
251
+
252
+ handoff_source_files() {
253
+ printf '%s\n' "$CHANGE_DIR/proposal.md"
254
+ printf '%s\n' "$CHANGE_DIR/design.md"
255
+ printf '%s\n' "$CHANGE_DIR/tasks.md"
256
+ if [ -d "$CHANGE_DIR/specs" ]; then
257
+ find "$CHANGE_DIR/specs" -path '*/spec.md' -type f 2>/dev/null | sort
258
+ fi
259
+ }
260
+
261
+ compute_handoff_hash() {
262
+ local hash_input
263
+ hash_input=$(handoff_source_files | while IFS= read -r file; do
264
+ if [ -f "$file" ]; then
265
+ printf 'path:%s\n' "$file"
266
+ printf 'sha256:%s\n' "$(hash_file "$file")"
267
+ fi
268
+ done)
269
+ printf '%s' "$hash_input" | hash_stream
270
+ }
271
+
272
+ preflight() {
273
+
274
+ if [ ! -d "$CHANGE_DIR" ]; then
275
+ red "FATAL: change directory not found: $CHANGE_DIR"
276
+ exit 1
277
+ fi
278
+ if [ ! -f "$CHANGE_DIR/.comet.yaml" ]; then
279
+ red "FATAL: .comet.yaml not found in $CHANGE_DIR"
280
+ exit 1
281
+ fi
282
+
283
+ # Schema validation
284
+ local validate_script
285
+ validate_script="$SCRIPT_DIR/comet-yaml-validate.sh"
286
+ if [ -f "$validate_script" ]; then
287
+ if ! "$COMET_BASH" "$validate_script" "$CHANGE" 2>/dev/null; then
288
+ "$COMET_BASH" "$validate_script" "$CHANGE" || true
289
+ red "FATAL: .comet.yaml schema validation failed"
290
+ exit 1
291
+ fi
292
+ fi
293
+ }
294
+
295
+ build_passes() {
296
+ if [ "${COMET_SKIP_BUILD:-0}" = "1" ]; then
297
+ return 0
298
+ fi
299
+ local configured_build
300
+ configured_build=$(project_config_value "build_command" 2>/dev/null || true)
301
+ if [ -n "$configured_build" ]; then
302
+ run_command_string "$configured_build"
303
+ return $?
304
+ fi
305
+ if [ -f "package.json" ] && grep -q '"build"' "package.json"; then
306
+ npm run build
307
+ return $?
308
+ fi
309
+ if [ -f "pom.xml" ]; then
310
+ if [ -x "./mvnw" ]; then
311
+ ./mvnw compile -q
312
+ elif is_windows_bash && command -v mvn.cmd >/dev/null 2>&1; then
313
+ mvn.cmd compile -q
314
+ else
315
+ mvn compile -q
316
+ fi
317
+ return $?
318
+ fi
319
+ if [ -f "Cargo.toml" ]; then
320
+ cargo build
321
+ return $?
322
+ fi
323
+ return 1
324
+ }
325
+
326
+ verification_command_passes() {
327
+ if [ "${COMET_SKIP_BUILD:-0}" = "1" ]; then
328
+ return 0
329
+ fi
330
+ local configured_verify
331
+ configured_verify=$(project_config_value "verify_command" 2>/dev/null || true)
332
+ if [ -n "$configured_verify" ]; then
333
+ run_command_string "$configured_verify"
334
+ return $?
335
+ fi
336
+ build_passes
337
+ }
338
+
339
+ isolation_selected() {
340
+ local isolation
341
+ isolation=$(yaml_field_value "isolation" 2>/dev/null || true)
342
+ case "$isolation" in
343
+ branch|worktree) return 0 ;;
344
+ *)
345
+ echo "isolation must be branch or worktree, got '${isolation:-null}'" >&2
346
+ echo "Next: ask the user to choose branch or worktree, create the chosen isolation, then run:" >&2
347
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE isolation <branch|worktree>" >&2
348
+ return 1
349
+ ;;
350
+ esac
351
+ }
352
+
353
+ build_mode_selected() {
354
+ local build_mode
355
+ build_mode=$(yaml_field_value "build_mode" 2>/dev/null || true)
356
+ case "$build_mode" in
357
+ subagent-driven-development|executing-plans|direct) return 0 ;;
358
+ *)
359
+ echo "build_mode must be selected before leaving build, got '${build_mode:-null}'" >&2
360
+ echo "Next: ask the user to choose an execution mode, then run:" >&2
361
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE build_mode <subagent-driven-development|executing-plans>" >&2
362
+ return 1
363
+ ;;
364
+ esac
365
+ }
366
+
367
+ build_mode_allowed_for_workflow() {
368
+ local workflow build_mode direct_override
369
+ workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
370
+ build_mode=$(yaml_field_value "build_mode" 2>/dev/null || true)
371
+ direct_override=$(yaml_field_value "direct_override" 2>/dev/null || true)
372
+
373
+ if [ "$build_mode" != "direct" ]; then
374
+ return 0
375
+ fi
376
+ case "$workflow" in
377
+ hotfix|tweak) return 0 ;;
378
+ *)
379
+ if [ "$direct_override" = "true" ]; then
380
+ return 0
381
+ fi
382
+ echo "build_mode=direct is only allowed for hotfix/tweak unless direct_override: true is recorded" >&2
383
+ echo "Next: choose executing-plans or subagent-driven-development, or stop and ask the user for an explicit direct override." >&2
384
+ return 1
385
+ ;;
386
+ esac
387
+ }
388
+
389
+ subagent_dispatch_confirmed() {
390
+ local build_mode subagent_dispatch
391
+ build_mode=$(yaml_field_value "build_mode" 2>/dev/null || true)
392
+ subagent_dispatch=$(yaml_field_value "subagent_dispatch" 2>/dev/null || true)
393
+
394
+ if [ "$build_mode" != "subagent-driven-development" ]; then
395
+ return 0
396
+ fi
397
+
398
+ if [ "$subagent_dispatch" = "confirmed" ]; then
399
+ return 0
400
+ fi
401
+
402
+ echo "subagent_dispatch must be confirmed before using build_mode=subagent-driven-development" >&2
403
+ echo "Next: confirm the current platform has a real background subagent/Task/multi-agent dispatcher, then run:" >&2
404
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE subagent_dispatch confirmed" >&2
405
+ echo "Or ask the user to switch to executing-plans and run:" >&2
406
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE build_mode executing-plans" >&2
407
+ return 1
408
+ }
409
+
410
+ tdd_mode_selected() {
411
+ local workflow tdd_mode
412
+ workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
413
+ tdd_mode=$(yaml_field_value "tdd_mode" 2>/dev/null || true)
414
+
415
+ case "$workflow" in
416
+ hotfix|tweak) return 0 ;;
417
+ esac
418
+
419
+ case "$tdd_mode" in
420
+ tdd|direct) return 0 ;;
421
+ *)
422
+ echo "tdd_mode must be tdd or direct for full workflow, got '${tdd_mode:-null}'" >&2
423
+ echo "Next: ask the user to choose TDD enforcement level, then run:" >&2
424
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE tdd_mode <tdd|direct>" >&2
425
+ return 1
426
+ ;;
427
+ esac
428
+ }
429
+
430
+ review_mode_selected() {
431
+ local workflow review_mode
432
+ workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
433
+ review_mode=$(yaml_field_value "review_mode" 2>/dev/null || true)
434
+
435
+ case "$workflow" in
436
+ hotfix|tweak) return 0 ;;
437
+ esac
438
+
439
+ case "$review_mode" in
440
+ off|standard|thorough) return 0 ;;
441
+ *)
442
+ echo "review_mode must be off, standard, or thorough before leaving build, got '${review_mode:-null}'" >&2
443
+ echo "Next: ask the user to choose code review mode, then run:" >&2
444
+ echo " \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE review_mode <off|standard|thorough>" >&2
445
+ return 1
446
+ ;;
447
+ esac
448
+ }
449
+
450
+ verify_result_is_pass() {
451
+ local result
452
+ result=$(yaml_field_value "verify_result" 2>/dev/null || true)
453
+ [ "$result" = "pass" ]
454
+ }
455
+
456
+ verification_report_exists() {
457
+ local report
458
+ report=$(yaml_field_value "verification_report" 2>/dev/null || true)
459
+ [ -n "$report" ] && [ "$report" != "null" ] && [ -f "$report" ]
460
+ }
461
+
462
+ branch_status_handled() {
463
+ local status
464
+ status=$(yaml_field_value "branch_status" 2>/dev/null || true)
465
+ [ "$status" = "handled" ]
466
+ }
467
+
468
+ design_handoff_context_valid() {
469
+ local context recorded_hash actual_hash markdown
470
+ context=$(yaml_field_value "handoff_context" 2>/dev/null || true)
471
+ recorded_hash=$(yaml_field_value "handoff_hash" 2>/dev/null || true)
472
+
473
+ if [ -z "$context" ] || [ "$context" = "null" ]; then
474
+ echo "handoff_context is missing from .comet.yaml" >&2
475
+ echo "Next: run \"\$COMET_BASH\" \"\$COMET_HANDOFF\" $CHANGE design --write before invoking Superpowers." >&2
476
+ return 1
477
+ fi
478
+ if [ ! -s "$context" ]; then
479
+ echo "handoff_context does not point to a non-empty file: $context" >&2
480
+ echo "Next: regenerate the design handoff with comet-handoff.sh." >&2
481
+ return 1
482
+ fi
483
+ if [[ ! "$recorded_hash" =~ ^[a-f0-9]{64}$ ]]; then
484
+ echo "handoff_hash is missing or invalid: ${recorded_hash:-null}" >&2
485
+ echo "Next: regenerate the design handoff with comet-handoff.sh." >&2
486
+ return 1
487
+ fi
488
+
489
+ actual_hash=$(compute_handoff_hash)
490
+ if [ "$actual_hash" != "$recorded_hash" ]; then
491
+ echo "OpenSpec artifacts changed after handoff was generated." >&2
492
+ echo "Expected handoff_hash: $recorded_hash" >&2
493
+ echo "Actual handoff_hash: $actual_hash" >&2
494
+ echo "Next: rerun comet-handoff.sh so Superpowers receives the current OpenSpec context." >&2
495
+ return 1
496
+ fi
497
+
498
+ markdown="${context%.json}.md"
499
+ if [ ! -s "$markdown" ]; then
500
+ echo "design handoff markdown is missing or empty: $markdown" >&2
501
+ echo "Next: regenerate the design handoff with comet-handoff.sh." >&2
502
+ return 1
503
+ fi
504
+ }
505
+
506
+ design_handoff_markdown_traceable() {
507
+ local context markdown missing=0
508
+ context=$(yaml_field_value "handoff_context" 2>/dev/null || true)
509
+ if [ -z "$context" ] || [ "$context" = "null" ]; then
510
+ echo "handoff_context is missing from .comet.yaml" >&2
511
+ return 1
512
+ fi
513
+ markdown="${context%.json}.md"
514
+ if [ ! -s "$markdown" ]; then
515
+ echo "design handoff markdown is missing or empty: $markdown" >&2
516
+ return 1
517
+ fi
518
+ grep -q '^Generated-by: comet-handoff\.sh$' "$markdown" || {
519
+ echo "handoff markdown is missing Generated-by marker" >&2
520
+ missing=1
521
+ }
522
+ grep -Eq '^- Mode: (compact|full|beta)$' "$markdown" || {
523
+ echo "handoff markdown is missing Mode marker" >&2
524
+ missing=1
525
+ }
526
+ handoff_source_files | while IFS= read -r file; do
527
+ [ -f "$file" ] || continue
528
+ if ! grep -q "^- Source: $file$" "$markdown"; then
529
+ echo "handoff markdown is missing source reference: $file" >&2
530
+ exit 2
531
+ fi
532
+ if ! grep -q "^- SHA256: $(hash_file "$file")$" "$markdown"; then
533
+ echo "handoff markdown is missing current sha256 for: $file" >&2
534
+ exit 2
535
+ fi
536
+ done || missing=1
537
+
538
+ [ "$missing" -eq 0 ]
539
+ }
540
+
541
+ context_compression_mode() {
542
+ local mode
543
+ mode=$(yaml_field_value "context_compression" 2>/dev/null || true)
544
+ printf '%s\n' "${mode:-off}"
545
+ }
546
+
547
+ beta_spec_json_structurally_valid() {
548
+ local context missing=0
549
+ if [ "$(context_compression_mode)" != "beta" ]; then
550
+ return 0
551
+ fi
552
+
553
+ context=$(yaml_field_value "handoff_context" 2>/dev/null || true)
554
+ if [ -z "$context" ] || [ "$context" = "null" ]; then
555
+ echo "handoff_context is missing from .comet.yaml" >&2
556
+ return 1
557
+ fi
558
+ if [ ! -s "$context" ]; then
559
+ echo "spec-context.json is missing or empty: $context" >&2
560
+ return 1
561
+ fi
562
+
563
+ # Validate required JSON fields
564
+ grep -q '"change"' "$context" || { echo "spec-context.json missing 'change' field" >&2; return 1; }
565
+ grep -q '"phase"' "$context" || { echo "spec-context.json missing 'phase' field" >&2; return 1; }
566
+ grep -q '"mode": "beta"' "$context" || { echo "spec-context.json mode is not beta" >&2; return 1; }
567
+ grep -q '"files"' "$context" || { echo "spec-context.json missing 'files' field" >&2; return 1; }
568
+ grep -q '"context_hash"' "$context" || { echo "spec-context.json missing 'context_hash' field" >&2; return 1; }
569
+
570
+ # Verify all source files are referenced in the JSON
571
+ handoff_source_files | while IFS= read -r file; do
572
+ [ -f "$file" ] || continue
573
+ if ! grep -qF "$file" "$context"; then
574
+ echo "spec-context.json missing source file reference: $file" >&2
575
+ exit 2
576
+ fi
577
+ done || missing=1
578
+
579
+ [ "$missing" -eq 0 ]
580
+ }
581
+
582
+ design_doc_frontmatter_has() {
583
+ local design_doc="$1"
584
+ local field="$2"
585
+ local expected="$3"
586
+ awk '
587
+ {
588
+ line = $0
589
+ sub(/^\357\273\277/, "", line)
590
+ }
591
+ !in_fm && line == "---" { in_fm = 1; next }
592
+ in_fm && line == "---" { exit }
593
+ in_fm { print line }
594
+ ' "$design_doc" | grep -Eq "^${field}: ['\"]?${expected}['\"]?[[:space:]]*$"
595
+ }
596
+
597
+ design_doc_links_current_change() {
598
+ local design_doc
599
+ design_doc=$(yaml_field_value "design_doc" 2>/dev/null || true)
600
+ if [ -z "$design_doc" ] || [ "$design_doc" = "null" ] || [ ! -s "$design_doc" ]; then
601
+ echo "design_doc must point to an existing Superpowers Design Doc before leaving design." >&2
602
+ return 1
603
+ fi
604
+ design_doc_frontmatter_has "$design_doc" "comet_change" "$CHANGE"
605
+ }
606
+
607
+ design_doc_declares_technical_role() {
608
+ local design_doc
609
+ design_doc=$(yaml_field_value "design_doc" 2>/dev/null || true)
610
+ [ -n "$design_doc" ] && [ "$design_doc" != "null" ] && [ -s "$design_doc" ] &&
611
+ design_doc_frontmatter_has "$design_doc" "role" "technical-design"
612
+ }
613
+
614
+ design_doc_declares_canonical_spec() {
615
+ local design_doc
616
+ design_doc=$(yaml_field_value "design_doc" 2>/dev/null || true)
617
+ [ -n "$design_doc" ] && [ "$design_doc" != "null" ] && [ -s "$design_doc" ] &&
618
+ design_doc_frontmatter_has "$design_doc" "canonical_spec" "openspec"
619
+ }
620
+
621
+ archived_is_true() {
622
+ local val
623
+ val=$(yaml_field_value "archived" 2>/dev/null || true)
624
+ [ "$val" = "true" ]
625
+ }
626
+
627
+ # --- Phase-specific checks ---
628
+
629
+ guard_open() {
630
+ echo "=== Guard: open → next ===" >&2
631
+
632
+ local workflow
633
+ workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
634
+
635
+ check "proposal.md exists and non-empty" file_nonempty "$CHANGE_DIR/proposal.md"
636
+ if [ "$workflow" = "full" ]; then
637
+ check "design.md exists and non-empty" file_nonempty "$CHANGE_DIR/design.md"
638
+ fi
639
+ check "tasks.md exists and non-empty" file_nonempty "$CHANGE_DIR/tasks.md"
640
+ check "tasks.md has at least one task" tasks_has_any
641
+ }
642
+
643
+ guard_design() {
644
+ echo "=== Guard: design → build ===" >&2
645
+
646
+ local design_doc workflow
647
+ design_doc=$(yaml_field_value "design_doc" 2>/dev/null || true)
648
+ workflow=$(yaml_field_value "workflow" 2>/dev/null || true)
649
+
650
+ check "proposal.md exists" file_nonempty "$CHANGE_DIR/proposal.md"
651
+ check "design.md exists" file_nonempty "$CHANGE_DIR/design.md"
652
+ check "tasks.md exists" file_nonempty "$CHANGE_DIR/tasks.md"
653
+ check "design handoff context exists" design_handoff_context_valid
654
+ check "design handoff markdown is traceable" design_handoff_markdown_traceable
655
+ if [ "$(context_compression_mode)" = "beta" ]; then
656
+ check "beta spec-context.json is structurally valid" beta_spec_json_structurally_valid
657
+ fi
658
+
659
+ if [ "$workflow" = "full" ]; then
660
+ # Full workflow: design_doc is REQUIRED
661
+ check "design_doc is recorded for full workflow" design_doc_recorded
662
+ fi
663
+
664
+ if [ -n "$design_doc" ] && [ "$design_doc" != "null" ]; then
665
+ check "Design Doc ($design_doc) exists" file_nonempty "$design_doc"
666
+ check "Design Doc frontmatter links current change" design_doc_links_current_change
667
+ check "Design Doc declares technical design role" design_doc_declares_technical_role
668
+ check "Design Doc declares OpenSpec as canonical spec" design_doc_declares_canonical_spec
669
+ elif [ "$workflow" != "full" ]; then
670
+ warn " [WARN] No design_doc recorded in .comet.yaml (optional for hotfix/tweak)"
671
+ fi
672
+ }
673
+
674
+ design_doc_recorded() {
675
+ local design_doc
676
+ design_doc=$(yaml_field_value "design_doc" 2>/dev/null || true)
677
+ if [ -n "$design_doc" ] && [ "$design_doc" != "null" ] && [ -f "$design_doc" ]; then
678
+ return 0
679
+ fi
680
+ echo "design_doc must point to an existing Superpowers Design Doc for full workflow before leaving design." >&2
681
+ echo "Next: create the Design Doc and run: \"\$COMET_BASH\" \"\$COMET_STATE\" set $CHANGE design_doc <path>" >&2
682
+ return 1
683
+ }
684
+
685
+ guard_build() {
686
+ echo "=== Guard: build → verify ===" >&2
687
+
688
+ check "isolation selected" isolation_selected
689
+ check "build_mode selected" build_mode_selected
690
+ check "build_mode allowed for workflow" build_mode_allowed_for_workflow
691
+ check "subagent dispatch confirmed" subagent_dispatch_confirmed
692
+ check "tdd_mode selected" tdd_mode_selected
693
+ check "review_mode selected" review_mode_selected
694
+ check "tasks.md all tasks checked" tasks_all_done
695
+ check "Superpowers plan all tasks checked" plan_tasks_all_done
696
+ check "proposal.md exists" file_nonempty "$CHANGE_DIR/proposal.md"
697
+ check "Build passes" build_passes
698
+ }
699
+
700
+ guard_verify() {
701
+ echo "=== Guard: verify → archive ===" >&2
702
+
703
+ check "tasks.md all tasks checked" tasks_all_done
704
+ check "Build passes" verification_command_passes
705
+ check "verification_report exists" verification_report_exists
706
+ check "branch_status=handled" branch_status_handled
707
+ }
708
+
709
+ guard_archive() {
710
+ echo "=== Guard: archive completeness ===" >&2
711
+
712
+ check "archived is true" archived_is_true
713
+ check "proposal.md exists" file_nonempty "$CHANGE_DIR/proposal.md"
714
+ check "design.md exists" file_nonempty "$CHANGE_DIR/design.md"
715
+ check "tasks.md all tasks checked" tasks_all_done
716
+ }
717
+
718
+ apply_state_update() {
719
+ local state_sh="$SCRIPT_DIR/comet-state.sh"
720
+ local p="$1"
721
+
722
+ if [ -f "$state_sh" ]; then
723
+ case "$p" in
724
+ open) "$COMET_BASH" "$state_sh" transition "$CHANGE" open-complete ;;
725
+ design) "$COMET_BASH" "$state_sh" transition "$CHANGE" design-complete ;;
726
+ build) "$COMET_BASH" "$state_sh" transition "$CHANGE" build-complete ;;
727
+ verify) "$COMET_BASH" "$state_sh" transition "$CHANGE" verify-pass ;;
728
+ esac
729
+ else
730
+ red "FATAL: comet-state.sh not found; cannot apply state transition"
731
+ exit 1
732
+ fi
733
+ }
734
+
735
+ # --- Main ---
736
+
737
+ if [ "${COMET_GUARD_SOURCE_ONLY:-0}" = "1" ]; then
738
+ return 0 2>/dev/null
739
+ # shellcheck disable=SC2317 # unreachable if sourced; fallback for direct execution
740
+ red "ERROR: COMET_GUARD_SOURCE_ONLY=1 is only for sourcing, not direct execution" >&2
741
+ # shellcheck disable=SC2317
742
+ exit 1
743
+ fi
744
+
745
+ case "$PHASE" in
746
+ open) preflight ; guard_open ;;
747
+ design) preflight ; guard_design ;;
748
+ build) preflight ; guard_build ;;
749
+ verify) preflight ; guard_verify ;;
750
+ archive) preflight ; guard_archive ;;
751
+ *)
752
+ red "Unknown phase: $PHASE"
753
+ echo "Valid phases: open, design, build, verify, archive" >&2
754
+ exit 1
755
+ ;;
756
+ esac
757
+
758
+ if [ "$BLOCK" -eq 1 ]; then
759
+ echo "" >&2
760
+ red "BLOCKED — fix failing checks before proceeding to next phase"
761
+ exit 1
762
+ else
763
+ echo "" >&2
764
+ green "ALL CHECKS PASSED — ready for next phase"
765
+ if [ "$APPLY" -eq 1 ]; then
766
+ apply_state_update "$PHASE"
767
+ case "$PHASE" in
768
+ open)
769
+ new_phase=$(yaml_field_value "phase")
770
+ green " [APPLY] .comet.yaml updated: phase=$new_phase"
771
+ ;;
772
+ design) green " [APPLY] .comet.yaml updated: phase=build" ;;
773
+ build) green " [APPLY] .comet.yaml updated: phase=verify, verify_result=pending" ;;
774
+ verify) green " [APPLY] .comet.yaml updated: phase=archive, verify_result=pass" ;;
775
+ esac
776
+ fi
777
+ exit 0
778
+ fi