ma-agents 3.13.2 → 3.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +3 -3
  2. package/lib/agents.js +9 -2
  3. package/lib/bmad-cache/bmb/.claude-plugin/marketplace.json +3 -3
  4. package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
  5. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-b388526edf307cf56f8e65673466cff074105abf.idx +0 -0
  6. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/{pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.pack → pack-b388526edf307cf56f8e65673466cff074105abf.pack} +0 -0
  7. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-b388526edf307cf56f8e65673466cff074105abf.rev +0 -0
  8. package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
  9. package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
  10. package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
  11. package/lib/bmad-cache/bmb/package-lock.json +2 -2
  12. package/lib/bmad-cache/bmb/package.json +1 -1
  13. package/lib/bmad-cache/bmb/samples/bmad-agent-code-coach/scripts/wake.py +78 -0
  14. package/lib/bmad-cache/bmb/samples/bmad-agent-creative-muse/scripts/wake.py +78 -0
  15. package/lib/bmad-cache/bmb/samples/bmad-agent-sentinel/scripts/wake.py +78 -0
  16. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/customize-template.toml +3 -0
  17. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/init-sanctum-template.py +11 -5
  18. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/report-shell.html +1073 -0
  19. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/wake-template.py +78 -0
  20. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/customize.toml +48 -0
  21. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/count_tokens.py +78 -0
  22. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass.py +258 -0
  23. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/process-template.py +20 -0
  24. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/render_report.py +387 -0
  25. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/assets/adapter-claude-code.json +9 -0
  26. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/aggregate_benchmark.py +236 -0
  27. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/memlog.py +197 -0
  28. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_evals.py +513 -390
  29. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_triggers.py +347 -251
  30. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/tests/test_env_isolation.py +79 -0
  31. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/tests/test_trigger_detection.py +123 -0
  32. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-validate-module.py +82 -4
  33. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/validate-module.py +55 -11
  34. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/customize-template.toml +3 -5
  35. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/report-shell.html +860 -0
  36. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/customize.toml +59 -0
  37. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/count_tokens.py +77 -0
  38. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/init_skill.py +132 -0
  39. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-prompt-metrics.py +186 -221
  40. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/quick_validate.py +117 -0
  41. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/render_report.py +387 -0
  42. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_canon_sync.py +46 -0
  43. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_count_tokens.py +180 -0
  44. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_render_report.py +171 -0
  45. package/lib/bmad-cache/cache-manifest.json +4 -4
  46. package/lib/bmad-customize/bmm-qa.customize.yaml +3 -3
  47. package/lib/bmad-extension/.claude-plugin/marketplace.json.template +3 -2
  48. package/lib/bmad-extension/skills/bmad-dev-epic/SKILL.md +101 -0
  49. package/lib/bmad-extension/skills/bmad-dev-epic/bmad-skill-manifest.yaml +3 -0
  50. package/lib/bmad-extension/skills/bmad-dev-epic/checklist.md +44 -0
  51. package/lib/bmad-extension/skills/bmad-dev-epic/customize.toml +54 -0
  52. package/lib/bmad-extension/skills/bmad-dev-epic/references/story-pipeline.md +112 -0
  53. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-01-intake.md +59 -0
  54. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-02-plan-waves.md +56 -0
  55. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-03-epic-branch.md +35 -0
  56. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-04-run-waves.md +49 -0
  57. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-05-epic-adversarial.md +31 -0
  58. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-06-release.md +57 -0
  59. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-07-report.md +40 -0
  60. package/lib/bmad-extension/skills/ma-agent-sqa/SKILL.md +3 -3
  61. package/lib/bmad-extension/skills/ma-agent-sqa/bmad-skill-manifest.yaml +1 -1
  62. package/lib/bmad-extension/skills/module-help.csv +2 -1
  63. package/lib/bmad-extension/skills/module.yaml +1 -1
  64. package/lib/bmad-extension/skills/sqa-audit/SKILL.md +2 -2
  65. package/lib/bmad-extension/skills/sqa-ieee12207/SKILL.md +3 -3
  66. package/lib/bmad-extension/skills/sqa-requirements-quality/SKILL.md +2 -2
  67. package/lib/bmad-extension-plugin/.claude-plugin/marketplace.json +4 -3
  68. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/SKILL.md +101 -0
  69. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/bmad-skill-manifest.yaml +3 -0
  70. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/checklist.md +44 -0
  71. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/customize.toml +54 -0
  72. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/references/story-pipeline.md +112 -0
  73. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-01-intake.md +59 -0
  74. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-02-plan-waves.md +56 -0
  75. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-03-epic-branch.md +35 -0
  76. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-04-run-waves.md +49 -0
  77. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-05-epic-adversarial.md +31 -0
  78. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-06-release.md +57 -0
  79. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-07-report.md +40 -0
  80. package/lib/bmad-extension-plugin/skills/ma-agent-sqa/SKILL.md +3 -3
  81. package/lib/bmad-extension-plugin/skills/ma-agent-sqa/bmad-skill-manifest.yaml +1 -1
  82. package/lib/bmad-extension-plugin/skills/module-help.csv +2 -1
  83. package/lib/bmad-extension-plugin/skills/module.yaml +1 -1
  84. package/lib/bmad-extension-plugin/skills/sqa-audit/SKILL.md +2 -2
  85. package/lib/bmad-extension-plugin/skills/sqa-ieee12207/SKILL.md +3 -3
  86. package/lib/bmad-extension-plugin/skills/sqa-requirements-quality/SKILL.md +2 -2
  87. package/lib/bmad.js +6 -1
  88. package/package.json +3 -3
  89. package/lib/.bmad-extension-plugin.build-22612-1782454014750/.claude-plugin/marketplace.json +0 -109
  90. package/lib/.bmad-extension-plugin.build-22612-1782454014750/skills/module-help.csv +0 -62
  91. package/lib/.bmad-extension-plugin.build-22612-1782454014750/skills/module.yaml +0 -20
  92. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.idx +0 -0
  93. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.rev +0 -0
  94. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/references/sample-init-sanctum.py +0 -274
  95. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/generate-html-report.py +0 -534
  96. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-execution-deps.py +0 -337
  97. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-prompt-metrics.py +0 -425
  98. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-sanctum-architecture.py +0 -385
  99. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-structure-capabilities.py +0 -482
  100. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/assets/Dockerfile +0 -29
  101. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/docker_setup.py +0 -115
  102. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/generate_report.py +0 -184
  103. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/pty_runner.py +0 -171
  104. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/utils.py +0 -260
  105. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/extract-report-json.py +0 -287
  106. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-html-report.py +0 -588
  107. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-execution-deps.py +0 -288
@@ -1,288 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Deterministic pre-pass for execution efficiency scanner.
3
-
4
- Extracts dependency graph data and execution patterns from a BMad skill
5
- so the LLM scanner can evaluate efficiency from compact structured data.
6
-
7
- Covers:
8
- - Dependency graph from skill structure
9
-
10
- - Circular dependency detection
11
- - Transitive dependency redundancy
12
- - Parallelizable stage groups (independent nodes)
13
- - Sequential pattern detection in prompts (numbered Read/Grep/Glob steps)
14
- - Subagent-from-subagent detection
15
- """
16
-
17
- # /// script
18
- # requires-python = ">=3.9"
19
- # ///
20
-
21
- from __future__ import annotations
22
-
23
- import argparse
24
- import json
25
- import re
26
- import sys
27
- from datetime import datetime, timezone
28
- from pathlib import Path
29
-
30
-
31
- def detect_cycles(graph: dict[str, list[str]]) -> list[list[str]]:
32
- """Detect circular dependencies in a directed graph using DFS."""
33
- cycles = []
34
- visited = set()
35
- path = []
36
- path_set = set()
37
-
38
- def dfs(node: str) -> None:
39
- if node in path_set:
40
- cycle_start = path.index(node)
41
- cycles.append(path[cycle_start:] + [node])
42
- return
43
- if node in visited:
44
- return
45
- visited.add(node)
46
- path.append(node)
47
- path_set.add(node)
48
- for neighbor in graph.get(node, []):
49
- dfs(neighbor)
50
- path.pop()
51
- path_set.discard(node)
52
-
53
- for node in graph:
54
- dfs(node)
55
-
56
- return cycles
57
-
58
-
59
- def find_transitive_redundancy(graph: dict[str, list[str]]) -> list[dict]:
60
- """Find cases where A declares dependency on C, but A->B->C already exists."""
61
- redundancies = []
62
-
63
- def get_transitive(node: str, visited: set | None = None) -> set[str]:
64
- if visited is None:
65
- visited = set()
66
- for dep in graph.get(node, []):
67
- if dep not in visited:
68
- visited.add(dep)
69
- get_transitive(dep, visited)
70
- return visited
71
-
72
- for node, direct_deps in graph.items():
73
- for dep in direct_deps:
74
- # Check if dep is reachable through other direct deps
75
- other_deps = [d for d in direct_deps if d != dep]
76
- for other in other_deps:
77
- transitive = get_transitive(other)
78
- if dep in transitive:
79
- redundancies.append({
80
- 'node': node,
81
- 'redundant_dep': dep,
82
- 'already_via': other,
83
- 'issue': f'"{node}" declares "{dep}" as dependency, but already reachable via "{other}"',
84
- })
85
-
86
- return redundancies
87
-
88
-
89
- def find_parallel_groups(graph: dict[str, list[str]], all_nodes: set[str]) -> list[list[str]]:
90
- """Find groups of nodes that have no dependencies on each other (can run in parallel)."""
91
- # Nodes with no incoming edges from other nodes in the set
92
- independent_groups = []
93
-
94
- # Simple approach: find all nodes at each "level" of the DAG
95
- remaining = set(all_nodes)
96
- while remaining:
97
- # Nodes whose dependencies are all satisfied (not in remaining)
98
- ready = set()
99
- for node in remaining:
100
- deps = set(graph.get(node, []))
101
- if not deps & remaining:
102
- ready.add(node)
103
- if not ready:
104
- break # Circular dependency, can't proceed
105
- if len(ready) > 1:
106
- independent_groups.append(sorted(ready))
107
- remaining -= ready
108
-
109
- return independent_groups
110
-
111
-
112
- def scan_sequential_patterns(filepath: Path, rel_path: str) -> list[dict]:
113
- """Detect sequential operation patterns that could be parallel."""
114
- content = filepath.read_text(encoding='utf-8')
115
- patterns = []
116
-
117
- # Sequential numbered steps with Read/Grep/Glob
118
- tool_steps = re.findall(
119
- r'^\s*\d+\.\s+.*?\b(Read|Grep|Glob|read|grep|glob)\b.*$',
120
- content, re.MULTILINE
121
- )
122
- if len(tool_steps) >= 3:
123
- patterns.append({
124
- 'file': rel_path,
125
- 'type': 'sequential-tool-calls',
126
- 'count': len(tool_steps),
127
- 'issue': f'{len(tool_steps)} sequential tool call steps found — check if independent calls can be parallel',
128
- })
129
-
130
- # "Read all files" / "for each" loop patterns
131
- loop_patterns = [
132
- (r'[Rr]ead all (?:files|documents|prompts)', 'read-all'),
133
- (r'[Ff]or each (?:file|document|prompt|stage)', 'for-each-loop'),
134
- (r'[Aa]nalyze each', 'analyze-each'),
135
- (r'[Ss]can (?:through|all|each)', 'scan-all'),
136
- (r'[Rr]eview (?:all|each)', 'review-all'),
137
- ]
138
- for pattern, ptype in loop_patterns:
139
- matches = re.findall(pattern, content)
140
- if matches:
141
- patterns.append({
142
- 'file': rel_path,
143
- 'type': ptype,
144
- 'count': len(matches),
145
- 'issue': f'"{matches[0]}" pattern found — consider parallel subagent delegation',
146
- })
147
-
148
- # Subagent spawning from subagent (impossible)
149
- if re.search(r'(?i)spawn.*subagent|launch.*subagent|create.*subagent', content):
150
- # Check if this file IS a subagent (non-SKILL.md, non-numbered prompt at root)
151
- if rel_path != 'SKILL.md' and not re.match(r'^\d+-', rel_path):
152
- patterns.append({
153
- 'file': rel_path,
154
- 'type': 'subagent-chain-violation',
155
- 'count': 1,
156
- 'issue': 'Subagent file references spawning other subagents — subagents cannot spawn subagents',
157
- })
158
-
159
- return patterns
160
-
161
-
162
- def scan_execution_deps(skill_path: Path) -> dict:
163
- """Run all deterministic execution efficiency checks."""
164
- # Build dependency graph from skill structure
165
- dep_graph: dict[str, list[str]] = {}
166
- prefer_after: dict[str, list[str]] = {}
167
- all_stages: set[str] = set()
168
-
169
- # Check for stage-level prompt files at skill root
170
- for f in sorted(skill_path.iterdir()):
171
- if f.is_file() and f.suffix == '.md' and f.name != 'SKILL.md':
172
- all_stages.add(f.stem)
173
-
174
- # Cycle detection
175
- cycles = detect_cycles(dep_graph)
176
-
177
- # Transitive redundancy
178
- redundancies = find_transitive_redundancy(dep_graph)
179
-
180
- # Parallel groups
181
- parallel_groups = find_parallel_groups(dep_graph, all_stages)
182
-
183
- # Sequential pattern detection across all prompt and agent files at root
184
- sequential_patterns = []
185
- for f in sorted(skill_path.iterdir()):
186
- if f.is_file() and f.suffix == '.md' and f.name != 'SKILL.md':
187
- patterns = scan_sequential_patterns(f, f.name)
188
- sequential_patterns.extend(patterns)
189
-
190
- # Also scan SKILL.md
191
- skill_md = skill_path / 'SKILL.md'
192
- if skill_md.exists():
193
- sequential_patterns.extend(scan_sequential_patterns(skill_md, 'SKILL.md'))
194
-
195
- # Build issues from deterministic findings
196
- issues = []
197
- for cycle in cycles:
198
- issues.append({
199
- 'severity': 'critical',
200
- 'category': 'circular-dependency',
201
- 'issue': f'Circular dependency detected: {" → ".join(cycle)}',
202
- })
203
- for r in redundancies:
204
- issues.append({
205
- 'severity': 'medium',
206
- 'category': 'dependency-bloat',
207
- 'issue': r['issue'],
208
- })
209
- for p in sequential_patterns:
210
- severity = 'critical' if p['type'] == 'subagent-chain-violation' else 'medium'
211
- issues.append({
212
- 'file': p['file'],
213
- 'severity': severity,
214
- 'category': p['type'],
215
- 'issue': p['issue'],
216
- })
217
-
218
- by_severity = {'critical': 0, 'high': 0, 'medium': 0, 'low': 0}
219
- for issue in issues:
220
- sev = issue['severity']
221
- if sev in by_severity:
222
- by_severity[sev] += 1
223
-
224
- status = 'pass'
225
- if by_severity['critical'] > 0:
226
- status = 'fail'
227
- elif by_severity['medium'] > 0:
228
- status = 'warning'
229
-
230
- return {
231
- 'scanner': 'execution-efficiency-prepass',
232
- 'script': 'prepass-execution-deps.py',
233
- 'version': '1.0.0',
234
- 'skill_path': str(skill_path),
235
- 'timestamp': datetime.now(timezone.utc).isoformat(),
236
- 'status': status,
237
- 'dependency_graph': {
238
- 'stages': sorted(all_stages),
239
- 'hard_dependencies': dep_graph,
240
- 'soft_dependencies': prefer_after,
241
- 'cycles': cycles,
242
- 'transitive_redundancies': redundancies,
243
- 'parallel_groups': parallel_groups,
244
- },
245
- 'sequential_patterns': sequential_patterns,
246
- 'issues': issues,
247
- 'summary': {
248
- 'total_issues': len(issues),
249
- 'by_severity': by_severity,
250
- },
251
- }
252
-
253
-
254
- def main() -> int:
255
- parser = argparse.ArgumentParser(
256
- description='Extract execution dependency graph and patterns for LLM scanner pre-pass',
257
- )
258
- parser.add_argument(
259
- 'skill_path',
260
- type=Path,
261
- help='Path to the skill directory to scan',
262
- )
263
- parser.add_argument(
264
- '--output', '-o',
265
- type=Path,
266
- help='Write JSON output to file instead of stdout',
267
- )
268
- args = parser.parse_args()
269
-
270
- if not args.skill_path.is_dir():
271
- print(f"Error: {args.skill_path} is not a directory", file=sys.stderr)
272
- return 2
273
-
274
- result = scan_execution_deps(args.skill_path)
275
- output = json.dumps(result, indent=2)
276
-
277
- if args.output:
278
- args.output.parent.mkdir(parents=True, exist_ok=True)
279
- args.output.write_text(output)
280
- print(f"Results written to {args.output}", file=sys.stderr)
281
- else:
282
- print(output)
283
-
284
- return 0
285
-
286
-
287
- if __name__ == '__main__':
288
- sys.exit(main())