Skip to content
TEA docs in plain text: llms-full.txt

TEA Configuration Reference

TEA configuration keys, defaults, and the skills they affect.

bmad setup tea asks TEA’s setup questions and writes the answers to the [modules.tea] table of _bmad/config.toml. The bmad skill from BMad Method core runs setup; TEA’s questions come from skills/bmod-tea/bmod.toml. If a TEA skill finds no [modules.tea] table, it tells you to run bmad setup tea and stops.

Skills read the config through _bmad/scripts/resolve_config.py, which merges three layers, later files winning:

FileHolds
_bmad/config.tomlThe setup answers
_bmad/custom/config.tomlTeam overrides, committed with the project
_bmad/custom/config.user.tomlPersonal overrides, kept out of version control

Setup answers are strings. A boolean key holds "true" or "false", and skills read those as booleans.

To change an answer, run bmad setup tea again: it shows each answer with its value and the file it lives in, and changes the ones you name. You can also edit the TOML directly. Skills read the config once at activation, so start a fresh chat after a change.

Every module setup key is read by a skill. The two Per-Skill Settings live in customization files and are configured separately.

TEA 3.0 names every direct workflow bmad-tea-*. Use these command replacements:

Before 3.0From 3.0
bmad-testarch-automatebmad-tea-automate
bmad-testarch-evaluatebmad-tea-evaluate
bmad-testarch-frameworkbmad-tea-framework
bmad-testarch-nfrbmad-tea-nfr
bmad-testarch-test-designbmad-tea-test-design
bmad-testarch-test-reviewbmad-tea-test-review
bmad-testarch-tracebmad-tea-trace
bmad-teach-me-testingbmad-tea-teach-me-testing

The 3.0 package does not publish the old slash commands. The agent name bmad-tea, module name bmod-tea, menu codes, and existing tea-* CLI names remain.

After installing 3.0, run this in each existing project before invoking a workflow directly:

Terminal window
npx --package=bmad-method-test-architecture-enterprise@3 tea-migrate-customizations --project-root . --check
npx --package=bmad-method-test-architecture-enterprise@3 tea-migrate-customizations --project-root .

The migration renames old customization files, including ATDD, CI, and teaching files. It updates old [[agent.menu]] skill IDs in _bmad/custom/bmad-tea.toml and .user.toml; ATDD routes to Automate and CI to Framework. It preserves other settings, comments, and file permissions. When old and new files coexist in one layer, merge their values and comments manually. The command checks every file before writing. Headless TEA CLIs can read old filenames until migration completes.

An upgrade can leave the former skill folders in a host’s project or global skills directory. After migrating customization files, check for old slash commands and move their folders to a backup. Review edits in those folders before removing them from the host’s skill discovery path.

The setup defaults are the recommended values:

_bmad/config.toml
[modules.tea]
test_artifacts = "{project-root}/_bmad-output/test-artifacts"
tea_use_playwright_utils = "true" # production-ready fixtures and utilities
tea_use_pactjs_utils = "true" # pactjs-utils is the implementation whenever contract tests are written
tea_pact_mcp = "mcp" # use a broker when one is reachable; skipped automatically when it is not
tea_browser_automation = "auto" # smart CLI/MCP selection with fallback
tea_execution_mode = "auto" # capability-aware orchestration
tea_capability_probe = "true" # fall back safely when a mode is unsupported
test_stack_type = "auto"
test_framework = "auto"
auto_validate = "true"
auto_heal_failures = "true"
max_healing_iterations = "3"
use_mcp_healing = "true"
Terminal window
npm install -D @seontechnologies/playwright-utils
npm install -g @playwright/cli@latest # needed for 'cli' and 'auto' browser modes

Pact scaffolding requires an applicable consumer-provider boundary. For applicable Pact suites, tea_use_pactjs_utils: true selects Pact.js Utils; false selects raw Pact. tea_pact_mcp: mcp uses available broker tools, with provider source or an OpenAPI spec as the fallback. The report identifies the source used.


Each key below is asked by bmad setup tea and stored under [modules.tea].

Base output folder for TEA-generated artifacts (test designs, reports, traceability).

Type: string · Default: {project-root}/_bmad-output/test-artifacts

Setup question: Where should test artifacts be stored? (test plans, coverage reports, quality audits)

Skills replace {project-root} in the value with the project root, so it can live outside the core output folder. Each skill writes into its own folder under it, as described in Output Layout.

test_artifacts = "{project-root}/docs/testing-artifacts"

Enable Playwright Utils integration for production-ready fixtures and utilities.

Type: boolean · Default: true

Setup question: Use Playwright Utils (@seontechnologies/playwright-utils) as the default implementation for Playwright tests?

When the flag is true and the package is a project dependency, playwright-utils-mandate defines the default implementation:

CapabilityImplementation
Network interceptioninterceptNetworkCall
API requestsapiRequest
Pollingrecurse
Test logginglog
Fixture entry pointtest from the project’s merged fixtures

A capability outside the utilities’ scope can use plain Playwright with a // playwright-utils deviation: <reason> comment and an entry in the output summary. auth-session, network-recorder, webhook helpers, and burn-in are recommended integrations that need project wiring. Skills describe that wiring when proposing them.

With the flag enabled and the package absent, TEA generates plain Playwright, skips the utility review criteria, and recommends running framework. tea_use_pactjs_utils has the same package gate.

The Playwright mandate applies to JavaScript/TypeScript suites on the Playwright runner.

Affects skills (each reads the key and branches on it):

  • automate red mode loads the mandate, selects a playwright-utils fragment profile, and passes use_playwright_utils to generation workers. Red-phase scaffolds are generated in playwright-utils style, since the scaffold is the file the developer un-skips and keeps
  • automate expand mode uses the same fragment profile and worker flag, plus a merged-fixtures.ts entry point and an auth fixture built on auth-session during aggregation
  • test-design loads the mandate so every code example in the design document matches what automate will generate
  • test-review scores registry rows M9 (a configured utility bypassed with no stated deviation, MEDIUM) and L9 (a spec importing test from @playwright/test against a merged-fixtures convention, LOW). M9 also requires the package to be a project dependency: the flag alone never produces a deduction
  • framework framework phase installs the package, scaffolds merged-fixtures.ts and the auth fixture, and generates samples in the mandated style
  • framework CI phase uses runBurnIn for Playwright burn-in selection

The trace and nfr-assess skills do not read this key.

tea_use_playwright_utils = "true" # "false" selects plain Playwright

Prerequisites:

Terminal window
npm install -D @seontechnologies/playwright-utils

Related:


Enable Pact.js Utils integration for consumer-driven contract testing utilities.

Type: boolean · Default: true

Setup question: Use Pact.js Utils (@seontechnologies/pactjs-utils) when contract tests are written?

When the flag is true and the package is installed, pactjs-utils-mandate defines the default implementation for applicable Pact artifacts:

CapabilityImplementation
Provider-state parameterscreateProviderState
Verifier configurationbuildVerifierOptions
Auth request filtercreateRequestFilter
PactV4 request/response bodiessetJsonContent / setJsonBody

Raw Pact is allowed where the helpers cannot cover a capability, with a // pactjs-utils deviation: <reason> comment and an entry in the output summary. Before creating contract scaffolds, TEA checks whether contract testing applies to the project. Existing Pact artifacts, a dependency on @pact-foundation/pact, broker variables, two or more independently deployable services in the repo that call each other, or an explicit request for contract testing each establish relevance. See pactjs-utils-mandate for the full rules.

zodToPactMatchers and the pact-consumer-di injection are recommended integrations. The first needs a Zod schema; the second needs a production-code change. TEA describes the missing setup when proposing them.

The determinism rules never relax under the mandate: one addInteraction() per it(), fileParallelism: false plus pool: 'forks' plus singleFork: true on the consumer config, the pool pair on the provider config, and provider scrutiny before any response matcher.

Affects skills:

  • framework framework phase installs the packages and scaffolds Pact samples when contract testing is relevant
  • automate red mode loads the mandate and generates contract scaffolds in that style
  • automate expand mode loads the mandate and passes pact config to subagents
  • test-design loads the mandate so Pact code examples in design documents match what automate generates
  • test-review scores registry row M10 (a configured contract utility bypassed with no stated deviation, MEDIUM), gated on the flag plus the package being installed
  • framework CI phase adds a contract-test stage and quality gates

Set this to false for raw @pact-foundation/pact output.

tea_use_pactjs_utils = "true" # "false" selects raw Pact

Prerequisites:

Terminal window
npm install -D @seontechnologies/pactjs-utils @pact-foundation/pact
# peer dependency: @pact-foundation/pact >= 16.2.0

For the remote flow with a Pact Broker, set PACT_BROKER_BASE_URL and PACT_BROKER_TOKEN, plus GITHUB_SHA (GitHub Actions sets this) and GITHUB_BRANCH (you must set it explicitly: ${{ github.head_ref || github.ref_name }}). The flow follows PACT_BROKER_BASE_URL: when it is set the remote flow runs, otherwise the local monorepo flow runs and needs pactUrls, the list of local pact files, instead of a broker. The consumer generates the pacts and the provider verifies them locally.

Related:


Pact MCP strategy for broker interaction during contract testing skills.

Type: string · Default: "mcp" · Options: "mcp" | "none"

Setup question: Use the SmartBear MCP for PactFlow or a Pact Broker?

Controls whether TEA can use SmartBear MCP tools for provider-state discovery, Pact test review assistance, and can-i-deploy/matrix guidance.

Each broker-dependent step checks once whether SmartBear MCP tools are available in the session. When they are unavailable, it follows pact-mcp’s fallback: provider source, then an OpenAPI spec, then the confidence gate if the needed facts remain unknown. The report records tool availability and the source used for provider states.

Affects skills: test-design, automate (red and expand), framework (framework and CI), and test-review.

Set it to none to disable broker calls, for example in an air-gapped environment.

tea_pact_mcp = "mcp" # "none" disables all broker/MCP integration

Prerequisites:

Terminal window
npm install -g @smartbear/mcp # Node.js 20+ required
# or run on demand: npx -y @smartbear/mcp@latest

Required broker env vars:

  • PACT_BROKER_BASE_URL (for example https://{tenant}.pactflow.io)
  • PACT_BROKER_TOKEN (or username/password for basic auth)

Related:


Browser automation strategy. Controls how TEA interacts with live browsers during test generation.

Type: string · Default: "auto" · Options: "auto" | "cli" | "mcp" | "none"

Setup question: How should TEA drive live browsers while generating tests?

ModeBehavior
autoRecommended. CLI for stateless tasks, MCP for stateful flows. Falls back gracefully.
cliCLI only (@playwright/cli). MCP ignored.
mcpMCP only. CLI ignored. Same as the old tea_use_mcp_enhancements: true.
noneNo browser interaction. Pure AI generation from docs and code.

Affects skills:

  • test-design exploratory mode (CLI snapshots for page discovery)
  • automate red and expand modes: recording for selector verification, plus browser evidence for test repairs when enabled
  • nfr-assess browser-based evidence collection when the mode is cli or auto
  • test-review evidence collection (CLI for traces and screenshots)

Prerequisites:

Terminal window
# CLI mode (and 'auto')
npm install -g @playwright/cli@latest
playwright-cli install --skills # run from project root; Node.js 18+
# MCP mode (and 'auto') needs two servers configured in your IDE:
# playwright -> npx @playwright/mcp@latest
# playwright-test -> npx playwright run-test-mcp-server
tea_browser_automation = "auto" # "cli" | "mcp" | "none"

Migration from the old flag:

Old settingNew equivalent
tea_use_mcp_enhancements: truetea_browser_automation: "auto"
tea_use_mcp_enhancements: falsetea_browser_automation: "none"

Related:


Execution strategy for orchestration-capable TEA skills.

Type: string · Default: "auto" · Options: "auto" | "subagent" | "agent-team" | "sequential"

Setup question: How should TEA run multi-step generation and evaluation?

Applies to automate (red and expand), test-review, nfr-assess, framework (framework and CI), test-design, and trace. teach-me-testing does not use this setting.

ModeBehavior
autoRecommended. Picks the best supported mode using runtime capability checks when probing.
agent-teamPrefer runtime team/delegation orchestration.
subagentPrefer isolated subagent-style orchestration.
sequentialForce one-by-one execution. Most deterministic, typically slowest.

Per-skill effect:

SkillOrchestrated unitWhat the mode changes
automate expand modeAPI + E2E/backend/mobile generation workersDispatch style only
automate red mode (ATDD)failing API + failing E2E workersDispatch style only
test-reviewquality-dimension workersDispatch style only
nfr-assessdomain assessment workersDispatch style only
frameworkscaffold work unitsDispatch style only
framework CI phaseorchestration-capable pipeline generation stepOrchestration policy
test-designorchestration-capable output generation stepOrchestration policy
tracephase/work-unit separation with dependenciesOrchestration policy

In agent-team and subagent modes, the runtime decides scheduling and concurrency. Output contracts are the same across modes.

Resolution order:

  1. Normalize an explicit run-level request when one is present: agent team / agent teams / agentteam become agent-team; subagent / subagents / sub agent / sub agents become subagent; sequential and auto pass through.
  2. With no explicit override, use tea_execution_mode from [modules.tea].
  3. With tea_capability_probe: true, detect runtime support for agent-team and subagent.
  4. Resolve: auto walks agent-team then subagent then sequential; an explicit agent-team or subagent falls back only when probing is enabled; sequential is always sequential.
tea_execution_mode = "auto" # "sequential" forces deterministic single-threaded runs

Whether TEA probes runtime capabilities before resolving the execution mode.

Type: boolean · Default: true

Setup question: Check what the tool supports before choosing an execution mode, and fall back when it is missing?

When enabled, TEA checks whether agent-team or subagent execution is supported and falls back safely. When disabled, TEA honors the configured mode strictly and fails if it is unsupported.

tea_capability_probe = "true" # "false" honors tea_execution_mode strictly

Detected or configured project stack type. Controls CI pipeline generation and framework selection.

Type: string · Default: "auto" · Options: "auto" | "frontend" | "backend" | "fullstack" | "mobile"

Setup question: What type of project is this?

Stack typeBehavior
autoAuto-detect from project manifests (playwright.config.*, jest.config.*, pyproject.toml, go.mod, pubspec.yaml, and similar)
frontendBrowser-based tests (Playwright/Cypress), browser install in CI, burn-in enabled
backendAPI/unit tests (pytest, JUnit, Go test, Jest/Vitest), no browser install, burn-in skipped by default
fullstackBoth frontend and backend tests, full CI pipeline
mobileNative app: Maestro device flows plus the app’s unit/component suite, no browser install, burn-in enabled and scoped to changed flows

Detection checks mobile first: a React Native or Expo project carries package.json with react and would otherwise misdetect as frontend.

Affects skills:

  • framework CI phase uses stack-conditional pipeline stages (browser install, burn-in, device/emulator legs)
  • framework framework phase adapts the scaffold to the stack type
  • automate expand mode selects which generation workers launch (mobile runs the API worker plus the mobile worker)
  • test-design scopes the planned test levels to the stack
  • automate red mode picks stack-appropriate failing-test patterns
  • test-review applies stack-appropriate review criteria
test_stack_type = "fullstack"

Detected or configured test framework preference.

Type: string · Default: "auto"

Options: "auto" | "playwright" | "cypress" | "jest" | "vitest" | "pytest" | "junit" | "go-test" | "dotnet-test" | "rspec" | "maestro" | "other"

Setup question: Which test framework does the project use?

Controls which framework patterns TEA uses for code generation. With "auto", TEA detects from project configuration files and manifests.

Affects skills: framework (scaffold generation and CI test commands) and automate (red and expand test generation patterns).

test_framework = "playwright"

Execute generated tests during Create.

Type: boolean · Default: true

Setup question: Run generated tests during Create? true (recommended) or false to report generation without execution.

Affects skills: automate in red and expand modes.

Set "false" to generate tests without executing them, matching the generation-only behavior of version 2.0.0. Repair requires execution, so this also disables repairs for the run.

auto_validate = "true"

Repair confirmed defects in generated tests after execution while preserving acceptance criteria and real product defects.

Type: boolean · Default: true

Setup question: Repair confirmed defects in generated tests after running them? true (recommended) or false to report failures without repairs. Acceptance criteria and real product defects are preserved.

Affects skills: automate Create in red and expand modes.

Requires auto_validate to be enabled. Set "false" to execute tests and report failures without repairs.

auto_heal_failures = "true"

Maximum repair and rerun rounds after the initial execution, from 0 to 3.

Type: integer · Default: 3

Setup question: How many repair rounds may generated tests use? 0 to 3, with 3 recommended.

Affects skills: automate Create and Resume in red and expand modes.

Set "0" to execute tests once and report failures without repairs. Resume retains rounds already used.

max_healing_iterations = "3"

Use available browser evidence tools to diagnose generated browser test failures when the browser automation setting permits MCP.

Type: boolean · Default: true

Setup question: Use available browser evidence tools to diagnose generated browser test failures? true (recommended) or false to use source, runner reports and traces.

Affects skills: automate Create in red and expand modes.

Test execution and repairs also work without MCP. Set "false" to diagnose failures from source, runner reports, and traces.

use_mcp_healing = "true"

Each setting below is read by one skill and lives in its customization file under [workflow]. Put team values in _bmad/custom/<skill>.toml and personal values in _bmad/custom/<skill>.user.toml. The bmad-customize skill can write either file.

Base folder for Evaluate (bmad-tea-evaluate) evaluation folders.

Type: string · Default: evals · File: _bmad/custom/bmad-tea-evaluate.toml

Resolves to {project-root}/{value}, independent of test_artifacts. Earlier releases named this key tea_evaluations_folder and stored it with the module config; a value there is no longer read.

_bmad/custom/bmad-tea-evaluate.toml
[workflow]
evaluations_folder = "quality/evals"

CI/CD platform for pipeline generation.

Type: string · Default: "auto" · File: _bmad/custom/bmad-tea-framework.toml

Options: "auto" | "github-actions" | "gitlab-ci" | "jenkins" | "azure-devops" | "harness" | "circle-ci" | "other"

Controls which CI template the framework skill’s CI phase uses and where it writes. With "auto", TEA scans for .github/workflows/, .gitlab-ci.yml, Jenkinsfile, azure-pipelines.yml, .harness/, and .circleci/config.yml, then falls back to inferring from the git remote. Any other value skips detection. Earlier releases stored this key with the module config; a value there is no longer read.

Affects skills: framework when CI is included.

An explicit ci_platform override in _bmad/custom/bmad-tea-framework.toml or its .user.toml wins, including an explicit "auto". Otherwise, existing _bmad/custom/bmad-tea-ci.toml and .user.toml values supply the CI setting. The default remains "auto".

Framework customizations apply when framework setup is included. CI-only runs use your CI customizations. Both includes each phase’s customizations once; Resume skips hooks that already finished. bmad setup tea and bmad migrate keep invocation entries and configuration values. Run the 3.0 customization migration above to rename pre-3.0 workflow files.

_bmad/custom/bmad-tea-framework.toml
[workflow]
ci_platform = "github-actions"

bmad-tea-automate supports red and expand modes selected by your prompt. The command and TA menu code default to expand when no task mode is given; ask for acceptance tests before implementation to select red. Unattended runs state the selected mode in the summary. Resume continues interrupted red or expand progress. A new unattended run starts over by default.

Red reads _bmad/custom/bmad-tea-atdd.toml; expand reads _bmad/custom/bmad-tea-automate.toml. Both include their .user.toml layers. Only the selected mode’s activation hooks, persistent facts, and completion hook run.

Create runs execute generated tests, classify failures, fix test issues, and rerun. Red verifies the intended missing behavior in a disposable activated copy. It uses tea-atdd-red-check when available for compatible browserless loopback Playwright tests and tea-unit-check for Vitest and Jest scaffolds; browser tests or projects needing their own environment and services use the installed project runner with original configuration and environment. The summary records the execution route and any fallback reason. Expand aims for passing coverage and reports real product defects with their assertions intact. Validate reports findings and Edit checks requested changes. These operations never repair tests or require the full suite to pass.

These are setup answers under [modules.tea]. An explicit instruction for a run overrides the setup default:

SettingDefaultEffect
auto_validatetrueExecute generated tests during Create.
auto_heal_failurestrueRepair test issues after execution. Requires validation.
max_healing_iterations3Maximum repair and rerun rounds, from 0 to 3.
use_mcp_healingtrueUse available browser MCP evidence when browser automation allows it. Test execution and repairs also work without MCP.
_bmad/custom/config.toml
[modules.tea]
auto_validate = "true"
auto_heal_failures = "true"
max_healing_iterations = "3"
use_mcp_healing = "true"

The summary lists what was repaired, the execution results, and remaining test or product failures.

Every TEA skill also reads the [core] table of the same config layers. bmad setup writes project_name and output_folder there. The other keys below are optional; set them under [core] yourself, in _bmad/custom/config.user.toml for personal values such as your name.

Type: string · Default: {project-root}/_bmad-output

Base output folder for core BMad artifacts. TEA writes its own artifacts under test_artifacts, which defaults to {project-root}/_bmad-output/test-artifacts. The default does not follow a different output_folder; when you changed it, answer the test_artifacts setup question to match.

[core]
output_folder = "{project-root}/_bmad-output"

Type: string · Default: none

Your name. Skills greet you with it, and teach-me-testing uses it to name your progress and session-notes files.

_bmad/custom/config.user.toml
[core]
user_name = "Jane Doe"

Type: string · Default: directory name

Used in report headers, documentation titles, CI configuration comments, and the test-design handoff filename {test_artifacts}/test-design/{project_name}-handoff.md.

[core]
project_name = "my-awesome-app"

Type: string · Default: none (the skill answers in your language)

Language for TEA chat responses. Any language works.

[core]
communication_language = "english"

Type: string · Default: none

Language for TEA-generated documents (test designs, reports). It can differ from communication_language: chat in Spanish, generate docs in English.

[core]
document_output_language = "english"

Older projects may still hold classic-installer files under _bmad/tea/. To upgrade, run bmad migrate in the assistant chat. The v6 installer in bmad-method 6.12 already writes [modules.tea] into _bmad/config.toml. A project with that table can still carry v6 keys. If [modules.tea] is missing from every config layer, run bmad setup tea first, then run the migration. The migration keeps the thirteen current module settings, converts their values to strings, and moves non-default ci_platform and tea_evaluations_folder values into their skill customization files. It removes both moved keys and all unread keys from every [modules.tea] layer, and offers to delete the classic installer’s config, help file, and TEA agent or skill copies under _bmad/tea/. If answers survive only in the classic YAML while the TOML holds defaults, the migration proposes restoring them for your approval. A _bmad/tea/config.yaml that is left is not read by any skill. The tea-test-review CLI is the one exception: it reads that file only when _bmad/config.toml does not exist, so older CI setups keep working. See tea-test-review CLI.

The risk_threshold key was never read by a skill and is no longer asked at setup. tea_evaluations_folder and ci_platform moved to Per-Skill Settings.

Earlier releases also declared three FUTURE output-folder keys: test_design_output, test_review_output, and trace_output. No skill ever read them, and they are removed. Every skill now writes to a fixed folder of its own, described in Output Layout.


Outputs use fixed folders under {test_artifacts}: test-design/, atdd/, automate/, test-review/, nfr/, trace/, ci/, and framework/. Framework and CI setup save progress in framework/setup-run-progress.md. Resume picks up any interrupted setup run where it stopped, including Edit and Validate. The existing framework/framework-setup-progress.md and ci/ci-pipeline-progress.md files remain Create progress checkpoints. Edit and Validate leave that earlier progress intact. Previous setup history and validation reports are kept when a new run begins. The folder names are fixed, and no configuration key moves them. teach-me-testing keeps its per-learner folders, and Evaluate writes under evaluations_folder.

Commit outputs to keep a history per scope. Re-running a scope replaces its outputs; other scopes retain their files.

A file produced once per scope carries that scope’s run_key in its name, so a trace run for epic 16 never opens, rewrites, or appends to epic 15’s matrix or gate decision. A file that exists once per project keeps a plain name: test-design-architecture.md, test-design-qa.md, {project_name}-handoff.md, ci-pipeline-progress.md, and framework-setup-progress.md.

Paths are relative to {test_artifacts} unless noted. Deliverables are declared in the skill’s workflow.yaml; resume progress files are declared in the steps or setup resources that write them.

SkillOutput
test-designtest-design/test-design-architecture.md and test-design/test-design-qa.md (system-level writes both)
test-designtest-design/{project_name}-handoff.md (system-level; feeds BMAD create-epics-and-stories)
test-designtest-design/test-design-epic-{epic_num}.md (epic-level)
test-designtest-design/test-design-progress-{run_key}.md (resume checkpoint; run_key is system or epic-{epic_num})
test-designtest-design/exploration/explore-{run_key}-<page>.png (browser exploration screenshots)
framework{project-root}/tests/README.md
frameworkframework/setup-run-progress.md (shared setup progress for Create, Edit, and Validate)
frameworkframework/framework-setup-progress.md (Create progress checkpoint)
framework CI phase{project-root}/.github/workflows/test.yml (GitHub Actions default; per-platform otherwise)
framework CI phaseci/ci-pipeline-progress.md (Create progress checkpoint)
automate red modeatdd/atdd-checklist-{story_key}.md
automateautomate/automation-summary-{run_key}.md
test-reviewtest-review/test-review-{run_key}.md (a non-empty output_file_override replaces this path for one run)
test-reviewtest-review/review-evidence-{run_key}.png (browser evidence screenshot)
nfr-assessnfr/nfr-assessment-{run_key}.md
nfr-assessnfr/perf-{run_key}-<page>.png (browser evidence screenshots)
tracetrace/traceability-matrix-{run_key}.md
tracetrace/e2e-trace-summary-{run_key}.json (machine-readable summary for CI/CD and reporting)
tracetrace/gate-decision-{run_key}.json (emitted only when the collection is gate-eligible)
teach-me-testingteaching-progress/{user_name}-tea-progress.yaml
teach-me-testingtea-academy/{user_name}/session-{N}-notes.md
teach-me-testingtea-academy/{user_name}/tea-completion-summary.md

trace also reads two optional inputs it never writes, and both stay at the root of {test_artifacts} because other tools and people produce them: live-verification-results.json and gate-waivers.md. Any producer may write live-verification-results.json (an agent, a shell script, a CI job, or a person recording an outcome by hand). See Live Verification Results for the contract.

Each skill that runs once per scope resolves its run_key in its first step, before it writes anything, and records it as runScope and runKey in the output’s frontmatter. Later steps carry both forward unchanged.

  • system: the whole project or system, or no narrower scope could be resolved.
  • epic-{epic_num}: one epic. An epic with no number uses the slug of its title.
  • story-{story_key}: one story. story_key is the BMM story file basename without .md (for example 1-2-user-authentication). Without a story file, it is the story id with . replaced by - (1.2 becomes 1-2).
  • release-{slug} and hotfix-{slug}: trace only, from gate_type and the release version or hotfix id.
  • target-{slug}: automate and test-review only, when no story or epic applies. The slug comes from the automated or reviewed path or feature name. A test-review run with review_scope: suite and no story or epic is system.

The slug rule applies to every {slug} and to an epic title with no number: lowercase; replace every run of characters outside a-z and 0-9 with a single -; trim leading and trailing -; truncate to 64 characters. For example, release v1.2.0 becomes release-v1-2-0, and the review target tests/e2e/checkout.spec.ts becomes target-tests-e2e-checkout-spec-ts.

A skill resolves the scope in this order:

  1. The scope you name when you invoke it (“run trace for epic 16”).
  2. The scope the loaded artifacts carry: a story file name, an epic document’s metadata, heading, or filename, or trace’s gate_type and its id.
  3. When several candidates remain, an interactive run lists them, asks which one this run covers, and waits. A headless or autonomous run never asks: it uses system, or target-{slug} where a target applies, and says so in its output. The one exception is a test-design epic plan, which has no system-level fallback: a headless epic-level run whose epic stays ambiguous halts with a message naming the candidate epics.

Automate red mode (atdd in stored identifiers) runs once per story, so its checklist is named by story_key directly. test-design uses system or epic-{epic_num}.

A run reads and writes only its own run_key’s files. Files for other scopes are never opened.

The output path determines how a run starts:

  • No file: a fresh run.
  • An earlier run of this scope was interrupted (the file is marked in progress): an interactive run asks whether to resume or start over, and a headless or autonomous run starts over.
  • An earlier run of this scope finished: the new run replaces the file entirely.

Two runs are never merged into one file. A file grows only while the run that created it is still adding its later sections. To keep an earlier result for the same scope, commit or copy it before you re-run. A trace run that evaluates no gate also removes an earlier gate-decision-{run_key}.json for the same run_key, so the folder never pairs a new summary with a stale decision.

Framework and CI setup use fixed progress filenames. Resume continues the saved setup scope and operation. A new unattended Create, Edit, or Validate request starts over when earlier progress is unfinished; an explicit Resume request continues it. An uncertain customization action still needs your confirmation.

Earlier TEA versions wrote everything flat under {test_artifacts} with fixed names, such as traceability-matrix.md, gate-decision.json, test-review.md, nfr-assessment.md, and automation-summary.md. Upgrading leaves those files where they are:

  • New runs never treat an old flat file as their own output, so they never rewrite it or append to it.
  • Skills that read another skill’s output look in the producing skill’s folder first, then at the old root location, and name both. For example, nfr-assess looks for test-design documents in test-design/ and then at the root of {test_artifacts}, and automate looks for ATDD checklists in atdd/ and then at the root.
  • Resume migrates an old file only while it is still in progress. A completed flat file stays where it is. Resume first resolves the file’s scope. Automate red mode recovers the story from the checklist’s storyKey, a test-design checkpoint that already carries a runKey (test-design-progress-{run_key}.md at the root) keeps it, and for any other old file Resume asks which scope it covers. It then writes the file into the skill’s folder under its scoped name with runScope and runKey added, deletes the old copy, and continues. It never writes over a scoped file that already exists for the same scope. Framework and CI checkpoints have no story, epic, or release scope to resolve, so they move their root checkpoint into their folder under the same rules.

Once nothing you run still reads an old file, archive or delete it.

CI jobs, dashboards, and scripts that read TEA’s old flat paths need the new ones:

Old path under {test_artifacts}New path under {test_artifacts}
gate-decision.jsontrace/gate-decision-{run_key}.json
e2e-trace-summary.jsontrace/e2e-trace-summary-{run_key}.json
traceability-matrix.mdtrace/traceability-matrix-{run_key}.md
test-review.mdtest-review/test-review-{run_key}.md
nfr-assessment.mdnfr/nfr-assessment-{run_key}.md
automation-summary.mdautomate/automation-summary-{run_key}.md
atdd-checklist-{story_key}.mdatdd/atdd-checklist-{story_key}.md
test-design-architecture.md, test-design-qa.mdtest-design/test-design-architecture.md, test-design/test-design-qa.md
test-design-epic-{epic_num}.mdtest-design/test-design-epic-{epic_num}.md
test-design-progress-{run_key}.mdtest-design/test-design-progress-{run_key}.md
test-design-progress.mdtest-design/test-design-progress-{run_key}.md (after Resume migrates it)
ci-pipeline-progress.mdci/ci-pipeline-progress.md
framework-setup-progress.mdframework/framework-setup-progress.md
{workflow}-validation-report-{validation_scope}-{run_timestamp}.mdthe same name inside the skill’s folder

A job that gates one scope reads that scope’s file, for example trace/gate-decision-epic-16.json or trace/gate-decision-release-v1-2-0.json. A job that wants the latest gate of any scope globs trace/gate-decision-*.json and picks the file with the newest evaluated_at. The run_key in each file name identifies the scope, and the target field inside gives the gate type and target id.

The tea-test-review CLI is unaffected: it passes its own --output path (default test-review.md, resolved under --project-root, which defaults to the working directory) as output_file_override, which replaces the skill’s default path.

Rebinding {test_artifacts} From a Customization

Section titled “Rebinding {test_artifacts} From a Customization”

Before this layout existed, some projects got per-skill folders with an activation_steps_append rule in _bmad/custom/bmad-tea-*.toml that rebinds {test_artifacts} to a subfolder before the first step runs. Remove that rule when you upgrade. Each skill already appends its own folder, so a rebound {test_artifacts} nests a second level, such as test-artifacts/traceability/trace/.

{test_artifacts} also locates shared inputs and other skills’ outputs. Rebinding it can hide trace’s live results and waivers, test-design documents, ATDD checklists, and NFR audit reports.

Validate mode preserves every report as a separate artifact. The artifact-producing skills and their named modes write {workflow}-validation-report-{validation_scope}-{run_timestamp}.md into their own folder under {test_artifacts}, next to the outputs they validate. The stored workflow identifier is atdd, automate, ci, framework, nfr-assess, test-design, test-review, or trace; nfr-assess reports land in nfr/.

validation_scope identifies what was checked, such as story-1-2, epic-9, system, or pull-request-123. run_timestamp is the UTC start time with milliseconds in YYYYMMDDTHHmmssSSSZ format. Each report also records the exact project-relative paths of its validated artifacts. Concurrent validation runs save separate reports without overwriting earlier results.

The teach-me-testing skill validates its skill definition. Its reports use workflow-validation/teach-me-testing-validation-{run_timestamp}.md under {test_artifacts} and follow the same no-overwrite rule.


Generated tests and CI jobs can use environment variables for URLs and credentials.

Playwright:

.env
BASE_URL=https://todomvc.com/examples/react/dist/
API_BASE_URL=https://api.example.com
TEST_USER_EMAIL=test@example.com
TEST_USER_PASSWORD=password123

Cypress:

Terminal window
# .env (exported as shell variables; Cypress reads variables prefixed with CYPRESS_)
CYPRESS_BASE_URL=https://example.com
CYPRESS_API_URL=https://api.example.com

Or keep Cypress values in cypress.env.json, which Cypress loads itself:

{
"API_URL": "https://api.example.com",
"TEST_USER_EMAIL": "test@example.com",
"TEST_USER_PASSWORD": "replace-me"
}

Framework setup writes .env.example; copy it to .env and fill in real values. A .env file helps only when something loads it: your shell (set -a; source .env; set +a), your runner’s config, or CI.

Split them per environment (.env.development, .env.staging, .env.production) and keep the production file pointed at read-only tests only. Ignore every file that holds real credentials, and commit only a sanitized example:

.env*
!.env.example
cypress.env.json

CI/CD: set the same names as secrets in your CI platform.

.github/workflows/test.yml
env:
BASE_URL: ${{ secrets.STAGING_URL }}
API_KEY: ${{ secrets.API_KEY }}
TEST_USER_EMAIL: ${{ secrets.TEST_USER }}

Ask the bmad skill for bmad setup tea. It reports the module’s state and shows every answer with the file it lives in. From a shell:

Terminal window
# 1. Print the TEA answers bmad setup wrote
sed -n '/^\[modules.tea\]/,/^\[/p' _bmad/config.toml
# 2. Print the merged config a skill sees, all three layers applied
uv run _bmad/scripts/resolve_config.py --project-root . --key core --key modules.tea
# 3. Confirm playwright-utils is installed when tea_use_playwright_utils is "true"
npm ls @seontechnologies/playwright-utils

A key you set that does not appear in step 2 is misspelled or in the wrong table. Compare it against the key list on this page.

For anything that stays broken, see the Troubleshooting guide.