basic BMAD setup
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# Lens: architecture
|
||||
|
||||
Lane: structure and progressive disclosure, per `lenses/standards.md` and the canon. The bar: the entry carries only what every route needs; everything the skill promises exists and resolves.
|
||||
|
||||
- `skill_md_tokens` against what each route loads: branch content in `SKILL.md`, or a reference smaller than its pointer. High past about 800 tokens in a plain skill, or 1,200 in an agent, with a carvable section, else medium. A small skill in one file with no references is the right shape, not a gap. The budget is the entry's; a large workflow carved so that a run loads only its branch is right-sized at any total, and a large one loaded whole is not.
|
||||
- A reference loading another reference, or leaning on "as described above": high; it breaks when the entry drops out.
|
||||
- A router with one branch, or branches of a line each: medium; inline it.
|
||||
- Content duplicated across files, or a fact restated across sections: medium.
|
||||
- A route or step file loaded ahead of its branch: high; the model pays for text it may never need.
|
||||
- `path_findings` that hold up: a path that does not resolve, a path into another skill, a bare `scripts/` call. High, critical if activation depends on it.
|
||||
- A pattern over-applied (parallel reviewers on a one-file transform, a memlog on a one-shot, a menu on a one-job skill): medium; say what removing it loses. A multi-turn build with no state across turns: medium.
|
||||
- Agent (`shape_hint` is `agent` or `memory-agent`): every `[[agent.menu]]` item resolves to an installed skill, a `references/<capability>.md` that exists, or an inline prompt that is the whole instruction; one pointing at a missing file is high. A capability file holding nothing the persona and one sentence would not supply: low; recommend inlining it. Overlapping capabilities, one job split across several, or a persona promising what no capability delivers: medium.
|
||||
- `bmod_kind` is `none` while the skill ships `customize.toml` or calls `_bmad/scripts`: wired to BMad and registered nowhere, so help, setup and update checks never see it. Critical when the read-back registered it; not a finding when the read-back chose a plain skill. `invalid`: critical, `bmad` reports the file as a problem.
|
||||
- Memory agent: the sanctum seeds the shape ships in `assets/` and the wake and init scripts in `scripts/`; a missing one is critical, the agent cannot wake. Sanctum content sitting in `SKILL.md`: high. Memory kept as one growing file loaded at waking, a token guardrail that forces pruning, or an index the agent must update by hand: high; memory is small files by subject that load when reached, and the map is generated. A bootloader or First Breath reading the owner's name or language from config: high; they are learned in the first exchange.
|
||||
|
||||
Not flagged: a thin memory-agent `SKILL.md` (thin is the design); the identity files loaded whole on waking; branch lines too small to carve; the other lenses' lanes.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Lens contract
|
||||
|
||||
The return mechanics every lens shares.
|
||||
|
||||
Input: the pre-pass JSON (`skill`, `shape_hint`, `files[{path, tokens, kind}]`, `skill_md_tokens`, `total_tokens`, `has_customize`, `has_scripts`, `scripts[{path, has_pep723, has_test}]`, `description_chars`, `has_use_when`, `frontmatter_ok`, `bmod_kind`, `path_findings`, `script_findings`), the target path, and the lens file. Read the metrics first, then every file in `files[]` whose `kind` is `entry` or `prompt`, and any `asset` a model will read as text. The lens covers the whole skill, not `SKILL.md`; a finding names the file it is in.
|
||||
|
||||
Return exactly this JSON in-context, never as a file:
|
||||
|
||||
```json
|
||||
{
|
||||
"lens": "<lens name>",
|
||||
"verdict": "<one line for this lens>",
|
||||
"findings": [
|
||||
{
|
||||
"id": "<lens>-<n>",
|
||||
"severity": "critical | high | medium | low",
|
||||
"title": "<short>",
|
||||
"location": "<file:region>",
|
||||
"evidence": "<what was observed>",
|
||||
"recommendation": "<the fix>"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `id` numbers within the lens (`leanness-1`, `leanness-2`) so findings stay traceable.
|
||||
- The leanness lens alone adds `proposed_smallest` and `predicted_delta`.
|
||||
- An empty `findings` array with a passing verdict is valid. Padding is worse than silence.
|
||||
- Findings are advice to the user, never a gate; the gates are the validators and the trigger eval.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Lens: customization
|
||||
|
||||
Lane: the `customize.toml` surface and its wiring, per `lenses/standards.md`. The bar: every declared value reaches the place it changes; every value a team would override is declared.
|
||||
|
||||
- Persona keys (`identity`, `communication_style`, `principles`) in `[workflow]`, or a skill's scalars in `[agent]`: high; the skill wants to be an agent, or the reverse.
|
||||
- Not resolved: no `resolve_customization.py` call in activation, or `{workflow.*}` and `{agent.*}` tokens naming no key. High; overrides never reach the model.
|
||||
- Declared and hardcoded: the table declares a scalar the body hardcodes. High; every override is a silent no-op.
|
||||
- Hardcoded values a team would override (`<purpose>_output_path`, a template path, a completion hook): low each, medium at two or more.
|
||||
- Arrays of tables without `code` or `id`, or mixing the two: medium; the resolver can only append.
|
||||
- Boolean toggles: one medium, three or more high; a switch means the author never decided.
|
||||
- Old-format config (`module.yaml`, `module-help.csv`, `_bmad/config.yaml`), installer questions, a settings concept in the skill, or config read other than via `resolve_config.py`: high.
|
||||
- The skill writing under `_bmad/custom/`, merging `customize.toml` with override files itself, or carrying its own reader for when `_bmad/` is absent: high. The resolver reads, `bmad-customize` writes, setup installs; `script_findings` carries `custom-io` for the script side. Users who will change a value and no line telling them to invoke `bmad-customize`: low.
|
||||
- Jinja where `SKILL.md` does not call `render_skill.py`: high; it reaches the model verbatim. In a rendered skill, `config.*` or `workflow.*` in a file named "template": high.
|
||||
- Agent (`shape_hint` is `agent` or `memory-agent`): `[agent]` missing `name`, `title` or `icon`, or a menu item with both or neither of `skill` and `prompt`: high. A memory agent's `[agent]` duplicating its sanctum: medium; two selves drift.
|
||||
|
||||
Not flagged: a line telling the user to invoke `bmad-customize`; an empty `persistent_facts` (shipped skills carry none); `name` and `title` being fixed; reading project config at activation; a skill with no `customize.toml` and nothing a team would change.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Lens: determinism
|
||||
|
||||
Lane: the boundary between script and prose. The bar: a script does work with one right answer per input; prose does work that turns on meaning. A line crossing either way is a defect.
|
||||
|
||||
- Prose doing work a unit test could check: parsing, counting, path resolution, rendering a template, validating structure, diffing. The signal verbs: validate, count, extract, convert, compare, scan for, check structure, list all, diff. High when paid on every invocation, medium when occasional and cheap. Name the script and its interface.
|
||||
- Prose reading raw files to pull out a few facts (frontmatter values, token counts, inventories) where a pre-pass script could hand the model compact JSON: medium, high for large files.
|
||||
- Scripts in `scripts[]` with `has_pep723` or `has_test` false, or without `--help`: medium each. `script_findings` carries the detail; cite it, do not re-derive it.
|
||||
- A script that defers errors to the model: swallows an exception, warns and exits 0, or returns partial output with no reason. High; the model will treat it as success.
|
||||
- A script deciding meaning: a regex or string match classifying intent, tone or quality rather than locating a delimiter. Critical when it gates later behavior, high otherwise; it breaks when the phrasing shifts.
|
||||
- Memory agent (`shape_hint` is `memory-agent`): prose maintaining an index of memory files, counting or sorting entries, or checking the sanctum's structure, when `wake.py` generates the map: medium. The model's tokens go to what to remember, not bookkeeping.
|
||||
- A transcript or session log in hand: the same helper re-derived turn after turn is the strongest script signal. High; name the script that does it once.
|
||||
|
||||
Not flagged: judgment on meaning, tone, ambiguity or severity; persona; a one-off operation cheaper to say than to script; work the pre-pass already did.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Lens: leanness
|
||||
|
||||
Lane: whether every line beats its own absence, and whether what survives is a goal. The bar is `canon.md`, applied line by line; cite its tests, do not restate them.
|
||||
|
||||
- Core-test failures: lines a capable model follows unprompted. "Make sure", "don't forget", templates that teach markdown, mechanics of a tool the model drives fluently, scoring formulas for judgment. Low for a line or two, high for a section.
|
||||
- Explanation wrapped around an instruction that survives truncation: low or medium.
|
||||
- Meta-explanation of the system to itself, negative space ("this no longer does"), facts restated across sections: medium.
|
||||
- Numbered lists that are not sequences: independent steps the model will march through. Medium; the recommendation holds the goal sentence that replaces them. A sequence guarding a named failure stays.
|
||||
- ALL-CAPS MUST, ALWAYS, NEVER and stacked imperatives: medium; recommend the failure the rule prevents, in plain words.
|
||||
- A stripped why: a non-obvious rule with no reason, so it cannot reach the unforeseen case. Medium; under-writing, not leanness.
|
||||
- The same point in two places: medium; name the one place it belongs. A step that ends on a bound the model cannot check ("when it is clear", "once done"): medium; recommend the condition that closes it.
|
||||
- A prohibition where a positive form says the same, or a coined term and adjective runs where one word the model knows would do: low; recommend the positive sentence or the word.
|
||||
- Content the model could get by looking, a file's contents, a command's flags, copied into the skill: low, since it goes stale.
|
||||
- A section that cannot name where its elaborate form beats a five-line version (role, outcome, consumer, the scarred rules): write the five lines into `proposed_smallest` and the predicted loss, often nothing, into `predicted_delta`; a variant eval through the `bmad-eval` skill settles it. High for a section, medium for a paragraph.
|
||||
|
||||
Not flagged: persona voice in an agent (identity, communication style, principles, examples of voice): the bar applies to capability prompts, and a flatter persona is a worse outcome, not a leaner one; repetition or contradiction inside persona text still counts. A menu item whose prompt is a sentence with no capability file: it is listed for the user to see what is on offer, and the model does the rest. The other lenses' lanes. Critical only for friction that misleads the model into a wrong action.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Lens: trigger
|
||||
|
||||
Lane: the description as the whole trigger. The bar is the canon's trigger section: the model decides to load a skill from the description alone, so it must fire on the real requests and stay quiet on the neighbors. Start from `description_chars`, `has_use_when` and `frontmatter_ok`, then read the description.
|
||||
|
||||
- Over 1024 characters, or no `Use when`: high; the validator fails it too.
|
||||
- Past the canon's two parts: a summary longer than one short sentence, a third sentence, or a `Not for` no collision called for. Medium; name what to cut.
|
||||
- An agent whose `Use when` omits its name, or has no phrase for a capability that lives inside it: medium; name the capability.
|
||||
- Nothing on what it does before the `Use when`, or first person ("I help you"): medium.
|
||||
- No concrete anchors: no file types, tool names, artifact names or phrases a user types, only adjectives ("helps with planning"). High; it will hijack neighbors or never fire.
|
||||
- A sibling skill shares its vocabulary and no trigger eval has tested the boundary: low; recommend one with near misses, and a `Not for` naming the sibling only if it fails.
|
||||
- Procedure in the description: steps or flow the body should own. Medium; the model can skip the body and improvise.
|
||||
- "When to use" text in the body: an overview saying when the skill applies, trigger phrases under a heading. Medium; the model never sees it when choosing.
|
||||
- One noun covering a whole domain: high. A single phrasing where users say it several ways: medium. Several wordings of one situation stacked as separate clauses: low; collapse them. A tool's symptom where the user's problem is the trigger, in a skill not about that tool: low.
|
||||
- `{target}/evals/triggers.json` absent, or without near misses (`should_trigger: false` cases sharing vocabulary): low; recommend writing it from the discovery, eight to ten each way.
|
||||
- Doubt about any of the above: recommend a trigger eval through the `bmad-eval` skill, not a rewrite by opinion. When a description is revised from failures, change its contexts and anchors; never paste a failed query's words into it.
|
||||
|
||||
Not flagged: an agent's long `Use when` when each phrase belongs to an internal capability; a `Not for` naming a sibling that an eval or a known collision called for; a one-line description on a skill with model invocation disabled; the body for lacking trigger text, which is where it should not be.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Standards
|
||||
|
||||
The contract a built skill meets; `canon.md` covers the prose.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
`name` and `description` only. `name` equals the folder name, kebab-case. `bmad-` belongs to modules shipped by the bmad-code-org (`^bmad-[a-z0-9]+(?:-[a-z0-9]+)*$`); anyone else's module skills carry its own code as prefix; a lone skill is a plain name, and one with the user's prefix is better. `description`: a single-quoted YAML string in the canon's two parts, with 1024 characters as the ceiling, per the canon's trigger section. `disable-model-invocation: true` is the one further key, for a skill only ever called by name, where the host honours it.
|
||||
|
||||
## Layout
|
||||
|
||||
`SKILL.md` at the root. `references/` for prompt content a branch loads, one level deep. `scripts/` for deterministic code, tests in `scripts/tests/`. `assets/` for templates and examples of emitted output. Folders stay flat; group files with a filename prefix (`scan-*.md`), not a subfolder. Only a rendered skill keeps `workflow.md` and step files at root. An agent whose internal routes would not fit a flat folder may group them in subfolders by axis, as `bmad-toolsmith` does; each route file then names the conventions it depends on, because the entry may have left context by the time it loads.
|
||||
|
||||
## Paths
|
||||
|
||||
`{project-root}` is the nearest folder holding `_bmad/`, `{skill-root}` the skill's folder. A skill's own script runs as `uv run {skill-root}/scripts/<name>.py`, a runtime script as `uv run {project-root}/_bmad/scripts/<name>.py`; never a bare `scripts/` call, which resolves from the working directory, and never `python`, `python3` or `pip`, since `uv run` reads the script's PEP 723 header for its dependencies. Every backticked path resolves to a real file. Never a path into another skill: to use one, write "invoke the `<name>` skill". Never `module.yaml`, `module-help.csv` or `_bmad/config.yaml`, the old format. Config: `resolve_config.py --key core.<key>` or `--key modules.<code>.<key>`; customization: `resolve_customization.py --key workflow` or `--key agent`. Config values already hold `{project-root}`; never prefix them.
|
||||
|
||||
## Output
|
||||
|
||||
A document lands at `<type>-<slug>/<type>-<slug>.md` under `{output_folder}/{active_initiative}/`.
|
||||
|
||||
## customize.toml
|
||||
|
||||
One table, read in activation. `[workflow]` for a skill: `activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`, `<purpose>_output_path`, `run_folder_pattern`, and its own scalars, each commented with when to override it. `[agent]` for an agent: `name`, `title`, `icon`, `role`, `identity`, `communication_style`, `principles`, the two step arrays, `persistent_facts`, and `[[agent.menu]]` items with `code`, `description` and exactly one of `skill` or `prompt`. The body reads values as `{workflow.<key>}` or `{agent.<key>}`; a value declared but hardcoded in the body makes every override a silent no-op. Scalars override, arrays append, arrays of tables merge by `code` or `id`. No boolean toggles; a switch means the author never decided. Reading is the resolver's job; writing is the `bmad-customize` skill's, which authors the override files under `_bmad/custom/` for any skill with a `customize.toml`. A skill never writes there, never merges its own TOML, and never carries a second code path for when `_bmad/` is absent: it offers setup. When users will change a value, the body says so in one line: invoke the `bmad-customize` skill naming the key, and if it is not installed offer `npx skills add bmad-code-org/BMAD-METHOD --skill bmad-customize`.
|
||||
|
||||
## bmod.toml
|
||||
|
||||
A skill in a module: `[skill]` with `bmod` (the record folder), `source` (the record's `update_source`), `required_skills` (it invokes them), `recommended_skills` (they help beside it) and `scripts` it ships. A dependency is a plain name for the same source, `{ skill, source, version? }` for another. A single-skill module carries `[bmod]` (`code`, `version`, `update_source`, `skills`, `required_skills`) and an empty `[skill]` in one file; a multi-skill module keeps `[bmod]` in a `bmod-<code>` record folder with `help/` and, with agents, `roster.toml`. A skill outside BMad needs none.
|
||||
|
||||
## Scripts
|
||||
|
||||
A script does work that has one right answer per input: parsing, counting, resolving paths, validating structure, rendering a template, diffing. Prose does work that turns on meaning. Tests assert what a script produced, never what a model wrote or what a prompt file says. Python with a PEP 723 header, `requires-python = ">=3.11"`, dependencies listed. argparse with `--help`. JSON on stdout when a model reads the result. Non-zero exit with a reason, never an error deferred to the model. Stdlib first, a graceful fallback when an optional import is absent. A test at `scripts/tests/test_<name>.py` using `unittest`. No model ids or time estimates anywhere in a skill.
|
||||
|
||||
## Memory agents
|
||||
|
||||
The sanctum lives at `{project-root}/_bmad/memory/{name}/`, `{name}` being the skill name; the agent needs the skill bundle only for first wake and init. Waking loads the identity files (PERSONA, CREED, BOND, HOW-I-REMEMBER as the layout guide, CAPABILITIES) and a generated map; memory is small files under `memory/<kind>/` and a write-once `raw/` layer, read as a conversation reaches them. The owner's name and language come from the First Breath conversation into BOND.md, never from config.
|
||||
Reference in New Issue
Block a user