Compare commits
3 Commits
2ae3ddfee4
...
6a56d2eb11
| Author | SHA1 | Date |
|---|---|---|
|
|
6a56d2eb11 | |
|
|
e7f80909fa | |
|
|
45b168f015 |
|
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
title: 'How to Expand BMad for Your Organization'
|
||||
description: Five customization patterns that reshape BMad without forking — agent-wide rules, workflow conventions, external publishing, template swaps, and agent roster changes
|
||||
description: Six customization patterns that reshape BMad without forking — agent-wide rules, workflow conventions, external publishing, template swaps, agent roster changes, and advanced integration patterns
|
||||
sidebar:
|
||||
order: 9
|
||||
---
|
||||
|
||||
BMad's customization surface lets an organization reshape behavior without editing installed files or forking skills. This guide walks through five recipes that cover most enterprise needs.
|
||||
BMad's customization surface lets an organization reshape behavior without editing installed files or forking skills. This guide walks through six recipes that cover most enterprise needs.
|
||||
|
||||
:::note[Prerequisites]
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ The agent adapts to whatever structure the template defines. Keep templates unde
|
|||
|
||||
## Combining Recipes
|
||||
|
||||
All five recipes compose. A realistic enterprise override for `bmad-product-brief` might set `persistent_facts` (Recipe 2), `on_complete` (Recipe 3), and `brief_template` (Recipe 4) in one file. The agent-level rule (Recipe 1) lives in a separate file under the agent's name, central config (Recipe 5) pins the shared roster and team settings, and all four apply in parallel.
|
||||
All six recipes compose. A realistic enterprise override for `bmad-product-brief` might set `persistent_facts` (Recipe 2), `on_complete` (Recipe 3), and `brief_template` (Recipe 4) in one file. The agent-level rule (Recipe 1) lives in a separate file under the agent's name, central config (Recipe 5) pins the shared roster and team settings, advanced integration patterns (Recipe 6) configure external sources and handoffs, and all layers apply in parallel.
|
||||
|
||||
```toml
|
||||
# _bmad/custom/bmad-product-brief.toml (workflow-level)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Define what to build and for whom.
|
|||
|
||||
| Workflow | Purpose | Produces |
|
||||
|-------------------------|-------------------------------------------------------------------------------------|---------------------------------------------------|
|
||||
| `bmad-prd` | Create, update, or validate a PRD — facilitated discovery, three intents in one skill | `prd.md`, `addendum.md`, `decision-log.md` |
|
||||
| `bmad-prd` | Create, update, or validate a PRD — facilitated discovery, three intents in one skill | Create/Update: `prd.md`, `addendum.md`, `decision-log.md`; Validate: `validation-report.html` + `.md` |
|
||||
| `bmad-create-ux-design` | Design user experience (when UX matters) | `ux-spec.md` |
|
||||
|
||||
:::tip[Three intents in one skill]
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ def compute_stats(findings: list[dict]) -> dict:
|
|||
failed_critical = 0
|
||||
failed_high = 0
|
||||
for f in findings:
|
||||
status = f.get("status", "n/a")
|
||||
status = (f.get("status") or "n/a").lower()
|
||||
if status in by_status:
|
||||
by_status[status] += 1
|
||||
if status == "fail":
|
||||
|
|
@ -219,8 +219,19 @@ def main(argv: list[str]) -> int:
|
|||
template_path = Path(args.template)
|
||||
output_path = Path(args.output)
|
||||
|
||||
data = json.loads(findings_path.read_text())
|
||||
template = template_path.read_text()
|
||||
try:
|
||||
data = json.loads(findings_path.read_text(encoding="utf-8"))
|
||||
except FileNotFoundError:
|
||||
print(f"error: findings file not found: {findings_path}", file=sys.stderr)
|
||||
return 1
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"error: findings file is not valid JSON ({findings_path}): {e}", file=sys.stderr)
|
||||
return 1
|
||||
try:
|
||||
template = template_path.read_text(encoding="utf-8")
|
||||
except FileNotFoundError:
|
||||
print(f"error: template file not found: {template_path}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
findings = data.get("findings", []) or []
|
||||
|
||||
|
|
@ -257,10 +268,10 @@ def main(argv: list[str]) -> int:
|
|||
}
|
||||
|
||||
rendered = string.Template(template).safe_substitute(substitutions)
|
||||
output_path.write_text(rendered)
|
||||
output_path.write_text(rendered, encoding="utf-8")
|
||||
|
||||
md_path = output_path.with_suffix(".md")
|
||||
md_path.write_text(render_markdown_report(data, findings, stats, grade))
|
||||
md_path.write_text(render_markdown_report(data, findings, stats, grade), encoding="utf-8")
|
||||
|
||||
print(json.dumps({
|
||||
"output": str(output_path),
|
||||
|
|
|
|||
Loading…
Reference in New Issue