Skip to content

Commit d97d675

Browse files
authored
Standardize builders: runtime memlog + uv script invocations (#98)
* Standardize builders on runtime-installed memlog Reference {project-root}/_bmad/scripts/memlog.py (sourced from bmm core src/scripts) instead of bundling a per-skill copy, in bmad-workflow-builder and bmad-agent-builder. Remove the bundled memlog.py copies and the workflow-builder memlog test; rewrite the working-state teaching so produced skills reference the runtime CLI rather than copying it in. * Standardize script invocations on uv run Replace `python3 <script>` with `uv run <script>` across bmad-workflow-builder and bmad-agent-builder: prompt-facing invocations, script usage strings, and the emitted init-sanctum/wake template usage. Align workflow-builder's script-standards.md to mandate `uv run` for all scripts, matching agent-builder. Left as-is: `#!/usr/bin/env python3` shebangs (stdlib-script convention per script-standards), "runs under a bare python3" capability notes, and `python3 -m pytest` test-runner docstrings.
1 parent 4156901 commit d97d675

20 files changed

Lines changed: 36 additions & 679 deletions

skills/bmad-agent-builder/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ The builder produces agents along one gradient surfaced as feature decisions, no
2727

2828
## On Activation
2929

30-
1. **Resolve customization.** Run `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` and apply the resolved `{agent.*}` values throughout the session. On failure, read `{skill-root}/customize.toml` directly and use defaults. Then execute each entry in `{agent.activation_steps_prepend}` in order, and treat every entry in `{agent.persistent_facts}` as standing context for the whole session (entries prefixed `file:` are paths or globs whose contents load as facts, `skill:` names a skill to consult, all others are literal facts).
30+
1. **Resolve customization.** Run `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` and apply the resolved `{agent.*}` values throughout the session. On failure, read `{skill-root}/customize.toml` directly and use defaults. Then execute each entry in `{agent.activation_steps_prepend}` in order, and treat every entry in `{agent.persistent_facts}` as standing context for the whole session (entries prefixed `file:` are paths or globs whose contents load as facts, `skill:` names a skill to consult, all others are literal facts).
3131

3232
2. **Detect intent.** If `--headless` or `-H` is present, set `{headless_mode}=true` for every sub-prompt; this makes the builder non-interactive and is not the Pulse Mode a built autonomous agent runs at its own runtime. Otherwise read the invocation for whether the user wants to Create, Edit, or Analyze, and which agent they mean.
3333

3434
3. **Load config.** Read `{project-root}/_bmad/config.yaml` and `{project-root}/_bmad/config.user.yaml` (root and bmb section), falling back to `{project-root}/_bmad/bmb/config.yaml`. If none exist and `bmad-bmb-setup` is available, mention it. Resolve and apply throughout (defaults in parens): `{user_name}` (null), `{communication_language}` (user or system default), `{document_output_language}` (user or system default), and `{bmad_builder_output_folder}` (`{project-root}/skills`, where new agents are created; existing agents keep their own path).
3535

3636
4. **Open the floor (interactive only).** Before any structured questions or routing, invite the user to share everything in mind: who the agent is, how it should make them feel, the core outcome, examples, half-formed ideas, paths to existing agents or artifacts. Adapt the invitation to what they already gave you, then one soft "anything else?" surfaces what they almost forgot. This dump replaces most downstream questioning, so let it run. Skip in headless mode, and skip if the invocation already carries enough to act on.
3737

38-
5. **Resume detection.** Once a target agent is identified, glob `{target-agent-path}/.memlog.md`. If one exists, read it once in full to rebuild the prior session's state, then continue append-only through `scripts/memlog.py`. This `.memlog.md` is the builder's process log and is separate from the agent's sanctum. In headless mode, resume automatically.
38+
5. **Resume detection.** Once a target agent is identified, glob `{target-agent-path}/.memlog.md`. If one exists, read it once in full to rebuild the prior session's state, then continue append-only through `{project-root}/_bmad/scripts/memlog.py`. This `.memlog.md` is the builder's process log and is separate from the agent's sanctum. In headless mode, resume automatically.
3939

4040
6. **Route to the intent.** Pick the path below from the resolved intent and load only that file. Once the intent is routed, execute each entry in `{agent.activation_steps_append}` in order before the loop begins.
4141

skills/bmad-agent-builder/assets/SKILL-template-bootloader.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The full discipline (what goes where, the two-tier flow from session log to MEMO
5555
{if-customizable}
5656
### Resolve the Agent Block
5757

58-
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
58+
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
5959

6060
If the script fails, resolve the `agent` block yourself by reading these three files in base → team → user order and applying structural merge rules: `{skill-root}/customize.toml`, `{project-root}/_bmad/custom/{skill-name}.toml`, `{project-root}/_bmad/custom/{skill-name}.user.toml`. Scalars override, tables deep-merge, arrays of tables keyed by `code`/`id` replace matching entries and append new ones, all other arrays append.
6161

skills/bmad-agent-builder/assets/SKILL-template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ description: { skill-description } # [4-6 word summary]. [trigger phrases]
4242
{if-customizable}
4343
### Step 1: Resolve the Agent Block
4444

45-
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
45+
Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent`
4646

4747
If the script fails, resolve the `agent` block yourself by reading these three files in base → team → user order and applying structural merge rules: `{skill-root}/customize.toml`, `{project-root}/_bmad/custom/{skill-name}.toml`, `{project-root}/_bmad/custom/{skill-name}.user.toml`. Scalars override, tables deep-merge, arrays of tables keyed by `code`/`id` replace matching entries and append new ones, all other arrays append.
4848

skills/bmad-agent-builder/assets/init-sanctum-template.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
touches.
1818
1919
Usage:
20-
python3 init-sanctum.py <project-root> <skill-path>
20+
uv run init-sanctum.py <project-root> <skill-path>
2121
2222
project-root: The root of the project (where _bmad/ lives)
2323
skill-path: Path to the skill directory (where SKILL.md, references/, assets/ live)
@@ -187,7 +187,7 @@ def substitute_vars(content: str, variables: dict) -> str:
187187

188188
def main():
189189
if len(sys.argv) < 3:
190-
print("Usage: python3 init-sanctum.py <project-root> <skill-path>")
190+
print("Usage: uv run init-sanctum.py <project-root> <skill-path>")
191191
sys.exit(1)
192192

193193
project_root = Path(sys.argv[1]).resolve()

skills/bmad-agent-builder/assets/wake-template.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
This loads runtime memory only. It never reads or writes config or customize.toml.
1515
1616
Usage:
17-
python3 wake.py <project-root> [--pulse]
17+
uv run wake.py <project-root> [--pulse]
1818
1919
project-root: The root of the project (where _bmad/ lives)
2020
"""

skills/bmad-agent-builder/references/build-process.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ The dump tells you what the user pictured; offer what they did not. Before draft
2525

2626
## Capture into the memlog throughout
2727

28-
As decisions and directions land, write them to `{target-agent-path}/.memlog.md` through `scripts/memlog.py`: `init --path {target-agent-path}/.memlog.md` once when the target is named, then `append --path {target-agent-path}/.memlog.md --type <decision|direction|assumption|gap|note|event> --text "..."` as things happen. For a new agent, propose a kebab-case name when the user did not give one; renaming later is a logged decision, not a redo. This `.memlog.md` is the builder's process trace beside the built agent's SKILL.md, never the agent's sanctum — a memlog entry records a build decision, sanctum content is the agent's living runtime state, and neither ever holds the other's material. Capture as you go so the reasoning is caught while fresh, because the memlog is the resume source and the trail you walk with the user at handoff.
28+
As decisions and directions land, write them to `{target-agent-path}/.memlog.md` through `{project-root}/_bmad/scripts/memlog.py`: `init --path {target-agent-path}/.memlog.md` once when the target is named, then `append --path {target-agent-path}/.memlog.md --type <decision|direction|assumption|gap|note|event> --text "..."` as things happen. For a new agent, propose a kebab-case name when the user did not give one; renaming later is a logged decision, not a redo. This `.memlog.md` is the builder's process trace beside the built agent's SKILL.md, never the agent's sanctum — a memlog entry records a build decision, sanctum content is the agent's living runtime state, and neither ever holds the other's material. Capture as you go so the reasoning is caught while fresh, because the memlog is the resume source and the trail you walk with the user at handoff.
2929

3030
## Write the minimal outcome-driven version first
3131

@@ -69,7 +69,7 @@ Confirm the agent passes its own leanness bar before handoff, because the builde
6969

7070
Every agent shares one output tree. The archetype changes which parts are present and the SKILL.md weight, captured in the delta table below rather than three separate trees.
7171

72-
Emit each file from its matching template in this builder's `assets/`, applying `references/template-substitution-rules.md` for tokens, conditionals, and template selection — deterministically, via `python3 scripts/process-template.py <template> -o <dest> --var key=value... --true <condition>...` (one `--var` per token, one `--true` per conditional that holds). The templates are the single source for every emitted file, including `assets/init-sanctum-template.py`, `assets/wake-template.py`, `assets/memory-guidance-template.md`, and the two First Breath templates. The files whose content you author rather than substitute have guidance — load each at the moment you author that file, not before: `references/mission-writing-guidance.md` for the species mission, `references/standing-order-guidance.md` for CREED standing orders, `references/first-breath-adaptation-guidance.md` for deriving the First Breath territories, and `references/sample-capability-authoring.md` for the emitted capability-authoring.md.
72+
Emit each file from its matching template in this builder's `assets/`, applying `references/template-substitution-rules.md` for tokens, conditionals, and template selection — deterministically, via `uv run scripts/process-template.py <template> -o <dest> --var key=value... --true <condition>...` (one `--var` per token, one `--true` per conditional that holds). The templates are the single source for every emitted file, including `assets/init-sanctum-template.py`, `assets/wake-template.py`, `assets/memory-guidance-template.md`, and the two First Breath templates. The files whose content you author rather than substitute have guidance — load each at the moment you author that file, not before: `references/mission-writing-guidance.md` for the species mission, `references/standing-order-guidance.md` for CREED standing orders, `references/first-breath-adaptation-guidance.md` for deriving the First Breath territories, and `references/sample-capability-authoring.md` for the emitted capability-authoring.md.
7373

7474
```
7575
{agent-name}/

skills/bmad-agent-builder/references/quality-analysis.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ Confirm the agent is resolvable at `{target-agent-path}` and that a `SKILL.md` i
2828
Run the pre-pass once, before any lens sees the agent, so every lens reads a compact classification and token picture instead of re-deriving it from raw text:
2929

3030
```bash
31-
python3 scripts/prepass.py {target-agent-path}
32-
python3 scripts/scan-path-standards.py {target-agent-path}
33-
python3 scripts/scan-scripts.py {target-agent-path}
31+
uv run scripts/prepass.py {target-agent-path}
32+
uv run scripts/scan-path-standards.py {target-agent-path}
33+
uv run scripts/scan-scripts.py {target-agent-path}
3434
```
3535

3636
The two lint scanners return deterministic findings as JSON; carry their entries straight into the merged findings list with ids `lint-<n>`, keeping their severities. They are facts, not judgment, so no lens re-derives them.
@@ -143,7 +143,7 @@ Rules:
143143
Write the island object to `{run-folder}/findings.json` and render:
144144

145145
```bash
146-
python3 scripts/render_report.py {run-folder}/findings.json --shell assets/report-shell.html -o {run-folder}/agent-analysis-report.html --md {run-folder}/agent-analysis-report.md
146+
uv run scripts/render_report.py {run-folder}/findings.json --shell assets/report-shell.html -o {run-folder}/agent-analysis-report.html --md {run-folder}/agent-analysis-report.md
147147
```
148148

149149
If the script refuses, fix `findings.json` and re-run; never hand-edit the HTML. Open the HTML report for the user — it is the deliverable of Analyze; do not replace it with a chat summary of the findings. The shell fails loud: a malformed island shows a visible banner, never a blank page, and an empty findings array renders an explicit no-findings panel, so a clean agent still produces a real report.
@@ -153,7 +153,7 @@ If the script refuses, fix `findings.json` and re-run; never hand-edit the HTML.
153153
Append one memlog event carrying the grade (init the memlog first if `{target-agent-path}/.memlog.md` does not exist):
154154

155155
```bash
156-
python3 scripts/memlog.py append --path {target-agent-path}/.memlog.md --type event --text "analyze: grade <grade>, <c> critical / <h> high / <m> medium / <l> low, report .analysis/<timestamp>/agent-analysis-report.html"
156+
uv run {project-root}/_bmad/scripts/memlog.py append --path {target-agent-path}/.memlog.md --type event --text "analyze: grade <grade>, <c> critical / <h> high / <m> medium / <l> low, report .analysis/<timestamp>/agent-analysis-report.html"
157157
```
158158

159159
## Present

skills/bmad-agent-builder/references/template-substitution-rules.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Template Substitution Rules
22

3-
The SKILL-template provides a minimal skeleton: frontmatter, overview, agent identity sections, memory, and the activation spine. The bootloader carries no standalone config-load step — `init-sanctum` bakes config into the sanctum, so wake.py loads it as part of the identity. Everything beyond the skeleton is crafted by the builder based on what was learned during discovery. Apply these rules deterministically via `python3 scripts/process-template.py <template> -o <dest> --var key=value... --true <condition>...` — one `--var` per token, one `--true` per conditional that holds. The script fails (exit 3) on any leftover `{if-...}` marker and reports remaining `{token}` placeholders as `tokens_remaining` for you to judge against the runtime-token set.
3+
The SKILL-template provides a minimal skeleton: frontmatter, overview, agent identity sections, memory, and the activation spine. The bootloader carries no standalone config-load step — `init-sanctum` bakes config into the sanctum, so wake.py loads it as part of the identity. Everything beyond the skeleton is crafted by the builder based on what was learned during discovery. Apply these rules deterministically via `uv run scripts/process-template.py <template> -o <dest> --var key=value... --true <condition>...` — one `--var` per token, one `--true` per conditional that holds. The script fails (exit 3) on any leftover `{if-...}` marker and reports remaining `{token}` placeholders as `tokens_remaining` for you to judge against the runtime-token set.
44

55
## Frontmatter
66

0 commit comments

Comments
 (0)