bmalph 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 (396) hide show
  1. package/README.md +217 -0
  2. package/bin/bmalph.js +14 -0
  3. package/bmad/bmm/agents/analyst.agent.yaml +36 -0
  4. package/bmad/bmm/agents/architect.agent.yaml +28 -0
  5. package/bmad/bmm/agents/dev.agent.yaml +38 -0
  6. package/bmad/bmm/agents/pm.agent.yaml +46 -0
  7. package/bmad/bmm/agents/quick-flow-solo-dev.agent.yaml +32 -0
  8. package/bmad/bmm/agents/sm.agent.yaml +36 -0
  9. package/bmad/bmm/agents/tea.agent.yaml +63 -0
  10. package/bmad/bmm/agents/tech-writer/tech-writer-sidecar/documentation-standards.md +224 -0
  11. package/bmad/bmm/agents/tech-writer/tech-writer.agent.yaml +45 -0
  12. package/bmad/bmm/agents/ux-designer.agent.yaml +26 -0
  13. package/bmad/bmm/data/project-context-template.md +26 -0
  14. package/bmad/bmm/module-help.csv +31 -0
  15. package/bmad/bmm/module.yaml +44 -0
  16. package/bmad/bmm/sub-modules/claude-code/config.yaml +4 -0
  17. package/bmad/bmm/sub-modules/claude-code/injections.yaml +242 -0
  18. package/bmad/bmm/sub-modules/claude-code/readme.md +87 -0
  19. package/bmad/bmm/teams/default-party.csv +21 -0
  20. package/bmad/bmm/teams/team-fullstack.yaml +12 -0
  21. package/bmad/bmm/testarch/knowledge/adr-quality-readiness-checklist.md +350 -0
  22. package/bmad/bmm/testarch/knowledge/api-request.md +442 -0
  23. package/bmad/bmm/testarch/knowledge/api-testing-patterns.md +843 -0
  24. package/bmad/bmm/testarch/knowledge/auth-session.md +552 -0
  25. package/bmad/bmm/testarch/knowledge/burn-in.md +273 -0
  26. package/bmad/bmm/testarch/knowledge/ci-burn-in.md +675 -0
  27. package/bmad/bmm/testarch/knowledge/component-tdd.md +486 -0
  28. package/bmad/bmm/testarch/knowledge/contract-testing.md +957 -0
  29. package/bmad/bmm/testarch/knowledge/data-factories.md +500 -0
  30. package/bmad/bmm/testarch/knowledge/email-auth.md +721 -0
  31. package/bmad/bmm/testarch/knowledge/error-handling.md +725 -0
  32. package/bmad/bmm/testarch/knowledge/feature-flags.md +750 -0
  33. package/bmad/bmm/testarch/knowledge/file-utils.md +463 -0
  34. package/bmad/bmm/testarch/knowledge/fixture-architecture.md +401 -0
  35. package/bmad/bmm/testarch/knowledge/fixtures-composition.md +382 -0
  36. package/bmad/bmm/testarch/knowledge/intercept-network-call.md +430 -0
  37. package/bmad/bmm/testarch/knowledge/log.md +429 -0
  38. package/bmad/bmm/testarch/knowledge/network-error-monitor.md +405 -0
  39. package/bmad/bmm/testarch/knowledge/network-first.md +486 -0
  40. package/bmad/bmm/testarch/knowledge/network-recorder.md +527 -0
  41. package/bmad/bmm/testarch/knowledge/nfr-criteria.md +670 -0
  42. package/bmad/bmm/testarch/knowledge/overview.md +286 -0
  43. package/bmad/bmm/testarch/knowledge/playwright-config.md +730 -0
  44. package/bmad/bmm/testarch/knowledge/probability-impact.md +601 -0
  45. package/bmad/bmm/testarch/knowledge/recurse.md +421 -0
  46. package/bmad/bmm/testarch/knowledge/risk-governance.md +615 -0
  47. package/bmad/bmm/testarch/knowledge/selective-testing.md +732 -0
  48. package/bmad/bmm/testarch/knowledge/selector-resilience.md +527 -0
  49. package/bmad/bmm/testarch/knowledge/test-healing-patterns.md +644 -0
  50. package/bmad/bmm/testarch/knowledge/test-levels-framework.md +473 -0
  51. package/bmad/bmm/testarch/knowledge/test-priorities-matrix.md +373 -0
  52. package/bmad/bmm/testarch/knowledge/test-quality.md +664 -0
  53. package/bmad/bmm/testarch/knowledge/timing-debugging.md +372 -0
  54. package/bmad/bmm/testarch/knowledge/visual-debugging.md +524 -0
  55. package/bmad/bmm/testarch/tea-index.csv +35 -0
  56. package/bmad/bmm/workflows/1-analysis/create-product-brief/product-brief.template.md +10 -0
  57. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-01-init.md +177 -0
  58. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +161 -0
  59. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +199 -0
  60. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +202 -0
  61. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +205 -0
  62. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +219 -0
  63. package/bmad/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +162 -0
  64. package/bmad/bmm/workflows/1-analysis/create-product-brief/workflow.md +58 -0
  65. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-01-init.md +137 -0
  66. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +229 -0
  67. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +238 -0
  68. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +206 -0
  69. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +234 -0
  70. package/bmad/bmm/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +443 -0
  71. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +182 -0
  72. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +237 -0
  73. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-insights.md +200 -0
  74. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +249 -0
  75. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +259 -0
  76. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +177 -0
  77. package/bmad/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +475 -0
  78. package/bmad/bmm/workflows/1-analysis/research/research.template.md +29 -0
  79. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-01-init.md +137 -0
  80. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +239 -0
  81. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +248 -0
  82. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +202 -0
  83. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +239 -0
  84. package/bmad/bmm/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +486 -0
  85. package/bmad/bmm/workflows/1-analysis/research/workflow.md +173 -0
  86. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md +135 -0
  87. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +127 -0
  88. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +190 -0
  89. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +216 -0
  90. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +219 -0
  91. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +234 -0
  92. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +252 -0
  93. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +254 -0
  94. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +224 -0
  95. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +224 -0
  96. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +241 -0
  97. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +248 -0
  98. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +237 -0
  99. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +264 -0
  100. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +171 -0
  101. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +13 -0
  102. package/bmad/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +43 -0
  103. package/bmad/bmm/workflows/2-plan-workflows/prd/data/domain-complexity.csv +13 -0
  104. package/bmad/bmm/workflows/2-plan-workflows/prd/data/prd-purpose.md +197 -0
  105. package/bmad/bmm/workflows/2-plan-workflows/prd/data/project-types.csv +11 -0
  106. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-01-init.md +191 -0
  107. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-01b-continue.md +153 -0
  108. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-02-discovery.md +224 -0
  109. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-03-success.md +226 -0
  110. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-04-journeys.md +213 -0
  111. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-05-domain.md +207 -0
  112. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-06-innovation.md +226 -0
  113. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-07-project-type.md +237 -0
  114. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-08-scoping.md +228 -0
  115. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-09-functional.md +231 -0
  116. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-10-nonfunctional.md +242 -0
  117. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-11-polish.md +217 -0
  118. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-c/step-12-complete.md +124 -0
  119. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-01-discovery.md +247 -0
  120. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-01b-legacy-conversion.md +208 -0
  121. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-02-review.md +249 -0
  122. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-03-edit.md +253 -0
  123. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-e/step-e-04-complete.md +168 -0
  124. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-01-discovery.md +218 -0
  125. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-02-format-detection.md +191 -0
  126. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-02b-parity-check.md +209 -0
  127. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-03-density-validation.md +174 -0
  128. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +214 -0
  129. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-05-measurability-validation.md +228 -0
  130. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-06-traceability-validation.md +217 -0
  131. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +205 -0
  132. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +243 -0
  133. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-09-project-type-validation.md +263 -0
  134. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-10-smart-validation.md +209 -0
  135. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +264 -0
  136. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-12-completeness-validation.md +242 -0
  137. package/bmad/bmm/workflows/2-plan-workflows/prd/steps-v/step-v-13-report-complete.md +231 -0
  138. package/bmad/bmm/workflows/2-plan-workflows/prd/templates/prd-template.md +10 -0
  139. package/bmad/bmm/workflows/2-plan-workflows/prd/validation-report-prd-workflow.md +433 -0
  140. package/bmad/bmm/workflows/2-plan-workflows/prd/workflow.md +150 -0
  141. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +190 -0
  142. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +178 -0
  143. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +179 -0
  144. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +139 -0
  145. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +252 -0
  146. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +135 -0
  147. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/templates/readiness-report-template.md +4 -0
  148. package/bmad/bmm/workflows/3-solutioning/check-implementation-readiness/workflow.md +55 -0
  149. package/bmad/bmm/workflows/3-solutioning/create-architecture/architecture-decision-template.md +12 -0
  150. package/bmad/bmm/workflows/3-solutioning/create-architecture/data/domain-complexity.csv +11 -0
  151. package/bmad/bmm/workflows/3-solutioning/create-architecture/data/project-types.csv +7 -0
  152. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-01-init.md +153 -0
  153. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +164 -0
  154. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +224 -0
  155. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +331 -0
  156. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +318 -0
  157. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +359 -0
  158. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +379 -0
  159. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +359 -0
  160. package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +76 -0
  161. package/bmad/bmm/workflows/3-solutioning/create-architecture/workflow.md +50 -0
  162. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +259 -0
  163. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +233 -0
  164. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +272 -0
  165. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +149 -0
  166. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md +57 -0
  167. package/bmad/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +59 -0
  168. package/bmad/bmm/workflows/4-implementation/code-review/checklist.md +23 -0
  169. package/bmad/bmm/workflows/4-implementation/code-review/instructions.xml +227 -0
  170. package/bmad/bmm/workflows/4-implementation/code-review/workflow.yaml +51 -0
  171. package/bmad/bmm/workflows/4-implementation/correct-course/checklist.md +288 -0
  172. package/bmad/bmm/workflows/4-implementation/correct-course/instructions.md +206 -0
  173. package/bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml +60 -0
  174. package/bmad/bmm/workflows/4-implementation/create-story/checklist.md +358 -0
  175. package/bmad/bmm/workflows/4-implementation/create-story/instructions.xml +345 -0
  176. package/bmad/bmm/workflows/4-implementation/create-story/template.md +49 -0
  177. package/bmad/bmm/workflows/4-implementation/create-story/workflow.yaml +61 -0
  178. package/bmad/bmm/workflows/4-implementation/dev-story/checklist.md +80 -0
  179. package/bmad/bmm/workflows/4-implementation/dev-story/instructions.xml +410 -0
  180. package/bmad/bmm/workflows/4-implementation/dev-story/workflow.yaml +27 -0
  181. package/bmad/bmm/workflows/4-implementation/retrospective/instructions.md +1443 -0
  182. package/bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml +58 -0
  183. package/bmad/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -0
  184. package/bmad/bmm/workflows/4-implementation/sprint-planning/instructions.md +225 -0
  185. package/bmad/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -0
  186. package/bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +54 -0
  187. package/bmad/bmm/workflows/4-implementation/sprint-status/instructions.md +229 -0
  188. package/bmad/bmm/workflows/4-implementation/sprint-status/workflow.yaml +36 -0
  189. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/data/project-levels.yaml +59 -0
  190. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-01-mode-detection.md +156 -0
  191. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-02-context-gathering.md +120 -0
  192. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-03-execute.md +113 -0
  193. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-04-self-check.md +113 -0
  194. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +106 -0
  195. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-06-resolve-findings.md +140 -0
  196. package/bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +50 -0
  197. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-01-understand.md +189 -0
  198. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-02-investigate.md +144 -0
  199. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-03-generate.md +128 -0
  200. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +191 -0
  201. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/tech-spec-template.md +74 -0
  202. package/bmad/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +79 -0
  203. package/bmad/bmm/workflows/document-project/checklist.md +245 -0
  204. package/bmad/bmm/workflows/document-project/documentation-requirements.csv +12 -0
  205. package/bmad/bmm/workflows/document-project/instructions.md +221 -0
  206. package/bmad/bmm/workflows/document-project/templates/deep-dive-template.md +345 -0
  207. package/bmad/bmm/workflows/document-project/templates/index-template.md +169 -0
  208. package/bmad/bmm/workflows/document-project/templates/project-overview-template.md +103 -0
  209. package/bmad/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
  210. package/bmad/bmm/workflows/document-project/templates/source-tree-template.md +135 -0
  211. package/bmad/bmm/workflows/document-project/workflow.yaml +30 -0
  212. package/bmad/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -0
  213. package/bmad/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -0
  214. package/bmad/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -0
  215. package/bmad/bmm/workflows/document-project/workflows/full-scan.yaml +31 -0
  216. package/bmad/bmm/workflows/excalidraw-diagrams/_shared/excalidraw-library.json +90 -0
  217. package/bmad/bmm/workflows/excalidraw-diagrams/_shared/excalidraw-templates.yaml +127 -0
  218. package/bmad/bmm/workflows/excalidraw-diagrams/create-dataflow/checklist.md +39 -0
  219. package/bmad/bmm/workflows/excalidraw-diagrams/create-dataflow/instructions.md +130 -0
  220. package/bmad/bmm/workflows/excalidraw-diagrams/create-dataflow/workflow.yaml +27 -0
  221. package/bmad/bmm/workflows/excalidraw-diagrams/create-diagram/checklist.md +43 -0
  222. package/bmad/bmm/workflows/excalidraw-diagrams/create-diagram/instructions.md +141 -0
  223. package/bmad/bmm/workflows/excalidraw-diagrams/create-diagram/workflow.yaml +27 -0
  224. package/bmad/bmm/workflows/excalidraw-diagrams/create-flowchart/checklist.md +49 -0
  225. package/bmad/bmm/workflows/excalidraw-diagrams/create-flowchart/instructions.md +241 -0
  226. package/bmad/bmm/workflows/excalidraw-diagrams/create-flowchart/workflow.yaml +27 -0
  227. package/bmad/bmm/workflows/excalidraw-diagrams/create-wireframe/checklist.md +38 -0
  228. package/bmad/bmm/workflows/excalidraw-diagrams/create-wireframe/instructions.md +133 -0
  229. package/bmad/bmm/workflows/excalidraw-diagrams/create-wireframe/workflow.yaml +27 -0
  230. package/bmad/bmm/workflows/testarch/atdd/atdd-checklist-template.md +363 -0
  231. package/bmad/bmm/workflows/testarch/atdd/checklist.md +374 -0
  232. package/bmad/bmm/workflows/testarch/atdd/instructions.md +806 -0
  233. package/bmad/bmm/workflows/testarch/atdd/workflow.yaml +47 -0
  234. package/bmad/bmm/workflows/testarch/automate/checklist.md +582 -0
  235. package/bmad/bmm/workflows/testarch/automate/instructions.md +1324 -0
  236. package/bmad/bmm/workflows/testarch/automate/workflow.yaml +54 -0
  237. package/bmad/bmm/workflows/testarch/ci/checklist.md +247 -0
  238. package/bmad/bmm/workflows/testarch/ci/github-actions-template.yaml +198 -0
  239. package/bmad/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +149 -0
  240. package/bmad/bmm/workflows/testarch/ci/instructions.md +536 -0
  241. package/bmad/bmm/workflows/testarch/ci/workflow.yaml +47 -0
  242. package/bmad/bmm/workflows/testarch/framework/checklist.md +320 -0
  243. package/bmad/bmm/workflows/testarch/framework/instructions.md +481 -0
  244. package/bmad/bmm/workflows/testarch/framework/workflow.yaml +49 -0
  245. package/bmad/bmm/workflows/testarch/nfr-assess/checklist.md +407 -0
  246. package/bmad/bmm/workflows/testarch/nfr-assess/instructions.md +726 -0
  247. package/bmad/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +461 -0
  248. package/bmad/bmm/workflows/testarch/nfr-assess/workflow.yaml +49 -0
  249. package/bmad/bmm/workflows/testarch/test-design/checklist.md +407 -0
  250. package/bmad/bmm/workflows/testarch/test-design/instructions.md +1158 -0
  251. package/bmad/bmm/workflows/testarch/test-design/test-design-architecture-template.md +213 -0
  252. package/bmad/bmm/workflows/testarch/test-design/test-design-qa-template.md +286 -0
  253. package/bmad/bmm/workflows/testarch/test-design/test-design-template.md +294 -0
  254. package/bmad/bmm/workflows/testarch/test-design/workflow.yaml +71 -0
  255. package/bmad/bmm/workflows/testarch/test-review/checklist.md +472 -0
  256. package/bmad/bmm/workflows/testarch/test-review/instructions.md +628 -0
  257. package/bmad/bmm/workflows/testarch/test-review/test-review-template.md +390 -0
  258. package/bmad/bmm/workflows/testarch/test-review/workflow.yaml +48 -0
  259. package/bmad/bmm/workflows/testarch/trace/checklist.md +642 -0
  260. package/bmad/bmm/workflows/testarch/trace/instructions.md +1030 -0
  261. package/bmad/bmm/workflows/testarch/trace/trace-template.md +675 -0
  262. package/bmad/bmm/workflows/testarch/trace/workflow.yaml +57 -0
  263. package/bmad/core/agents/bmad-master.agent.yaml +30 -0
  264. package/bmad/core/module-help.csv +11 -0
  265. package/bmad/core/module.yaml +25 -0
  266. package/bmad/core/resources/excalidraw/README.md +160 -0
  267. package/bmad/core/resources/excalidraw/excalidraw-helpers.md +127 -0
  268. package/bmad/core/resources/excalidraw/library-loader.md +50 -0
  269. package/bmad/core/resources/excalidraw/validate-json-instructions.md +79 -0
  270. package/bmad/core/tasks/bmad-help.md +62 -0
  271. package/bmad/core/tasks/editorial-review-prose.xml +91 -0
  272. package/bmad/core/tasks/editorial-review-structure.xml +198 -0
  273. package/bmad/core/tasks/index-docs.xml +65 -0
  274. package/bmad/core/tasks/review-adversarial-general.xml +48 -0
  275. package/bmad/core/tasks/shard-doc.xml +109 -0
  276. package/bmad/core/tasks/workflow.xml +235 -0
  277. package/bmad/core/workflows/advanced-elicitation/methods.csv +51 -0
  278. package/bmad/core/workflows/advanced-elicitation/workflow.xml +117 -0
  279. package/bmad/core/workflows/brainstorming/brain-methods.csv +62 -0
  280. package/bmad/core/workflows/brainstorming/steps/step-01-session-setup.md +197 -0
  281. package/bmad/core/workflows/brainstorming/steps/step-01b-continue.md +122 -0
  282. package/bmad/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -0
  283. package/bmad/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -0
  284. package/bmad/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -0
  285. package/bmad/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -0
  286. package/bmad/core/workflows/brainstorming/steps/step-03-technique-execution.md +399 -0
  287. package/bmad/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -0
  288. package/bmad/core/workflows/brainstorming/template.md +15 -0
  289. package/bmad/core/workflows/brainstorming/workflow.md +58 -0
  290. package/bmad/core/workflows/party-mode/steps/step-01-agent-loading.md +138 -0
  291. package/bmad/core/workflows/party-mode/steps/step-02-discussion-orchestration.md +187 -0
  292. package/bmad/core/workflows/party-mode/steps/step-03-graceful-exit.md +157 -0
  293. package/bmad/core/workflows/party-mode/workflow.md +194 -0
  294. package/dist/cli.d.ts +1 -0
  295. package/dist/cli.js +26 -0
  296. package/dist/commands/doctor.d.ts +1 -0
  297. package/dist/commands/doctor.js +168 -0
  298. package/dist/commands/guide.d.ts +1 -0
  299. package/dist/commands/guide.js +19 -0
  300. package/dist/commands/implement.d.ts +1 -0
  301. package/dist/commands/implement.js +83 -0
  302. package/dist/commands/init.d.ts +6 -0
  303. package/dist/commands/init.js +67 -0
  304. package/dist/commands/plan.d.ts +5 -0
  305. package/dist/commands/plan.js +44 -0
  306. package/dist/commands/reset.d.ts +5 -0
  307. package/dist/commands/reset.js +35 -0
  308. package/dist/commands/resume.d.ts +1 -0
  309. package/dist/commands/resume.js +44 -0
  310. package/dist/commands/start.d.ts +5 -0
  311. package/dist/commands/start.js +54 -0
  312. package/dist/commands/status.d.ts +1 -0
  313. package/dist/commands/status.js +53 -0
  314. package/dist/commands/upgrade.d.ts +1 -0
  315. package/dist/commands/upgrade.js +34 -0
  316. package/dist/installer.d.ts +11 -0
  317. package/dist/installer.js +219 -0
  318. package/dist/transition.d.ts +52 -0
  319. package/dist/transition.js +656 -0
  320. package/dist/utils/config.d.ts +7 -0
  321. package/dist/utils/config.js +14 -0
  322. package/dist/utils/json.d.ts +7 -0
  323. package/dist/utils/json.js +26 -0
  324. package/dist/utils/logger.d.ts +3 -0
  325. package/dist/utils/logger.js +13 -0
  326. package/dist/utils/state.d.ts +29 -0
  327. package/dist/utils/state.js +78 -0
  328. package/dist/utils/validate.d.ts +4 -0
  329. package/dist/utils/validate.js +42 -0
  330. package/package.json +59 -0
  331. package/ralph/lib/circuit_breaker.sh +330 -0
  332. package/ralph/lib/date_utils.sh +53 -0
  333. package/ralph/lib/response_analyzer.sh +768 -0
  334. package/ralph/lib/timeout_utils.sh +145 -0
  335. package/ralph/ralph_loop.sh +1391 -0
  336. package/ralph/templates/AGENT.md +158 -0
  337. package/ralph/templates/PROMPT.md +292 -0
  338. package/ralph/templates/fix_plan.md +27 -0
  339. package/ralph/templates/specs/.gitkeep +2 -0
  340. package/slash-commands/advanced-elicitation.md +1 -0
  341. package/slash-commands/adversarial-review.md +1 -0
  342. package/slash-commands/analyst.md +1 -0
  343. package/slash-commands/architect.md +1 -0
  344. package/slash-commands/atdd.md +1 -0
  345. package/slash-commands/bmad-help.md +1 -0
  346. package/slash-commands/bmalph-implement.md +152 -0
  347. package/slash-commands/bmalph.md +1 -0
  348. package/slash-commands/brainstorm-project.md +1 -0
  349. package/slash-commands/brainstorming.md +1 -0
  350. package/slash-commands/continuous-integration.md +1 -0
  351. package/slash-commands/correct-course.md +1 -0
  352. package/slash-commands/create-architecture.md +1 -0
  353. package/slash-commands/create-brief.md +1 -0
  354. package/slash-commands/create-dataflow.md +1 -0
  355. package/slash-commands/create-diagram.md +1 -0
  356. package/slash-commands/create-epics-stories.md +1 -0
  357. package/slash-commands/create-flowchart.md +1 -0
  358. package/slash-commands/create-prd.md +1 -0
  359. package/slash-commands/create-story.md +1 -0
  360. package/slash-commands/create-ux.md +1 -0
  361. package/slash-commands/create-wireframe.md +1 -0
  362. package/slash-commands/dev.md +1 -0
  363. package/slash-commands/document-project.md +1 -0
  364. package/slash-commands/domain-research.md +1 -0
  365. package/slash-commands/editorial-prose.md +1 -0
  366. package/slash-commands/editorial-structure.md +1 -0
  367. package/slash-commands/execute-workflow.md +1 -0
  368. package/slash-commands/implementation-readiness.md +1 -0
  369. package/slash-commands/index-docs.md +1 -0
  370. package/slash-commands/market-research.md +1 -0
  371. package/slash-commands/nfr-assess.md +1 -0
  372. package/slash-commands/party-mode.md +1 -0
  373. package/slash-commands/pm.md +1 -0
  374. package/slash-commands/quick-dev.md +1 -0
  375. package/slash-commands/quick-flow-solo-dev.md +1 -0
  376. package/slash-commands/retrospective.md +1 -0
  377. package/slash-commands/shard-doc.md +1 -0
  378. package/slash-commands/sm.md +1 -0
  379. package/slash-commands/sprint-planning.md +1 -0
  380. package/slash-commands/sprint-status.md +1 -0
  381. package/slash-commands/tea.md +1 -0
  382. package/slash-commands/tech-spec.md +1 -0
  383. package/slash-commands/technical-research.md +1 -0
  384. package/slash-commands/test-automate.md +1 -0
  385. package/slash-commands/test-design.md +1 -0
  386. package/slash-commands/test-framework.md +1 -0
  387. package/slash-commands/test-review.md +1 -0
  388. package/slash-commands/test-trace.md +1 -0
  389. package/slash-commands/ux-designer.md +1 -0
  390. package/slash-commands/validate-architecture.md +1 -0
  391. package/slash-commands/validate-brief.md +1 -0
  392. package/slash-commands/validate-epics-stories.md +1 -0
  393. package/slash-commands/validate-prd.md +1 -0
  394. package/slash-commands/validate-story.md +1 -0
  395. package/slash-commands/validate-test-design.md +1 -0
  396. package/slash-commands/validate-ux.md +1 -0
@@ -0,0 +1,768 @@
1
+ #!/bin/bash
2
+ # Response Analyzer Component for Ralph
3
+ # Analyzes Claude Code output to detect completion signals, test-only loops, and progress
4
+
5
+ # Source date utilities for cross-platform compatibility
6
+ source "$(dirname "${BASH_SOURCE[0]}")/date_utils.sh"
7
+
8
+ # Response Analysis Functions
9
+ # Based on expert recommendations from Martin Fowler, Michael Nygard, Sam Newman
10
+
11
+ # Colors for output
12
+ RED='\033[0;31m'
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ BLUE='\033[0;34m'
16
+ NC='\033[0m'
17
+
18
+ # Use RALPH_DIR if set by main script, otherwise default to .ralph
19
+ RALPH_DIR="${RALPH_DIR:-.ralph}"
20
+
21
+ # Analysis configuration
22
+ COMPLETION_KEYWORDS=("done" "complete" "finished" "all tasks complete" "project complete" "ready for review")
23
+ TEST_ONLY_PATTERNS=("npm test" "bats" "pytest" "jest" "cargo test" "go test" "running tests")
24
+ NO_WORK_PATTERNS=("nothing to do" "no changes" "already implemented" "up to date")
25
+
26
+ # =============================================================================
27
+ # JSON OUTPUT FORMAT DETECTION AND PARSING
28
+ # =============================================================================
29
+
30
+ # Detect output format (json or text)
31
+ # Returns: "json" if valid JSON, "text" otherwise
32
+ detect_output_format() {
33
+ local output_file=$1
34
+
35
+ if [[ ! -f "$output_file" ]] || [[ ! -s "$output_file" ]]; then
36
+ echo "text"
37
+ return
38
+ fi
39
+
40
+ # Check if file starts with { or [ (JSON indicators)
41
+ local first_char=$(head -c 1 "$output_file" 2>/dev/null | tr -d '[:space:]')
42
+
43
+ if [[ "$first_char" != "{" && "$first_char" != "[" ]]; then
44
+ echo "text"
45
+ return
46
+ fi
47
+
48
+ # Validate as JSON using jq
49
+ if jq empty "$output_file" 2>/dev/null; then
50
+ echo "json"
51
+ else
52
+ echo "text"
53
+ fi
54
+ }
55
+
56
+ # Parse JSON response and extract structured fields
57
+ # Creates .ralph/.json_parse_result with normalized analysis data
58
+ # Supports THREE JSON formats:
59
+ # 1. Flat format: { status, exit_signal, work_type, files_modified, ... }
60
+ # 2. Claude CLI object format: { result, sessionId, metadata: { files_changed, has_errors, completion_status, ... } }
61
+ # 3. Claude CLI array format: [ {type: "system", ...}, {type: "assistant", ...}, {type: "result", ...} ]
62
+ parse_json_response() {
63
+ local output_file=$1
64
+ local result_file="${2:-$RALPH_DIR/.json_parse_result}"
65
+ local normalized_file=""
66
+
67
+ if [[ ! -f "$output_file" ]]; then
68
+ echo "ERROR: Output file not found: $output_file" >&2
69
+ return 1
70
+ fi
71
+
72
+ # Validate JSON first
73
+ if ! jq empty "$output_file" 2>/dev/null; then
74
+ echo "ERROR: Invalid JSON in output file" >&2
75
+ return 1
76
+ fi
77
+
78
+ # Check if JSON is an array (Claude CLI array format)
79
+ # Claude CLI outputs: [{type: "system", ...}, {type: "assistant", ...}, {type: "result", ...}]
80
+ if jq -e 'type == "array"' "$output_file" >/dev/null 2>&1; then
81
+ normalized_file=$(mktemp)
82
+
83
+ # Extract the "result" type message from the array (usually the last entry)
84
+ # This contains: result, session_id, is_error, duration_ms, etc.
85
+ local result_obj=$(jq '[.[] | select(.type == "result")] | .[-1] // {}' "$output_file" 2>/dev/null)
86
+
87
+ # Guard against empty result_obj if jq fails (review fix: Macroscope)
88
+ [[ -z "$result_obj" ]] && result_obj="{}"
89
+
90
+ # Extract session_id from init message as fallback
91
+ local init_session_id=$(jq -r '.[] | select(.type == "system" and .subtype == "init") | .session_id // empty' "$output_file" 2>/dev/null | head -1)
92
+
93
+ # Prioritize result object's own session_id, then fall back to init message (review fix: CodeRabbit)
94
+ # This prevents session ID loss when arrays lack an init message with session_id
95
+ local effective_session_id
96
+ effective_session_id=$(echo "$result_obj" | jq -r '.sessionId // .session_id // empty' 2>/dev/null)
97
+ if [[ -z "$effective_session_id" || "$effective_session_id" == "null" ]]; then
98
+ effective_session_id="$init_session_id"
99
+ fi
100
+
101
+ # Build normalized object merging result with effective session_id
102
+ if [[ -n "$effective_session_id" && "$effective_session_id" != "null" ]]; then
103
+ echo "$result_obj" | jq --arg sid "$effective_session_id" '. + {sessionId: $sid} | del(.session_id)' > "$normalized_file"
104
+ else
105
+ echo "$result_obj" | jq 'del(.session_id)' > "$normalized_file"
106
+ fi
107
+
108
+ # Use normalized file for subsequent parsing
109
+ output_file="$normalized_file"
110
+ fi
111
+
112
+ # Detect JSON format by checking for Claude CLI fields
113
+ local has_result_field=$(jq -r 'has("result")' "$output_file" 2>/dev/null)
114
+
115
+ # Extract fields - support both flat format and Claude CLI format
116
+ # Priority: Claude CLI fields first, then flat format fields
117
+
118
+ # Status: from flat format OR derived from metadata.completion_status
119
+ local status=$(jq -r '.status // "UNKNOWN"' "$output_file" 2>/dev/null)
120
+ local completion_status=$(jq -r '.metadata.completion_status // ""' "$output_file" 2>/dev/null)
121
+ if [[ "$completion_status" == "complete" || "$completion_status" == "COMPLETE" ]]; then
122
+ status="COMPLETE"
123
+ fi
124
+
125
+ # Exit signal: from flat format OR derived from completion_status
126
+ local exit_signal=$(jq -r '.exit_signal // false' "$output_file" 2>/dev/null)
127
+
128
+ # Bug #1 Fix: If exit_signal is still false, check for RALPH_STATUS block in .result field
129
+ # Claude CLI JSON format embeds the RALPH_STATUS block within the .result text field
130
+ if [[ "$exit_signal" == "false" && "$has_result_field" == "true" ]]; then
131
+ local result_text=$(jq -r '.result // ""' "$output_file" 2>/dev/null)
132
+ if [[ -n "$result_text" ]] && echo "$result_text" | grep -q -- "---RALPH_STATUS---"; then
133
+ # Extract EXIT_SIGNAL value from RALPH_STATUS block within result text
134
+ local embedded_exit_sig=$(echo "$result_text" | grep "EXIT_SIGNAL:" | cut -d: -f2 | xargs)
135
+ if [[ "$embedded_exit_sig" == "true" ]]; then
136
+ exit_signal="true"
137
+ [[ "${VERBOSE_PROGRESS:-}" == "true" ]] && echo "DEBUG: Extracted EXIT_SIGNAL=true from .result RALPH_STATUS block" >&2
138
+ fi
139
+ # Also check STATUS field as fallback
140
+ local embedded_status=$(echo "$result_text" | grep "STATUS:" | cut -d: -f2 | xargs)
141
+ if [[ "$embedded_status" == "COMPLETE" && "$exit_signal" != "true" ]]; then
142
+ # STATUS: COMPLETE without explicit EXIT_SIGNAL implies completion
143
+ exit_signal="true"
144
+ [[ "${VERBOSE_PROGRESS:-}" == "true" ]] && echo "DEBUG: Inferred EXIT_SIGNAL=true from .result STATUS=COMPLETE" >&2
145
+ fi
146
+ fi
147
+ fi
148
+
149
+ # Work type: from flat format
150
+ local work_type=$(jq -r '.work_type // "UNKNOWN"' "$output_file" 2>/dev/null)
151
+
152
+ # Files modified: from flat format OR from metadata.files_changed
153
+ local files_modified=$(jq -r '.metadata.files_changed // .files_modified // 0' "$output_file" 2>/dev/null)
154
+
155
+ # Error count: from flat format OR derived from metadata.has_errors
156
+ # Note: When only has_errors=true is present (without explicit error_count),
157
+ # we set error_count=1 as a minimum. This is defensive programming since
158
+ # the stuck detection threshold is >5 errors, so 1 error won't trigger it.
159
+ # Actual error count may be higher, but precise count isn't critical for our logic.
160
+ local error_count=$(jq -r '.error_count // 0' "$output_file" 2>/dev/null)
161
+ local has_errors=$(jq -r '.metadata.has_errors // false' "$output_file" 2>/dev/null)
162
+ if [[ "$has_errors" == "true" && "$error_count" == "0" ]]; then
163
+ error_count=1 # At least one error if has_errors is true
164
+ fi
165
+
166
+ # Summary: from flat format OR from result field (Claude CLI format)
167
+ local summary=$(jq -r '.result // .summary // ""' "$output_file" 2>/dev/null)
168
+
169
+ # Session ID: from Claude CLI format (sessionId) OR from metadata.session_id
170
+ local session_id=$(jq -r '.sessionId // .metadata.session_id // ""' "$output_file" 2>/dev/null)
171
+
172
+ # Loop number: from metadata
173
+ local loop_number=$(jq -r '.metadata.loop_number // .loop_number // 0' "$output_file" 2>/dev/null)
174
+
175
+ # Confidence: from flat format
176
+ local confidence=$(jq -r '.confidence // 0' "$output_file" 2>/dev/null)
177
+
178
+ # Progress indicators: from Claude CLI metadata (optional)
179
+ local progress_count=$(jq -r '.metadata.progress_indicators | if . then length else 0 end' "$output_file" 2>/dev/null)
180
+
181
+ # Normalize values
182
+ # Convert exit_signal to boolean string
183
+ if [[ "$exit_signal" == "true" || "$status" == "COMPLETE" || "$completion_status" == "complete" || "$completion_status" == "COMPLETE" ]]; then
184
+ exit_signal="true"
185
+ else
186
+ exit_signal="false"
187
+ fi
188
+
189
+ # Determine is_test_only from work_type
190
+ local is_test_only="false"
191
+ if [[ "$work_type" == "TEST_ONLY" ]]; then
192
+ is_test_only="true"
193
+ fi
194
+
195
+ # Determine is_stuck from error_count (threshold >5)
196
+ local is_stuck="false"
197
+ error_count=$((error_count + 0)) # Ensure integer
198
+ if [[ $error_count -gt 5 ]]; then
199
+ is_stuck="true"
200
+ fi
201
+
202
+ # Ensure files_modified is integer
203
+ files_modified=$((files_modified + 0))
204
+
205
+ # Ensure progress_count is integer
206
+ progress_count=$((progress_count + 0))
207
+
208
+ # Calculate has_completion_signal
209
+ local has_completion_signal="false"
210
+ if [[ "$status" == "COMPLETE" || "$exit_signal" == "true" ]]; then
211
+ has_completion_signal="true"
212
+ fi
213
+
214
+ # Boost confidence based on structured data availability
215
+ if [[ "$has_result_field" == "true" ]]; then
216
+ confidence=$((confidence + 20)) # Structured response boost
217
+ fi
218
+ if [[ $progress_count -gt 0 ]]; then
219
+ confidence=$((confidence + progress_count * 5)) # Progress indicators boost
220
+ fi
221
+
222
+ # Write normalized result using jq for safe JSON construction
223
+ # String fields use --arg (auto-escapes), numeric/boolean use --argjson
224
+ jq -n \
225
+ --arg status "$status" \
226
+ --argjson exit_signal "$exit_signal" \
227
+ --argjson is_test_only "$is_test_only" \
228
+ --argjson is_stuck "$is_stuck" \
229
+ --argjson has_completion_signal "$has_completion_signal" \
230
+ --argjson files_modified "$files_modified" \
231
+ --argjson error_count "$error_count" \
232
+ --arg summary "$summary" \
233
+ --argjson loop_number "$loop_number" \
234
+ --arg session_id "$session_id" \
235
+ --argjson confidence "$confidence" \
236
+ '{
237
+ status: $status,
238
+ exit_signal: $exit_signal,
239
+ is_test_only: $is_test_only,
240
+ is_stuck: $is_stuck,
241
+ has_completion_signal: $has_completion_signal,
242
+ files_modified: $files_modified,
243
+ error_count: $error_count,
244
+ summary: $summary,
245
+ loop_number: $loop_number,
246
+ session_id: $session_id,
247
+ confidence: $confidence,
248
+ metadata: {
249
+ loop_number: $loop_number,
250
+ session_id: $session_id
251
+ }
252
+ }' > "$result_file"
253
+
254
+ # Cleanup temporary normalized file if created (for array format handling)
255
+ if [[ -n "$normalized_file" && -f "$normalized_file" ]]; then
256
+ rm -f "$normalized_file"
257
+ fi
258
+
259
+ return 0
260
+ }
261
+
262
+ # Analyze Claude Code response and extract signals
263
+ analyze_response() {
264
+ local output_file=$1
265
+ local loop_number=$2
266
+ local analysis_result_file=${3:-"$RALPH_DIR/.response_analysis"}
267
+
268
+ # Initialize analysis result
269
+ local has_completion_signal=false
270
+ local is_test_only=false
271
+ local is_stuck=false
272
+ local has_progress=false
273
+ local confidence_score=0
274
+ local exit_signal=false
275
+ local work_summary=""
276
+ local files_modified=0
277
+
278
+ # Read output file
279
+ if [[ ! -f "$output_file" ]]; then
280
+ echo "ERROR: Output file not found: $output_file"
281
+ return 1
282
+ fi
283
+
284
+ local output_content=$(cat "$output_file")
285
+ local output_length=${#output_content}
286
+
287
+ # Detect output format and try JSON parsing first
288
+ local output_format=$(detect_output_format "$output_file")
289
+
290
+ if [[ "$output_format" == "json" ]]; then
291
+ # Try JSON parsing
292
+ if parse_json_response "$output_file" "$RALPH_DIR/.json_parse_result" 2>/dev/null; then
293
+ # Extract values from JSON parse result
294
+ has_completion_signal=$(jq -r '.has_completion_signal' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "false")
295
+ exit_signal=$(jq -r '.exit_signal' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "false")
296
+ is_test_only=$(jq -r '.is_test_only' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "false")
297
+ is_stuck=$(jq -r '.is_stuck' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "false")
298
+ work_summary=$(jq -r '.summary' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "")
299
+ files_modified=$(jq -r '.files_modified' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "0")
300
+ local json_confidence=$(jq -r '.confidence' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "0")
301
+ local session_id=$(jq -r '.session_id' $RALPH_DIR/.json_parse_result 2>/dev/null || echo "")
302
+
303
+ # Persist session ID if present (for session continuity across loop iterations)
304
+ if [[ -n "$session_id" && "$session_id" != "null" ]]; then
305
+ store_session_id "$session_id"
306
+ [[ "${VERBOSE_PROGRESS:-}" == "true" ]] && echo "DEBUG: Persisted session ID: $session_id" >&2
307
+ fi
308
+
309
+ # JSON parsing provides high confidence
310
+ if [[ "$exit_signal" == "true" ]]; then
311
+ confidence_score=100
312
+ else
313
+ confidence_score=$((json_confidence + 50))
314
+ fi
315
+
316
+ # Check for file changes via git (supplements JSON data)
317
+ if command -v git &>/dev/null && git rev-parse --git-dir >/dev/null 2>&1; then
318
+ local git_files=$(git diff --name-only 2>/dev/null | wc -l)
319
+ if [[ $git_files -gt 0 ]]; then
320
+ has_progress=true
321
+ files_modified=$git_files
322
+ fi
323
+ fi
324
+
325
+ # Write analysis results for JSON path using jq for safe construction
326
+ jq -n \
327
+ --argjson loop_number "$loop_number" \
328
+ --arg timestamp "$(get_iso_timestamp)" \
329
+ --arg output_file "$output_file" \
330
+ --arg output_format "json" \
331
+ --argjson has_completion_signal "$has_completion_signal" \
332
+ --argjson is_test_only "$is_test_only" \
333
+ --argjson is_stuck "$is_stuck" \
334
+ --argjson has_progress "$has_progress" \
335
+ --argjson files_modified "$files_modified" \
336
+ --argjson confidence_score "$confidence_score" \
337
+ --argjson exit_signal "$exit_signal" \
338
+ --arg work_summary "$work_summary" \
339
+ --argjson output_length "$output_length" \
340
+ '{
341
+ loop_number: $loop_number,
342
+ timestamp: $timestamp,
343
+ output_file: $output_file,
344
+ output_format: $output_format,
345
+ analysis: {
346
+ has_completion_signal: $has_completion_signal,
347
+ is_test_only: $is_test_only,
348
+ is_stuck: $is_stuck,
349
+ has_progress: $has_progress,
350
+ files_modified: $files_modified,
351
+ confidence_score: $confidence_score,
352
+ exit_signal: $exit_signal,
353
+ work_summary: $work_summary,
354
+ output_length: $output_length
355
+ }
356
+ }' > "$analysis_result_file"
357
+ rm -f "$RALPH_DIR/.json_parse_result"
358
+ return 0
359
+ fi
360
+ # If JSON parsing failed, fall through to text parsing
361
+ fi
362
+
363
+ # Text parsing fallback (original logic)
364
+
365
+ # Track whether an explicit EXIT_SIGNAL was found in RALPH_STATUS block
366
+ # If explicit signal found, heuristics should NOT override Claude's intent
367
+ local explicit_exit_signal_found=false
368
+
369
+ # 1. Check for explicit structured output (if Claude follows schema)
370
+ if grep -q -- "---RALPH_STATUS---" "$output_file"; then
371
+ # Parse structured output
372
+ local status=$(grep "STATUS:" "$output_file" | cut -d: -f2 | xargs)
373
+ local exit_sig=$(grep "EXIT_SIGNAL:" "$output_file" | cut -d: -f2 | xargs)
374
+
375
+ # If EXIT_SIGNAL is explicitly provided, respect it
376
+ if [[ -n "$exit_sig" ]]; then
377
+ explicit_exit_signal_found=true
378
+ if [[ "$exit_sig" == "true" ]]; then
379
+ has_completion_signal=true
380
+ exit_signal=true
381
+ confidence_score=100
382
+ else
383
+ # Explicit EXIT_SIGNAL: false - Claude says to continue
384
+ exit_signal=false
385
+ fi
386
+ elif [[ "$status" == "COMPLETE" ]]; then
387
+ # No explicit EXIT_SIGNAL but STATUS is COMPLETE
388
+ has_completion_signal=true
389
+ exit_signal=true
390
+ confidence_score=100
391
+ fi
392
+ fi
393
+
394
+ # 2. Detect completion keywords in natural language output
395
+ for keyword in "${COMPLETION_KEYWORDS[@]}"; do
396
+ if grep -qi "$keyword" "$output_file"; then
397
+ has_completion_signal=true
398
+ ((confidence_score+=10))
399
+ break
400
+ fi
401
+ done
402
+
403
+ # 3. Detect test-only loops
404
+ local test_command_count=0
405
+ local implementation_count=0
406
+ local error_count=0
407
+
408
+ test_command_count=$(grep -c -i "running tests\|npm test\|bats\|pytest\|jest" "$output_file" 2>/dev/null | head -1 || echo "0")
409
+ implementation_count=$(grep -c -i "implementing\|creating\|writing\|adding\|function\|class" "$output_file" 2>/dev/null | head -1 || echo "0")
410
+
411
+ # Strip whitespace and ensure it's a number
412
+ test_command_count=$(echo "$test_command_count" | tr -d '[:space:]')
413
+ implementation_count=$(echo "$implementation_count" | tr -d '[:space:]')
414
+
415
+ # Convert to integers with default fallback
416
+ test_command_count=${test_command_count:-0}
417
+ implementation_count=${implementation_count:-0}
418
+ test_command_count=$((test_command_count + 0))
419
+ implementation_count=$((implementation_count + 0))
420
+
421
+ if [[ $test_command_count -gt 0 ]] && [[ $implementation_count -eq 0 ]]; then
422
+ is_test_only=true
423
+ work_summary="Test execution only, no implementation"
424
+ fi
425
+
426
+ # 4. Detect stuck/error loops
427
+ # Use two-stage filtering to avoid counting JSON field names as errors
428
+ # Stage 1: Filter out JSON field patterns like "is_error": false
429
+ # Stage 2: Count actual error messages in specific contexts
430
+ # Pattern aligned with ralph_loop.sh to ensure consistent behavior
431
+ error_count=$(grep -v '"[^"]*error[^"]*":' "$output_file" 2>/dev/null | \
432
+ grep -cE '(^Error:|^ERROR:|^error:|\]: error|Link: error|Error occurred|failed with error|[Ee]xception|Fatal|FATAL)' \
433
+ 2>/dev/null || echo "0")
434
+ error_count=$(echo "$error_count" | tr -d '[:space:]')
435
+ error_count=${error_count:-0}
436
+ error_count=$((error_count + 0))
437
+
438
+ if [[ $error_count -gt 5 ]]; then
439
+ is_stuck=true
440
+ fi
441
+
442
+ # 5. Detect "nothing to do" patterns
443
+ for pattern in "${NO_WORK_PATTERNS[@]}"; do
444
+ if grep -qi "$pattern" "$output_file"; then
445
+ has_completion_signal=true
446
+ ((confidence_score+=15))
447
+ work_summary="No work remaining"
448
+ break
449
+ fi
450
+ done
451
+
452
+ # 6. Check for file changes (git integration)
453
+ if command -v git &>/dev/null && git rev-parse --git-dir >/dev/null 2>&1; then
454
+ files_modified=$(git diff --name-only 2>/dev/null | wc -l)
455
+ if [[ $files_modified -gt 0 ]]; then
456
+ has_progress=true
457
+ ((confidence_score+=20))
458
+ fi
459
+ fi
460
+
461
+ # 7. Analyze output length trends (detect declining engagement)
462
+ if [[ -f "$RALPH_DIR/.last_output_length" ]]; then
463
+ local last_length=$(cat "$RALPH_DIR/.last_output_length")
464
+ local length_ratio=$((output_length * 100 / last_length))
465
+
466
+ if [[ $length_ratio -lt 50 ]]; then
467
+ # Output is less than 50% of previous - possible completion
468
+ ((confidence_score+=10))
469
+ fi
470
+ fi
471
+ echo "$output_length" > "$RALPH_DIR/.last_output_length"
472
+
473
+ # 8. Extract work summary from output
474
+ if [[ -z "$work_summary" ]]; then
475
+ # Try to find summary in output
476
+ work_summary=$(grep -i "summary\|completed\|implemented" "$output_file" | head -1 | cut -c 1-100)
477
+ if [[ -z "$work_summary" ]]; then
478
+ work_summary="Output analyzed, no explicit summary found"
479
+ fi
480
+ fi
481
+
482
+ # 9. Determine exit signal based on confidence (heuristic)
483
+ # IMPORTANT: Only apply heuristics if no explicit EXIT_SIGNAL was found in RALPH_STATUS
484
+ # Claude's explicit intent takes precedence over natural language pattern matching
485
+ if [[ "$explicit_exit_signal_found" != "true" ]]; then
486
+ if [[ $confidence_score -ge 40 || "$has_completion_signal" == "true" ]]; then
487
+ exit_signal=true
488
+ fi
489
+ fi
490
+
491
+ # Write analysis results to file (text parsing path) using jq for safe construction
492
+ jq -n \
493
+ --argjson loop_number "$loop_number" \
494
+ --arg timestamp "$(get_iso_timestamp)" \
495
+ --arg output_file "$output_file" \
496
+ --arg output_format "text" \
497
+ --argjson has_completion_signal "$has_completion_signal" \
498
+ --argjson is_test_only "$is_test_only" \
499
+ --argjson is_stuck "$is_stuck" \
500
+ --argjson has_progress "$has_progress" \
501
+ --argjson files_modified "$files_modified" \
502
+ --argjson confidence_score "$confidence_score" \
503
+ --argjson exit_signal "$exit_signal" \
504
+ --arg work_summary "$work_summary" \
505
+ --argjson output_length "$output_length" \
506
+ '{
507
+ loop_number: $loop_number,
508
+ timestamp: $timestamp,
509
+ output_file: $output_file,
510
+ output_format: $output_format,
511
+ analysis: {
512
+ has_completion_signal: $has_completion_signal,
513
+ is_test_only: $is_test_only,
514
+ is_stuck: $is_stuck,
515
+ has_progress: $has_progress,
516
+ files_modified: $files_modified,
517
+ confidence_score: $confidence_score,
518
+ exit_signal: $exit_signal,
519
+ work_summary: $work_summary,
520
+ output_length: $output_length
521
+ }
522
+ }' > "$analysis_result_file"
523
+
524
+ # Always return 0 (success) - callers should check the JSON result file
525
+ # Returning non-zero would cause issues with set -e and test frameworks
526
+ return 0
527
+ }
528
+
529
+ # Update exit signals file based on analysis
530
+ update_exit_signals() {
531
+ local analysis_file=${1:-"$RALPH_DIR/.response_analysis"}
532
+ local exit_signals_file=${2:-"$RALPH_DIR/.exit_signals"}
533
+
534
+ if [[ ! -f "$analysis_file" ]]; then
535
+ echo "ERROR: Analysis file not found: $analysis_file"
536
+ return 1
537
+ fi
538
+
539
+ # Read analysis results
540
+ local is_test_only=$(jq -r '.analysis.is_test_only' "$analysis_file")
541
+ local has_completion_signal=$(jq -r '.analysis.has_completion_signal' "$analysis_file")
542
+ local loop_number=$(jq -r '.loop_number' "$analysis_file")
543
+ local has_progress=$(jq -r '.analysis.has_progress' "$analysis_file")
544
+
545
+ # Read current exit signals
546
+ local signals=$(cat "$exit_signals_file" 2>/dev/null || echo '{"test_only_loops": [], "done_signals": [], "completion_indicators": []}')
547
+
548
+ # Update test_only_loops array
549
+ if [[ "$is_test_only" == "true" ]]; then
550
+ signals=$(echo "$signals" | jq ".test_only_loops += [$loop_number]")
551
+ else
552
+ # Clear test_only_loops if we had implementation
553
+ if [[ "$has_progress" == "true" ]]; then
554
+ signals=$(echo "$signals" | jq '.test_only_loops = []')
555
+ fi
556
+ fi
557
+
558
+ # Update done_signals array
559
+ if [[ "$has_completion_signal" == "true" ]]; then
560
+ signals=$(echo "$signals" | jq ".done_signals += [$loop_number]")
561
+ fi
562
+
563
+ # Update completion_indicators array (strong signals)
564
+ local confidence=$(jq -r '.analysis.confidence_score' "$analysis_file")
565
+ if [[ $confidence -ge 60 ]]; then
566
+ signals=$(echo "$signals" | jq ".completion_indicators += [$loop_number]")
567
+ fi
568
+
569
+ # Keep only last 5 signals (rolling window)
570
+ signals=$(echo "$signals" | jq '.test_only_loops = .test_only_loops[-5:]')
571
+ signals=$(echo "$signals" | jq '.done_signals = .done_signals[-5:]')
572
+ signals=$(echo "$signals" | jq '.completion_indicators = .completion_indicators[-5:]')
573
+
574
+ # Write updated signals
575
+ echo "$signals" > "$exit_signals_file"
576
+
577
+ return 0
578
+ }
579
+
580
+ # Log analysis results in human-readable format
581
+ log_analysis_summary() {
582
+ local analysis_file=${1:-"$RALPH_DIR/.response_analysis"}
583
+
584
+ if [[ ! -f "$analysis_file" ]]; then
585
+ return 1
586
+ fi
587
+
588
+ local loop=$(jq -r '.loop_number' "$analysis_file")
589
+ local exit_sig=$(jq -r '.analysis.exit_signal' "$analysis_file")
590
+ local confidence=$(jq -r '.analysis.confidence_score' "$analysis_file")
591
+ local test_only=$(jq -r '.analysis.is_test_only' "$analysis_file")
592
+ local files_changed=$(jq -r '.analysis.files_modified' "$analysis_file")
593
+ local summary=$(jq -r '.analysis.work_summary' "$analysis_file")
594
+
595
+ echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
596
+ echo -e "${BLUE}║ Response Analysis - Loop #$loop ║${NC}"
597
+ echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
598
+ echo -e "${YELLOW}Exit Signal:${NC} $exit_sig"
599
+ echo -e "${YELLOW}Confidence:${NC} $confidence%"
600
+ echo -e "${YELLOW}Test Only:${NC} $test_only"
601
+ echo -e "${YELLOW}Files Changed:${NC} $files_changed"
602
+ echo -e "${YELLOW}Summary:${NC} $summary"
603
+ echo ""
604
+ }
605
+
606
+ # Detect if Claude is stuck (repeating same errors)
607
+ detect_stuck_loop() {
608
+ local current_output=$1
609
+ local history_dir=${2:-"$RALPH_DIR/logs"}
610
+
611
+ # Get last 3 output files
612
+ local recent_outputs=$(ls -t "$history_dir"/claude_output_*.log 2>/dev/null | head -3)
613
+
614
+ if [[ -z "$recent_outputs" ]]; then
615
+ return 1 # Not enough history
616
+ fi
617
+
618
+ # Extract key errors from current output using two-stage filtering
619
+ # Stage 1: Filter out JSON field patterns to avoid false positives
620
+ # Stage 2: Extract actual error messages
621
+ local current_errors=$(grep -v '"[^"]*error[^"]*":' "$current_output" 2>/dev/null | \
622
+ grep -E '(^Error:|^ERROR:|^error:|\]: error|Link: error|Error occurred|failed with error|[Ee]xception|Fatal|FATAL)' 2>/dev/null | \
623
+ sort | uniq)
624
+
625
+ if [[ -z "$current_errors" ]]; then
626
+ return 1 # No errors
627
+ fi
628
+
629
+ # Check if same errors appear in all recent outputs
630
+ # For multi-line errors, verify ALL error lines appear in ALL history files
631
+ local all_files_match=true
632
+ while IFS= read -r output_file; do
633
+ local file_matches_all=true
634
+ while IFS= read -r error_line; do
635
+ # Use -F for literal fixed-string matching (not regex)
636
+ if ! grep -qF "$error_line" "$output_file" 2>/dev/null; then
637
+ file_matches_all=false
638
+ break
639
+ fi
640
+ done <<< "$current_errors"
641
+
642
+ if [[ "$file_matches_all" != "true" ]]; then
643
+ all_files_match=false
644
+ break
645
+ fi
646
+ done <<< "$recent_outputs"
647
+
648
+ if [[ "$all_files_match" == "true" ]]; then
649
+ return 0 # Stuck on same error(s)
650
+ else
651
+ return 1 # Making progress or different errors
652
+ fi
653
+ }
654
+
655
+ # =============================================================================
656
+ # SESSION MANAGEMENT FUNCTIONS
657
+ # =============================================================================
658
+
659
+ # Session file location - standardized across ralph_loop.sh and response_analyzer.sh
660
+ SESSION_FILE="$RALPH_DIR/.claude_session_id"
661
+ # Session expiration time in seconds (24 hours)
662
+ SESSION_EXPIRATION_SECONDS=86400
663
+
664
+ # Store session ID to file with timestamp
665
+ # Usage: store_session_id "session-uuid-123"
666
+ store_session_id() {
667
+ local session_id=$1
668
+
669
+ if [[ -z "$session_id" ]]; then
670
+ return 1
671
+ fi
672
+
673
+ # Write session with timestamp using jq for safe JSON construction
674
+ jq -n \
675
+ --arg session_id "$session_id" \
676
+ --arg timestamp "$(get_iso_timestamp)" \
677
+ '{
678
+ session_id: $session_id,
679
+ timestamp: $timestamp
680
+ }' > "$SESSION_FILE"
681
+
682
+ return 0
683
+ }
684
+
685
+ # Get the last stored session ID
686
+ # Returns: session ID string or empty if not found
687
+ get_last_session_id() {
688
+ if [[ ! -f "$SESSION_FILE" ]]; then
689
+ echo ""
690
+ return 0
691
+ fi
692
+
693
+ # Extract session_id from JSON file
694
+ local session_id=$(jq -r '.session_id // ""' "$SESSION_FILE" 2>/dev/null)
695
+ echo "$session_id"
696
+ return 0
697
+ }
698
+
699
+ # Check if the stored session should be resumed
700
+ # Returns: 0 (true) if session is valid and recent, 1 (false) otherwise
701
+ should_resume_session() {
702
+ if [[ ! -f "$SESSION_FILE" ]]; then
703
+ echo "false"
704
+ return 1
705
+ fi
706
+
707
+ # Get session timestamp
708
+ local timestamp=$(jq -r '.timestamp // ""' "$SESSION_FILE" 2>/dev/null)
709
+
710
+ if [[ -z "$timestamp" ]]; then
711
+ echo "false"
712
+ return 1
713
+ fi
714
+
715
+ # Calculate session age using date utilities
716
+ local now=$(get_epoch_seconds)
717
+ local session_time
718
+
719
+ # Parse ISO timestamp to epoch - try multiple formats for cross-platform compatibility
720
+ # Strip milliseconds if present (e.g., 2026-01-09T10:30:00.123+00:00 → 2026-01-09T10:30:00+00:00)
721
+ local clean_timestamp="${timestamp}"
722
+ if [[ "$timestamp" =~ \.[0-9]+[+-Z] ]]; then
723
+ clean_timestamp=$(echo "$timestamp" | sed 's/\.[0-9]*\([+-Z]\)/\1/')
724
+ fi
725
+
726
+ if command -v gdate &>/dev/null; then
727
+ # macOS with coreutils
728
+ session_time=$(gdate -d "$clean_timestamp" +%s 2>/dev/null)
729
+ elif date --version 2>&1 | grep -q GNU; then
730
+ # GNU date (Linux)
731
+ session_time=$(date -d "$clean_timestamp" +%s 2>/dev/null)
732
+ else
733
+ # BSD date (macOS without coreutils) - try parsing ISO format
734
+ # Format: 2026-01-09T10:30:00+00:00 or 2026-01-09T10:30:00Z
735
+ # Strip timezone suffix for BSD date parsing
736
+ local date_only="${clean_timestamp%[+-Z]*}"
737
+ session_time=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$date_only" +%s 2>/dev/null)
738
+ fi
739
+
740
+ # If we couldn't parse the timestamp, consider session expired
741
+ if [[ -z "$session_time" || ! "$session_time" =~ ^[0-9]+$ ]]; then
742
+ echo "false"
743
+ return 1
744
+ fi
745
+
746
+ # Calculate age in seconds
747
+ local age=$((now - session_time))
748
+
749
+ # Check if session is still valid (less than expiration time)
750
+ if [[ $age -lt $SESSION_EXPIRATION_SECONDS ]]; then
751
+ echo "true"
752
+ return 0
753
+ else
754
+ echo "false"
755
+ return 1
756
+ fi
757
+ }
758
+
759
+ # Export functions for use in ralph_loop.sh
760
+ export -f detect_output_format
761
+ export -f parse_json_response
762
+ export -f analyze_response
763
+ export -f update_exit_signals
764
+ export -f log_analysis_summary
765
+ export -f detect_stuck_loop
766
+ export -f store_session_id
767
+ export -f get_last_session_id
768
+ export -f should_resume_session