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,81 @@
1
+ #!/usr/bin/env bash
2
+ # run-plan-parser.sh — Parse markdown plan files into batch/task structures
3
+ #
4
+ # Plan format:
5
+ # ## Batch N: Title <- batch boundary
6
+ # ### Task M: Name <- task within batch
7
+ # [full text...] <- extracted verbatim
8
+ #
9
+ # Functions:
10
+ # count_batches <plan_file> -> number of batches
11
+ # get_batch_title <plan_file> <batch_num> -> batch title text
12
+ # get_batch_text <plan_file> <batch_num> -> full batch content (tasks + text)
13
+ # get_batch_task_count <plan_file> <batch_num> -> number of tasks in batch
14
+ # is_critical_batch <plan_file> <batch_num> -> exit 0 if tagged CRITICAL
15
+
16
+ count_batches() {
17
+ local plan_file="$1"
18
+ local count
19
+ count=$(grep -cE '^## Batch [0-9]+' "$plan_file" 2>/dev/null || true)
20
+ echo "${count:-0}"
21
+ }
22
+
23
+ get_batch_title() {
24
+ local plan_file="$1" batch_num="$2"
25
+ local line
26
+ line=$(grep -E "^## Batch ${batch_num}:" "$plan_file" 2>/dev/null | head -1)
27
+ if [[ -z "$line" ]]; then
28
+ echo ""
29
+ return
30
+ fi
31
+ # Strip "## Batch N: " prefix using bash parameter expansion
32
+ echo "${line#\#\# Batch ${batch_num}: }"
33
+ }
34
+
35
+ get_batch_text() {
36
+ local plan_file="$1" batch_num="$2"
37
+ # Extract everything after "## Batch N" up to the next "## Batch" or EOF
38
+ # Uses POSIX-compatible awk: $3 + 0 extracts batch number
39
+ awk -v batch="$batch_num" '
40
+ /^## Batch [0-9]+/ {
41
+ n = $3 + 0
42
+ if (n == batch) { printing = 1; next }
43
+ else if (printing) { exit }
44
+ }
45
+ printing { print }
46
+ ' "$plan_file"
47
+ }
48
+
49
+ get_batch_task_count() {
50
+ local plan_file="$1" batch_num="$2"
51
+ local text count
52
+ text=$(get_batch_text "$plan_file" "$batch_num")
53
+ if [[ -z "$text" ]]; then
54
+ echo "0"
55
+ return
56
+ fi
57
+ count=$(echo "$text" | grep -cE '^### Task [0-9]+' 2>/dev/null || true)
58
+ echo "${count:-0}"
59
+ }
60
+
61
+ get_batch_context_refs() {
62
+ local plan_file="$1" batch_num="$2"
63
+ local batch_text
64
+ batch_text=$(get_batch_text "$plan_file" "$batch_num")
65
+ # Extract "context_refs: file1, file2, ..." line
66
+ local refs_line
67
+ refs_line=$(echo "$batch_text" | grep -E '^context_refs:' | head -1 || true)
68
+ if [[ -z "$refs_line" ]]; then
69
+ echo ""
70
+ return
71
+ fi
72
+ # Strip "context_refs: " prefix and split on comma
73
+ echo "${refs_line#context_refs: }" | tr ',' '\n' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//'
74
+ }
75
+
76
+ is_critical_batch() {
77
+ local plan_file="$1" batch_num="$2"
78
+ local header
79
+ header=$(grep -E "^## Batch ${batch_num}:" "$plan_file" 2>/dev/null | head -1)
80
+ [[ "$header" == *"CRITICAL"* ]]
81
+ }
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env bash
2
+ # run-plan-prompt.sh — Build prompts for headless claude -p batch execution
3
+ #
4
+ # Requires run-plan-parser.sh to be sourced first (provides get_batch_title, get_batch_text)
5
+ #
6
+ # Functions:
7
+ # build_stable_prefix <plan_file> <worktree> <python> <quality_gate_cmd>
8
+ # -> stable portion of the prompt (plan identity, worktree, python, branch, TDD rules)
9
+ # -> safe to cache across batches; does NOT include prev_test_count or other per-batch data
10
+ # build_variable_suffix <plan_file> <batch_num> <worktree> <prev_test_count>
11
+ # -> per-batch portion of the prompt (tasks, commits, progress, gate results, test count)
12
+ # build_batch_prompt <plan_file> <batch_num> <worktree> <python> <quality_gate_cmd> <prev_test_count>
13
+ # -> full self-contained prompt (stable prefix + variable suffix) for claude -p
14
+ # generate_agents_md <plan_file> <worktree> <mode>
15
+ # -> writes AGENTS.md to worktree for agent team awareness
16
+
17
+ # build_stable_prefix — assemble the stable (batch-invariant) portion of a batch prompt.
18
+ #
19
+ # Stability contract: output depends only on plan_file path, worktree path, python path,
20
+ # quality_gate_cmd, and the git branch name. None of these change between batches in a
21
+ # normal run, so the result may be cached and reused across batches.
22
+ #
23
+ # NOTE: prev_test_count intentionally excluded — it changes each batch. It belongs in
24
+ # build_variable_suffix (see issue #48).
25
+ #
26
+ # Args: <plan_file> <worktree> <python> <quality_gate_cmd>
27
+ build_stable_prefix() {
28
+ local plan_file="$1"
29
+ local worktree="$2"
30
+ local python="$3"
31
+ local quality_gate_cmd="$4"
32
+
33
+ local branch
34
+
35
+ # #46: Check worktree exists before calling git. Log a warning if git fails so
36
+ # the caller knows the branch name is unreliable rather than silently caching "unknown".
37
+ if [[ ! -d "$worktree" ]]; then
38
+ echo "WARNING: worktree directory does not exist: $worktree" >&2
39
+ branch="unknown"
40
+ else
41
+ branch=$(git -C "$worktree" branch --show-current 2>/dev/null) || {
42
+ echo "WARNING: git branch failed for worktree: $worktree — using 'unknown'" >&2
43
+ branch="unknown"
44
+ }
45
+ # git can succeed but print nothing (detached HEAD)
46
+ [[ -z "$branch" ]] && branch="unknown"
47
+ fi
48
+
49
+ cat <<PREFIX
50
+ Working directory: ${worktree}
51
+ Python: ${python}
52
+ Branch: ${branch}
53
+
54
+ Requirements:
55
+ - TDD: write test -> verify fail -> implement -> verify pass -> commit each task
56
+ - After all tasks: run quality gate (${quality_gate_cmd})
57
+ - Update progress.txt with batch summary and commit
58
+ PREFIX
59
+ }
60
+
61
+ # build_variable_suffix — assemble the per-batch (variable) portion of a batch prompt.
62
+ #
63
+ # Contains everything that can differ between batches: batch number, title, task text,
64
+ # recent commits, progress tail, previous quality gate result, context refs, and the
65
+ # current prev_test_count (which increases after each batch).
66
+ #
67
+ # Args: <plan_file> <batch_num> <worktree> <prev_test_count>
68
+ build_variable_suffix() {
69
+ local plan_file="$1"
70
+ local batch_num="$2"
71
+ local worktree="$3"
72
+ local prev_test_count="$4"
73
+
74
+ local title batch_text recent_commits progress_tail prev_gate
75
+
76
+ title=$(get_batch_title "$plan_file" "$batch_num")
77
+ batch_text=$(get_batch_text "$plan_file" "$batch_num")
78
+
79
+ # Cross-batch context: recent commits
80
+ recent_commits=$(git -C "$worktree" log --oneline -5 2>/dev/null || echo "(no commits)")
81
+
82
+ # Cross-batch context: progress.txt tail
83
+ # #50: File existence is already checked before calling tail.
84
+ # Remove 2>/dev/null || true — permission errors on a confirmed-existing file should
85
+ # propagate so the caller sees the real error rather than silently getting no progress.
86
+ progress_tail=""
87
+ if [[ -f "$worktree/progress.txt" ]]; then
88
+ progress_tail=$(tail -20 "$worktree/progress.txt")
89
+ fi
90
+
91
+ # Cross-batch context: previous quality gate result
92
+ # #47: Distinguish "no state file / no key" (expected) from "corrupted JSON" (error).
93
+ # jq returns exit 5 on parse failure. Check exit code and warn on corruption so the
94
+ # caller knows prev_gate is empty due to an error, not just an absent first batch.
95
+ prev_gate=""
96
+ if [[ -f "$worktree/.run-plan-state.json" ]]; then
97
+ local jq_exit=0
98
+ prev_gate=$(jq -r '.last_quality_gate // empty' "$worktree/.run-plan-state.json" 2>/dev/null) || jq_exit=$?
99
+ if [[ $jq_exit -ne 0 ]]; then
100
+ echo "WARNING: .run-plan-state.json is corrupted (jq exit $jq_exit) — proceeding without previous gate context" >&2
101
+ prev_gate=""
102
+ fi
103
+ fi
104
+
105
+ # Cross-batch context: referenced files from context_refs
106
+ local context_refs_content=""
107
+ local refs
108
+ refs=$(get_batch_context_refs "$plan_file" "$batch_num")
109
+ if [[ -n "$refs" ]]; then
110
+ while IFS= read -r ref; do
111
+ [[ -z "$ref" ]] && continue
112
+ if [[ -f "$worktree/$ref" ]]; then
113
+ context_refs_content+="
114
+ --- $ref ---
115
+ $(head -100 "$worktree/$ref")
116
+ "
117
+ fi
118
+ done <<< "$refs"
119
+ fi
120
+
121
+ cat <<SUFFIX
122
+ You are implementing Batch ${batch_num}: ${title} from ${plan_file}.
123
+
124
+ Tasks in this batch:
125
+ ${batch_text}
126
+
127
+ Recent commits:
128
+ ${recent_commits}
129
+ $(if [[ -n "$progress_tail" ]]; then
130
+ echo "
131
+ Previous progress:
132
+ ${progress_tail}"
133
+ fi)
134
+ $(if [[ -n "$prev_gate" && "$prev_gate" != "null" ]]; then
135
+ echo "
136
+ Previous quality gate: ${prev_gate}"
137
+ fi)
138
+ $(if [[ -n "$context_refs_content" ]]; then
139
+ echo "
140
+ Referenced files from prior batches:
141
+ ${context_refs_content}"
142
+ fi)
143
+ - All ${prev_test_count}+ tests must pass
144
+ SUFFIX
145
+ }
146
+
147
+ # build_batch_prompt — full prompt for a single batch (stable prefix + variable suffix).
148
+ #
149
+ # Callers that run multiple batches should prefer calling build_stable_prefix once and
150
+ # caching the result, then calling build_variable_suffix per batch — see run-plan-headless.sh.
151
+ # This function is a convenience wrapper for single-batch callers and tests.
152
+ #
153
+ # Args: <plan_file> <batch_num> <worktree> <python> <quality_gate_cmd> <prev_test_count>
154
+ build_batch_prompt() {
155
+ local plan_file="$1"
156
+ local batch_num="$2"
157
+ local worktree="$3"
158
+ local python="$4"
159
+ local quality_gate_cmd="$5"
160
+ local prev_test_count="$6"
161
+
162
+ local stable_prefix variable_suffix
163
+ stable_prefix=$(build_stable_prefix "$plan_file" "$worktree" "$python" "$quality_gate_cmd")
164
+ variable_suffix=$(build_variable_suffix "$plan_file" "$batch_num" "$worktree" "$prev_test_count")
165
+
166
+ printf '%s\n\n%s\n' "$variable_suffix" "$stable_prefix"
167
+ }
168
+
169
+ # Generate AGENTS.md in the worktree for agent team awareness.
170
+ # Args: <plan_file> <worktree> <mode>
171
+ generate_agents_md() {
172
+ local plan_file="$1" worktree="$2" mode="${3:-headless}"
173
+
174
+ # Source parser if needed
175
+ type count_batches &>/dev/null || source "$(dirname "${BASH_SOURCE[0]}")/run-plan-parser.sh"
176
+
177
+ local total_batches
178
+ total_batches=$(count_batches "$plan_file")
179
+
180
+ local batch_info=""
181
+ for ((b = 1; b <= total_batches; b++)); do
182
+ local title
183
+ title=$(get_batch_title "$plan_file" "$b")
184
+ [[ -z "$title" ]] && continue
185
+ batch_info+="| $b | $title |"$'\n'
186
+ done
187
+
188
+ cat > "$worktree/AGENTS.md" << EOF
189
+ # Agent Configuration
190
+
191
+ **Plan:** $(basename "$plan_file")
192
+ **Mode:** $mode
193
+ **Total:** $total_batches batches
194
+
195
+ ## Tools Allowed
196
+
197
+ Bash, Read, Write, Edit, Grep, Glob
198
+
199
+ ## Permission Mode
200
+
201
+ bypassPermissions
202
+
203
+ ## Batches
204
+
205
+ | # | Title |
206
+ |---|-------|
207
+ ${batch_info}
208
+ ## Guidelines
209
+
210
+ - Run quality gate after each batch
211
+ - Commit after passing gate
212
+ - Append discoveries to progress.txt
213
+ - Do not modify files outside your batch scope
214
+ EOF
215
+ }
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env bash
2
+ # run-plan-quality-gate.sh — Quality gate runner for plan execution
3
+ #
4
+ # Wraps quality-gate.sh with test count regression detection + git status check.
5
+ # Runs between every batch in all modes.
6
+ #
7
+ # Functions:
8
+ # extract_test_count <test_output> -> parse "N passed" from pytest output
9
+ # check_test_count_regression <new_count> <previous_count> -> 0 if new >= previous, 1 otherwise
10
+ # check_git_clean <worktree> -> 0 if clean, 1 if dirty
11
+ # run_quality_gate <worktree> <quality_gate_cmd> <batch_num> [duration] -> full gate: cmd + regression + clean + state update
12
+ #
13
+ # Requires: run-plan-state.sh sourced for run_quality_gate (state functions)
14
+
15
+ QUALITY_GATE_SCRIPT="${QUALITY_GATE_SCRIPT:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../quality-gate.sh}"
16
+
17
+ # Extract passed test count from test output.
18
+ # Supports pytest ("N passed"), jest ("Tests: N passed"), go test ("ok" lines).
19
+ # Returns -1 if no recognized format found (signals "skip regression check").
20
+ extract_test_count() {
21
+ local output="$1"
22
+ local count
23
+
24
+ # 1. pytest: "N passed" (e.g., "85 passed" in "3 failed, 85 passed, 2 skipped in 30.1s")
25
+ count=$(echo "$output" | grep -oE '[0-9]+ passed' | tail -1 | grep -oE '^[0-9]+' || true)
26
+ if [[ -n "$count" ]]; then
27
+ echo "$count"
28
+ return
29
+ fi
30
+
31
+ # 2. jest: "Tests: N passed" (e.g., "Tests: 45 passed, 48 total")
32
+ count=$(echo "$output" | grep -oE 'Tests:[[:space:]]+([0-9]+ failed, )?[0-9]+ passed' | grep -oE '[0-9]+ passed' | grep -oE '^[0-9]+' || true)
33
+ if [[ -n "$count" ]]; then
34
+ echo "$count"
35
+ return
36
+ fi
37
+
38
+ # 3. go test: count "ok" lines (each = one passing package)
39
+ count=$(echo "$output" | grep -c '^ok' || true)
40
+ if [[ "$count" -gt 0 ]]; then
41
+ echo "$count"
42
+ return
43
+ fi
44
+
45
+ # 4. No recognized format — return -1 to signal "skip regression check"
46
+ echo "-1"
47
+ }
48
+
49
+ # Check for test count regression.
50
+ # Returns 0 if new_count >= previous_count, 1 otherwise.
51
+ # -1 means unrecognized format — skip regression check.
52
+ check_test_count_regression() {
53
+ local new_count="$1" previous_count="$2"
54
+ if [[ "$new_count" == "-1" || "$previous_count" == "-1" ]]; then
55
+ echo "INFO: Skipping test count regression check (unrecognized test format)" >&2
56
+ return 0
57
+ fi
58
+ if [[ "$new_count" -ge "$previous_count" ]]; then
59
+ return 0
60
+ else
61
+ echo "WARNING: Test count regression: $new_count < $previous_count (previous)" >&2
62
+ return 1
63
+ fi
64
+ }
65
+
66
+ # Check if worktree has uncommitted changes.
67
+ # Returns 0 if clean, 1 if dirty.
68
+ check_git_clean() {
69
+ local worktree="$1"
70
+ local status
71
+ status=$(git -C "$worktree" status --porcelain 2>/dev/null)
72
+ if [[ -z "$status" ]]; then
73
+ return 0
74
+ else
75
+ echo "WARNING: Worktree has uncommitted changes:" >&2
76
+ echo "$status" >&2
77
+ return 1
78
+ fi
79
+ }
80
+
81
+ # Run the full quality gate for a batch.
82
+ # Executes quality_gate_cmd, checks test regression, checks git clean, updates state.
83
+ # Returns 0 on pass, 1 on fail.
84
+ #
85
+ # Requires run-plan-state.sh functions: get_previous_test_count, complete_batch, set_quality_gate
86
+ run_quality_gate() {
87
+ local worktree="$1" quality_gate_cmd="$2" batch_num="$3" duration="${4:-0}"
88
+ local gate_output gate_exit test_count previous_count
89
+
90
+ echo "=== Quality Gate: Batch $batch_num ==="
91
+
92
+ # 1. Execute quality gate command in worktree.
93
+ # Use 'bash -c' rather than 'eval' to avoid command injection from the
94
+ # user-supplied --quality-gate CLI flag (#3). The command may contain
95
+ # shell features (pipes, redirects) so a simple array exec isn't viable,
96
+ # but 'bash -c' still runs in a fresh subshell which limits injection scope.
97
+ gate_output=$(cd "$worktree" && bash -c "$quality_gate_cmd" 2>&1) && gate_exit=0 || gate_exit=$?
98
+ echo "$gate_output"
99
+
100
+ if [[ $gate_exit -ne 0 ]]; then
101
+ echo ""
102
+ echo "QUALITY GATE FAILED: command exited $gate_exit"
103
+ set_quality_gate "$worktree" "$batch_num" "false" 0
104
+ return 1
105
+ fi
106
+
107
+ # 2. Extract test count from output
108
+ test_count=$(extract_test_count "$gate_output")
109
+ echo "Test count: $test_count"
110
+
111
+ # 3. Compare against previous batch count
112
+ previous_count=$(get_previous_test_count "$worktree")
113
+ if ! check_test_count_regression "$test_count" "$previous_count"; then
114
+ echo "QUALITY GATE FAILED: test count regression ($test_count < $previous_count)"
115
+ set_quality_gate "$worktree" "$batch_num" "false" "$test_count"
116
+ return 1
117
+ fi
118
+
119
+ # 4. Check git clean
120
+ if ! check_git_clean "$worktree"; then
121
+ echo "QUALITY GATE FAILED: uncommitted changes in worktree"
122
+ set_quality_gate "$worktree" "$batch_num" "false" "$test_count"
123
+ return 1
124
+ fi
125
+
126
+ # 5. Update state — batch complete, gate passed
127
+ complete_batch "$worktree" "$batch_num" "$test_count" "$duration"
128
+ set_quality_gate "$worktree" "$batch_num" "true" "$test_count"
129
+
130
+ echo "QUALITY GATE PASSED (batch $batch_num, $test_count tests)"
131
+ return 0
132
+ }