Skip to content

Commit 2620e7f

Browse files
committed
fix: reconcile merge-help-csv HEADER with canonical 13-column schema
merge-help-csv.py defined a 15-column HEADER (agent-name, skill-name, capability, trailing empty) that diverged from the 13-column schema used by validate-module.py, all module-help.csv files, and create-module.md. This would silently corrupt or misalign CSV data during module setup.
1 parent 4df6de5 commit 2620e7f

4 files changed

Lines changed: 18 additions & 22 deletions

File tree

docs/explanation/module-configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ If these cover your discoverability needs, you can skip the setup skill entirely
8888
The CSV asset registers the module's capabilities with the help system. Each row describes one capability that users can discover and invoke.
8989

9090
```csv
91-
module,agent-name,skill-name,display-name,menu-code,capability,args,description,...
92-
mymod,,my-skill,My Skill,MS,build-process,,"Does something useful.",...
91+
module,skill,display-name,menu-code,description,action,args,phase,after,before,required,output-location,outputs
92+
mymod,my-skill,My Skill,MS,"Does something useful.",build-process,,anytime,,,false,,
9393
```
9494

9595
When the setup skill runs, it merges these rows into the project-wide `_bmad/module-help.csv`, replacing any existing rows for this module. This is how users find your module's commands through the help system.

skills/bmad-builder-setup/scripts/merge-help-csv.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,18 @@
2626
# CSV header for module-help.csv
2727
HEADER = [
2828
"module",
29-
"agent-name",
30-
"skill-name",
29+
"skill",
3130
"display-name",
3231
"menu-code",
33-
"capability",
34-
"args",
3532
"description",
33+
"action",
34+
"args",
3635
"phase",
3736
"after",
3837
"before",
3938
"required",
4039
"output-location",
4140
"outputs",
42-
"", # trailing empty column from trailing comma
4341
]
4442

4543

skills/bmad-builder-setup/scripts/tests/test-merge-help-csv.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232

3333

3434
SAMPLE_ROWS = [
35-
["bmb", "", "bmad-bmb-module-init", "Install Module", "IM", "install", "", "Install BMad Builder.", "anytime", "", "", "false", "", "config", ""],
36-
["bmb", "", "bmad-agent-builder", "Build Agent", "BA", "build-process", "", "Create an agent.", "anytime", "", "", "false", "output_folder", "agent skill", ""],
35+
["bmb", "bmad-bmb-module-init", "Install Module", "IM", "Install BMad Builder.", "install", "", "anytime", "", "", "false", "", "config"],
36+
["bmb", "bmad-agent-builder", "Build Agent", "BA", "Create an agent.", "build-process", "", "anytime", "", "", "false", "output_folder", "agent skill"],
3737
]
3838

3939

@@ -44,7 +44,7 @@ def test_extracts_codes(self):
4444

4545
def test_multiple_codes(self):
4646
rows = SAMPLE_ROWS + [
47-
["cis", "", "cis-skill", "CIS Skill", "CS", "run", "", "A skill.", "anytime", "", "", "false", "", "", ""],
47+
["cis", "cis-skill", "CIS Skill", "CS", "A skill.", "run", "", "anytime", "", "", "false", "", ""],
4848
]
4949
codes = extract_module_codes(rows)
5050
self.assertEqual(codes, {"bmb", "cis"})
@@ -61,7 +61,7 @@ def test_removes_matching_rows(self):
6161

6262
def test_preserves_non_matching_rows(self):
6363
mixed_rows = SAMPLE_ROWS + [
64-
["cis", "", "cis-skill", "CIS Skill", "CS", "run", "", "A skill.", "anytime", "", "", "false", "", "", ""],
64+
["cis", "cis-skill", "CIS Skill", "CS", "A skill.", "run", "", "anytime", "", "", "false", "", ""],
6565
]
6666
result = filter_rows(mixed_rows, "bmb")
6767
self.assertEqual(len(result), 1)
@@ -86,7 +86,7 @@ def test_round_trip(self):
8686
header, rows = read_csv_rows(path)
8787
self.assertEqual(len(rows), 2)
8888
self.assertEqual(rows[0][0], "bmb")
89-
self.assertEqual(rows[0][2], "bmad-bmb-module-init")
89+
self.assertEqual(rows[0][1], "bmad-bmb-module-init")
9090

9191
def test_creates_parent_dirs(self):
9292
with tempfile.TemporaryDirectory() as tmpdir:
@@ -125,7 +125,7 @@ def test_fresh_install_no_existing_target(self):
125125
def test_merge_into_existing_with_other_module(self):
126126
with tempfile.TemporaryDirectory() as tmpdir:
127127
other_rows = [
128-
["cis", "", "cis-skill", "CIS Skill", "CS", "run", "", "A skill.", "anytime", "", "", "false", "", "", ""],
128+
["cis", "cis-skill", "CIS Skill", "CS", "A skill.", "run", "", "anytime", "", "", "false", "", ""],
129129
]
130130
target_path = self._write_target(tmpdir, other_rows)
131131
source_path = self._write_source(tmpdir, SAMPLE_ROWS)
@@ -150,11 +150,11 @@ def test_anti_zombie_replaces_stale_entries(self):
150150
with tempfile.TemporaryDirectory() as tmpdir:
151151
# Existing target has old bmb entries + cis entry
152152
old_bmb_rows = [
153-
["bmb", "", "old-skill", "Old Skill", "OS", "run", "", "Old.", "anytime", "", "", "false", "", "", ""],
154-
["bmb", "", "another-old", "Another", "AO", "run", "", "Old too.", "anytime", "", "", "false", "", "", ""],
153+
["bmb", "old-skill", "Old Skill", "OS", "Old.", "run", "", "anytime", "", "", "false", "", ""],
154+
["bmb", "another-old", "Another", "AO", "Old too.", "run", "", "anytime", "", "", "false", "", ""],
155155
]
156156
cis_rows = [
157-
["cis", "", "cis-skill", "CIS Skill", "CS", "run", "", "A skill.", "anytime", "", "", "false", "", "", ""],
157+
["cis", "cis-skill", "CIS Skill", "CS", "A skill.", "run", "", "anytime", "", "", "false", "", ""],
158158
]
159159
target_path = self._write_target(tmpdir, old_bmb_rows + cis_rows)
160160
source_path = self._write_source(tmpdir, SAMPLE_ROWS)
@@ -179,7 +179,7 @@ def test_anti_zombie_replaces_stale_entries(self):
179179
self.assertEqual(module_codes.count("bmb"), 2)
180180
self.assertEqual(module_codes.count("cis"), 1)
181181
# Old skills should be gone
182-
skill_names = [r[2] for r in result_rows]
182+
skill_names = [r[1] for r in result_rows]
183183
self.assertNotIn("old-skill", skill_names)
184184
self.assertNotIn("another-old", skill_names)
185185

skills/bmad-module-builder/assets/setup-skill-template/scripts/merge-help-csv.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,18 @@
2626
# CSV header for module-help.csv
2727
HEADER = [
2828
"module",
29-
"agent-name",
30-
"skill-name",
29+
"skill",
3130
"display-name",
3231
"menu-code",
33-
"capability",
34-
"args",
3532
"description",
33+
"action",
34+
"args",
3635
"phase",
3736
"after",
3837
"before",
3938
"required",
4039
"output-location",
4140
"outputs",
42-
"", # trailing empty column from trailing comma
4341
]
4442

4543

0 commit comments

Comments
 (0)