From ade7a966e96e1e197db802db4afdc187de04baaf Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 9 Aug 2026 18:25:48 -0500 Subject: [PATCH] fix(installer,skills): make uv a real requirement and stop assuming a system Python (#2704) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The installer told users uv was optional while bmad-build had already made it mandatory. uv-check.js called it "becoming the de facto standard", install-messages.yaml led with HEADS UP, and installer.js printed a Tip inside a box titled "BMAD is ready to use!" — while bmad-build and bmad-build-auto HALT on activation without `uv run`. The probe's result was discarded (`await checkUvEnvironment();`), so nothing branched on it. Messaging now names the consequence, and the post-install summary repeats the warning when it applies — the pre-install probe fires before every prompt, so by then it is far up the scrollback. Still warn-don't-block: core-only, docs-only, and CI installs never render a skill, so a missing uv must not fail the run. Adds a python3 probe used only when uv is absent, since that is the only case where the interpreter on PATH matters. It reports whether the direct-interpreter skills still work (3.11+) or nothing Python-backed will (below 3.11, or no python3 at all). Separately, 25 call sites still ran resolve_customization.py under a bare `python3`. That script requires 3.11+ for tomllib, so on macOS without Homebrew or Ubuntu 22.04 they fell through to their "if the script fails" path and hand-merged the TOML in-context — no error surfaced. All 25 now use `uv run`, which provisions a matching interpreter from the script's own requires-python. Four more spawned Python purely to open an HTML file: python3 -c "import webbrowser, pathlib; webbrowser.open(...)" Replaced with the platform opener bmad-brainstorming already uses — open / xdg-open / start. src/ now contains no bare Python invocation at all, so "Python 3.11+" leaves the user contract: uv provisions its own. docs/how-to/customize-bmad.md described a transition that this ends. Test suite 46 grows from 12 to 29 assertions: Python parsing, the 3.11 boundary in both directions, that uv-present skips the python3 probe, and all three missing-uv sub-branches. --- docs/how-to/customize-bmad.md | 6 +- .../agents/bmad-agent-analyst/SKILL.md | 2 +- .../agents/bmad-agent-architect/SKILL.md | 2 +- src/bmm-skills/agents/bmad-agent-dev/SKILL.md | 2 +- src/bmm-skills/agents/bmad-agent-pm/SKILL.md | 2 +- .../agents/bmad-agent-ux-designer/SKILL.md | 2 +- .../bmad-create-epics-and-stories/SKILL.md | 2 +- .../steps/step-04-final-validation.md | 2 +- .../plan/bmad-prd/references/validate.md | 6 +- src/bmm-skills/plan/bmad-prfaq/SKILL.md | 2 +- .../plan/bmad-prfaq/references/verdict.md | 2 +- .../plan/bmad-ux/assets/color-themes.md | 2 +- .../plan/bmad-ux/references/creative-tools.md | 2 +- .../plan/bmad-ux/references/validate.md | 2 +- .../ship/bmad-checkpoint-preview/SKILL.md | 2 +- .../bmad-checkpoint-preview/step-05-wrapup.md | 2 +- src/bmm-skills/ship/bmad-code-review/SKILL.md | 2 +- .../bmad-code-review/steps/step-04-present.md | 2 +- .../ship/bmad-correct-course/SKILL.md | 4 +- .../ship/bmad-qa-generate-e2e-tests/SKILL.md | 4 +- .../bmad-create-architecture/SKILL.md | 2 +- .../v6-shims/bmad-create-prd/SKILL.md | 2 +- .../v6-shims/bmad-create-story/SKILL.md | 4 +- .../v6-shims/bmad-dev-story/SKILL.md | 4 +- .../v6-shims/bmad-edit-prd/SKILL.md | 2 +- .../v6-shims/bmad-validate-prd/SKILL.md | 2 +- test/test-installation-components.js | 67 ++++++-- tools/installer/core/installer.js | 20 ++- tools/installer/core/uv-check.js | 146 +++++++++++++++--- tools/installer/install-messages.yaml | 5 +- tools/installer/ui.js | 16 +- 31 files changed, 243 insertions(+), 79 deletions(-) diff --git a/docs/how-to/customize-bmad.md b/docs/how-to/customize-bmad.md index 8ae0e7c16..7fa74f4ee 100644 --- a/docs/how-to/customize-bmad.md +++ b/docs/how-to/customize-bmad.md @@ -22,7 +22,7 @@ The `bmad-customize` skill is a guided authoring helper for the **per-skill agen :::note[Prerequisites] - BMad installed in your project (see [How to Install BMad](./install-bmad.md)) -- A way to run the resolver script — BMad is standardizing on `uv` (`uv run`, which provisions Python for you); a plain `python3` 3.11+ on your PATH still works during the transition. The script uses only stdlib `tomllib`, so there's nothing to `pip install`. +- [`uv`](https://docs.astral.sh/uv/) on your PATH — BMad runs the resolver script with `uv run`, and uv provisions a suitable Python for you, so you don't need to install one yourself. The script uses only stdlib `tomllib`, so there's nothing to `pip install`. - A text editor for TOML files ::: @@ -201,7 +201,7 @@ persistent_facts = [ ## How Resolution Works -On activation, the agent's SKILL.md runs a shared Python script that does the three-layer merge and returns the resolved block as JSON. The script uses only the Python standard library's `tomllib` module (no external dependencies). BMad is standardizing on `uv run` to invoke these scripts (uv provisions a suitable Python for you); a plain `python3` still works during the transition: +On activation, the agent's SKILL.md runs a shared Python script that does the three-layer merge and returns the resolved block as JSON. The script uses only the Python standard library's `tomllib` module (no external dependencies). BMad invokes it with `uv run`, which provisions a suitable Python for you: ```bash uv run {project-root}/_bmad/scripts/resolve_customization.py \ @@ -209,7 +209,7 @@ uv run {project-root}/_bmad/scripts/resolve_customization.py \ --key agent ``` -**Requirements**: Python 3.11+ (earlier versions don't include `tomllib`); nothing to `pip install`. Running via `uv run` is the going-forward standard — uv resolves a suitable interpreter for you. If you run it with `python3` directly during the transition, check your version with `python3 --version`: some platforms (macOS without Homebrew, Ubuntu 22.04) default `python3` to 3.10 or earlier, so you may need to install 3.11+ separately. +**Requirements**: `uv`, and nothing to `pip install`. The script declares `requires-python = ">=3.11"` in its own header (earlier versions don't include `tomllib`), and `uv run` reads that and resolves a matching interpreter — so whatever `python3` resolves to on your PATH doesn't matter. If you'd rather invoke it by hand with `python3`, check your version first: some platforms (macOS without Homebrew, Ubuntu 22.04) default `python3` to 3.10 or earlier. `--skill` points at the skill's installed directory (where `customize.toml` lives). The skill name is derived from the directory's basename, and the script looks up `_bmad/custom/{skill-name}.toml` and `{skill-name}.user.toml` automatically. diff --git a/src/bmm-skills/agents/bmad-agent-analyst/SKILL.md b/src/bmm-skills/agents/bmad-agent-analyst/SKILL.md index c672058eb..e3fcb19c7 100644 --- a/src/bmm-skills/agents/bmad-agent-analyst/SKILL.md +++ b/src/bmm-skills/agents/bmad-agent-analyst/SKILL.md @@ -20,7 +20,7 @@ You are Mary, the Business Analyst. You bring deep expertise in market research, ### Step 1: Resolve the Agent Block -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` **If the script fails**, resolve the `agent` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver: diff --git a/src/bmm-skills/agents/bmad-agent-architect/SKILL.md b/src/bmm-skills/agents/bmad-agent-architect/SKILL.md index b5807ba6e..3391d4bc6 100644 --- a/src/bmm-skills/agents/bmad-agent-architect/SKILL.md +++ b/src/bmm-skills/agents/bmad-agent-architect/SKILL.md @@ -20,7 +20,7 @@ You are Winston, the System Architect. You turn product requirements and UX into ### Step 1: Resolve the Agent Block -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` **If the script fails**, resolve the `agent` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver: diff --git a/src/bmm-skills/agents/bmad-agent-dev/SKILL.md b/src/bmm-skills/agents/bmad-agent-dev/SKILL.md index 22d158bfe..8fc59dceb 100644 --- a/src/bmm-skills/agents/bmad-agent-dev/SKILL.md +++ b/src/bmm-skills/agents/bmad-agent-dev/SKILL.md @@ -20,7 +20,7 @@ You are Amelia, the Senior Software Engineer. You execute approved stories with ### Step 1: Resolve the Agent Block -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` **If the script fails**, resolve the `agent` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver: diff --git a/src/bmm-skills/agents/bmad-agent-pm/SKILL.md b/src/bmm-skills/agents/bmad-agent-pm/SKILL.md index accf47d34..145433470 100644 --- a/src/bmm-skills/agents/bmad-agent-pm/SKILL.md +++ b/src/bmm-skills/agents/bmad-agent-pm/SKILL.md @@ -20,7 +20,7 @@ You are John, the Product Manager. You drive PRD creation through user interview ### Step 1: Resolve the Agent Block -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` **If the script fails**, resolve the `agent` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver: diff --git a/src/bmm-skills/agents/bmad-agent-ux-designer/SKILL.md b/src/bmm-skills/agents/bmad-agent-ux-designer/SKILL.md index f2ee265e8..3c33bedd3 100644 --- a/src/bmm-skills/agents/bmad-agent-ux-designer/SKILL.md +++ b/src/bmm-skills/agents/bmad-agent-ux-designer/SKILL.md @@ -20,7 +20,7 @@ You are Sally, the UX Designer. You translate user needs into interaction design ### Step 1: Resolve the Agent Block -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key agent` **If the script fails**, resolve the `agent` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver: diff --git a/src/bmm-skills/plan/bmad-create-epics-and-stories/SKILL.md b/src/bmm-skills/plan/bmad-create-epics-and-stories/SKILL.md index a97bc2404..e822e6a68 100644 --- a/src/bmm-skills/plan/bmad-create-epics-and-stories/SKILL.md +++ b/src/bmm-skills/plan/bmad-create-epics-and-stories/SKILL.md @@ -51,7 +51,7 @@ This uses **step-file architecture** for disciplined execution: ### Step 1: Resolve the Workflow Block -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow` **If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver: diff --git a/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-04-final-validation.md b/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-04-final-validation.md index 6d2dd9dfa..a943f3d8f 100644 --- a/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-04-final-validation.md +++ b/src/bmm-skills/plan/bmad-create-epics-and-stories/steps/step-04-final-validation.md @@ -138,6 +138,6 @@ Upon Completion of task output: offer to answer any questions about the Epics an ## On Complete -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting. diff --git a/src/bmm-skills/plan/bmad-prd/references/validate.md b/src/bmm-skills/plan/bmad-prd/references/validate.md index f9bb8cd68..d34e8e342 100644 --- a/src/bmm-skills/plan/bmad-prd/references/validate.md +++ b/src/bmm-skills/plan/bmad-prd/references/validate.md @@ -41,11 +41,11 @@ Once every selected reviewer has returned, the parent synthesizes one consolidat - **Footer.** Rubric path, ISO timestamp. 3. Write the filled HTML to `{doc_workspace}/validation-report.html`. 4. Write the markdown twin to `{doc_workspace}/validation-report.md` (same content, grouped by severity rather than by dimension — see format below; this is the canonical form for downstream re-reading). -5. Open the HTML in the default browser: +5. Open the HTML in the default browser with the platform opener — `open` on macOS, `xdg-open` on Linux, `start ""` on Windows — double-quoting the path: ```bash - python3 -c "import webbrowser, pathlib; webbrowser.open(pathlib.Path('{doc_workspace}/validation-report.html').resolve().as_uri())" + open "{doc_workspace}/validation-report.html" ``` - Skip the open step in headless mode (see `references/headless.md`). + If the command fails, don't retry with another opener: tell the user the file path and move on. Skip the open step in headless mode (see `references/headless.md`). ### Markdown twin format diff --git a/src/bmm-skills/plan/bmad-prfaq/SKILL.md b/src/bmm-skills/plan/bmad-prfaq/SKILL.md index 7cee7790d..41dd3af51 100644 --- a/src/bmm-skills/plan/bmad-prfaq/SKILL.md +++ b/src/bmm-skills/plan/bmad-prfaq/SKILL.md @@ -30,7 +30,7 @@ The PRFAQ forces customer-first clarity: write the press release announcing the ### Step 1: Resolve the Workflow Block -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow` **If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver: diff --git a/src/bmm-skills/plan/bmad-prfaq/references/verdict.md b/src/bmm-skills/plan/bmad-prfaq/references/verdict.md index 5d3a09287..caf4c8172 100644 --- a/src/bmm-skills/plan/bmad-prfaq/references/verdict.md +++ b/src/bmm-skills/plan/bmad-prfaq/references/verdict.md @@ -78,6 +78,6 @@ purpose: "Token-efficient context for downstream PRD creation" This is the terminal stage. If the user wants to revise, loop back to the relevant stage. Otherwise, the workflow is done. -Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` +Run: `uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting. diff --git a/src/bmm-skills/plan/bmad-ux/assets/color-themes.md b/src/bmm-skills/plan/bmad-ux/assets/color-themes.md index 31169edc3..2b23b466d 100644 --- a/src/bmm-skills/plan/bmad-ux/assets/color-themes.md +++ b/src/bmm-skills/plan/bmad-ux/assets/color-themes.md @@ -6,4 +6,4 @@ Each variation: header (name + one-line emotional register), token chips for eve Inline CSS only, system font stack, no JS, no network. Document concrete hex values in `