autonomous-coding-toolkit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +13 -0
  3. package/LICENSE +21 -0
  4. package/Makefile +21 -0
  5. package/README.md +140 -0
  6. package/SECURITY.md +28 -0
  7. package/agents/bash-expert.md +113 -0
  8. package/agents/dependency-auditor.md +138 -0
  9. package/agents/integration-tester.md +120 -0
  10. package/agents/lesson-scanner.md +149 -0
  11. package/agents/python-expert.md +179 -0
  12. package/agents/service-monitor.md +141 -0
  13. package/agents/shell-expert.md +147 -0
  14. package/benchmarks/runner.sh +147 -0
  15. package/benchmarks/tasks/01-rest-endpoint/rubric.sh +29 -0
  16. package/benchmarks/tasks/01-rest-endpoint/task.md +17 -0
  17. package/benchmarks/tasks/02-refactor-module/task.md +8 -0
  18. package/benchmarks/tasks/03-fix-integration-bug/task.md +8 -0
  19. package/benchmarks/tasks/04-add-test-coverage/task.md +8 -0
  20. package/benchmarks/tasks/05-multi-file-feature/task.md +8 -0
  21. package/bin/act.js +238 -0
  22. package/commands/autocode.md +6 -0
  23. package/commands/cancel-ralph.md +18 -0
  24. package/commands/code-factory.md +53 -0
  25. package/commands/create-prd.md +55 -0
  26. package/commands/ralph-loop.md +18 -0
  27. package/commands/run-plan.md +117 -0
  28. package/commands/submit-lesson.md +122 -0
  29. package/docs/ARCHITECTURE.md +630 -0
  30. package/docs/CONTRIBUTING.md +125 -0
  31. package/docs/lessons/0001-bare-exception-swallowing.md +34 -0
  32. package/docs/lessons/0002-async-def-without-await.md +28 -0
  33. package/docs/lessons/0003-create-task-without-callback.md +28 -0
  34. package/docs/lessons/0004-hardcoded-test-counts.md +28 -0
  35. package/docs/lessons/0005-sqlite-without-closing.md +33 -0
  36. package/docs/lessons/0006-venv-pip-path.md +27 -0
  37. package/docs/lessons/0007-runner-state-self-rejection.md +35 -0
  38. package/docs/lessons/0008-quality-gate-blind-spot.md +33 -0
  39. package/docs/lessons/0009-parser-overcount-empty-batches.md +36 -0
  40. package/docs/lessons/0010-local-outside-function-bash.md +33 -0
  41. package/docs/lessons/0011-batch-tests-for-unimplemented-code.md +36 -0
  42. package/docs/lessons/0012-api-markdown-unescaped-chars.md +33 -0
  43. package/docs/lessons/0013-export-prefix-env-parsing.md +33 -0
  44. package/docs/lessons/0014-decorator-registry-import-side-effect.md +43 -0
  45. package/docs/lessons/0015-frontend-backend-schema-drift.md +43 -0
  46. package/docs/lessons/0016-event-driven-cold-start-seeding.md +44 -0
  47. package/docs/lessons/0017-copy-paste-logic-diverges.md +43 -0
  48. package/docs/lessons/0018-layer-passes-pipeline-broken.md +45 -0
  49. package/docs/lessons/0019-systemd-envfile-ignores-export.md +41 -0
  50. package/docs/lessons/0020-persist-state-incrementally.md +44 -0
  51. package/docs/lessons/0021-dual-axis-testing.md +48 -0
  52. package/docs/lessons/0022-jsx-factory-shadowing.md +43 -0
  53. package/docs/lessons/0023-static-analysis-spiral.md +51 -0
  54. package/docs/lessons/0024-shared-pipeline-implementation.md +55 -0
  55. package/docs/lessons/0025-defense-in-depth-all-entry-points.md +65 -0
  56. package/docs/lessons/0026-linter-no-rules-false-enforcement.md +54 -0
  57. package/docs/lessons/0027-jsx-silent-prop-drop.md +64 -0
  58. package/docs/lessons/0028-no-infrastructure-in-client-code.md +49 -0
  59. package/docs/lessons/0029-never-write-secrets-to-files.md +61 -0
  60. package/docs/lessons/0030-cache-merge-not-replace.md +62 -0
  61. package/docs/lessons/0031-verify-units-at-boundaries.md +66 -0
  62. package/docs/lessons/0032-module-lifecycle-subscribe-unsubscribe.md +89 -0
  63. package/docs/lessons/0033-async-iteration-mutable-snapshot.md +72 -0
  64. package/docs/lessons/0034-caller-missing-await-silent-discard.md +65 -0
  65. package/docs/lessons/0035-duplicate-registration-silent-overwrite.md +85 -0
  66. package/docs/lessons/0036-websocket-dirty-disconnect.md +33 -0
  67. package/docs/lessons/0037-parallel-agents-worktree-corruption.md +31 -0
  68. package/docs/lessons/0038-subscribe-no-stored-ref.md +36 -0
  69. package/docs/lessons/0039-fallback-or-default-hides-bugs.md +34 -0
  70. package/docs/lessons/0040-event-firehose-filter-first.md +36 -0
  71. package/docs/lessons/0041-ambiguous-base-dir-path-nesting.md +32 -0
  72. package/docs/lessons/0042-spec-compliance-insufficient.md +36 -0
  73. package/docs/lessons/0043-exact-count-extensible-collections.md +32 -0
  74. package/docs/lessons/0044-relative-file-deps-worktree.md +39 -0
  75. package/docs/lessons/0045-iterative-design-improvement.md +33 -0
  76. package/docs/lessons/0046-plan-assertion-math-bugs.md +38 -0
  77. package/docs/lessons/0047-pytest-single-threaded-default.md +37 -0
  78. package/docs/lessons/0048-integration-wiring-batch.md +40 -0
  79. package/docs/lessons/0049-ab-verification.md +41 -0
  80. package/docs/lessons/0050-editing-sourced-files-during-execution.md +33 -0
  81. package/docs/lessons/0051-infrastructure-fixes-cant-self-heal.md +30 -0
  82. package/docs/lessons/0052-uncommitted-changes-poison-quality-gates.md +31 -0
  83. package/docs/lessons/0053-jq-compact-flag-inconsistency.md +31 -0
  84. package/docs/lessons/0054-parser-matches-inside-code-blocks.md +30 -0
  85. package/docs/lessons/0055-agents-compensate-for-garbled-prompts.md +31 -0
  86. package/docs/lessons/0056-grep-count-exit-code-on-zero.md +42 -0
  87. package/docs/lessons/0057-new-artifacts-break-git-clean-gates.md +42 -0
  88. package/docs/lessons/0058-dead-config-keys-never-consumed.md +49 -0
  89. package/docs/lessons/0059-contract-test-shared-structures.md +53 -0
  90. package/docs/lessons/0060-set-e-silent-death-in-runners.md +53 -0
  91. package/docs/lessons/0061-context-injection-dirty-state.md +50 -0
  92. package/docs/lessons/0062-sibling-bug-neighborhood-scan.md +29 -0
  93. package/docs/lessons/0063-one-flag-two-lifetimes.md +31 -0
  94. package/docs/lessons/0064-test-passes-wrong-reason.md +31 -0
  95. package/docs/lessons/0065-pipefail-grep-count-double-output.md +39 -0
  96. package/docs/lessons/0066-local-keyword-outside-function.md +37 -0
  97. package/docs/lessons/0067-stdin-hang-non-interactive-shell.md +36 -0
  98. package/docs/lessons/0068-agent-builds-wrong-thing-correctly.md +31 -0
  99. package/docs/lessons/0069-plan-quality-dominates-execution.md +30 -0
  100. package/docs/lessons/0070-spec-echo-back-prevents-drift.md +31 -0
  101. package/docs/lessons/0071-positive-instructions-outperform-negative.md +30 -0
  102. package/docs/lessons/0072-lost-in-the-middle-context-placement.md +30 -0
  103. package/docs/lessons/0073-unscoped-lessons-cause-false-positives.md +30 -0
  104. package/docs/lessons/0074-stale-context-injection-wrong-batch.md +32 -0
  105. package/docs/lessons/0075-research-artifacts-must-persist.md +32 -0
  106. package/docs/lessons/0076-wrong-decomposition-contaminates-downstream.md +30 -0
  107. package/docs/lessons/0077-cherry-pick-merges-need-manual-resolution.md +30 -0
  108. package/docs/lessons/0078-static-review-without-live-test.md +30 -0
  109. package/docs/lessons/0079-integration-wiring-batch-required.md +32 -0
  110. package/docs/lessons/FRAMEWORK.md +161 -0
  111. package/docs/lessons/SUMMARY.md +201 -0
  112. package/docs/lessons/TEMPLATE.md +85 -0
  113. package/docs/plans/2026-02-21-code-factory-v2-design.md +204 -0
  114. package/docs/plans/2026-02-21-code-factory-v2-implementation-plan.md +2189 -0
  115. package/docs/plans/2026-02-21-code-factory-v2-phase4-design.md +537 -0
  116. package/docs/plans/2026-02-21-code-factory-v2-phase4-implementation-plan.md +2012 -0
  117. package/docs/plans/2026-02-21-hardening-pass-design.md +108 -0
  118. package/docs/plans/2026-02-21-hardening-pass-plan.md +1378 -0
  119. package/docs/plans/2026-02-21-mab-research-report.md +406 -0
  120. package/docs/plans/2026-02-21-marketplace-restructure-design.md +240 -0
  121. package/docs/plans/2026-02-21-marketplace-restructure-plan.md +832 -0
  122. package/docs/plans/2026-02-21-phase4-completion-plan.md +697 -0
  123. package/docs/plans/2026-02-21-validator-suite-design.md +148 -0
  124. package/docs/plans/2026-02-21-validator-suite-plan.md +540 -0
  125. package/docs/plans/2026-02-22-mab-research-round2.md +556 -0
  126. package/docs/plans/2026-02-22-mab-run-design.md +462 -0
  127. package/docs/plans/2026-02-22-mab-run-plan.md +2046 -0
  128. package/docs/plans/2026-02-22-operations-design-methodology-research.md +681 -0
  129. package/docs/plans/2026-02-22-research-agent-failure-taxonomy.md +532 -0
  130. package/docs/plans/2026-02-22-research-code-guideline-policies.md +886 -0
  131. package/docs/plans/2026-02-22-research-codebase-audit-refactoring.md +908 -0
  132. package/docs/plans/2026-02-22-research-coding-standards-documentation.md +541 -0
  133. package/docs/plans/2026-02-22-research-competitive-landscape.md +687 -0
  134. package/docs/plans/2026-02-22-research-comprehensive-testing.md +1076 -0
  135. package/docs/plans/2026-02-22-research-context-utilization.md +459 -0
  136. package/docs/plans/2026-02-22-research-cost-quality-tradeoff.md +548 -0
  137. package/docs/plans/2026-02-22-research-lesson-transferability.md +508 -0
  138. package/docs/plans/2026-02-22-research-multi-agent-coordination.md +312 -0
  139. package/docs/plans/2026-02-22-research-phase-integration.md +602 -0
  140. package/docs/plans/2026-02-22-research-plan-quality.md +428 -0
  141. package/docs/plans/2026-02-22-research-prompt-engineering.md +558 -0
  142. package/docs/plans/2026-02-22-research-unconventional-perspectives.md +528 -0
  143. package/docs/plans/2026-02-22-research-user-adoption.md +638 -0
  144. package/docs/plans/2026-02-22-research-verification-effectiveness.md +433 -0
  145. package/docs/plans/2026-02-23-agent-suite-design.md +299 -0
  146. package/docs/plans/2026-02-23-agent-suite-plan.md +578 -0
  147. package/docs/plans/2026-02-23-phase3-cost-infrastructure-design.md +148 -0
  148. package/docs/plans/2026-02-23-phase3-cost-infrastructure-plan.md +1062 -0
  149. package/docs/plans/2026-02-23-research-bash-expert-agent.md +543 -0
  150. package/docs/plans/2026-02-23-research-dependency-auditor-agent.md +564 -0
  151. package/docs/plans/2026-02-23-research-improving-existing-agents.md +503 -0
  152. package/docs/plans/2026-02-23-research-integration-tester-agent.md +454 -0
  153. package/docs/plans/2026-02-23-research-python-expert-agent.md +429 -0
  154. package/docs/plans/2026-02-23-research-service-monitor-agent.md +425 -0
  155. package/docs/plans/2026-02-23-research-shell-expert-agent.md +533 -0
  156. package/docs/plans/2026-02-23-roadmap-to-completion.md +530 -0
  157. package/docs/plans/2026-02-24-headless-module-split-design.md +98 -0
  158. package/docs/plans/2026-02-24-headless-module-split.md +443 -0
  159. package/docs/plans/2026-02-24-lesson-scope-metadata-design.md +228 -0
  160. package/docs/plans/2026-02-24-lesson-scope-metadata-plan.md +968 -0
  161. package/docs/plans/2026-02-24-npm-packaging-design.md +841 -0
  162. package/docs/plans/2026-02-24-npm-packaging-plan.md +1965 -0
  163. package/docs/plans/audit-findings.md +186 -0
  164. package/docs/telegram-notification-format.md +98 -0
  165. package/examples/example-plan.md +51 -0
  166. package/examples/example-prd.json +72 -0
  167. package/examples/example-roadmap.md +33 -0
  168. package/examples/quickstart-plan.md +63 -0
  169. package/hooks/hooks.json +26 -0
  170. package/hooks/setup-symlinks.sh +48 -0
  171. package/hooks/stop-hook.sh +135 -0
  172. package/package.json +47 -0
  173. package/policies/bash.md +71 -0
  174. package/policies/python.md +71 -0
  175. package/policies/testing.md +61 -0
  176. package/policies/universal.md +60 -0
  177. package/scripts/analyze-report.sh +97 -0
  178. package/scripts/architecture-map.sh +145 -0
  179. package/scripts/auto-compound.sh +273 -0
  180. package/scripts/batch-audit.sh +42 -0
  181. package/scripts/batch-test.sh +101 -0
  182. package/scripts/entropy-audit.sh +221 -0
  183. package/scripts/failure-digest.sh +51 -0
  184. package/scripts/generate-ast-rules.sh +96 -0
  185. package/scripts/init.sh +112 -0
  186. package/scripts/lesson-check.sh +428 -0
  187. package/scripts/lib/common.sh +61 -0
  188. package/scripts/lib/cost-tracking.sh +153 -0
  189. package/scripts/lib/ollama.sh +60 -0
  190. package/scripts/lib/progress-writer.sh +128 -0
  191. package/scripts/lib/run-plan-context.sh +215 -0
  192. package/scripts/lib/run-plan-echo-back.sh +231 -0
  193. package/scripts/lib/run-plan-headless.sh +396 -0
  194. package/scripts/lib/run-plan-notify.sh +57 -0
  195. package/scripts/lib/run-plan-parser.sh +81 -0
  196. package/scripts/lib/run-plan-prompt.sh +215 -0
  197. package/scripts/lib/run-plan-quality-gate.sh +132 -0
  198. package/scripts/lib/run-plan-routing.sh +315 -0
  199. package/scripts/lib/run-plan-sampling.sh +170 -0
  200. package/scripts/lib/run-plan-scoring.sh +146 -0
  201. package/scripts/lib/run-plan-state.sh +142 -0
  202. package/scripts/lib/run-plan-team.sh +199 -0
  203. package/scripts/lib/telegram.sh +54 -0
  204. package/scripts/lib/thompson-sampling.sh +176 -0
  205. package/scripts/license-check.sh +74 -0
  206. package/scripts/mab-run.sh +575 -0
  207. package/scripts/module-size-check.sh +146 -0
  208. package/scripts/patterns/async-no-await.yml +5 -0
  209. package/scripts/patterns/bare-except.yml +6 -0
  210. package/scripts/patterns/empty-catch.yml +6 -0
  211. package/scripts/patterns/hardcoded-localhost.yml +9 -0
  212. package/scripts/patterns/retry-loop-no-backoff.yml +12 -0
  213. package/scripts/pipeline-status.sh +197 -0
  214. package/scripts/policy-check.sh +226 -0
  215. package/scripts/prior-art-search.sh +133 -0
  216. package/scripts/promote-mab-lessons.sh +126 -0
  217. package/scripts/prompts/agent-a-superpowers.md +29 -0
  218. package/scripts/prompts/agent-b-ralph.md +29 -0
  219. package/scripts/prompts/judge-agent.md +61 -0
  220. package/scripts/prompts/planner-agent.md +44 -0
  221. package/scripts/pull-community-lessons.sh +90 -0
  222. package/scripts/quality-gate.sh +266 -0
  223. package/scripts/research-gate.sh +90 -0
  224. package/scripts/run-plan.sh +329 -0
  225. package/scripts/scope-infer.sh +159 -0
  226. package/scripts/setup-ralph-loop.sh +155 -0
  227. package/scripts/telemetry.sh +230 -0
  228. package/scripts/tests/run-all-tests.sh +52 -0
  229. package/scripts/tests/test-act-cli.sh +46 -0
  230. package/scripts/tests/test-agents-md.sh +87 -0
  231. package/scripts/tests/test-analyze-report.sh +114 -0
  232. package/scripts/tests/test-architecture-map.sh +89 -0
  233. package/scripts/tests/test-auto-compound.sh +169 -0
  234. package/scripts/tests/test-batch-test.sh +65 -0
  235. package/scripts/tests/test-benchmark-runner.sh +25 -0
  236. package/scripts/tests/test-common.sh +168 -0
  237. package/scripts/tests/test-cost-tracking.sh +158 -0
  238. package/scripts/tests/test-echo-back.sh +180 -0
  239. package/scripts/tests/test-entropy-audit.sh +146 -0
  240. package/scripts/tests/test-failure-digest.sh +66 -0
  241. package/scripts/tests/test-generate-ast-rules.sh +145 -0
  242. package/scripts/tests/test-helpers.sh +82 -0
  243. package/scripts/tests/test-init.sh +47 -0
  244. package/scripts/tests/test-lesson-check.sh +278 -0
  245. package/scripts/tests/test-lesson-local.sh +55 -0
  246. package/scripts/tests/test-license-check.sh +109 -0
  247. package/scripts/tests/test-mab-run.sh +182 -0
  248. package/scripts/tests/test-ollama-lib.sh +49 -0
  249. package/scripts/tests/test-ollama.sh +60 -0
  250. package/scripts/tests/test-pipeline-status.sh +198 -0
  251. package/scripts/tests/test-policy-check.sh +124 -0
  252. package/scripts/tests/test-prior-art-search.sh +96 -0
  253. package/scripts/tests/test-progress-writer.sh +140 -0
  254. package/scripts/tests/test-promote-mab-lessons.sh +110 -0
  255. package/scripts/tests/test-pull-community-lessons.sh +149 -0
  256. package/scripts/tests/test-quality-gate.sh +241 -0
  257. package/scripts/tests/test-research-gate.sh +132 -0
  258. package/scripts/tests/test-run-plan-cli.sh +86 -0
  259. package/scripts/tests/test-run-plan-context.sh +305 -0
  260. package/scripts/tests/test-run-plan-e2e.sh +153 -0
  261. package/scripts/tests/test-run-plan-headless.sh +424 -0
  262. package/scripts/tests/test-run-plan-notify.sh +124 -0
  263. package/scripts/tests/test-run-plan-parser.sh +217 -0
  264. package/scripts/tests/test-run-plan-prompt.sh +254 -0
  265. package/scripts/tests/test-run-plan-quality-gate.sh +222 -0
  266. package/scripts/tests/test-run-plan-routing.sh +178 -0
  267. package/scripts/tests/test-run-plan-scoring.sh +148 -0
  268. package/scripts/tests/test-run-plan-state.sh +261 -0
  269. package/scripts/tests/test-run-plan-team.sh +157 -0
  270. package/scripts/tests/test-scope-infer.sh +150 -0
  271. package/scripts/tests/test-setup-ralph-loop.sh +63 -0
  272. package/scripts/tests/test-telegram-env.sh +38 -0
  273. package/scripts/tests/test-telegram.sh +121 -0
  274. package/scripts/tests/test-telemetry.sh +46 -0
  275. package/scripts/tests/test-thompson-sampling.sh +139 -0
  276. package/scripts/tests/test-validate-all.sh +60 -0
  277. package/scripts/tests/test-validate-commands.sh +89 -0
  278. package/scripts/tests/test-validate-hooks.sh +98 -0
  279. package/scripts/tests/test-validate-lessons.sh +150 -0
  280. package/scripts/tests/test-validate-plan-quality.sh +235 -0
  281. package/scripts/tests/test-validate-plans.sh +187 -0
  282. package/scripts/tests/test-validate-plugin.sh +106 -0
  283. package/scripts/tests/test-validate-prd.sh +184 -0
  284. package/scripts/tests/test-validate-skills.sh +134 -0
  285. package/scripts/validate-all.sh +57 -0
  286. package/scripts/validate-commands.sh +67 -0
  287. package/scripts/validate-hooks.sh +89 -0
  288. package/scripts/validate-lessons.sh +98 -0
  289. package/scripts/validate-plan-quality.sh +369 -0
  290. package/scripts/validate-plans.sh +120 -0
  291. package/scripts/validate-plugin.sh +86 -0
  292. package/scripts/validate-policies.sh +42 -0
  293. package/scripts/validate-prd.sh +118 -0
  294. package/scripts/validate-skills.sh +96 -0
  295. package/skills/autocode/SKILL.md +285 -0
  296. package/skills/autocode/ab-verification.md +51 -0
  297. package/skills/autocode/code-quality-standards.md +37 -0
  298. package/skills/autocode/competitive-mode.md +364 -0
  299. package/skills/brainstorming/SKILL.md +97 -0
  300. package/skills/capture-lesson/SKILL.md +187 -0
  301. package/skills/check-lessons/SKILL.md +116 -0
  302. package/skills/dispatching-parallel-agents/SKILL.md +110 -0
  303. package/skills/executing-plans/SKILL.md +85 -0
  304. package/skills/finishing-a-development-branch/SKILL.md +201 -0
  305. package/skills/receiving-code-review/SKILL.md +72 -0
  306. package/skills/requesting-code-review/SKILL.md +59 -0
  307. package/skills/requesting-code-review/code-reviewer.md +82 -0
  308. package/skills/research/SKILL.md +145 -0
  309. package/skills/roadmap/SKILL.md +115 -0
  310. package/skills/subagent-driven-development/SKILL.md +98 -0
  311. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +18 -0
  312. package/skills/subagent-driven-development/implementer-prompt.md +73 -0
  313. package/skills/subagent-driven-development/spec-reviewer-prompt.md +57 -0
  314. package/skills/systematic-debugging/SKILL.md +134 -0
  315. package/skills/systematic-debugging/condition-based-waiting.md +64 -0
  316. package/skills/systematic-debugging/defense-in-depth.md +32 -0
  317. package/skills/systematic-debugging/root-cause-tracing.md +55 -0
  318. package/skills/test-driven-development/SKILL.md +167 -0
  319. package/skills/using-git-worktrees/SKILL.md +219 -0
  320. package/skills/using-superpowers/SKILL.md +54 -0
  321. package/skills/verification-before-completion/SKILL.md +140 -0
  322. package/skills/verify/SKILL.md +82 -0
  323. package/skills/writing-plans/SKILL.md +128 -0
  324. package/skills/writing-skills/SKILL.md +93 -0
@@ -0,0 +1,266 @@
1
+ #!/usr/bin/env bash
2
+ # quality-gate.sh — Composite quality gate for Ralph loop --quality-checks
3
+ # Runs lesson check + project test suite in sequence, fails fast on first failure.
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
7
+ source "$SCRIPT_DIR/lib/common.sh"
8
+ PROJECT_ROOT=""
9
+ QUICK=false
10
+ WITH_LICENSE=false
11
+
12
+ usage() {
13
+ cat <<'USAGE'
14
+ Usage: quality-gate.sh --project-root <dir> [--quick] [--with-license]
15
+
16
+ Composite quality gate for the Ralph loop. Runs checks in order, stops at first failure.
17
+
18
+ Checks:
19
+ 0. Toolkit validation — runs validate-all.sh if present (toolkit self-check)
20
+ 1. Lesson check — runs lesson-check.sh on git-changed files in project root
21
+ 2. Lint check — ruff (Python) or eslint (Node) if available (skipped with --quick)
22
+ 3. Project test suite — auto-detects pytest / npm test / make test
23
+ 4. License check — flags GPL/AGPL deps (only with --with-license, skipped with --quick)
24
+ 5. Memory warning — warns if available memory < 4G (never fails)
25
+
26
+ Options:
27
+ --project-root <dir> Project directory to check (required)
28
+ --quick Skip lint and license checks (fast inner-loop mode)
29
+ --with-license Include dependency license audit
30
+ --help, -h Show this help
31
+
32
+ Exit: 0 if all pass, 1 on first failure
33
+ USAGE
34
+ exit 0
35
+ }
36
+
37
+ # --- Parse args ---
38
+ while [[ $# -gt 0 ]]; do
39
+ case "$1" in
40
+ --project-root)
41
+ PROJECT_ROOT="${2:-}"
42
+ shift 2
43
+ ;;
44
+ --quick)
45
+ QUICK=true
46
+ shift
47
+ ;;
48
+ --with-license)
49
+ WITH_LICENSE=true
50
+ shift
51
+ ;;
52
+ --help|-h)
53
+ usage
54
+ ;;
55
+ *)
56
+ echo "quality-gate: unknown option: $1" >&2
57
+ echo "Run with --help for usage." >&2
58
+ exit 1
59
+ ;;
60
+ esac
61
+ done
62
+
63
+ if [[ -z "$PROJECT_ROOT" ]]; then
64
+ echo "quality-gate: --project-root is required" >&2
65
+ exit 1
66
+ fi
67
+
68
+ if [[ ! -d "$PROJECT_ROOT" ]]; then
69
+ echo "quality-gate: directory not found: $PROJECT_ROOT" >&2
70
+ exit 1
71
+ fi
72
+
73
+ cd "$PROJECT_ROOT"
74
+
75
+ # === Check 0: Toolkit Self-Validation ===
76
+ # Only runs when quality-gate is invoked from the toolkit itself
77
+ if [[ -f "$PROJECT_ROOT/scripts/validate-all.sh" ]]; then
78
+ echo "=== Quality Gate: Toolkit Validation ==="
79
+ if ! bash "$PROJECT_ROOT/scripts/validate-all.sh"; then
80
+ echo ""
81
+ echo "quality-gate: FAILED at toolkit validation"
82
+ exit 1
83
+ fi
84
+ fi
85
+
86
+ # === Check 1: Lesson check on changed files ===
87
+ echo "=== Quality Gate: Lesson Check ==="
88
+ changed_files=$(git diff --name-only 2>/dev/null || true)
89
+ if [[ -n "$changed_files" ]]; then
90
+ # Use an array to avoid word-splitting on filenames with spaces (#5).
91
+ readarray -t changed_array <<< "$changed_files"
92
+ if ! "$SCRIPT_DIR/lesson-check.sh" "${changed_array[@]}"; then
93
+ echo ""
94
+ echo "quality-gate: FAILED at lesson check"
95
+ exit 1
96
+ fi
97
+ else
98
+ echo "lesson-check: no changed files — skipped"
99
+ fi
100
+
101
+ # === Check 2: Lint Check (skipped with --quick) ===
102
+ if [[ "$QUICK" != true ]]; then
103
+ echo ""
104
+ echo "=== Quality Gate: Lint Check ==="
105
+ lint_ran=0
106
+
107
+ case "$(detect_project_type "$PROJECT_ROOT")" in
108
+ python)
109
+ if command -v ruff >/dev/null 2>&1; then
110
+ echo "Running: ruff check --select E,W,F"
111
+ if ! ruff check --select E,W,F "$PROJECT_ROOT" 2>/dev/null; then
112
+ echo ""
113
+ echo "quality-gate: FAILED at lint check"
114
+ exit 1
115
+ fi
116
+ lint_ran=1
117
+ else
118
+ echo "ruff not installed — skipping Python lint"
119
+ fi
120
+ ;;
121
+ node)
122
+ if [[ -f "$PROJECT_ROOT/.eslintrc" || -f "$PROJECT_ROOT/.eslintrc.js" || -f "$PROJECT_ROOT/.eslintrc.json" || -f "$PROJECT_ROOT/eslint.config.js" ]]; then
123
+ echo "Running: npx eslint"
124
+ if ! npx eslint "$PROJECT_ROOT" 2>/dev/null; then
125
+ echo ""
126
+ echo "quality-gate: FAILED at lint check"
127
+ exit 1
128
+ fi
129
+ lint_ran=1
130
+ else
131
+ echo "No eslint config found — skipping Node lint"
132
+ fi
133
+ ;;
134
+ esac
135
+
136
+ if [[ $lint_ran -eq 0 ]]; then
137
+ echo "No linter configured — skipped"
138
+ fi
139
+ fi
140
+
141
+ # === Check 2.5: ast-grep structural analysis (optional, advisory) ===
142
+ if [[ "$QUICK" != true ]]; then
143
+ echo ""
144
+ echo "=== Quality Gate: Structural Analysis (ast-grep) ==="
145
+ if command -v ast-grep >/dev/null 2>&1; then
146
+ PATTERNS_DIR="$SCRIPT_DIR/patterns"
147
+ ast_violations=0
148
+ if [[ -d "$PATTERNS_DIR" ]]; then
149
+ for pattern_file in "$PATTERNS_DIR"/*.yml; do
150
+ [[ -f "$pattern_file" ]] || continue
151
+ matches=$(ast-grep scan --rule "$pattern_file" "$PROJECT_ROOT" 2>/dev/null || true)
152
+ if [[ -n "$matches" ]]; then
153
+ echo "WARNING: $(basename "$pattern_file" .yml): $(echo "$matches" | wc -l) matches"
154
+ echo "$matches" | head -3
155
+ ast_violations=$((ast_violations + 1))
156
+ fi
157
+ done
158
+ fi
159
+ if [[ $ast_violations -gt 0 ]]; then
160
+ echo "ast-grep: $ast_violations pattern(s) matched (advisory)"
161
+ else
162
+ echo "ast-grep: clean"
163
+ fi
164
+ else
165
+ echo "ast-grep not installed — skipping structural analysis"
166
+ fi
167
+ fi
168
+
169
+ # === Check 2.7: Module size check (advisory) ===
170
+ if [[ "$QUICK" != true ]]; then
171
+ echo ""
172
+ echo "=== Quality Gate: Module Size Check ==="
173
+ if [[ -x "$SCRIPT_DIR/module-size-check.sh" ]]; then
174
+ _size_exit=0
175
+ "$SCRIPT_DIR/module-size-check.sh" --project-root "$PROJECT_ROOT" || _size_exit=$?
176
+ if [[ $_size_exit -ne 0 ]]; then
177
+ echo "module-size-check: $( [ $_size_exit -eq 1 ] && echo "oversized modules detected (advisory)" || echo "error (exit $_size_exit)")"
178
+ fi
179
+ else
180
+ echo "module-size-check.sh not found — skipped"
181
+ fi
182
+ fi
183
+
184
+ # === Check 3: Project test suite (auto-detect) ===
185
+ echo ""
186
+ echo "=== Quality Gate: Test Suite ==="
187
+ test_ran=0
188
+
189
+ project_type=$(detect_project_type "$PROJECT_ROOT")
190
+ case "$project_type" in
191
+ python)
192
+ echo "Detected: pytest project"
193
+ .venv/bin/python -m pytest --timeout=120 -x -q
194
+ test_ran=1
195
+ ;;
196
+ node)
197
+ if grep -q '"test"' "$PROJECT_ROOT/package.json" 2>/dev/null; then
198
+ echo "Detected: npm project"
199
+ npm test
200
+ test_ran=1
201
+ fi
202
+ ;;
203
+ make)
204
+ if grep -q '^test:' "$PROJECT_ROOT/Makefile" 2>/dev/null; then
205
+ echo "Detected: Makefile project"
206
+ make test
207
+ test_ran=1
208
+ fi
209
+ ;;
210
+ bash)
211
+ if [[ -x "$PROJECT_ROOT/scripts/tests/run-all-tests.sh" ]]; then
212
+ echo "Detected: bash project (run-all-tests.sh)"
213
+ "$PROJECT_ROOT/scripts/tests/run-all-tests.sh"
214
+ test_ran=1
215
+ fi
216
+ ;;
217
+ esac
218
+
219
+ if [[ $test_ran -eq 0 ]]; then
220
+ echo "No test suite detected (no pyproject.toml/setup.py/pytest.ini, no npm test script, no Makefile test target) — skipped"
221
+ fi
222
+
223
+ # === Check 4: License Check (only with --with-license, skipped with --quick) ===
224
+ if [[ "$WITH_LICENSE" == true ]]; then
225
+ echo ""
226
+ echo "=== Quality Gate: License Check ==="
227
+ if ! "$SCRIPT_DIR/license-check.sh" --project-root "$PROJECT_ROOT"; then
228
+ echo "quality-gate: FAILED at license check"
229
+ exit 1
230
+ fi
231
+ fi
232
+
233
+ # === Check 5: Memory warning (advisory only) ===
234
+ echo ""
235
+ echo "=== Quality Gate: Memory Check ==="
236
+ _mem_exit=0
237
+ check_memory_available 4 || _mem_exit=$?
238
+ if [[ $_mem_exit -eq 0 ]]; then
239
+ available_mb=$(free -m 2>/dev/null | awk '/Mem:/{print $7}')
240
+ available_display=$(awk "BEGIN {printf \"%.1f\", ${available_mb:-0} / 1024}")
241
+ echo "Memory OK (${available_display}G available)"
242
+ elif [[ $_mem_exit -eq 2 ]]; then
243
+ echo "WARNING: Memory check skipped (cannot determine available memory)"
244
+ else
245
+ echo "WARNING: Consider -n 0 for pytest"
246
+ fi
247
+
248
+ echo ""
249
+ echo "quality-gate: ALL PASSED"
250
+
251
+ # === Telemetry capture (append batch result) ===
252
+ # Only record if TELEMETRY_BATCH_NUMBER is set (called from run-plan context)
253
+ if [[ -n "${TELEMETRY_BATCH_NUMBER:-}" ]]; then
254
+ "$SCRIPT_DIR/telemetry.sh" record \
255
+ --project-root "$PROJECT_ROOT" \
256
+ --batch-number "${TELEMETRY_BATCH_NUMBER}" \
257
+ --passed true \
258
+ --strategy "${TELEMETRY_STRATEGY:-unknown}" \
259
+ --duration "${TELEMETRY_DURATION:-0}" \
260
+ --cost "${TELEMETRY_COST:-0}" \
261
+ --test-delta "${TELEMETRY_TEST_DELTA:-0}" \
262
+ --batch-type "${TELEMETRY_BATCH_TYPE:-unknown}" \
263
+ 2>/dev/null || true # Never fail the gate for telemetry errors
264
+ fi
265
+
266
+ exit 0
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env bash
2
+ # research-gate.sh — Blocks PRD generation if research has unresolved blocking issues
3
+ #
4
+ # Usage: research-gate.sh <research-json> [--force]
5
+ #
6
+ # Reads tasks/research-<slug>.json and checks:
7
+ # - File exists and is valid JSON
8
+ # - No blocking_issues with resolved: false
9
+ #
10
+ # Exit 0 = clear (proceed to PRD)
11
+ # Exit 1 = blocked (unresolved issues)
12
+ # --force = override (exit 0 regardless, with warning)
13
+
14
+ set -euo pipefail
15
+
16
+ FORCE=false
17
+
18
+ usage() {
19
+ cat <<'EOF'
20
+ research-gate.sh — Research phase gate for PRD generation
21
+
22
+ USAGE:
23
+ research-gate.sh <research-json> [--force]
24
+
25
+ OPTIONS:
26
+ --force Override blocking issues (exit 0 with warning)
27
+ -h, --help Show this help
28
+
29
+ EXIT CODES:
30
+ 0 Clear — no unresolved blocking issues
31
+ 1 Blocked — unresolved blocking issues found
32
+ EOF
33
+ }
34
+
35
+ # Parse args
36
+ RESEARCH_FILE=""
37
+ while [[ $# -gt 0 ]]; do
38
+ case $1 in
39
+ --force) FORCE=true; shift ;;
40
+ -h|--help) usage; exit 0 ;;
41
+ -*) echo "Unknown option: $1" >&2; exit 1 ;;
42
+ *) RESEARCH_FILE="$1"; shift ;;
43
+ esac
44
+ done
45
+
46
+ if [[ -z "$RESEARCH_FILE" ]]; then
47
+ echo "Error: research JSON file required" >&2
48
+ echo "Usage: research-gate.sh <research-json> [--force]" >&2
49
+ exit 1
50
+ fi
51
+
52
+ if [[ ! -f "$RESEARCH_FILE" ]]; then
53
+ echo "Error: file not found: $RESEARCH_FILE" >&2
54
+ exit 1
55
+ fi
56
+
57
+ # Validate JSON
58
+ if ! jq empty "$RESEARCH_FILE" 2>/dev/null; then
59
+ echo "Error: invalid JSON: $RESEARCH_FILE" >&2
60
+ exit 1
61
+ fi
62
+
63
+ # Check for unresolved blocking issues
64
+ unresolved_count=$(jq '[.blocking_issues[]? | select(.resolved == false)] | length' "$RESEARCH_FILE" 2>/dev/null || echo "0")
65
+
66
+ if [[ "$unresolved_count" -gt 0 ]]; then
67
+ echo "RESEARCH GATE: $unresolved_count unresolved blocking issue(s)"
68
+ jq -r '.blocking_issues[]? | select(.resolved == false) | " - \(.issue)"' "$RESEARCH_FILE" 2>/dev/null
69
+
70
+ if [[ "$FORCE" == "true" ]]; then
71
+ echo ""
72
+ echo "WARNING: --force used, proceeding despite blocking issues"
73
+ exit 0
74
+ else
75
+ echo ""
76
+ echo "Resolve blocking issues or use --force to override"
77
+ exit 1
78
+ fi
79
+ fi
80
+
81
+ # Check for warnings (informational, never blocks)
82
+ warning_count=$(jq '[.warnings[]?] | length' "$RESEARCH_FILE" 2>/dev/null || echo "0")
83
+ if [[ "$warning_count" -gt 0 ]]; then
84
+ echo "RESEARCH GATE: clear ($warning_count warning(s))"
85
+ jq -r '.warnings[]? | " ⚠ \(.)"' "$RESEARCH_FILE" 2>/dev/null
86
+ else
87
+ echo "RESEARCH GATE: clear (no blocking issues, no warnings)"
88
+ fi
89
+
90
+ exit 0
@@ -0,0 +1,329 @@
1
+ #!/usr/bin/env bash
2
+ # run-plan.sh — Execute implementation plans via headless Claude batches
3
+ #
4
+ # Usage:
5
+ # run-plan.sh <plan-file> [options]
6
+ # run-plan.sh --resume [options]
7
+ #
8
+ # Modes:
9
+ # headless (default) — bash loop calling claude -p per batch
10
+ # team — prints launch command for Claude agent team mode
11
+ # competitive — prints launch command for competitive agent mode
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
15
+
16
+ # --- Signal handling ---
17
+ # Log unexpected exits for diagnostics (silent death prevention)
18
+ _run_plan_exit_code=0
19
+ _run_plan_exit_logged=false
20
+ _log_exit() {
21
+ local code=${1:-$?}
22
+ [[ "$_run_plan_exit_logged" == true ]] && return
23
+ _run_plan_exit_logged=true
24
+ if [[ $code -ne 0 ]]; then
25
+ echo "" >&2
26
+ echo "run-plan: EXIT with code $code at $(date -u +%Y-%m-%dT%H:%M:%SZ)" >&2
27
+ # Print last few lines of bash call stack
28
+ local i
29
+ for ((i = 0; i < ${#FUNCNAME[@]}; i++)); do
30
+ echo " ${BASH_SOURCE[$i]:-unknown}:${BASH_LINENO[$i]:-?} in ${FUNCNAME[$i]:-main}" >&2
31
+ done
32
+ fi
33
+ }
34
+ trap '_log_exit $?' EXIT
35
+
36
+ # Ignore HUP and PIPE so background execution survives terminal disconnect
37
+ # and broken pipe from task manager stdout (confirmed root cause: exit 141 = SIGPIPE)
38
+ trap '' HUP PIPE
39
+
40
+ # Source all lib functions
41
+ source "$SCRIPT_DIR/lib/run-plan-parser.sh"
42
+ source "$SCRIPT_DIR/lib/run-plan-state.sh"
43
+ source "$SCRIPT_DIR/lib/run-plan-quality-gate.sh"
44
+ source "$SCRIPT_DIR/lib/run-plan-notify.sh"
45
+ source "$SCRIPT_DIR/lib/run-plan-prompt.sh"
46
+ source "$SCRIPT_DIR/lib/progress-writer.sh"
47
+ source "$SCRIPT_DIR/lib/run-plan-echo-back.sh"
48
+ source "$SCRIPT_DIR/lib/run-plan-sampling.sh"
49
+ source "$SCRIPT_DIR/lib/run-plan-headless.sh"
50
+ source "$SCRIPT_DIR/lib/run-plan-context.sh"
51
+ source "$SCRIPT_DIR/lib/progress-writer.sh"
52
+ source "$SCRIPT_DIR/lib/run-plan-scoring.sh"
53
+ source "$SCRIPT_DIR/lib/cost-tracking.sh"
54
+ source "$SCRIPT_DIR/lib/run-plan-team.sh"
55
+ source "$SCRIPT_DIR/lib/thompson-sampling.sh"
56
+
57
+ # --- Defaults ---
58
+ PLAN_FILE=""
59
+ MODE="headless"
60
+ START_BATCH=""
61
+ END_BATCH=""
62
+ WORKTREE="$(pwd)"
63
+ PYTHON="python3"
64
+ QUALITY_GATE_CMD="$SCRIPT_DIR/quality-gate.sh --project-root ."
65
+ ON_FAILURE="stop"
66
+ MAX_RETRIES=2
67
+ COMPETITIVE_BATCHES=""
68
+ SAMPLE_COUNT=0 # 0 = disabled
69
+ NOTIFY=false
70
+ VERIFY=false
71
+ RESUME=false
72
+ SKIP_PLAN_QUALITY=false
73
+ SKIP_ECHO_BACK=false
74
+ STRICT_ECHO_BACK=false
75
+ MAB=false
76
+ MAX_BUDGET=""
77
+
78
+ # --- Usage ---
79
+ usage() {
80
+ cat <<'USAGE'
81
+ run-plan — Execute implementation plans via headless Claude batches
82
+
83
+ Usage:
84
+ run-plan.sh <plan-file> [options]
85
+ run-plan.sh --resume [options]
86
+
87
+ Options:
88
+ --mode <headless|team|competitive> Execution mode (default: headless)
89
+ --start-batch N First batch to execute
90
+ --end-batch N Last batch to execute
91
+ --worktree <path> Working directory (default: cwd)
92
+ --python <path> Python interpreter (default: python3)
93
+ --quality-gate <cmd> Quality gate command
94
+ (default: "scripts/quality-gate.sh --project-root .")
95
+ --on-failure <stop|skip|retry> Failure handling (default: stop)
96
+ --max-retries N Max retries per batch (default: 2)
97
+ --competitive-batches N,N,... Batches for competitive mode
98
+ --sample N Parallel patch sampling (N candidates, default 3)
99
+ --no-sample Disable sampling (default)
100
+ --notify Send Telegram notifications
101
+ --verify Run verification after all batches
102
+ --skip-plan-quality Skip plan quality scorecard check
103
+ --skip-echo-back Skip spec echo-back verification
104
+ --resume Resume from saved state
105
+ --max-budget <dollars> Stop if total cost exceeds this amount
106
+ --skip-echo-back Disable echo-back spec check entirely
107
+ --strict-echo-back Make echo-back blocking (aborts batch on mismatch)
108
+ --mab Enable MAB routing (competing agents via Thompson Sampling)
109
+ -h, --help Show this help message
110
+
111
+ Modes:
112
+ headless Bash loop calling claude -p per batch (runs locally)
113
+ team Multi-agent team mode (prints Claude launch command)
114
+ competitive Competitive agent mode (prints Claude launch command)
115
+
116
+ Examples:
117
+ run-plan.sh docs/plans/2026-02-20-feature.md
118
+ run-plan.sh docs/plans/2026-02-20-feature.md --mode headless --start-batch 2
119
+ run-plan.sh --resume --worktree /path/to/worktree
120
+ run-plan.sh docs/plans/feature.md --on-failure retry --max-retries 3 --notify
121
+ USAGE
122
+ }
123
+
124
+ # --- Argument parsing ---
125
+ # shellcheck disable=SC2034 # Globals consumed by sourced lib scripts
126
+ parse_args() {
127
+ while [[ $# -gt 0 ]]; do
128
+ case "$1" in
129
+ -h|--help)
130
+ usage
131
+ exit 0
132
+ ;;
133
+ --mode)
134
+ MODE="$2"; shift 2
135
+ ;;
136
+ --start-batch)
137
+ START_BATCH="$2"; shift 2
138
+ ;;
139
+ --end-batch)
140
+ END_BATCH="$2"; shift 2
141
+ ;;
142
+ --worktree)
143
+ WORKTREE="$2"; shift 2
144
+ ;;
145
+ --python)
146
+ PYTHON="$2"; shift 2
147
+ ;;
148
+ --quality-gate)
149
+ QUALITY_GATE_CMD="$2"; shift 2
150
+ ;;
151
+ --on-failure)
152
+ ON_FAILURE="$2"; shift 2
153
+ ;;
154
+ --max-retries)
155
+ MAX_RETRIES="$2"; shift 2
156
+ ;;
157
+ --competitive-batches)
158
+ COMPETITIVE_BATCHES="$2"; shift 2
159
+ ;;
160
+ --sample)
161
+ SAMPLE_COUNT="${2:-3}"; shift 2
162
+ ;;
163
+ --no-sample)
164
+ SAMPLE_COUNT=0; shift
165
+ ;;
166
+ --notify)
167
+ NOTIFY=true; shift
168
+ ;;
169
+ --verify)
170
+ VERIFY=true; shift
171
+ ;;
172
+ --skip-plan-quality)
173
+ SKIP_PLAN_QUALITY=true; shift
174
+ ;;
175
+ --skip-echo-back)
176
+ SKIP_ECHO_BACK=true; shift
177
+ ;;
178
+ --resume)
179
+ RESUME=true; shift
180
+ ;;
181
+ --max-budget)
182
+ MAX_BUDGET="$2"; shift 2
183
+ ;;
184
+ --skip-echo-back) SKIP_ECHO_BACK=true; shift ;;
185
+ --strict-echo-back) STRICT_ECHO_BACK=true; shift ;;
186
+ --mab) MAB=true; shift ;;
187
+ -*)
188
+ echo "ERROR: Unknown option: $1" >&2
189
+ usage >&2
190
+ exit 1
191
+ ;;
192
+ *)
193
+ # Positional arg = plan file
194
+ if [[ -z "$PLAN_FILE" ]]; then
195
+ PLAN_FILE="$1"
196
+ else
197
+ echo "ERROR: Unexpected argument: $1" >&2
198
+ exit 1
199
+ fi
200
+ shift
201
+ ;;
202
+ esac
203
+ done
204
+ }
205
+
206
+ # --- Validation ---
207
+ validate_args() {
208
+ # Resume mode: load state file
209
+ if [[ "$RESUME" == true ]]; then
210
+ local state_file="$WORKTREE/.run-plan-state.json"
211
+ if [[ ! -f "$state_file" ]]; then
212
+ echo "ERROR: No state file found at $state_file" >&2
213
+ echo "Cannot resume without a previous run." >&2
214
+ exit 1
215
+ fi
216
+ # Load defaults from state
217
+ if [[ -z "$PLAN_FILE" ]]; then
218
+ PLAN_FILE=$(read_state_field "$WORKTREE" "plan_file")
219
+ fi
220
+ if [[ -z "$MODE" || "$MODE" == "headless" ]]; then
221
+ local saved_mode
222
+ saved_mode=$(read_state_field "$WORKTREE" "mode")
223
+ if [[ -n "$saved_mode" && "$saved_mode" != "null" ]]; then
224
+ MODE="$saved_mode"
225
+ fi
226
+ fi
227
+ if [[ -z "$START_BATCH" ]]; then
228
+ START_BATCH=$(read_state_field "$WORKTREE" "current_batch")
229
+ fi
230
+ fi
231
+
232
+ # Must have a plan file
233
+ if [[ -z "$PLAN_FILE" ]]; then
234
+ echo "ERROR: No plan file specified. Use: run-plan.sh <plan-file> or --resume" >&2
235
+ exit 1
236
+ fi
237
+
238
+ # Plan file must exist
239
+ if [[ ! -f "$PLAN_FILE" ]]; then
240
+ echo "ERROR: Plan file not found: $PLAN_FILE" >&2
241
+ exit 1
242
+ fi
243
+
244
+ # Validate mode
245
+ case "$MODE" in
246
+ headless|team|competitive) ;;
247
+ *)
248
+ echo "ERROR: Invalid mode: $MODE (must be headless, team, or competitive)" >&2
249
+ exit 1
250
+ ;;
251
+ esac
252
+
253
+ # Validate on-failure
254
+ case "$ON_FAILURE" in
255
+ stop|skip|retry) ;;
256
+ *)
257
+ echo "ERROR: Invalid --on-failure: $ON_FAILURE (must be stop, skip, or retry)" >&2
258
+ exit 1
259
+ ;;
260
+ esac
261
+
262
+ # Set batch range defaults
263
+ local total
264
+ total=$(count_batches "$PLAN_FILE")
265
+ if [[ -z "$START_BATCH" ]]; then
266
+ START_BATCH=1
267
+ fi
268
+ if [[ -z "$END_BATCH" ]]; then
269
+ END_BATCH="$total"
270
+ fi
271
+ }
272
+
273
+ # --- Banner ---
274
+ print_banner() {
275
+ local total
276
+ total=$(count_batches "$PLAN_FILE")
277
+ local plan_display
278
+ plan_display=$(basename "$PLAN_FILE")
279
+
280
+ cat <<BANNER
281
+ ╔══════════════════════════════════════════════════════╗
282
+ ║ run-plan — $MODE mode
283
+ ║ Plan: $plan_display
284
+ ║ Batches: $START_BATCH → $END_BATCH (of $total)
285
+ ║ Worktree: $WORKTREE
286
+ ╚══════════════════════════════════════════════════════╝
287
+ BANNER
288
+ }
289
+
290
+ # --- Mode stubs ---
291
+ run_mode_competitive() {
292
+ echo "Competitive mode requires a Claude session with agent teams enabled."
293
+ echo ""
294
+ echo "Launch command:"
295
+ echo " CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 claude -p \"/run-plan $PLAN_FILE --mode competitive --start-batch $START_BATCH --end-batch $END_BATCH --worktree $WORKTREE\" --allowedTools '*' --permission-mode bypassPermissions"
296
+ }
297
+
298
+ # --- Main ---
299
+ main() {
300
+ parse_args "$@"
301
+ validate_args
302
+ print_banner
303
+
304
+ # Plan quality gate (skip on resume or explicit flag)
305
+ if [[ "$SKIP_PLAN_QUALITY" != true && "$RESUME" != true ]]; then
306
+ echo ""
307
+ echo "Running plan quality check..."
308
+ if ! bash "$SCRIPT_DIR/validate-plan-quality.sh" "$PLAN_FILE" --min-score 60; then
309
+ echo ""
310
+ echo "Plan quality below threshold. Use --skip-plan-quality to override."
311
+ exit 1
312
+ fi
313
+ echo ""
314
+ fi
315
+
316
+ case "$MODE" in
317
+ headless)
318
+ run_mode_headless
319
+ ;;
320
+ team)
321
+ run_mode_team
322
+ ;;
323
+ competitive)
324
+ run_mode_competitive
325
+ ;;
326
+ esac
327
+ }
328
+
329
+ main "$@"