Replace the regex token substitution and the line-parsed bmad-if
directives in render_skill.py with Jinja2. Templates see config,
workflow, and snapshot(); undefined names, empty entry files, and
links to omitted sources halt; every value a render reaches and the
Jinja2 version key the generation. Migrate the five rendered skills'
sources to the new forms, keep their shipped output byte-identical,
and update the validator rule and the authoring docs.
* build: declare the Python toolchain in pyproject.toml
Pin the dev environment (pytest, pytest-xdist, pyyaml, ruamel.yaml, ruff)
with uv instead of a one-line --with list in package.json. The project is
marked non-packaged: the tree itself is what gets installed, and shipped
scripts keep their inline metadata. The validate CI job now runs on uv
alone, without Node, and gains a ruff check.
* style: apply ruff to tools and skill scripts
Mechanical output of ruff check --fix and ruff format under the new
config, plus four hand edits: explicit zip strictness in setup.py and
test_sprint_status.py, an f-string for the hex colour in brain.py, and a
noqa on the sys.path-dependent import in render_skill.py. No behaviour
change; 500 tests pass.
* build: declare Python 3.11 as the floor of every shipped script
Eighteen scripts declared 3.8 or 3.10 inline while ruff targeted 3.11,
so an autofix could introduce syntax those scripts did not advertise.
The lower floors were never reachable: every skill that carried one
also runs a 3.11 hub script, and uv fetches whatever interpreter a
script asks for. All inline metadata now says 3.11, and a test keeps
the inline floors equal to requires-python and the ruff target.
Replace tools/validate-skills.js with a stdlib Python 3.11 port and rewire
validate:skills and test:skills onto it. Observable behavior is preserved,
including the JS frontmatter quirks; in-skill file walks are sorted.
Replaces tools/validate-skills.js with tools/validate_skills.py, taken from the
flat-tree work on feat/npx-skills-distribution rather than written afresh, so
the two do not diverge again. Discovery is repointed from that branch's flat
skills/ tree to src/. Behaviour is otherwise unchanged: same rule IDs, same
JSON shape, same --strict and --json flags, and the tests come across as
unittest cases run through uv, matching how the other Python tests are wired.
The three step-structure rules go away with it. STEP-01 (filename format),
STEP-06 (step frontmatter) and STEP-07 (step count) all key off a literal
steps/ directory that only two of fifty skills have — everywhere else step
files sit at the skill root — so they validated almost nothing. The catalog's
first-pass list drops from 13 rules to 10 to match, and their rule sections
are removed.
CI is unaffected: quality.yaml already provisions uv and invokes the npm
script rather than the file.