bmad-method 6.11.1-next.8 → 6.12.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/AGENTS.md +12 -0
- package/CLAUDE.md +1 -0
- package/README.md +13 -19
- package/README_CN.md +0 -10
- package/README_KR.md +90 -0
- package/README_VN.md +0 -10
- package/greptile.json +52 -0
- package/package.json +6 -5
- package/src/bmm-skills/agents/bmad-agent-analyst/SKILL.md +1 -1
- package/src/bmm-skills/agents/bmad-agent-analyst/customize.toml +1 -3
- package/src/bmm-skills/agents/bmad-agent-architect/SKILL.md +1 -1
- package/src/bmm-skills/agents/bmad-agent-architect/customize.toml +1 -3
- package/src/bmm-skills/agents/bmad-agent-dev/SKILL.md +1 -1
- package/src/bmm-skills/agents/bmad-agent-dev/customize.toml +1 -3
- package/src/bmm-skills/agents/bmad-agent-pm/SKILL.md +1 -1
- package/src/bmm-skills/agents/bmad-agent-pm/customize.toml +1 -3
- package/src/bmm-skills/agents/bmad-agent-ux-designer/SKILL.md +1 -1
- package/src/bmm-skills/agents/bmad-agent-ux-designer/customize.toml +1 -3
- package/src/bmm-skills/module-help.csv +2 -2
- package/src/bmm-skills/plan/bmad-architecture/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-architecture/customize.toml +5 -6
- package/src/bmm-skills/plan/bmad-create-epics-and-stories/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-create-epics-and-stories/customize.toml +1 -3
- package/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-04-final-validation.md +1 -1
- package/src/bmm-skills/plan/bmad-prd/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-prd/customize.toml +5 -6
- package/src/bmm-skills/plan/bmad-prfaq/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-prfaq/customize.toml +1 -3
- package/src/bmm-skills/plan/bmad-prfaq/references/verdict.md +1 -1
- package/src/bmm-skills/plan/bmad-product-brief/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-product-brief/customize.toml +5 -6
- package/src/bmm-skills/plan/bmad-project-context/SKILL.md +7 -6
- package/src/bmm-skills/plan/bmad-project-context/references/best-practices.md +2 -2
- package/src/bmm-skills/plan/bmad-spec/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-spec/customize.toml +5 -5
- package/src/bmm-skills/plan/bmad-sprint-planning/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-sprint-planning/customize.toml +1 -3
- package/src/bmm-skills/plan/bmad-sprint-planning/scripts/__pycache__/sprint_plan.cpython-311.pyc +0 -0
- package/src/bmm-skills/plan/bmad-sprint-planning/scripts/tests/__pycache__/test_sprint_plan.cpython-311-pytest-9.1.1.pyc +0 -0
- package/src/bmm-skills/plan/bmad-ux/SKILL.md +1 -1
- package/src/bmm-skills/plan/bmad-ux/customize.toml +1 -3
- package/src/bmm-skills/ship/bmad-build/SKILL.md +1 -1
- package/src/bmm-skills/ship/bmad-build/customize.toml +21 -33
- package/src/bmm-skills/ship/bmad-build/references/claims-check.md +14 -0
- package/src/bmm-skills/ship/bmad-build/review-prompts/edge-case-hunter.md +31 -7
- package/src/bmm-skills/ship/bmad-build/review-prompts/verification-gap.md +4 -4
- package/src/bmm-skills/ship/bmad-build/spec-template.md +26 -4
- package/src/bmm-skills/ship/bmad-build/step-01-clarify-and-route.md +21 -26
- package/src/bmm-skills/ship/bmad-build/step-02-plan.md +31 -16
- package/src/bmm-skills/ship/bmad-build/step-03-implement.md +5 -3
- package/src/bmm-skills/ship/bmad-build/step-04-review.md +49 -19
- package/src/bmm-skills/ship/bmad-build/step-05-present.md +9 -41
- package/src/bmm-skills/ship/bmad-build/step-oneshot.md +60 -29
- package/src/bmm-skills/ship/bmad-build/sync-sprint-status.md +5 -19
- package/src/bmm-skills/ship/bmad-build-auto/customize.toml +17 -19
- package/src/bmm-skills/ship/bmad-build-auto/references/claims-check.md +14 -0
- package/src/bmm-skills/ship/bmad-build-auto/review-prompts/edge-case-hunter.md +31 -7
- package/src/bmm-skills/ship/bmad-build-auto/review-prompts/verification-gap.md +4 -4
- package/src/bmm-skills/ship/bmad-build-auto/spec-template.md +4 -7
- package/src/bmm-skills/ship/bmad-build-auto/step-01-clarify-and-route.md +3 -2
- package/src/bmm-skills/ship/bmad-build-auto/step-03-implement.md +5 -1
- package/src/bmm-skills/ship/bmad-build-auto/step-04-review.md +58 -38
- package/src/bmm-skills/ship/bmad-build-auto/workflow.md +1 -1
- package/src/bmm-skills/ship/bmad-code-review/SKILL.md +1 -1
- package/src/bmm-skills/ship/bmad-code-review/customize.toml +15 -18
- package/src/bmm-skills/ship/bmad-code-review/references/claims-check.md +14 -0
- package/src/bmm-skills/ship/bmad-code-review/review-prompts/edge-case-hunter.md +31 -7
- package/src/bmm-skills/ship/bmad-code-review/review-prompts/verification-gap.md +4 -4
- package/src/bmm-skills/ship/bmad-code-review/steps/step-01-gather-context.md +30 -23
- package/src/bmm-skills/ship/bmad-code-review/steps/step-02-review.md +3 -3
- package/src/bmm-skills/ship/bmad-code-review/steps/step-03-triage.md +25 -21
- package/src/bmm-skills/ship/bmad-code-review/steps/step-04-present.md +20 -18
- package/src/bmm-skills/ship/bmad-correct-course/SKILL.md +13 -5
- package/src/bmm-skills/ship/bmad-correct-course/customize.toml +1 -3
- package/src/bmm-skills/ship/bmad-qa-generate-e2e-tests/SKILL.md +2 -2
- package/src/bmm-skills/ship/bmad-qa-generate-e2e-tests/customize.toml +1 -3
- package/src/bmm-skills/ship/bmad-retrospective/SKILL.md +1 -1
- package/src/bmm-skills/ship/bmad-retrospective/customize.toml +1 -3
- package/src/bmm-skills/ship/bmad-retrospective/scripts/__pycache__/sprint_status.cpython-311.pyc +0 -0
- package/src/bmm-skills/ship/bmad-retrospective/scripts/tests/__pycache__/test_git_evidence.cpython-311-pytest-9.1.1.pyc +0 -0
- package/src/bmm-skills/ship/bmad-retrospective/scripts/tests/__pycache__/test_sprint_status.cpython-311-pytest-9.1.1.pyc +0 -0
- package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/SKILL.md +4 -4
- package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/customize.toml +2 -4
- package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/step-05-wrapup.md +1 -1
- package/src/bmm-skills/v6-shims/README.md +1 -0
- package/src/bmm-skills/v6-shims/bmad-checkpoint-preview/SKILL.md +21 -0
- package/src/bmm-skills/v6-shims/bmad-create-architecture/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-create-architecture/customize.toml +1 -3
- package/src/bmm-skills/v6-shims/bmad-create-prd/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-create-prd/customize.toml +1 -3
- package/src/bmm-skills/v6-shims/bmad-create-story/SKILL.md +3 -3
- package/src/bmm-skills/v6-shims/bmad-create-story/customize.toml +1 -3
- package/src/bmm-skills/v6-shims/bmad-dev-story/SKILL.md +2 -2
- package/src/bmm-skills/v6-shims/bmad-dev-story/customize.toml +1 -6
- package/src/bmm-skills/v6-shims/bmad-domain-research/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-edit-prd/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-edit-prd/customize.toml +1 -3
- package/src/bmm-skills/v6-shims/bmad-market-research/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-sprint-status/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-sprint-status/customize.toml +1 -3
- package/src/bmm-skills/v6-shims/bmad-technical-research/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-validate-prd/SKILL.md +1 -1
- package/src/bmm-skills/v6-shims/bmad-validate-prd/customize.toml +1 -3
- package/src/core-skills/bmad-advanced-elicitation/SKILL.md +22 -23
- package/src/core-skills/bmad-brainstorming/SKILL.md +1 -1
- package/src/core-skills/bmad-brainstorming/customize.toml +5 -6
- package/src/core-skills/bmad-brainstorming/scripts/brain.py +19 -0
- package/src/core-skills/bmad-brainstorming/scripts/tests/test_brain.py +50 -0
- package/src/core-skills/bmad-customize/SKILL.md +1 -1
- package/src/core-skills/bmad-deep-recon/SKILL.md +1 -1
- package/src/core-skills/bmad-forge-idea/SKILL.md +1 -1
- package/src/core-skills/bmad-forge-idea/customize.toml +5 -6
- package/src/core-skills/bmad-forge-idea/scripts/resolve_personas.py +3 -1
- package/src/core-skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py +22 -0
- package/src/core-skills/bmad-help/SKILL.md +1 -1
- package/src/core-skills/bmad-party-mode/SKILL.md +1 -1
- package/src/core-skills/bmad-party-mode/customize.toml +4 -4
- package/src/core-skills/bmad-party-mode/references/create-party.md +1 -1
- package/src/core-skills/bmad-party-mode/scripts/resolve_party.py +3 -1
- package/src/core-skills/bmad-party-mode/scripts/tests/test_resolve_party.py +22 -0
- package/src/core-skills/bmad-review/SKILL.md +5 -4
- package/src/core-skills/bmad-review/customize.toml +1 -1
- package/src/core-skills/bmad-review/references/lens-edge-case-hunter.md +18 -0
- package/src/core-skills/module-help.csv +1 -1
- package/src/scripts/__pycache__/config_utils.cpython-311.pyc +0 -0
- package/src/scripts/resolve_config.py +9 -1
- package/src/scripts/resolve_customization.py +72 -7
- package/src/scripts/tests/__pycache__/test_config_utils.cpython-311.pyc +0 -0
- package/src/scripts/tests/__pycache__/test_resolve_config.cpython-311.pyc +0 -0
- package/src/scripts/tests/__pycache__/test_resolve_customization.cpython-311.pyc +0 -0
- package/src/scripts/tests/test_resolve_config.py +28 -0
- package/src/scripts/tests/test_resolve_customization.py +102 -0
- package/tools/installer/core/installer.js +33 -1
- package/tools/installer/core/shim-policy.js +75 -7
- package/tools/installer/ide/platform-codes.yaml +13 -0
- package/tools/installer/prompts.js +15 -2
- package/tools/installer/ui.js +28 -8
- package/tools/skill-validator.md +85 -151
- package/tools/tests/__pycache__/test_validate_skills.cpython-311.pyc +0 -0
- package/tools/tests/fixtures/validate-skills/bmad/SKILL.md +8 -0
- package/tools/tests/fixtures/validate-skills/deprecated-shim/SKILL.md +9 -0
- package/tools/tests/fixtures/validate-skills/missing-trigger/SKILL.md +9 -0
- package/tools/tests/fixtures/validate-skills/with-trigger/SKILL.md +8 -0
- package/tools/tests/test_validate_skills.py +476 -0
- package/tools/validate-published-implementation-model.mjs +0 -9
- package/tools/validate_skills.py +698 -0
- package/tools/validate-skills.js +0 -735
- /package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/generate-trail.md +0 -0
- /package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/step-01-orientation.md +0 -0
- /package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/step-02-walkthrough.md +0 -0
- /package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/step-03-detail-pass.md +0 -0
- /package/src/bmm-skills/ship/{bmad-checkpoint-preview → bmad-walkthrough}/step-04-testing.md +0 -0
|
@@ -25,6 +25,6 @@ HALT — do not proceed until the user makes their choice.
|
|
|
25
25
|
|
|
26
26
|
## On Complete
|
|
27
27
|
|
|
28
|
-
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
|
|
28
|
+
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow.on_complete`
|
|
29
29
|
|
|
30
30
|
If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
|
|
@@ -18,6 +18,7 @@ stated intent and pre-resolved customization fields so the target skips its own
|
|
|
18
18
|
| `bmad-domain-research` | `bmad-deep-recon` (domain type) |
|
|
19
19
|
| `bmad-technical-research` | `bmad-deep-recon` (technical type) |
|
|
20
20
|
| `bmad-sprint-status` | `bmad-sprint-planning` (status view) |
|
|
21
|
+
| `bmad-checkpoint-preview` | `bmad-walkthrough` |
|
|
21
22
|
|
|
22
23
|
Enterprise users may still depend on these IDs, so they ship by default. Removal rides the
|
|
23
24
|
v7 cut — never a 6.x minor.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bmad-checkpoint-preview
|
|
3
|
+
description: "Deprecated: forwards to bmad-walkthrough. Do not use unless invoked by name"
|
|
4
|
+
metadata:
|
|
5
|
+
lifecycle: shim
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Deprecated Walkthrough Alias
|
|
9
|
+
|
|
10
|
+
## On Activation
|
|
11
|
+
|
|
12
|
+
1. Check whether either legacy customization file exists:
|
|
13
|
+
- `{project-root}/_bmad/custom/bmad-checkpoint-preview.toml`
|
|
14
|
+
- `{project-root}/_bmad/custom/bmad-checkpoint-preview.user.toml`
|
|
15
|
+
2. If neither legacy file exists, output exactly `bmad-checkpoint-preview is deprecated. Redirecting to bmad-walkthrough. Please use bmad-walkthrough in the future.`, invoke `bmad-walkthrough` exactly once with the user's original input verbatim, then execute no further steps in this shim.
|
|
16
|
+
3. For every legacy file that exists, use its matching new filename:
|
|
17
|
+
- `{project-root}/_bmad/custom/bmad-checkpoint-preview.toml` becomes `{project-root}/_bmad/custom/bmad-walkthrough.toml`.
|
|
18
|
+
- `{project-root}/_bmad/custom/bmad-checkpoint-preview.user.toml` becomes `{project-root}/_bmad/custom/bmad-walkthrough.user.toml`.
|
|
19
|
+
4. If the matching new file does not exist, tell the user that the customization file uses the deprecated name and offer to rename it. Rename it only after explicit approval. If approval is declined or unavailable, or the rename fails, HALT and do not invoke any skill.
|
|
20
|
+
5. If the matching new file already exists, do not overwrite it. Read both files, explain their differences, and propose the exact content for the new file. Resolve conflicting values with the user. Only after the user explicitly approves that content, save and verify the new file, then remove the legacy file. If approval is declined or unavailable, or any operation fails, HALT and do not invoke any skill.
|
|
21
|
+
6. After every detected legacy file has been migrated successfully and no legacy file remains, output exactly `bmad-checkpoint-preview is deprecated. Redirecting to bmad-walkthrough. Please use bmad-walkthrough in the future.`, invoke `bmad-walkthrough` exactly once with the user's original input verbatim, then execute no further steps in this shim.
|
|
@@ -11,7 +11,7 @@ This skill was consolidated into `bmad-architecture`. It is retained as a thin c
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-architecture.toml` and `bmad-create-architecture.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-architecture.toml` and `bmad-create-architecture.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
|
|
16
16
|
2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
|
|
17
17
|
|
|
@@ -30,9 +30,7 @@ activation_steps_append = []
|
|
|
30
30
|
# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
|
|
31
31
|
# (glob patterns are supported; the file's contents are loaded and treated as facts).
|
|
32
32
|
|
|
33
|
-
persistent_facts = [
|
|
34
|
-
"file:{project-root}/**/project-context.md",
|
|
35
|
-
]
|
|
33
|
+
persistent_facts = []
|
|
36
34
|
|
|
37
35
|
# Scalar: executed when the workflow reaches Step 8 (Architecture Completion & Handoff),
|
|
38
36
|
# after the architecture document frontmatter is updated and next-steps guidance is given.
|
|
@@ -11,7 +11,7 @@ This skill was consolidated into `bmad-prd`. It is retained as a thin compatibil
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-prd.toml` and `bmad-create-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-prd.toml` and `bmad-create-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
|
|
16
16
|
2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
|
|
17
17
|
|
|
@@ -30,9 +30,7 @@ activation_steps_append = []
|
|
|
30
30
|
# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
|
|
31
31
|
# (glob patterns are supported; the file's contents are loaded and treated as facts).
|
|
32
32
|
|
|
33
|
-
persistent_facts = [
|
|
34
|
-
"file:{project-root}/**/project-context.md",
|
|
35
|
-
]
|
|
33
|
+
persistent_facts = []
|
|
36
34
|
|
|
37
35
|
# Scalar: executed when the workflow reaches Step 12 (Workflow Completion),
|
|
38
36
|
# after the PRD is finalized and workflow status is updated. Override wins.
|
|
@@ -32,7 +32,7 @@ If you need an explicit user instruction to run them, ask once now for the whole
|
|
|
32
32
|
|
|
33
33
|
### Step 1: Resolve the Workflow Block
|
|
34
34
|
|
|
35
|
-
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
|
|
35
|
+
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`
|
|
36
36
|
|
|
37
37
|
**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
|
|
38
38
|
|
|
@@ -257,7 +257,7 @@ Activation is complete. If `activation_steps_prepend` or `activation_steps_appen
|
|
|
257
257
|
|
|
258
258
|
<!-- Load all available content through discovery protocol -->
|
|
259
259
|
<action>Read fully and follow `./discover-inputs.md` to load all input files</action>
|
|
260
|
-
<note>Available content: {epics_content}, {prd_content}, {architecture_content}, {ux_content}, plus
|
|
260
|
+
<note>Available content: {epics_content}, {prd_content}, {architecture_content}, {ux_content}, plus any facts loaded during activation via `persistent_facts` (empty unless the user opted in).</note>
|
|
261
261
|
|
|
262
262
|
<!-- Analyze epics file for story foundation -->
|
|
263
263
|
<action>From {epics_content}, extract Epic {{epic_num}} complete context:</action> **EPIC ANALYSIS:** - Epic
|
|
@@ -430,7 +430,7 @@ Activation is complete. If `activation_steps_prepend` or `activation_steps_appen
|
|
|
430
430
|
|
|
431
431
|
**The developer now has everything needed for flawless implementation!**
|
|
432
432
|
</output>
|
|
433
|
-
<action>Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.</action>
|
|
433
|
+
<action>Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.</action>
|
|
434
434
|
</step>
|
|
435
435
|
|
|
436
436
|
</workflow>
|
|
@@ -30,9 +30,7 @@ activation_steps_append = []
|
|
|
30
30
|
# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
|
|
31
31
|
# (glob patterns are supported; the file's contents are loaded and treated as facts).
|
|
32
32
|
|
|
33
|
-
persistent_facts = [
|
|
34
|
-
"file:{project-root}/**/project-context.md",
|
|
35
|
-
]
|
|
33
|
+
persistent_facts = []
|
|
36
34
|
|
|
37
35
|
# Scalar: executed when the workflow reaches Step 6 (Update sprint status and finalize),
|
|
38
36
|
# after the story file is saved and sprint-status.yaml is updated. Override wins.
|
|
@@ -29,7 +29,7 @@ metadata:
|
|
|
29
29
|
|
|
30
30
|
### Step 1: Resolve the Workflow Block
|
|
31
31
|
|
|
32
|
-
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
|
|
32
|
+
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`
|
|
33
33
|
|
|
34
34
|
**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
|
|
35
35
|
|
|
@@ -498,7 +498,7 @@ Activation is complete. If `activation_steps_prepend` or `activation_steps_appen
|
|
|
498
498
|
<action>Suggest checking {sprint_status} to see project progress</action>
|
|
499
499
|
</check>
|
|
500
500
|
<action>Remain flexible - allow user to choose their own path or ask for other assistance</action>
|
|
501
|
-
<action>Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.</action>
|
|
501
|
+
<action>Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.</action>
|
|
502
502
|
</step>
|
|
503
503
|
|
|
504
504
|
</workflow>
|
|
@@ -30,12 +30,7 @@ activation_steps_append = []
|
|
|
30
30
|
# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
|
|
31
31
|
# (glob patterns are supported; the file's contents are loaded and treated as facts).
|
|
32
32
|
|
|
33
|
-
persistent_facts = [
|
|
34
|
-
"file:{project-root}/**/project-context.md",
|
|
35
|
-
"Never add epic or story references as inline code comments (e.g. # Epic: X, # Story: PROJ-42).",
|
|
36
|
-
"Code comments explain why, not what — no AI workflow metadata, planning refs, or story tracking in source code.",
|
|
37
|
-
"Generated code must be production-ready: clean, minimal, and free of AI-generated noise.",
|
|
38
|
-
]
|
|
33
|
+
persistent_facts = []
|
|
39
34
|
|
|
40
35
|
# Scalar: executed when the workflow reaches its final step,
|
|
41
36
|
# after the story implementation is complete and status is updated. Override wins.
|
|
@@ -11,6 +11,6 @@ This skill was consolidated into `bmad-deep-recon`. It is retained as a thin com
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-domain-research.toml` and `bmad-domain-research.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-domain-research.toml` and `bmad-domain-research.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
2. Emit a deprecation notice to the user (in their configured communication language): `bmad-domain-research` is deprecated and forwards to `bmad-deep-recon` with the domain type. To silence this notice and access the full new surface (draft/process/run modes, research types, verification levels, HTML briefing, handoffs), migrate `_bmad/custom/bmad-domain-research.toml` to `_bmad/custom/bmad-deep-recon.toml` and invoke `bmad-deep-recon` directly.
|
|
16
16
|
3. Invoke `bmad-deep-recon` with: **research type** `domain` (skip its type inference), the four legacy fields above as pre-resolved values, and the user's original input verbatim. `bmad-deep-recon` takes the workflow from here — do not execute any further steps in this shim.
|
|
@@ -11,7 +11,7 @@ This skill was consolidated into `bmad-prd`. It is retained as a thin compatibil
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-edit-prd.toml` and `bmad-edit-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-edit-prd.toml` and `bmad-edit-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
|
|
16
16
|
2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
|
|
17
17
|
|
|
@@ -30,9 +30,7 @@ activation_steps_append = []
|
|
|
30
30
|
# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
|
|
31
31
|
# (glob patterns are supported; the file's contents are loaded and treated as facts).
|
|
32
32
|
|
|
33
|
-
persistent_facts = [
|
|
34
|
-
"file:{project-root}/**/project-context.md",
|
|
35
|
-
]
|
|
33
|
+
persistent_facts = []
|
|
36
34
|
|
|
37
35
|
# Scalar: executed when the workflow reaches Step E-4 (Complete & Validate) and the
|
|
38
36
|
# user exits via [S] Summary or [X] Exit — not on [V] Validate (which chains to
|
|
@@ -11,6 +11,6 @@ This skill was consolidated into `bmad-deep-recon`. It is retained as a thin com
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-market-research.toml` and `bmad-market-research.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-market-research.toml` and `bmad-market-research.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
2. Emit a deprecation notice to the user (in their configured communication language): `bmad-market-research` is deprecated and forwards to `bmad-deep-recon` with the market type. To silence this notice and access the full new surface (draft/process/run modes, research types, verification levels, HTML briefing, handoffs), migrate `_bmad/custom/bmad-market-research.toml` to `_bmad/custom/bmad-deep-recon.toml` and invoke `bmad-deep-recon` directly.
|
|
16
16
|
3. Invoke `bmad-deep-recon` with: **research type** `market` (skip its type inference), the four legacy fields above as pre-resolved values, and the user's original input verbatim. `bmad-deep-recon` takes the workflow from here — do not execute any further steps in this shim.
|
|
@@ -11,7 +11,7 @@ This skill was consolidated into `bmad-sprint-planning`, which now owns the whol
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-sprint-status.toml` and `bmad-sprint-status.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-sprint-status.toml` and `bmad-sprint-status.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
|
|
16
16
|
2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
|
|
17
17
|
|
|
@@ -30,9 +30,7 @@ activation_steps_append = []
|
|
|
30
30
|
# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
|
|
31
31
|
# (glob patterns are supported; the file's contents are loaded and treated as facts).
|
|
32
32
|
|
|
33
|
-
persistent_facts = [
|
|
34
|
-
"file:{project-root}/**/project-context.md",
|
|
35
|
-
]
|
|
33
|
+
persistent_facts = []
|
|
36
34
|
|
|
37
35
|
# Scalar: executed when the workflow reaches its final step,
|
|
38
36
|
# after sprint status is summarized and risks are surfaced. Override wins.
|
|
@@ -11,6 +11,6 @@ This skill was consolidated into `bmad-deep-recon`. It is retained as a thin com
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-technical-research.toml` and `bmad-technical-research.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-technical-research.toml` and `bmad-technical-research.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
2. Emit a deprecation notice to the user (in their configured communication language): `bmad-technical-research` is deprecated and forwards to `bmad-deep-recon` with the technical type. To silence this notice and access the full new surface (draft/process/run modes, research types, verification levels, HTML briefing, handoffs), migrate `_bmad/custom/bmad-technical-research.toml` to `_bmad/custom/bmad-deep-recon.toml` and invoke `bmad-deep-recon` directly.
|
|
16
16
|
3. Invoke `bmad-deep-recon` with: **research type** `technical` (skip its type inference), the four legacy fields above as pre-resolved values, and the user's original input verbatim. `bmad-deep-recon` takes the workflow from here — do not execute any further steps in this shim.
|
|
@@ -11,7 +11,7 @@ This skill was consolidated into `bmad-prd`. It is retained as a thin compatibil
|
|
|
11
11
|
|
|
12
12
|
## On Activation
|
|
13
13
|
|
|
14
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-validate-prd.toml` and `bmad-validate-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
14
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-validate-prd.toml` and `bmad-validate-prd.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
|
15
15
|
|
|
16
16
|
2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
|
|
17
17
|
|
|
@@ -30,9 +30,7 @@ activation_steps_append = []
|
|
|
30
30
|
# - a file reference prefixed with `file:`, e.g. "file:{project-root}/docs/standards.md"
|
|
31
31
|
# (glob patterns are supported; the file's contents are loaded and treated as facts).
|
|
32
32
|
|
|
33
|
-
persistent_facts = [
|
|
34
|
-
"file:{project-root}/**/project-context.md",
|
|
35
|
-
]
|
|
33
|
+
persistent_facts = []
|
|
36
34
|
|
|
37
35
|
# Scalar: executed when the workflow reaches Step 13 (Validation Report Complete) and
|
|
38
36
|
# the user exits via [X] Exit — not on [E] Use Edit Workflow (which chains to
|
|
@@ -14,12 +14,12 @@ You are BMad's shared refinement checkpoint: other skills invoke you at natural
|
|
|
14
14
|
|
|
15
15
|
## On Activation
|
|
16
16
|
|
|
17
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults.
|
|
17
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults.
|
|
18
18
|
2. Hold every `{workflow.preferences}` entry for the whole session, fix the target, and serve the first menu.
|
|
19
19
|
|
|
20
20
|
## Serving the Catalog
|
|
21
21
|
|
|
22
|
-
`scripts/pick_methods.py` serves the method catalog (num, category, method_name, description, output_pattern) so it never enters context whole — the one exception is
|
|
22
|
+
`scripts/pick_methods.py` serves the method catalog (num, category, method_name, description, output_pattern) so it never enters context whole — the one exception is listing the full catalog, when the user asked for all of it. Invoke as:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
uv run {skill-root}/scripts/pick_methods.py --file {workflow.methods_file} <command>
|
|
@@ -28,7 +28,7 @@ uv run {skill-root}/scripts/pick_methods.py --file {workflow.methods_file} <comm
|
|
|
28
28
|
If `{workflow.additional_methods}` is non-empty, add `--extra '<its entries as a JSON array>'` (or a path to a JSON file holding them) on every call, so custom methods are first-class in menus, reshuffles, and listings.
|
|
29
29
|
|
|
30
30
|
- `categories` — category names + counts, the cheap map.
|
|
31
|
-
- `list --category <cat> [--category <cat>]` — the index for chosen categories; `--all` dumps the whole catalog, only
|
|
31
|
+
- `list --category <cat> [--category <cat>]` — the index for chosen categories; `--all` dumps the whole catalog, only when listing all.
|
|
32
32
|
- `show <name-or-num> [...]` — full rows by name or num.
|
|
33
33
|
- `random -n 5 --spread [--exclude <name>]...` — a category-diverse random draw.
|
|
34
34
|
|
|
@@ -36,30 +36,29 @@ If `{workflow.additional_methods}` is non-empty, add `--extra '<its entries as a
|
|
|
36
36
|
|
|
37
37
|
## The Menu
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
3. [Method Name]
|
|
46
|
-
4. [Method Name]
|
|
47
|
-
5. [Method Name]
|
|
48
|
-
r. Reshuffle the list with 5 new options
|
|
49
|
-
a. List all methods with descriptions
|
|
50
|
-
x. Proceed / No Further Actions
|
|
51
|
-
```
|
|
39
|
+
HALT and give the user a choice:
|
|
40
|
+
|
|
41
|
+
- The five offered methods, listed by name. The user may pick one or several.
|
|
42
|
+
- **Reshuffle** — replace the list with five new options.
|
|
43
|
+
- **List all** — show the full catalog with descriptions.
|
|
44
|
+
- **Proceed** — no further elicitation.
|
|
52
45
|
|
|
53
|
-
This menu is the interface other skills and their users rely on — keep its options and behavior stable. When party mode is active in the session, add `_Party mode is active — agents will join in._` under the heading.
|
|
46
|
+
This menu is the interface other skills and their users rely on — keep its options and behavior stable. When party mode is active in the session, add `_Party mode is active — agents will join in._` under the heading.
|
|
54
47
|
|
|
55
|
-
-
|
|
56
|
-
- **
|
|
57
|
-
- **
|
|
58
|
-
- **
|
|
59
|
-
-
|
|
48
|
+
- If the user picks methods: run them (several: in sequence), then offer the menu again.
|
|
49
|
+
- If the user chooses **Reshuffle**: reshuffle as above and offer the menu again.
|
|
50
|
+
- If the user chooses **List all**: show the full catalog (`list --all`) as a compact table; a pick by name or number runs like a method choice.
|
|
51
|
+
- If the user chooses **Proceed**: done. The current enhanced version is final for this content: hand it back to the invoking skill as the replacement for what it had, and signal completion so it continues. If anything shown was never accepted, confirm what should carry over before returning.
|
|
52
|
+
- Any other reply is direction: apply it to the target and offer the menu again.
|
|
60
53
|
|
|
61
54
|
## Running a Method
|
|
62
55
|
|
|
63
|
-
Use the method's description as its intent and its output_pattern as a flexible flow guide; scale depth to the target — a paragraph gets a light pass, an architecture decision gets the full treatment. Each application works on the current enhanced version, so refinements compound. Show what the method revealed and the changes it proposes, then
|
|
56
|
+
Use the method's description as its intent and its output_pattern as a flexible flow guide; scale depth to the target — a paragraph gets a light pass, an architecture decision gets the full treatment. Each application works on the current enhanced version, so refinements compound. Show what the method revealed and the changes it proposes, then HALT and give the user a choice:
|
|
57
|
+
|
|
58
|
+
- **Apply** — accept the proposed changes.
|
|
59
|
+
- **Reject** — drop the proposal entirely.
|
|
60
|
+
- Or give different direction.
|
|
61
|
+
|
|
62
|
+
Never change the work unless the user accepts the proposal. If they reject it, drop the proposal entirely. Any other reply is instruction to follow.
|
|
64
63
|
|
|
65
64
|
When a method casts personas (round tables, panels, debates), reuse party members already in the session if party mode is active; otherwise resolve installed agents on demand via `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root} --key agents` (a four-layer merge of `_bmad/config.toml`, `config.user.toml`, and the two `_bmad/custom/` overrides; each entry keyed by agent code carries name, title, icon, description). If neither yields a fit, invent named viewpoints suited to the content.
|
|
@@ -18,7 +18,7 @@ The session runs in one of three stances, chosen by the user — set explicitly
|
|
|
18
18
|
|
|
19
19
|
## On Activation
|
|
20
20
|
|
|
21
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, use a subagent to read `{skill-root}/customize.toml` directly with defaults.
|
|
21
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. On failure, use a subagent to read `{skill-root}/customize.toml` directly with defaults.
|
|
22
22
|
2. Run each `{workflow.activation_steps_prepend}` entry. Treat each `{workflow.persistent_facts}` entry as foundational context (`file:`-prefixed entries are paths/globs under `{project-root}` — load their contents; others are facts verbatim).
|
|
23
23
|
3. Resolve central config: `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root} --key core` (merges `_bmad/config.toml`, `_bmad/config.user.toml`, and the `_bmad/custom/` overrides); from the merged JSON resolve `{user_name}`, `{communication_language}`, `{document_output_language}`, `{output_folder}`, `{project_name}`; `{date}` is today. On failure or missing values → neutral defaults; never block.
|
|
24
24
|
4. **If launched headless** (a machine signal, not a human asking for output — `references/headless.md` lists them): load `references/headless.md` and follow it for the whole run; never load it otherwise. Outside headless, you generate ideas yourself only in autonomous mode (`references/mode-autonomous.md`) — never in facilitator or partner mode.
|
|
@@ -22,12 +22,11 @@ activation_steps_append = []
|
|
|
22
22
|
# Persistent facts the facilitator keeps in mind for the whole session
|
|
23
23
|
# (domain constraints, house rules, stylistic guardrails). Each entry is a
|
|
24
24
|
# literal sentence, a skill prefixed with `skill:`, or a `file:`-prefixed
|
|
25
|
-
# path/glob whose contents are loaded as facts.
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
]
|
|
25
|
+
# path/glob whose contents are loaded as facts. Empty by default — repo-wide context
|
|
26
|
+
# belongs in AGENTS.md (see bmad-project-context), which every skill already sees. Use
|
|
27
|
+
# this for context only the facilitator needs, loaded on demand rather than carried as
|
|
28
|
+
# constant memory (e.g. `file:{project-root}/**/project-context.md` if you keep one).
|
|
29
|
+
persistent_facts = []
|
|
31
30
|
|
|
32
31
|
# The technique library loaded on demand during the session. Swap the path in
|
|
33
32
|
# team/user TOML to ship a different or extended catalog of creative methods.
|
|
@@ -692,7 +692,26 @@ def html_doc(rows: list[dict]) -> str:
|
|
|
692
692
|
)
|
|
693
693
|
|
|
694
694
|
|
|
695
|
+
def pin_utf8(stream):
|
|
696
|
+
"""Pin a console stream to UTF-8, keeping its own error handler.
|
|
697
|
+
|
|
698
|
+
`--extra` technique text and the technique names echoed to stderr are
|
|
699
|
+
arbitrary user input, so either stream can carry a character the platform
|
|
700
|
+
default cannot encode (cp1252 on Windows) and print() then raises.
|
|
701
|
+
|
|
702
|
+
errors= is passed through deliberately: reconfigure(encoding=...) alone
|
|
703
|
+
resets the handler to "strict", which would silently downgrade stderr's
|
|
704
|
+
POSIX default of "backslashreplace" and turn a diagnostic about an
|
|
705
|
+
undecodable path into a traceback.
|
|
706
|
+
"""
|
|
707
|
+
reconfigure = getattr(stream, "reconfigure", None)
|
|
708
|
+
if reconfigure is not None:
|
|
709
|
+
reconfigure(encoding="utf-8", errors=getattr(stream, "errors", None) or "strict")
|
|
710
|
+
|
|
711
|
+
|
|
695
712
|
def main(argv: list[str] | None = None) -> int:
|
|
713
|
+
pin_utf8(sys.stdout)
|
|
714
|
+
pin_utf8(sys.stderr)
|
|
696
715
|
p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
697
716
|
p.add_argument("--file", type=Path, default=DEFAULT_FILE, help="technique CSV (default: sibling assets/brain-methods.csv)")
|
|
698
717
|
p.add_argument("--extra", type=Path, help="JSON overlay of additional techniques (customize.toml additional_techniques), merged into every command")
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# dependencies = ["pytest>=8.0"]
|
|
4
4
|
# ///
|
|
5
5
|
"""Tests for brain.py. Run: uv run -m pytest scripts/tests/test_brain.py"""
|
|
6
|
+
import io
|
|
6
7
|
import json
|
|
7
8
|
import sys
|
|
8
9
|
from pathlib import Path
|
|
@@ -227,6 +228,55 @@ def test_unknown_category_style_uses_fallback_glyph():
|
|
|
227
228
|
assert glyph == brain._FALLBACK_GLYPH
|
|
228
229
|
|
|
229
230
|
|
|
231
|
+
# --- console encoding (Windows cp1252) ----------------------------------
|
|
232
|
+
|
|
233
|
+
def _cp1252_stream():
|
|
234
|
+
"""A text stream that behaves like a Windows console: cp1252, strict."""
|
|
235
|
+
return io.TextIOWrapper(io.BytesIO(), encoding="cp1252", errors="strict", write_through=True)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def test_extra_technique_prints_when_stdout_encoding_is_cp1252(lib, tmp_path, monkeypatch):
|
|
239
|
+
# --extra text is arbitrary user input; the shipped catalog happens to be
|
|
240
|
+
# cp1252-safe, an overlay is not. Unpinned stdout raises UnicodeEncodeError
|
|
241
|
+
# and the command exits having printed nothing.
|
|
242
|
+
overlay = tmp_path / "extra.json"
|
|
243
|
+
overlay.write_text(
|
|
244
|
+
json.dumps([{"category": "wild", "technique_name": "Fikir Fırtınası 🌪", "description": "Beyin fırtınası — 日本語"}]),
|
|
245
|
+
encoding="utf-8",
|
|
246
|
+
)
|
|
247
|
+
fake = _cp1252_stream()
|
|
248
|
+
monkeypatch.setattr(sys, "stdout", fake)
|
|
249
|
+
assert brain.main(["--file", str(lib), "--extra", str(overlay), "list", "--all"]) == 0
|
|
250
|
+
out = fake.buffer.getvalue().decode("utf-8")
|
|
251
|
+
assert "Fikir Fırtınası 🌪" in out
|
|
252
|
+
assert "日本語" in out
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def test_missing_technique_name_reports_when_stderr_encoding_is_cp1252(lib, monkeypatch):
|
|
256
|
+
# `show` echoes the name it could not find; that name came from argv.
|
|
257
|
+
fake = _cp1252_stream()
|
|
258
|
+
monkeypatch.setattr(sys, "stderr", fake)
|
|
259
|
+
assert brain.main(["--file", str(lib), "show", "日本語"]) == 1
|
|
260
|
+
assert "日本語" in fake.buffer.getvalue().decode("utf-8")
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def test_pin_utf8_preserves_the_streams_error_handler():
|
|
264
|
+
# reconfigure(encoding=...) on its own resets errors to "strict"; stderr on
|
|
265
|
+
# POSIX defaults to "backslashreplace" and must keep it, or a diagnostic
|
|
266
|
+
# carrying a surrogate-escaped path becomes a traceback.
|
|
267
|
+
stream = io.TextIOWrapper(io.BytesIO(), encoding="ascii", errors="backslashreplace")
|
|
268
|
+
brain.pin_utf8(stream)
|
|
269
|
+
assert stream.encoding == "utf-8"
|
|
270
|
+
assert stream.errors == "backslashreplace"
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def test_pin_utf8_ignores_a_stream_without_reconfigure():
|
|
274
|
+
class Captured: # e.g. pytest's capture object, or a StringIO stand-in
|
|
275
|
+
errors = None
|
|
276
|
+
|
|
277
|
+
brain.pin_utf8(Captured()) # must not raise
|
|
278
|
+
|
|
279
|
+
|
|
230
280
|
def test_shipped_selector_is_in_sync_with_catalog():
|
|
231
281
|
# foolproofing: if someone edits brain-methods.csv they must regenerate the page.
|
|
232
282
|
# Regenerate with: uv run brain.py html --out assets/brain-selector.html
|
|
@@ -87,7 +87,7 @@ Default by character (policy → team, personal → user), confirm before writin
|
|
|
87
87
|
3. Write. Create `{project-root}/_bmad/custom/` if needed.
|
|
88
88
|
4. Verify:
|
|
89
89
|
```
|
|
90
|
-
uv run {project-root}/_bmad/scripts/resolve_customization.py --skill <install-path> --key <agent-or-workflow>
|
|
90
|
+
uv run {project-root}/_bmad/scripts/resolve_customization.py --skill <install-path> --project-root {project-root} --key <agent-or-workflow>
|
|
91
91
|
```
|
|
92
92
|
Show the merged output, point out the changed fields.
|
|
93
93
|
|
|
@@ -37,7 +37,7 @@ Three services, freely combined — each detailed in its reference: **Draft** a
|
|
|
37
37
|
|
|
38
38
|
**Forwarded activation:** if a caller invoked you with a stated intent, research type, or pre-resolved customization fields (the legacy research shims and Mary's menu do), honor them verbatim — skip your own inference for those values and resolve only the rest.
|
|
39
39
|
|
|
40
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow` (on failure read `{skill-root}/customize.toml`, use defaults). Run `{workflow.activation_steps_prepend}`, then `{workflow.activation_steps_append}`.
|
|
40
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow` (on failure read `{skill-root}/customize.toml`, use defaults). Run `{workflow.activation_steps_prepend}`, then `{workflow.activation_steps_append}`.
|
|
41
41
|
2. Resolve config: `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root}`. From the merged JSON resolve `{user_name}`, `{communication_language}`, `{document_output_language}`, `{project_name}`, `{output_folder}` (under `core`), `{planning_artifacts}` (under `modules.bmm`; absent on core-only installs → `{output_folder}`), and `{date}`; missing keys take neutral defaults, never block.
|
|
42
42
|
3. Headless (no interactive user) → see `## Headless Mode`. Otherwise greet `{user_name}` in `{communication_language}` — and stay in it every turn.
|
|
43
43
|
4. Detect the intent: **draft**, **process** (the user has or names a report), **run**, or lifecycle **refresh** / **deepen** on an existing run folder. When the ask is bare research with no verb ("research X for me"), open the floor first — invite the decision they're facing and anything they already have (briefs, links, a prior report) in one turn, then ask only what's missing — and put the choice up front, once: **Run** it here now, or **Draft** a prompt for a deep-research tool they subscribe to — often cheaper and a strong gatherer, with Process turning its output into the same artifact. State the trade honestly (tokens and minutes here vs. one manual round-trip there); their call, remembered for the session.
|
|
@@ -22,7 +22,7 @@ Lead by questioning, not lecturing. Ask one question at a time, press on weak po
|
|
|
22
22
|
|
|
23
23
|
## On Activation
|
|
24
24
|
|
|
25
|
-
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly with defaults. Apply the resolved `{workflow.*}` values throughout.
|
|
25
|
+
1. Resolve customization: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly with defaults. Apply the resolved `{workflow.*}` values throughout.
|
|
26
26
|
2. Run each `{workflow.activation_steps_prepend}` entry; treat each `{workflow.persistent_facts}` entry as foundational context (`file:` entries load their contents, `skill:` names a skill to consult, others are facts verbatim).
|
|
27
27
|
3. Resolve central config: `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root} --key core`; from the merged JSON read `{user_name}`, `{communication_language}`, `{output_folder}`. On failure use neutral defaults; never block. Greet `{user_name}` in `{communication_language}` and stay in it.
|
|
28
28
|
4. Note whether a BMad persona is already active in this conversation — the user loaded one (e.g. the analyst, the storyteller) and invoked the forge from within it. If so, that persona leads the session, in voice, throughout.
|
|
@@ -20,12 +20,11 @@ activation_steps_append = []
|
|
|
20
20
|
# Persistent facts the interrogator keeps in mind for the whole session
|
|
21
21
|
# (domain constraints, house rules, what's off the table). Each entry is a
|
|
22
22
|
# literal sentence, a skill prefixed with `skill:`, or a `file:`-prefixed
|
|
23
|
-
# path/glob whose contents are loaded as facts.
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
]
|
|
23
|
+
# path/glob whose contents are loaded as facts. Empty by default — repo-wide context
|
|
24
|
+
# belongs in AGENTS.md (see bmad-project-context), which every skill already sees. Use
|
|
25
|
+
# this for context only the forge needs, loaded on demand rather than carried as constant
|
|
26
|
+
# memory (e.g. `file:{project-root}/**/project-context.md` if you keep one).
|
|
27
|
+
persistent_facts = []
|
|
29
28
|
|
|
30
29
|
# Executed when the session completes. Scalar or array of instructions. Empty for none.
|
|
31
30
|
on_complete = []
|
|
@@ -110,7 +110,9 @@ def find_party_skill(project_root: Path, skill_root: Path):
|
|
|
110
110
|
def load_party_workflow(project_root: Path, party_skill: Path):
|
|
111
111
|
"""Merged [workflow] table for bmad-party-mode (base + user overrides)."""
|
|
112
112
|
resolver = project_root / "_bmad" / "scripts" / "resolve_customization.py"
|
|
113
|
-
data = _run_json(
|
|
113
|
+
data = _run_json(
|
|
114
|
+
[sys.executable, str(resolver), "--skill", str(party_skill), "--project-root", str(project_root), "--key", "workflow"]
|
|
115
|
+
)
|
|
114
116
|
if data is not None and isinstance(data.get("workflow"), dict):
|
|
115
117
|
return data["workflow"]
|
|
116
118
|
# Fallback: base customize.toml directly, no override merge.
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"""Unit tests for resolve_personas.py — pool merge, alias, party resolution."""
|
|
6
6
|
|
|
7
7
|
import sys
|
|
8
|
+
import tempfile
|
|
8
9
|
import unittest
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
@@ -134,5 +135,26 @@ class TestOverrideMergeFallback(unittest.TestCase):
|
|
|
134
135
|
self.assertEqual([m["code"] for m in wf["party_members"]], ["x", "y"]) # appended
|
|
135
136
|
|
|
136
137
|
|
|
138
|
+
class TestResolverInvocation(unittest.TestCase):
|
|
139
|
+
"""The wrapper knows the project root, so it must not let the resolver
|
|
140
|
+
infer one from the working directory (#2796)."""
|
|
141
|
+
|
|
142
|
+
def _captured_command(self, tmp):
|
|
143
|
+
captured = []
|
|
144
|
+
original = rp._run_json
|
|
145
|
+
rp._run_json = lambda cmd: captured.append(cmd) or {"workflow": {}}
|
|
146
|
+
try:
|
|
147
|
+
rp.load_party_workflow(Path(tmp) / "project", Path(tmp) / "skill")
|
|
148
|
+
finally:
|
|
149
|
+
rp._run_json = original
|
|
150
|
+
return captured[0]
|
|
151
|
+
|
|
152
|
+
def test_passes_project_root_to_the_customization_resolver(self):
|
|
153
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
154
|
+
cmd = self._captured_command(tmp)
|
|
155
|
+
self.assertIn("--project-root", cmd)
|
|
156
|
+
self.assertEqual(cmd[cmd.index("--project-root") + 1], str(Path(tmp) / "project"))
|
|
157
|
+
|
|
158
|
+
|
|
137
159
|
if __name__ == "__main__":
|
|
138
160
|
unittest.main()
|
|
@@ -26,7 +26,7 @@ When this skill completes, the user should:
|
|
|
26
26
|
- **Config**: Run `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root}` and use the merged JSON to resolve `output-location` variables and read `core.communication_language` and `modules.bmm.project_knowledge`. The resolver merges `_bmad/config.toml`, `_bmad/config.user.toml`, `_bmad/custom/config.toml`, and `_bmad/custom/config.user.toml` in that order.
|
|
27
27
|
- **Artifacts**: Files matching `outputs` patterns at resolved `output-location` paths reveal which steps are possibly completed; their content may also provide grounding context for recommendations
|
|
28
28
|
- **Project knowledge**: If `project_knowledge` resolves to an existing path, read it for grounding context. Never fabricate project-specific details.
|
|
29
|
-
- **Module docs**: Rows with `_meta` in the `skill` column carry a URL or path in `output-location` pointing to the module's documentation
|
|
29
|
+
- **Module docs**: Rows with `_meta` in the `skill` column carry a URL or path in `output-location` pointing to the module's documentation. Fetch and use these to answer general questions about that module.
|
|
30
30
|
|
|
31
31
|
## CSV Interpretation
|
|
32
32
|
|
|
@@ -16,7 +16,7 @@ Run a round-table where these agents talk to each other and to the user like rea
|
|
|
16
16
|
|
|
17
17
|
## On Activation
|
|
18
18
|
|
|
19
|
-
1. **Resolve customization:** `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults. Then run each `{workflow.activation_steps_prepend}` entry, and hold each `{workflow.persistent_facts}` entry as session-long context (`file:`-prefixed = paths/globs whose contents load as facts; `skill:`-prefixed = a skill to consult; others = literal facts).
|
|
19
|
+
1. **Resolve customization:** `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults. Then run each `{workflow.activation_steps_prepend}` entry, and hold each `{workflow.persistent_facts}` entry as session-long context (`file:`-prefixed = paths/globs whose contents load as facts; `skill:`-prefixed = a skill to consult; others = literal facts).
|
|
20
20
|
2. **Resolve core config:** `uv run {project-root}/_bmad/scripts/resolve_config.py --project-root {project-root}`. From the merged JSON's `core` table: greet with `{user_name}`, speak in `{communication_language}`, and resolve `{output_folder}`; `{date}` is today's date.
|
|
21
21
|
3. **Detect intent and route.** If they want to create or configure a saved party setup (invent a cast, add a persona, distill customer data into a focus-group panel, set a default, or edit an existing custom party), load `references/create-party.md` and follow it. Otherwise run a party — continue below.
|
|
22
22
|
4. **Resolve the roster:** `uv run {skill-root}/scripts/resolve_party.py --project-root {project-root} --skill {skill-root}`. It returns the active roster (`{workflow.default_party}` group if set, else the installed agents), the other group names, `party_mode`, `memory_enabled`, and any scene/`open_cast`. Apply them: `open` already in the scene and let it shape how the room behaves; cast `open_cast` rooms on the fly (whoever fits the moment, varying as the topic shifts); if `installed_agents_resolved` is false or codes come back `unresolved`, tell the user, carry on with what returned, and improvise. Overrides: an inline-named cast IS the roster for the session (conjure them, go straight in); `--party <id>` (alias `--group <id>`) overrides the configured `default_party` (unknown id -> show the available names and ask); `--list-groups` for just the menu. Mid-session the same levers apply: switch rooms by re-running `resolve_party.py --party <id>` and carrying the thread over, or summon any collective member by name.
|