bmad-method 6.2.3-next.2 → 6.2.3-next.21
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 +0 -4
- package/README.md +1 -1
- package/README_CN.md +1 -1
- package/README_VN.md +110 -0
- package/package.json +2 -1
- package/src/bmm-skills/1-analysis/bmad-agent-analyst/SKILL.md +7 -4
- package/src/bmm-skills/1-analysis/bmad-agent-tech-writer/SKILL.md +6 -4
- package/src/bmm-skills/1-analysis/bmad-document-project/workflow.md +8 -10
- package/src/bmm-skills/1-analysis/bmad-prfaq/SKILL.md +96 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/agents/artifact-analyzer.md +60 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/agents/web-researcher.md +49 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/assets/prfaq-template.md +62 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/bmad-manifest.json +16 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/references/customer-faq.md +55 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/references/internal-faq.md +51 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/references/press-release.md +60 -0
- package/src/bmm-skills/1-analysis/bmad-prfaq/references/verdict.md +79 -0
- package/src/bmm-skills/1-analysis/bmad-product-brief/SKILL.md +1 -6
- package/src/bmm-skills/1-analysis/bmad-product-brief/bmad-manifest.json +1 -1
- package/src/bmm-skills/1-analysis/research/bmad-domain-research/workflow.md +8 -6
- package/src/bmm-skills/1-analysis/research/bmad-market-research/workflow.md +8 -6
- package/src/bmm-skills/1-analysis/research/bmad-technical-research/workflow.md +8 -6
- package/src/bmm-skills/2-plan-workflows/bmad-agent-pm/SKILL.md +6 -4
- package/src/bmm-skills/2-plan-workflows/bmad-agent-ux-designer/SKILL.md +6 -4
- package/src/bmm-skills/2-plan-workflows/bmad-create-prd/workflow.md +8 -9
- package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/steps/step-13-responsive-accessibility.md +1 -1
- package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/workflow.md +8 -9
- package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01-discovery.md +1 -1
- package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01b-legacy-conversion.md +1 -1
- package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-02-review.md +1 -1
- package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-03-edit.md +1 -1
- package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-04-complete.md +1 -1
- package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/workflow.md +8 -9
- package/src/bmm-skills/2-plan-workflows/bmad-validate-prd/workflow.md +8 -9
- package/src/bmm-skills/3-solutioning/bmad-agent-architect/SKILL.md +6 -4
- package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/steps/step-01-document-discovery.md +1 -1
- package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/steps/step-02-prd-analysis.md +1 -1
- package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/steps/step-03-epic-coverage-validation.md +1 -1
- package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/workflow.md +9 -11
- package/src/bmm-skills/3-solutioning/bmad-create-architecture/workflow.md +8 -14
- package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/workflow.md +10 -12
- package/src/bmm-skills/3-solutioning/bmad-generate-project-context/workflow.md +8 -12
- package/src/bmm-skills/4-implementation/bmad-agent-dev/SKILL.md +11 -4
- package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/SKILL.md +29 -0
- package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/generate-trail.md +38 -0
- package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-01-orientation.md +105 -0
- package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-02-walkthrough.md +89 -0
- package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-03-detail-pass.md +106 -0
- package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-04-testing.md +74 -0
- package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-05-wrapup.md +24 -0
- package/src/bmm-skills/4-implementation/bmad-code-review/steps/step-01-gather-context.md +38 -15
- package/src/bmm-skills/4-implementation/bmad-correct-course/checklist.md +2 -2
- package/src/bmm-skills/4-implementation/bmad-correct-course/workflow.md +8 -8
- package/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/checklist.md +1 -1
- package/src/bmm-skills/4-implementation/bmad-quick-dev/spec-template.md +1 -1
- package/src/bmm-skills/4-implementation/bmad-quick-dev/step-01-clarify-and-route.md +11 -2
- package/src/bmm-skills/4-implementation/bmad-quick-dev/step-03-implement.md +2 -0
- package/src/bmm-skills/4-implementation/bmad-quick-dev/step-oneshot.md +17 -4
- package/src/bmm-skills/4-implementation/bmad-retrospective/workflow.md +134 -134
- package/src/bmm-skills/4-implementation/bmad-sprint-planning/sprint-status-template.yaml +1 -1
- package/src/bmm-skills/4-implementation/bmad-sprint-planning/workflow.md +3 -3
- package/src/bmm-skills/4-implementation/bmad-sprint-status/workflow.md +2 -2
- package/src/bmm-skills/module-help.csv +3 -1
- package/src/core-skills/bmad-advanced-elicitation/SKILL.md +1 -2
- package/src/core-skills/bmad-distillator/SKILL.md +0 -1
- package/src/core-skills/bmad-distillator/resources/distillate-format-reference.md +9 -9
- package/src/core-skills/bmad-party-mode/SKILL.md +121 -2
- package/tools/installer/core/installer.js +6 -53
- package/tools/installer/core/manifest-generator.js +9 -0
- package/tools/installer/external-official-modules.yaml +1 -1
- package/tools/installer/ide/platform-codes.yaml +6 -4
- package/tools/installer/modules/custom-modules.js +105 -0
- package/tools/installer/modules/external-manager.js +34 -3
- package/tools/platform-codes.yaml +6 -0
- package/src/bmm-skills/2-plan-workflows/create-prd/data/domain-complexity.csv +0 -15
- package/src/bmm-skills/2-plan-workflows/create-prd/data/prd-purpose.md +0 -197
- package/src/bmm-skills/2-plan-workflows/create-prd/data/project-types.csv +0 -11
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +0 -224
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +0 -191
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +0 -209
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +0 -174
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +0 -214
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +0 -228
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +0 -217
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +0 -205
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +0 -243
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +0 -263
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +0 -209
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +0 -264
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +0 -242
- package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +0 -232
- package/src/bmm-skills/2-plan-workflows/create-prd/workflow-validate-prd.md +0 -65
- package/src/bmm-skills/4-implementation/bmad-agent-qa/SKILL.md +0 -59
- package/src/bmm-skills/4-implementation/bmad-agent-qa/bmad-skill-manifest.yaml +0 -11
- package/src/bmm-skills/4-implementation/bmad-agent-quick-flow-solo-dev/SKILL.md +0 -51
- package/src/bmm-skills/4-implementation/bmad-agent-quick-flow-solo-dev/bmad-skill-manifest.yaml +0 -11
- package/src/bmm-skills/4-implementation/bmad-agent-sm/SKILL.md +0 -53
- package/src/bmm-skills/4-implementation/bmad-agent-sm/bmad-skill-manifest.yaml +0 -11
- package/src/core-skills/bmad-init/SKILL.md +0 -100
- package/src/core-skills/bmad-init/resources/core-module.yaml +0 -25
- package/src/core-skills/bmad-init/scripts/bmad_init.py +0 -624
- package/src/core-skills/bmad-init/scripts/tests/test_bmad_init.py +0 -393
- package/src/core-skills/bmad-party-mode/steps/step-01-agent-loading.md +0 -138
- package/src/core-skills/bmad-party-mode/steps/step-02-discussion-orchestration.md +0 -187
- package/src/core-skills/bmad-party-mode/steps/step-03-graceful-exit.md +0 -167
- package/src/core-skills/bmad-party-mode/workflow.md +0 -190
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
# /// script
|
|
2
|
-
# requires-python = ">=3.10"
|
|
3
|
-
# dependencies = ["pyyaml"]
|
|
4
|
-
# ///
|
|
5
|
-
|
|
6
|
-
#!/usr/bin/env python3
|
|
7
|
-
"""Unit tests for bmad_init.py"""
|
|
8
|
-
|
|
9
|
-
import json
|
|
10
|
-
import os
|
|
11
|
-
import shutil
|
|
12
|
-
import sys
|
|
13
|
-
import tempfile
|
|
14
|
-
import unittest
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
|
|
17
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
18
|
-
|
|
19
|
-
from bmad_init import (
|
|
20
|
-
find_project_root,
|
|
21
|
-
parse_var_specs,
|
|
22
|
-
resolve_project_root_placeholder,
|
|
23
|
-
expand_template,
|
|
24
|
-
apply_result_template,
|
|
25
|
-
load_module_yaml,
|
|
26
|
-
find_core_module_yaml,
|
|
27
|
-
find_target_module_yaml,
|
|
28
|
-
load_config_file,
|
|
29
|
-
load_module_config,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class TestFindProjectRoot(unittest.TestCase):
|
|
34
|
-
|
|
35
|
-
def test_finds_bmad_folder(self):
|
|
36
|
-
temp_dir = tempfile.mkdtemp()
|
|
37
|
-
try:
|
|
38
|
-
(Path(temp_dir) / '_bmad').mkdir()
|
|
39
|
-
original_cwd = os.getcwd()
|
|
40
|
-
try:
|
|
41
|
-
os.chdir(temp_dir)
|
|
42
|
-
result = find_project_root()
|
|
43
|
-
self.assertEqual(result.resolve(), Path(temp_dir).resolve())
|
|
44
|
-
finally:
|
|
45
|
-
os.chdir(original_cwd)
|
|
46
|
-
finally:
|
|
47
|
-
shutil.rmtree(temp_dir)
|
|
48
|
-
|
|
49
|
-
def test_llm_provided_with_bmad(self):
|
|
50
|
-
temp_dir = tempfile.mkdtemp()
|
|
51
|
-
try:
|
|
52
|
-
(Path(temp_dir) / '_bmad').mkdir()
|
|
53
|
-
result = find_project_root(llm_provided=temp_dir)
|
|
54
|
-
self.assertEqual(result.resolve(), Path(temp_dir).resolve())
|
|
55
|
-
finally:
|
|
56
|
-
shutil.rmtree(temp_dir)
|
|
57
|
-
|
|
58
|
-
def test_llm_provided_without_bmad_still_returns_dir(self):
|
|
59
|
-
"""First-run case: LLM provides path but _bmad doesn't exist yet."""
|
|
60
|
-
temp_dir = tempfile.mkdtemp()
|
|
61
|
-
try:
|
|
62
|
-
result = find_project_root(llm_provided=temp_dir)
|
|
63
|
-
self.assertEqual(result.resolve(), Path(temp_dir).resolve())
|
|
64
|
-
finally:
|
|
65
|
-
shutil.rmtree(temp_dir)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class TestParseVarSpecs(unittest.TestCase):
|
|
69
|
-
|
|
70
|
-
def test_vars_with_defaults(self):
|
|
71
|
-
specs = parse_var_specs('var1:value1,var2:value2')
|
|
72
|
-
self.assertEqual(len(specs), 2)
|
|
73
|
-
self.assertEqual(specs[0]['name'], 'var1')
|
|
74
|
-
self.assertEqual(specs[0]['default'], 'value1')
|
|
75
|
-
|
|
76
|
-
def test_vars_without_defaults(self):
|
|
77
|
-
specs = parse_var_specs('var1,var2')
|
|
78
|
-
self.assertEqual(len(specs), 2)
|
|
79
|
-
self.assertIsNone(specs[0]['default'])
|
|
80
|
-
|
|
81
|
-
def test_mixed_vars(self):
|
|
82
|
-
specs = parse_var_specs('required_var,var2:default2')
|
|
83
|
-
self.assertIsNone(specs[0]['default'])
|
|
84
|
-
self.assertEqual(specs[1]['default'], 'default2')
|
|
85
|
-
|
|
86
|
-
def test_colon_in_default(self):
|
|
87
|
-
specs = parse_var_specs('path:{project-root}/some/path')
|
|
88
|
-
self.assertEqual(specs[0]['default'], '{project-root}/some/path')
|
|
89
|
-
|
|
90
|
-
def test_empty_string(self):
|
|
91
|
-
self.assertEqual(parse_var_specs(''), [])
|
|
92
|
-
|
|
93
|
-
def test_none(self):
|
|
94
|
-
self.assertEqual(parse_var_specs(None), [])
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
class TestResolveProjectRootPlaceholder(unittest.TestCase):
|
|
98
|
-
|
|
99
|
-
def test_resolve_placeholder(self):
|
|
100
|
-
result = resolve_project_root_placeholder('{project-root}/output', Path('/test'))
|
|
101
|
-
self.assertEqual(result, '/test/output')
|
|
102
|
-
|
|
103
|
-
def test_no_placeholder(self):
|
|
104
|
-
result = resolve_project_root_placeholder('/absolute/path', Path('/test'))
|
|
105
|
-
self.assertEqual(result, '/absolute/path')
|
|
106
|
-
|
|
107
|
-
def test_none(self):
|
|
108
|
-
self.assertIsNone(resolve_project_root_placeholder(None, Path('/test')))
|
|
109
|
-
|
|
110
|
-
def test_non_string(self):
|
|
111
|
-
self.assertEqual(resolve_project_root_placeholder(42, Path('/test')), 42)
|
|
112
|
-
|
|
113
|
-
def test_absolute_path_stored_with_prefix(self):
|
|
114
|
-
"""Absolute output_folder entered by user is stored as '{project-root}//abs/path'
|
|
115
|
-
by the '{project-root}/{value}' template. It must resolve to '/abs/path', not
|
|
116
|
-
'/project//abs/path'."""
|
|
117
|
-
result = resolve_project_root_placeholder(
|
|
118
|
-
'{project-root}//Users/me/outside', Path('/Users/me/myproject')
|
|
119
|
-
)
|
|
120
|
-
self.assertEqual(result, '/Users/me/outside')
|
|
121
|
-
|
|
122
|
-
def test_relative_path_with_traversal_is_normalized(self):
|
|
123
|
-
"""A relative path like '../../sibling' produces '{project-root}/../../sibling'
|
|
124
|
-
after the template. It must resolve to the normalized absolute path, not the
|
|
125
|
-
un-normalized string '/project/../../sibling'."""
|
|
126
|
-
result = resolve_project_root_placeholder(
|
|
127
|
-
'{project-root}/../../sibling', Path('/Users/me/myproject')
|
|
128
|
-
)
|
|
129
|
-
self.assertEqual(result, '/Users/sibling')
|
|
130
|
-
|
|
131
|
-
def test_relative_path_one_level_up(self):
|
|
132
|
-
result = resolve_project_root_placeholder(
|
|
133
|
-
'{project-root}/../outside-outputs', Path('/project/root')
|
|
134
|
-
)
|
|
135
|
-
self.assertEqual(result, '/project/outside-outputs')
|
|
136
|
-
|
|
137
|
-
def test_standard_relative_path_unchanged(self):
|
|
138
|
-
"""Normal in-project relative paths continue to work correctly."""
|
|
139
|
-
result = resolve_project_root_placeholder(
|
|
140
|
-
'{project-root}/_bmad-output', Path('/project/root')
|
|
141
|
-
)
|
|
142
|
-
self.assertEqual(result, '/project/root/_bmad-output')
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
class TestExpandTemplate(unittest.TestCase):
|
|
146
|
-
|
|
147
|
-
def test_basic_expansion(self):
|
|
148
|
-
result = expand_template('{project-root}/output', {'project-root': '/test'})
|
|
149
|
-
self.assertEqual(result, '/test/output')
|
|
150
|
-
|
|
151
|
-
def test_multiple_placeholders(self):
|
|
152
|
-
result = expand_template(
|
|
153
|
-
'{output_folder}/planning',
|
|
154
|
-
{'output_folder': '_bmad-output', 'project-root': '/test'}
|
|
155
|
-
)
|
|
156
|
-
self.assertEqual(result, '_bmad-output/planning')
|
|
157
|
-
|
|
158
|
-
def test_none_value(self):
|
|
159
|
-
self.assertIsNone(expand_template(None, {}))
|
|
160
|
-
|
|
161
|
-
def test_non_string(self):
|
|
162
|
-
self.assertEqual(expand_template(42, {}), 42)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
class TestApplyResultTemplate(unittest.TestCase):
|
|
166
|
-
|
|
167
|
-
def test_with_result_template(self):
|
|
168
|
-
var_def = {'result': '{project-root}/{value}'}
|
|
169
|
-
result = apply_result_template(var_def, '_bmad-output', {'project-root': '/test'})
|
|
170
|
-
self.assertEqual(result, '/test/_bmad-output')
|
|
171
|
-
|
|
172
|
-
def test_without_result_template(self):
|
|
173
|
-
result = apply_result_template({}, 'raw_value', {})
|
|
174
|
-
self.assertEqual(result, 'raw_value')
|
|
175
|
-
|
|
176
|
-
def test_value_only_template(self):
|
|
177
|
-
var_def = {'result': '{value}'}
|
|
178
|
-
result = apply_result_template(var_def, 'English', {})
|
|
179
|
-
self.assertEqual(result, 'English')
|
|
180
|
-
|
|
181
|
-
def test_absolute_value_skips_project_root_template(self):
|
|
182
|
-
"""When the user enters an absolute path, the '{project-root}/{value}' template
|
|
183
|
-
must not be applied — doing so would produce '/project//absolute/path'."""
|
|
184
|
-
var_def = {'result': '{project-root}/{value}'}
|
|
185
|
-
result = apply_result_template(
|
|
186
|
-
var_def, '/Users/me/shared-outputs', {'project-root': '/Users/me/myproject'}
|
|
187
|
-
)
|
|
188
|
-
self.assertEqual(result, '/Users/me/shared-outputs')
|
|
189
|
-
|
|
190
|
-
def test_relative_traversal_value_is_normalized(self):
|
|
191
|
-
"""A relative path like '../../outside' combined with the project-root template
|
|
192
|
-
must produce a clean normalized absolute path, not '/project/../../outside'."""
|
|
193
|
-
var_def = {'result': '{project-root}/{value}'}
|
|
194
|
-
result = apply_result_template(
|
|
195
|
-
var_def, '../../outside-dir', {'project-root': '/Users/me/myproject'}
|
|
196
|
-
)
|
|
197
|
-
self.assertEqual(result, '/Users/outside-dir')
|
|
198
|
-
|
|
199
|
-
def test_relative_one_level_up_is_normalized(self):
|
|
200
|
-
var_def = {'result': '{project-root}/{value}'}
|
|
201
|
-
result = apply_result_template(
|
|
202
|
-
var_def, '../sibling-outputs', {'project-root': '/project/root'}
|
|
203
|
-
)
|
|
204
|
-
self.assertEqual(result, '/project/sibling-outputs')
|
|
205
|
-
|
|
206
|
-
def test_normal_relative_value_unchanged(self):
|
|
207
|
-
"""Standard in-project relative paths still produce the expected joined path."""
|
|
208
|
-
var_def = {'result': '{project-root}/{value}'}
|
|
209
|
-
result = apply_result_template(
|
|
210
|
-
var_def, '_bmad-output', {'project-root': '/project/root'}
|
|
211
|
-
)
|
|
212
|
-
self.assertEqual(result, '/project/root/_bmad-output')
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
class TestLoadModuleYaml(unittest.TestCase):
|
|
216
|
-
|
|
217
|
-
def setUp(self):
|
|
218
|
-
self.temp_dir = tempfile.mkdtemp()
|
|
219
|
-
|
|
220
|
-
def tearDown(self):
|
|
221
|
-
shutil.rmtree(self.temp_dir)
|
|
222
|
-
|
|
223
|
-
def test_loads_core_module_yaml(self):
|
|
224
|
-
path = Path(self.temp_dir) / 'module.yaml'
|
|
225
|
-
path.write_text(
|
|
226
|
-
'code: core\n'
|
|
227
|
-
'name: "BMad Core Module"\n'
|
|
228
|
-
'header: "Core Config"\n'
|
|
229
|
-
'user_name:\n'
|
|
230
|
-
' prompt: "What should agents call you?"\n'
|
|
231
|
-
' default: "BMad"\n'
|
|
232
|
-
' result: "{value}"\n'
|
|
233
|
-
)
|
|
234
|
-
result = load_module_yaml(path)
|
|
235
|
-
self.assertIsNotNone(result)
|
|
236
|
-
self.assertEqual(result['meta']['code'], 'core')
|
|
237
|
-
self.assertEqual(result['meta']['name'], 'BMad Core Module')
|
|
238
|
-
self.assertIn('user_name', result['variables'])
|
|
239
|
-
self.assertEqual(result['variables']['user_name']['prompt'], 'What should agents call you?')
|
|
240
|
-
|
|
241
|
-
def test_loads_module_with_directories(self):
|
|
242
|
-
path = Path(self.temp_dir) / 'module.yaml'
|
|
243
|
-
path.write_text(
|
|
244
|
-
'code: bmm\n'
|
|
245
|
-
'name: "BMad Method"\n'
|
|
246
|
-
'project_name:\n'
|
|
247
|
-
' prompt: "Project name?"\n'
|
|
248
|
-
' default: "{directory_name}"\n'
|
|
249
|
-
' result: "{value}"\n'
|
|
250
|
-
'directories:\n'
|
|
251
|
-
' - "{planning_artifacts}"\n'
|
|
252
|
-
)
|
|
253
|
-
result = load_module_yaml(path)
|
|
254
|
-
self.assertEqual(result['directories'], ['{planning_artifacts}'])
|
|
255
|
-
|
|
256
|
-
def test_returns_none_for_missing(self):
|
|
257
|
-
result = load_module_yaml(Path(self.temp_dir) / 'nonexistent.yaml')
|
|
258
|
-
self.assertIsNone(result)
|
|
259
|
-
|
|
260
|
-
def test_returns_none_for_empty(self):
|
|
261
|
-
path = Path(self.temp_dir) / 'empty.yaml'
|
|
262
|
-
path.write_text('')
|
|
263
|
-
result = load_module_yaml(path)
|
|
264
|
-
self.assertIsNone(result)
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
class TestFindCoreModuleYaml(unittest.TestCase):
|
|
268
|
-
|
|
269
|
-
def test_returns_path_to_resources(self):
|
|
270
|
-
path = find_core_module_yaml()
|
|
271
|
-
self.assertTrue(str(path).endswith('resources/core-module.yaml'))
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
class TestFindTargetModuleYaml(unittest.TestCase):
|
|
275
|
-
|
|
276
|
-
def setUp(self):
|
|
277
|
-
self.temp_dir = tempfile.mkdtemp()
|
|
278
|
-
self.project_root = Path(self.temp_dir)
|
|
279
|
-
|
|
280
|
-
def tearDown(self):
|
|
281
|
-
shutil.rmtree(self.temp_dir)
|
|
282
|
-
|
|
283
|
-
def test_finds_in_skill_assets(self):
|
|
284
|
-
skill_path = self.project_root / 'skills' / 'test-skill'
|
|
285
|
-
assets = skill_path / 'assets'
|
|
286
|
-
assets.mkdir(parents=True)
|
|
287
|
-
(assets / 'module.yaml').write_text('code: test\n')
|
|
288
|
-
|
|
289
|
-
result = find_target_module_yaml('test', self.project_root, str(skill_path))
|
|
290
|
-
self.assertIsNotNone(result)
|
|
291
|
-
self.assertTrue(str(result).endswith('assets/module.yaml'))
|
|
292
|
-
|
|
293
|
-
def test_finds_in_skill_root(self):
|
|
294
|
-
skill_path = self.project_root / 'skills' / 'test-skill'
|
|
295
|
-
skill_path.mkdir(parents=True)
|
|
296
|
-
(skill_path / 'module.yaml').write_text('code: test\n')
|
|
297
|
-
|
|
298
|
-
result = find_target_module_yaml('test', self.project_root, str(skill_path))
|
|
299
|
-
self.assertIsNotNone(result)
|
|
300
|
-
|
|
301
|
-
def test_finds_in_bmad_module_dir(self):
|
|
302
|
-
module_dir = self.project_root / '_bmad' / 'mymod'
|
|
303
|
-
module_dir.mkdir(parents=True)
|
|
304
|
-
(module_dir / 'module.yaml').write_text('code: mymod\n')
|
|
305
|
-
|
|
306
|
-
result = find_target_module_yaml('mymod', self.project_root)
|
|
307
|
-
self.assertIsNotNone(result)
|
|
308
|
-
|
|
309
|
-
def test_returns_none_when_not_found(self):
|
|
310
|
-
result = find_target_module_yaml('missing', self.project_root)
|
|
311
|
-
self.assertIsNone(result)
|
|
312
|
-
|
|
313
|
-
def test_skill_path_takes_priority(self):
|
|
314
|
-
"""Skill assets module.yaml takes priority over _bmad/{module}/."""
|
|
315
|
-
skill_path = self.project_root / 'skills' / 'test-skill'
|
|
316
|
-
assets = skill_path / 'assets'
|
|
317
|
-
assets.mkdir(parents=True)
|
|
318
|
-
(assets / 'module.yaml').write_text('code: test\nname: from-skill\n')
|
|
319
|
-
|
|
320
|
-
module_dir = self.project_root / '_bmad' / 'test'
|
|
321
|
-
module_dir.mkdir(parents=True)
|
|
322
|
-
(module_dir / 'module.yaml').write_text('code: test\nname: from-bmad\n')
|
|
323
|
-
|
|
324
|
-
result = find_target_module_yaml('test', self.project_root, str(skill_path))
|
|
325
|
-
self.assertTrue('assets' in str(result))
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
class TestLoadConfigFile(unittest.TestCase):
|
|
329
|
-
|
|
330
|
-
def setUp(self):
|
|
331
|
-
self.temp_dir = tempfile.mkdtemp()
|
|
332
|
-
|
|
333
|
-
def tearDown(self):
|
|
334
|
-
shutil.rmtree(self.temp_dir)
|
|
335
|
-
|
|
336
|
-
def test_loads_flat_yaml(self):
|
|
337
|
-
path = Path(self.temp_dir) / 'config.yaml'
|
|
338
|
-
path.write_text('user_name: Test\ncommunication_language: English\n')
|
|
339
|
-
result = load_config_file(path)
|
|
340
|
-
self.assertEqual(result['user_name'], 'Test')
|
|
341
|
-
|
|
342
|
-
def test_returns_none_for_missing(self):
|
|
343
|
-
result = load_config_file(Path(self.temp_dir) / 'missing.yaml')
|
|
344
|
-
self.assertIsNone(result)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
class TestLoadModuleConfig(unittest.TestCase):
|
|
348
|
-
|
|
349
|
-
def setUp(self):
|
|
350
|
-
self.temp_dir = tempfile.mkdtemp()
|
|
351
|
-
self.project_root = Path(self.temp_dir)
|
|
352
|
-
bmad_core = self.project_root / '_bmad' / 'core'
|
|
353
|
-
bmad_core.mkdir(parents=True)
|
|
354
|
-
(bmad_core / 'config.yaml').write_text(
|
|
355
|
-
'user_name: TestUser\n'
|
|
356
|
-
'communication_language: English\n'
|
|
357
|
-
'document_output_language: English\n'
|
|
358
|
-
'output_folder: "{project-root}/_bmad-output"\n'
|
|
359
|
-
)
|
|
360
|
-
bmad_bmb = self.project_root / '_bmad' / 'bmb'
|
|
361
|
-
bmad_bmb.mkdir(parents=True)
|
|
362
|
-
(bmad_bmb / 'config.yaml').write_text(
|
|
363
|
-
'user_name: TestUser\n'
|
|
364
|
-
'communication_language: English\n'
|
|
365
|
-
'document_output_language: English\n'
|
|
366
|
-
'output_folder: "{project-root}/_bmad-output"\n'
|
|
367
|
-
'bmad_builder_output_folder: "{project-root}/_bmad-output/skills"\n'
|
|
368
|
-
'bmad_builder_reports: "{project-root}/_bmad-output/reports"\n'
|
|
369
|
-
)
|
|
370
|
-
|
|
371
|
-
def tearDown(self):
|
|
372
|
-
shutil.rmtree(self.temp_dir)
|
|
373
|
-
|
|
374
|
-
def test_load_core(self):
|
|
375
|
-
result = load_module_config('core', self.project_root)
|
|
376
|
-
self.assertIsNotNone(result)
|
|
377
|
-
self.assertEqual(result['user_name'], 'TestUser')
|
|
378
|
-
|
|
379
|
-
def test_load_module_includes_core_vars(self):
|
|
380
|
-
result = load_module_config('bmb', self.project_root)
|
|
381
|
-
self.assertIsNotNone(result)
|
|
382
|
-
# Module-specific var
|
|
383
|
-
self.assertIn('bmad_builder_output_folder', result)
|
|
384
|
-
# Core vars also present
|
|
385
|
-
self.assertEqual(result['user_name'], 'TestUser')
|
|
386
|
-
|
|
387
|
-
def test_missing_module(self):
|
|
388
|
-
result = load_module_config('nonexistent', self.project_root)
|
|
389
|
-
self.assertIsNone(result)
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
if __name__ == '__main__':
|
|
393
|
-
unittest.main()
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# Step 1: Agent Loading and Party Mode Initialization
|
|
2
|
-
|
|
3
|
-
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
4
|
-
|
|
5
|
-
- ✅ YOU ARE A PARTY MODE FACILITATOR, not just a workflow executor
|
|
6
|
-
- 🎯 CREATE ENGAGING ATMOSPHERE for multi-agent collaboration
|
|
7
|
-
- 📋 LOAD COMPLETE AGENT ROSTER from manifest with merged personalities
|
|
8
|
-
- 🔍 PARSE AGENT DATA for conversation orchestration
|
|
9
|
-
- 💬 INTRODUCE DIVERSE AGENT SAMPLE to kick off discussion
|
|
10
|
-
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
11
|
-
|
|
12
|
-
## EXECUTION PROTOCOLS:
|
|
13
|
-
|
|
14
|
-
- 🎯 Show agent loading process before presenting party activation
|
|
15
|
-
- ⚠️ Present [C] continue option after agent roster is loaded
|
|
16
|
-
- 💾 ONLY save when user chooses C (Continue)
|
|
17
|
-
- 📖 Update frontmatter `stepsCompleted: [1]` before loading next step
|
|
18
|
-
- 🚫 FORBIDDEN to start conversation until C is selected
|
|
19
|
-
|
|
20
|
-
## CONTEXT BOUNDARIES:
|
|
21
|
-
|
|
22
|
-
- Agent manifest CSV is available at `{project-root}/_bmad/_config/agent-manifest.csv`
|
|
23
|
-
- User configuration from config.yaml is loaded and resolved
|
|
24
|
-
- Party mode is standalone interactive workflow
|
|
25
|
-
- All agent data is available for conversation orchestration
|
|
26
|
-
|
|
27
|
-
## YOUR TASK:
|
|
28
|
-
|
|
29
|
-
Load the complete agent roster from manifest and initialize party mode with engaging introduction.
|
|
30
|
-
|
|
31
|
-
## AGENT LOADING SEQUENCE:
|
|
32
|
-
|
|
33
|
-
### 1. Load Agent Manifest
|
|
34
|
-
|
|
35
|
-
Begin agent loading process:
|
|
36
|
-
|
|
37
|
-
"Now initializing **Party Mode** with our complete BMAD agent roster! Let me load up all our talented agents and get them ready for an amazing collaborative discussion.
|
|
38
|
-
|
|
39
|
-
**Agent Manifest Loading:**"
|
|
40
|
-
|
|
41
|
-
Load and parse the agent manifest CSV from `{project-root}/_bmad/_config/agent-manifest.csv`
|
|
42
|
-
|
|
43
|
-
### 2. Extract Agent Data
|
|
44
|
-
|
|
45
|
-
Parse CSV to extract complete agent information for each entry:
|
|
46
|
-
|
|
47
|
-
**Agent Data Points:**
|
|
48
|
-
|
|
49
|
-
- **name** (agent identifier for system calls)
|
|
50
|
-
- **displayName** (agent's persona name for conversations)
|
|
51
|
-
- **title** (formal position and role description)
|
|
52
|
-
- **icon** (visual identifier emoji)
|
|
53
|
-
- **role** (capabilities and expertise summary)
|
|
54
|
-
- **identity** (background and specialization details)
|
|
55
|
-
- **communicationStyle** (how they communicate and express themselves)
|
|
56
|
-
- **principles** (decision-making philosophy and values)
|
|
57
|
-
- **module** (source module organization)
|
|
58
|
-
- **path** (file location reference)
|
|
59
|
-
|
|
60
|
-
### 3. Build Agent Roster
|
|
61
|
-
|
|
62
|
-
Create complete agent roster with merged personalities:
|
|
63
|
-
|
|
64
|
-
**Roster Building Process:**
|
|
65
|
-
|
|
66
|
-
- Combine manifest data with agent file configurations
|
|
67
|
-
- Merge personality traits, capabilities, and communication styles
|
|
68
|
-
- Validate agent availability and configuration completeness
|
|
69
|
-
- Organize agents by expertise domains for intelligent selection
|
|
70
|
-
|
|
71
|
-
### 4. Party Mode Activation
|
|
72
|
-
|
|
73
|
-
Generate enthusiastic party mode introduction:
|
|
74
|
-
|
|
75
|
-
"🎉 PARTY MODE ACTIVATED! 🎉
|
|
76
|
-
|
|
77
|
-
Welcome {{user_name}}! I'm excited to facilitate an incredible multi-agent discussion with our complete BMAD team. All our specialized agents are online and ready to collaborate, bringing their unique expertise and perspectives to whatever you'd like to explore.
|
|
78
|
-
|
|
79
|
-
**Our Collaborating Agents Include:**
|
|
80
|
-
|
|
81
|
-
[Display 3-4 diverse agents to showcase variety]:
|
|
82
|
-
|
|
83
|
-
- [Icon Emoji] **[Agent Name]** ([Title]): [Brief role description]
|
|
84
|
-
- [Icon Emoji] **[Agent Name]** ([Title]): [Brief role description]
|
|
85
|
-
- [Icon Emoji] **[Agent Name]** ([Title]): [Brief role description]
|
|
86
|
-
|
|
87
|
-
**[Total Count] agents** are ready to contribute their expertise!
|
|
88
|
-
|
|
89
|
-
**What would you like to discuss with the team today?**"
|
|
90
|
-
|
|
91
|
-
### 5. Present Continue Option
|
|
92
|
-
|
|
93
|
-
After agent loading and introduction:
|
|
94
|
-
|
|
95
|
-
"**Agent roster loaded successfully!** All our BMAD experts are excited to collaborate with you.
|
|
96
|
-
|
|
97
|
-
**Ready to start the discussion?**
|
|
98
|
-
[C] Continue - Begin multi-agent conversation
|
|
99
|
-
|
|
100
|
-
### 6. Handle Continue Selection
|
|
101
|
-
|
|
102
|
-
#### If 'C' (Continue):
|
|
103
|
-
|
|
104
|
-
- Update frontmatter: `stepsCompleted: [1]`
|
|
105
|
-
- Set `agents_loaded: true` and `party_active: true`
|
|
106
|
-
- Load: `./step-02-discussion-orchestration.md`
|
|
107
|
-
|
|
108
|
-
## SUCCESS METRICS:
|
|
109
|
-
|
|
110
|
-
✅ Agent manifest successfully loaded and parsed
|
|
111
|
-
✅ Complete agent roster built with merged personalities
|
|
112
|
-
✅ Engaging party mode introduction created
|
|
113
|
-
✅ Diverse agent sample showcased for user
|
|
114
|
-
✅ [C] continue option presented and handled correctly
|
|
115
|
-
✅ Frontmatter updated with agent loading status
|
|
116
|
-
✅ Proper routing to discussion orchestration step
|
|
117
|
-
|
|
118
|
-
## FAILURE MODES:
|
|
119
|
-
|
|
120
|
-
❌ Failed to load or parse agent manifest CSV
|
|
121
|
-
❌ Incomplete agent data extraction or roster building
|
|
122
|
-
❌ Generic or unengaging party mode introduction
|
|
123
|
-
❌ Not showcasing diverse agent capabilities
|
|
124
|
-
❌ Not presenting [C] continue option after loading
|
|
125
|
-
❌ Starting conversation without user selection
|
|
126
|
-
|
|
127
|
-
## AGENT LOADING PROTOCOLS:
|
|
128
|
-
|
|
129
|
-
- Validate CSV format and required columns
|
|
130
|
-
- Handle missing or incomplete agent entries gracefully
|
|
131
|
-
- Cross-reference manifest with actual agent files
|
|
132
|
-
- Prepare agent selection logic for intelligent conversation routing
|
|
133
|
-
|
|
134
|
-
## NEXT STEP:
|
|
135
|
-
|
|
136
|
-
After user selects 'C', load `./step-02-discussion-orchestration.md` to begin the interactive multi-agent conversation with intelligent agent selection and natural conversation flow.
|
|
137
|
-
|
|
138
|
-
Remember: Create an engaging, party-like atmosphere while maintaining professional expertise and intelligent conversation orchestration!
|