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,575 @@
1
+ #!/usr/bin/env bash
2
+ # mab-run.sh — MAB orchestrator: worktrees, competing agents, judge, merge
3
+ #
4
+ # Usage:
5
+ # mab-run.sh --plan <file> --batch <N> --work-unit <desc> --worktree <dir> [options]
6
+ # mab-run.sh --init-data --worktree <dir>
7
+ # mab-run.sh --help
8
+ #
9
+ # Options:
10
+ # --plan <file> Implementation plan file
11
+ # --batch <N> Batch number to execute
12
+ # --work-unit <desc> Work unit description
13
+ # --worktree <dir> Base worktree directory
14
+ # --dry-run Show planned actions without executing
15
+ # --init-data Initialize strategy-perf.json and mab-lessons.json
16
+ # --prd <file> PRD file path (optional)
17
+ # --quality-gate <cmd> Quality gate command
18
+ # -h, --help Show this help
19
+ set -euo pipefail
20
+
21
+ SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
22
+
23
+ # Source dependencies
24
+ source "$SCRIPT_DIR/lib/thompson-sampling.sh"
25
+ if [[ -f "$SCRIPT_DIR/lib/run-plan-scoring.sh" ]]; then
26
+ source "$SCRIPT_DIR/lib/run-plan-scoring.sh"
27
+ fi
28
+ if [[ -f "$SCRIPT_DIR/lib/run-plan-state.sh" ]]; then
29
+ source "$SCRIPT_DIR/lib/run-plan-state.sh"
30
+ fi
31
+
32
+ # --- Defaults ---
33
+ MAB_PLAN=""
34
+ MAB_BATCH=""
35
+ MAB_WORK_UNIT=""
36
+ MAB_WORKTREE=""
37
+ MAB_DRY_RUN=false
38
+ MAB_INIT_DATA=false
39
+ MAB_PRD=""
40
+ MAB_QUALITY_GATE="scripts/quality-gate.sh --project-root ."
41
+ MAB_SOURCE_ONLY=false
42
+
43
+ # --- Usage ---
44
+ mab_usage() {
45
+ cat <<'USAGE'
46
+ mab-run.sh — MAB orchestrator for competing agent strategies
47
+
48
+ Usage:
49
+ mab-run.sh --plan <file> --batch <N> --work-unit <desc> --worktree <dir> [options]
50
+ mab-run.sh --init-data --worktree <dir>
51
+
52
+ Runs two agents (superpowers + ralph) in parallel worktrees on the same work
53
+ unit. A judge agent evaluates both outputs. Quality gate override: if only one
54
+ agent passes, that agent wins regardless of judge verdict.
55
+
56
+ Options:
57
+ --plan <file> Implementation plan file
58
+ --batch <N> Batch number to execute
59
+ --work-unit <desc> Work unit description
60
+ --worktree <dir> Base worktree directory
61
+ --dry-run Show planned actions without executing
62
+ --init-data Initialize strategy-perf.json and mab-lessons.json
63
+ --prd <file> PRD file path (optional)
64
+ --quality-gate <cmd> Quality gate command
65
+ -h, --help Show this help
66
+ USAGE
67
+ }
68
+
69
+ # --- Argument parsing ---
70
+ parse_mab_args() {
71
+ while [[ $# -gt 0 ]]; do
72
+ case "$1" in
73
+ --source-only)
74
+ MAB_SOURCE_ONLY=true; shift ;;
75
+ -h|--help)
76
+ mab_usage; exit 0 ;;
77
+ --plan)
78
+ MAB_PLAN="$2"; shift 2 ;;
79
+ --batch)
80
+ MAB_BATCH="$2"; shift 2 ;;
81
+ --work-unit)
82
+ MAB_WORK_UNIT="$2"; shift 2 ;;
83
+ --worktree)
84
+ MAB_WORKTREE="$2"; shift 2 ;;
85
+ --dry-run)
86
+ MAB_DRY_RUN=true; shift ;;
87
+ --init-data)
88
+ MAB_INIT_DATA=true; shift ;;
89
+ --prd)
90
+ MAB_PRD="$2"; shift 2 ;;
91
+ --quality-gate)
92
+ MAB_QUALITY_GATE="$2"; shift 2 ;;
93
+ *)
94
+ echo "ERROR: Unknown option: $1" >&2
95
+ mab_usage >&2
96
+ exit 1 ;;
97
+ esac
98
+ done
99
+ }
100
+
101
+ # --- Validation ---
102
+ validate_mab_args() {
103
+ if [[ "$MAB_INIT_DATA" == true ]]; then
104
+ if [[ -z "$MAB_WORKTREE" ]]; then
105
+ echo "ERROR: --init-data requires --worktree" >&2
106
+ exit 1
107
+ fi
108
+ return
109
+ fi
110
+
111
+ if [[ -z "$MAB_PLAN" || ! -f "$MAB_PLAN" ]]; then
112
+ echo "ERROR: --plan file required and must exist" >&2
113
+ exit 1
114
+ fi
115
+
116
+ if [[ -z "$MAB_BATCH" ]]; then
117
+ echo "ERROR: --batch required" >&2
118
+ exit 1
119
+ fi
120
+
121
+ # Validate batch is numeric
122
+ if ! [[ "$MAB_BATCH" =~ ^[0-9]+$ ]]; then
123
+ echo "ERROR: --batch must be a number (got: $MAB_BATCH)" >&2
124
+ exit 1
125
+ fi
126
+
127
+ if [[ -z "$MAB_WORK_UNIT" ]]; then
128
+ echo "ERROR: --work-unit required" >&2
129
+ exit 1
130
+ fi
131
+
132
+ if [[ -z "$MAB_WORKTREE" ]]; then
133
+ echo "ERROR: --worktree required" >&2
134
+ exit 1
135
+ fi
136
+ }
137
+
138
+ # --- Template substitution ---
139
+ # Replaces {PLACEHOLDER} tokens in a prompt template with actual values.
140
+ #
141
+ # Args: <template> <work_unit> <prd_path> <arch_map_path> <mab_lessons> <quality_gate_cmd>
142
+ # Output: substituted string
143
+ assemble_agent_prompt() {
144
+ local template="$1"
145
+ local work_unit="$2"
146
+ local prd_path="${3:-}"
147
+ local arch_map_path="${4:-}"
148
+ local mab_lessons="${5:-}"
149
+ local quality_gate_cmd="${6:-}"
150
+
151
+ local result="$template"
152
+ result="${result//\{WORK_UNIT_DESCRIPTION\}/$work_unit}"
153
+ result="${result//\{PRD_PATH\}/$prd_path}"
154
+ result="${result//\{ARCH_MAP_PATH\}/$arch_map_path}"
155
+ result="${result//\{MAB_LESSONS\}/$mab_lessons}"
156
+ result="${result//\{QUALITY_GATE_CMD\}/$quality_gate_cmd}"
157
+
158
+ echo "$result"
159
+ }
160
+
161
+ # --- Gate override logic ---
162
+ # If only one agent passes the quality gate, that agent wins regardless of judge.
163
+ #
164
+ # Args: <gate_a_exit> <gate_b_exit> <judge_winner>
165
+ # Output: "agent-a" | "agent-b" | "none" | <judge_winner>
166
+ select_winner_with_gate_override() {
167
+ local gate_a="$1" gate_b="$2" judge_winner="$3"
168
+
169
+ local a_passed=false b_passed=false
170
+ [[ "$gate_a" -eq 0 ]] && a_passed=true
171
+ [[ "$gate_b" -eq 0 ]] && b_passed=true
172
+
173
+ if [[ "$a_passed" == true && "$b_passed" == false ]]; then
174
+ echo "agent-a"
175
+ elif [[ "$a_passed" == false && "$b_passed" == true ]]; then
176
+ echo "agent-b"
177
+ elif [[ "$a_passed" == false && "$b_passed" == false ]]; then
178
+ echo "none"
179
+ else
180
+ # Both passed — use judge verdict
181
+ echo "$judge_winner"
182
+ fi
183
+ }
184
+
185
+ # --- Create MAB worktrees ---
186
+ create_mab_worktrees() {
187
+ local base_worktree="$1" batch="$2"
188
+ local branch_a="mab-agent-a-batch-${batch}"
189
+ local branch_b="mab-agent-b-batch-${batch}"
190
+ local wt_a="$base_worktree/.mab-worktrees/agent-a"
191
+ local wt_b="$base_worktree/.mab-worktrees/agent-b"
192
+
193
+ mkdir -p "$base_worktree/.mab-worktrees"
194
+
195
+ # Clean up any leftover worktrees from previous runs
196
+ git -C "$base_worktree" worktree remove "$wt_a" --force 2>/dev/null || true
197
+ git -C "$base_worktree" worktree remove "$wt_b" --force 2>/dev/null || true
198
+ git -C "$base_worktree" branch -D "$branch_a" 2>/dev/null || true
199
+ git -C "$base_worktree" branch -D "$branch_b" 2>/dev/null || true
200
+
201
+ git -C "$base_worktree" worktree add "$wt_a" -b "$branch_a" HEAD 2>/dev/null
202
+ git -C "$base_worktree" worktree add "$wt_b" -b "$branch_b" HEAD 2>/dev/null
203
+
204
+ echo "$wt_a $wt_b"
205
+ }
206
+
207
+ # --- Run agents in parallel ---
208
+ run_agents_parallel() {
209
+ local wt_a="$1" wt_b="$2" prompt_a="$3" prompt_b="$4"
210
+ local log_a="$MAB_WORKTREE/logs/mab-batch-${MAB_BATCH}-agent-a.log"
211
+ local log_b="$MAB_WORKTREE/logs/mab-batch-${MAB_BATCH}-agent-b.log"
212
+
213
+ mkdir -p "$MAB_WORKTREE/logs"
214
+
215
+ echo " Running Agent A (superpowers) in $wt_a..."
216
+ (cd "$wt_a" && CLAUDECODE='' claude -p "$prompt_a" \
217
+ --allowedTools "Bash,Read,Write,Edit,Grep,Glob" \
218
+ --permission-mode bypassPermissions \
219
+ > "$log_a" 2>&1) &
220
+ local pid_a=$!
221
+
222
+ echo " Running Agent B (ralph) in $wt_b..."
223
+ (cd "$wt_b" && CLAUDECODE='' claude -p "$prompt_b" \
224
+ --allowedTools "Bash,Read,Write,Edit,Grep,Glob" \
225
+ --permission-mode bypassPermissions \
226
+ > "$log_b" 2>&1) &
227
+ local pid_b=$!
228
+
229
+ # Kill children on interrupt, clean up worktrees
230
+ trap 'kill "$pid_a" "$pid_b" 2>/dev/null; wait "$pid_a" "$pid_b" 2>/dev/null; echo "MAB agents interrupted" >&2' INT TERM
231
+
232
+ # Wait for both
233
+ local exit_a=0 exit_b=0
234
+ wait $pid_a || exit_a=$?
235
+ wait $pid_b || exit_b=$?
236
+
237
+ # Clear the interrupt trap
238
+ trap - INT TERM
239
+
240
+ echo " Agent A exited: $exit_a | Agent B exited: $exit_b"
241
+ echo "$exit_a $exit_b"
242
+ }
243
+
244
+ # --- Run quality gate on an agent worktree ---
245
+ run_gate_on_agent() {
246
+ local agent_wt="$1" agent_name="$2"
247
+ local gate_exit=0
248
+ (cd "$agent_wt" && bash -c "$MAB_QUALITY_GATE") > "$MAB_WORKTREE/logs/mab-gate-${agent_name}.log" 2>&1 || gate_exit=$?
249
+ echo " Gate $agent_name: exit=$gate_exit"
250
+ return $gate_exit
251
+ }
252
+
253
+ # --- Invoke judge ---
254
+ invoke_judge() {
255
+ local wt_a="$1" wt_b="$2" gate_a_log="$3" gate_b_log="$4"
256
+ local judge_template
257
+ judge_template=$(cat "$SCRIPT_DIR/prompts/judge-agent.md")
258
+
259
+ local diff_a diff_b gate_a_text gate_b_text
260
+ diff_a=$(cd "$wt_a" && git diff HEAD 2>/dev/null | head -500) || diff_a="(no diff)"
261
+ diff_b=$(cd "$wt_b" && git diff HEAD 2>/dev/null | head -500) || diff_b="(no diff)"
262
+ gate_a_text=$(cat "$gate_a_log" 2>/dev/null | tail -50 || echo "(no gate output)")
263
+ gate_b_text=$(cat "$gate_b_log" 2>/dev/null | tail -50 || echo "(no gate output)")
264
+
265
+ local design_doc=""
266
+ if [[ -n "$MAB_PLAN" && -f "$MAB_PLAN" ]]; then
267
+ design_doc=$(head -100 "$MAB_PLAN")
268
+ fi
269
+
270
+ local judge_prompt="$judge_template"
271
+ judge_prompt="${judge_prompt//\{WORK_UNIT_DESCRIPTION\}/$MAB_WORK_UNIT}"
272
+ judge_prompt="${judge_prompt//\{DIFF_A\}/$diff_a}"
273
+ judge_prompt="${judge_prompt//\{DIFF_B\}/$diff_b}"
274
+ judge_prompt="${judge_prompt//\{GATE_A\}/$gate_a_text}"
275
+ judge_prompt="${judge_prompt//\{GATE_B\}/$gate_b_text}"
276
+ judge_prompt="${judge_prompt//\{DESIGN_DOC\}/$design_doc}"
277
+
278
+ local judge_output
279
+ local judge_exit=0
280
+ judge_output=$(CLAUDECODE='' claude -p "$judge_prompt" \
281
+ --allowedTools "" \
282
+ --permission-mode bypassPermissions \
283
+ 2>"$MAB_WORKTREE/logs/mab-judge-stderr.log") || judge_exit=$?
284
+ if [[ $judge_exit -ne 0 ]]; then
285
+ echo "WARNING: judge failed (exit $judge_exit), defaulting to tie" >&2
286
+ fi
287
+
288
+ echo "$judge_output" > "$MAB_WORKTREE/logs/mab-judge-output.log"
289
+
290
+ # Parse winner from judge output
291
+ local winner
292
+ winner=$(echo "$judge_output" | grep -oE 'WINNER:\s*(agent-[ab]|tie)' | sed 's/WINNER:\s*//' | head -1 || echo "tie")
293
+ winner="${winner:-tie}"
294
+
295
+ # Parse lesson
296
+ local lesson
297
+ lesson=$(echo "$judge_output" | grep -oE 'LESSON:\s*.*' | sed 's/LESSON:\s*//' | head -1 || echo "")
298
+
299
+ echo "$winner|$lesson"
300
+ }
301
+
302
+ # --- Human calibration prompt ---
303
+ prompt_human_calibration() {
304
+ local winner="$1" perf_file="$2"
305
+
306
+ local cal_count cal_complete
307
+ cal_count=$(jq -r '.calibration_count // 0' "$perf_file" 2>/dev/null || echo "0")
308
+ cal_complete=$(jq -r '.calibration_complete // false' "$perf_file" 2>/dev/null || echo "false")
309
+
310
+ if [[ "$cal_complete" == "true" ]]; then
311
+ echo "$winner"
312
+ return
313
+ fi
314
+
315
+ # Only prompt if stdin is a tty
316
+ if [[ -t 0 ]]; then
317
+ echo ""
318
+ echo " [CALIBRATION $((cal_count + 1))/10] Judge picked: $winner"
319
+ echo " [y] Accept [a] Override → agent-a [b] Override → agent-b [n] Skip"
320
+ read -r -p " Choice: " choice < /dev/tty
321
+ case "$choice" in
322
+ y|Y) ;; # Accept judge verdict
323
+ a|A) winner="agent-a" ;;
324
+ b|B) winner="agent-b" ;;
325
+ n|N) winner="none" ;;
326
+ esac
327
+ else
328
+ echo " [CALIBRATION] headless-auto-approved: $winner"
329
+ fi
330
+
331
+ # Increment calibration count
332
+ local tmp
333
+ tmp=$(mktemp)
334
+ local new_count=$((cal_count + 1))
335
+ if [[ "$new_count" -ge 10 ]]; then
336
+ jq ".calibration_count = $new_count | .calibration_complete = true" "$perf_file" > "$tmp" && mv "$tmp" "$perf_file"
337
+ else
338
+ jq ".calibration_count = $new_count" "$perf_file" > "$tmp" && mv "$tmp" "$perf_file"
339
+ fi
340
+
341
+ echo "$winner"
342
+ }
343
+
344
+ # --- Merge winner branch ---
345
+ merge_winner() {
346
+ local winner="$1" wt_a="$2" wt_b="$3"
347
+
348
+ local winner_wt
349
+ if [[ "$winner" == "agent-a" ]]; then
350
+ winner_wt="$wt_a"
351
+ elif [[ "$winner" == "agent-b" ]]; then
352
+ winner_wt="$wt_b"
353
+ else
354
+ echo "ERROR: merge_winner called with unexpected winner='$winner'" >&2
355
+ return 1
356
+ fi
357
+
358
+ # Commit winner's changes in their worktree
359
+ (cd "$winner_wt" && git add -u && git commit -m "mab: $winner batch $MAB_BATCH — $MAB_WORK_UNIT" --allow-empty 2>/dev/null) || true
360
+
361
+ # Cherry-pick into base worktree
362
+ local winner_commit
363
+ winner_commit=$(cd "$winner_wt" && git rev-parse HEAD)
364
+
365
+ (cd "$MAB_WORKTREE" && git cherry-pick "$winner_commit" --no-edit 2>/dev/null) || {
366
+ echo "WARNING: Cherry-pick failed, attempting manual merge" >&2
367
+ (cd "$MAB_WORKTREE" && git cherry-pick --abort 2>/dev/null || true)
368
+ # Fallback: copy files from winner worktree
369
+ (cd "$winner_wt" && git diff HEAD~1 --name-only 2>/dev/null | while IFS= read -r f; do
370
+ mkdir -p "$MAB_WORKTREE/$(dirname "$f")"
371
+ cp "$winner_wt/$f" "$MAB_WORKTREE/$f" 2>/dev/null || true
372
+ done)
373
+ (cd "$MAB_WORKTREE" && git add -u && git commit -m "mab: $winner batch $MAB_BATCH (manual merge)" --allow-empty 2>/dev/null) || true
374
+ }
375
+ }
376
+
377
+ # --- Update MAB data files ---
378
+ update_mab_data() {
379
+ local winner="$1" lesson="$2" batch_type="$3"
380
+ local perf_file="$MAB_WORKTREE/logs/strategy-perf.json"
381
+ local lessons_file="$MAB_WORKTREE/logs/mab-lessons.json"
382
+
383
+ # Update strategy performance
384
+ local winner_strategy
385
+ if [[ "$winner" == "agent-a" ]]; then
386
+ winner_strategy="superpowers"
387
+ else
388
+ winner_strategy="ralph"
389
+ fi
390
+ update_strategy_perf "$perf_file" "$batch_type" "$winner_strategy"
391
+
392
+ # Record lesson if present
393
+ if [[ -n "$lesson" ]]; then
394
+ if [[ ! -f "$lessons_file" ]]; then
395
+ echo "[]" > "$lessons_file"
396
+ fi
397
+
398
+ local tmp
399
+ tmp=$(mktemp)
400
+ jq --arg p "$lesson" --arg ctx "$batch_type" --arg w "$winner_strategy" '
401
+ # Check if pattern already exists
402
+ if [.[] | select(.pattern == $p)] | length > 0 then
403
+ [.[] | if .pattern == $p then .occurrences += 1 | .last_seen = (now | tostring) else . end]
404
+ else
405
+ . + [{"pattern": $p, "context": $ctx, "winner": $w, "occurrences": 1, "last_seen": (now | tostring), "promoted": false}]
406
+ end
407
+ ' "$lessons_file" > "$tmp" && mv "$tmp" "$lessons_file"
408
+ fi
409
+
410
+ # Log the run
411
+ local run_log="$MAB_WORKTREE/logs/mab-runs.log"
412
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] batch=$MAB_BATCH type=$batch_type winner=$winner lesson=\"$lesson\"" >> "$run_log"
413
+ }
414
+
415
+ # --- Cleanup worktrees ---
416
+ cleanup_mab_worktrees() {
417
+ local base_worktree="$1" batch="$2"
418
+ local branch_a="mab-agent-a-batch-${batch}"
419
+ local branch_b="mab-agent-b-batch-${batch}"
420
+ local wt_a="$base_worktree/.mab-worktrees/agent-a"
421
+ local wt_b="$base_worktree/.mab-worktrees/agent-b"
422
+
423
+ git -C "$base_worktree" worktree remove "$wt_a" --force 2>/dev/null || true
424
+ git -C "$base_worktree" worktree remove "$wt_b" --force 2>/dev/null || true
425
+ git -C "$base_worktree" branch -D "$branch_a" 2>/dev/null || true
426
+ git -C "$base_worktree" branch -D "$branch_b" 2>/dev/null || true
427
+ rm -rf "$base_worktree/.mab-worktrees" 2>/dev/null || true
428
+ }
429
+
430
+ # --- Main orchestration ---
431
+ run_mab() {
432
+ local perf_file="$MAB_WORKTREE/logs/strategy-perf.json"
433
+ [[ ! -f "$perf_file" ]] && init_strategy_perf "$perf_file"
434
+
435
+ local lessons_file="$MAB_WORKTREE/logs/mab-lessons.json"
436
+ [[ ! -f "$lessons_file" ]] && echo "[]" > "$lessons_file"
437
+
438
+ echo ""
439
+ echo "╔══════════════════════════════════════════════════════╗"
440
+ echo "║ MAB Run — Batch $MAB_BATCH"
441
+ echo "║ Work: $MAB_WORK_UNIT"
442
+ echo "╚══════════════════════════════════════════════════════╝"
443
+
444
+ if [[ "$MAB_DRY_RUN" == true ]]; then
445
+ echo ""
446
+ echo "=== DRY RUN ==="
447
+ echo " Plan: $MAB_PLAN"
448
+ echo " Batch: $MAB_BATCH"
449
+ echo " Work unit: $MAB_WORK_UNIT"
450
+ echo " Worktree: $MAB_WORKTREE"
451
+ echo " Quality gate: $MAB_QUALITY_GATE"
452
+ echo ""
453
+ echo " Would create worktrees:"
454
+ echo " agent-a: $MAB_WORKTREE/.mab-worktrees/agent-a"
455
+ echo " agent-b: $MAB_WORKTREE/.mab-worktrees/agent-b"
456
+ echo ""
457
+ echo " Would run agents in parallel, invoke judge, merge winner."
458
+ echo "=== END DRY RUN ==="
459
+ return 0
460
+ fi
461
+
462
+ # Load MAB lessons for injection
463
+ local mab_lessons_text=""
464
+ if [[ -f "$lessons_file" ]]; then
465
+ mab_lessons_text=$(jq -r '
466
+ sort_by(-.occurrences // 0) | .[0:5] | .[] |
467
+ "- \(.pattern) (\(.context // "general")): winner=\(.winner // "unknown")"
468
+ ' "$lessons_file" 2>/dev/null || echo "No lessons yet.")
469
+ fi
470
+ [[ -z "$mab_lessons_text" ]] && mab_lessons_text="No lessons yet."
471
+
472
+ # Resolve paths
473
+ local prd_path="${MAB_PRD:-tasks/prd.json}"
474
+ local arch_map_path="docs/ARCHITECTURE-MAP.json"
475
+
476
+ # Assemble prompts
477
+ local prompt_a_template prompt_b_template
478
+ prompt_a_template=$(cat "$SCRIPT_DIR/prompts/agent-a-superpowers.md")
479
+ prompt_b_template=$(cat "$SCRIPT_DIR/prompts/agent-b-ralph.md")
480
+
481
+ local prompt_a prompt_b
482
+ prompt_a=$(assemble_agent_prompt "$prompt_a_template" "$MAB_WORK_UNIT" "$prd_path" "$arch_map_path" "$mab_lessons_text" "$MAB_QUALITY_GATE")
483
+ prompt_b=$(assemble_agent_prompt "$prompt_b_template" "$MAB_WORK_UNIT" "$prd_path" "$arch_map_path" "$mab_lessons_text" "$MAB_QUALITY_GATE")
484
+
485
+ # Create worktrees
486
+ echo ""
487
+ echo "--- Creating worktrees ---"
488
+ local worktrees
489
+ worktrees=$(create_mab_worktrees "$MAB_WORKTREE" "$MAB_BATCH")
490
+ local wt_a wt_b
491
+ wt_a=$(echo "$worktrees" | awk '{print $1}')
492
+ wt_b=$(echo "$worktrees" | awk '{print $2}')
493
+ echo " Agent A: $wt_a"
494
+ echo " Agent B: $wt_b"
495
+
496
+ # Run agents in parallel
497
+ echo ""
498
+ echo "--- Running agents ---"
499
+ run_agents_parallel "$wt_a" "$wt_b" "$prompt_a" "$prompt_b" || true
500
+
501
+ # Run quality gates
502
+ echo ""
503
+ echo "--- Quality gates ---"
504
+ # Capture gate exit codes without disabling set -e inside functions (SC2310)
505
+ local gate_a gate_b
506
+ set +e; run_gate_on_agent "$wt_a" "agent-a"; gate_a=$?; set -e
507
+ set +e; run_gate_on_agent "$wt_b" "agent-b"; gate_b=$?; set -e
508
+
509
+ # Invoke judge (only if both agents ran)
510
+ echo ""
511
+ echo "--- Judge evaluation ---"
512
+ local judge_result judge_winner judge_lesson
513
+ judge_result=$(invoke_judge "$wt_a" "$wt_b" \
514
+ "$MAB_WORKTREE/logs/mab-gate-agent-a.log" \
515
+ "$MAB_WORKTREE/logs/mab-gate-agent-b.log")
516
+ judge_winner=$(echo "$judge_result" | cut -d'|' -f1)
517
+ judge_lesson=$(echo "$judge_result" | cut -d'|' -f2-)
518
+ echo " Judge verdict: $judge_winner"
519
+
520
+ # Apply gate override
521
+ local final_winner
522
+ final_winner=$(select_winner_with_gate_override "$gate_a" "$gate_b" "$judge_winner")
523
+ echo " Final winner: $final_winner (gate override applied)"
524
+
525
+ # Human calibration
526
+ final_winner=$(prompt_human_calibration "$final_winner" "$perf_file")
527
+
528
+ if [[ "$final_winner" == "none" || "$final_winner" == "tie" ]]; then
529
+ echo " No winner — both agents failed or tie with no override."
530
+ cleanup_mab_worktrees "$MAB_WORKTREE" "$MAB_BATCH"
531
+ return 1
532
+ fi
533
+
534
+ # Merge winner
535
+ echo ""
536
+ echo "--- Merging winner ($final_winner) ---"
537
+ merge_winner "$final_winner" "$wt_a" "$wt_b"
538
+
539
+ # Classify batch type for data recording
540
+ local batch_type="unknown"
541
+ if type classify_batch_type &>/dev/null && [[ -n "$MAB_PLAN" ]]; then
542
+ batch_type=$(classify_batch_type "$MAB_PLAN" "$MAB_BATCH" 2>/dev/null || echo "unknown")
543
+ fi
544
+
545
+ # Update data
546
+ update_mab_data "$final_winner" "$judge_lesson" "$batch_type"
547
+
548
+ # Cleanup
549
+ echo ""
550
+ echo "--- Cleanup ---"
551
+ cleanup_mab_worktrees "$MAB_WORKTREE" "$MAB_BATCH"
552
+
553
+ echo ""
554
+ echo "MAB batch $MAB_BATCH complete. Winner: $final_winner"
555
+ }
556
+
557
+ # --- Entry point ---
558
+ parse_mab_args "$@"
559
+
560
+ # --source-only: export functions for testing, don't execute
561
+ if [[ "$MAB_SOURCE_ONLY" == true ]]; then
562
+ return 0 2>/dev/null || exit 0
563
+ fi
564
+
565
+ validate_mab_args
566
+
567
+ if [[ "$MAB_INIT_DATA" == true ]]; then
568
+ mkdir -p "$MAB_WORKTREE/logs"
569
+ init_strategy_perf "$MAB_WORKTREE/logs/strategy-perf.json"
570
+ echo "[]" > "$MAB_WORKTREE/logs/mab-lessons.json"
571
+ echo "Initialized MAB data files in $MAB_WORKTREE/logs/"
572
+ exit 0
573
+ fi
574
+
575
+ run_mab