@rpamis/comet 0.3.8 → 0.4.0-beta.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 (627) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +381 -234
  3. package/assets/manifest.json +33 -12
  4. package/assets/skills/comet/SKILL.md +87 -102
  5. package/assets/skills/comet/reference/auto-transition.md +1 -1
  6. package/assets/skills/comet/reference/comet-yaml-fields.md +11 -4
  7. package/assets/skills/comet/reference/context-recovery.md +12 -2
  8. package/assets/skills/comet/reference/debug-gate.md +17 -1
  9. package/assets/skills/comet/reference/decision-point.md +13 -2
  10. package/assets/skills/comet/reference/dirty-worktree.md +59 -59
  11. package/assets/skills/comet/reference/intent-frame.md +74 -0
  12. package/assets/skills/comet/reference/scripts.md +69 -0
  13. package/assets/skills/comet/reference/subagent-dispatch.md +79 -23
  14. package/assets/skills/comet/rules/comet-phase-guard.en.md +43 -11
  15. package/assets/skills/comet/rules/comet-phase-guard.md +44 -11
  16. package/assets/skills/comet/runtime/classic/checks.yaml +6 -0
  17. package/assets/skills/comet/runtime/classic/guardrails.yaml +13 -0
  18. package/assets/skills/comet/runtime/classic/skill.yaml +122 -0
  19. package/assets/skills/comet/scripts/comet-archive.mjs +3 -0
  20. package/assets/skills/comet/scripts/comet-env.mjs +15 -0
  21. package/assets/skills/comet/scripts/comet-guard.mjs +3 -0
  22. package/assets/skills/comet/scripts/comet-handoff.mjs +3 -0
  23. package/assets/skills/comet/scripts/comet-hook-guard.mjs +3 -0
  24. package/assets/skills/comet/scripts/comet-intent.mjs +3 -0
  25. package/assets/skills/comet/scripts/comet-runtime.mjs +12857 -0
  26. package/assets/skills/comet/scripts/comet-state.mjs +3 -0
  27. package/assets/skills/comet/scripts/comet-yaml-validate.mjs +3 -0
  28. package/assets/skills/comet-any/SKILL.md +118 -0
  29. package/assets/skills/comet-any/reference/authored-zone-example.md +100 -0
  30. package/assets/skills/comet-any/reference/authoring-protocol.json +91 -0
  31. package/assets/skills/comet-any/reference/authoring-subagents.md +102 -0
  32. package/assets/skills/comet-any/reference/bundle-authoring.md +166 -0
  33. package/assets/skills/comet-any/reference/eval-provider.md +83 -0
  34. package/assets/skills/comet-any/reference/subagents/pause-points-author.md +75 -0
  35. package/assets/skills/comet-any/reference/subagents/reference-author.md +77 -0
  36. package/assets/skills/comet-any/reference/subagents/script-author.md +81 -0
  37. package/assets/skills/comet-any/reference/subagents/skill-core-author.md +129 -0
  38. package/assets/skills/comet-any/reference/subagents/skill-reviewer.md +124 -0
  39. package/assets/skills/comet-any/reference/subagents/workflow-entry-author.md +100 -0
  40. package/assets/skills/comet-archive/SKILL.md +25 -15
  41. package/assets/skills/comet-build/SKILL.md +51 -40
  42. package/assets/skills/comet-design/SKILL.md +14 -18
  43. package/assets/skills/comet-hotfix/SKILL.md +33 -43
  44. package/assets/skills/comet-open/SKILL.md +28 -21
  45. package/assets/skills/comet-tweak/SKILL.md +71 -65
  46. package/assets/skills/comet-verify/SKILL.md +31 -35
  47. package/assets/skills-zh/comet/SKILL.md +88 -102
  48. package/assets/skills-zh/comet/reference/auto-transition.md +3 -3
  49. package/assets/skills-zh/comet/reference/comet-yaml-fields.md +11 -4
  50. package/assets/skills-zh/comet/reference/context-recovery.md +12 -2
  51. package/assets/skills-zh/comet/reference/debug-gate.md +19 -3
  52. package/assets/skills-zh/comet/reference/decision-point.md +13 -2
  53. package/assets/skills-zh/comet/reference/dirty-worktree.md +59 -59
  54. package/assets/skills-zh/comet/reference/intent-frame.md +74 -0
  55. package/assets/skills-zh/comet/reference/scripts.md +69 -0
  56. package/assets/skills-zh/comet/reference/subagent-dispatch.md +79 -23
  57. package/assets/skills-zh/comet/runtime/classic/checks.yaml +6 -0
  58. package/assets/skills-zh/comet/runtime/classic/guardrails.yaml +13 -0
  59. package/assets/skills-zh/comet/runtime/classic/skill.yaml +122 -0
  60. package/assets/skills-zh/comet-any/SKILL.md +118 -0
  61. package/assets/skills-zh/comet-any/reference/authored-zone-example.md +100 -0
  62. package/assets/skills-zh/comet-any/reference/authoring-protocol.json +91 -0
  63. package/assets/skills-zh/comet-any/reference/authoring-subagents.md +107 -0
  64. package/assets/skills-zh/comet-any/reference/bundle-authoring.md +166 -0
  65. package/assets/skills-zh/comet-any/reference/eval-provider.md +66 -0
  66. package/assets/skills-zh/comet-any/reference/subagents/pause-points-author.md +79 -0
  67. package/assets/skills-zh/comet-any/reference/subagents/reference-author.md +81 -0
  68. package/assets/skills-zh/comet-any/reference/subagents/script-author.md +84 -0
  69. package/assets/skills-zh/comet-any/reference/subagents/skill-core-author.md +129 -0
  70. package/assets/skills-zh/comet-any/reference/subagents/skill-reviewer.md +124 -0
  71. package/assets/skills-zh/comet-any/reference/subagents/workflow-entry-author.md +98 -0
  72. package/assets/skills-zh/comet-archive/SKILL.md +25 -15
  73. package/assets/skills-zh/comet-build/SKILL.md +54 -43
  74. package/assets/skills-zh/comet-design/SKILL.md +16 -20
  75. package/assets/skills-zh/comet-hotfix/SKILL.md +37 -47
  76. package/assets/skills-zh/comet-open/SKILL.md +30 -23
  77. package/assets/skills-zh/comet-tweak/SKILL.md +70 -63
  78. package/assets/skills-zh/comet-verify/SKILL.md +30 -32
  79. package/bin/comet.js +1 -1
  80. package/dist/{cli → app/cli}/index.d.ts.map +1 -1
  81. package/dist/app/cli/index.js +430 -0
  82. package/dist/app/cli/index.js.map +1 -0
  83. package/dist/app/commands/bundle.d.ts +51 -0
  84. package/dist/app/commands/bundle.d.ts.map +1 -0
  85. package/dist/app/commands/bundle.js +387 -0
  86. package/dist/app/commands/bundle.js.map +1 -0
  87. package/dist/app/commands/creator.d.ts +14 -0
  88. package/dist/app/commands/creator.d.ts.map +1 -0
  89. package/dist/app/commands/creator.js +82 -0
  90. package/dist/app/commands/creator.js.map +1 -0
  91. package/dist/app/commands/dashboard.d.ts +16 -0
  92. package/dist/app/commands/dashboard.d.ts.map +1 -0
  93. package/dist/app/commands/dashboard.js +53 -0
  94. package/dist/app/commands/dashboard.js.map +1 -0
  95. package/dist/{commands → app/commands}/doctor.d.ts +1 -1
  96. package/dist/app/commands/doctor.d.ts.map +1 -0
  97. package/dist/{commands → app/commands}/doctor.js +114 -60
  98. package/dist/app/commands/doctor.js.map +1 -0
  99. package/dist/app/commands/eval.d.ts +17 -0
  100. package/dist/app/commands/eval.d.ts.map +1 -0
  101. package/dist/app/commands/eval.js +169 -0
  102. package/dist/app/commands/eval.js.map +1 -0
  103. package/dist/app/commands/i18n.d.ts +4 -0
  104. package/dist/app/commands/i18n.d.ts.map +1 -0
  105. package/dist/app/commands/i18n.js +174 -0
  106. package/dist/app/commands/i18n.js.map +1 -0
  107. package/dist/{commands → app/commands}/init.d.ts +6 -1
  108. package/dist/app/commands/init.d.ts.map +1 -0
  109. package/dist/app/commands/init.js +402 -0
  110. package/dist/app/commands/init.js.map +1 -0
  111. package/dist/app/commands/platform-select-prompt.d.ts +38 -0
  112. package/dist/app/commands/platform-select-prompt.d.ts.map +1 -0
  113. package/dist/app/commands/platform-select-prompt.js +141 -0
  114. package/dist/app/commands/platform-select-prompt.js.map +1 -0
  115. package/dist/app/commands/publish.d.ts +7 -0
  116. package/dist/app/commands/publish.d.ts.map +1 -0
  117. package/dist/app/commands/publish.js +14 -0
  118. package/dist/app/commands/publish.js.map +1 -0
  119. package/dist/app/commands/skill.d.ts +23 -0
  120. package/dist/app/commands/skill.d.ts.map +1 -0
  121. package/dist/app/commands/skill.js +208 -0
  122. package/dist/app/commands/skill.js.map +1 -0
  123. package/dist/app/commands/status.d.ts.map +1 -0
  124. package/dist/app/commands/status.js +159 -0
  125. package/dist/app/commands/status.js.map +1 -0
  126. package/dist/{commands → app/commands}/uninstall.d.ts +1 -1
  127. package/dist/app/commands/uninstall.d.ts.map +1 -0
  128. package/dist/{commands → app/commands}/uninstall.js +37 -18
  129. package/dist/app/commands/uninstall.js.map +1 -0
  130. package/dist/{commands → app/commands}/update.d.ts +6 -4
  131. package/dist/app/commands/update.d.ts.map +1 -0
  132. package/dist/{commands → app/commands}/update.js +77 -46
  133. package/dist/app/commands/update.js.map +1 -0
  134. package/dist/config/repository-layout.json +98 -0
  135. package/dist/domains/bundle/authoring.d.ts +82 -0
  136. package/dist/domains/bundle/authoring.d.ts.map +1 -0
  137. package/dist/domains/bundle/authoring.js +185 -0
  138. package/dist/domains/bundle/authoring.js.map +1 -0
  139. package/dist/domains/bundle/bundle-platform.d.ts +39 -0
  140. package/dist/domains/bundle/bundle-platform.d.ts.map +1 -0
  141. package/dist/domains/bundle/bundle-platform.js +287 -0
  142. package/dist/domains/bundle/bundle-platform.js.map +1 -0
  143. package/dist/domains/bundle/candidates.d.ts +29 -0
  144. package/dist/domains/bundle/candidates.d.ts.map +1 -0
  145. package/dist/domains/bundle/candidates.js +37 -0
  146. package/dist/domains/bundle/candidates.js.map +1 -0
  147. package/dist/domains/bundle/compatibility-benchmark.d.ts +12 -0
  148. package/dist/domains/bundle/compatibility-benchmark.d.ts.map +1 -0
  149. package/dist/domains/bundle/compatibility-benchmark.js +224 -0
  150. package/dist/domains/bundle/compatibility-benchmark.js.map +1 -0
  151. package/dist/domains/bundle/compiler.d.ts +5 -0
  152. package/dist/domains/bundle/compiler.d.ts.map +1 -0
  153. package/dist/domains/bundle/compiler.js +106 -0
  154. package/dist/domains/bundle/compiler.js.map +1 -0
  155. package/dist/domains/bundle/distribute.d.ts +33 -0
  156. package/dist/domains/bundle/distribute.d.ts.map +1 -0
  157. package/dist/domains/bundle/distribute.js +166 -0
  158. package/dist/domains/bundle/distribute.js.map +1 -0
  159. package/dist/domains/bundle/draft.d.ts +19 -0
  160. package/dist/domains/bundle/draft.d.ts.map +1 -0
  161. package/dist/domains/bundle/draft.js +82 -0
  162. package/dist/domains/bundle/draft.js.map +1 -0
  163. package/dist/domains/bundle/eval.d.ts +36 -0
  164. package/dist/domains/bundle/eval.d.ts.map +1 -0
  165. package/dist/domains/bundle/eval.js +501 -0
  166. package/dist/domains/bundle/eval.js.map +1 -0
  167. package/dist/domains/bundle/factory-compose.d.ts +12 -0
  168. package/dist/domains/bundle/factory-compose.d.ts.map +1 -0
  169. package/dist/domains/bundle/factory-compose.js +309 -0
  170. package/dist/domains/bundle/factory-compose.js.map +1 -0
  171. package/dist/domains/bundle/factory-guide.d.ts +37 -0
  172. package/dist/domains/bundle/factory-guide.d.ts.map +1 -0
  173. package/dist/domains/bundle/factory-guide.js +96 -0
  174. package/dist/domains/bundle/factory-guide.js.map +1 -0
  175. package/dist/domains/bundle/factory-plan.d.ts +48 -0
  176. package/dist/domains/bundle/factory-plan.d.ts.map +1 -0
  177. package/dist/domains/bundle/factory-plan.js +172 -0
  178. package/dist/domains/bundle/factory-plan.js.map +1 -0
  179. package/dist/domains/bundle/factory-proposal.d.ts +31 -0
  180. package/dist/domains/bundle/factory-proposal.d.ts.map +1 -0
  181. package/dist/domains/bundle/factory-proposal.js +225 -0
  182. package/dist/domains/bundle/factory-proposal.js.map +1 -0
  183. package/dist/domains/bundle/factory-resolve.d.ts +11 -0
  184. package/dist/domains/bundle/factory-resolve.d.ts.map +1 -0
  185. package/dist/domains/bundle/factory-resolve.js +121 -0
  186. package/dist/domains/bundle/factory-resolve.js.map +1 -0
  187. package/dist/domains/bundle/factory.d.ts +17 -0
  188. package/dist/domains/bundle/factory.d.ts.map +1 -0
  189. package/dist/domains/bundle/factory.js +511 -0
  190. package/dist/domains/bundle/factory.js.map +1 -0
  191. package/dist/domains/bundle/hash.d.ts +3 -0
  192. package/dist/domains/bundle/hash.d.ts.map +1 -0
  193. package/dist/domains/bundle/hash.js +72 -0
  194. package/dist/domains/bundle/hash.js.map +1 -0
  195. package/dist/domains/bundle/load.d.ts +4 -0
  196. package/dist/domains/bundle/load.d.ts.map +1 -0
  197. package/dist/domains/bundle/load.js +355 -0
  198. package/dist/domains/bundle/load.js.map +1 -0
  199. package/dist/domains/bundle/next-action.d.ts +37 -0
  200. package/dist/domains/bundle/next-action.d.ts.map +1 -0
  201. package/dist/domains/bundle/next-action.js +185 -0
  202. package/dist/domains/bundle/next-action.js.map +1 -0
  203. package/dist/domains/bundle/platform.d.ts +21 -0
  204. package/dist/domains/bundle/platform.d.ts.map +1 -0
  205. package/dist/domains/bundle/platform.js +170 -0
  206. package/dist/domains/bundle/platform.js.map +1 -0
  207. package/dist/domains/bundle/preferences.d.ts +11 -0
  208. package/dist/domains/bundle/preferences.d.ts.map +1 -0
  209. package/dist/domains/bundle/preferences.js +17 -0
  210. package/dist/domains/bundle/preferences.js.map +1 -0
  211. package/dist/domains/bundle/publish.d.ts +14 -0
  212. package/dist/domains/bundle/publish.d.ts.map +1 -0
  213. package/dist/domains/bundle/publish.js +159 -0
  214. package/dist/domains/bundle/publish.js.map +1 -0
  215. package/dist/domains/bundle/readiness-user-summary.d.ts +25 -0
  216. package/dist/domains/bundle/readiness-user-summary.d.ts.map +1 -0
  217. package/dist/domains/bundle/readiness-user-summary.js +186 -0
  218. package/dist/domains/bundle/readiness-user-summary.js.map +1 -0
  219. package/dist/domains/bundle/review-summary.d.ts +36 -0
  220. package/dist/domains/bundle/review-summary.d.ts.map +1 -0
  221. package/dist/domains/bundle/review-summary.js +348 -0
  222. package/dist/domains/bundle/review-summary.js.map +1 -0
  223. package/dist/domains/bundle/state.d.ts +7 -0
  224. package/dist/domains/bundle/state.d.ts.map +1 -0
  225. package/dist/domains/bundle/state.js +132 -0
  226. package/dist/domains/bundle/state.js.map +1 -0
  227. package/dist/domains/bundle/types.d.ts +347 -0
  228. package/dist/domains/bundle/types.d.ts.map +1 -0
  229. package/dist/domains/bundle/types.js.map +1 -0
  230. package/dist/domains/bundle/user-facing.d.ts +48 -0
  231. package/dist/domains/bundle/user-facing.d.ts.map +1 -0
  232. package/dist/domains/bundle/user-facing.js +73 -0
  233. package/dist/domains/bundle/user-facing.js.map +1 -0
  234. package/dist/domains/bundle/validate.d.ts +5 -0
  235. package/dist/domains/bundle/validate.d.ts.map +1 -0
  236. package/dist/domains/bundle/validate.js +292 -0
  237. package/dist/domains/bundle/validate.js.map +1 -0
  238. package/dist/domains/comet-classic/classic-archive-entry.d.ts +2 -0
  239. package/dist/domains/comet-classic/classic-archive-entry.d.ts.map +1 -0
  240. package/dist/domains/comet-classic/classic-archive-entry.js +4 -0
  241. package/dist/domains/comet-classic/classic-archive-entry.js.map +1 -0
  242. package/dist/domains/comet-classic/classic-archive.d.ts +3 -0
  243. package/dist/domains/comet-classic/classic-archive.d.ts.map +1 -0
  244. package/dist/domains/comet-classic/classic-archive.js +392 -0
  245. package/dist/domains/comet-classic/classic-archive.js.map +1 -0
  246. package/dist/domains/comet-classic/classic-cli.d.ts +15 -0
  247. package/dist/domains/comet-classic/classic-cli.d.ts.map +1 -0
  248. package/dist/domains/comet-classic/classic-cli.js +94 -0
  249. package/dist/domains/comet-classic/classic-cli.js.map +1 -0
  250. package/dist/domains/comet-classic/classic-diagnostics.d.ts +16 -0
  251. package/dist/domains/comet-classic/classic-diagnostics.d.ts.map +1 -0
  252. package/dist/domains/comet-classic/classic-diagnostics.js +57 -0
  253. package/dist/domains/comet-classic/classic-diagnostics.js.map +1 -0
  254. package/dist/domains/comet-classic/classic-evidence.d.ts +10 -0
  255. package/dist/domains/comet-classic/classic-evidence.d.ts.map +1 -0
  256. package/dist/domains/comet-classic/classic-evidence.js +114 -0
  257. package/dist/domains/comet-classic/classic-evidence.js.map +1 -0
  258. package/dist/domains/comet-classic/classic-guard-entry.d.ts +2 -0
  259. package/dist/domains/comet-classic/classic-guard-entry.d.ts.map +1 -0
  260. package/dist/domains/comet-classic/classic-guard-entry.js +4 -0
  261. package/dist/domains/comet-classic/classic-guard-entry.js.map +1 -0
  262. package/dist/domains/comet-classic/classic-guard.d.ts +3 -0
  263. package/dist/domains/comet-classic/classic-guard.d.ts.map +1 -0
  264. package/dist/domains/comet-classic/classic-guard.js +833 -0
  265. package/dist/domains/comet-classic/classic-guard.js.map +1 -0
  266. package/dist/domains/comet-classic/classic-handoff-entry.d.ts +2 -0
  267. package/dist/domains/comet-classic/classic-handoff-entry.d.ts.map +1 -0
  268. package/dist/domains/comet-classic/classic-handoff-entry.js +4 -0
  269. package/dist/domains/comet-classic/classic-handoff-entry.js.map +1 -0
  270. package/dist/domains/comet-classic/classic-handoff.d.ts +3 -0
  271. package/dist/domains/comet-classic/classic-handoff.d.ts.map +1 -0
  272. package/dist/domains/comet-classic/classic-handoff.js +478 -0
  273. package/dist/domains/comet-classic/classic-handoff.js.map +1 -0
  274. package/dist/domains/comet-classic/classic-hook-guard-entry.d.ts +2 -0
  275. package/dist/domains/comet-classic/classic-hook-guard-entry.d.ts.map +1 -0
  276. package/dist/domains/comet-classic/classic-hook-guard-entry.js +4 -0
  277. package/dist/domains/comet-classic/classic-hook-guard-entry.js.map +1 -0
  278. package/dist/domains/comet-classic/classic-hook-guard.d.ts +3 -0
  279. package/dist/domains/comet-classic/classic-hook-guard.d.ts.map +1 -0
  280. package/dist/domains/comet-classic/classic-hook-guard.js +302 -0
  281. package/dist/domains/comet-classic/classic-hook-guard.js.map +1 -0
  282. package/dist/domains/comet-classic/classic-intent-command.d.ts +3 -0
  283. package/dist/domains/comet-classic/classic-intent-command.d.ts.map +1 -0
  284. package/dist/domains/comet-classic/classic-intent-command.js +40 -0
  285. package/dist/domains/comet-classic/classic-intent-command.js.map +1 -0
  286. package/dist/domains/comet-classic/classic-intent-entry.d.ts +2 -0
  287. package/dist/domains/comet-classic/classic-intent-entry.d.ts.map +1 -0
  288. package/dist/domains/comet-classic/classic-intent-entry.js +4 -0
  289. package/dist/domains/comet-classic/classic-intent-entry.js.map +1 -0
  290. package/dist/domains/comet-classic/classic-intent.d.ts +79 -0
  291. package/dist/domains/comet-classic/classic-intent.d.ts.map +1 -0
  292. package/dist/domains/comet-classic/classic-intent.js +307 -0
  293. package/dist/domains/comet-classic/classic-intent.js.map +1 -0
  294. package/dist/domains/comet-classic/classic-migrate.d.ts +18 -0
  295. package/dist/domains/comet-classic/classic-migrate.d.ts.map +1 -0
  296. package/dist/domains/comet-classic/classic-migrate.js +184 -0
  297. package/dist/domains/comet-classic/classic-migrate.js.map +1 -0
  298. package/dist/domains/comet-classic/classic-paths.d.ts +8 -0
  299. package/dist/domains/comet-classic/classic-paths.d.ts.map +1 -0
  300. package/dist/domains/comet-classic/classic-paths.js +61 -0
  301. package/dist/domains/comet-classic/classic-paths.js.map +1 -0
  302. package/dist/domains/comet-classic/classic-resolver.d.ts +10 -0
  303. package/dist/domains/comet-classic/classic-resolver.d.ts.map +1 -0
  304. package/dist/domains/comet-classic/classic-resolver.js +89 -0
  305. package/dist/domains/comet-classic/classic-resolver.js.map +1 -0
  306. package/dist/domains/comet-classic/classic-runtime-evals.d.ts +9 -0
  307. package/dist/domains/comet-classic/classic-runtime-evals.d.ts.map +1 -0
  308. package/dist/domains/comet-classic/classic-runtime-evals.js +45 -0
  309. package/dist/domains/comet-classic/classic-runtime-evals.js.map +1 -0
  310. package/dist/domains/comet-classic/classic-runtime-run.d.ts +7 -0
  311. package/dist/domains/comet-classic/classic-runtime-run.d.ts.map +1 -0
  312. package/dist/domains/comet-classic/classic-runtime-run.js +105 -0
  313. package/dist/domains/comet-classic/classic-runtime-run.js.map +1 -0
  314. package/dist/domains/comet-classic/classic-script-entry.d.ts +3 -0
  315. package/dist/domains/comet-classic/classic-script-entry.d.ts.map +1 -0
  316. package/dist/domains/comet-classic/classic-script-entry.js +31 -0
  317. package/dist/domains/comet-classic/classic-script-entry.js.map +1 -0
  318. package/dist/domains/comet-classic/classic-state-command.d.ts +3 -0
  319. package/dist/domains/comet-classic/classic-state-command.d.ts.map +1 -0
  320. package/dist/domains/comet-classic/classic-state-command.js +984 -0
  321. package/dist/domains/comet-classic/classic-state-command.js.map +1 -0
  322. package/dist/domains/comet-classic/classic-state-entry.d.ts +2 -0
  323. package/dist/domains/comet-classic/classic-state-entry.d.ts.map +1 -0
  324. package/dist/domains/comet-classic/classic-state-entry.js +4 -0
  325. package/dist/domains/comet-classic/classic-state-entry.js.map +1 -0
  326. package/dist/domains/comet-classic/classic-state-events.d.ts +18 -0
  327. package/dist/domains/comet-classic/classic-state-events.d.ts.map +1 -0
  328. package/dist/domains/comet-classic/classic-state-events.js +15 -0
  329. package/dist/domains/comet-classic/classic-state-events.js.map +1 -0
  330. package/dist/domains/comet-classic/classic-state.d.ts +69 -0
  331. package/dist/domains/comet-classic/classic-state.d.ts.map +1 -0
  332. package/dist/domains/comet-classic/classic-state.js +238 -0
  333. package/dist/domains/comet-classic/classic-state.js.map +1 -0
  334. package/dist/domains/comet-classic/classic-store.d.ts +7 -0
  335. package/dist/domains/comet-classic/classic-store.d.ts.map +1 -0
  336. package/dist/domains/comet-classic/classic-store.js +127 -0
  337. package/dist/domains/comet-classic/classic-store.js.map +1 -0
  338. package/dist/domains/comet-classic/classic-transitions.d.ts +24 -0
  339. package/dist/domains/comet-classic/classic-transitions.d.ts.map +1 -0
  340. package/dist/domains/comet-classic/classic-transitions.js +124 -0
  341. package/dist/domains/comet-classic/classic-transitions.js.map +1 -0
  342. package/dist/domains/comet-classic/classic-validate-command.d.ts +3 -0
  343. package/dist/domains/comet-classic/classic-validate-command.d.ts.map +1 -0
  344. package/dist/domains/comet-classic/classic-validate-command.js +154 -0
  345. package/dist/domains/comet-classic/classic-validate-command.js.map +1 -0
  346. package/dist/domains/comet-classic/classic-validate-entry.d.ts +2 -0
  347. package/dist/domains/comet-classic/classic-validate-entry.d.ts.map +1 -0
  348. package/dist/domains/comet-classic/classic-validate-entry.js +4 -0
  349. package/dist/domains/comet-classic/classic-validate-entry.js.map +1 -0
  350. package/dist/domains/comet-classic/index.d.ts +20 -0
  351. package/dist/domains/comet-classic/index.d.ts.map +1 -0
  352. package/dist/domains/comet-classic/index.js +20 -0
  353. package/dist/domains/comet-classic/index.js.map +1 -0
  354. package/dist/domains/dashboard/collector.d.ts +12 -0
  355. package/dist/domains/dashboard/collector.d.ts.map +1 -0
  356. package/dist/domains/dashboard/collector.js +475 -0
  357. package/dist/domains/dashboard/collector.js.map +1 -0
  358. package/dist/domains/dashboard/git.d.ts +8 -0
  359. package/dist/domains/dashboard/git.d.ts.map +1 -0
  360. package/dist/domains/dashboard/git.js +69 -0
  361. package/dist/domains/dashboard/git.js.map +1 -0
  362. package/dist/domains/dashboard/next-action.d.ts +17 -0
  363. package/dist/domains/dashboard/next-action.d.ts.map +1 -0
  364. package/dist/domains/dashboard/next-action.js +83 -0
  365. package/dist/domains/dashboard/next-action.js.map +1 -0
  366. package/dist/domains/dashboard/open-browser.d.ts +9 -0
  367. package/dist/domains/dashboard/open-browser.d.ts.map +1 -0
  368. package/dist/domains/dashboard/open-browser.js +40 -0
  369. package/dist/domains/dashboard/open-browser.js.map +1 -0
  370. package/dist/domains/dashboard/risk.d.ts +24 -0
  371. package/dist/domains/dashboard/risk.d.ts.map +1 -0
  372. package/dist/domains/dashboard/risk.js +97 -0
  373. package/dist/domains/dashboard/risk.js.map +1 -0
  374. package/dist/domains/dashboard/server.d.ts +21 -0
  375. package/dist/domains/dashboard/server.d.ts.map +1 -0
  376. package/dist/domains/dashboard/server.js +149 -0
  377. package/dist/domains/dashboard/server.js.map +1 -0
  378. package/dist/domains/dashboard/task-parser.d.ts +13 -0
  379. package/dist/domains/dashboard/task-parser.d.ts.map +1 -0
  380. package/dist/domains/dashboard/task-parser.js +82 -0
  381. package/dist/domains/dashboard/task-parser.js.map +1 -0
  382. package/dist/domains/dashboard/types.d.ts +122 -0
  383. package/dist/domains/dashboard/types.d.ts.map +1 -0
  384. package/dist/domains/dashboard/types.js +10 -0
  385. package/dist/domains/dashboard/types.js.map +1 -0
  386. package/dist/domains/dashboard/verify-parser.d.ts +18 -0
  387. package/dist/domains/dashboard/verify-parser.d.ts.map +1 -0
  388. package/dist/domains/dashboard/verify-parser.js +94 -0
  389. package/dist/domains/dashboard/verify-parser.js.map +1 -0
  390. package/dist/domains/dashboard/web/assets/demo-DQyfozbi.js +1 -0
  391. package/dist/domains/dashboard/web/assets/index-BcO3_QlT.css +1 -0
  392. package/dist/domains/dashboard/web/assets/index-CjU3VXVu.js +22 -0
  393. package/dist/domains/dashboard/web/favicon.png +0 -0
  394. package/dist/domains/dashboard/web/index.html +16 -0
  395. package/dist/domains/dashboard/yaml.d.ts +13 -0
  396. package/dist/domains/dashboard/yaml.d.ts.map +1 -0
  397. package/dist/domains/dashboard/yaml.js +61 -0
  398. package/dist/domains/dashboard/yaml.js.map +1 -0
  399. package/dist/domains/engine/evals.d.ts +4 -0
  400. package/dist/domains/engine/evals.d.ts.map +1 -0
  401. package/dist/domains/engine/evals.js +25 -0
  402. package/dist/domains/engine/evals.js.map +1 -0
  403. package/dist/domains/engine/guardrails.d.ts +10 -0
  404. package/dist/domains/engine/guardrails.d.ts.map +1 -0
  405. package/dist/domains/engine/guardrails.js +25 -0
  406. package/dist/domains/engine/guardrails.js.map +1 -0
  407. package/dist/domains/engine/loop.d.ts +15 -0
  408. package/dist/domains/engine/loop.d.ts.map +1 -0
  409. package/dist/domains/engine/loop.js +126 -0
  410. package/dist/domains/engine/loop.js.map +1 -0
  411. package/dist/domains/engine/manual-run.d.ts +30 -0
  412. package/dist/domains/engine/manual-run.d.ts.map +1 -0
  413. package/dist/domains/engine/manual-run.js +184 -0
  414. package/dist/domains/engine/manual-run.js.map +1 -0
  415. package/dist/domains/engine/resolver.d.ts +20 -0
  416. package/dist/domains/engine/resolver.d.ts.map +1 -0
  417. package/dist/domains/engine/resolver.js +36 -0
  418. package/dist/domains/engine/resolver.js.map +1 -0
  419. package/dist/domains/engine/run-store.d.ts +13 -0
  420. package/dist/domains/engine/run-store.d.ts.map +1 -0
  421. package/dist/domains/engine/run-store.js +100 -0
  422. package/dist/domains/engine/run-store.js.map +1 -0
  423. package/dist/domains/engine/runtime-types.d.ts +11 -0
  424. package/dist/domains/engine/runtime-types.d.ts.map +1 -0
  425. package/dist/domains/engine/runtime-types.js +2 -0
  426. package/dist/domains/engine/runtime-types.js.map +1 -0
  427. package/dist/domains/engine/standalone-run.d.ts +13 -0
  428. package/dist/domains/engine/standalone-run.d.ts.map +1 -0
  429. package/dist/domains/engine/standalone-run.js +27 -0
  430. package/dist/domains/engine/standalone-run.js.map +1 -0
  431. package/dist/domains/engine/state.d.ts +10 -0
  432. package/dist/domains/engine/state.d.ts.map +1 -0
  433. package/dist/domains/engine/state.js +160 -0
  434. package/dist/domains/engine/state.js.map +1 -0
  435. package/dist/domains/engine/types.d.ts +51 -0
  436. package/dist/domains/engine/types.d.ts.map +1 -0
  437. package/dist/domains/engine/types.js +2 -0
  438. package/dist/domains/engine/types.js.map +1 -0
  439. package/dist/domains/eval/index.d.ts +7 -0
  440. package/dist/domains/eval/index.d.ts.map +1 -0
  441. package/dist/domains/eval/index.js +11 -0
  442. package/dist/domains/eval/index.js.map +1 -0
  443. package/dist/domains/eval/repository-benchmarks.d.ts +6 -0
  444. package/dist/domains/eval/repository-benchmarks.d.ts.map +1 -0
  445. package/dist/domains/eval/repository-benchmarks.js +10 -0
  446. package/dist/domains/eval/repository-benchmarks.js.map +1 -0
  447. package/dist/domains/factory/artifacts.d.ts +53 -0
  448. package/dist/domains/factory/artifacts.d.ts.map +1 -0
  449. package/dist/domains/factory/artifacts.js +8 -0
  450. package/dist/domains/factory/artifacts.js.map +1 -0
  451. package/dist/domains/factory/package.d.ts +7 -0
  452. package/dist/domains/factory/package.d.ts.map +1 -0
  453. package/dist/domains/factory/package.js +1511 -0
  454. package/dist/domains/factory/package.js.map +1 -0
  455. package/dist/domains/factory/types.d.ts +127 -0
  456. package/dist/domains/factory/types.d.ts.map +1 -0
  457. package/dist/domains/factory/types.js +2 -0
  458. package/dist/domains/factory/types.js.map +1 -0
  459. package/dist/domains/integrations/codegraph.d.ts +6 -0
  460. package/dist/domains/integrations/codegraph.d.ts.map +1 -0
  461. package/dist/domains/integrations/codegraph.js +118 -0
  462. package/dist/domains/integrations/codegraph.js.map +1 -0
  463. package/dist/domains/integrations/openspec.d.ts +18 -0
  464. package/dist/domains/integrations/openspec.d.ts.map +1 -0
  465. package/dist/{core → domains/integrations}/openspec.js +114 -31
  466. package/dist/domains/integrations/openspec.js.map +1 -0
  467. package/dist/domains/integrations/superpowers.d.ts +21 -0
  468. package/dist/domains/integrations/superpowers.d.ts.map +1 -0
  469. package/dist/{core → domains/integrations}/superpowers.js +63 -14
  470. package/dist/domains/integrations/superpowers.js.map +1 -0
  471. package/dist/domains/skill/discovery.d.ts +17 -0
  472. package/dist/domains/skill/discovery.d.ts.map +1 -0
  473. package/dist/domains/skill/discovery.js +80 -0
  474. package/dist/domains/skill/discovery.js.map +1 -0
  475. package/dist/domains/skill/find.d.ts +41 -0
  476. package/dist/domains/skill/find.d.ts.map +1 -0
  477. package/dist/domains/skill/find.js +251 -0
  478. package/dist/domains/skill/find.js.map +1 -0
  479. package/dist/domains/skill/install.d.ts +11 -0
  480. package/dist/domains/skill/install.d.ts.map +1 -0
  481. package/dist/domains/skill/install.js +82 -0
  482. package/dist/domains/skill/install.js.map +1 -0
  483. package/dist/domains/skill/inventory.d.ts +19 -0
  484. package/dist/domains/skill/inventory.d.ts.map +1 -0
  485. package/dist/domains/skill/inventory.js +64 -0
  486. package/dist/domains/skill/inventory.js.map +1 -0
  487. package/dist/domains/skill/languages.d.ts +19 -0
  488. package/dist/domains/skill/languages.d.ts.map +1 -0
  489. package/dist/domains/skill/languages.js +21 -0
  490. package/dist/domains/skill/languages.js.map +1 -0
  491. package/dist/domains/skill/load.d.ts +5 -0
  492. package/dist/domains/skill/load.d.ts.map +1 -0
  493. package/dist/domains/skill/load.js +313 -0
  494. package/dist/domains/skill/load.js.map +1 -0
  495. package/dist/domains/skill/platform-install.d.ts +87 -0
  496. package/dist/domains/skill/platform-install.d.ts.map +1 -0
  497. package/dist/{core/skills.js → domains/skill/platform-install.js} +242 -42
  498. package/dist/domains/skill/platform-install.js.map +1 -0
  499. package/dist/domains/skill/preferences.d.ts +42 -0
  500. package/dist/domains/skill/preferences.d.ts.map +1 -0
  501. package/dist/domains/skill/preferences.js +118 -0
  502. package/dist/domains/skill/preferences.js.map +1 -0
  503. package/dist/domains/skill/snapshot.d.ts +8 -0
  504. package/dist/domains/skill/snapshot.d.ts.map +1 -0
  505. package/dist/domains/skill/snapshot.js +184 -0
  506. package/dist/domains/skill/snapshot.js.map +1 -0
  507. package/dist/domains/skill/types.d.ts +85 -0
  508. package/dist/domains/skill/types.d.ts.map +1 -0
  509. package/dist/domains/skill/types.js +2 -0
  510. package/dist/{core → domains/skill}/types.js.map +1 -1
  511. package/dist/{core → domains/skill}/uninstall.d.ts +2 -18
  512. package/dist/domains/skill/uninstall.d.ts.map +1 -0
  513. package/dist/{core → domains/skill}/uninstall.js +15 -66
  514. package/dist/domains/skill/uninstall.js.map +1 -0
  515. package/dist/domains/skill/validate.d.ts +3 -0
  516. package/dist/domains/skill/validate.d.ts.map +1 -0
  517. package/dist/domains/skill/validate.js +81 -0
  518. package/dist/domains/skill/validate.js.map +1 -0
  519. package/dist/domains/workflow-contract/builtins.d.ts +8 -0
  520. package/dist/domains/workflow-contract/builtins.d.ts.map +1 -0
  521. package/dist/domains/workflow-contract/builtins.js +229 -0
  522. package/dist/domains/workflow-contract/builtins.js.map +1 -0
  523. package/dist/domains/workflow-contract/hash.d.ts +3 -0
  524. package/dist/domains/workflow-contract/hash.d.ts.map +1 -0
  525. package/dist/domains/workflow-contract/hash.js +16 -0
  526. package/dist/domains/workflow-contract/hash.js.map +1 -0
  527. package/dist/domains/workflow-contract/index.d.ts +6 -0
  528. package/dist/domains/workflow-contract/index.d.ts.map +1 -0
  529. package/dist/domains/workflow-contract/index.js +5 -0
  530. package/dist/domains/workflow-contract/index.js.map +1 -0
  531. package/dist/domains/workflow-contract/normalize.d.ts +3 -0
  532. package/dist/domains/workflow-contract/normalize.d.ts.map +1 -0
  533. package/dist/domains/workflow-contract/normalize.js +146 -0
  534. package/dist/domains/workflow-contract/normalize.js.map +1 -0
  535. package/dist/domains/workflow-contract/types.d.ts +128 -0
  536. package/dist/domains/workflow-contract/types.d.ts.map +1 -0
  537. package/dist/domains/workflow-contract/types.js +2 -0
  538. package/dist/domains/workflow-contract/types.js.map +1 -0
  539. package/dist/domains/workflow-contract/validation.d.ts +3 -0
  540. package/dist/domains/workflow-contract/validation.d.ts.map +1 -0
  541. package/dist/domains/workflow-contract/validation.js +180 -0
  542. package/dist/domains/workflow-contract/validation.js.map +1 -0
  543. package/dist/platform/fs/file-system.d.ts.map +1 -0
  544. package/dist/platform/fs/file-system.js.map +1 -0
  545. package/dist/{core → platform/install}/detect.d.ts +6 -1
  546. package/dist/platform/install/detect.d.ts.map +1 -0
  547. package/dist/{core → platform/install}/detect.js +32 -14
  548. package/dist/platform/install/detect.js.map +1 -0
  549. package/dist/platform/install/platforms.d.ts.map +1 -0
  550. package/dist/{core → platform/install}/platforms.js +41 -0
  551. package/dist/platform/install/platforms.js.map +1 -0
  552. package/dist/platform/install/types.d.ts +3 -0
  553. package/dist/platform/install/types.d.ts.map +1 -0
  554. package/dist/platform/install/types.js +2 -0
  555. package/dist/platform/install/types.js.map +1 -0
  556. package/dist/platform/paths/repository-layout.d.ts +22 -0
  557. package/dist/platform/paths/repository-layout.d.ts.map +1 -0
  558. package/dist/platform/paths/repository-layout.js +11 -0
  559. package/dist/platform/paths/repository-layout.js.map +1 -0
  560. package/dist/platform/process/command-error.d.ts.map +1 -0
  561. package/dist/platform/process/command-error.js.map +1 -0
  562. package/dist/platform/process/shell-quote.d.ts +22 -0
  563. package/dist/platform/process/shell-quote.d.ts.map +1 -0
  564. package/dist/platform/process/shell-quote.js +34 -0
  565. package/dist/platform/process/shell-quote.js.map +1 -0
  566. package/dist/platform/version/version.d.ts.map +1 -0
  567. package/dist/{core → platform/version}/version.js +16 -3
  568. package/dist/platform/version/version.js.map +1 -0
  569. package/package.json +40 -14
  570. package/assets/skills/comet/scripts/comet-archive.sh +0 -311
  571. package/assets/skills/comet/scripts/comet-env.sh +0 -110
  572. package/assets/skills/comet/scripts/comet-guard.sh +0 -752
  573. package/assets/skills/comet/scripts/comet-handoff.sh +0 -390
  574. package/assets/skills/comet/scripts/comet-hook-guard.sh +0 -260
  575. package/assets/skills/comet/scripts/comet-state.sh +0 -1245
  576. package/assets/skills/comet/scripts/comet-yaml-validate.sh +0 -223
  577. package/dist/cli/index.js +0 -83
  578. package/dist/cli/index.js.map +0 -1
  579. package/dist/commands/doctor.d.ts.map +0 -1
  580. package/dist/commands/doctor.js.map +0 -1
  581. package/dist/commands/init.d.ts.map +0 -1
  582. package/dist/commands/init.js +0 -300
  583. package/dist/commands/init.js.map +0 -1
  584. package/dist/commands/status.d.ts.map +0 -1
  585. package/dist/commands/status.js +0 -108
  586. package/dist/commands/status.js.map +0 -1
  587. package/dist/commands/uninstall.d.ts.map +0 -1
  588. package/dist/commands/uninstall.js.map +0 -1
  589. package/dist/commands/update.d.ts.map +0 -1
  590. package/dist/commands/update.js.map +0 -1
  591. package/dist/core/codegraph.d.ts +0 -4
  592. package/dist/core/codegraph.d.ts.map +0 -1
  593. package/dist/core/codegraph.js +0 -63
  594. package/dist/core/codegraph.js.map +0 -1
  595. package/dist/core/command-error.d.ts.map +0 -1
  596. package/dist/core/command-error.js.map +0 -1
  597. package/dist/core/detect.d.ts.map +0 -1
  598. package/dist/core/detect.js.map +0 -1
  599. package/dist/core/openspec.d.ts +0 -11
  600. package/dist/core/openspec.d.ts.map +0 -1
  601. package/dist/core/openspec.js.map +0 -1
  602. package/dist/core/platforms.d.ts.map +0 -1
  603. package/dist/core/platforms.js.map +0 -1
  604. package/dist/core/skills.d.ts +0 -58
  605. package/dist/core/skills.d.ts.map +0 -1
  606. package/dist/core/skills.js.map +0 -1
  607. package/dist/core/superpowers.d.ts +0 -13
  608. package/dist/core/superpowers.d.ts.map +0 -1
  609. package/dist/core/superpowers.js.map +0 -1
  610. package/dist/core/types.d.ts +0 -2
  611. package/dist/core/types.d.ts.map +0 -1
  612. package/dist/core/uninstall.d.ts.map +0 -1
  613. package/dist/core/uninstall.js.map +0 -1
  614. package/dist/core/version.d.ts.map +0 -1
  615. package/dist/core/version.js.map +0 -1
  616. package/dist/utils/file-system.d.ts.map +0 -1
  617. package/dist/utils/file-system.js.map +0 -1
  618. /package/dist/{cli → app/cli}/index.d.ts +0 -0
  619. /package/dist/{commands → app/commands}/status.d.ts +0 -0
  620. /package/dist/{core → domains/bundle}/types.js +0 -0
  621. /package/dist/{utils → platform/fs}/file-system.d.ts +0 -0
  622. /package/dist/{utils → platform/fs}/file-system.js +0 -0
  623. /package/dist/{core → platform/install}/platforms.d.ts +0 -0
  624. /package/dist/{core → platform/process}/command-error.d.ts +0 -0
  625. /package/dist/{core → platform/process}/command-error.js +0 -0
  626. /package/dist/{core → platform/version}/version.d.ts +0 -0
  627. /package/scripts/{postinstall.js → install/postinstall.js} +0 -0
@@ -0,0 +1,833 @@
1
+ import { spawnSync } from 'child_process';
2
+ import { createHash } from 'crypto';
3
+ import { existsSync, promises as fs, readFileSync } from 'fs';
4
+ import path from 'path';
5
+ import { parseDocument } from 'yaml';
6
+ import { inspectClassicChange } from './classic-diagnostics.js';
7
+ import { openSpecChangeNameError, resolveClassicChangeDirectory } from './classic-paths.js';
8
+ import { ensureClassicRuntimeRun, transitionClassicRuntimeRun } from './classic-runtime-run.js';
9
+ import { appendClassicStateEvent } from './classic-state-events.js';
10
+ import { CLASSIC_GUARD_TRANSITION_EVENT, applyClassicTransition } from './classic-transitions.js';
11
+ import { classicValidateCommand } from './classic-validate-command.js';
12
+ const GREEN = '\u001b[32m';
13
+ const RED = '\u001b[31m';
14
+ const YELLOW = '\u001b[33m';
15
+ const RESET = '\u001b[0m';
16
+ const PHASES = ['open', 'design', 'build', 'verify', 'archive'];
17
+ const PHASE_HEADER = {
18
+ open: '=== Guard: open → next ===',
19
+ design: '=== Guard: design → build ===',
20
+ build: '=== Guard: build → verify ===',
21
+ verify: '=== Guard: verify → archive ===',
22
+ archive: '=== Guard: archive completeness ===',
23
+ };
24
+ const APPLY_MESSAGE = {
25
+ open: ' [APPLY] .comet.yaml updated: phase=PLACEHOLDER',
26
+ design: ' [APPLY] .comet.yaml updated: phase=build',
27
+ build: ' [APPLY] .comet.yaml updated: phase=verify, verify_result=pending',
28
+ verify: ' [APPLY] .comet.yaml updated: phase=archive, verify_result=pass',
29
+ };
30
+ const CLASSIC_FIELD_WIRE_NAMES = {
31
+ branchStatus: 'branch_status',
32
+ phase: 'phase',
33
+ verificationReport: 'verification_report',
34
+ verifiedAt: 'verified_at',
35
+ verifyResult: 'verify_result',
36
+ };
37
+ function green(message) {
38
+ return `${GREEN}${message}${RESET}`;
39
+ }
40
+ function red(message) {
41
+ return `${RED}${message}${RESET}`;
42
+ }
43
+ function yellow(message) {
44
+ return `${YELLOW}${message}${RESET}`;
45
+ }
46
+ function wireField(field) {
47
+ return CLASSIC_FIELD_WIRE_NAMES[field] ?? String(field);
48
+ }
49
+ function wireValue(value) {
50
+ if (value === null)
51
+ return 'null';
52
+ if (value === undefined)
53
+ return '';
54
+ if (typeof value === 'object')
55
+ return JSON.stringify(value);
56
+ return String(value);
57
+ }
58
+ class GuardFailure extends Error {
59
+ exitCode;
60
+ constructor(message, exitCode = 1) {
61
+ super(message);
62
+ this.exitCode = exitCode;
63
+ }
64
+ }
65
+ class GuardOutput {
66
+ stderr = [];
67
+ diagnostics;
68
+ toResult(exitCode = 0) {
69
+ return {
70
+ exitCode,
71
+ ...(this.diagnostics
72
+ ? { stdout: JSON.stringify({ diagnostics: this.diagnostics }) + '\n' }
73
+ : {}),
74
+ ...(this.stderr.length > 0 ? { stderr: this.stderr.join('\n') + '\n' } : {}),
75
+ };
76
+ }
77
+ }
78
+ async function exists(file) {
79
+ try {
80
+ await fs.access(file);
81
+ return true;
82
+ }
83
+ catch (error) {
84
+ if (error.code === 'ENOENT')
85
+ return false;
86
+ throw error;
87
+ }
88
+ }
89
+ async function nonempty(file) {
90
+ try {
91
+ return (await fs.stat(file)).size > 0;
92
+ }
93
+ catch (error) {
94
+ if (error.code === 'ENOENT')
95
+ return false;
96
+ throw error;
97
+ }
98
+ }
99
+ function validateChangeName(name) {
100
+ const error = openSpecChangeNameError(name);
101
+ if (error)
102
+ throw new GuardFailure(red(`ERROR: ${error}`));
103
+ }
104
+ // Resolve the change directory the way the frozen guard does: prefer the active
105
+ // `openspec/changes/<name>` path, fall back to the archive copy. Returns the
106
+ // RELATIVE path (cwd is the project root) so handoff-hash inputs and check
107
+ // output match the frozen `openspec/changes/...` form byte-for-byte.
108
+ async function resolveChangeDir(name) {
109
+ return (await resolveClassicChangeDirectory(name)).label;
110
+ }
111
+ function stripInlineComment(value) {
112
+ let out = '';
113
+ let quote = '';
114
+ for (let i = 0; i < value.length; i += 1) {
115
+ const c = value[i];
116
+ if (quote === '') {
117
+ if (c === '"' || c === "'") {
118
+ quote = c;
119
+ }
120
+ else if (c === '#' && (i === 0 || /\s/u.test(value[i - 1]))) {
121
+ return out.replace(/\s+$/u, '');
122
+ }
123
+ }
124
+ else if (c === quote) {
125
+ quote = '';
126
+ }
127
+ out += c;
128
+ }
129
+ return out;
130
+ }
131
+ function stripWrappingQuotes(value) {
132
+ if (value.length >= 2 && value.startsWith('"') && value.endsWith('"'))
133
+ return value.slice(1, -1);
134
+ if (value.length >= 2 && value.startsWith("'") && value.endsWith("'"))
135
+ return value.slice(1, -1);
136
+ return value;
137
+ }
138
+ async function readField(changeDir, field) {
139
+ const file = path.join(changeDir, '.comet.yaml');
140
+ const document = parseDocument(await fs.readFile(file, 'utf8'), { uniqueKeys: false });
141
+ if (document.errors.length > 0) {
142
+ throw new GuardFailure(`ERROR: Invalid .comet.yaml: ${document.errors[0].message}`);
143
+ }
144
+ const record = document.toJS();
145
+ const value = record[field];
146
+ if (value === null || value === undefined)
147
+ return '';
148
+ if (typeof value === 'object')
149
+ return JSON.stringify(value);
150
+ return String(value);
151
+ }
152
+ async function projectConfigValue(field, changeDir) {
153
+ const changeValue = await readField(changeDir, field);
154
+ if (changeValue && changeValue !== 'null')
155
+ return changeValue;
156
+ for (const config of [
157
+ '.comet/config.yaml',
158
+ '.comet.yaml',
159
+ 'comet.yaml',
160
+ '.comet.yml',
161
+ 'comet.yml',
162
+ ]) {
163
+ if (!(await exists(config)))
164
+ continue;
165
+ for (const line of (await fs.readFile(config, 'utf8')).split(/\r?\n/u)) {
166
+ if (new RegExp(`^${field}:`, 'u').test(line)) {
167
+ const value = stripWrappingQuotes(stripInlineComment(line.replace(new RegExp(`^${field}:\\s*`, 'u'), '')));
168
+ if (value && value !== 'null')
169
+ return value;
170
+ }
171
+ }
172
+ }
173
+ return '';
174
+ }
175
+ async function configuredLanguage(changeDir) {
176
+ const language = await projectConfigValue('language', changeDir);
177
+ if (!language)
178
+ return 'en';
179
+ if (language === 'en' || language === 'zh-CN')
180
+ return language;
181
+ throw new Error(`configured language '${language}' is invalid; expected en or zh-CN.`);
182
+ }
183
+ function stripFencedCodeBlocks(source) {
184
+ const kept = [];
185
+ let inFence = false;
186
+ for (const line of source.split(/\r?\n/u)) {
187
+ if (/^\s*```/u.test(line)) {
188
+ inFence = !inFence;
189
+ continue;
190
+ }
191
+ if (!inFence)
192
+ kept.push(line);
193
+ }
194
+ return kept.join('\n');
195
+ }
196
+ function countCjkChars(source) {
197
+ return source.match(/[\u4e00-\u9fff]/gu)?.length ?? 0;
198
+ }
199
+ function countEnglishWords(source) {
200
+ return source.match(/[A-Za-z][A-Za-z0-9_-]{2,}/gu)?.length ?? 0;
201
+ }
202
+ async function documentLanguageMatchesConfigured(changeDir, file) {
203
+ const language = await configuredLanguage(changeDir);
204
+ const source = stripFencedCodeBlocks(await fs.readFile(file, 'utf8'));
205
+ const cjk = countCjkChars(source);
206
+ const englishWords = countEnglishWords(source);
207
+ if (language === 'zh-CN' && cjk < 20 && englishWords >= 20) {
208
+ return fail(`configured language is zh-CN, but ${file} appears to be English-dominant (cjk_chars=${cjk}, english_words=${englishWords}).\nNext: regenerate or rewrite this artifact in Chinese while preserving necessary technical terms.`);
209
+ }
210
+ if (language === 'en' && cjk > 20 && cjk > englishWords) {
211
+ return fail(`configured language is en, but ${file} appears to be Chinese-dominant (cjk_chars=${cjk}, english_words=${englishWords}).\nNext: regenerate or rewrite this artifact in English while preserving necessary technical terms.`);
212
+ }
213
+ return pass();
214
+ }
215
+ // Build/verify commands run through the platform's default shell (cmd.exe on
216
+ // Windows, /bin/sh elsewhere) via `shell: true`, so Comet no longer requires a
217
+ // usable bash. Configured commands are pre-validated to reject shell
218
+ // metacharacters before they ever reach the shell.
219
+ function runCommandString(command) {
220
+ if (!command)
221
+ return { status: 1, output: red('ERROR: build/verify command is empty') };
222
+ const split = splitCommandChain(command);
223
+ if (typeof split === 'string') {
224
+ return {
225
+ status: 1,
226
+ output: `${red(`ERROR: build/verify command contains shell metacharacters: ${command}`)}\n${red(split)}`,
227
+ };
228
+ }
229
+ const output = [];
230
+ for (const part of split) {
231
+ const segment = part.trim();
232
+ if (!segment) {
233
+ return { status: 1, output: red('ERROR: build/verify command contains an empty && step') };
234
+ }
235
+ const result = spawnSync(segment, { shell: true, encoding: 'utf8', timeout: 300_000 });
236
+ const combined = `${result.stdout ?? ''}${result.stderr ?? ''}`.replace(/\n+$/u, '');
237
+ output.push(`${red(`+ ${segment}`)}${combined ? `\n${combined}` : ''}`);
238
+ if (result.status !== 0) {
239
+ return { status: result.status ?? 1, output: output.join('\n') };
240
+ }
241
+ }
242
+ return { status: 0, output: output.join('\n') };
243
+ }
244
+ function splitCommandChain(command) {
245
+ const parts = [];
246
+ let current = '';
247
+ let quote = '';
248
+ for (let i = 0; i < command.length; i += 1) {
249
+ const c = command[i];
250
+ if (c === '$' || c === '`') {
251
+ return 'Allowed: command words, quotes, paths, and && between sequential commands';
252
+ }
253
+ if (quote) {
254
+ current += c;
255
+ if (c === quote)
256
+ quote = '';
257
+ continue;
258
+ }
259
+ if (c === '"' || c === "'") {
260
+ quote = c;
261
+ current += c;
262
+ continue;
263
+ }
264
+ if (c === '&' && command[i + 1] === '&') {
265
+ parts.push(current);
266
+ current = '';
267
+ i += 1;
268
+ continue;
269
+ }
270
+ if (c === ';' || c === '|' || c === '&') {
271
+ return 'Allowed: command words, quotes, paths, and && between sequential commands';
272
+ }
273
+ current += c;
274
+ }
275
+ if (quote)
276
+ return 'Command has an unmatched quote';
277
+ parts.push(current);
278
+ return parts;
279
+ }
280
+ function hashFile(file) {
281
+ return createHash('sha256').update(readFileSync(file)).digest('hex');
282
+ }
283
+ async function handoffSourceFiles(changeDir) {
284
+ // Use forward-slash concatenation (not path.join, which uses the OS separator)
285
+ // so the handoff-hash input and markdown `Source:` references match the frozen
286
+ // shell + comet-handoff provenance byte-for-byte. changeDir is a relative forward-slash
287
+ // path (openspec/changes/<name>); forward slashes are readable on Windows too.
288
+ const files = [`${changeDir}/proposal.md`, `${changeDir}/design.md`, `${changeDir}/tasks.md`];
289
+ const specs = `${changeDir}/specs`;
290
+ if (await exists(specs)) {
291
+ for (const entry of (await fs.readdir(specs)).sort()) {
292
+ const spec = `${specs}/${entry}/spec.md`;
293
+ if (await exists(spec))
294
+ files.push(spec);
295
+ }
296
+ }
297
+ return files;
298
+ }
299
+ async function computeHandoffHash(changeDir) {
300
+ const lines = [];
301
+ for (const file of await handoffSourceFiles(changeDir)) {
302
+ if (await exists(file)) {
303
+ lines.push(`path:${file}`, `sha256:${hashFile(file)}`);
304
+ }
305
+ }
306
+ // Match the frozen shell: command substitution $(...) strips the trailing
307
+ // newline, so the hashed payload ends with the last sha256 line (no trailing \n).
308
+ return createHash('sha256').update(lines.join('\n')).digest('hex');
309
+ }
310
+ async function preflight(changeDir, name) {
311
+ if (!(await exists(changeDir))) {
312
+ throw new GuardFailure(red(`FATAL: change directory not found: ${changeDir}`));
313
+ }
314
+ if (!(await exists(path.join(changeDir, '.comet.yaml')))) {
315
+ throw new GuardFailure(red(`FATAL: .comet.yaml not found in ${changeDir}`));
316
+ }
317
+ const result = await classicValidateCommand([name], { json: false });
318
+ if (result.exitCode !== 0) {
319
+ if (result.stderr)
320
+ process.stderr.write(result.stderr.endsWith('\n') ? result.stderr : `${result.stderr}\n`);
321
+ throw new GuardFailure(red('FATAL: .comet.yaml schema validation failed'));
322
+ }
323
+ }
324
+ function pushCheck(output, outcome) {
325
+ if (outcome.passed) {
326
+ output.stderr.push(green(` [PASS] ${outcome.description}`));
327
+ }
328
+ else {
329
+ output.stderr.push(red(` [FAIL] ${outcome.description}`));
330
+ if (outcome.detail) {
331
+ for (const line of outcome.detail.split('\n'))
332
+ output.stderr.push(red(` ${line}`));
333
+ }
334
+ }
335
+ }
336
+ function check(description, run) {
337
+ return async () => {
338
+ try {
339
+ const result = await run();
340
+ return {
341
+ description,
342
+ passed: result.passed,
343
+ detail: ('detail' in result ? result.detail : '') ?? '',
344
+ };
345
+ }
346
+ catch (error) {
347
+ return {
348
+ description,
349
+ passed: false,
350
+ detail: error instanceof Error ? error.message : String(error),
351
+ };
352
+ }
353
+ };
354
+ }
355
+ function pass() {
356
+ return { passed: true };
357
+ }
358
+ function fail(detail) {
359
+ return { passed: false, detail };
360
+ }
361
+ async function runChecks(output, builders) {
362
+ let blocked = false;
363
+ for (const build of builders) {
364
+ const outcome = await build();
365
+ pushCheck(output, outcome);
366
+ if (!outcome.passed)
367
+ blocked = true;
368
+ }
369
+ return blocked;
370
+ }
371
+ function runInferred(command) {
372
+ // Inferred build/verify commands (npm run build, mvn, cargo, …) run through
373
+ // the platform's default shell so .cmd shims resolve on Windows without
374
+ // requiring bash. Output is returned raw (no `+ ` prefix).
375
+ const result = spawnSync(command, { shell: true, encoding: 'utf8', timeout: 300_000 });
376
+ return {
377
+ status: result.status ?? 1,
378
+ output: `${result.stdout ?? ''}${result.stderr ?? ''}`.replace(/\n+$/u, ''),
379
+ };
380
+ }
381
+ async function buildPasses(changeDir) {
382
+ if (process.env.COMET_SKIP_BUILD === '1')
383
+ return { status: 0, output: '' };
384
+ const configured = await projectConfigValue('build_command', changeDir);
385
+ if (configured)
386
+ return runCommandString(configured);
387
+ if ((await exists('package.json')) &&
388
+ /"build"/u.test(await fs.readFile('package.json', 'utf8'))) {
389
+ return runInferred('npm run build');
390
+ }
391
+ if (await exists('pom.xml')) {
392
+ if (process.platform === 'win32') {
393
+ if (existsSync('mvnw.cmd'))
394
+ return runInferred('mvnw.cmd compile -q');
395
+ return runInferred('mvn.cmd compile -q');
396
+ }
397
+ if (existsSync('mvnw'))
398
+ return runInferred('./mvnw compile -q');
399
+ return runInferred('mvn compile -q');
400
+ }
401
+ if (await exists('Cargo.toml'))
402
+ return runInferred('cargo build');
403
+ return { status: 1, output: '' };
404
+ }
405
+ async function verificationCommandPasses(changeDir) {
406
+ if (process.env.COMET_SKIP_BUILD === '1')
407
+ return { status: 0, output: '' };
408
+ const configured = await projectConfigValue('verify_command', changeDir);
409
+ if (configured)
410
+ return runCommandString(configured);
411
+ return buildPasses(changeDir);
412
+ }
413
+ async function tasksAllDone(changeDir) {
414
+ const tasks = path.join(changeDir, 'tasks.md');
415
+ if (!(await exists(tasks))) {
416
+ return fail(`tasks.md is missing at ${tasks}\nNext: restore or create tasks.md for this change before leaving build.`);
417
+ }
418
+ const source = await fs.readFile(tasks, 'utf8');
419
+ if (!/- \[x\]/u.test(source)) {
420
+ return fail("tasks.md has no completed tasks.\nNext: complete implementation tasks and mark them with '- [x]'.");
421
+ }
422
+ const unfinished = source
423
+ .split(/\r?\n/u)
424
+ .map((line, index) => ({ line, number: index + 1 }))
425
+ .filter((entry) => /^- \[ \]/u.test(entry.line));
426
+ if (unfinished.length > 0) {
427
+ return fail(`Unfinished tasks:\n${unfinished.map((entry) => `${entry.number}:${entry.line}`).join('\n')}\nNext: complete or explicitly remove unfinished tasks, then mark tasks.md with '- [x]'.`);
428
+ }
429
+ return pass();
430
+ }
431
+ async function tasksHasAny(changeDir) {
432
+ const tasks = path.join(changeDir, 'tasks.md');
433
+ if (!(await exists(tasks)))
434
+ return false;
435
+ return /- \[/u.test(await fs.readFile(tasks, 'utf8'));
436
+ }
437
+ async function planTasksAllDone(changeDir) {
438
+ const plan = await readField(changeDir, 'plan');
439
+ if (!plan || plan === 'null')
440
+ return pass();
441
+ if (!(await exists(plan))) {
442
+ return fail(`plan file is missing at ${plan}\nNext: restore the Superpowers plan file or update .comet.yaml plan before leaving build.`);
443
+ }
444
+ const source = await fs.readFile(plan, 'utf8');
445
+ const unfinished = source
446
+ .split(/\r?\n/u)
447
+ .map((line, index) => ({ line, number: index + 1 }))
448
+ .filter((entry) => /^\s*- \[ \]/u.test(entry.line));
449
+ if (unfinished.length > 0) {
450
+ return fail(`Unfinished Superpowers plan tasks:\n${unfinished.map((entry) => `${entry.number}:${entry.line}`).join('\n')}\nNext: check off corresponding completed plan tasks, then commit the plan update.`);
451
+ }
452
+ return pass();
453
+ }
454
+ async function isolationSelected(changeDir, change) {
455
+ const isolation = await readField(changeDir, 'isolation');
456
+ if (isolation === 'branch' || isolation === 'worktree')
457
+ return pass();
458
+ return fail(`isolation must be branch or worktree, got '${isolation || 'null'}'\nNext: ask the user to choose branch or worktree, create the chosen isolation, then run:\n node "$COMET_STATE" set ${change} isolation <branch|worktree>`);
459
+ }
460
+ async function buildModeSelected(changeDir, change) {
461
+ const buildMode = await readField(changeDir, 'build_mode');
462
+ if (['subagent-driven-development', 'executing-plans', 'direct'].includes(buildMode))
463
+ return pass();
464
+ return fail(`build_mode must be selected before leaving build, got '${buildMode || 'null'}'\nNext: ask the user to choose an execution mode, then run:\n node "$COMET_STATE" set ${change} build_mode <subagent-driven-development|executing-plans>`);
465
+ }
466
+ async function buildModeAllowedForWorkflow(changeDir) {
467
+ const workflow = await readField(changeDir, 'workflow');
468
+ const buildMode = await readField(changeDir, 'build_mode');
469
+ const directOverride = await readField(changeDir, 'direct_override');
470
+ if (buildMode !== 'direct')
471
+ return pass();
472
+ if (workflow === 'hotfix' || workflow === 'tweak')
473
+ return pass();
474
+ if (directOverride === 'true')
475
+ return pass();
476
+ return fail('build_mode=direct is only allowed for hotfix/tweak unless direct_override: true is recorded\nNext: choose executing-plans or subagent-driven-development, or stop and ask the user for an explicit direct override.');
477
+ }
478
+ async function subagentDispatchConfirmed(changeDir, change) {
479
+ const buildMode = await readField(changeDir, 'build_mode');
480
+ const subagentDispatch = await readField(changeDir, 'subagent_dispatch');
481
+ if (buildMode !== 'subagent-driven-development')
482
+ return pass();
483
+ if (subagentDispatch === 'confirmed')
484
+ return pass();
485
+ return fail(`subagent_dispatch must be confirmed before using build_mode=subagent-driven-development\nNext: confirm the current platform has a real background subagent/Task/multi-agent dispatcher, then run:\n node "$COMET_STATE" set ${change} subagent_dispatch confirmed\nOr ask the user to switch to executing-plans and run:\n node "$COMET_STATE" set ${change} build_mode executing-plans`);
486
+ }
487
+ async function tddModeSelected(changeDir, change) {
488
+ const workflow = await readField(changeDir, 'workflow');
489
+ if (workflow === 'hotfix' || workflow === 'tweak')
490
+ return pass();
491
+ const tddMode = await readField(changeDir, 'tdd_mode');
492
+ if (tddMode === 'tdd' || tddMode === 'direct')
493
+ return pass();
494
+ return fail(`tdd_mode must be tdd or direct for full workflow, got '${tddMode || 'null'}'\nNext: ask the user to choose TDD enforcement level, then run:\n node "$COMET_STATE" set ${change} tdd_mode <tdd|direct>`);
495
+ }
496
+ async function reviewModeSelected(changeDir, change) {
497
+ const workflow = await readField(changeDir, 'workflow');
498
+ if (workflow === 'hotfix' || workflow === 'tweak')
499
+ return pass();
500
+ const reviewMode = await readField(changeDir, 'review_mode');
501
+ if (reviewMode === 'off' || reviewMode === 'standard' || reviewMode === 'thorough') {
502
+ return pass();
503
+ }
504
+ return fail(`review_mode must be off, standard, or thorough before leaving build, got '${reviewMode || 'null'}'\nNext: ask the user to choose review strength, then run:\n node "$COMET_STATE" set ${change} review_mode <off|standard|thorough>`);
505
+ }
506
+ async function verificationReportExists(changeDir) {
507
+ const report = await readField(changeDir, 'verification_report');
508
+ return Boolean(report) && report !== 'null' && existsSync(report);
509
+ }
510
+ async function branchStatusHandled(changeDir) {
511
+ return (await readField(changeDir, 'branch_status')) === 'handled';
512
+ }
513
+ async function archivedIsTrue(changeDir) {
514
+ return (await readField(changeDir, 'archived')) === 'true';
515
+ }
516
+ async function designDocFrontmatterHas(designDoc, field, expected) {
517
+ const source = (await fs.readFile(designDoc, 'utf8')).replace(/^\uFEFF/u, '');
518
+ let inFrontmatter = false;
519
+ for (const line of source.split(/\r?\n/u)) {
520
+ if (!inFrontmatter) {
521
+ if (line === '---')
522
+ inFrontmatter = true;
523
+ continue;
524
+ }
525
+ if (line === '---')
526
+ break;
527
+ if (new RegExp(`^${field}: ['"]?${expected}['"]?\\s*$`, 'u').test(line))
528
+ return true;
529
+ }
530
+ return false;
531
+ }
532
+ async function designDocRecorded(changeDir, change) {
533
+ const designDoc = await readField(changeDir, 'design_doc');
534
+ if (designDoc && designDoc !== 'null' && existsSync(designDoc))
535
+ return pass();
536
+ return fail(`design_doc must point to an existing Superpowers Design Doc for full workflow before leaving design.\nNext: create the Design Doc and run: node "$COMET_STATE" set ${change} design_doc <path>`);
537
+ }
538
+ async function designHandoffContextValid(changeDir, change) {
539
+ const context = await readField(changeDir, 'handoff_context');
540
+ const recordedHash = await readField(changeDir, 'handoff_hash');
541
+ if (!context || context === 'null') {
542
+ return fail(`handoff_context is missing from .comet.yaml\nNext: run node "$COMET_HANDOFF" ${change} design --write before invoking Superpowers.`);
543
+ }
544
+ if (!(await nonempty(context))) {
545
+ return fail(`handoff_context does not point to a non-empty file: ${context}\nNext: regenerate the design handoff with comet-handoff.mjs.`);
546
+ }
547
+ if (!/^[a-f0-9]{64}$/u.test(recordedHash)) {
548
+ return fail(`handoff_hash is missing or invalid: ${recordedHash || 'null'}\nNext: regenerate the design handoff with comet-handoff.mjs.`);
549
+ }
550
+ const actualHash = await computeHandoffHash(changeDir);
551
+ if (actualHash !== recordedHash) {
552
+ return fail(`OpenSpec artifacts changed after handoff was generated.\nExpected handoff_hash: ${recordedHash}\nActual handoff_hash: ${actualHash}\nNext: rerun comet-handoff.mjs so Superpowers receives the current OpenSpec context.`);
553
+ }
554
+ const markdown = `${context.replace(/\.json$/u, '')}.md`;
555
+ if (!(await nonempty(markdown))) {
556
+ return fail(`design handoff markdown is missing or empty: ${markdown}\nNext: regenerate the design handoff with comet-handoff.mjs.`);
557
+ }
558
+ return pass();
559
+ }
560
+ async function designHandoffMarkdownTraceable(changeDir) {
561
+ const context = await readField(changeDir, 'handoff_context');
562
+ if (!context || context === 'null')
563
+ return fail('handoff_context is missing from .comet.yaml');
564
+ const markdown = `${context.replace(/\.json$/u, '')}.md`;
565
+ if (!(await nonempty(markdown)))
566
+ return fail(`design handoff markdown is missing or empty: ${markdown}`);
567
+ const source = await fs.readFile(markdown, 'utf8');
568
+ const problems = [];
569
+ if (!/^Generated-by: comet-handoff\.sh$/mu.test(source)) {
570
+ problems.push('handoff markdown is missing Generated-by marker');
571
+ }
572
+ if (!/^- Mode: (compact|full|beta)$/mu.test(source)) {
573
+ problems.push('handoff markdown is missing Mode marker');
574
+ }
575
+ for (const file of await handoffSourceFiles(changeDir)) {
576
+ if (!(await exists(file)))
577
+ continue;
578
+ if (!new RegExp(`^- Source: ${file}$`, 'mu').test(source)) {
579
+ problems.push(`handoff markdown is missing source reference: ${file}`);
580
+ }
581
+ if (!new RegExp(`^- SHA256: ${hashFile(file)}$`, 'mu').test(source)) {
582
+ problems.push(`handoff markdown is missing current sha256 for: ${file}`);
583
+ }
584
+ }
585
+ return problems.length === 0 ? pass() : fail(problems.join('\n'));
586
+ }
587
+ async function contextCompressionMode(changeDir) {
588
+ return (await readField(changeDir, 'context_compression')) || 'off';
589
+ }
590
+ async function betaSpecJsonStructurallyValid(changeDir) {
591
+ if ((await contextCompressionMode(changeDir)) !== 'beta')
592
+ return pass();
593
+ const context = await readField(changeDir, 'handoff_context');
594
+ if (!context || context === 'null')
595
+ return fail('handoff_context is missing from .comet.yaml');
596
+ if (!(await nonempty(context)))
597
+ return fail(`spec-context.json is missing or empty: ${context}`);
598
+ const source = await fs.readFile(context, 'utf8');
599
+ const problems = [];
600
+ let parsed;
601
+ try {
602
+ parsed = JSON.parse(source);
603
+ }
604
+ catch (error) {
605
+ return fail(`spec-context.json invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
606
+ }
607
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
608
+ return fail('spec-context.json root must be an object');
609
+ }
610
+ const record = parsed;
611
+ if (typeof record.change !== 'string')
612
+ problems.push("spec-context.json missing 'change' field");
613
+ if (typeof record.phase !== 'string')
614
+ problems.push("spec-context.json missing 'phase' field");
615
+ if (record.mode !== 'beta')
616
+ problems.push('spec-context.json mode is not beta');
617
+ if (typeof record.context_hash !== 'string') {
618
+ problems.push("spec-context.json missing 'context_hash' field");
619
+ }
620
+ if (!Array.isArray(record.files))
621
+ problems.push("spec-context.json missing 'files' field");
622
+ const files = Array.isArray(record.files)
623
+ ? record.files.filter((file) => Boolean(file) && typeof file === 'object' && !Array.isArray(file))
624
+ : [];
625
+ for (const file of await handoffSourceFiles(changeDir)) {
626
+ if (!(await exists(file)))
627
+ continue;
628
+ if (!files.some((entry) => entry.path === file && typeof entry.sha256 === 'string')) {
629
+ problems.push(`spec-context.json missing source file reference: ${file}`);
630
+ }
631
+ }
632
+ return problems.length === 0 ? pass() : fail(problems.join('\n'));
633
+ }
634
+ async function guardOpenChecks(output, changeDir) {
635
+ const workflow = await readField(changeDir, 'workflow');
636
+ const checks = [
637
+ check('proposal.md exists and non-empty', async () => (await nonempty(path.join(changeDir, 'proposal.md'))) ? pass() : fail('')),
638
+ check('proposal.md matches configured language', () => documentLanguageMatchesConfigured(changeDir, path.join(changeDir, 'proposal.md'))),
639
+ check('tasks.md exists and non-empty', async () => (await nonempty(path.join(changeDir, 'tasks.md'))) ? pass() : fail('')),
640
+ check('tasks.md matches configured language', () => documentLanguageMatchesConfigured(changeDir, path.join(changeDir, 'tasks.md'))),
641
+ check('tasks.md has at least one task', async () => (await tasksHasAny(changeDir)) ? pass() : fail('')),
642
+ ];
643
+ if (workflow === 'full') {
644
+ checks.splice(1, 0, check('design.md exists and non-empty', async () => (await nonempty(path.join(changeDir, 'design.md'))) ? pass() : fail('')), check('design.md matches configured language', () => documentLanguageMatchesConfigured(changeDir, path.join(changeDir, 'design.md'))));
645
+ }
646
+ return runChecks(output, checks);
647
+ }
648
+ async function guardDesignChecks(output, changeDir, change) {
649
+ const designDoc = await readField(changeDir, 'design_doc');
650
+ const workflow = await readField(changeDir, 'workflow');
651
+ const builders = [
652
+ check('proposal.md exists', async () => (await nonempty(path.join(changeDir, 'proposal.md'))) ? pass() : fail('')),
653
+ check('proposal.md matches configured language', () => documentLanguageMatchesConfigured(changeDir, path.join(changeDir, 'proposal.md'))),
654
+ check('design.md exists', async () => (await nonempty(path.join(changeDir, 'design.md'))) ? pass() : fail('')),
655
+ check('design.md matches configured language', () => documentLanguageMatchesConfigured(changeDir, path.join(changeDir, 'design.md'))),
656
+ check('tasks.md exists', async () => (await nonempty(path.join(changeDir, 'tasks.md'))) ? pass() : fail('')),
657
+ check('tasks.md matches configured language', () => documentLanguageMatchesConfigured(changeDir, path.join(changeDir, 'tasks.md'))),
658
+ check('design handoff context exists', () => designHandoffContextValid(changeDir, change)),
659
+ check('design handoff markdown is traceable', () => designHandoffMarkdownTraceable(changeDir)),
660
+ ];
661
+ if ((await contextCompressionMode(changeDir)) === 'beta') {
662
+ builders.push(check('beta spec-context.json is structurally valid', () => betaSpecJsonStructurallyValid(changeDir)));
663
+ }
664
+ if (workflow === 'full') {
665
+ builders.push(check('design_doc is recorded for full workflow', () => designDocRecorded(changeDir, change)));
666
+ }
667
+ let blocked = await runChecks(output, builders);
668
+ if (designDoc && designDoc !== 'null') {
669
+ blocked =
670
+ (await runChecks(output, [
671
+ check(`Design Doc (${designDoc}) exists`, async () => (await nonempty(designDoc)) ? pass() : fail('')),
672
+ check('Design Doc matches configured language', () => documentLanguageMatchesConfigured(changeDir, designDoc)),
673
+ check('Design Doc frontmatter links current change', async () => {
674
+ if (!(await nonempty(designDoc)))
675
+ return fail('');
676
+ return (await designDocFrontmatterHas(designDoc, 'comet_change', change))
677
+ ? pass()
678
+ : fail('');
679
+ }),
680
+ check('Design Doc declares technical design role', async () => {
681
+ if (!(await nonempty(designDoc)))
682
+ return fail('');
683
+ return (await designDocFrontmatterHas(designDoc, 'role', 'technical-design'))
684
+ ? pass()
685
+ : fail('');
686
+ }),
687
+ check('Design Doc declares OpenSpec as canonical spec', async () => {
688
+ if (!(await nonempty(designDoc)))
689
+ return fail('');
690
+ return (await designDocFrontmatterHas(designDoc, 'canonical_spec', 'openspec'))
691
+ ? pass()
692
+ : fail('');
693
+ }),
694
+ ])) || blocked;
695
+ }
696
+ else if (workflow !== 'full') {
697
+ output.stderr.push(yellow(' [WARN] No design_doc recorded in .comet.yaml (optional for hotfix/tweak)'));
698
+ }
699
+ return blocked;
700
+ }
701
+ async function guardBuildChecks(output, changeDir, change) {
702
+ return runChecks(output, [
703
+ check('isolation selected', () => isolationSelected(changeDir, change)),
704
+ check('build_mode selected', () => buildModeSelected(changeDir, change)),
705
+ check('build_mode allowed for workflow', () => buildModeAllowedForWorkflow(changeDir)),
706
+ check('subagent dispatch confirmed', () => subagentDispatchConfirmed(changeDir, change)),
707
+ check('tdd_mode selected', () => tddModeSelected(changeDir, change)),
708
+ check('review_mode selected', () => reviewModeSelected(changeDir, change)),
709
+ check('tasks.md all tasks checked', () => tasksAllDone(changeDir)),
710
+ check('Superpowers plan all tasks checked', () => planTasksAllDone(changeDir)),
711
+ check('proposal.md exists', async () => (await nonempty(path.join(changeDir, 'proposal.md'))) ? pass() : fail('')),
712
+ check('proposal.md matches configured language', () => documentLanguageMatchesConfigured(changeDir, path.join(changeDir, 'proposal.md'))),
713
+ check('Superpowers plan matches configured language', async () => {
714
+ const plan = await readField(changeDir, 'plan');
715
+ if (!plan || plan === 'null' || !(await exists(plan)))
716
+ return pass();
717
+ return documentLanguageMatchesConfigured(changeDir, plan);
718
+ }),
719
+ // Build check runs last — only after all config checks pass — to avoid
720
+ // wasting time on a build that would be rejected by a config failure.
721
+ check('Build passes', async () => {
722
+ const buildResult = await buildPasses(changeDir);
723
+ return buildResult.status === 0 ? pass() : fail(buildResult.output);
724
+ }),
725
+ ]);
726
+ }
727
+ async function guardVerifyChecks(output, changeDir) {
728
+ return runChecks(output, [
729
+ check('tasks.md all tasks checked', () => tasksAllDone(changeDir)),
730
+ // Verification command runs after tasks check — no point running tests
731
+ // if tasks.md is incomplete.
732
+ check('Verification passes', async () => {
733
+ const verifyResult = await verificationCommandPasses(changeDir);
734
+ return verifyResult.status === 0 ? pass() : fail(verifyResult.output);
735
+ }),
736
+ check('verification_report exists', async () => (await verificationReportExists(changeDir)) ? pass() : fail('')),
737
+ check('verification_report matches configured language', async () => {
738
+ const report = await readField(changeDir, 'verification_report');
739
+ if (!report || report === 'null' || !(await exists(report)))
740
+ return pass();
741
+ return documentLanguageMatchesConfigured(changeDir, report);
742
+ }),
743
+ check('branch_status=handled', async () => (await branchStatusHandled(changeDir)) ? pass() : fail('')),
744
+ ]);
745
+ }
746
+ async function guardArchiveChecks(output, changeDir) {
747
+ return runChecks(output, [
748
+ check('archived is true', async () => ((await archivedIsTrue(changeDir)) ? pass() : fail(''))),
749
+ check('proposal.md exists', async () => (await nonempty(path.join(changeDir, 'proposal.md'))) ? pass() : fail('')),
750
+ check('design.md exists', async () => (await nonempty(path.join(changeDir, 'design.md'))) ? pass() : fail('')),
751
+ check('tasks.md all tasks checked', () => tasksAllDone(changeDir)),
752
+ ]);
753
+ }
754
+ async function applyStateUpdate(output, change, changeDir, phase, context) {
755
+ const event = CLASSIC_GUARD_TRANSITION_EVENT[phase];
756
+ if (!event)
757
+ return;
758
+ const result = applyClassicTransition(context.classic, event);
759
+ await transitionClassicRuntimeRun(changeDir, result.classic, context.run, {
760
+ event,
761
+ phase,
762
+ source: 'comet-guard',
763
+ });
764
+ await appendClassicStateEvent(changeDir, {
765
+ change,
766
+ event,
767
+ source: 'comet-guard',
768
+ from: context.classic,
769
+ to: result.classic,
770
+ effects: result.effects,
771
+ });
772
+ for (const effect of result.effects) {
773
+ output.stderr.push(green(`[SET] ${wireField(effect.field)}=${wireValue(effect.to)}`));
774
+ }
775
+ output.stderr.push(green(`[TRANSITION] ${event}`));
776
+ const template = APPLY_MESSAGE[phase];
777
+ const message = phase === 'open' ? template.replace('PLACEHOLDER', result.classic.phase) : template;
778
+ output.stderr.push(green(message));
779
+ }
780
+ export const classicGuardCommand = async (args, options) => {
781
+ const output = new GuardOutput();
782
+ const [change, phase, flag] = args;
783
+ try {
784
+ validateChangeName(change);
785
+ if (!phase || !PHASES.includes(phase)) {
786
+ throw new GuardFailure(`${red(`Unknown phase: ${phase ?? ''}`)}\nValid phases: open, design, build, verify, archive`);
787
+ }
788
+ const changeDir = await resolveChangeDir(change);
789
+ await preflight(changeDir, change);
790
+ const runContext = await ensureClassicRuntimeRun(changeDir);
791
+ const diagnostic = await inspectClassicChange(changeDir, change);
792
+ if (options.json) {
793
+ output.diagnostics = {
794
+ change,
795
+ phase,
796
+ currentStep: diagnostic.currentStep,
797
+ runtimeEval: diagnostic.runtimeEval,
798
+ };
799
+ }
800
+ output.stderr.push(PHASE_HEADER[phase]);
801
+ let blocked;
802
+ if (phase === 'open')
803
+ blocked = await guardOpenChecks(output, changeDir);
804
+ else if (phase === 'design')
805
+ blocked = await guardDesignChecks(output, changeDir, change);
806
+ else if (phase === 'build')
807
+ blocked = await guardBuildChecks(output, changeDir, change);
808
+ else if (phase === 'verify')
809
+ blocked = await guardVerifyChecks(output, changeDir);
810
+ else
811
+ blocked = await guardArchiveChecks(output, changeDir);
812
+ if (blocked) {
813
+ output.stderr.push('');
814
+ output.stderr.push(red('BLOCKED — fix failing checks before proceeding to next phase'));
815
+ return output.toResult(1);
816
+ }
817
+ output.stderr.push('');
818
+ output.stderr.push(green('ALL CHECKS PASSED — ready for next phase'));
819
+ if (flag === '--apply') {
820
+ await applyStateUpdate(output, change, changeDir, phase, runContext);
821
+ }
822
+ return output.toResult(0);
823
+ }
824
+ catch (error) {
825
+ if (error instanceof GuardFailure) {
826
+ for (const line of error.message.split('\n'))
827
+ output.stderr.push(line);
828
+ return output.toResult(error.exitCode);
829
+ }
830
+ throw error;
831
+ }
832
+ };
833
+ //# sourceMappingURL=classic-guard.js.map