bmad-method-test-architecture-enterprise 0.1.1-beta.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 (320) hide show
  1. package/.github/CODE_OF_CONDUCT.md +128 -0
  2. package/.github/FUNDING.yaml +15 -0
  3. package/.github/ISSUE_TEMPLATE/config.yaml +11 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +70 -0
  5. package/.github/ISSUE_TEMPLATE/issue.md +61 -0
  6. package/.github/workflows/docs.yaml +66 -0
  7. package/.github/workflows/manual-release.yaml +195 -0
  8. package/.github/workflows/quality.yaml +114 -0
  9. package/.husky/pre-commit +20 -0
  10. package/.markdownlint-cli2.yaml +36 -0
  11. package/.nvmrc +1 -0
  12. package/.prettierignore +9 -0
  13. package/.vscode/settings.json +47 -0
  14. package/CHANGELOG.md +217 -0
  15. package/CONTRIBUTING.md +268 -0
  16. package/LICENSE +26 -0
  17. package/README.md +300 -0
  18. package/SECURITY.md +85 -0
  19. package/TEA-MODULE-MIGRATION-PLAN.md +3788 -0
  20. package/docs/404.md +20 -0
  21. package/docs/MIGRATION.md +447 -0
  22. package/docs/explanation/engagement-models.md +767 -0
  23. package/docs/explanation/fixture-architecture.md +484 -0
  24. package/docs/explanation/knowledge-base-system.md +599 -0
  25. package/docs/explanation/network-first-patterns.md +884 -0
  26. package/docs/explanation/risk-based-testing.md +628 -0
  27. package/docs/explanation/step-file-architecture.md +609 -0
  28. package/docs/explanation/subprocess-architecture.md +578 -0
  29. package/docs/explanation/subprocess-implementation-status.md +327 -0
  30. package/docs/explanation/tea-overview.md +425 -0
  31. package/docs/explanation/test-quality-standards.md +965 -0
  32. package/docs/explanation/testing-as-engineering.md +111 -0
  33. package/docs/glossary/index.md +160 -0
  34. package/docs/how-to/brownfield/use-tea-for-enterprise.md +571 -0
  35. package/docs/how-to/brownfield/use-tea-with-existing-tests.md +631 -0
  36. package/docs/how-to/customization/enable-tea-mcp-enhancements.md +455 -0
  37. package/docs/how-to/customization/integrate-playwright-utils.md +846 -0
  38. package/docs/how-to/workflows/run-atdd.md +460 -0
  39. package/docs/how-to/workflows/run-automate.md +690 -0
  40. package/docs/how-to/workflows/run-nfr-assess.md +731 -0
  41. package/docs/how-to/workflows/run-test-design.md +144 -0
  42. package/docs/how-to/workflows/run-test-review.md +638 -0
  43. package/docs/how-to/workflows/run-trace.md +951 -0
  44. package/docs/how-to/workflows/setup-ci.md +761 -0
  45. package/docs/how-to/workflows/setup-test-framework.md +99 -0
  46. package/docs/index.md +122 -0
  47. package/docs/reference/commands.md +300 -0
  48. package/docs/reference/configuration.md +729 -0
  49. package/docs/reference/knowledge-base.md +365 -0
  50. package/docs/reference/troubleshooting.md +717 -0
  51. package/docs/tutorials/tea-lite-quickstart.md +465 -0
  52. package/eslint.config.mjs +152 -0
  53. package/package.json +117 -0
  54. package/prettier.config.mjs +32 -0
  55. package/release_notes.md +28 -0
  56. package/src/_module-installer/installer.js +92 -0
  57. package/src/agents/tea.agent.yaml +63 -0
  58. package/src/module-help.csv +9 -0
  59. package/src/module.yaml +91 -0
  60. package/src/testarch/knowledge/adr-quality-readiness-checklist.md +377 -0
  61. package/src/testarch/knowledge/api-request.md +442 -0
  62. package/src/testarch/knowledge/api-testing-patterns.md +851 -0
  63. package/src/testarch/knowledge/auth-session.md +548 -0
  64. package/src/testarch/knowledge/burn-in.md +273 -0
  65. package/src/testarch/knowledge/ci-burn-in.md +675 -0
  66. package/src/testarch/knowledge/component-tdd.md +486 -0
  67. package/src/testarch/knowledge/contract-testing.md +957 -0
  68. package/src/testarch/knowledge/data-factories.md +500 -0
  69. package/src/testarch/knowledge/email-auth.md +721 -0
  70. package/src/testarch/knowledge/error-handling.md +725 -0
  71. package/src/testarch/knowledge/feature-flags.md +750 -0
  72. package/src/testarch/knowledge/file-utils.md +456 -0
  73. package/src/testarch/knowledge/fixture-architecture.md +401 -0
  74. package/src/testarch/knowledge/fixtures-composition.md +382 -0
  75. package/src/testarch/knowledge/intercept-network-call.md +426 -0
  76. package/src/testarch/knowledge/log.md +426 -0
  77. package/src/testarch/knowledge/network-error-monitor.md +401 -0
  78. package/src/testarch/knowledge/network-first.md +486 -0
  79. package/src/testarch/knowledge/network-recorder.md +527 -0
  80. package/src/testarch/knowledge/nfr-criteria.md +670 -0
  81. package/src/testarch/knowledge/overview.md +286 -0
  82. package/src/testarch/knowledge/playwright-config.md +730 -0
  83. package/src/testarch/knowledge/probability-impact.md +601 -0
  84. package/src/testarch/knowledge/recurse.md +421 -0
  85. package/src/testarch/knowledge/risk-governance.md +615 -0
  86. package/src/testarch/knowledge/selective-testing.md +732 -0
  87. package/src/testarch/knowledge/selector-resilience.md +527 -0
  88. package/src/testarch/knowledge/test-healing-patterns.md +644 -0
  89. package/src/testarch/knowledge/test-levels-framework.md +473 -0
  90. package/src/testarch/knowledge/test-priorities-matrix.md +373 -0
  91. package/src/testarch/knowledge/test-quality.md +664 -0
  92. package/src/testarch/knowledge/timing-debugging.md +372 -0
  93. package/src/testarch/knowledge/visual-debugging.md +524 -0
  94. package/src/testarch/tea-index.csv +35 -0
  95. package/src/workflows/testarch/README.md +74 -0
  96. package/src/workflows/testarch/atdd/atdd-checklist-template.md +363 -0
  97. package/src/workflows/testarch/atdd/checklist.md +374 -0
  98. package/src/workflows/testarch/atdd/instructions.md +38 -0
  99. package/src/workflows/testarch/atdd/steps-c/step-01-preflight-and-context.md +110 -0
  100. package/src/workflows/testarch/atdd/steps-c/step-02-generation-mode.md +79 -0
  101. package/src/workflows/testarch/atdd/steps-c/step-03-test-strategy.md +76 -0
  102. package/src/workflows/testarch/atdd/steps-c/step-04-generate-tests.md +228 -0
  103. package/src/workflows/testarch/atdd/steps-c/step-04a-subprocess-api-failing.md +215 -0
  104. package/src/workflows/testarch/atdd/steps-c/step-04b-subprocess-e2e-failing.md +212 -0
  105. package/src/workflows/testarch/atdd/steps-c/step-04c-aggregate.md +329 -0
  106. package/src/workflows/testarch/atdd/steps-c/step-05-validate-and-complete.md +68 -0
  107. package/src/workflows/testarch/atdd/steps-e/step-01-assess.md +65 -0
  108. package/src/workflows/testarch/atdd/steps-e/step-02-apply-edit.md +60 -0
  109. package/src/workflows/testarch/atdd/steps-v/step-01-validate.md +67 -0
  110. package/src/workflows/testarch/atdd/validation-report-20260127-095021.md +73 -0
  111. package/src/workflows/testarch/atdd/validation-report-20260127-102401.md +116 -0
  112. package/src/workflows/testarch/atdd/workflow-plan.md +21 -0
  113. package/src/workflows/testarch/atdd/workflow.md +39 -0
  114. package/src/workflows/testarch/atdd/workflow.yaml +47 -0
  115. package/src/workflows/testarch/automate/checklist.md +582 -0
  116. package/src/workflows/testarch/automate/instructions.md +43 -0
  117. package/src/workflows/testarch/automate/steps-c/step-01-preflight-and-context.md +127 -0
  118. package/src/workflows/testarch/automate/steps-c/step-02-identify-targets.md +95 -0
  119. package/src/workflows/testarch/automate/steps-c/step-03-generate-tests.md +199 -0
  120. package/src/workflows/testarch/automate/steps-c/step-03a-subprocess-api.md +183 -0
  121. package/src/workflows/testarch/automate/steps-c/step-03b-subprocess-e2e.md +181 -0
  122. package/src/workflows/testarch/automate/steps-c/step-03c-aggregate.md +300 -0
  123. package/src/workflows/testarch/automate/steps-c/step-04-validate-and-summarize.md +69 -0
  124. package/src/workflows/testarch/automate/steps-e/step-01-assess.md +65 -0
  125. package/src/workflows/testarch/automate/steps-e/step-02-apply-edit.md +60 -0
  126. package/src/workflows/testarch/automate/steps-v/step-01-validate.md +67 -0
  127. package/src/workflows/testarch/automate/validation-report-20260127-095021.md +72 -0
  128. package/src/workflows/testarch/automate/validation-report-20260127-102401.md +114 -0
  129. package/src/workflows/testarch/automate/workflow-plan.md +20 -0
  130. package/src/workflows/testarch/automate/workflow.md +39 -0
  131. package/src/workflows/testarch/automate/workflow.yaml +54 -0
  132. package/src/workflows/testarch/ci/checklist.md +247 -0
  133. package/src/workflows/testarch/ci/github-actions-template.yaml +198 -0
  134. package/src/workflows/testarch/ci/gitlab-ci-template.yaml +149 -0
  135. package/src/workflows/testarch/ci/instructions.md +38 -0
  136. package/src/workflows/testarch/ci/steps-c/step-01-preflight.md +92 -0
  137. package/src/workflows/testarch/ci/steps-c/step-02-generate-pipeline.md +82 -0
  138. package/src/workflows/testarch/ci/steps-c/step-03-configure-quality-gates.md +75 -0
  139. package/src/workflows/testarch/ci/steps-c/step-04-validate-and-summary.md +67 -0
  140. package/src/workflows/testarch/ci/steps-e/step-01-assess.md +65 -0
  141. package/src/workflows/testarch/ci/steps-e/step-02-apply-edit.md +60 -0
  142. package/src/workflows/testarch/ci/steps-v/step-01-validate.md +67 -0
  143. package/src/workflows/testarch/ci/validation-report-20260127-095021.md +72 -0
  144. package/src/workflows/testarch/ci/validation-report-20260127-102401.md +114 -0
  145. package/src/workflows/testarch/ci/workflow-plan.md +20 -0
  146. package/src/workflows/testarch/ci/workflow.md +39 -0
  147. package/src/workflows/testarch/ci/workflow.yaml +47 -0
  148. package/src/workflows/testarch/framework/checklist.md +320 -0
  149. package/src/workflows/testarch/framework/instructions.md +38 -0
  150. package/src/workflows/testarch/framework/steps-c/step-01-preflight.md +75 -0
  151. package/src/workflows/testarch/framework/steps-c/step-02-select-framework.md +73 -0
  152. package/src/workflows/testarch/framework/steps-c/step-03-scaffold-framework.md +120 -0
  153. package/src/workflows/testarch/framework/steps-c/step-04-docs-and-scripts.md +70 -0
  154. package/src/workflows/testarch/framework/steps-c/step-05-validate-and-summary.md +68 -0
  155. package/src/workflows/testarch/framework/steps-e/step-01-assess.md +65 -0
  156. package/src/workflows/testarch/framework/steps-e/step-02-apply-edit.md +60 -0
  157. package/src/workflows/testarch/framework/steps-v/step-01-validate.md +67 -0
  158. package/src/workflows/testarch/framework/validation-report-20260127-095021.md +73 -0
  159. package/src/workflows/testarch/framework/validation-report-20260127-102401.md +116 -0
  160. package/src/workflows/testarch/framework/workflow-plan.md +22 -0
  161. package/src/workflows/testarch/framework/workflow.md +39 -0
  162. package/src/workflows/testarch/framework/workflow.yaml +49 -0
  163. package/src/workflows/testarch/nfr-assess/checklist.md +407 -0
  164. package/src/workflows/testarch/nfr-assess/instructions.md +36 -0
  165. package/src/workflows/testarch/nfr-assess/nfr-report-template.md +462 -0
  166. package/src/workflows/testarch/nfr-assess/steps-c/step-01-load-context.md +85 -0
  167. package/src/workflows/testarch/nfr-assess/steps-c/step-02-define-thresholds.md +82 -0
  168. package/src/workflows/testarch/nfr-assess/steps-c/step-03-gather-evidence.md +64 -0
  169. package/src/workflows/testarch/nfr-assess/steps-c/step-04-evaluate-and-score.md +140 -0
  170. package/src/workflows/testarch/nfr-assess/steps-c/step-04a-subprocess-security.md +138 -0
  171. package/src/workflows/testarch/nfr-assess/steps-c/step-04b-subprocess-performance.md +84 -0
  172. package/src/workflows/testarch/nfr-assess/steps-c/step-04c-subprocess-reliability.md +85 -0
  173. package/src/workflows/testarch/nfr-assess/steps-c/step-04d-subprocess-scalability.md +88 -0
  174. package/src/workflows/testarch/nfr-assess/steps-c/step-04e-aggregate-nfr.md +219 -0
  175. package/src/workflows/testarch/nfr-assess/steps-c/step-05-generate-report.md +71 -0
  176. package/src/workflows/testarch/nfr-assess/steps-e/step-01-assess.md +65 -0
  177. package/src/workflows/testarch/nfr-assess/steps-e/step-02-apply-edit.md +60 -0
  178. package/src/workflows/testarch/nfr-assess/steps-v/step-01-validate.md +67 -0
  179. package/src/workflows/testarch/nfr-assess/validation-report-20260127-095021.md +73 -0
  180. package/src/workflows/testarch/nfr-assess/validation-report-20260127-102401.md +116 -0
  181. package/src/workflows/testarch/nfr-assess/workflow-plan.md +19 -0
  182. package/src/workflows/testarch/nfr-assess/workflow.md +39 -0
  183. package/src/workflows/testarch/nfr-assess/workflow.yaml +49 -0
  184. package/src/workflows/testarch/test-design/checklist.md +410 -0
  185. package/src/workflows/testarch/test-design/instructions.md +52 -0
  186. package/src/workflows/testarch/test-design/steps-c/step-01-detect-mode.md +109 -0
  187. package/src/workflows/testarch/test-design/steps-c/step-02-load-context.md +127 -0
  188. package/src/workflows/testarch/test-design/steps-c/step-03-risk-and-testability.md +85 -0
  189. package/src/workflows/testarch/test-design/steps-c/step-04-coverage-plan.md +98 -0
  190. package/src/workflows/testarch/test-design/steps-c/step-05-generate-output.md +97 -0
  191. package/src/workflows/testarch/test-design/steps-e/step-01-assess.md +65 -0
  192. package/src/workflows/testarch/test-design/steps-e/step-02-apply-edit.md +60 -0
  193. package/src/workflows/testarch/test-design/steps-v/step-01-validate.md +67 -0
  194. package/src/workflows/testarch/test-design/test-design-architecture-template.md +222 -0
  195. package/src/workflows/testarch/test-design/test-design-qa-template.md +296 -0
  196. package/src/workflows/testarch/test-design/test-design-template.md +294 -0
  197. package/src/workflows/testarch/test-design/validation-report-20260127-095021.md +73 -0
  198. package/src/workflows/testarch/test-design/validation-report-20260127-102401.md +116 -0
  199. package/src/workflows/testarch/test-design/workflow-plan.md +22 -0
  200. package/src/workflows/testarch/test-design/workflow.md +39 -0
  201. package/src/workflows/testarch/test-design/workflow.yaml +71 -0
  202. package/src/workflows/testarch/test-review/checklist.md +472 -0
  203. package/src/workflows/testarch/test-review/instructions.md +36 -0
  204. package/src/workflows/testarch/test-review/steps-c/step-01-load-context.md +101 -0
  205. package/src/workflows/testarch/test-review/steps-c/step-02-discover-tests.md +69 -0
  206. package/src/workflows/testarch/test-review/steps-c/step-03-quality-evaluation.md +184 -0
  207. package/src/workflows/testarch/test-review/steps-c/step-03a-subprocess-determinism.md +214 -0
  208. package/src/workflows/testarch/test-review/steps-c/step-03b-subprocess-isolation.md +125 -0
  209. package/src/workflows/testarch/test-review/steps-c/step-03c-subprocess-maintainability.md +102 -0
  210. package/src/workflows/testarch/test-review/steps-c/step-03d-subprocess-coverage.md +111 -0
  211. package/src/workflows/testarch/test-review/steps-c/step-03e-subprocess-performance.md +117 -0
  212. package/src/workflows/testarch/test-review/steps-c/step-03f-aggregate-scores.md +246 -0
  213. package/src/workflows/testarch/test-review/steps-c/step-04-generate-report.md +72 -0
  214. package/src/workflows/testarch/test-review/steps-e/step-01-assess.md +65 -0
  215. package/src/workflows/testarch/test-review/steps-e/step-02-apply-edit.md +60 -0
  216. package/src/workflows/testarch/test-review/steps-v/step-01-validate.md +67 -0
  217. package/src/workflows/testarch/test-review/test-review-template.md +390 -0
  218. package/src/workflows/testarch/test-review/validation-report-20260127-095021.md +72 -0
  219. package/src/workflows/testarch/test-review/validation-report-20260127-102401.md +114 -0
  220. package/src/workflows/testarch/test-review/workflow-plan.md +18 -0
  221. package/src/workflows/testarch/test-review/workflow.md +39 -0
  222. package/src/workflows/testarch/test-review/workflow.yaml +48 -0
  223. package/src/workflows/testarch/trace/checklist.md +642 -0
  224. package/src/workflows/testarch/trace/instructions.md +36 -0
  225. package/src/workflows/testarch/trace/steps-c/step-01-load-context.md +80 -0
  226. package/src/workflows/testarch/trace/steps-c/step-02-discover-tests.md +69 -0
  227. package/src/workflows/testarch/trace/steps-c/step-03-map-criteria.md +65 -0
  228. package/src/workflows/testarch/trace/steps-c/step-04-analyze-gaps.md +244 -0
  229. package/src/workflows/testarch/trace/steps-c/step-05-gate-decision.md +232 -0
  230. package/src/workflows/testarch/trace/steps-e/step-01-assess.md +65 -0
  231. package/src/workflows/testarch/trace/steps-e/step-02-apply-edit.md +60 -0
  232. package/src/workflows/testarch/trace/steps-v/step-01-validate.md +67 -0
  233. package/src/workflows/testarch/trace/trace-template.md +675 -0
  234. package/src/workflows/testarch/trace/validation-report-20260127-095021.md +73 -0
  235. package/src/workflows/testarch/trace/validation-report-20260127-102401.md +116 -0
  236. package/src/workflows/testarch/trace/workflow-plan.md +21 -0
  237. package/src/workflows/testarch/trace/workflow.md +39 -0
  238. package/src/workflows/testarch/trace/workflow.yaml +57 -0
  239. package/test/README.md +23 -0
  240. package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +27 -0
  241. package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +30 -0
  242. package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +22 -0
  243. package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +20 -0
  244. package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +25 -0
  245. package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +24 -0
  246. package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +25 -0
  247. package/test/fixtures/agent-schema/invalid/menu-triggers/compound-invalid-format.agent.yaml +25 -0
  248. package/test/fixtures/agent-schema/invalid/menu-triggers/compound-mismatched-kebab.agent.yaml +25 -0
  249. package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +31 -0
  250. package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +25 -0
  251. package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +25 -0
  252. package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +25 -0
  253. package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +25 -0
  254. package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +26 -0
  255. package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +24 -0
  256. package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +27 -0
  257. package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +23 -0
  258. package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +24 -0
  259. package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +27 -0
  260. package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +27 -0
  261. package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +24 -0
  262. package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +29 -0
  263. package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +31 -0
  264. package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +28 -0
  265. package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +28 -0
  266. package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +5 -0
  267. package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +28 -0
  268. package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +11 -0
  269. package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +19 -0
  270. package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +18 -0
  271. package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +24 -0
  272. package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +22 -0
  273. package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +27 -0
  274. package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +31 -0
  275. package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +22 -0
  276. package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +38 -0
  277. package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +24 -0
  278. package/test/fixtures/agent-schema/valid/menu-triggers/compound-triggers.agent.yaml +31 -0
  279. package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +34 -0
  280. package/test/fixtures/agent-schema/valid/metadata/core-agent-with-module.agent.yaml +24 -0
  281. package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +24 -0
  282. package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +24 -0
  283. package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +24 -0
  284. package/test/fixtures/agent-schema/valid/metadata/module-agent-missing-module.agent.yaml +23 -0
  285. package/test/fixtures/agent-schema/valid/metadata/wrong-module-value.agent.yaml +24 -0
  286. package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +24 -0
  287. package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +24 -0
  288. package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +22 -0
  289. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +28 -0
  290. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +30 -0
  291. package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +24 -0
  292. package/test/schema/agent.js +491 -0
  293. package/test/test-agent-schema.js +387 -0
  294. package/test/test-installation-components.js +183 -0
  295. package/test/test-knowledge-base.js +199 -0
  296. package/test/unit-test-schema.js +133 -0
  297. package/test/validate-agent-schema.js +110 -0
  298. package/tools/build-docs.js +575 -0
  299. package/tools/fix-doc-links.js +288 -0
  300. package/tools/schema/agent.js +491 -0
  301. package/tools/validate-agent-schema.js +111 -0
  302. package/tools/validate-doc-links.js +371 -0
  303. package/tools/verify-paths.js +100 -0
  304. package/website/README.md +137 -0
  305. package/website/astro.config.mjs +158 -0
  306. package/website/package-lock.json +6856 -0
  307. package/website/package.json +23 -0
  308. package/website/public/favicon.ico +0 -0
  309. package/website/public/img/tea-logo.svg +7 -0
  310. package/website/public/robots.txt +37 -0
  311. package/website/src/components/Banner.astro +59 -0
  312. package/website/src/components/Header.astro +121 -0
  313. package/website/src/components/MobileMenuFooter.astro +53 -0
  314. package/website/src/content/config.ts +6 -0
  315. package/website/src/lib/site-url.js +25 -0
  316. package/website/src/pages/404.astro +11 -0
  317. package/website/src/rehype-base-paths.js +89 -0
  318. package/website/src/rehype-markdown-links.js +117 -0
  319. package/website/src/styles/custom.css +499 -0
  320. package/website/tsconfig.json +9 -0
@@ -0,0 +1,387 @@
1
+ /**
2
+ * Agent Schema Validation Test Runner
3
+ *
4
+ * Runs all test fixtures and verifies expected outcomes.
5
+ * Reports pass/fail for each test and overall coverage statistics.
6
+ *
7
+ * Usage: node test/test-agent-schema.js
8
+ * Exit codes: 0 = all tests pass, 1 = test failures
9
+ */
10
+
11
+ const fs = require('node:fs');
12
+ const path = require('node:path');
13
+ const yaml = require('yaml');
14
+ const { validateAgentFile } = require('./schema/agent.js');
15
+ const { glob } = require('glob');
16
+
17
+ // ANSI color codes
18
+ const colors = {
19
+ reset: '\u001B[0m',
20
+ green: '\u001B[32m',
21
+ red: '\u001B[31m',
22
+ yellow: '\u001B[33m',
23
+ blue: '\u001B[34m',
24
+ cyan: '\u001B[36m',
25
+ dim: '\u001B[2m',
26
+ };
27
+
28
+ /**
29
+ * Parse test metadata from YAML comments
30
+ * @param {string} filePath
31
+ * @returns {{shouldPass: boolean, errorExpectation?: object, pathContext?: string}}
32
+ */
33
+ function parseTestMetadata(filePath) {
34
+ const content = fs.readFileSync(filePath, 'utf8');
35
+ const lines = content.split('\n');
36
+
37
+ let shouldPass = true;
38
+ let pathContext = null;
39
+ const errorExpectation = {};
40
+
41
+ for (const line of lines) {
42
+ if (line.includes('Expected: PASS')) {
43
+ shouldPass = true;
44
+ } else if (line.includes('Expected: FAIL')) {
45
+ shouldPass = false;
46
+ }
47
+
48
+ // Parse error metadata
49
+ const codeMatch = line.match(/^# Error code: (.+)$/);
50
+ if (codeMatch) {
51
+ errorExpectation.code = codeMatch[1].trim();
52
+ }
53
+
54
+ const pathMatch = line.match(/^# Error path: (.+)$/);
55
+ if (pathMatch) {
56
+ errorExpectation.path = pathMatch[1].trim();
57
+ }
58
+
59
+ const messageMatch = line.match(/^# Error message: (.+)$/);
60
+ if (messageMatch) {
61
+ errorExpectation.message = messageMatch[1].trim();
62
+ }
63
+
64
+ const minimumMatch = line.match(/^# Error minimum: (\d+)$/);
65
+ if (minimumMatch) {
66
+ errorExpectation.minimum = parseInt(minimumMatch[1], 10);
67
+ }
68
+
69
+ const expectedMatch = line.match(/^# Error expected: (.+)$/);
70
+ if (expectedMatch) {
71
+ errorExpectation.expected = expectedMatch[1].trim();
72
+ }
73
+
74
+ const receivedMatch = line.match(/^# Error received: (.+)$/);
75
+ if (receivedMatch) {
76
+ errorExpectation.received = receivedMatch[1].trim();
77
+ }
78
+
79
+ const keysMatch = line.match(/^# Error keys: \[(.+)\]$/);
80
+ if (keysMatch) {
81
+ errorExpectation.keys = keysMatch[1].split(',').map((k) => k.trim().replaceAll(/['"]/g, ''));
82
+ }
83
+
84
+ const contextMatch = line.match(/^# Path context: (.+)$/);
85
+ if (contextMatch) {
86
+ pathContext = contextMatch[1].trim();
87
+ }
88
+ }
89
+
90
+ return {
91
+ shouldPass,
92
+ errorExpectation: Object.keys(errorExpectation).length > 0 ? errorExpectation : null,
93
+ pathContext,
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Convert dot-notation path string to array (handles array indices)
99
+ * e.g., "agent.menu[0].trigger" => ["agent", "menu", 0, "trigger"]
100
+ */
101
+ function parsePathString(pathString) {
102
+ return pathString
103
+ .replaceAll(/\[(\d+)\]/g, '.$1') // Convert [0] to .0
104
+ .split('.')
105
+ .map((part) => {
106
+ const num = parseInt(part, 10);
107
+ return isNaN(num) ? part : num;
108
+ });
109
+ }
110
+
111
+ /**
112
+ * Validate error against expectations
113
+ * @param {object} error - Zod error issue
114
+ * @param {object} expectation - Expected error structure
115
+ * @returns {{valid: boolean, reason?: string}}
116
+ */
117
+ function validateError(error, expectation) {
118
+ // Check error code
119
+ if (expectation.code && error.code !== expectation.code) {
120
+ return { valid: false, reason: `Expected code "${expectation.code}", got "${error.code}"` };
121
+ }
122
+
123
+ // Check error path
124
+ if (expectation.path) {
125
+ const expectedPath = parsePathString(expectation.path);
126
+ const actualPath = error.path;
127
+
128
+ if (JSON.stringify(expectedPath) !== JSON.stringify(actualPath)) {
129
+ return {
130
+ valid: false,
131
+ reason: `Expected path ${JSON.stringify(expectedPath)}, got ${JSON.stringify(actualPath)}`,
132
+ };
133
+ }
134
+ }
135
+
136
+ // For custom errors, strictly check message
137
+ if (expectation.code === 'custom' && expectation.message && error.message !== expectation.message) {
138
+ return {
139
+ valid: false,
140
+ reason: `Expected message "${expectation.message}", got "${error.message}"`,
141
+ };
142
+ }
143
+
144
+ // For Zod errors, check type-specific fields
145
+ if (expectation.minimum !== undefined && error.minimum !== expectation.minimum) {
146
+ return { valid: false, reason: `Expected minimum ${expectation.minimum}, got ${error.minimum}` };
147
+ }
148
+
149
+ if (expectation.expected && error.expected !== expectation.expected) {
150
+ return { valid: false, reason: `Expected type "${expectation.expected}", got "${error.expected}"` };
151
+ }
152
+
153
+ if (expectation.received && error.received !== expectation.received) {
154
+ return { valid: false, reason: `Expected received "${expectation.received}", got "${error.received}"` };
155
+ }
156
+
157
+ if (expectation.keys) {
158
+ const expectedKeys = expectation.keys.sort();
159
+ const actualKeys = (error.keys || []).sort();
160
+ if (JSON.stringify(expectedKeys) !== JSON.stringify(actualKeys)) {
161
+ return {
162
+ valid: false,
163
+ reason: `Expected keys ${JSON.stringify(expectedKeys)}, got ${JSON.stringify(actualKeys)}`,
164
+ };
165
+ }
166
+ }
167
+
168
+ return { valid: true };
169
+ }
170
+
171
+ /**
172
+ * Run a single test case
173
+ * @param {string} filePath
174
+ * @returns {{passed: boolean, message: string}}
175
+ */
176
+ function runTest(filePath) {
177
+ const metadata = parseTestMetadata(filePath);
178
+ const { shouldPass, errorExpectation, pathContext } = metadata;
179
+
180
+ try {
181
+ const fileContent = fs.readFileSync(filePath, 'utf8');
182
+ let agentData;
183
+
184
+ try {
185
+ agentData = yaml.parse(fileContent);
186
+ } catch (parseError) {
187
+ // YAML parse error
188
+ if (shouldPass) {
189
+ return {
190
+ passed: false,
191
+ message: `Expected PASS but got YAML parse error: ${parseError.message}`,
192
+ };
193
+ }
194
+ return {
195
+ passed: true,
196
+ message: 'Got expected YAML parse error',
197
+ };
198
+ }
199
+
200
+ // Determine validation path
201
+ // If pathContext is specified in comments, use it; otherwise derive from fixture location
202
+ let validationPath = pathContext;
203
+ if (!validationPath) {
204
+ // Map fixture location to simulated src/ path
205
+ const relativePath = path.relative(path.join(__dirname, 'fixtures/agent-schema'), filePath);
206
+ const parts = relativePath.split(path.sep);
207
+
208
+ if (parts.includes('metadata') && parts[0] === 'valid') {
209
+ // Valid metadata tests: check if filename suggests module or core
210
+ const filename = path.basename(filePath);
211
+ if (filename.includes('module')) {
212
+ validationPath = 'src/modules/bmm/agents/test.agent.yaml';
213
+ } else {
214
+ validationPath = 'src/core/agents/test.agent.yaml';
215
+ }
216
+ } else if (parts.includes('metadata') && parts[0] === 'invalid') {
217
+ // Invalid metadata tests: derive from filename
218
+ const filename = path.basename(filePath);
219
+ if (filename.includes('module') || filename.includes('wrong-module')) {
220
+ validationPath = 'src/modules/bmm/agents/test.agent.yaml';
221
+ } else if (filename.includes('core')) {
222
+ validationPath = 'src/core/agents/test.agent.yaml';
223
+ } else {
224
+ validationPath = 'src/core/agents/test.agent.yaml';
225
+ }
226
+ } else {
227
+ // Default to core agent path
228
+ validationPath = 'src/core/agents/test.agent.yaml';
229
+ }
230
+ }
231
+
232
+ const result = validateAgentFile(validationPath, agentData);
233
+
234
+ if (result.success && shouldPass) {
235
+ return {
236
+ passed: true,
237
+ message: 'Validation passed as expected',
238
+ };
239
+ }
240
+
241
+ if (!result.success && !shouldPass) {
242
+ const actualError = result.error.issues[0];
243
+
244
+ // If we have error expectations, validate strictly
245
+ if (errorExpectation) {
246
+ const validation = validateError(actualError, errorExpectation);
247
+
248
+ if (!validation.valid) {
249
+ return {
250
+ passed: false,
251
+ message: `Error validation failed: ${validation.reason}`,
252
+ };
253
+ }
254
+
255
+ return {
256
+ passed: true,
257
+ message: `Got expected error (${errorExpectation.code}): ${actualError.message}`,
258
+ };
259
+ }
260
+
261
+ // No specific expectations - just check that it failed
262
+ return {
263
+ passed: true,
264
+ message: `Got expected validation error: ${actualError?.message}`,
265
+ };
266
+ }
267
+
268
+ if (result.success && !shouldPass) {
269
+ return {
270
+ passed: false,
271
+ message: 'Expected validation to FAIL but it PASSED',
272
+ };
273
+ }
274
+
275
+ if (!result.success && shouldPass) {
276
+ return {
277
+ passed: false,
278
+ message: `Expected validation to PASS but it FAILED: ${result.error.issues[0]?.message}`,
279
+ };
280
+ }
281
+
282
+ return {
283
+ passed: false,
284
+ message: 'Unexpected test state',
285
+ };
286
+ } catch (error) {
287
+ return {
288
+ passed: false,
289
+ message: `Test execution error: ${error.message}`,
290
+ };
291
+ }
292
+ }
293
+
294
+ /**
295
+ * Main test runner
296
+ */
297
+ async function main() {
298
+ console.log(`${colors.cyan}╔═══════════════════════════════════════════════════════════╗${colors.reset}`);
299
+ console.log(`${colors.cyan}║ Agent Schema Validation Test Suite ║${colors.reset}`);
300
+ console.log(`${colors.cyan}╚═══════════════════════════════════════════════════════════╝${colors.reset}\n`);
301
+
302
+ // Find all test fixtures
303
+ const testFiles = await glob('test/fixtures/agent-schema/**/*.agent.yaml', {
304
+ cwd: path.join(__dirname, '..'),
305
+ absolute: true,
306
+ });
307
+
308
+ if (testFiles.length === 0) {
309
+ console.log(`${colors.yellow}⚠️ No test fixtures found${colors.reset}`);
310
+ process.exit(0);
311
+ }
312
+
313
+ console.log(`Found ${colors.cyan}${testFiles.length}${colors.reset} test fixture(s)\n`);
314
+
315
+ // Group tests by category
316
+ const categories = {};
317
+ for (const testFile of testFiles) {
318
+ const relativePath = path.relative(path.join(__dirname, 'fixtures/agent-schema'), testFile);
319
+ const parts = relativePath.split(path.sep);
320
+ const validInvalid = parts[0]; // 'valid' or 'invalid'
321
+ const category = parts[1]; // 'top-level', 'metadata', etc.
322
+
323
+ const categoryKey = `${validInvalid}/${category}`;
324
+ if (!categories[categoryKey]) {
325
+ categories[categoryKey] = [];
326
+ }
327
+ categories[categoryKey].push(testFile);
328
+ }
329
+
330
+ // Run tests by category
331
+ let totalTests = 0;
332
+ let passedTests = 0;
333
+ const failures = [];
334
+
335
+ for (const [categoryKey, files] of Object.entries(categories).sort()) {
336
+ const [validInvalid, category] = categoryKey.split('/');
337
+ const categoryLabel = category.replaceAll('-', ' ').toUpperCase();
338
+ const validLabel = validInvalid === 'valid' ? '✅' : '❌';
339
+
340
+ console.log(`${colors.blue}${validLabel} ${categoryLabel} (${validInvalid})${colors.reset}`);
341
+
342
+ for (const testFile of files) {
343
+ totalTests++;
344
+ const testName = path.basename(testFile, '.agent.yaml');
345
+ const result = runTest(testFile);
346
+
347
+ if (result.passed) {
348
+ passedTests++;
349
+ console.log(` ${colors.green}✓${colors.reset} ${testName} ${colors.dim}${result.message}${colors.reset}`);
350
+ } else {
351
+ console.log(` ${colors.red}✗${colors.reset} ${testName} ${colors.red}${result.message}${colors.reset}`);
352
+ failures.push({
353
+ file: path.relative(process.cwd(), testFile),
354
+ message: result.message,
355
+ });
356
+ }
357
+ }
358
+ console.log('');
359
+ }
360
+
361
+ // Summary
362
+ console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}`);
363
+ console.log(`${colors.cyan}Test Results:${colors.reset}`);
364
+ console.log(` Total: ${totalTests}`);
365
+ console.log(` Passed: ${colors.green}${passedTests}${colors.reset}`);
366
+ console.log(` Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`);
367
+ console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}\n`);
368
+
369
+ // Report failures
370
+ if (failures.length > 0) {
371
+ console.log(`${colors.red}❌ FAILED TESTS:${colors.reset}\n`);
372
+ for (const failure of failures) {
373
+ console.log(`${colors.red}✗${colors.reset} ${failure.file}`);
374
+ console.log(` ${failure.message}\n`);
375
+ }
376
+ process.exit(1);
377
+ }
378
+
379
+ console.log(`${colors.green}✨ All tests passed!${colors.reset}\n`);
380
+ process.exit(0);
381
+ }
382
+
383
+ // Run
384
+ main().catch((error) => {
385
+ console.error(`${colors.red}Fatal error:${colors.reset}`, error);
386
+ process.exit(1);
387
+ });
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Installation Component Tests - TEA Module
3
+ *
4
+ * Tests TEA module installation components in isolation:
5
+ * - Agent YAML structure validation
6
+ * - Module.yaml validation
7
+ * - Path references validation
8
+ *
9
+ * These are deterministic unit tests that don't require full installation.
10
+ * Usage: node test/test-installation-components.js
11
+ */
12
+
13
+ const path = require('node:path');
14
+ const fs = require('fs-extra');
15
+ const yaml = require('js-yaml');
16
+
17
+ // ANSI colors
18
+ const colors = {
19
+ reset: '\u001B[0m',
20
+ green: '\u001B[32m',
21
+ red: '\u001B[31m',
22
+ yellow: '\u001B[33m',
23
+ cyan: '\u001B[36m',
24
+ dim: '\u001B[2m',
25
+ };
26
+
27
+ let passed = 0;
28
+ let failed = 0;
29
+
30
+ /**
31
+ * Test helper: Assert condition
32
+ */
33
+ function assert(condition, testName, errorMessage = '') {
34
+ if (condition) {
35
+ console.log(`${colors.green}✓${colors.reset} ${testName}`);
36
+ passed++;
37
+ } else {
38
+ console.log(`${colors.red}✗${colors.reset} ${testName}`);
39
+ if (errorMessage) {
40
+ console.log(` ${colors.dim}${errorMessage}${colors.reset}`);
41
+ }
42
+ failed++;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Test Suite
48
+ */
49
+ async function runTests() {
50
+ console.log(`${colors.cyan}========================================`);
51
+ console.log('TEA Installation Component Tests');
52
+ console.log(`========================================${colors.reset}\n`);
53
+
54
+ const projectRoot = path.join(__dirname, '..');
55
+
56
+ // ============================================================
57
+ // Test 1: Module.yaml Structure
58
+ // ============================================================
59
+ console.log(`${colors.yellow}Test Suite 1: Module Configuration${colors.reset}\n`);
60
+
61
+ try {
62
+ const moduleYamlPath = path.join(projectRoot, 'src/module.yaml');
63
+ const moduleYaml = yaml.load(await fs.readFile(moduleYamlPath, 'utf8'));
64
+
65
+ assert(moduleYaml.code === 'tea', 'module.yaml has correct code: tea');
66
+ assert(moduleYaml.name === 'Test Architect', 'module.yaml has correct name');
67
+ assert(typeof moduleYaml.description === 'string' && moduleYaml.description.length > 0, 'module.yaml has description');
68
+ assert(typeof moduleYaml.default_selected === 'boolean', 'module.yaml has boolean default_selected');
69
+ } catch (error) {
70
+ assert(false, 'module.yaml loads and validates', error.message);
71
+ }
72
+
73
+ console.log('');
74
+
75
+ // ============================================================
76
+ // Test 2: TEA Agent YAML Structure
77
+ // ============================================================
78
+ console.log(`${colors.yellow}Test Suite 2: TEA Agent Structure${colors.reset}\n`);
79
+
80
+ try {
81
+ const teaAgentPath = path.join(projectRoot, 'src/agents/tea.agent.yaml');
82
+
83
+ if (await fs.pathExists(teaAgentPath)) {
84
+ const teaAgent = yaml.load(await fs.readFile(teaAgentPath, 'utf8'));
85
+
86
+ assert(teaAgent.agent !== undefined, 'tea.agent.yaml has agent root key');
87
+ assert(teaAgent.agent.metadata !== undefined, 'TEA agent has metadata section');
88
+ assert(teaAgent.agent.metadata.module === 'tea', 'TEA agent metadata has module: tea');
89
+ assert(teaAgent.agent.metadata.id.includes('_bmad/tea/'), 'TEA agent id references _bmad/tea/ path');
90
+ assert(teaAgent.agent.persona !== undefined, 'TEA agent has persona section');
91
+ assert(teaAgent.agent.critical_actions !== undefined, 'TEA agent has critical_actions');
92
+ assert(teaAgent.agent.menu !== undefined, 'TEA agent has menu');
93
+ assert(Array.isArray(teaAgent.agent.menu) && teaAgent.agent.menu.length === 8, 'TEA agent menu has 8 workflows');
94
+
95
+ // Verify no BMM references
96
+ const yamlContent = await fs.readFile(teaAgentPath, 'utf8');
97
+ assert(!yamlContent.includes('_bmad/bmm/'), 'TEA agent has no _bmad/bmm/ references');
98
+ assert(!yamlContent.includes('module: bmm'), 'TEA agent has no module: bmm references');
99
+ } else {
100
+ assert(false, 'TEA agent YAML exists', 'src/agents/tea.agent.yaml not found - run Phase 2 first');
101
+ }
102
+ } catch (error) {
103
+ assert(false, 'TEA agent structure validates', error.message);
104
+ }
105
+
106
+ console.log('');
107
+
108
+ // ============================================================
109
+ // Test 3: Knowledge Base Structure
110
+ // ============================================================
111
+ console.log(`${colors.yellow}Test Suite 3: Knowledge Base${colors.reset}\n`);
112
+
113
+ try {
114
+ const teaIndexPath = path.join(projectRoot, 'src/testarch/tea-index.csv');
115
+
116
+ if (await fs.pathExists(teaIndexPath)) {
117
+ const csvContent = await fs.readFile(teaIndexPath, 'utf8');
118
+ const lines = csvContent.trim().split('\n');
119
+
120
+ assert(lines.length === 35, 'tea-index.csv has 35 lines (header + 34 fragments)', `Found ${lines.length} lines`);
121
+ assert(lines[0].includes('id,name,description,tags,fragment_file'), 'tea-index.csv has correct header format');
122
+
123
+ // Verify no BMM references in CSV
124
+ assert(!csvContent.includes('bmm'), 'tea-index.csv has no BMM references');
125
+ } else {
126
+ console.log(` ${colors.dim}Skipping - tea-index.csv not found (run Phase 2 first)${colors.reset}`);
127
+ }
128
+ } catch (error) {
129
+ assert(false, 'Knowledge base structure validates', error.message);
130
+ }
131
+
132
+ console.log('');
133
+
134
+ // ============================================================
135
+ // Test 4: Workflow Structure
136
+ // ============================================================
137
+ console.log(`${colors.yellow}Test Suite 4: Workflow Structure${colors.reset}\n`);
138
+
139
+ const workflowNames = ['framework', 'ci', 'test-design', 'atdd', 'automate', 'test-review', 'nfr-assess', 'trace'];
140
+
141
+ for (const workflowName of workflowNames) {
142
+ const workflowYamlPath = path.join(projectRoot, `src/workflows/testarch/${workflowName}/workflow.yaml`);
143
+
144
+ if (await fs.pathExists(workflowYamlPath)) {
145
+ try {
146
+ const workflowYaml = yaml.load(await fs.readFile(workflowYamlPath, 'utf8'));
147
+ assert(workflowYaml !== undefined, `${workflowName}/workflow.yaml is valid YAML`);
148
+
149
+ // Verify no BMM references
150
+ const yamlContent = await fs.readFile(workflowYamlPath, 'utf8');
151
+ assert(!yamlContent.includes('_bmad/bmm/'), `${workflowName} has no _bmad/bmm/ references`);
152
+ } catch (error) {
153
+ assert(false, `${workflowName}/workflow.yaml validates`, error.message);
154
+ }
155
+ }
156
+ }
157
+
158
+ console.log('');
159
+
160
+ // ============================================================
161
+ // Summary
162
+ // ============================================================
163
+ console.log(`${colors.cyan}========================================`);
164
+ console.log('Test Results:');
165
+ console.log(` Passed: ${colors.green}${passed}${colors.reset}`);
166
+ console.log(` Failed: ${colors.red}${failed}${colors.reset}`);
167
+ console.log(`========================================${colors.reset}\n`);
168
+
169
+ if (failed === 0) {
170
+ console.log(`${colors.green}✨ All installation component tests passed!${colors.reset}\n`);
171
+ process.exit(0);
172
+ } else {
173
+ console.log(`${colors.red}❌ Some installation component tests failed${colors.reset}\n`);
174
+ process.exit(1);
175
+ }
176
+ }
177
+
178
+ // Run tests
179
+ runTests().catch((error) => {
180
+ console.error(`${colors.red}Test runner failed:${colors.reset}`, error.message);
181
+ console.error(error.stack);
182
+ process.exit(1);
183
+ });