refactor(bmad-spec): companions+sources model, routing tilt, flat output path

- Collapse `related:` into `companions:`; companion paths may point inside the spec folder (spec-authored) or outside it (adopted from an upstream skill), distinguished implicitly by path
- `sources:` reserved for fully-absorbed inputs; downstream does NOT read these
- Soften mutation contract: bmad-spec owns SPEC.md and spec-authored companions; adopted companions belong to their originating skill
- Add "when to spawn a companion" tilt: multi-item catalogs, tables, diagrams (always), editorial voice rules; sub-bullets in a kernel field signal it has outgrown the kernel
- Fix Spec Law rule 7 and Pass 2: load-bearing content lands in SPEC.md or a companion, not the decision log (the log records wrapper-drops only)
- Flatten output path to `{planning_artifacts}/specs/spec-{slug}-{date}/`, mirroring `prds/` and `ux-designs/`; drop `spec_folder_name` (no longer used)
- Extract Load-bearing definition into its own section above Spec Law
This commit is contained in:
Brian Madison 2026-05-24 01:16:36 -05:00
parent 2b0ad2e5a3
commit b6b41e84ed
3 changed files with 97 additions and 32 deletions

View File

@ -1,80 +1,124 @@
---
name: bmad-spec
description: Distill any intent input into the five-field Spec kernel. Use when the user says "create a spec", "distill this into a spec", "validate this spec", or "update the spec".
description: Distill any intent input into the SPEC kernel + companions — the canonical, preservation-validated machine contract for downstream work. Use when the user says "create a spec", "distill this into a spec", "validate this spec", or "update the spec".
---
# BMad Spec
## Overview
Universal distiller. Takes any intent input — vague idea, brain dump, PRD, GDD, RFC, brief, Slack thread, customer email, meeting transcript — and produces a `spec.md` carrying the five-field kernel: Problem, Capabilities, Constraints, Non-goals, Success signal. Quality scales with input richness; the contract holds.
Canonical transformer for the BMad spec-kernel ecosystem. Takes any intent input — vague idea, brain dump, PRD, GDD, RFC, brief, Slack thread, customer email, meeting transcript, mockups, mixed multi-source — and produces **SPEC.md** carrying the five-field kernel (Why, Capabilities, Constraints, Non-goals, Success signal) plus companion files for load-bearing content that does not fit or would bloat with expansive line item details the kernel. Together they are the machine contract every downstream BMad skill consumes (UX, architecture, ticketing, quick-dev).
The operation is input-driven: read the input, produce the Spec, self-validate, present. Headless callers get JSON; interactive users get a conversational close with the spec path and an invitation to address gaps. The Spec is the machine-readable contract every downstream BMad skill consumes (UX, Architecture, Ticketing). PRDs and other ceremony docs are for humans; Specs are for machines.
Multiple skills may call to update the same spec over time.
## Conventions
- Bare paths (e.g. `assets/spec-template.md`) resolve from the skill root.
- `{skill-root}` is this skill's install dir; `{project-root}` is the working dir.
- `{workflow.<name>}` resolves to fields in `customize.toml`.
- `{doc_workspace}` is the bound run folder for this Spec.
- `{doc_workspace}` is the bound spec folder for this run.
## On Activation
1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly.
2. Run `{workflow.activation_steps_prepend}`. Treat `{workflow.persistent_facts}` as foundational context (`file:` entries are loaded).
3. Load `{project-root}/_bmad/config.yaml` (and `config.user.yaml` if present), root level and `bmm` section. Resolve `{user_name}`, `{communication_language}`, `{document_output_language}`, `{planning_artifacts}`, `{project_name}`, `{date}`.
4. Detect mode. **Headless** when any of: no TTY, programmatic caller (another skill or non-interactive runner), or the first message pre-supplies all inputs and asks for an artifact path back. **Interactive** otherwise — the normal case when a user is in the conversation. In interactive mode, greet by `{user_name}` in `{communication_language}`, stay in that language, and mention that `bmad-party-mode` and `bmad-advanced-elicitation` are available for deeper exploration on any field.
4. Detect mode. **Headless** when any of: no TTY, programmatic caller (another skill or non-interactive runner), or the first message pre-supplies all inputs and asks for an artifact path back. **Interactive** otherwise. In interactive mode, greet by `{user_name}` in `{communication_language}`, stay in that language, and mention that `bmad-party-mode` and `bmad-advanced-elicitation` are available for deeper exploration on any field.
5. Run `{workflow.activation_steps_append}`.
## Workspace
Where the Spec lands depends on the input:
The spec is **always a folder** named `{workflow.spec_output_path}/{workflow.run_folder_pattern}`, resolving by default to `{planning_artifacts}/specs/spec-{slug}-{date}/`.
- **Input is a local file** — write `{input-basename}-spec-{datetime}.md` as a sibling of the source.
- **Input is in-chat prose or a remote source we cannot write next to** — write `{planning_artifacts}/specs/{slug}-spec-{datetime}.md`.
- **No input** — interactive: ask the user to share a file path, paste content, explain the idea in detail, or point to a source. Headless: respond with json containing error code insufficient_intent.
`{slug}` describes the thing being specced, not the input shape:
When a `.decision-log.md` is in scope (file-input case, source folder already has one), it is canonical memory — every decision, override, assumption, and rejected alternative captured during the run. When no decision log is in scope, the verdict surfaces in the conversational output (interactive) and the headless JSON only.
- Source artifact already carries a slug (e.g., `prd-foo-bar-2026-05-23/`): inherit (`foo-bar`).
- Sparse, in-chat, or multi-source input: interactive asks; headless caller provides.
- A second run on the same `{slug}` is an update: re-read the existing spec, preserve capability IDs.
**No input.** Interactive: ask the user to share a file path, paste content, explain the idea in detail, or point to a source. Headless: respond with JSON containing error code `insufficient_intent`.
Inside the spec folder:
```
<spec-folder>/
SPEC.md ← uppercase, the kernel
<companion-1>.md ← optional, content-typed (e.g. glossary.md)
<companion-2>.md
.decision-log.md ← canonical memory for this spec
```
## The Operation
Read the input. If there is no input, follow the no-input branch in **Workspace** (ask or block). If the input is itself a prior Spec — or a prior Spec exists at the target sibling path — read it too; the operation becomes an update. Preserve capability IDs, new capabilities get the next unused `CAP-N`, never reuse retired IDs. Otherwise this is a create.
Read the input and its ancillary linked materials. If there is no input, follow the no-input branch in **Workspace** (ask or block). If a prior `SPEC.md` exists at the target folder, read it too — the operation becomes an update. Preserve capability IDs; new capabilities get the next unused `CAP-N`; never reuse retired IDs. Otherwise this is a create.
Distill the input into the five-field kernel using `{workflow.spec_template}` as the skeleton. When input is rich (PRD, GDD, RFC, detailed brain dump), extract directly — no elicitation. When input is sparse (a paragraph, a one-line idea), choose: **express** (best-effort distill, every gap becomes an `open_questions[]` entry) or **guided** (walk the five fields with the user one at a time). Headless defaults to express and logs the choice. Interactive asks.
When the input is structured and pre-sorted (a PRD with an addendum, a GDD, a brief produced by an upstream BMad skill), trust the authored separation: lift kernel-fitting content into SPEC.md, lift overflow into appropriately-named companions. When the input is mixed (a brain dump, a transcript, an RFC, a customer email), do the sorting yourself: walk each claim, apply the three-lens load-bearing test (Spec Law rule 7), and route to the kernel field or a companion.
When the user volunteers content that belongs in the wrapper rather than the kernel (a persona detail, a milestone, an architecture choice), capture it to a sibling `addendum.md` rather than pushing back mid-flow. Tell them at the end where it landed.
Distill the input into the five-field kernel using `{workflow.spec_template}` as the skeleton. When input is rich, extract directly — no elicitation. When input is sparse, choose: **express** (best-effort distill, every gap becomes an `open_questions[]` entry) or **guided** (walk the five fields with the user one at a time). Headless defaults to express and logs the choice. Interactive asks.
If the input is genuinely too thin to distill (e.g. "an app for hikers" with no surrounding context), stop and suggest `bmad-prd` (or sibling ceremony skill). This skill distills; it does not coach.
## Load-bearing
A claim is **load-bearing** if any consumer (downstream skill, implementing agent, verification pass) would change a decision without it.
## Companions
When load-bearing content does not fit the five-field kernel, it lives in a companion. The kernel cites it; the companion holds it. Companions are part of the contract; every consumer reads `companions:` in SPEC.md frontmatter to discover them.
**Spawn a companion when the content needs more than one kernel-shape line:** multi-item catalogs (per-entity matrices like archetypes, drinks, modes, routes), tables, diagrams (always), editorial voice rules, long-form reference material the kernel cites by name (glossary, brownfield notes, project conventions). Single-line decision-benders stay in Constraints; intent+success pairs stay in Capabilities. If a kernel field is starting to bullet into sub-bullets, the content has outgrown the kernel and wants a companion.
Companions are either:
- **Spec-authored** companions are written by bmad-spec and live as **siblings of SPEC.md** (e.g., `glossary.md`, `patron-archetypes.md`). bmad-spec owns them and may edit them on update operations.
- **Adopted** companions are load-bearing artifacts written by an upstream skill that downstream still needs to read. bmad-spec references them into `companions:` by relative path but does NOT edit them (e.g., a `DESIGN.md` or `EXPERIENCE.md` from a UX run, an integration partner's API spec). The originating skill owns them.
Two rules govern companions:
1. **Name spec-authored companions for the content type they hold.** `glossary.md`, `<entity-class>.md` (e.g. `patron-archetypes.md`, `medication-routes.md`, `flight-modes.md`), `stack.md`, `conventions.md`, `brownfield.md`, `architecture-diagrams.md`, `state-machines.md`, `failure-modes.md`, `compliance-references.md`. The principle: "a reader should know what is inside before opening it." Adopted companions keep whatever name their originating skill gave them.
2. **Diagrams always land in a companion**, regardless of size. SPEC.md kernel holds prose only. Mermaid blocks, ASCII diagrams, and image references all live in a companion (e.g. `architecture-diagrams.md`), with sibling image files referenced from there.
Pre-existing project-wide docs (e.g. `project-context.md`) that downstream needs are listed as **adopted companions**, never duplicated into SPEC.md or a spec-authored companion.
## Spec Law
Every Spec must satisfy these six rules. The operation aims for them; the self-validate sweep enforces them.
Every spec must satisfy these seven rules. The operation aims for them; the self-validate sweep enforces them.
1. **Each capability has both `intent` and `success`.** Missing either = not a capability.
2. **Intents describe WHAT, not HOW.** Implementation prescription belongs in the wrapper or downstream architecture.
2. **Intents describe WHAT, not HOW.** Implementation prescription belongs in a companion (stack, conventions)..
3. **Constraints actually bend design decisions.** A "constraint" that rules nothing out is decoration.
4. **Non-goals are explicit.** At least one. Absence means downstream skills fill the vacuum.
5. **Success signal is concrete enough to test or demonstrate against.** "Users love it" doesn't qualify.
6. **Capability IDs are stable and unique.** Never reused, never renumbered.
What does NOT belong in a Spec, regardless of input: personas, NFR matrices, journey diagrams, risk registers, milestones, acceptance criteria matrices, traceability tables, implementation prescription, stakeholder approval ceremony. All of that lives in the wrapper.
7. **Preservation.** Every load-bearing source claim lands in SPEC.md or a companion. Wrapper ceremony does not.
## Self-Validate
After every create or update, sweep the resulting Spec file against Spec Law before presenting. For each rule, judge whether the Spec passes; for anything that fails or feels weak, attempt to fix it without inventing content the input did not support. Calls you made without direct confirmation become `assumptions[]`; gaps you could not fill become `open_questions[]`. If a `.decision-log.md` is in scope (per **Workspace**), append a one-paragraph verdict to it.
After every create or update, sweep the resulting artifact in **two passes** before presenting.
This is judgment, not ceremony — no separate report, no grade tiers, no severity counts. The verdict either reads "ready for downstream" or names what's blocking that. The user sees the verdict, the assumptions, and the open questions in the final output.
**Pass 1 — Coherence.** Judge the spec against Spec Law rules 16. For anything that fails or feels weak, attempt to fix it without inventing content the input did not support. Calls made without direct confirmation become `assumptions[]`; gaps that could not be filled become `open_questions[]`.
## Validate-Only Mode
**Pass 2 — Preservation.** Walk the source claim by claim. Confirm each load-bearing claim landed in SPEC.md or a companion. Wrapper-ceremony drops are logged under "Wrapper-only content" so the drop is on the record, not silent.
When the user points the skill at an existing Spec file with no change signal, run the self-validate sweep without modifying anything. Surface findings inline; if a `.decision-log.md` sits alongside the Spec, append the verdict to it. Offer to roll findings into an update.
Append a one-paragraph verdict to `.decision-log.md` covering both passes, review with user.
## Spec with no change signal
When the user points the skill at an existing spec folder (or its SPEC.md) with no change signal, offer to review assumptions or open questions, or determine what they want to do.
## Output
**Interactive** — share the Spec file path conversationally. Name the capability count and the verdict in one or two sentences. If `assumptions[]` or `open_questions[]` are non-empty, list them (short — one line each) and invite the user to walk through them. Make clear that addressing them can update the source input (if it was a file), the spec, or both — whichever combination the user prefers. Do not dump JSON. Do not present a wall of numbers.
**Interactive** — share the spec folder path conversationally. Name the capability count, the companions produced, and the verdict in one or two sentences. If `assumptions[]` or `open_questions[]` are non-empty, list them (short — one line each) and invite the user to walk through them. Make clear that addressing them can update the source input (if it was a file), the spec, or both — whichever combination the user prefers. Do not dump JSON or present a wall of output.
**Headless** — return JSON per `assets/headless-schemas.md`. Nothing else.
**Headless** — return JSON per `assets/headless-schemas.md`.
Run `{workflow.on_complete}` if set.
## Post Output
## After Spec is Output
If the user wants to address assumptions or open questions, loop back into the operation with the Spec as input. If they want to update the source input, loop back with that. If they want to update both, loop back with the Spec and overwrite the source file if there is one. If they want to update neither, end the conversation. If there are any udpates to the source, and there is a `.decision-log.md` in scope, append all details of change to the source about the updates to it.
Any update to spec regarding assumptions, open questions, or other changes should be appended to that source's decision log also and offer to update the source.
## Frontmatter conventions
- `companions:` array of `.md` files downstream MUST read alongside SPEC.md to have the full contract. Paths may point inside the spec folder (spec-authored companions like `glossary.md`) or outside it (adopted companions like `_bmad-output/ux-designs/foo-ux/DESIGN.md`). The split between spec-authored and adopted is implicit by path; downstream treats both the same.
- `sources:` array of paths to files that were **fully absorbed** into the SPEC, with no remaining downstream value (e.g., a PRD whose every load-bearing claim is now in the kernel). Listed for audit and for bmad-spec to re-read on update. Downstream does NOT read these. Files that downstream still needs to read belong in `companions:`, not here.
- **Do not list** decision logs, README files, organizational artifacts, or any operational record of how upstream skills produced their artifacts. Those are not source content; they are process metadata that downstream consumers don't need.

View File

@ -1,16 +1,22 @@
---
id: SPEC-{slug}
created: {date}
updated: {date}
status: draft
source_artifact: null
companions: [] # files downstream MUST read alongside SPEC.md. Paths may point inside the spec folder (spec-authored) or outside it (adopted from an upstream skill).
sources: [] # files fully absorbed into the SPEC (audit only; downstream does NOT read these). Never decision logs.
---
> **Canonical contract.** This SPEC and the files in `companions:` are the complete, preservation-validated contract for what to build, test, and validate. Source documents listed in frontmatter are for traceability only — consult them only if you need narrative rationale or prose color this contract intentionally omits.
# {Spec Title}
## Problem
## Why
{One paragraph. What gap, for whom, why now. Concrete: name the user and the gap they're stuck on. This is the anchor every downstream trade-off resolves against.}
{One paragraph naming the force behind this work. A spec can exist for any of:
- **a pain to solve** — a user or operator is stuck on a specific gap;
- **an opportunity to capture** — something newly possible we want to claim;
- **a vision to realize** — a thing we want to make exist because we want it to exist;
- **a mandate to meet** — a regulation, deprecation, deadline, or contractual obligation.
Name which (or which combination) applies, who is affected, and the backdrop that makes it matter now. This is the anchor every downstream trade-off resolves against.}
## Capabilities

View File

@ -27,7 +27,22 @@ persistent_facts = [
# Executed when the workflow completes. Scalar or array of instructions.
on_complete = ""
# Spec template — the five-field kernel skeleton. Override the path in
# Spec template. The five-field kernel skeleton. Override the path in
# team/user TOML to enforce a different shape (e.g. a hypothesis field
# for research initiatives, or a mechanics field for games).
spec_template = "assets/spec-template.md"
# Canonical filename for the kernel artifact inside the spec folder.
# Uppercase by convention to signal "the central source of truth."
spec_filename = "SPEC.md"
# Output path for spec folders. Mirrors the BMad convention for PRDs
# (`prds/`) and UX runs (`ux-designs/`): one predictable location for
# downstream skills, regardless of input shape.
spec_output_path = "{planning_artifacts}/specs"
# Run-folder pattern inside spec_output_path. Resolved against the
# input-derived slug and date at activation. A second run on the same
# slug is an update; date in the pattern keeps fresh dated folders
# only when the user explicitly intends a new spec.
run_folder_pattern = "spec-{slug}-{date}"