@xulthekl/team-flow 0.22.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 (405) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.agents/skills +1 -0
  3. package/.claude/always/phase-guard.md +3 -0
  4. package/.claude-plugin/marketplace.json +20 -0
  5. package/.claude-plugin/plugin.json +31 -0
  6. package/.codex-plugin/plugin.json +45 -0
  7. package/.codexignore +6 -0
  8. package/.cursor-plugin/marketplace.json +17 -0
  9. package/.cursor-plugin/plugin.json +31 -0
  10. package/.github/copilot-instructions.md +15 -0
  11. package/.github/dependabot.yml +10 -0
  12. package/.github/plugin/marketplace.json +42 -0
  13. package/.github/workflows/ci.yml +98 -0
  14. package/.github/workflows/hol-plugin-scanner.yml +17 -0
  15. package/.opencode/INSTALL.md +61 -0
  16. package/.opencode/plugins/team-flow.js +70 -0
  17. package/AGENTS.md +280 -0
  18. package/CHANGELOG.md +635 -0
  19. package/CONTRIBUTING.md +115 -0
  20. package/GEMINI.md +14 -0
  21. package/HANDOFF.md +219 -0
  22. package/INSTALL.md +810 -0
  23. package/LICENSE +21 -0
  24. package/README.md +185 -0
  25. package/SECURITY.md +37 -0
  26. package/agents/bug-investigator.md +180 -0
  27. package/agents/change-split-auditor.md +257 -0
  28. package/agents/code-reviewer.md +171 -0
  29. package/agents/cross-change-consistency-checker.md +215 -0
  30. package/agents/prd-completeness-reviewer.md +197 -0
  31. package/agents/prototype-builder.md +230 -0
  32. package/agents/prototype-env-scout.md +156 -0
  33. package/agents/prototype-reviewer.md +226 -0
  34. package/assets/icon.svg +6 -0
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.js +5 -0
  37. package/dist/parsing/change-parser.d.ts +12 -0
  38. package/dist/parsing/change-parser.js +54 -0
  39. package/dist/parsing/requirement-blocks.d.ts +31 -0
  40. package/dist/parsing/requirement-blocks.js +192 -0
  41. package/dist/schema/base.d.ts +7 -0
  42. package/dist/schema/base.js +1 -0
  43. package/dist/schema/change.d.ts +25 -0
  44. package/dist/schema/change.js +1 -0
  45. package/dist/schema/index.d.ts +3 -0
  46. package/dist/schema/index.js +1 -0
  47. package/dist/schema/spec.d.ts +11 -0
  48. package/dist/schema/spec.js +1 -0
  49. package/dist/validation/constants.d.ts +42 -0
  50. package/dist/validation/constants.js +42 -0
  51. package/dist/validation/tokenizer.d.ts +17 -0
  52. package/dist/validation/tokenizer.js +173 -0
  53. package/dist/validation/types.d.ts +40 -0
  54. package/dist/validation/types.js +1 -0
  55. package/dist/validation/validator.d.ts +21 -0
  56. package/dist/validation/validator.js +489 -0
  57. package/docs/README_en.md +358 -0
  58. package/docs/artifact-contract.md +96 -0
  59. package/docs/decision-points.md +88 -0
  60. package/docs/e2e-integration-design.md +207 -0
  61. package/docs/examples/README.md +25 -0
  62. package/docs/examples/add-dark-mode/README.md +13 -0
  63. package/docs/examples/add-dark-mode/design.md +49 -0
  64. package/docs/examples/add-dark-mode/execution-contract.md +56 -0
  65. package/docs/examples/add-dark-mode/proposal.md +46 -0
  66. package/docs/examples/add-dark-mode/specs/ui-theme/spec.md +35 -0
  67. package/docs/examples/add-dark-mode/tasks.md +26 -0
  68. package/docs/examples/refactor-auth-boundary/README.md +15 -0
  69. package/docs/examples/refactor-auth-boundary/design.md +41 -0
  70. package/docs/examples/refactor-auth-boundary/execution-contract.md +61 -0
  71. package/docs/examples/refactor-auth-boundary/proposal.md +47 -0
  72. package/docs/examples/refactor-auth-boundary/specs/auth-boundary/spec.md +45 -0
  73. package/docs/examples/refactor-auth-boundary/tasks.md +25 -0
  74. package/docs/plans/2026-07-07-fix-batch-design.md +68 -0
  75. package/docs/plans/2026-07-20-001-refactor-skill-collaboration-protocol-plan.md +128 -0
  76. package/docs/platform-matrix.md +45 -0
  77. package/docs/prototype-design-research.md +206 -0
  78. package/docs/release-checklist.md +96 -0
  79. package/docs/showcase.html +699 -0
  80. package/docs/skill-rename-v0.8.0.md +49 -0
  81. package/docs/state-machine.md +162 -0
  82. package/gemini-extension.json +6 -0
  83. package/hooks/hooks-cursor.json +8 -0
  84. package/hooks/hooks.json +26 -0
  85. package/hooks/pre-tool-use-guard +116 -0
  86. package/hooks/session-start +14 -0
  87. package/llms.txt +51 -0
  88. package/package.json +48 -0
  89. package/plugin.json +27 -0
  90. package/prd/v1/plan.md +443 -0
  91. package/prd/v1/prd.md +580 -0
  92. package/scripts/check-update.mjs +91 -0
  93. package/scripts/check-version-consistency.mjs +345 -0
  94. package/scripts/ensure-branch.mjs +71 -0
  95. package/scripts/get-config +31 -0
  96. package/scripts/guard/checks/artifacts-exist.mjs +36 -0
  97. package/scripts/guard/checks/contract-current.mjs +33 -0
  98. package/scripts/guard/checks/contract-fresh.mjs +17 -0
  99. package/scripts/guard/checks/dp-gate-passed.mjs +35 -0
  100. package/scripts/guard/checks/dp3-approved.mjs +22 -0
  101. package/scripts/guard/checks/execution-plan-ready.mjs +40 -0
  102. package/scripts/guard/checks/execution-reviews-passed.mjs +36 -0
  103. package/scripts/guard/checks/schema-valid.mjs +63 -0
  104. package/scripts/guard/checks/specs-merged.mjs +51 -0
  105. package/scripts/guard/checks/tasks-complete.mjs +31 -0
  106. package/scripts/guard/checks/tests-passing.mjs +31 -0
  107. package/scripts/guard/design-token-guard.mjs +237 -0
  108. package/scripts/guard/guard.mjs +205 -0
  109. package/scripts/infer-workflow.mjs +136 -0
  110. package/scripts/install-amazon-q.mjs +9 -0
  111. package/scripts/install-cline.mjs +9 -0
  112. package/scripts/install-continue.mjs +9 -0
  113. package/scripts/install-cursor.mjs +265 -0
  114. package/scripts/install-git-hooks.mjs +82 -0
  115. package/scripts/install-kiro.mjs +9 -0
  116. package/scripts/install-pi.mjs +9 -0
  117. package/scripts/install-qoder.mjs +9 -0
  118. package/scripts/install-qwen.mjs +9 -0
  119. package/scripts/install-roocode.mjs +9 -0
  120. package/scripts/install-windsurf.mjs +9 -0
  121. package/scripts/install-zcode.mjs +265 -0
  122. package/scripts/lib/cmd-audit.mjs +127 -0
  123. package/scripts/lib/cmd-checkpoint.mjs +118 -0
  124. package/scripts/lib/cmd-config.mjs +88 -0
  125. package/scripts/lib/cmd-doctor.mjs +267 -0
  126. package/scripts/lib/cmd-execution.mjs +206 -0
  127. package/scripts/lib/cmd-handoff.mjs +94 -0
  128. package/scripts/lib/cmd-inject.mjs +310 -0
  129. package/scripts/lib/cmd-install-amazon-q.mjs +11 -0
  130. package/scripts/lib/cmd-install-cline.mjs +11 -0
  131. package/scripts/lib/cmd-install-continue.mjs +11 -0
  132. package/scripts/lib/cmd-install-cursor.mjs +14 -0
  133. package/scripts/lib/cmd-install-kiro.mjs +11 -0
  134. package/scripts/lib/cmd-install-pi.mjs +11 -0
  135. package/scripts/lib/cmd-install-qoder.mjs +11 -0
  136. package/scripts/lib/cmd-install-qwen.mjs +11 -0
  137. package/scripts/lib/cmd-install-roocode.mjs +11 -0
  138. package/scripts/lib/cmd-install-windsurf.mjs +11 -0
  139. package/scripts/lib/cmd-install-workbuddy.mjs +359 -0
  140. package/scripts/lib/cmd-install-zcode.mjs +14 -0
  141. package/scripts/lib/cmd-isolate.mjs +37 -0
  142. package/scripts/lib/cmd-list.mjs +71 -0
  143. package/scripts/lib/cmd-runtime.mjs +85 -0
  144. package/scripts/lib/cmd-solutions.mjs +71 -0
  145. package/scripts/lib/cmd-state.mjs +231 -0
  146. package/scripts/lib/cmd-sync.mjs +102 -0
  147. package/scripts/lib/cmd-validate.mjs +105 -0
  148. package/scripts/lib/cmd-version.mjs +148 -0
  149. package/scripts/lib/config-loader.mjs +107 -0
  150. package/scripts/lib/execution-plan.mjs +492 -0
  151. package/scripts/lib/execution-recommendation.mjs +221 -0
  152. package/scripts/lib/hash.mjs +74 -0
  153. package/scripts/lib/install.mjs +267 -0
  154. package/scripts/lib/platform-runtime-inventory.mjs +27 -0
  155. package/scripts/lib/platforms.mjs +165 -0
  156. package/scripts/lib/prototype-sync.mjs +192 -0
  157. package/scripts/lib/sdd-overlay.mjs +262 -0
  158. package/scripts/lib/shell-quote.mjs +4 -0
  159. package/scripts/lib/solutions-capture.mjs +102 -0
  160. package/scripts/lib/solutions-index-gen.mjs +112 -0
  161. package/scripts/lib/solutions-inject.mjs +77 -0
  162. package/scripts/lib/solutions-promote.mjs +145 -0
  163. package/scripts/lib/spec-paths.mjs +85 -0
  164. package/scripts/lib/state-loader.mjs +154 -0
  165. package/scripts/lint/lint-skills.mjs +149 -0
  166. package/scripts/lint/rules/behavior-consistency.mjs +56 -0
  167. package/scripts/lint/rules/dp-trigger-points.mjs +60 -0
  168. package/scripts/lint/rules/exception-handling.mjs +59 -0
  169. package/scripts/lint/rules/no-contradictory-instructions.mjs +67 -0
  170. package/scripts/lint/rules/no-redundant-checks.mjs +50 -0
  171. package/scripts/lint/rules/token-rules.mjs +122 -0
  172. package/scripts/review-package +44 -0
  173. package/scripts/task-brief +40 -0
  174. package/scripts/team-flow.mjs +164 -0
  175. package/scripts/token-baseline.mjs +158 -0
  176. package/scripts/validate-artifacts +96 -0
  177. package/scripts/verify-marketplace-release.mjs +59 -0
  178. package/skills/architecture-design/SKILL.md +140 -0
  179. package/skills/architecture-design/chapters/ch01-4a-domains.md +27 -0
  180. package/skills/architecture-design/chapters/ch02-change-cascade.md +27 -0
  181. package/skills/architecture-design/chapters/ch03-architecture-outputs.md +25 -0
  182. package/skills/architecture-design/chapters/ch04-entity-to-aggregate.md +27 -0
  183. package/skills/architecture-design/chapters/ch05-cqrs.md +32 -0
  184. package/skills/architecture-design/chapters/ch06-integration.md +54 -0
  185. package/skills/architecture-design/cheatsheet.md +51 -0
  186. package/skills/architecture-design/glossary.md +23 -0
  187. package/skills/architecture-design/patterns.md +32 -0
  188. package/skills/bug-investigator/SKILL.md +77 -0
  189. package/skills/build-executor/SKILL.md +163 -0
  190. package/skills/build-executor/implementer-prompt.md +162 -0
  191. package/skills/build-executor/references/execution-modes.md +86 -0
  192. package/skills/build-executor/task-reviewer-prompt.md +195 -0
  193. package/skills/ce-brainstorm/SKILL.md +415 -0
  194. package/skills/ce-brainstorm/references/agents/slack-researcher.md +127 -0
  195. package/skills/ce-brainstorm/references/blindspot-pass.md +70 -0
  196. package/skills/ce-brainstorm/references/brainstorm-sections.md +285 -0
  197. package/skills/ce-brainstorm/references/handoff.md +168 -0
  198. package/skills/ce-brainstorm/references/html-rendering.md +634 -0
  199. package/skills/ce-brainstorm/references/markdown-rendering.md +241 -0
  200. package/skills/ce-brainstorm/references/model-tiers.md +9 -0
  201. package/skills/ce-brainstorm/references/prd-mapping.md +71 -0
  202. package/skills/ce-brainstorm/references/product-pressure-test.md +42 -0
  203. package/skills/ce-brainstorm/references/reasoning-elevation.md +63 -0
  204. package/skills/ce-brainstorm/references/settled-decisions.md +45 -0
  205. package/skills/ce-brainstorm/references/synthesis-summary.md +282 -0
  206. package/skills/ce-brainstorm/references/universal-brainstorming.md +73 -0
  207. package/skills/ce-brainstorm/references/verdict-routing.md +26 -0
  208. package/skills/ce-brainstorm/references/visual-probes.md +158 -0
  209. package/skills/ce-brainstorm/scripts/visual-probe-server.js +418 -0
  210. package/skills/ce-compound/SKILL.md +114 -0
  211. package/skills/ce-compound/assets/resolution-template.md +94 -0
  212. package/skills/ce-compound/references/agents/best-practices-researcher.md +115 -0
  213. package/skills/ce-compound/references/agents/data-integrity-guardian.md +68 -0
  214. package/skills/ce-compound/references/agents/framework-docs-researcher.md +93 -0
  215. package/skills/ce-compound/references/agents/pattern-recognition-specialist.md +55 -0
  216. package/skills/ce-compound/references/agents/performance-oracle.md +108 -0
  217. package/skills/ce-compound/references/agents/security-sentinel.md +91 -0
  218. package/skills/ce-compound/references/agents/session-historian.md +83 -0
  219. package/skills/ce-compound/references/concepts-vocabulary.md +78 -0
  220. package/skills/ce-compound/references/full-mode-workflow.md +413 -0
  221. package/skills/ce-compound/references/grounding-validation.md +84 -0
  222. package/skills/ce-compound/references/lightweight-mode.md +53 -0
  223. package/skills/ce-compound/references/output-standards.md +182 -0
  224. package/skills/ce-compound/references/promotion-rules.md +38 -0
  225. package/skills/ce-compound/references/schema.yaml +231 -0
  226. package/skills/ce-compound/references/three-tier-index.md +55 -0
  227. package/skills/ce-compound/references/v0.5-upgrade.md +32 -0
  228. package/skills/ce-compound/references/write-flow.md +36 -0
  229. package/skills/ce-compound/references/yaml-schema.md +118 -0
  230. package/skills/ce-compound/scripts/session-history/discover-sessions.sh +130 -0
  231. package/skills/ce-compound/scripts/session-history/extract-errors.py +254 -0
  232. package/skills/ce-compound/scripts/session-history/extract-metadata.py +456 -0
  233. package/skills/ce-compound/scripts/session-history/extract-skeleton.py +575 -0
  234. package/skills/ce-compound/scripts/validate-doc-claims.py +346 -0
  235. package/skills/ce-compound/scripts/validate-frontmatter.py +137 -0
  236. package/skills/ce-ideate/SKILL.md +402 -0
  237. package/skills/ce-ideate/references/agents/issue-intelligence-analyst.md +200 -0
  238. package/skills/ce-ideate/references/agents/learnings-researcher.md +247 -0
  239. package/skills/ce-ideate/references/agents/slack-researcher.md +127 -0
  240. package/skills/ce-ideate/references/agents/web-researcher.md +121 -0
  241. package/skills/ce-ideate/references/divergent-ideation.md +89 -0
  242. package/skills/ce-ideate/references/html-rendering.md +634 -0
  243. package/skills/ce-ideate/references/ideation-sections.md +191 -0
  244. package/skills/ce-ideate/references/markdown-rendering.md +238 -0
  245. package/skills/ce-ideate/references/post-ideation-workflow.md +167 -0
  246. package/skills/ce-ideate/references/universal-ideation.md +107 -0
  247. package/skills/ce-ideate/references/web-research-cache.md +56 -0
  248. package/skills/ce-plan/SKILL.md +137 -0
  249. package/skills/ce-plan/references/agents/agent-native-planning-strategist.md +62 -0
  250. package/skills/ce-plan/references/agents/architecture-strategist.md +46 -0
  251. package/skills/ce-plan/references/agents/best-practices-researcher.md +114 -0
  252. package/skills/ce-plan/references/agents/data-integrity-guardian.md +68 -0
  253. package/skills/ce-plan/references/agents/data-migration-reviewer.md +103 -0
  254. package/skills/ce-plan/references/agents/deployment-verification-agent.md +157 -0
  255. package/skills/ce-plan/references/agents/framework-docs-researcher.md +93 -0
  256. package/skills/ce-plan/references/agents/git-history-analyzer.md +40 -0
  257. package/skills/ce-plan/references/agents/learnings-researcher.md +247 -0
  258. package/skills/ce-plan/references/agents/pattern-recognition-specialist.md +55 -0
  259. package/skills/ce-plan/references/agents/performance-oracle.md +108 -0
  260. package/skills/ce-plan/references/agents/repo-research-analyst.md +258 -0
  261. package/skills/ce-plan/references/agents/security-sentinel.md +91 -0
  262. package/skills/ce-plan/references/agents/slack-researcher.md +127 -0
  263. package/skills/ce-plan/references/agents/spec-flow-analyzer.md +80 -0
  264. package/skills/ce-plan/references/agents/web-researcher.md +121 -0
  265. package/skills/ce-plan/references/approach-altitude.md +55 -0
  266. package/skills/ce-plan/references/change-splitting.md +65 -0
  267. package/skills/ce-plan/references/completion-contract.md +33 -0
  268. package/skills/ce-plan/references/core-principles.md +40 -0
  269. package/skills/ce-plan/references/deepening-workflow.md +263 -0
  270. package/skills/ce-plan/references/dependency-graph.md +36 -0
  271. package/skills/ce-plan/references/html-rendering.md +634 -0
  272. package/skills/ce-plan/references/intake-routing.md +189 -0
  273. package/skills/ce-plan/references/markdown-rendering.md +238 -0
  274. package/skills/ce-plan/references/plan-handoff.md +150 -0
  275. package/skills/ce-plan/references/plan-sections.md +427 -0
  276. package/skills/ce-plan/references/plan-structure.md +120 -0
  277. package/skills/ce-plan/references/planning-modes.md +69 -0
  278. package/skills/ce-plan/references/reasoning-elevation.md +63 -0
  279. package/skills/ce-plan/references/research-workflow.md +165 -0
  280. package/skills/ce-plan/references/review-and-write.md +127 -0
  281. package/skills/ce-plan/references/settled-decisions.md +45 -0
  282. package/skills/ce-plan/references/synthesis-summary.md +418 -0
  283. package/skills/ce-plan/references/universal-planning.md +168 -0
  284. package/skills/ce-proof/SKILL.md +346 -0
  285. package/skills/ce-strategy/SKILL.md +97 -0
  286. package/skills/ce-strategy/references/interview.md +143 -0
  287. package/skills/ce-strategy/references/strategy-template.md +89 -0
  288. package/skills/code-reviewer/SKILL.md +84 -0
  289. package/skills/code-reviewer/code-reviewer-prompt.md +195 -0
  290. package/skills/contract-builder/SKILL.md +72 -0
  291. package/skills/design-system/SKILL.md +75 -0
  292. package/skills/design-system/references/agents/design-system-architect.md +138 -0
  293. package/skills/design-system/references/creation-flow.md +170 -0
  294. package/skills/design-system/references/preview-template.html +319 -0
  295. package/skills/design-system/references/token-derivation.md +115 -0
  296. package/skills/design-system/references/variant-schema.md +60 -0
  297. package/skills/e2e/SKILL.md +56 -0
  298. package/skills/e2e/references/test-verifier.md +40 -0
  299. package/skills/need-explorer/SKILL.md +79 -0
  300. package/skills/prototype/SKILL.md +98 -0
  301. package/skills/prototype/references/agents/design-system-architect.md +122 -0
  302. package/skills/prototype/references/checklist.md +82 -0
  303. package/skills/prototype/references/craft/accessibility-baseline.md +71 -0
  304. package/skills/prototype/references/craft/anti-ai-slop.md +87 -0
  305. package/skills/prototype/references/craft/laws-of-ux.md +60 -0
  306. package/skills/prototype/references/craft/state-coverage.md +81 -0
  307. package/skills/prototype/references/craft/typography-hierarchy.md +50 -0
  308. package/skills/prototype/references/layouts.md +223 -0
  309. package/skills/prototype/references/orchestration-flow.md +101 -0
  310. package/skills/prototype/references/prototype-scaffold/assets/design-tokens.css +19 -0
  311. package/skills/prototype/references/prototype-scaffold/components/button.html +3 -0
  312. package/skills/prototype/references/prototype-scaffold/design-system.md +7 -0
  313. package/skills/prototype/references/prototype-scaffold/flow.md +11 -0
  314. package/skills/prototype/references/prototype-scaffold/index.html +20 -0
  315. package/skills/prototype/references/prototype-scaffold/pages/index.html +11 -0
  316. package/skills/prototype/references/template.html +396 -0
  317. package/skills/release-archivist/SKILL.md +166 -0
  318. package/skills/release-archivist/references/closing-procedures.md +81 -0
  319. package/skills/session-handoff/SKILL.md +110 -0
  320. package/skills/session-handoff/references/context-extraction.md +70 -0
  321. package/skills/session-handoff/references/handoff-template.md +90 -0
  322. package/skills/session-handoff/references/skill-recommendation.md +43 -0
  323. package/skills/spec-merger/SKILL.md +66 -0
  324. package/skills/spec-writer/SKILL.md +149 -0
  325. package/skills/workflow-bootstrap/SKILL.md +148 -0
  326. package/skills/workflow-bootstrap/references/agents/codebase-recon-analyst.md +121 -0
  327. package/skills/workflow-bootstrap/references/b1-reconnaissance.md +80 -0
  328. package/skills/workflow-bootstrap/scripts/recon-probe.sh +328 -0
  329. package/skills/workflow-feedback/SKILL.md +120 -0
  330. package/skills/workflow-feedback/references/category-guide.md +121 -0
  331. package/skills/workflow-feedback/references/feedback-template.md +73 -0
  332. package/skills/workflow-feedback/references/review-mode.md +92 -0
  333. package/skills/workflow-orchestrator/SKILL.md +94 -0
  334. package/skills/workflow-orchestrator/references/feedback-loops.md +56 -0
  335. package/skills/workflow-orchestrator/references/s1-path-router.md +81 -0
  336. package/skills/workflow-orchestrator/references/s2-prd-prototype-loop.md +96 -0
  337. package/skills/workflow-orchestrator/references/s3-plan-pipeline.md +50 -0
  338. package/skills/workflow-orchestrator/references/s4-split-validate.md +108 -0
  339. package/skills/workflow-orchestrator/references/s5-monitoring.md +61 -0
  340. package/skills/workflow-orchestrator/references/state-model.md +185 -0
  341. package/skills/workflow-start/SKILL.md +147 -0
  342. package/skills/workflow-start/references/routing-rules.md +155 -0
  343. package/src/index.ts +16 -0
  344. package/src/parsing/change-parser.ts +79 -0
  345. package/src/parsing/requirement-blocks.ts +244 -0
  346. package/src/schema/base.ts +8 -0
  347. package/src/schema/change.ts +29 -0
  348. package/src/schema/index.ts +3 -0
  349. package/src/schema/spec.ts +12 -0
  350. package/src/validation/constants.ts +53 -0
  351. package/src/validation/tokenizer.ts +180 -0
  352. package/src/validation/types.ts +47 -0
  353. package/src/validation/validator.ts +552 -0
  354. package/templates/abandonment-summary.md +29 -0
  355. package/templates/design.md +37 -0
  356. package/templates/execution-contract.md +99 -0
  357. package/templates/plan.md +86 -0
  358. package/templates/prd.md +468 -0
  359. package/templates/proposal.md +37 -0
  360. package/templates/spec.md +31 -0
  361. package/templates/tasks.md +47 -0
  362. package/tests/e2e.test.mjs +266 -0
  363. package/tests/lib/cmd-audit.test.mjs +202 -0
  364. package/tests/lib/cmd-checkpoint.test.mjs +98 -0
  365. package/tests/lib/cmd-config.test.mjs +101 -0
  366. package/tests/lib/cmd-doctor.test.mjs +450 -0
  367. package/tests/lib/cmd-execution.test.mjs +647 -0
  368. package/tests/lib/cmd-handoff.test.mjs +137 -0
  369. package/tests/lib/cmd-inject.test.mjs +218 -0
  370. package/tests/lib/cmd-install-workbuddy.test.mjs +113 -0
  371. package/tests/lib/cmd-install-zcode.test.mjs +42 -0
  372. package/tests/lib/cmd-isolate.test.mjs +68 -0
  373. package/tests/lib/cmd-list.test.mjs +127 -0
  374. package/tests/lib/cmd-runtime.test.mjs +83 -0
  375. package/tests/lib/cmd-state-missing.test.mjs +65 -0
  376. package/tests/lib/cmd-state.test.mjs +365 -0
  377. package/tests/lib/cmd-sync-paths.test.mjs +84 -0
  378. package/tests/lib/cmd-validate-paths.test.mjs +90 -0
  379. package/tests/lib/config-loader.test.mjs +175 -0
  380. package/tests/lib/ensure-branch.test.mjs +59 -0
  381. package/tests/lib/execution-control-plane.test.mjs +168 -0
  382. package/tests/lib/execution-plan.test.mjs +474 -0
  383. package/tests/lib/guard-specs-merged.test.mjs +108 -0
  384. package/tests/lib/guard-tests-passing.test.mjs +112 -0
  385. package/tests/lib/guard-transitions.test.mjs +262 -0
  386. package/tests/lib/guard.test.mjs +611 -0
  387. package/tests/lib/hash.test.mjs +138 -0
  388. package/tests/lib/infer-workflow.test.mjs +161 -0
  389. package/tests/lib/install-git-hooks.test.mjs +20 -0
  390. package/tests/lib/marketplace-release-docs.test.mjs +31 -0
  391. package/tests/lib/minimality-discipline.test.mjs +37 -0
  392. package/tests/lib/model-profiles-docs.test.mjs +33 -0
  393. package/tests/lib/node20-compatibility.test.mjs +73 -0
  394. package/tests/lib/node20-test-entry.test.mjs +17 -0
  395. package/tests/lib/platform-runtime-distribution.test.mjs +150 -0
  396. package/tests/lib/raw-mode-smoke.test.mjs +42 -0
  397. package/tests/lib/sdd-overlay.test.mjs +118 -0
  398. package/tests/lib/spec-paths.test.mjs +80 -0
  399. package/tests/lib/state-loader.test.mjs +251 -0
  400. package/tests/lib/token-baseline.test.mjs +72 -0
  401. package/tests/lib/token-rules.test.mjs +94 -0
  402. package/tests/lib/verify-marketplace-release.test.mjs +128 -0
  403. package/tests/tsconfig.json +12 -0
  404. package/token-baseline.json +95 -0
  405. package/tsconfig.json +14 -0
@@ -0,0 +1,611 @@
1
+ // tests/lib/guard.test.mjs
2
+ // Tests for scripts/guard/guard.mjs — transition matrix and workflow behavior
3
+ import { describe, it, before, after } from 'node:test';
4
+ import assert from 'node:assert/strict';
5
+ import { mkdtempSync, writeFileSync, mkdirSync, readFileSync, rmSync, symlinkSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { tmpdir } from 'node:os';
8
+ import { execFileSync } from 'node:child_process';
9
+
10
+ let tempDir;
11
+ let gitRefs;
12
+ const GUARD_PATH = join(process.cwd(), 'scripts/guard/guard.mjs');
13
+ const CLI_PATH = join(process.cwd(), 'scripts/team-flow.mjs');
14
+
15
+ function runNodeScript(scriptPath, args) {
16
+ return execFileSync(process.execPath, [scriptPath, ...args], {
17
+ encoding: 'utf-8',
18
+ stdio: ['pipe', 'pipe', 'pipe'],
19
+ });
20
+ }
21
+
22
+ function runGit(directory, args) {
23
+ return execFileSync('git', args, { cwd: directory, encoding: 'utf8' }).trim();
24
+ }
25
+
26
+ function initializeGitRepository(directory) {
27
+ runGit(directory, ['init', '--quiet']);
28
+ runGit(directory, ['config', 'user.email', 'tests@example.invalid']);
29
+ runGit(directory, ['config', 'user.name', 'Guard Control Records Test']);
30
+ runGit(directory, ['add', '--all']);
31
+ runGit(directory, ['commit', '--quiet', '--message', 'initial guard control records change']);
32
+ const base = runGit(directory, ['rev-parse', 'HEAD']);
33
+ writeFileSync(join(directory, 'git-range-marker.txt'), 'second commit\n');
34
+ runGit(directory, ['add', 'git-range-marker.txt']);
35
+ runGit(directory, ['commit', '--quiet', '--message', 'second guard control records change']);
36
+ return { base, head: runGit(directory, ['rev-parse', 'HEAD']) };
37
+ }
38
+
39
+ describe('guard: transition matrix', () => {
40
+ before(() => {
41
+ tempDir = mkdtempSync(join(tmpdir(), 'tf-guard-test-'));
42
+ // Create minimal artifacts so artifact checks can pass
43
+ writeFileSync(join(tempDir, 'proposal.md'), '## Why\nThis is a test proposal for guard testing purposes. The system needs to support feature X which will enable users to accomplish their goals more efficiently.\n## What Changes\n- Add feature X');
44
+ mkdirSync(join(tempDir, 'specs', 'test'), { recursive: true });
45
+ writeFileSync(join(tempDir, 'specs', 'test', 'spec.md'), '## ADDED Requirements\n### Requirement: Feature X\nThe system SHALL do X.\n#### Scenario: basic\n- **WHEN** user triggers\n- **THEN** system responds');
46
+ writeFileSync(join(tempDir, 'design.md'), '## Context\nTest design\n## Decisions\n### Decision 1\n- Choice: A\n- Rationale: B');
47
+ writeFileSync(join(tempDir, 'tasks.md'), '## File Structure\n- Create: src/x.ts\n## Tasks\n### 1.1 Task\n- [x] done');
48
+ });
49
+
50
+ after(() => {
51
+ if (tempDir) rmSync(tempDir, { recursive: true, force: true });
52
+ });
53
+
54
+ function runGuard(fromState, toState, opts = '') {
55
+ try {
56
+ const extraArgs = opts ? opts.split(/\s+/).filter(Boolean) : [];
57
+ const result = runNodeScript(GUARD_PATH, ['check', tempDir, fromState, toState, '--json', ...extraArgs]);
58
+ return { exitCode: 0, output: JSON.parse(result.trim()) };
59
+ } catch (err) {
60
+ if (err.stdout) {
61
+ try { return { exitCode: err.status, output: JSON.parse(err.stdout.trim()) }; }
62
+ catch { return { exitCode: err.status, output: err.stderr || err.message }; }
63
+ }
64
+ return { exitCode: err.status || 1, output: err.stderr || err.message };
65
+ }
66
+ }
67
+
68
+ it('exploring→specifying requires artifacts-exist', () => {
69
+ const result = runGuard('exploring', 'specifying');
70
+ assert.equal(result.exitCode, 0, `Expected exit 0 but got ${result.exitCode}: ${JSON.stringify(result.output)}`);
71
+ const checks = result.output.checks;
72
+ assert.ok(checks.some(c => c.dimension === 'artifacts-exist'));
73
+ });
74
+
75
+ it('specifying→bridging requires artifacts-exist + schema-valid', () => {
76
+ const result = runGuard('specifying', 'bridging');
77
+ assert.equal(result.exitCode, 0, `Expected exit 0 but got ${result.exitCode}: ${JSON.stringify(result.output)}`);
78
+ const dims = result.output.checks.map(c => c.dimension);
79
+ assert.ok(dims.includes('artifacts-exist'));
80
+ assert.ok(dims.includes('schema-valid'));
81
+ });
82
+
83
+ it('bridging→approved-for-build requires artifacts-exist + schema-valid + contract-fresh', () => {
84
+ const result = runGuard('bridging', 'approved-for-build');
85
+ // contract-fresh may fail since no contract exists, but the check should run
86
+ const dims = result.output.checks.map(c => c.dimension);
87
+ assert.ok(dims.includes('artifacts-exist'));
88
+ assert.ok(dims.includes('schema-valid'));
89
+ assert.ok(dims.includes('contract-fresh'));
90
+ });
91
+
92
+ it('approved-for-build→executing requires artifacts-exist + contract-fresh', () => {
93
+ const result = runGuard('approved-for-build', 'executing');
94
+ const dims = result.output.checks.map(c => c.dimension);
95
+ assert.ok(dims.includes('artifacts-exist'));
96
+ assert.ok(dims.includes('contract-fresh'));
97
+ });
98
+
99
+ it('executing→closing requires tasks-complete + tests-passing', () => {
100
+ const result = runGuard('executing', 'closing');
101
+ const dims = result.output.checks.map(c => c.dimension);
102
+ assert.ok(dims.includes('tasks-complete'));
103
+ assert.ok(dims.includes('tests-passing'));
104
+ });
105
+
106
+ it('executing→debugging requires no checks', () => {
107
+ const result = runGuard('executing', 'debugging');
108
+ assert.equal(result.exitCode, 0);
109
+ assert.deepStrictEqual(result.output.checks, []);
110
+ });
111
+
112
+ it('exploring→approved-for-build fails in default full workflow', () => {
113
+ const result = runGuard('exploring', 'approved-for-build');
114
+ assert.equal(result.exitCode, 1, `Expected exit 1 but got ${result.exitCode}: ${JSON.stringify(result.output)}`);
115
+ const dims = result.output.checks.map(c => c.dimension);
116
+ assert.ok(dims.includes('workflow-mode'));
117
+ });
118
+
119
+ it('exploring→approved-for-build passes in tweak workflow', () => {
120
+ const result = runGuard('exploring', 'approved-for-build', '--workflow tweak');
121
+ assert.equal(result.exitCode, 0, `Expected exit 0 but got ${result.exitCode}: ${JSON.stringify(result.output)}`);
122
+ assert.deepEqual(result.output.checks, []);
123
+ });
124
+
125
+ it('unknown transition returns error', () => {
126
+ const result = runGuard('closing', 'exploring');
127
+ assert.equal(result.exitCode, 1);
128
+ });
129
+ });
130
+
131
+ describe('guard: workflow mode behavior', () => {
132
+ before(() => {
133
+ tempDir = mkdtempSync(join(tmpdir(), 'tf-guard-mode-'));
134
+ writeFileSync(join(tempDir, 'proposal.md'), '## Why\nTest for mode skipping\n## What Changes\n- Add Y');
135
+ });
136
+
137
+ after(() => {
138
+ if (tempDir) rmSync(tempDir, { recursive: true, force: true });
139
+ });
140
+
141
+ function runGuardWithMode(fromState, toState, workflow) {
142
+ try {
143
+ const result = runNodeScript(GUARD_PATH, ['check', tempDir, fromState, toState, '--json', '--workflow', workflow]);
144
+ return { exitCode: 0, output: JSON.parse(result.trim()) };
145
+ } catch (err) {
146
+ if (err.stdout) {
147
+ try { return { exitCode: err.status, output: JSON.parse(err.stdout.trim()) }; }
148
+ catch { return { exitCode: err.status, output: err.stderr || err.message }; }
149
+ }
150
+ return { exitCode: err.status || 1, output: err.stderr || err.message };
151
+ }
152
+ }
153
+
154
+ it('tweak mode allows exploring to approved-for-build without artifacts', () => {
155
+ const result = runGuardWithMode('exploring', 'approved-for-build', 'tweak');
156
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
157
+ assert.deepEqual(result.output.checks, []);
158
+ });
159
+
160
+ it('hotfix mode allows exploring to bridging without artifacts', () => {
161
+ const result = runGuardWithMode('exploring', 'bridging', 'hotfix');
162
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
163
+ assert.deepEqual(result.output.checks, []);
164
+ });
165
+
166
+ it('full mode keeps requiring artifacts on specifying to bridging', () => {
167
+ const result = runGuardWithMode('specifying', 'bridging', 'full');
168
+ const checks = result.output.checks;
169
+ assert.ok(checks.some(c => c.dimension === 'artifacts-exist'));
170
+ assert.ok(checks.some(c => c.dimension === 'schema-valid'));
171
+ });
172
+
173
+ it('invalid workflow mode exits with error', () => {
174
+ const result = runGuardWithMode('exploring', 'specifying', 'invalid-mode');
175
+ assert.equal(result.exitCode, 2);
176
+ });
177
+ });
178
+
179
+ describe('guard: hotfix minimal contract', () => {
180
+ let dir;
181
+
182
+ before(() => {
183
+ dir = mkdtempSync(join(tmpdir(), 'tf-hotfix-guard-'));
184
+ writeFileSync(join(dir, '.team-flow.yaml'), 'state: exploring\nworkflow: hotfix\nchange_name: hotfix-test\n');
185
+ });
186
+
187
+ after(() => {
188
+ if (dir) rmSync(dir, { recursive: true, force: true });
189
+ });
190
+
191
+ function run(fromState, toState) {
192
+ try {
193
+ const stdout = runNodeScript(GUARD_PATH, ['check', dir, fromState, toState, '--json', '--workflow', 'hotfix']);
194
+ return { exitCode: 0, output: JSON.parse(stdout.trim()) };
195
+ } catch (err) {
196
+ if (err.stdout) {
197
+ try { return { exitCode: err.status, output: JSON.parse(err.stdout.trim()) }; }
198
+ catch { return { exitCode: err.status, output: err.stderr || err.message }; }
199
+ }
200
+ return { exitCode: err.status || 1, output: err.stderr || err.message };
201
+ }
202
+ }
203
+
204
+ function prepareFreshHotfixState() {
205
+ writeFileSync(join(dir, 'execution-contract.md'), '# Execution Contract\n\n## Intent Lock\n\nHotfix contract.\n');
206
+ runNodeScript(CLI_PATH, ['state', 'init', dir]);
207
+ runNodeScript(CLI_PATH, ['state', 'set', dir, 'workflow', 'hotfix']);
208
+ }
209
+
210
+ it('allows exploring to bridging without full planning artifacts', () => {
211
+ const result = run('exploring', 'bridging');
212
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
213
+ assert.deepEqual(result.output.checks, []);
214
+ });
215
+
216
+ it('blocks bridging to approved-for-build without execution-contract.md', () => {
217
+ const result = run('bridging', 'approved-for-build');
218
+ assert.equal(result.exitCode, 1);
219
+ assert.ok(result.output.checks.some(c => c.dimension === 'contract-current'));
220
+ });
221
+
222
+ it('blocks bridging to approved-for-build without DP-3', () => {
223
+ prepareFreshHotfixState();
224
+ const result = run('bridging', 'approved-for-build');
225
+ assert.equal(result.exitCode, 1);
226
+ assert.ok(result.output.checks.some(c => c.dimension === 'dp3-approved'));
227
+ });
228
+
229
+ it('rejects bridging to approved-for-build when DP-3 is recorded but not approved', () => {
230
+ prepareFreshHotfixState();
231
+ runNodeScript(CLI_PATH, ['state', 'set', dir, 'dp_3_result', 'rejected']);
232
+ const result = run('bridging', 'approved-for-build');
233
+ assert.equal(result.exitCode, 1);
234
+ const dp3Check = result.output.checks.find(c => c.dimension === 'dp3-approved');
235
+ assert.ok(dp3Check);
236
+ assert.equal(dp3Check.pass, false);
237
+ });
238
+
239
+ it('allows bridging to approved-for-build with fresh contract and DP-3', () => {
240
+ prepareFreshHotfixState();
241
+ runNodeScript(CLI_PATH, ['state', 'set', dir, 'dp_3_result', 'approved']);
242
+ const result = run('bridging', 'approved-for-build');
243
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
244
+ });
245
+
246
+ it('allows approved-for-build to executing with fresh contract and approved DP-3', () => {
247
+ prepareFreshHotfixState();
248
+ runNodeScript(CLI_PATH, ['state', 'set', dir, 'dp_3_result', 'approved: user confirmed minimal contract']);
249
+ runNodeScript(CLI_PATH, ['execution', 'recommend', dir, '--wave', 'wave-1:serial:1.1']);
250
+ runNodeScript(CLI_PATH, ['execution', 'plan', dir, '--mode', 'sdd', '--confirm', '--acknowledge-recommendation',
251
+ '--reason', 'hotfix user-selected execution plan', '--wave', 'wave-1:serial:1.1']);
252
+ const result = run('approved-for-build', 'executing');
253
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
254
+ const dims = result.output.checks.map(c => c.dimension);
255
+ assert.deepEqual(dims, ['contract-current', 'dp3-approved', 'execution-plan-ready']);
256
+ });
257
+ });
258
+
259
+ describe('guard: execution control records', () => {
260
+ let dir;
261
+
262
+ before(() => {
263
+ dir = mkdtempSync(join(tmpdir(), 'tf-guard-control-records-'));
264
+ });
265
+
266
+ after(() => {
267
+ if (dir) rmSync(dir, { recursive: true, force: true });
268
+ });
269
+
270
+ function run(fromState, toState, workflow = 'full') {
271
+ try {
272
+ const stdout = runNodeScript(GUARD_PATH, ['check', dir, fromState, toState, '--json', '--workflow', workflow]);
273
+ return { exitCode: 0, output: JSON.parse(stdout.trim()) };
274
+ } catch (err) {
275
+ if (err.stdout) {
276
+ try { return { exitCode: err.status, output: JSON.parse(err.stdout.trim()) }; }
277
+ catch { return { exitCode: err.status, output: err.stderr || err.message }; }
278
+ }
279
+ return { exitCode: err.status || 1, output: err.stderr || err.message };
280
+ }
281
+ }
282
+
283
+ function prepareFreshFullState() {
284
+ rmSync(dir, { recursive: true, force: true });
285
+ mkdirSync(join(dir, 'specs', 'execution'), { recursive: true });
286
+ writeFileSync(join(dir, 'proposal.md'), '## Why\nThis proposal has enough context to verify guard control records in a full workflow.\n## What Changes\n- Enforce recorded execution control data.\n');
287
+ writeFileSync(join(dir, 'design.md'), '# Design\n\n## Context\nGuard control records.\n');
288
+ writeFileSync(join(dir, 'tasks.md'), '# Tasks\n\n- [x] 1.1 First task\n- [x] 1.2 Second task\n');
289
+ writeFileSync(join(dir, 'specs', 'execution', 'spec.md'), '## ADDED Requirements\n\n### Requirement: Execution control records\nThe system SHALL require current execution control records.\n\n#### Scenario: Guard transition\n- **WHEN** execution starts\n- **THEN** the guard verifies control records.\n');
290
+ writeFileSync(join(dir, 'execution-contract.md'), '# Execution Contract\n\n## Intent Lock\n\nGuard control records.\n');
291
+ writeFileSync(join(dir, '.team-flow.yaml'), 'state: approved-for-build\nworkflow: full\n');
292
+ runNodeScript(CLI_PATH, ['state', 'init', dir]);
293
+ gitRefs = initializeGitRepository(dir);
294
+ }
295
+
296
+ function createCurrentPlan() {
297
+ runNodeScript(CLI_PATH, ['execution', 'recommend', dir,
298
+ '--wave', 'wave-1:parallel:1.1,1.2',
299
+ '--wave', 'wave-2:serial:2.1']);
300
+ runNodeScript(CLI_PATH, ['execution', 'plan', dir, '--mode', 'sdd', '--confirm',
301
+ '--reason', 'full workflow user-selected execution plan',
302
+ '--wave', 'wave-1:parallel:1.1,1.2',
303
+ '--wave', 'wave-2:serial:2.1']);
304
+ }
305
+
306
+ function setStateField(field, value) {
307
+ const statePath = join(dir, '.team-flow.yaml');
308
+ const current = readFileSync(statePath, 'utf8');
309
+ writeFileSync(statePath, current.replace(new RegExp(`^${field}:.*$`, 'm'), `${field}: ${value}`));
310
+ }
311
+
312
+ function recordPassingClosingPrerequisites() {
313
+ runNodeScript(CLI_PATH, ['state', 'set', dir, 'test_result', 'pass: unit tests']);
314
+ runNodeScript(CLI_PATH, ['state', 'set', dir, 'spec_merged', 'true']);
315
+ }
316
+
317
+ function writeReviewReport(name, content = 'Review completed without blocking findings.\n') {
318
+ const reportsDir = join(dir, '.superpowers', 'sdd', 'reviews');
319
+ mkdirSync(reportsDir, { recursive: true });
320
+ const reportPath = join(reportsDir, name);
321
+ writeFileSync(reportPath, content);
322
+ return reportPath;
323
+ }
324
+
325
+ it('rejects arbitrary DP-4 text when no current execution plan exists', () => {
326
+ prepareFreshFullState();
327
+ setStateField('dp_4_result', 'anything');
328
+
329
+ const result = run('approved-for-build', 'executing');
330
+
331
+ assert.equal(result.exitCode, 1);
332
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
333
+ assert.ok(planCheck);
334
+ assert.equal(planCheck.pass, false);
335
+ assert.match(planCheck.failures.join('\n'), /plan.*missing|execution plan/i);
336
+ });
337
+
338
+ it('rejects a debugging return without a current execution plan in full workflow', () => {
339
+ prepareFreshFullState();
340
+
341
+ const result = run('debugging', 'executing');
342
+
343
+ assert.equal(result.exitCode, 1);
344
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
345
+ assert.ok(planCheck);
346
+ assert.equal(planCheck.pass, false);
347
+ assert.match(planCheck.failures.join('\n'), /plan.*missing|execution plan/i);
348
+ });
349
+
350
+ it('rejects a debugging return without a current execution plan in hotfix workflow', () => {
351
+ prepareFreshFullState();
352
+ setStateField('workflow', 'hotfix');
353
+
354
+ const result = run('debugging', 'executing', 'hotfix');
355
+
356
+ assert.equal(result.exitCode, 1);
357
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
358
+ assert.ok(planCheck);
359
+ assert.equal(planCheck.pass, false);
360
+ assert.match(planCheck.failures.join('\n'), /plan.*missing|execution plan/i);
361
+ });
362
+
363
+ it('keeps a debugging return in tweak workflow limited to contract freshness', () => {
364
+ prepareFreshFullState();
365
+ setStateField('workflow', 'tweak');
366
+
367
+ const result = run('debugging', 'executing', 'tweak');
368
+
369
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
370
+ assert.deepEqual(result.output.checks.map(check => check.dimension), ['contract-fresh']);
371
+ });
372
+
373
+ it('rejects a debugging return when the execution plan is stale', () => {
374
+ prepareFreshFullState();
375
+ createCurrentPlan();
376
+ writeFileSync(join(dir, 'tasks.md'), '# Tasks\n\n- [x] 1.1 Changed task\n');
377
+
378
+ const result = run('debugging', 'executing');
379
+
380
+ assert.equal(result.exitCode, 1);
381
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
382
+ assert.ok(planCheck);
383
+ assert.equal(planCheck.pass, false);
384
+ assert.match(planCheck.failures.join('\n'), /stale: artifacts hash mismatch/i);
385
+ });
386
+
387
+ it('rejects a debugging return when the execution plan mode mismatches state', () => {
388
+ prepareFreshFullState();
389
+ createCurrentPlan();
390
+ setStateField('execution_mode', 'inline');
391
+
392
+ const result = run('debugging', 'executing');
393
+
394
+ assert.equal(result.exitCode, 1);
395
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
396
+ assert.ok(planCheck);
397
+ assert.equal(planCheck.pass, false);
398
+ assert.match(planCheck.failures.join('\n'), /mode does not match state/i);
399
+ });
400
+
401
+ it('rejects a debugging return when DP-4 forges the current plan revision', () => {
402
+ prepareFreshFullState();
403
+ createCurrentPlan();
404
+ setStateField('dp_4_result', 'sdd: plan revision 10; forged revision reference');
405
+
406
+ const result = run('debugging', 'executing');
407
+
408
+ assert.equal(result.exitCode, 1);
409
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
410
+ assert.ok(planCheck);
411
+ assert.equal(planCheck.pass, false);
412
+ assert.match(planCheck.failures.join('\n'), /DP-4.*revision/i);
413
+ });
414
+
415
+ it('rejects DP-4 that names a different execution plan revision', () => {
416
+ prepareFreshFullState();
417
+ createCurrentPlan();
418
+ setStateField('dp_4_result', 'sdd: plan revision 10; forged revision reference');
419
+
420
+ const result = run('approved-for-build', 'executing');
421
+
422
+ assert.equal(result.exitCode, 1);
423
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
424
+ assert.equal(planCheck.pass, false);
425
+ assert.match(planCheck.failures.join('\n'), /DP-4.*revision/i);
426
+ });
427
+
428
+ it('keeps tweak transitions exempt from execution plan and review receipt checks', () => {
429
+ prepareFreshFullState();
430
+ setStateField('workflow', 'tweak');
431
+ setStateField('dp_4_result', 'tweak execution selected');
432
+
433
+ const executing = run('approved-for-build', 'executing', 'tweak');
434
+ assert.equal(executing.exitCode, 0, JSON.stringify(executing.output));
435
+ assert.ok(!executing.output.checks.some(check => check.dimension === 'execution-plan-ready'));
436
+
437
+ recordPassingClosingPrerequisites();
438
+ const closing = run('executing', 'closing', 'tweak');
439
+ assert.equal(closing.exitCode, 0, JSON.stringify(closing.output));
440
+ assert.ok(!closing.output.checks.some(check => check.dimension === 'execution-reviews-passed'));
441
+ });
442
+
443
+ it('rejects full and hotfix closing without a current execution plan', () => {
444
+ for (const workflow of ['full', 'hotfix']) {
445
+ prepareFreshFullState();
446
+ setStateField('workflow', workflow);
447
+ recordPassingClosingPrerequisites();
448
+
449
+ const result = run('executing', 'closing', workflow);
450
+ const planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
451
+ assert.equal(result.exitCode, 1, workflow);
452
+ assert.ok(planCheck, workflow);
453
+ assert.equal(planCheck.pass, false, workflow);
454
+ assert.match(planCheck.failures.join('\n'), /plan.*missing|execution plan/i, workflow);
455
+ }
456
+ });
457
+
458
+ it('rejects stale and state-mismatched execution plans before executing', () => {
459
+ prepareFreshFullState();
460
+ createCurrentPlan();
461
+ writeFileSync(join(dir, 'tasks.md'), '# Tasks\n\n- [x] 1.1 Changed task\n');
462
+
463
+ let result = run('approved-for-build', 'executing');
464
+ let planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
465
+ assert.equal(result.exitCode, 1);
466
+ assert.equal(planCheck.pass, false);
467
+ assert.match(planCheck.failures.join('\n'), /stale: artifacts hash mismatch/i);
468
+
469
+ prepareFreshFullState();
470
+ createCurrentPlan();
471
+ setStateField('execution_mode', 'inline');
472
+ result = run('approved-for-build', 'executing');
473
+ planCheck = result.output.checks.find(check => check.dimension === 'execution-plan-ready');
474
+ assert.equal(result.exitCode, 1);
475
+ assert.equal(planCheck.pass, false);
476
+ assert.match(planCheck.failures.join('\n'), /mode does not match state/i);
477
+ });
478
+
479
+ it('blocks closing until every planned wave has a passing review receipt', () => {
480
+ prepareFreshFullState();
481
+ createCurrentPlan();
482
+ recordPassingClosingPrerequisites();
483
+
484
+ let result = run('executing', 'closing');
485
+ let reviewCheck = result.output.checks.find(check => check.dimension === 'execution-reviews-passed');
486
+ assert.equal(result.exitCode, 1);
487
+ assert.equal(reviewCheck.pass, false);
488
+ assert.match(reviewCheck.failures.join('\n'), /wave-1|receipt/i);
489
+
490
+ runNodeScript(CLI_PATH, ['execution', 'review', dir, '--wave', 'wave-1',
491
+ '--base', gitRefs.base, '--head', gitRefs.head, '--report', writeReviewReport('wave-1.md'), '--verdict', 'pass']);
492
+ runNodeScript(CLI_PATH, ['execution', 'review', dir, '--wave', 'wave-2',
493
+ '--base', gitRefs.base, '--head', gitRefs.head, '--report', writeReviewReport('wave-2.md'), '--verdict', 'fail']);
494
+
495
+ result = run('executing', 'closing');
496
+ reviewCheck = result.output.checks.find(check => check.dimension === 'execution-reviews-passed');
497
+ assert.equal(result.exitCode, 1);
498
+ assert.equal(reviewCheck.pass, false);
499
+ assert.match(reviewCheck.failures.join('\n'), /wave-2.*fail/i);
500
+
501
+ runNodeScript(CLI_PATH, ['execution', 'review', dir, '--wave', 'wave-2',
502
+ '--base', gitRefs.base, '--head', gitRefs.head, '--report', writeReviewReport('wave-2-repair.md'), '--verdict', 'pass']);
503
+
504
+ result = run('executing', 'closing');
505
+ reviewCheck = result.output.checks.find(check => check.dimension === 'execution-reviews-passed');
506
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
507
+ assert.equal(reviewCheck.pass, true);
508
+ });
509
+
510
+ it('allows closing with passing receipts when existing checks also pass', () => {
511
+ prepareFreshFullState();
512
+ createCurrentPlan();
513
+ recordPassingClosingPrerequisites();
514
+ runNodeScript(CLI_PATH, ['execution', 'review', dir, '--wave', 'wave-1',
515
+ '--base', gitRefs.base, '--head', gitRefs.head, '--report', writeReviewReport('wave-1.md'), '--verdict', 'pass']);
516
+ runNodeScript(CLI_PATH, ['execution', 'review', dir, '--wave', 'wave-2',
517
+ '--base', gitRefs.base, '--head', gitRefs.head, '--report', writeReviewReport('wave-2.md'), '--verdict', 'pass']);
518
+
519
+ const result = run('executing', 'closing');
520
+
521
+ assert.equal(result.exitCode, 0, JSON.stringify(result.output));
522
+ assert.equal(result.output.checks.find(check => check.dimension === 'execution-reviews-passed').pass, true);
523
+ });
524
+
525
+ it('blocks closing when a persisted passing review report is no longer safe evidence', () => {
526
+ const replacements = [
527
+ {
528
+ name: 'deleted',
529
+ replace: reportPath => rmSync(reportPath),
530
+ },
531
+ {
532
+ name: 'empty',
533
+ replace: reportPath => writeFileSync(reportPath, ''),
534
+ },
535
+ {
536
+ name: 'directory',
537
+ replace: reportPath => {
538
+ rmSync(reportPath);
539
+ mkdirSync(reportPath);
540
+ },
541
+ },
542
+ {
543
+ name: 'symbolic link',
544
+ replace: reportPath => {
545
+ rmSync(reportPath);
546
+ symlinkSync(writeReviewReport('replacement-target.md'), reportPath);
547
+ },
548
+ },
549
+ {
550
+ name: 'control-character path',
551
+ replace: reportPath => {
552
+ const receiptPath = join(dir, '.superpowers', 'sdd', 'reviews', `${Buffer.from('wave-1').toString('base64url')}.json`);
553
+ const receipt = JSON.parse(readFileSync(receiptPath, 'utf8'));
554
+ receipt.report = `${reportPath}\nforged`;
555
+ writeFileSync(receiptPath, `${JSON.stringify(receipt)}\n`);
556
+ },
557
+ },
558
+ ];
559
+
560
+ for (const replacement of replacements) {
561
+ prepareFreshFullState();
562
+ createCurrentPlan();
563
+ recordPassingClosingPrerequisites();
564
+ const waveOneReport = writeReviewReport('wave-1.md');
565
+ runNodeScript(CLI_PATH, ['execution', 'review', dir, '--wave', 'wave-1',
566
+ '--base', gitRefs.base, '--head', gitRefs.head, '--report', waveOneReport, '--verdict', 'pass']);
567
+ runNodeScript(CLI_PATH, ['execution', 'review', dir, '--wave', 'wave-2',
568
+ '--base', gitRefs.base, '--head', gitRefs.head, '--report', writeReviewReport('wave-2.md'), '--verdict', 'pass']);
569
+
570
+ replacement.replace(waveOneReport);
571
+
572
+ const result = run('executing', 'closing');
573
+ const reviewCheck = result.output.checks.find(check => check.dimension === 'execution-reviews-passed');
574
+ assert.equal(result.exitCode, 1, replacement.name);
575
+ assert.equal(reviewCheck.pass, false, replacement.name);
576
+ assert.match(reviewCheck.failures.join('\n'), /wave-1|receipt/i, replacement.name);
577
+ }
578
+ });
579
+ });
580
+
581
+ describe('guard: artifacts-exist check', () => {
582
+ before(() => {
583
+ tempDir = mkdtempSync(join(tmpdir(), 'tf-guard-artifacts-'));
584
+ });
585
+
586
+ after(() => {
587
+ if (tempDir) rmSync(tempDir, { recursive: true, force: true });
588
+ });
589
+
590
+ function runGuard(fromState, toState) {
591
+ try {
592
+ const result = runNodeScript(GUARD_PATH, ['check', tempDir, fromState, toState, '--json']);
593
+ return { exitCode: 0, output: JSON.parse(result.trim()) };
594
+ } catch (err) {
595
+ if (err.stdout) {
596
+ try { return { exitCode: err.status, output: JSON.parse(err.stdout.trim()) }; }
597
+ catch { return { exitCode: err.status, output: err.stderr || err.message }; }
598
+ }
599
+ return { exitCode: err.status || 1, output: err.stderr || err.message };
600
+ }
601
+ }
602
+
603
+ it('fails when no artifacts exist', () => {
604
+ const result = runGuard('exploring', 'specifying');
605
+ // artifacts-exist should fail — no proposal, specs, etc.
606
+ const artifactsCheck = result.output.checks.find(c => c.dimension === 'artifacts-exist');
607
+ assert.ok(artifactsCheck);
608
+ assert.equal(artifactsCheck.pass, false);
609
+ assert.ok(artifactsCheck.failures.length > 0);
610
+ });
611
+ });