bmalph 1.0.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +398 -217
  3. package/bmad/bmm/agents/analyst.agent.yaml +43 -36
  4. package/bmad/bmm/agents/architect.agent.yaml +29 -28
  5. package/bmad/bmm/agents/dev.agent.yaml +38 -38
  6. package/bmad/bmm/agents/pm.agent.yaml +44 -46
  7. package/bmad/bmm/agents/qa.agent.yaml +58 -0
  8. package/bmad/bmm/agents/quick-flow-solo-dev.agent.yaml +32 -32
  9. package/bmad/bmm/agents/sm.agent.yaml +37 -36
  10. package/bmad/bmm/agents/tech-writer/tech-writer-sidecar/documentation-standards.md +223 -223
  11. package/bmad/bmm/agents/tech-writer/tech-writer.agent.yaml +46 -45
  12. package/bmad/bmm/agents/ux-designer.agent.yaml +27 -26
  13. package/bmad/bmm/data/project-context-template.md +26 -26
  14. package/bmad/bmm/module-help.csv +31 -31
  15. package/bmad/bmm/module.yaml +50 -44
  16. package/bmad/bmm/teams/default-party.csv +20 -21
  17. package/bmad/bmm/teams/team-fullstack.yaml +12 -12
  18. package/bmad/bmm/workflows/1-analysis/create-product-brief/product-brief.template.md +10 -10
  19. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +177 -177
  20. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +161 -161
  21. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +199 -199
  22. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +202 -202
  23. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +205 -205
  24. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +219 -219
  25. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +162 -162
  26. package/bmad/bmm/workflows/1-analysis/create-product-brief/workflow.md +57 -58
  27. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +137 -137
  28. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +229 -229
  29. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +238 -238
  30. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +206 -206
  31. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +234 -234
  32. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +443 -443
  33. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +182 -182
  34. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +237 -237
  35. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +249 -249
  36. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +259 -259
  37. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +177 -177
  38. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +475 -475
  39. package/bmad/bmm/workflows/1-analysis/research/research.template.md +29 -29
  40. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +137 -137
  41. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +239 -239
  42. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +248 -248
  43. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +202 -202
  44. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +233 -239
  45. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +486 -486
  46. package/bmad/bmm/workflows/1-analysis/research/workflow-domain-research.md +54 -0
  47. package/bmad/bmm/workflows/1-analysis/research/workflow-market-research.md +54 -0
  48. package/bmad/bmm/workflows/1-analysis/research/workflow-technical-research.md +54 -0
  49. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/data/domain-complexity.csv +14 -12
  50. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/data/prd-purpose.md +197 -197
  51. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/data/project-types.csv +10 -10
  52. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-01-init.md +191 -191
  53. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-01b-continue.md +153 -153
  54. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-02-discovery.md +224 -224
  55. package/bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +154 -0
  56. package/bmad/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +170 -0
  57. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-03-success.md +226 -226
  58. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-04-journeys.md +213 -213
  59. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-05-domain.md +207 -207
  60. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-06-innovation.md +226 -226
  61. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-07-project-type.md +237 -237
  62. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-08-scoping.md +228 -228
  63. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-09-functional.md +231 -231
  64. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-10-nonfunctional.md +242 -242
  65. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-11-polish.md +217 -217
  66. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-c/step-12-complete.md +124 -124
  67. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-e/step-e-01-discovery.md +247 -247
  68. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-e/step-e-01b-legacy-conversion.md +208 -208
  69. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-e/step-e-02-review.md +249 -249
  70. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-e/step-e-03-edit.md +253 -253
  71. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-e/step-e-04-complete.md +168 -168
  72. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-01-discovery.md +226 -218
  73. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-02-format-detection.md +191 -191
  74. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-02b-parity-check.md +209 -209
  75. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-03-density-validation.md +174 -174
  76. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-04-brief-coverage-validation.md +214 -214
  77. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-05-measurability-validation.md +228 -228
  78. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-06-traceability-validation.md +217 -217
  79. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-07-implementation-leakage-validation.md +205 -205
  80. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-08-domain-compliance-validation.md +243 -243
  81. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-09-project-type-validation.md +263 -263
  82. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-10-smart-validation.md +209 -209
  83. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-11-holistic-quality-validation.md +264 -264
  84. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-12-completeness-validation.md +242 -242
  85. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/steps-v/step-v-13-report-complete.md +231 -231
  86. package/bmad/bmm/workflows/2-plan-workflows/{prd → create-prd}/templates/prd-template.md +10 -10
  87. package/bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +63 -0
  88. package/bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +65 -0
  89. package/bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +63 -0
  90. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md +135 -135
  91. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +127 -127
  92. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +190 -190
  93. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +216 -216
  94. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +219 -219
  95. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +234 -234
  96. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +252 -252
  97. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +254 -254
  98. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +224 -224
  99. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +224 -224
  100. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +241 -241
  101. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +248 -248
  102. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +237 -237
  103. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +264 -264
  104. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +171 -171
  105. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +13 -13
  106. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +42 -43
  107. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +184 -190
  108. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +172 -178
  109. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +173 -179
  110. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +133 -139
  111. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +245 -252
  112. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +129 -135
  113. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/templates/readiness-report-template.md +4 -4
  114. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +54 -55
  115. package/bmad/bmm/workflows/3-solutioning/create-architecture/architecture-decision-template.md +12 -12
  116. package/bmad/bmm/workflows/3-solutioning/create-architecture/data/domain-complexity.csv +12 -10
  117. package/bmad/bmm/workflows/3-solutioning/create-architecture/data/project-types.csv +6 -6
  118. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md +153 -153
  119. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +164 -164
  120. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +224 -224
  121. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +331 -331
  122. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +318 -318
  123. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +359 -359
  124. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +379 -379
  125. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +359 -359
  126. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +76 -76
  127. package/bmad/bmm/workflows/3-solutioning/create-architecture/workflow.md +49 -50
  128. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +259 -259
  129. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +233 -233
  130. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +272 -272
  131. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +149 -149
  132. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md +57 -57
  133. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +58 -59
  134. package/bmad/bmm/workflows/4-implementation/code-review/checklist.md +23 -23
  135. package/bmad/bmm/workflows/4-implementation/code-review/instructions.xml +226 -226
  136. package/bmad/bmm/workflows/4-implementation/code-review/workflow.yaml +44 -51
  137. package/bmad/bmm/workflows/4-implementation/correct-course/checklist.md +288 -288
  138. package/bmad/bmm/workflows/4-implementation/correct-course/instructions.md +207 -206
  139. package/bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml +54 -60
  140. package/bmad/bmm/workflows/4-implementation/create-story/checklist.md +358 -358
  141. package/bmad/bmm/workflows/4-implementation/create-story/instructions.xml +346 -345
  142. package/bmad/bmm/workflows/4-implementation/create-story/template.md +49 -49
  143. package/bmad/bmm/workflows/4-implementation/create-story/workflow.yaml +53 -61
  144. package/bmad/bmm/workflows/4-implementation/dev-story/checklist.md +80 -80
  145. package/bmad/bmm/workflows/4-implementation/dev-story/instructions.xml +410 -410
  146. package/bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml +21 -27
  147. package/bmad/bmm/workflows/4-implementation/retrospective/instructions.md +1444 -1443
  148. package/bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml +53 -58
  149. package/bmad/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -33
  150. package/bmad/bmm/workflows/4-implementation/sprint-planning/instructions.md +226 -225
  151. package/bmad/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -55
  152. package/bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +47 -54
  153. package/bmad/bmm/workflows/4-implementation/sprint-status/instructions.md +230 -229
  154. package/bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml +25 -36
  155. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +174 -156
  156. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +118 -120
  157. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +111 -113
  158. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +111 -113
  159. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +104 -106
  160. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +146 -140
  161. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +50 -50
  162. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md +191 -189
  163. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +144 -144
  164. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +127 -128
  165. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +200 -191
  166. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/tech-spec-template.md +74 -74
  167. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +79 -79
  168. package/bmad/bmm/workflows/document-project/checklist.md +245 -245
  169. package/bmad/bmm/workflows/document-project/documentation-requirements.csv +12 -12
  170. package/bmad/bmm/workflows/document-project/instructions.md +130 -221
  171. package/bmad/bmm/workflows/document-project/templates/deep-dive-template.md +345 -345
  172. package/bmad/bmm/workflows/document-project/templates/index-template.md +169 -169
  173. package/bmad/bmm/workflows/document-project/templates/project-overview-template.md +103 -103
  174. package/bmad/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -160
  175. package/bmad/bmm/workflows/document-project/templates/source-tree-template.md +135 -135
  176. package/bmad/bmm/workflows/document-project/workflow.yaml +22 -30
  177. package/bmad/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -298
  178. package/bmad/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -31
  179. package/bmad/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -1106
  180. package/bmad/bmm/workflows/document-project/workflows/full-scan.yaml +31 -31
  181. package/bmad/bmm/workflows/generate-project-context/project-context-template.md +21 -0
  182. package/bmad/bmm/workflows/generate-project-context/steps/step-01-discover.md +184 -0
  183. package/bmad/bmm/workflows/generate-project-context/steps/step-02-generate.md +318 -0
  184. package/bmad/bmm/workflows/generate-project-context/steps/step-03-complete.md +278 -0
  185. package/bmad/bmm/workflows/generate-project-context/workflow.md +49 -0
  186. package/bmad/bmm/workflows/qa/automate/checklist.md +33 -0
  187. package/bmad/bmm/workflows/qa/automate/instructions.md +110 -0
  188. package/bmad/bmm/workflows/qa/automate/workflow.yaml +44 -0
  189. package/bmad/core/agents/bmad-master.agent.yaml +30 -30
  190. package/bmad/core/module-help.csv +9 -11
  191. package/bmad/core/module.yaml +25 -25
  192. package/bmad/core/tasks/editorial-review-prose.xml +102 -91
  193. package/bmad/core/tasks/editorial-review-structure.xml +209 -198
  194. package/bmad/core/tasks/help.md +85 -0
  195. package/bmad/core/tasks/index-docs.xml +64 -64
  196. package/bmad/core/tasks/review-adversarial-general.xml +48 -48
  197. package/bmad/core/tasks/shard-doc.xml +107 -108
  198. package/bmad/core/tasks/workflow.xml +234 -234
  199. package/bmad/core/workflows/advanced-elicitation/methods.csv +51 -51
  200. package/bmad/core/workflows/advanced-elicitation/workflow.xml +116 -116
  201. package/bmad/core/workflows/brainstorming/brain-methods.csv +61 -61
  202. package/bmad/core/workflows/brainstorming/steps/step-01-session-setup.md +197 -197
  203. package/bmad/core/workflows/brainstorming/steps/step-01b-continue.md +122 -122
  204. package/bmad/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -225
  205. package/bmad/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -237
  206. package/bmad/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -209
  207. package/bmad/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -264
  208. package/bmad/core/workflows/brainstorming/steps/step-03-technique-execution.md +399 -399
  209. package/bmad/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -303
  210. package/bmad/core/workflows/brainstorming/template.md +15 -15
  211. package/bmad/core/workflows/brainstorming/workflow.md +58 -58
  212. package/bmad/core/workflows/party-mode/steps/step-01-agent-loading.md +138 -138
  213. package/bmad/core/workflows/party-mode/steps/step-02-discussion-orchestration.md +187 -187
  214. package/bmad/core/workflows/party-mode/steps/step-03-graceful-exit.md +168 -157
  215. package/bmad/core/workflows/party-mode/workflow.md +194 -194
  216. package/bundled-versions.json +3 -0
  217. package/dist/cli.js +61 -6
  218. package/dist/commands/check-updates.d.ts +5 -0
  219. package/dist/commands/check-updates.js +63 -0
  220. package/dist/commands/doctor.d.ts +39 -1
  221. package/dist/commands/doctor.js +348 -79
  222. package/dist/commands/init.d.ts +2 -0
  223. package/dist/commands/init.js +41 -15
  224. package/dist/commands/status.d.ts +7 -1
  225. package/dist/commands/status.js +111 -42
  226. package/dist/commands/upgrade.d.ts +7 -1
  227. package/dist/commands/upgrade.js +43 -12
  228. package/dist/installer.d.ts +19 -2
  229. package/dist/installer.js +305 -66
  230. package/dist/transition/artifacts.d.ts +2 -0
  231. package/dist/transition/artifacts.js +46 -0
  232. package/dist/transition/context.d.ts +19 -0
  233. package/dist/transition/context.js +261 -0
  234. package/dist/transition/fix-plan.d.ts +15 -0
  235. package/dist/transition/fix-plan.js +94 -0
  236. package/dist/transition/index.d.ts +9 -0
  237. package/dist/transition/index.js +16 -0
  238. package/dist/transition/orchestration.d.ts +2 -0
  239. package/dist/transition/orchestration.js +243 -0
  240. package/dist/transition/specs-changelog.d.ts +3 -0
  241. package/dist/transition/specs-changelog.js +75 -0
  242. package/dist/transition/specs-index.d.ts +22 -0
  243. package/dist/transition/specs-index.js +157 -0
  244. package/dist/transition/story-parsing.d.ts +7 -0
  245. package/dist/transition/story-parsing.js +124 -0
  246. package/dist/transition/tech-stack.d.ts +3 -0
  247. package/dist/transition/tech-stack.js +79 -0
  248. package/dist/transition/types.d.ts +60 -0
  249. package/dist/transition/types.js +1 -0
  250. package/dist/utils/config.d.ts +4 -0
  251. package/dist/utils/config.js +14 -4
  252. package/dist/utils/constants.d.ts +70 -0
  253. package/dist/utils/constants.js +97 -0
  254. package/dist/utils/dryrun.d.ts +7 -0
  255. package/dist/utils/dryrun.js +48 -0
  256. package/dist/utils/errors.d.ts +63 -0
  257. package/dist/utils/errors.js +86 -0
  258. package/dist/utils/file-system.d.ts +24 -0
  259. package/dist/utils/file-system.js +99 -0
  260. package/dist/utils/github.d.ts +83 -0
  261. package/dist/utils/github.js +230 -0
  262. package/dist/utils/json.js +3 -3
  263. package/dist/utils/logger.d.ts +6 -0
  264. package/dist/utils/logger.js +27 -0
  265. package/dist/utils/state.d.ts +4 -7
  266. package/dist/utils/state.js +147 -26
  267. package/dist/utils/validate.d.ts +40 -0
  268. package/dist/utils/validate.js +175 -1
  269. package/package.json +75 -59
  270. package/ralph/RALPH-REFERENCE.md +412 -0
  271. package/ralph/lib/circuit_breaker.sh +463 -330
  272. package/ralph/lib/date_utils.sh +104 -53
  273. package/ralph/lib/enable_core.sh +815 -0
  274. package/ralph/lib/response_analyzer.sh +884 -768
  275. package/ralph/lib/task_sources.sh +577 -0
  276. package/ralph/lib/timeout_utils.sh +145 -145
  277. package/ralph/lib/wizard_utils.sh +547 -0
  278. package/ralph/ralph_import.sh +636 -0
  279. package/ralph/ralph_loop.sh +1793 -1391
  280. package/ralph/ralph_monitor.sh +125 -0
  281. package/ralph/templates/AGENT.md +158 -158
  282. package/ralph/templates/PROMPT.md +285 -292
  283. package/ralph/templates/fix_plan.md +27 -27
  284. package/ralph/templates/ralphrc.template +102 -0
  285. package/ralph/templates/specs/.gitkeep +1 -1
  286. package/slash-commands/advanced-elicitation.md +1 -1
  287. package/slash-commands/adversarial-review.md +1 -1
  288. package/slash-commands/analyst.md +1 -1
  289. package/slash-commands/architect.md +1 -1
  290. package/slash-commands/bmad-help.md +1 -1
  291. package/slash-commands/bmalph-implement.md +152 -152
  292. package/slash-commands/brainstorm-project.md +1 -1
  293. package/slash-commands/brainstorming.md +1 -1
  294. package/slash-commands/correct-course.md +1 -1
  295. package/slash-commands/create-architecture.md +1 -1
  296. package/slash-commands/create-brief.md +1 -1
  297. package/slash-commands/create-epics-stories.md +1 -1
  298. package/slash-commands/create-prd.md +1 -1
  299. package/slash-commands/create-story.md +1 -1
  300. package/slash-commands/create-ux.md +1 -1
  301. package/slash-commands/dev.md +1 -1
  302. package/slash-commands/document-project.md +1 -1
  303. package/slash-commands/domain-research.md +1 -1
  304. package/slash-commands/editorial-prose.md +1 -1
  305. package/slash-commands/editorial-structure.md +1 -1
  306. package/slash-commands/execute-workflow.md +1 -1
  307. package/slash-commands/generate-project-context.md +1 -0
  308. package/slash-commands/implementation-readiness.md +1 -1
  309. package/slash-commands/index-docs.md +1 -1
  310. package/slash-commands/market-research.md +1 -1
  311. package/slash-commands/party-mode.md +1 -1
  312. package/slash-commands/pm.md +1 -1
  313. package/slash-commands/qa-automate.md +1 -0
  314. package/slash-commands/qa.md +1 -0
  315. package/slash-commands/quick-dev.md +1 -1
  316. package/slash-commands/quick-flow-solo-dev.md +1 -1
  317. package/slash-commands/retrospective.md +1 -1
  318. package/slash-commands/shard-doc.md +1 -1
  319. package/slash-commands/sm.md +1 -1
  320. package/slash-commands/sprint-planning.md +1 -1
  321. package/slash-commands/sprint-status.md +1 -1
  322. package/slash-commands/tech-spec.md +1 -1
  323. package/slash-commands/tech-writer.md +1 -0
  324. package/slash-commands/technical-research.md +1 -1
  325. package/slash-commands/ux-designer.md +1 -1
  326. package/slash-commands/validate-architecture.md +1 -1
  327. package/slash-commands/validate-brief.md +1 -1
  328. package/slash-commands/validate-epics-stories.md +1 -1
  329. package/slash-commands/validate-prd.md +1 -1
  330. package/slash-commands/validate-story.md +1 -1
  331. package/slash-commands/validate-ux.md +1 -1
  332. package/bmad/bmm/agents/tea.agent.yaml +0 -63
  333. package/bmad/bmm/sub-modules/claude-code/config.yaml +0 -4
  334. package/bmad/bmm/sub-modules/claude-code/injections.yaml +0 -242
  335. package/bmad/bmm/sub-modules/claude-code/readme.md +0 -87
  336. package/bmad/bmm/testarch/knowledge/adr-quality-readiness-checklist.md +0 -350
  337. package/bmad/bmm/testarch/knowledge/api-request.md +0 -442
  338. package/bmad/bmm/testarch/knowledge/api-testing-patterns.md +0 -843
  339. package/bmad/bmm/testarch/knowledge/auth-session.md +0 -552
  340. package/bmad/bmm/testarch/knowledge/burn-in.md +0 -273
  341. package/bmad/bmm/testarch/knowledge/ci-burn-in.md +0 -675
  342. package/bmad/bmm/testarch/knowledge/component-tdd.md +0 -486
  343. package/bmad/bmm/testarch/knowledge/contract-testing.md +0 -957
  344. package/bmad/bmm/testarch/knowledge/data-factories.md +0 -500
  345. package/bmad/bmm/testarch/knowledge/email-auth.md +0 -721
  346. package/bmad/bmm/testarch/knowledge/error-handling.md +0 -725
  347. package/bmad/bmm/testarch/knowledge/feature-flags.md +0 -750
  348. package/bmad/bmm/testarch/knowledge/file-utils.md +0 -463
  349. package/bmad/bmm/testarch/knowledge/fixture-architecture.md +0 -401
  350. package/bmad/bmm/testarch/knowledge/fixtures-composition.md +0 -382
  351. package/bmad/bmm/testarch/knowledge/intercept-network-call.md +0 -430
  352. package/bmad/bmm/testarch/knowledge/log.md +0 -429
  353. package/bmad/bmm/testarch/knowledge/network-error-monitor.md +0 -405
  354. package/bmad/bmm/testarch/knowledge/network-first.md +0 -486
  355. package/bmad/bmm/testarch/knowledge/network-recorder.md +0 -527
  356. package/bmad/bmm/testarch/knowledge/nfr-criteria.md +0 -670
  357. package/bmad/bmm/testarch/knowledge/overview.md +0 -286
  358. package/bmad/bmm/testarch/knowledge/playwright-config.md +0 -730
  359. package/bmad/bmm/testarch/knowledge/probability-impact.md +0 -601
  360. package/bmad/bmm/testarch/knowledge/recurse.md +0 -421
  361. package/bmad/bmm/testarch/knowledge/risk-governance.md +0 -615
  362. package/bmad/bmm/testarch/knowledge/selective-testing.md +0 -732
  363. package/bmad/bmm/testarch/knowledge/selector-resilience.md +0 -527
  364. package/bmad/bmm/testarch/knowledge/test-healing-patterns.md +0 -644
  365. package/bmad/bmm/testarch/knowledge/test-levels-framework.md +0 -473
  366. package/bmad/bmm/testarch/knowledge/test-priorities-matrix.md +0 -373
  367. package/bmad/bmm/testarch/knowledge/test-quality.md +0 -664
  368. package/bmad/bmm/testarch/knowledge/timing-debugging.md +0 -372
  369. package/bmad/bmm/testarch/knowledge/visual-debugging.md +0 -524
  370. package/bmad/bmm/testarch/tea-index.csv +0 -35
  371. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-insights.md +0 -200
  372. package/bmad/bmm/workflows/1-analysis/research/workflow.md +0 -173
  373. package/bmad/bmm/workflows/2-plan-workflows/prd/validation-report-prd-workflow.md +0 -433
  374. package/bmad/bmm/workflows/2-plan-workflows/prd/workflow.md +0 -150
  375. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/data/project-levels.yaml +0 -59
  376. package/bmad/bmm/workflows/excalidraw-diagrams/_shared/excalidraw-library.json +0 -90
  377. package/bmad/bmm/workflows/excalidraw-diagrams/_shared/excalidraw-templates.yaml +0 -127
  378. package/bmad/bmm/workflows/excalidraw-diagrams/create-dataflow/checklist.md +0 -39
  379. package/bmad/bmm/workflows/excalidraw-diagrams/create-dataflow/instructions.md +0 -130
  380. package/bmad/bmm/workflows/excalidraw-diagrams/create-dataflow/workflow.yaml +0 -27
  381. package/bmad/bmm/workflows/excalidraw-diagrams/create-diagram/checklist.md +0 -43
  382. package/bmad/bmm/workflows/excalidraw-diagrams/create-diagram/instructions.md +0 -141
  383. package/bmad/bmm/workflows/excalidraw-diagrams/create-diagram/workflow.yaml +0 -27
  384. package/bmad/bmm/workflows/excalidraw-diagrams/create-flowchart/checklist.md +0 -49
  385. package/bmad/bmm/workflows/excalidraw-diagrams/create-flowchart/instructions.md +0 -241
  386. package/bmad/bmm/workflows/excalidraw-diagrams/create-flowchart/workflow.yaml +0 -27
  387. package/bmad/bmm/workflows/excalidraw-diagrams/create-wireframe/checklist.md +0 -38
  388. package/bmad/bmm/workflows/excalidraw-diagrams/create-wireframe/instructions.md +0 -133
  389. package/bmad/bmm/workflows/excalidraw-diagrams/create-wireframe/workflow.yaml +0 -27
  390. package/bmad/bmm/workflows/testarch/atdd/atdd-checklist-template.md +0 -363
  391. package/bmad/bmm/workflows/testarch/atdd/checklist.md +0 -374
  392. package/bmad/bmm/workflows/testarch/atdd/instructions.md +0 -806
  393. package/bmad/bmm/workflows/testarch/atdd/workflow.yaml +0 -47
  394. package/bmad/bmm/workflows/testarch/automate/checklist.md +0 -582
  395. package/bmad/bmm/workflows/testarch/automate/instructions.md +0 -1324
  396. package/bmad/bmm/workflows/testarch/automate/workflow.yaml +0 -54
  397. package/bmad/bmm/workflows/testarch/ci/checklist.md +0 -247
  398. package/bmad/bmm/workflows/testarch/ci/github-actions-template.yaml +0 -198
  399. package/bmad/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +0 -149
  400. package/bmad/bmm/workflows/testarch/ci/instructions.md +0 -536
  401. package/bmad/bmm/workflows/testarch/ci/workflow.yaml +0 -47
  402. package/bmad/bmm/workflows/testarch/framework/checklist.md +0 -320
  403. package/bmad/bmm/workflows/testarch/framework/instructions.md +0 -481
  404. package/bmad/bmm/workflows/testarch/framework/workflow.yaml +0 -49
  405. package/bmad/bmm/workflows/testarch/nfr-assess/checklist.md +0 -407
  406. package/bmad/bmm/workflows/testarch/nfr-assess/instructions.md +0 -726
  407. package/bmad/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +0 -461
  408. package/bmad/bmm/workflows/testarch/nfr-assess/workflow.yaml +0 -49
  409. package/bmad/bmm/workflows/testarch/test-design/checklist.md +0 -407
  410. package/bmad/bmm/workflows/testarch/test-design/instructions.md +0 -1158
  411. package/bmad/bmm/workflows/testarch/test-design/test-design-architecture-template.md +0 -213
  412. package/bmad/bmm/workflows/testarch/test-design/test-design-qa-template.md +0 -286
  413. package/bmad/bmm/workflows/testarch/test-design/test-design-template.md +0 -294
  414. package/bmad/bmm/workflows/testarch/test-design/workflow.yaml +0 -71
  415. package/bmad/bmm/workflows/testarch/test-review/checklist.md +0 -472
  416. package/bmad/bmm/workflows/testarch/test-review/instructions.md +0 -628
  417. package/bmad/bmm/workflows/testarch/test-review/test-review-template.md +0 -390
  418. package/bmad/bmm/workflows/testarch/test-review/workflow.yaml +0 -48
  419. package/bmad/bmm/workflows/testarch/trace/checklist.md +0 -642
  420. package/bmad/bmm/workflows/testarch/trace/instructions.md +0 -1030
  421. package/bmad/bmm/workflows/testarch/trace/trace-template.md +0 -675
  422. package/bmad/bmm/workflows/testarch/trace/workflow.yaml +0 -57
  423. package/bmad/core/resources/excalidraw/README.md +0 -160
  424. package/bmad/core/resources/excalidraw/excalidraw-helpers.md +0 -127
  425. package/bmad/core/resources/excalidraw/library-loader.md +0 -50
  426. package/bmad/core/resources/excalidraw/validate-json-instructions.md +0 -79
  427. package/bmad/core/tasks/bmad-help.md +0 -62
  428. package/dist/commands/guide.d.ts +0 -1
  429. package/dist/commands/guide.js +0 -19
  430. package/dist/commands/implement.d.ts +0 -1
  431. package/dist/commands/implement.js +0 -83
  432. package/dist/commands/plan.d.ts +0 -5
  433. package/dist/commands/plan.js +0 -44
  434. package/dist/commands/reset.d.ts +0 -5
  435. package/dist/commands/reset.js +0 -35
  436. package/dist/commands/resume.d.ts +0 -1
  437. package/dist/commands/resume.js +0 -44
  438. package/dist/commands/start.d.ts +0 -5
  439. package/dist/commands/start.js +0 -54
  440. package/dist/transition.d.ts +0 -52
  441. package/dist/transition.js +0 -656
  442. package/slash-commands/atdd.md +0 -1
  443. package/slash-commands/continuous-integration.md +0 -1
  444. package/slash-commands/create-dataflow.md +0 -1
  445. package/slash-commands/create-diagram.md +0 -1
  446. package/slash-commands/create-flowchart.md +0 -1
  447. package/slash-commands/create-wireframe.md +0 -1
  448. package/slash-commands/nfr-assess.md +0 -1
  449. package/slash-commands/tea.md +0 -1
  450. package/slash-commands/test-automate.md +0 -1
  451. package/slash-commands/test-design.md +0 -1
  452. package/slash-commands/test-framework.md +0 -1
  453. package/slash-commands/test-review.md +0 -1
  454. package/slash-commands/test-trace.md +0 -1
  455. package/slash-commands/validate-test-design.md +0 -1
@@ -1,330 +1,463 @@
1
- #!/bin/bash
2
- # Circuit Breaker Component for Ralph
3
- # Prevents runaway token consumption by detecting stagnation
4
- # Based on Michael Nygard's "Release It!" pattern
5
-
6
- # Source date utilities for cross-platform compatibility
7
- source "$(dirname "${BASH_SOURCE[0]}")/date_utils.sh"
8
-
9
- # Circuit Breaker States
10
- CB_STATE_CLOSED="CLOSED" # Normal operation, progress detected
11
- CB_STATE_HALF_OPEN="HALF_OPEN" # Monitoring mode, checking for recovery
12
- CB_STATE_OPEN="OPEN" # Failure detected, execution halted
13
-
14
- # Circuit Breaker Configuration
15
- # Use RALPH_DIR if set by main script, otherwise default to .ralph
16
- RALPH_DIR="${RALPH_DIR:-.ralph}"
17
- CB_STATE_FILE="$RALPH_DIR/.circuit_breaker_state"
18
- CB_HISTORY_FILE="$RALPH_DIR/.circuit_breaker_history"
19
- CB_NO_PROGRESS_THRESHOLD=3 # Open circuit after N loops with no progress
20
- CB_SAME_ERROR_THRESHOLD=5 # Open circuit after N loops with same error
21
- CB_OUTPUT_DECLINE_THRESHOLD=70 # Open circuit if output declines by >70%
22
-
23
- # Colors
24
- RED='\033[0;31m'
25
- GREEN='\033[0;32m'
26
- YELLOW='\033[1;33m'
27
- BLUE='\033[0;34m'
28
- NC='\033[0m'
29
-
30
- # Initialize circuit breaker
31
- init_circuit_breaker() {
32
- # Check if state file exists and is valid JSON
33
- if [[ -f "$CB_STATE_FILE" ]]; then
34
- if ! jq '.' "$CB_STATE_FILE" > /dev/null 2>&1; then
35
- # Corrupted, recreate
36
- rm -f "$CB_STATE_FILE"
37
- fi
38
- fi
39
-
40
- if [[ ! -f "$CB_STATE_FILE" ]]; then
41
- cat > "$CB_STATE_FILE" << EOF
42
- {
43
- "state": "$CB_STATE_CLOSED",
44
- "last_change": "$(get_iso_timestamp)",
45
- "consecutive_no_progress": 0,
46
- "consecutive_same_error": 0,
47
- "last_progress_loop": 0,
48
- "total_opens": 0,
49
- "reason": ""
50
- }
51
- EOF
52
- fi
53
-
54
- # Check if history file exists and is valid JSON
55
- if [[ -f "$CB_HISTORY_FILE" ]]; then
56
- if ! jq '.' "$CB_HISTORY_FILE" > /dev/null 2>&1; then
57
- # Corrupted, recreate
58
- rm -f "$CB_HISTORY_FILE"
59
- fi
60
- fi
61
-
62
- if [[ ! -f "$CB_HISTORY_FILE" ]]; then
63
- echo '[]' > "$CB_HISTORY_FILE"
64
- fi
65
- }
66
-
67
- # Get current circuit breaker state
68
- get_circuit_state() {
69
- if [[ ! -f "$CB_STATE_FILE" ]]; then
70
- echo "$CB_STATE_CLOSED"
71
- return
72
- fi
73
-
74
- jq -r '.state' "$CB_STATE_FILE" 2>/dev/null || echo "$CB_STATE_CLOSED"
75
- }
76
-
77
- # Check if circuit breaker allows execution
78
- can_execute() {
79
- local state=$(get_circuit_state)
80
-
81
- if [[ "$state" == "$CB_STATE_OPEN" ]]; then
82
- return 1 # Circuit is open, cannot execute
83
- else
84
- return 0 # Circuit is closed or half-open, can execute
85
- fi
86
- }
87
-
88
- # Record loop execution result
89
- record_loop_result() {
90
- local loop_number=$1
91
- local files_changed=$2
92
- local has_errors=$3
93
- local output_length=$4
94
-
95
- init_circuit_breaker
96
-
97
- local state_data=$(cat "$CB_STATE_FILE")
98
- local current_state=$(echo "$state_data" | jq -r '.state')
99
- local consecutive_no_progress=$(echo "$state_data" | jq -r '.consecutive_no_progress' | tr -d '[:space:]')
100
- local consecutive_same_error=$(echo "$state_data" | jq -r '.consecutive_same_error' | tr -d '[:space:]')
101
- local last_progress_loop=$(echo "$state_data" | jq -r '.last_progress_loop' | tr -d '[:space:]')
102
-
103
- # Ensure integers
104
- consecutive_no_progress=$((consecutive_no_progress + 0))
105
- consecutive_same_error=$((consecutive_same_error + 0))
106
- last_progress_loop=$((last_progress_loop + 0))
107
-
108
- # Detect progress
109
- local has_progress=false
110
- if [[ $files_changed -gt 0 ]]; then
111
- has_progress=true
112
- consecutive_no_progress=0
113
- last_progress_loop=$loop_number
114
- else
115
- consecutive_no_progress=$((consecutive_no_progress + 1))
116
- fi
117
-
118
- # Detect same error repetition
119
- if [[ "$has_errors" == "true" ]]; then
120
- consecutive_same_error=$((consecutive_same_error + 1))
121
- else
122
- consecutive_same_error=0
123
- fi
124
-
125
- # Determine new state and reason
126
- local new_state="$current_state"
127
- local reason=""
128
-
129
- # State transitions
130
- case $current_state in
131
- "$CB_STATE_CLOSED")
132
- # Normal operation - check for failure conditions
133
- if [[ $consecutive_no_progress -ge $CB_NO_PROGRESS_THRESHOLD ]]; then
134
- new_state="$CB_STATE_OPEN"
135
- reason="No progress detected in $consecutive_no_progress consecutive loops"
136
- elif [[ $consecutive_same_error -ge $CB_SAME_ERROR_THRESHOLD ]]; then
137
- new_state="$CB_STATE_OPEN"
138
- reason="Same error repeated in $consecutive_same_error consecutive loops"
139
- elif [[ $consecutive_no_progress -ge 2 ]]; then
140
- new_state="$CB_STATE_HALF_OPEN"
141
- reason="Monitoring: $consecutive_no_progress loops without progress"
142
- fi
143
- ;;
144
-
145
- "$CB_STATE_HALF_OPEN")
146
- # Monitoring mode - either recover or fail
147
- if [[ "$has_progress" == "true" ]]; then
148
- new_state="$CB_STATE_CLOSED"
149
- reason="Progress detected, circuit recovered"
150
- elif [[ $consecutive_no_progress -ge $CB_NO_PROGRESS_THRESHOLD ]]; then
151
- new_state="$CB_STATE_OPEN"
152
- reason="No recovery, opening circuit after $consecutive_no_progress loops"
153
- fi
154
- ;;
155
-
156
- "$CB_STATE_OPEN")
157
- # Circuit is open - stays open (manual intervention required)
158
- reason="Circuit breaker is open, execution halted"
159
- ;;
160
- esac
161
-
162
- # Update state file
163
- local total_opens=$(echo "$state_data" | jq -r '.total_opens' | tr -d '[:space:]')
164
- total_opens=$((total_opens + 0))
165
- if [[ "$new_state" == "$CB_STATE_OPEN" && "$current_state" != "$CB_STATE_OPEN" ]]; then
166
- total_opens=$((total_opens + 1))
167
- fi
168
-
169
- cat > "$CB_STATE_FILE" << EOF
170
- {
171
- "state": "$new_state",
172
- "last_change": "$(get_iso_timestamp)",
173
- "consecutive_no_progress": $consecutive_no_progress,
174
- "consecutive_same_error": $consecutive_same_error,
175
- "last_progress_loop": $last_progress_loop,
176
- "total_opens": $total_opens,
177
- "reason": "$reason",
178
- "current_loop": $loop_number
179
- }
180
- EOF
181
-
182
- # Log state transition
183
- if [[ "$new_state" != "$current_state" ]]; then
184
- log_circuit_transition "$current_state" "$new_state" "$reason" "$loop_number"
185
- fi
186
-
187
- # Return exit code based on new state
188
- if [[ "$new_state" == "$CB_STATE_OPEN" ]]; then
189
- return 1 # Circuit opened, signal to stop
190
- else
191
- return 0 # Can continue
192
- fi
193
- }
194
-
195
- # Log circuit breaker state transitions
196
- log_circuit_transition() {
197
- local from_state=$1
198
- local to_state=$2
199
- local reason=$3
200
- local loop_number=$4
201
-
202
- local history=$(cat "$CB_HISTORY_FILE")
203
- local transition="{
204
- \"timestamp\": \"$(get_iso_timestamp)\",
205
- \"loop\": $loop_number,
206
- \"from_state\": \"$from_state\",
207
- \"to_state\": \"$to_state\",
208
- \"reason\": \"$reason\"
209
- }"
210
-
211
- history=$(echo "$history" | jq ". += [$transition]")
212
- echo "$history" > "$CB_HISTORY_FILE"
213
-
214
- # Console log with colors
215
- case $to_state in
216
- "$CB_STATE_OPEN")
217
- echo -e "${RED}🚨 CIRCUIT BREAKER OPENED${NC}"
218
- echo -e "${RED}Reason: $reason${NC}"
219
- ;;
220
- "$CB_STATE_HALF_OPEN")
221
- echo -e "${YELLOW}⚠️ CIRCUIT BREAKER: Monitoring Mode${NC}"
222
- echo -e "${YELLOW}Reason: $reason${NC}"
223
- ;;
224
- "$CB_STATE_CLOSED")
225
- echo -e "${GREEN}✅ CIRCUIT BREAKER: Normal Operation${NC}"
226
- echo -e "${GREEN}Reason: $reason${NC}"
227
- ;;
228
- esac
229
- }
230
-
231
- # Display circuit breaker status
232
- show_circuit_status() {
233
- init_circuit_breaker
234
-
235
- local state_data=$(cat "$CB_STATE_FILE")
236
- local state=$(echo "$state_data" | jq -r '.state')
237
- local reason=$(echo "$state_data" | jq -r '.reason')
238
- local no_progress=$(echo "$state_data" | jq -r '.consecutive_no_progress')
239
- local last_progress=$(echo "$state_data" | jq -r '.last_progress_loop')
240
- local current_loop=$(echo "$state_data" | jq -r '.current_loop')
241
- local total_opens=$(echo "$state_data" | jq -r '.total_opens')
242
-
243
- local color=""
244
- local status_icon=""
245
-
246
- case $state in
247
- "$CB_STATE_CLOSED")
248
- color=$GREEN
249
- status_icon="✅"
250
- ;;
251
- "$CB_STATE_HALF_OPEN")
252
- color=$YELLOW
253
- status_icon="⚠️ "
254
- ;;
255
- "$CB_STATE_OPEN")
256
- color=$RED
257
- status_icon="🚨"
258
- ;;
259
- esac
260
-
261
- echo -e "${color}╔════════════════════════════════════════════════════════════╗${NC}"
262
- echo -e "${color}║ Circuit Breaker Status ║${NC}"
263
- echo -e "${color}╚════════════════════════════════════════════════════════════╝${NC}"
264
- echo -e "${color}State:${NC} $status_icon $state"
265
- echo -e "${color}Reason:${NC} $reason"
266
- echo -e "${color}Loops since progress:${NC} $no_progress"
267
- echo -e "${color}Last progress:${NC} Loop #$last_progress"
268
- echo -e "${color}Current loop:${NC} #$current_loop"
269
- echo -e "${color}Total opens:${NC} $total_opens"
270
- echo ""
271
- }
272
-
273
- # Reset circuit breaker (for manual intervention)
274
- reset_circuit_breaker() {
275
- local reason=${1:-"Manual reset"}
276
-
277
- cat > "$CB_STATE_FILE" << EOF
278
- {
279
- "state": "$CB_STATE_CLOSED",
280
- "last_change": "$(get_iso_timestamp)",
281
- "consecutive_no_progress": 0,
282
- "consecutive_same_error": 0,
283
- "last_progress_loop": 0,
284
- "total_opens": 0,
285
- "reason": "$reason"
286
- }
287
- EOF
288
-
289
- echo -e "${GREEN}✅ Circuit breaker reset to CLOSED state${NC}"
290
- }
291
-
292
- # Check if loop should halt (used in main loop)
293
- should_halt_execution() {
294
- local state=$(get_circuit_state)
295
-
296
- if [[ "$state" == "$CB_STATE_OPEN" ]]; then
297
- show_circuit_status
298
- echo ""
299
- echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}"
300
- echo -e "${RED}║ EXECUTION HALTED: Circuit Breaker Opened ║${NC}"
301
- echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}"
302
- echo ""
303
- echo -e "${YELLOW}Ralph has detected that no progress is being made.${NC}"
304
- echo ""
305
- echo -e "${YELLOW}Possible reasons:${NC}"
306
- echo " Project may be complete (check .ralph/@fix_plan.md)"
307
- echo " Claude may be stuck on an error"
308
- echo " .ralph/PROMPT.md may need clarification"
309
- echo " Manual intervention may be required"
310
- echo ""
311
- echo -e "${YELLOW}To continue:${NC}"
312
- echo " 1. Review recent logs: tail -20 .ralph/logs/ralph.log"
313
- echo " 2. Check Claude output: ls -lt .ralph/logs/claude_output_*.log | head -1"
314
- echo " 3. Update .ralph/@fix_plan.md if needed"
315
- echo " 4. Reset circuit breaker: ralph --reset-circuit"
316
- echo ""
317
- return 0 # Signal to halt
318
- else
319
- return 1 # Can continue
320
- fi
321
- }
322
-
323
- # Export functions
324
- export -f init_circuit_breaker
325
- export -f get_circuit_state
326
- export -f can_execute
327
- export -f record_loop_result
328
- export -f show_circuit_status
329
- export -f reset_circuit_breaker
330
- export -f should_halt_execution
1
+ #!/bin/bash
2
+ # Circuit Breaker Component for Ralph
3
+ # Prevents runaway token consumption by detecting stagnation
4
+ # Based on Michael Nygard's "Release It!" pattern
5
+
6
+ # Source date utilities for cross-platform compatibility
7
+ source "$(dirname "${BASH_SOURCE[0]}")/date_utils.sh"
8
+
9
+ # Circuit Breaker States
10
+ CB_STATE_CLOSED="CLOSED" # Normal operation, progress detected
11
+ CB_STATE_HALF_OPEN="HALF_OPEN" # Monitoring mode, checking for recovery
12
+ CB_STATE_OPEN="OPEN" # Failure detected, execution halted
13
+
14
+ # Circuit Breaker Configuration
15
+ # Use RALPH_DIR if set by main script, otherwise default to .ralph
16
+ RALPH_DIR="${RALPH_DIR:-.ralph}"
17
+ CB_STATE_FILE="$RALPH_DIR/.circuit_breaker_state"
18
+ CB_HISTORY_FILE="$RALPH_DIR/.circuit_breaker_history"
19
+ # Configurable thresholds - override via environment variables:
20
+ # Example: CB_NO_PROGRESS_THRESHOLD=10 ralph --monitor
21
+ CB_NO_PROGRESS_THRESHOLD=${CB_NO_PROGRESS_THRESHOLD:-3} # Open circuit after N loops with no progress
22
+ CB_SAME_ERROR_THRESHOLD=${CB_SAME_ERROR_THRESHOLD:-5} # Open circuit after N loops with same error
23
+ CB_OUTPUT_DECLINE_THRESHOLD=${CB_OUTPUT_DECLINE_THRESHOLD:-70} # Open circuit if output declines by >70%
24
+ CB_PERMISSION_DENIAL_THRESHOLD=${CB_PERMISSION_DENIAL_THRESHOLD:-2} # Open circuit after N loops with permission denials (Issue #101)
25
+ CB_COOLDOWN_MINUTES=${CB_COOLDOWN_MINUTES:-30} # Minutes before OPEN → HALF_OPEN auto-recovery (Issue #160)
26
+ CB_AUTO_RESET=${CB_AUTO_RESET:-false} # Reset to CLOSED on startup instead of waiting for cooldown
27
+
28
+ # Colors
29
+ RED='\033[0;31m'
30
+ GREEN='\033[0;32m'
31
+ YELLOW='\033[1;33m'
32
+ BLUE='\033[0;34m'
33
+ NC='\033[0m'
34
+
35
+ # Initialize circuit breaker
36
+ init_circuit_breaker() {
37
+ # Check if state file exists and is valid JSON
38
+ if [[ -f "$CB_STATE_FILE" ]]; then
39
+ if ! jq '.' "$CB_STATE_FILE" > /dev/null 2>&1; then
40
+ # Corrupted, recreate
41
+ rm -f "$CB_STATE_FILE"
42
+ fi
43
+ fi
44
+
45
+ if [[ ! -f "$CB_STATE_FILE" ]]; then
46
+ cat > "$CB_STATE_FILE" << EOF
47
+ {
48
+ "state": "$CB_STATE_CLOSED",
49
+ "last_change": "$(get_iso_timestamp)",
50
+ "consecutive_no_progress": 0,
51
+ "consecutive_same_error": 0,
52
+ "consecutive_permission_denials": 0,
53
+ "last_progress_loop": 0,
54
+ "total_opens": 0,
55
+ "reason": ""
56
+ }
57
+ EOF
58
+ fi
59
+
60
+ # Ensure history file exists before any transition logging
61
+ if [[ -f "$CB_HISTORY_FILE" ]]; then
62
+ if ! jq '.' "$CB_HISTORY_FILE" > /dev/null 2>&1; then
63
+ # Corrupted, recreate
64
+ rm -f "$CB_HISTORY_FILE"
65
+ fi
66
+ fi
67
+
68
+ if [[ ! -f "$CB_HISTORY_FILE" ]]; then
69
+ echo '[]' > "$CB_HISTORY_FILE"
70
+ fi
71
+
72
+ # Auto-recovery: check if OPEN state should transition (Issue #160)
73
+ local current_state
74
+ current_state=$(jq -r '.state' "$CB_STATE_FILE" 2>/dev/null || echo "$CB_STATE_CLOSED")
75
+
76
+ if [[ "$current_state" == "$CB_STATE_OPEN" ]]; then
77
+ if [[ "$CB_AUTO_RESET" == "true" ]]; then
78
+ # Auto-reset: bypass cooldown, go straight to CLOSED
79
+ local current_loop total_opens
80
+ current_loop=$(jq -r '.current_loop // 0' "$CB_STATE_FILE" 2>/dev/null || echo "0")
81
+ total_opens=$(jq -r '.total_opens // 0' "$CB_STATE_FILE" 2>/dev/null || echo "0")
82
+ log_circuit_transition "$CB_STATE_OPEN" "$CB_STATE_CLOSED" "Auto-reset on startup (CB_AUTO_RESET=true)" "$current_loop"
83
+
84
+ cat > "$CB_STATE_FILE" << EOF
85
+ {
86
+ "state": "$CB_STATE_CLOSED",
87
+ "last_change": "$(get_iso_timestamp)",
88
+ "consecutive_no_progress": 0,
89
+ "consecutive_same_error": 0,
90
+ "consecutive_permission_denials": 0,
91
+ "last_progress_loop": 0,
92
+ "total_opens": $total_opens,
93
+ "reason": "Auto-reset on startup"
94
+ }
95
+ EOF
96
+ else
97
+ # Cooldown: check if enough time has elapsed to transition to HALF_OPEN
98
+ local opened_at
99
+ opened_at=$(jq -r '.opened_at // .last_change // ""' "$CB_STATE_FILE" 2>/dev/null || echo "")
100
+
101
+ if [[ -n "$opened_at" && "$opened_at" != "null" ]]; then
102
+ local opened_epoch current_epoch elapsed_minutes
103
+ opened_epoch=$(parse_iso_to_epoch "$opened_at")
104
+ current_epoch=$(date +%s)
105
+ elapsed_minutes=$(( (current_epoch - opened_epoch) / 60 ))
106
+
107
+ if [[ $elapsed_minutes -ge 0 && $elapsed_minutes -ge $CB_COOLDOWN_MINUTES ]]; then
108
+ local current_loop
109
+ current_loop=$(jq -r '.current_loop // 0' "$CB_STATE_FILE" 2>/dev/null || echo "0")
110
+ log_circuit_transition "$CB_STATE_OPEN" "$CB_STATE_HALF_OPEN" "Cooldown elapsed (${elapsed_minutes}m >= ${CB_COOLDOWN_MINUTES}m)" "$current_loop"
111
+
112
+ # Preserve counters but transition state
113
+ local state_data
114
+ state_data=$(cat "$CB_STATE_FILE")
115
+ echo "$state_data" | jq \
116
+ --arg state "$CB_STATE_HALF_OPEN" \
117
+ --arg last_change "$(get_iso_timestamp)" \
118
+ --arg reason "Cooldown recovery: ${elapsed_minutes}m elapsed" \
119
+ '.state = $state | .last_change = $last_change | .reason = $reason' \
120
+ > "$CB_STATE_FILE"
121
+ fi
122
+ # If elapsed_minutes < 0 (clock skew), stay OPEN safely
123
+ fi
124
+ fi
125
+ fi
126
+ }
127
+
128
+ # Get current circuit breaker state
129
+ get_circuit_state() {
130
+ if [[ ! -f "$CB_STATE_FILE" ]]; then
131
+ echo "$CB_STATE_CLOSED"
132
+ return
133
+ fi
134
+
135
+ jq -r '.state' "$CB_STATE_FILE" 2>/dev/null || echo "$CB_STATE_CLOSED"
136
+ }
137
+
138
+ # Check if circuit breaker allows execution
139
+ can_execute() {
140
+ local state=$(get_circuit_state)
141
+
142
+ if [[ "$state" == "$CB_STATE_OPEN" ]]; then
143
+ return 1 # Circuit is open, cannot execute
144
+ else
145
+ return 0 # Circuit is closed or half-open, can execute
146
+ fi
147
+ }
148
+
149
+ # Record loop execution result
150
+ record_loop_result() {
151
+ local loop_number=$1
152
+ local files_changed=$2
153
+ local has_errors=$3
154
+ local output_length=$4
155
+
156
+ init_circuit_breaker
157
+
158
+ local state_data=$(cat "$CB_STATE_FILE")
159
+ local current_state=$(echo "$state_data" | jq -r '.state')
160
+ local consecutive_no_progress=$(echo "$state_data" | jq -r '.consecutive_no_progress' | tr -d '[:space:]')
161
+ local consecutive_same_error=$(echo "$state_data" | jq -r '.consecutive_same_error' | tr -d '[:space:]')
162
+ local consecutive_permission_denials=$(echo "$state_data" | jq -r '.consecutive_permission_denials // 0' | tr -d '[:space:]')
163
+ local last_progress_loop=$(echo "$state_data" | jq -r '.last_progress_loop' | tr -d '[:space:]')
164
+
165
+ # Ensure integers
166
+ consecutive_no_progress=$((consecutive_no_progress + 0))
167
+ consecutive_same_error=$((consecutive_same_error + 0))
168
+ consecutive_permission_denials=$((consecutive_permission_denials + 0))
169
+ last_progress_loop=$((last_progress_loop + 0))
170
+
171
+ # Detect progress from multiple sources:
172
+ # 1. Files changed (git diff)
173
+ # 2. Completion signal in response analysis (STATUS: COMPLETE or has_completion_signal)
174
+ # 3. Claude explicitly reported files modified in RALPH_STATUS block
175
+ local has_progress=false
176
+ local has_completion_signal=false
177
+ local ralph_files_modified=0
178
+
179
+ # Check response analysis file for completion signals and reported file changes
180
+ local response_analysis_file="$RALPH_DIR/.response_analysis"
181
+ if [[ -f "$response_analysis_file" ]]; then
182
+ # Read completion signal - STATUS: COMPLETE counts as progress even without git changes
183
+ has_completion_signal=$(jq -r '.analysis.has_completion_signal // false' "$response_analysis_file" 2>/dev/null || echo "false")
184
+
185
+ # Also check exit_signal (Claude explicitly signaling completion)
186
+ local exit_signal
187
+ exit_signal=$(jq -r '.analysis.exit_signal // false' "$response_analysis_file" 2>/dev/null || echo "false")
188
+ if [[ "$exit_signal" == "true" ]]; then
189
+ has_completion_signal="true"
190
+ fi
191
+
192
+ # Check if Claude reported files modified (may differ from git diff if already committed)
193
+ ralph_files_modified=$(jq -r '.analysis.files_modified // 0' "$response_analysis_file" 2>/dev/null || echo "0")
194
+ ralph_files_modified=$((ralph_files_modified + 0))
195
+ fi
196
+
197
+ # Track permission denials (Issue #101)
198
+ local has_permission_denials="false"
199
+ if [[ -f "$response_analysis_file" ]]; then
200
+ has_permission_denials=$(jq -r '.analysis.has_permission_denials // false' "$response_analysis_file" 2>/dev/null || echo "false")
201
+ fi
202
+
203
+ if [[ "$has_permission_denials" == "true" ]]; then
204
+ consecutive_permission_denials=$((consecutive_permission_denials + 1))
205
+ else
206
+ consecutive_permission_denials=0
207
+ fi
208
+
209
+ # Determine if progress was made
210
+ if [[ $files_changed -gt 0 ]]; then
211
+ # Git shows uncommitted changes - clear progress
212
+ has_progress=true
213
+ consecutive_no_progress=0
214
+ last_progress_loop=$loop_number
215
+ elif [[ "$has_completion_signal" == "true" ]]; then
216
+ # Claude reported STATUS: COMPLETE - this is progress even without git changes
217
+ # (work may have been committed already, or Claude finished analyzing/planning)
218
+ has_progress=true
219
+ consecutive_no_progress=0
220
+ last_progress_loop=$loop_number
221
+ elif [[ $ralph_files_modified -gt 0 ]]; then
222
+ # Claude reported modifying files (may be committed already)
223
+ has_progress=true
224
+ consecutive_no_progress=0
225
+ last_progress_loop=$loop_number
226
+ else
227
+ consecutive_no_progress=$((consecutive_no_progress + 1))
228
+ fi
229
+
230
+ # Detect same error repetition
231
+ if [[ "$has_errors" == "true" ]]; then
232
+ consecutive_same_error=$((consecutive_same_error + 1))
233
+ else
234
+ consecutive_same_error=0
235
+ fi
236
+
237
+ # Determine new state and reason
238
+ local new_state="$current_state"
239
+ local reason=""
240
+
241
+ # State transitions
242
+ case $current_state in
243
+ "$CB_STATE_CLOSED")
244
+ # Normal operation - check for failure conditions
245
+ # Permission denials take highest priority (Issue #101)
246
+ if [[ $consecutive_permission_denials -ge $CB_PERMISSION_DENIAL_THRESHOLD ]]; then
247
+ new_state="$CB_STATE_OPEN"
248
+ reason="Permission denied in $consecutive_permission_denials consecutive loops - update ALLOWED_TOOLS in .ralphrc"
249
+ elif [[ $consecutive_no_progress -ge $CB_NO_PROGRESS_THRESHOLD ]]; then
250
+ new_state="$CB_STATE_OPEN"
251
+ reason="No progress detected in $consecutive_no_progress consecutive loops"
252
+ elif [[ $consecutive_same_error -ge $CB_SAME_ERROR_THRESHOLD ]]; then
253
+ new_state="$CB_STATE_OPEN"
254
+ reason="Same error repeated in $consecutive_same_error consecutive loops"
255
+ elif [[ $consecutive_no_progress -ge 2 ]]; then
256
+ new_state="$CB_STATE_HALF_OPEN"
257
+ reason="Monitoring: $consecutive_no_progress loops without progress"
258
+ fi
259
+ ;;
260
+
261
+ "$CB_STATE_HALF_OPEN")
262
+ # Monitoring mode - either recover or fail
263
+ # Permission denials take highest priority (Issue #101)
264
+ if [[ $consecutive_permission_denials -ge $CB_PERMISSION_DENIAL_THRESHOLD ]]; then
265
+ new_state="$CB_STATE_OPEN"
266
+ reason="Permission denied in $consecutive_permission_denials consecutive loops - update ALLOWED_TOOLS in .ralphrc"
267
+ elif [[ "$has_progress" == "true" ]]; then
268
+ new_state="$CB_STATE_CLOSED"
269
+ reason="Progress detected, circuit recovered"
270
+ elif [[ $consecutive_no_progress -ge $CB_NO_PROGRESS_THRESHOLD ]]; then
271
+ new_state="$CB_STATE_OPEN"
272
+ reason="No recovery, opening circuit after $consecutive_no_progress loops"
273
+ fi
274
+ ;;
275
+
276
+ "$CB_STATE_OPEN")
277
+ # Circuit is open - stays open (auto-recovery handled in init_circuit_breaker)
278
+ reason="Circuit breaker is open, execution halted"
279
+ ;;
280
+ esac
281
+
282
+ # Update state file
283
+ local total_opens=$(echo "$state_data" | jq -r '.total_opens' | tr -d '[:space:]')
284
+ total_opens=$((total_opens + 0))
285
+ if [[ "$new_state" == "$CB_STATE_OPEN" && "$current_state" != "$CB_STATE_OPEN" ]]; then
286
+ total_opens=$((total_opens + 1))
287
+ fi
288
+
289
+ # Determine opened_at: set when entering OPEN, preserve when staying OPEN
290
+ local opened_at=""
291
+ if [[ "$new_state" == "$CB_STATE_OPEN" && "$current_state" != "$CB_STATE_OPEN" ]]; then
292
+ # Entering OPEN state - record the timestamp
293
+ opened_at=$(get_iso_timestamp)
294
+ elif [[ "$new_state" == "$CB_STATE_OPEN" && "$current_state" == "$CB_STATE_OPEN" ]]; then
295
+ # Staying OPEN - preserve existing opened_at (fall back to last_change for old state files)
296
+ opened_at=$(echo "$state_data" | jq -r '.opened_at // .last_change // ""' 2>/dev/null)
297
+ fi
298
+
299
+ cat > "$CB_STATE_FILE" << EOF
300
+ {
301
+ "state": "$new_state",
302
+ "last_change": "$(get_iso_timestamp)",
303
+ "consecutive_no_progress": $consecutive_no_progress,
304
+ "consecutive_same_error": $consecutive_same_error,
305
+ "consecutive_permission_denials": $consecutive_permission_denials,
306
+ "last_progress_loop": $last_progress_loop,
307
+ "total_opens": $total_opens,
308
+ "reason": "$reason",
309
+ "current_loop": $loop_number$(if [[ -n "$opened_at" ]]; then echo ",
310
+ \"opened_at\": \"$opened_at\""; fi)
311
+ }
312
+ EOF
313
+
314
+ # Log state transition
315
+ if [[ "$new_state" != "$current_state" ]]; then
316
+ log_circuit_transition "$current_state" "$new_state" "$reason" "$loop_number"
317
+ fi
318
+
319
+ # Return exit code based on new state
320
+ if [[ "$new_state" == "$CB_STATE_OPEN" ]]; then
321
+ return 1 # Circuit opened, signal to stop
322
+ else
323
+ return 0 # Can continue
324
+ fi
325
+ }
326
+
327
+ # Log circuit breaker state transitions
328
+ log_circuit_transition() {
329
+ local from_state=$1
330
+ local to_state=$2
331
+ local reason=$3
332
+ local loop_number=$4
333
+
334
+ local history=$(cat "$CB_HISTORY_FILE")
335
+ local transition="{
336
+ \"timestamp\": \"$(get_iso_timestamp)\",
337
+ \"loop\": $loop_number,
338
+ \"from_state\": \"$from_state\",
339
+ \"to_state\": \"$to_state\",
340
+ \"reason\": \"$reason\"
341
+ }"
342
+
343
+ history=$(echo "$history" | jq ". += [$transition]")
344
+ echo "$history" > "$CB_HISTORY_FILE"
345
+
346
+ # Console log with colors
347
+ case $to_state in
348
+ "$CB_STATE_OPEN")
349
+ echo -e "${RED}🚨 CIRCUIT BREAKER OPENED${NC}"
350
+ echo -e "${RED}Reason: $reason${NC}"
351
+ ;;
352
+ "$CB_STATE_HALF_OPEN")
353
+ echo -e "${YELLOW}⚠️ CIRCUIT BREAKER: Monitoring Mode${NC}"
354
+ echo -e "${YELLOW}Reason: $reason${NC}"
355
+ ;;
356
+ "$CB_STATE_CLOSED")
357
+ echo -e "${GREEN}✅ CIRCUIT BREAKER: Normal Operation${NC}"
358
+ echo -e "${GREEN}Reason: $reason${NC}"
359
+ ;;
360
+ esac
361
+ }
362
+
363
+ # Display circuit breaker status
364
+ show_circuit_status() {
365
+ init_circuit_breaker
366
+
367
+ local state_data=$(cat "$CB_STATE_FILE")
368
+ local state=$(echo "$state_data" | jq -r '.state')
369
+ local reason=$(echo "$state_data" | jq -r '.reason')
370
+ local no_progress=$(echo "$state_data" | jq -r '.consecutive_no_progress')
371
+ local last_progress=$(echo "$state_data" | jq -r '.last_progress_loop')
372
+ local current_loop=$(echo "$state_data" | jq -r '.current_loop')
373
+ local total_opens=$(echo "$state_data" | jq -r '.total_opens')
374
+
375
+ local color=""
376
+ local status_icon=""
377
+
378
+ case $state in
379
+ "$CB_STATE_CLOSED")
380
+ color=$GREEN
381
+ status_icon="✅"
382
+ ;;
383
+ "$CB_STATE_HALF_OPEN")
384
+ color=$YELLOW
385
+ status_icon="⚠️ "
386
+ ;;
387
+ "$CB_STATE_OPEN")
388
+ color=$RED
389
+ status_icon="🚨"
390
+ ;;
391
+ esac
392
+
393
+ echo -e "${color}╔════════════════════════════════════════════════════════════╗${NC}"
394
+ echo -e "${color}║ Circuit Breaker Status ║${NC}"
395
+ echo -e "${color}╚════════════════════════════════════════════════════════════╝${NC}"
396
+ echo -e "${color}State:${NC} $status_icon $state"
397
+ echo -e "${color}Reason:${NC} $reason"
398
+ echo -e "${color}Loops since progress:${NC} $no_progress"
399
+ echo -e "${color}Last progress:${NC} Loop #$last_progress"
400
+ echo -e "${color}Current loop:${NC} #$current_loop"
401
+ echo -e "${color}Total opens:${NC} $total_opens"
402
+ echo ""
403
+ }
404
+
405
+ # Reset circuit breaker (for manual intervention)
406
+ reset_circuit_breaker() {
407
+ local reason=${1:-"Manual reset"}
408
+
409
+ cat > "$CB_STATE_FILE" << EOF
410
+ {
411
+ "state": "$CB_STATE_CLOSED",
412
+ "last_change": "$(get_iso_timestamp)",
413
+ "consecutive_no_progress": 0,
414
+ "consecutive_same_error": 0,
415
+ "consecutive_permission_denials": 0,
416
+ "last_progress_loop": 0,
417
+ "total_opens": 0,
418
+ "reason": "$reason"
419
+ }
420
+ EOF
421
+
422
+ echo -e "${GREEN}✅ Circuit breaker reset to CLOSED state${NC}"
423
+ }
424
+
425
+ # Check if loop should halt (used in main loop)
426
+ should_halt_execution() {
427
+ local state=$(get_circuit_state)
428
+
429
+ if [[ "$state" == "$CB_STATE_OPEN" ]]; then
430
+ show_circuit_status
431
+ echo ""
432
+ echo -e "${RED}╔════════════════════════════════════════════════════════════╗${NC}"
433
+ echo -e "${RED}║ EXECUTION HALTED: Circuit Breaker Opened ║${NC}"
434
+ echo -e "${RED}╚════════════════════════════════════════════════════════════╝${NC}"
435
+ echo ""
436
+ echo -e "${YELLOW}Ralph has detected that no progress is being made.${NC}"
437
+ echo ""
438
+ echo -e "${YELLOW}Possible reasons:${NC}"
439
+ echo " • Project may be complete (check .ralph/fix_plan.md)"
440
+ echo " • Claude may be stuck on an error"
441
+ echo " • .ralph/PROMPT.md may need clarification"
442
+ echo " • Manual intervention may be required"
443
+ echo ""
444
+ echo -e "${YELLOW}To continue:${NC}"
445
+ echo " 1. Review recent logs: tail -20 .ralph/logs/ralph.log"
446
+ echo " 2. Check Claude output: ls -lt .ralph/logs/claude_output_*.log | head -1"
447
+ echo " 3. Update .ralph/fix_plan.md if needed"
448
+ echo " 4. Reset circuit breaker: ralph --reset-circuit"
449
+ echo ""
450
+ return 0 # Signal to halt
451
+ else
452
+ return 1 # Can continue
453
+ fi
454
+ }
455
+
456
+ # Export functions
457
+ export -f init_circuit_breaker
458
+ export -f get_circuit_state
459
+ export -f can_execute
460
+ export -f record_loop_result
461
+ export -f show_circuit_status
462
+ export -f reset_circuit_breaker
463
+ export -f should_halt_execution