Compare commits
15 Commits
4c928b1b85
...
1336aa5549
| Author | SHA1 | Date |
|---|---|---|
|
|
1336aa5549 | |
|
|
242dc6ef75 | |
|
|
93ff8d458f | |
|
|
46c5173b9c | |
|
|
0c3b9291a0 | |
|
|
7e65f5004c | |
|
|
61531ffaee | |
|
|
b290a15298 | |
|
|
839be11932 | |
|
|
e897fa6207 | |
|
|
ad428e0f9f | |
|
|
c31a892f6d | |
|
|
e41f453f87 | |
|
|
15ae6d0cbf | |
|
|
64f0eef3ec |
|
|
@ -26,6 +26,9 @@ design-artifacts/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
|
|
||||||
|
# BMad run artifacts (memlogs are per-run working memory, never committed)
|
||||||
|
.memlog.md
|
||||||
|
|
||||||
# System files
|
# System files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,13 @@
|
||||||
"lint:fix": "eslint . --ext .js,.cjs,.mjs,.yaml --fix",
|
"lint:fix": "eslint . --ext .js,.cjs,.mjs,.yaml --fix",
|
||||||
"lint:md": "markdownlint-cli2 \"**/*.md\"",
|
"lint:md": "markdownlint-cli2 \"**/*.md\"",
|
||||||
"prepare": "command -v husky >/dev/null 2>&1 && husky || exit 0",
|
"prepare": "command -v husky >/dev/null 2>&1 && husky || exit 0",
|
||||||
"quality": "npm run format:check && npm run lint && npm run lint:md && npm run docs:build && npm run test:install && npm run test:urls && npm run validate:refs && npm run validate:skills && npm run docs:validate-sidebar",
|
"quality": "npm run format:check && npm run lint && npm run lint:md && npm run docs:build && npm run test:install && npm run test:urls && npm run test:renderer && npm run validate:refs && npm run validate:skills && npm run docs:validate-sidebar",
|
||||||
"rebundle": "node tools/installer/bundlers/bundle-web.js rebundle",
|
"rebundle": "node tools/installer/bundlers/bundle-web.js rebundle",
|
||||||
"test": "npm run test:refs && npm run test:install && npm run test:urls && npm run test:channels && npm run lint && npm run lint:md && npm run format:check",
|
"test": "npm run test:refs && npm run test:install && npm run test:urls && npm run test:channels && npm run test:renderer && npm run lint && npm run lint:md && npm run format:check",
|
||||||
"test:channels": "node test/test-installer-channels.js",
|
"test:channels": "node test/test-installer-channels.js",
|
||||||
"test:install": "node test/test-installation-components.js",
|
"test:install": "node test/test-installation-components.js",
|
||||||
"test:refs": "node test/test-file-refs-csv.js",
|
"test:refs": "node test/test-file-refs-csv.js",
|
||||||
|
"test:renderer": "node test/test-quick-dev-renderer.js",
|
||||||
"test:urls": "node test/test-parse-source-urls.js",
|
"test:urls": "node test/test-parse-source-urls.js",
|
||||||
"validate:refs": "node tools/validate-file-refs.js --strict",
|
"validate:refs": "node tools/validate-file-refs.js --strict",
|
||||||
"validate:skills": "node tools/validate-skills.js --strict"
|
"validate:skills": "node tools/validate-skills.js --strict"
|
||||||
|
|
|
||||||
|
|
@ -88,5 +88,5 @@ Tell the user the sequence in one sentence, then walk it. Polish goes last so it
|
||||||
4. **Triage open items.** All Open Questions, `[ASSUMPTION]` tags, `[NOTE FOR PM]` callouts. Phase-blockers (would make the PRD unsafe for UX/architecture/epics) surfaced one at a time and resolved; non-blockers deferred with owner + revisit condition logged to `.decision-log.md`. If phase-blocker count is high, flag it.
|
4. **Triage open items.** All Open Questions, `[ASSUMPTION]` tags, `[NOTE FOR PM]` callouts. Phase-blockers (would make the PRD unsafe for UX/architecture/epics) surfaced one at a time and resolved; non-blockers deferred with owner + revisit condition logged to `.decision-log.md`. If phase-blocker count is high, flag it.
|
||||||
5. **Polish.** Apply `{workflow.doc_standards}` to `prd.md` and `addendum.md` in declared order (structural passes before prose — prose should not polish soon-to-be-cut text). Parallelize across documents, sequential within.
|
5. **Polish.** Apply `{workflow.doc_standards}` to `prd.md` and `addendum.md` in declared order (structural passes before prose — prose should not polish soon-to-be-cut text). Parallelize across documents, sequential within.
|
||||||
6. **External handoffs.** Execute `{workflow.external_handoffs}`; surface returned URLs/IDs. Skip and flag unavailable tools.
|
6. **External handoffs.** Execute `{workflow.external_handoffs}`; surface returned URLs/IDs. Skip and flag unavailable tools.
|
||||||
7. **Close.** Set `prd.md` frontmatter `status: final` and `updated` to `{date}` so future invocations distinguish this PRD from in-progress drafts. Record finalization to `.decision-log.md`. Share artifact paths. Common next: `bmad-ux`, `bmad-create-architecture`, `bmad-create-epics-and-stories`; invoke `bmad-help` for authoritative routing.
|
7. **Close.** Set `prd.md` frontmatter `status: final` and `updated` to `{date}` so future invocations distinguish this PRD from in-progress drafts. Record finalization to `.decision-log.md`. Share artifact paths. Common next: `bmad-ux`, `bmad-architecture`, `bmad-create-epics-and-stories`; invoke `bmad-help` for authoritative routing.
|
||||||
8. Run `{workflow.on_complete}` if non-empty.
|
8. Run `{workflow.on_complete}` if non-empty.
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ UX may lead, follow, or stand alone. Inherit `sources:` by reference; the spines
|
||||||
1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults.
|
1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly and use defaults.
|
||||||
2. Run `{workflow.activation_steps_prepend}`. Treat `{workflow.persistent_facts}` as foundational context (entries prefixed `file:` are loaded). `{workflow.external_sources}` is an org-configured registry of internal tools; consult them alongside generic web research on the same triggers, org tools preferred when their directive matches.
|
2. Run `{workflow.activation_steps_prepend}`. Treat `{workflow.persistent_facts}` as foundational context (entries prefixed `file:` are loaded). `{workflow.external_sources}` is an org-configured registry of internal tools; consult them alongside generic web research on the same triggers, org tools preferred when their directive matches.
|
||||||
3. Load `{project-root}/_bmad/bmm/config.yaml` (+ `config.user.yaml` if present). Resolve `{user_name}`, `{communication_language}`, `{document_output_language}`, `{planning_artifacts}`, `{project_name}`, `{date}`. Missing keys → neutral defaults; never block.
|
3. Load `{project-root}/_bmad/bmm/config.yaml` (+ `config.user.yaml` if present). Resolve `{user_name}`, `{communication_language}`, `{document_output_language}`, `{planning_artifacts}`, `{project_name}`, `{date}`. Missing keys → neutral defaults; never block.
|
||||||
4. If headless, follow `references/headless.md` for the whole run. Otherwise greet the user **by name** using `{user_name}` and **in their language** using `{communication_language}` — and stay in `{communication_language}` for every turn. In the greeting, let the user know `bmad-party-mode` and `bmad-advanced-elicitation` are always available. Then scan for misroute on the first message: PRD → `bmad-prd`; architecture → `bmad-create-architecture`; game UX → BMad GDS; agent/skill → `bmad-workflow-builder`; brief → `bmad-product-brief`.
|
4. If headless, follow `references/headless.md` for the whole run. Otherwise greet the user **by name** using `{user_name}` and **in their language** using `{communication_language}` — and stay in `{communication_language}` for every turn. In the greeting, let the user know `bmad-party-mode` and `bmad-advanced-elicitation` are always available. Then scan for misroute on the first message: PRD → `bmad-prd`; architecture → `bmad-architecture`; game UX → BMad GDS; agent/skill → `bmad-workflow-builder`; brief → `bmad-product-brief`.
|
||||||
5. Detect intent: **Create**, **Update**, **Validate**. For Create, before binding a fresh workspace, scan `{workflow.ux_output_path}` for prior in-progress runs (folders matching `{workflow.run_folder_pattern}` whose `DESIGN.md` frontmatter `status` is not `final`) and offer to resume rather than starting over.
|
5. Detect intent: **Create**, **Update**, **Validate**. For Create, before binding a fresh workspace, scan `{workflow.ux_output_path}` for prior in-progress runs (folders matching `{workflow.run_folder_pattern}` whose `DESIGN.md` frontmatter `status` is not `final`) and offer to resume rather than starting over.
|
||||||
|
|
||||||
Run `{workflow.activation_steps_append}`.
|
Run `{workflow.activation_steps_append}`.
|
||||||
|
|
@ -87,4 +87,4 @@ Outcomes, in order:
|
||||||
- **Key-screen mocks rendered.** Key-screens tool → `.working/` for surfaces where layout drives behavior or anchors visual language.
|
- **Key-screen mocks rendered.** Key-screens tool → `.working/` for surfaces where layout drives behavior or anchors visual language.
|
||||||
- **Mock coverage confirmed.** Walk every IA surface; classify *mocked* vs *spine-only*. Ask: *"These will be built from spine tables alone — any need a visual reference?"* Render more if named; log spine-only choices.
|
- **Mock coverage confirmed.** Walk every IA surface; classify *mocked* vs *spine-only*. Ask: *"These will be built from spine tables alone — any need a visual reference?"* Render more if named; log spine-only choices.
|
||||||
- **Layout extracted, artifacts promoted.** Distill subagent re-reads each `.working/` and `imports/` artifact; lifts visual decisions into DESIGN.md and behavioral decisions into EXPERIENCE.md. Promote `.working/` keepers to `mockups/` (HTML) or `wireframes/` (Excalidraw); imports stay. Inline relative links at relevant spine sections; state spines-win-on-conflict once.
|
- **Layout extracted, artifacts promoted.** Distill subagent re-reads each `.working/` and `imports/` artifact; lifts visual decisions into DESIGN.md and behavioral decisions into EXPERIENCE.md. Promote `.working/` keepers to `mockups/` (HTML) or `wireframes/` (Excalidraw); imports stay. Inline relative links at relevant spine sections; state spines-win-on-conflict once.
|
||||||
- **Polished, handed off, closed.** Apply `{workflow.doc_standards}` in order. Execute `{workflow.external_handoffs}`; surface URLs. Set both files' `status: final`, `updated: {date}`. Log finalization. Share paths. Common next: `bmad-create-architecture`, `bmad-create-epics-and-stories`, `bmad-dev-story`. Run `{workflow.on_complete}`.
|
- **Polished, handed off, closed.** Apply `{workflow.doc_standards}` in order. Execute `{workflow.external_handoffs}`; surface URLs. Set both files' `status: final`, `updated: {date}`. Log finalization. Share paths. Common next: `bmad-architecture`, `bmad-create-epics-and-stories`, `bmad-dev-story`. Run `{workflow.on_complete}`.
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ principles = [
|
||||||
|
|
||||||
[[agent.menu]]
|
[[agent.menu]]
|
||||||
code = "CA"
|
code = "CA"
|
||||||
description = "Guided workflow to document technical decisions to keep implementation on track"
|
description = "Produce the architecture spine: the invariants that keep independently-built units consistent"
|
||||||
skill = "bmad-create-architecture"
|
skill = "bmad-architecture"
|
||||||
|
|
||||||
[[agent.menu]]
|
[[agent.menu]]
|
||||||
code = "IR"
|
code = "IR"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
---
|
||||||
|
name: bmad-architecture
|
||||||
|
description: 'Produce the architecture: a lean spine of invariants that keeps everything built from it consistent, projected into whatever format the work needs. Use when the user says "create the architecture", "create technical architecture", "architecture spine", or "create a solution design".'
|
||||||
|
---
|
||||||
|
# BMad Architecture
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
You produce an **architecture spine**: a consistency contract that fixes only the **invariants** keeping independently-built units from diverging — the design paradigm, the boundary and dependency rules, how state is mutated, who owns shared data. Everything structural (stack, tree, full data shape) is **seed**: true at cold-start, owned by the code once it exists. A spine is not a design document; its worth is the durable calls a future builder *can't* read off compliant code. Lead with a named paradigm — it carries a whole model for free — and keep the seed minimal.
|
||||||
|
|
||||||
|
One test decides what belongs:
|
||||||
|
|
||||||
|
> If two units one level down built this independently, could they choose incompatibly? Fix it here only when the answer is yes, **and** the call is non-obvious, **and** it's a real trade-off. Otherwise name it under Deferred and move on.
|
||||||
|
|
||||||
|
Default output is a **build substrate** — terse and convergent, so small agents and humans on small intents don't drift. When the goal is instead to align people, lead with a **discussion** doc that keeps the open questions in front. Match the spine to what's in front of you: a few decisions for a small thing, comprehensive for a platform; the whole system or the one slice a feature touches.
|
||||||
|
|
||||||
|
Record decisions, not rationale (rationale lives in the memlog). Carry shape in diagrams, not prose. Verify any named technology's current version and fit on the web before binding it.
|
||||||
|
|
||||||
|
## How you work
|
||||||
|
|
||||||
|
You're a coach, and the **Coaching path is the default** — this runs against the model's instinct to just produce an architecture, so hold the line on it. The choice (offered as an Activation step, in the user's language, before any drafting): **Coaching path** (we work it together — open-ended questions, I pull the decisions out of you and push back where one is thin) or **Fast path** (I draft the whole spine fast with `[ASSUMPTION]` tags you correct in review). Unless the user clearly wants speed, **coach; don't silently draft.** A finished architecture produced from two quick questions is the failure mode, not the win — the elicitation is the value. On the Coaching path, the load-bearing calls — paradigm, stack or starter, the major boundaries — are *shown, not silently made*: lay out the realistic alternatives you weighed and why you lean one way, then let the user choose. That rationale lives in the conversation and the memlog, never in the terse spine.
|
||||||
|
|
||||||
|
Elicit, don't quiz: open-ended "how are you thinking about X?" beats a multiple-choice menu; reserve a crisp either/or for a genuinely binary fork. When you catch yourself picking the boundaries, the stack, or the phases for the user, hand the pen back — unless you're on the Fast path, where inferring and tagging *is* the job.
|
||||||
|
|
||||||
|
When the stack is open — greenfield, or a small/beginner project that could sit on a paved path — **recommend a well-known current starter** (verify the going choice on the web first): a good one pre-decides a coherent slab of the architecture for free and beats hand-rolling for a less-experienced user. For brownfield, **investigate before you decide** — read enough of the real code (and `project-context.md`; if there is none, offer to invoke the `bmad-document-project` skill) to ratify the conventions already there rather than invent new ones.
|
||||||
|
|
||||||
|
## Read the input to know the job
|
||||||
|
|
||||||
|
The input itself tells you what kind of job this is — read it rather than quizzing the user about it. A spec package (`SPEC.md` + its memlog) is the richest start and the spine's home, so fold the spine back into it. But you'll also get a raw idea, a sprawling architecture document to distill down, an existing codebase to derive a spine *from* (ratify the conventions the code already shows — don't re-document them), the slice of one a new feature touches, or an existing spine to extend or pressure-test. Prefer a `.memlog.md` over re-reading the source it came from. Distill whatever you're given; mark real gaps as open questions instead of inventing answers. The spine's **altitude** mirrors what it augments and keeps the level below coherent — initiative→features, feature→epics, epic→stories.
|
||||||
|
|
||||||
|
**Inheriting a parent spine** (e.g. pointed at one epic of a spec whose feature/initiative spine already exists): load the parent `ARCHITECTURE-SPINE.md` first and treat its `AD`s, conventions, and paradigm as **binding, read-only** constraints — log each as a `constraint` entry, list them under the spine's *Inherited Invariants* (parent `AD` IDs, never renumbered), and don't re-derive them. Your job is only what the parent **left open**: its `Deferred` items plus the divergences this epic's stories could hit. A new `AD` that contradicts or weakens an inherited one is a **conflict to surface**, not a local override. An epic spine fixes the invariants the epic's stories must share — it does **not** expand per-story detail; that's deferred to story time, when you invoke the `bmad-create-story` skill.
|
||||||
|
|
||||||
|
## How a run works
|
||||||
|
|
||||||
|
The **memlog** (`.memlog.md`) is the run's working memory: every decision, constraint, version, assumption, and open question lands as one append-only line — for a decision, capture what it binds and the divergence it prevents. It is the shared canonical memlog (the same `{project-root}/_bmad/scripts/memlog.py` bmad-spec writes through), so it carries no lifecycle status — terminal moments are logged as `event` entries, not a frontmatter flag. The spine is **distilled from the memlog at the end**, not written as you go. Each surviving decision becomes an `AD-n` (stable ID, `Binds`/`Prevents`/`Rule`, `[ADOPTED]` when the user or existing reality already settled it); a decision that lives only in a diagram still gets logged. Resume a prior run by reloading its memlog.
|
||||||
|
|
||||||
|
Writes go through the shared script (don't read the file back except on resume):
|
||||||
|
|
||||||
|
- `python3 {project-root}/_bmad/scripts/memlog.py init --workspace {doc_workspace} --field scope="…" --field purpose="…" --field altitude="…"`
|
||||||
|
- `python3 {project-root}/_bmad/scripts/memlog.py append --workspace {doc_workspace} --type <decision|constraint|version|assumption|question|direction|event> --text "…"`
|
||||||
|
- A terminal moment (spine finalized, a validation verdict) is an `append --type event` entry — there is no status field to set.
|
||||||
|
|
||||||
|
## Resolution rules
|
||||||
|
|
||||||
|
- Bare paths and `{skill-root}` (e.g. `references/headless.md`) resolve from this skill's installed directory.
|
||||||
|
- `{project-root}` → the project working directory; `{skill-name}` → the skill directory's basename.
|
||||||
|
- `{workflow.<name>}` → a merged `customize.toml` field; `{doc_workspace}` → the bound run folder.
|
||||||
|
- Forward slashes only. Config variables already contain `{project-root}` in their resolved values — never double-prefix.
|
||||||
|
|
||||||
|
## On Activation
|
||||||
|
|
||||||
|
**Forwarded activation:** if a caller (e.g. the `bmad-create-architecture` shim) invoked you with a stated intent and pre-resolved customization fields, honor them verbatim — skip your own intent inference, use the supplied values for those named fields, and resolve only the remaining fields from your own `customize.toml`. So a legacy per-project override still reaches the run.
|
||||||
|
|
||||||
|
1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow` (on failure read `{skill-root}/customize.toml`, use defaults). Run `{workflow.activation_steps_prepend}`, then `{workflow.activation_steps_append}`. Hold `{workflow.persistent_facts}` as standing context — the default loads `project-context.md`, load-bearing for brownfield — and consult `{workflow.external_sources}` on demand.
|
||||||
|
2. Load `{project-root}/_bmad/bmm/config.yaml` (+ `config.user.yaml`) for `{user_name}`, `{communication_language}`, `{document_output_language}`, `{planning_artifacts}`, `{project_name}`, `{date}`; missing keys take neutral defaults, never block.
|
||||||
|
3. Headless (no interactive user) → follow `references/headless.md` for the whole run. Otherwise greet `{user_name}` in `{communication_language}`. Detect the intent from the conversation and input — **create** (the default), **update** an existing spine, or **validate** one (see those sections). If the real ask is requirements / UX / a capability contract / epic breakdown / an agent, invoke the `bmad-prd`, `bmad-ux`, `bmad-spec`, `bmad-create-epics-and-stories`, or `bmad-workflow-builder` (if the BMad Builder module is installed) skill instead.
|
||||||
|
4. If a run folder for this target already exists under `{workflow.spine_output_path}`, offer to resume from its memlog rather than restart.
|
||||||
|
5. Interactive create: offer the working mode in `{communication_language}` — **Coaching path** (default) or **Fast path** (see *How you work*) — before any drafting; default to Coaching unless the user asks for speed.
|
||||||
|
6. **Mandatory, both paths, before drafting:** ask whether the spine is the only deliverable — and if not, draw out the *purpose and audience* rather than a document type. "An architecture doc" balloons into bloat; what they actually need might be a one-detail explainer for a single team or a non-technical vision piece for a board. Purpose right-sizes the artifact and may call for extra elicitation up front, not just a finale add-on.
|
||||||
|
|
||||||
|
For a new spine, bind `{doc_workspace}` to `{workflow.spine_output_path}/{workflow.run_folder_pattern}/`, seed `ARCHITECTURE-SPINE.md` from `{workflow.spine_template}`, run `memlog.py init`, and tell the user the path. **At epic altitude, scope the folder to the epic** (set `run_folder_pattern` per `customize.toml`) so per-epic runs don't collide.
|
||||||
|
|
||||||
|
## Reviewer Gate
|
||||||
|
|
||||||
|
The spine's pre-handoff review — full mechanics in `references/reviewer-gate.md`. Load it when finalizing or validating: a deterministic `lint_spine.py` pass, then a rubric walker (good-spine checklist) + every `{workflow.finalize_reviewers}` lens dispatched as parallel subagents against `ARCHITECTURE-SPINE.md`, scaled to stakes. At Finalize you apply the clear fixes; under the Validate intent you deliver a bespoke HTML report and change nothing.
|
||||||
|
|
||||||
|
## Finalize
|
||||||
|
|
||||||
|
Walk the sequence; reviewer fixes land before polish.
|
||||||
|
|
||||||
|
1. **Distill.** Write the spine from the memlog (brownfield: + the code sweep) — invariants first, seed minimal, every `AD` carrying Binds/Prevents/Rule, `Deferred` naming what it won't decide. No placeholders; never invent to fill a gap. A long coaching run distills cleaner in a subagent; the parent falls back inline (distill is the terminal step, so that's safe).
|
||||||
|
2. **Reconcile inputs.** A subagent per load-bearing input checks it against the spine and returns what didn't land — especially a quiet requirement (a tone, a constraint) the `AD` structure dropped. Before the gate.
|
||||||
|
3. **Reviewer pass.** Run the Reviewer Gate (`references/reviewer-gate.md`). Resolve before polish.
|
||||||
|
4. **Triage.** Open questions and `[ASSUMPTION]` tags: blockers (unsafe for what's next) resolved one at a time; the rest deferred with a revisit condition in the memlog.
|
||||||
|
5. **Renderings & polish.** The spine is the build deliverable; with it and the memlog now in place, produce any *additional* human-facing artifact the user needs, scoped to the purpose and audience drawn out up front. The up-front question already flagged whether one's needed; if it wasn't, still offer one here, seeding concrete options: an interactive HTML+SVG deck to walk a team through the architecture and drive discussion, a fuller HTML/md solution design, a C4 set, or a view of how the work splits across teams/epics. Build only what they pick, right-sized to that purpose; apply `{workflow.doc_standards}` polish to that prose only, never to the spine.
|
||||||
|
6. **External handoffs.** Run `{workflow.external_handoffs}`; surface returned URLs/IDs. Offer to invoke the `bmad-spec` skill to adopt the spine as a companion, keeping `AD` IDs stable so downstream can cite them.
|
||||||
|
7. **Close.** Set the spine's own frontmatter `status: final`, `updated: {date}`; log a `memlog.py append --type event --text "spine finalized"` (the memlog has no status field). Share paths. Next, **lead with `bmad-spec`** — recommend adopting/refreshing the spine as a spec companion (always the top recommendation when a spec was an input, and a useful next step even when it wasn't), then `bmad-create-epics-and-stories` or — epic altitude — `bmad-create-story`; or invoke `bmad-help` to route.
|
||||||
|
8. Run `{workflow.on_complete}`.
|
||||||
|
|
||||||
|
## Update
|
||||||
|
|
||||||
|
Amend an existing spine. Resume from its `.memlog.md` (the authority on what was decided), not the rendered spine. Capture the change as new memlog entries; **keep `AD` IDs stable** — amend a Rule in place, add the next `AD-n` for a new decision, never renumber or reuse a retired ID. Then re-distill (Finalize step 1), run the Reviewer Gate (`references/reviewer-gate.md`), and close as in Finalize. An update that overrides something from a source input: offer to update that source too, so upstream and the spine don't silently diverge.
|
||||||
|
|
||||||
|
## Validate
|
||||||
|
|
||||||
|
The standalone intent — critique an existing spine without changing it. Run the Reviewer Gate (`references/reviewer-gate.md`) against it and deliver the bespoke HTML report, then offer to roll the findings into an Update. (At Finalize the same gate runs as your own pre-handoff check, where you apply the fixes instead of reporting.)
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
---
|
||||||
|
name: '{name}'
|
||||||
|
type: architecture-spine
|
||||||
|
purpose: build-substrate # build-substrate (default) · discussion · report · deck
|
||||||
|
altitude: feature # initiative (keeps features) · feature (keeps epics) · epic (keeps stories)
|
||||||
|
paradigm: '{named design pattern, e.g. hexagonal, layered, pipes-and-filters, actor}'
|
||||||
|
scope: '{what this spine governs}'
|
||||||
|
status: draft # draft · final
|
||||||
|
created: '{date}'
|
||||||
|
updated: '{date}'
|
||||||
|
stack: # SEED — verified current at authoring; the code owns this once it exists
|
||||||
|
languages: []
|
||||||
|
frameworks: []
|
||||||
|
key_deps: [] # name@version
|
||||||
|
binds: [] # capability / unit IDs governed (from the driving spec; at epic altitude, also the parent AD IDs inherited)
|
||||||
|
sources: []
|
||||||
|
companions: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Architecture Spine — {name}
|
||||||
|
|
||||||
|
> A consistency contract, not a design document. It fixes the **invariants** that keep the
|
||||||
|
> independently-built level below ({features | epics | stories}) coherent — the durable rules a
|
||||||
|
> clean codebase can't reveal. Structure is **seed**: the code owns the detail, the spine keeps the shape.
|
||||||
|
> Decisions, not rationale (that lives in the memlog). Diagrams over prose.
|
||||||
|
>
|
||||||
|
> **Scale to the job — drop any section a project doesn't need.** A small intent may be just a
|
||||||
|
> paradigm + a few `AD`s + conventions, seed omitted; a platform earns the full set. An inherited
|
||||||
|
> epic spine is usually mostly Inherited Invariants + a thin Deferred. Empty sections are cut, not left as headers.
|
||||||
|
|
||||||
|
## Design Paradigm
|
||||||
|
|
||||||
|
Name the pattern — a known one loads a whole model for free — and map its layers to namespaces /
|
||||||
|
directories. The smallest, most durable thing in the file.
|
||||||
|
|
||||||
|
## Inherited Invariants
|
||||||
|
|
||||||
|
Present only when this spine inherits a parent at a higher altitude (e.g. an epic spine under a
|
||||||
|
feature/initiative spine). The parent's `AD`s, conventions, and paradigm that bind here, listed by
|
||||||
|
their original parent IDs — **read-only, never renumbered, not re-derived**. This spine adds only
|
||||||
|
what the parent left open; anything here that a local decision would contradict is a conflict to
|
||||||
|
surface, not override.
|
||||||
|
|
||||||
|
| Inherited | From parent | Binds here |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| {AD-n / convention} | {parent spine} | {what it constrains in this scope} |
|
||||||
|
|
||||||
|
## Invariants & Rules
|
||||||
|
|
||||||
|
The durable heart: the calls a future builder can't read from compliant code. Each `AD-n` has a
|
||||||
|
stable ID (never reused), a binding scope, the divergence it prevents, and an enforceable rule.
|
||||||
|
Cover the boundary/dependency rules (who may depend on whom) and how state is mutated — a
|
||||||
|
dependency-direction diagram says these better than prose. An `AD-n` the user asserted as
|
||||||
|
already-settled (or one verified from existing reality) carries an `[ADOPTED]` tag after its
|
||||||
|
title, so its provenance is legible versus decisions made here.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
%% arrows = allowed dependency direction (a rule, not just structure)
|
||||||
|
```
|
||||||
|
|
||||||
|
### AD-1 — {decision}
|
||||||
|
|
||||||
|
- **Binds:** {capability / unit IDs, areas, or `all`}
|
||||||
|
- **Prevents:** {the divergence this stops}
|
||||||
|
- **Rule:** {the constraint downstream must follow}
|
||||||
|
|
||||||
|
## Consistency Conventions
|
||||||
|
|
||||||
|
The defaults that bind everything where independent builders would otherwise drift. Cut rows that
|
||||||
|
don't apply.
|
||||||
|
|
||||||
|
| Concern | Convention |
|
||||||
|
| --- | --- |
|
||||||
|
| Naming (entities, files, interfaces, events) | |
|
||||||
|
| Data & formats (IDs, dates, error shapes, envelopes) | |
|
||||||
|
| State & cross-cutting (mutation, errors, logging, config, auth) | |
|
||||||
|
|
||||||
|
## Structural Seed
|
||||||
|
|
||||||
|
Cold-start scaffolding, kept minimal — include an item only where its shape is non-obvious at this
|
||||||
|
altitude (at epic altitude the parent usually already fixed it, so the seed is often empty). The code
|
||||||
|
owns the **detail** (every file, every column); once code exists it becomes the source of truth for
|
||||||
|
detail, and this seed is a starting scaffold, not a mirror to maintain against it. Evolve a seed item
|
||||||
|
only when the **shape** itself changes — a new container, a new core entity, a stack bump — and let
|
||||||
|
the memlog keep the history.
|
||||||
|
|
||||||
|
- **Stack & Versions** — the substrate (mirrors frontmatter `stack`).
|
||||||
|
- **System Shape** — a container/context view (at epic altitude, the slice of the parent system this scope touches). Use `flowchart` with a `subgraph` per boundary; C4 mermaid is experimental and won't render in most viewers.
|
||||||
|
- **Core Entities** — an ERD of entities and their relationships. Names and relationships only; attributes belong to the code unless one is itself an invariant (then it's an `AD`, not seed).
|
||||||
|
- **Project Structure** — a minimal source tree, only as deep as consistency needs.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
user(["{actor}"])
|
||||||
|
subgraph sys["{system boundary}"]
|
||||||
|
a["{container}<br/>{tech} — {role}"]
|
||||||
|
end
|
||||||
|
db[("{datastore}")]
|
||||||
|
ext["{external system}"]
|
||||||
|
user --> a
|
||||||
|
a --> db
|
||||||
|
a -->|{via port}| ext
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
erDiagram
|
||||||
|
ENTITY_A ||--o{ ENTITY_B : "{relationship}"
|
||||||
|
ENTITY_B ||--o| ENTITY_C : "{relationship}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
{root}/
|
||||||
|
{dir}/ # {what lives here}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Capability → Architecture Map
|
||||||
|
|
||||||
|
Bridges the spec's capabilities to the architecture (and is the consistency auditor's checklist).
|
||||||
|
Present when a spec drove this run.
|
||||||
|
|
||||||
|
| Capability / Area | Lives in | Governed by |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| {CAP-n / area} | {component / module} | {AD-n, convention, paradigm} |
|
||||||
|
|
||||||
|
## Deferred
|
||||||
|
|
||||||
|
Decisions intentionally pushed down, each with the reason it can wait. The half of the contract
|
||||||
|
that keeps the spine lean.
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
# DO NOT EDIT -- overwritten on every update.
|
||||||
|
#
|
||||||
|
# Workflow customization surface for bmad-architecture.
|
||||||
|
#
|
||||||
|
# Override files (not edited here):
|
||||||
|
# {project-root}/_bmad/custom/bmad-architecture.toml (team)
|
||||||
|
# {project-root}/_bmad/custom/bmad-architecture.user.toml (personal)
|
||||||
|
|
||||||
|
[workflow]
|
||||||
|
|
||||||
|
# --- Configurable below. Overrides merge per BMad structural rules: ---
|
||||||
|
# scalars: override wins • arrays: append
|
||||||
|
|
||||||
|
# Steps to run before the standard activation (config load, greet).
|
||||||
|
# Use for pre-flight loads, approved-stack policy checks, etc.
|
||||||
|
activation_steps_prepend = []
|
||||||
|
|
||||||
|
# Steps to run after greet but before the workflow begins.
|
||||||
|
# Use for context-heavy setup that should happen once the user has been acknowledged.
|
||||||
|
activation_steps_append = []
|
||||||
|
|
||||||
|
# Persistent facts the workflow keeps in mind for the whole run
|
||||||
|
# (approved stacks, banned dependencies, platform constraints, compliance guardrails).
|
||||||
|
# Each entry is either a literal sentence, a skill prefixed with `skill:`, or a `file:`-prefixed
|
||||||
|
# path/glob whose contents are loaded as facts.
|
||||||
|
#
|
||||||
|
# Default loads project-context.md if bmad-generate-project-context produced one — giving the
|
||||||
|
# architect persistent awareness of the project's tech, domain, and conventions (load-bearing
|
||||||
|
# for brownfield). Common opt-ins (set in team/user override TOML):
|
||||||
|
# "Our org is AWS-only -- do not propose GCP or Azure."
|
||||||
|
# "file:{project-root}/docs/engineering-standards.md"
|
||||||
|
persistent_facts = [
|
||||||
|
"file:{project-root}/**/project-context.md",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Executed when the workflow completes (after the spine is final and the user has been told).
|
||||||
|
# String scalar (single instruction) or array of instructions executed in order. Empty for none.
|
||||||
|
on_complete = ""
|
||||||
|
|
||||||
|
# The architecture spine template. Treated as expert prior knowledge, not a checklist — the LLM
|
||||||
|
# adapts it to the project, altitude, and domain, and drops sections a project genuinely doesn't
|
||||||
|
# need. Override the path in team/user TOML to enforce a different spine shape.
|
||||||
|
spine_template = "assets/spine-template.md"
|
||||||
|
|
||||||
|
# Run folder location. ARCHITECTURE-SPINE.md, its .memlog.md, and any fuller rendering the run
|
||||||
|
# produces all land inside `{spine_output_path}/{run_folder_pattern}/`. Resume-check scans
|
||||||
|
# `{spine_output_path}` for prior unfinished runs.
|
||||||
|
#
|
||||||
|
# The default pattern fits the common case (one spine per project, at the altitude above epics).
|
||||||
|
# At EPIC altitude, override run_folder_pattern to carry the epic identity so per-epic runs don't
|
||||||
|
# collide on the same day — e.g. set it (team/user TOML) to "architecture-epic-{epic_id}", binding
|
||||||
|
# {epic_id} from the driving spec / the activating payload. Headless callers may instead pass an
|
||||||
|
# explicit doc_workspace and bypass the pattern entirely.
|
||||||
|
spine_output_path = "{planning_artifacts}/architecture"
|
||||||
|
run_folder_pattern = "architecture-{project_name}-{date}"
|
||||||
|
|
||||||
|
# Prose-editorial standards applied at finalize ONLY to a fuller prose document the run produces
|
||||||
|
# (a discussion report, full architecture doc, or design addendum) — never to the spine or other
|
||||||
|
# short, structured outputs, which are terse and carry decisions in AD-n blocks and diagrams by
|
||||||
|
# design. Each entry is a `skill:`, `file:`, or plain-text directive applied before the user sees
|
||||||
|
# the polished draft. Suggested order: structural passes first, prose mechanics last. Append-only.
|
||||||
|
doc_standards = [
|
||||||
|
"skill:bmad-editorial-review-structure",
|
||||||
|
"skill:bmad-editorial-review-prose",
|
||||||
|
]
|
||||||
|
|
||||||
|
# External-source registry. Natural-language directives describing knowledge bases, MCP tools, or
|
||||||
|
# internal systems the LLM may consult ON DEMAND during the run (not preemptively) — approved-stack
|
||||||
|
# catalogs, internal platform docs, version registries. Each entry names the tool, the trigger
|
||||||
|
# condition, and any fields it needs. If a named tool is unavailable at runtime, the LLM falls back
|
||||||
|
# to standard behavior (e.g. web research) and notes the gap. Empty by default.
|
||||||
|
#
|
||||||
|
# Examples (set in team/user override TOML):
|
||||||
|
# "When choosing a datastore, consult corp:platform_catalog before recommending one."
|
||||||
|
# "For current library versions, query corp:artifact_registry before web search."
|
||||||
|
external_sources = []
|
||||||
|
|
||||||
|
# External-handoff routing applied at Finalize to push outputs beyond local files (Confluence,
|
||||||
|
# Notion, ticket systems). Each entry names the MCP tool, the destination, and required fields.
|
||||||
|
# Runs after polish; returned URLs/IDs are surfaced. Unavailable tools are skipped and flagged;
|
||||||
|
# local files always exist. Empty by default.
|
||||||
|
external_handoffs = []
|
||||||
|
|
||||||
|
# --- Finalize reviewers ---
|
||||||
|
# Extra review lenses spawned as parallel subagents at the validation gate (Finalize and the
|
||||||
|
# Validate intent), on top of the skill's built-in good-spine checklist and the lint_spine.py
|
||||||
|
# mechanical floor. The GATE is stakes-gated — a throwaway spine may run it quietly or skip it —
|
||||||
|
# but whenever the gate runs, every entry here runs with it (the configured floor, never cherry-
|
||||||
|
# picked); only ad-hoc lenses are optional, and headless never skips the gate.
|
||||||
|
#
|
||||||
|
# Entries follow the standard prefix convention:
|
||||||
|
# "skill:NAME" invoke the named review skill as a subagent against ARCHITECTURE-SPINE.md
|
||||||
|
# "file:PATH" load the file as a review prompt; spawn an adversarial subagent applying it
|
||||||
|
# plain text use the text directly as the subagent's review prompt
|
||||||
|
#
|
||||||
|
# Resolved on-demand (not at activation). Override TOML may append.
|
||||||
|
finalize_reviewers = [
|
||||||
|
"Verify every committed decision was web-researched or reality-checked rather than asserted from training data: current library/framework versions, that each named technology still exists and fits, and — greenfield — the live defaults of any starter it leans on. Flag anything that could be out of date and wasn't confirmed against the web, the existing project, or the current starter.",
|
||||||
|
"Attack the spine as an adversary: construct two units one level down that each obey every AD to the letter yet still build incompatibly — clashing shared-data shapes, two owners of one entity, conflicting state-mutation paths. Every pair you find is a hole to close with a new or tightened AD.",
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Headless
|
||||||
|
|
||||||
|
No interactive user: infer everything, ask nothing, but never invent — record inferences as `assumptions[]` and gaps that need a human as `open_questions[]`. Detect headless from a `headless: true` flag, a non-interactive / no-TTY invocation, an activation hook that declares it, or a first message that pre-supplies all inputs and asks for an artifact path back; when ambiguous, default to interactive.
|
||||||
|
|
||||||
|
Drive the run from the payload in the first message — `intent`, `altitude`, `purpose`, the driving input (spec package / PRD / raw intent / brownfield path), a parent spine path at lower altitude, and `doc_workspace` if a specific folder is required. Infer anything absent from the inputs or workspace; don't invent stack, constraints, or scope to fill a gap. You still verify named tech on the web (you can't ask, but you can check) and still drive every write through the shared `{project-root}/_bmad/scripts/memlog.py`. Run the full Reviewer Gate (`references/reviewer-gate.md`) non-interactively: `scripts/lint_spine.py` plus **every `{workflow.finalize_reviewers}` lens as a parallel subagent** (and any ad-hoc lens the spine's criticality warrants). Headless skips only the human picking from the menu — never the reviewers themselves; apply the clear fixes and record anything unresolved in `open_questions[]`. For a true authority collision, list it in `conflicts_with_prior_decisions[]`. For the Validate intent, always write the report to `{doc_workspace}` and add `"offer_to_update": true`. If intent stays ambiguous after inference, halt blocked.
|
||||||
|
|
||||||
|
End with JSON only, omitting keys for artifacts not produced — the shape below is the fully-produced (`complete`) case; a `blocked` run produces no spine, so it omits `spine`, `memlog`, and `companions` entirely (see the note under the block):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "complete | partial | blocked",
|
||||||
|
"intent": "create | update | validate",
|
||||||
|
"altitude": "initiative | feature | epic",
|
||||||
|
"purpose": "build-substrate | discussion",
|
||||||
|
"doc_workspace": "<resolved run folder>",
|
||||||
|
"spine": "{doc_workspace}/ARCHITECTURE-SPINE.md",
|
||||||
|
"memlog": "{doc_workspace}/.memlog.md",
|
||||||
|
"companions": [],
|
||||||
|
"assumptions": [],
|
||||||
|
"open_questions": [],
|
||||||
|
"conflicts_with_prior_decisions": [],
|
||||||
|
"reason": "<one line, only when blocked>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`complete` stands alone · `partial` (spine produced, but `open_questions[]` non-empty or critical inputs inferred) means review before downstream use · `blocked` means no spine produced — return only `status`, `intent`, `reason`, and `doc_workspace` (if bound), omitting `spine`, `memlog`, `companions`, and the artifact arrays that don't exist.
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Reviewer Gate
|
||||||
|
|
||||||
|
The spine's pre-handoff review. Runs at Finalize (after distill + reconcile) and *is* the Validate intent. The difference is the ending: at Finalize you apply the clear fixes yourself; under Validate you report and don't change the spine.
|
||||||
|
|
||||||
|
Cheap deterministic pass first: `python3 {skill-root}/scripts/lint_spine.py --workspace {doc_workspace}` settles the mechanical misses (placeholders, duplicate `AD` IDs, missing Binds/Prevents/Rule, unpinned deps), so reviewers spend judgment on the semantic half.
|
||||||
|
|
||||||
|
Assemble the menu: a **rubric walker** that judges the spine against the good-spine checklist below, **+ every entry in `{workflow.finalize_reviewers}`**, + ad-hoc lenses you invent or offer as the spine's rigor, altitude, and criticality warrant — a security/compliance lens for regulated stakes, a seam reviewer cross-team, a data-integrity lens for a heavy data model. Scale *whether and how heavily the gate runs* to the stakes: a throwaway prototype may run it quietly or skip the gate entirely; a high-criticality or platform-altitude spine earns more lenses and the explicit all / subset / skip menu. But once the gate runs, the `{workflow.finalize_reviewers}` always run — they are the configured floor, never cherry-picked out; only the ad-hoc lenses are optional. (Headless never skips the gate.)
|
||||||
|
|
||||||
|
Dispatch every entry as a **parallel subagent against `ARCHITECTURE-SPINE.md`** (prefix convention: `skill:` / `file:` / plain text). Each writes its full review to `{doc_workspace}/review-{slug}.md` and returns ONLY a compact summary (verdict, top 2–5 findings, file path) — the parent never holds full review text. An inline self-check does not count: the independent context is the point, because a fresh reviewer finds the divergences the author talks past. If subagents are unavailable, run sequentially — write the file first, then flush it from context.
|
||||||
|
|
||||||
|
**Good-spine checklist** (what the rubric walker judges): it fixes the real divergence points for the level below and misses none; every `AD`'s Rule is enforceable and actually prevents its stated divergence; nothing under Deferred could let two units diverge; named tech is verified-current; it ratifies rather than contradicts a brownfield codebase; if a spec drove it, it covers that spec's capabilities; and if a parent spine is inherited, no new `AD` weakens or contradicts an inherited one.
|
||||||
|
|
||||||
|
Surface findings tiered, never dumped: a one-sentence gate verdict, then critical + high; medium/low roll into a tail ("plus N more in {file}"). Per finding: autofix, discuss, defer to Deferred / open items, or ignore. **At Finalize this is your own gate — apply the clear fixes rather than handing over a list; surface only what genuinely needs the user.** Under the **Validate intent**, fold every reviewer's output into one bespoke HTML + markdown report and open the HTML.
|
||||||
|
|
@ -0,0 +1,260 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.10"
|
||||||
|
# ///
|
||||||
|
"""lint-spine — the mechanical half of spine decision-integrity, done deterministically.
|
||||||
|
|
||||||
|
LLMs miscount IDs and miss literal placeholders; a grep does not. This linter owns the
|
||||||
|
checks a script does better than a prompt, and leaves the semantic half (is each Rule
|
||||||
|
actually enforceable? does the boundary make sense?) to the rubric walker.
|
||||||
|
|
||||||
|
It reads ARCHITECTURE-SPINE.md from a workspace and reports, as compact JSON on stdout:
|
||||||
|
|
||||||
|
- placeholder literal TBD / TODO / "similar to AD-n" / unfilled {template-token}
|
||||||
|
- ad_id duplicate or non-monotonic AD-n identifiers
|
||||||
|
- ad_fields an AD-n block missing Binds / Prevents / Rule
|
||||||
|
- version_pin a frontmatter key_deps entry with no @version
|
||||||
|
|
||||||
|
Fenced code blocks are blanked (replaced with equal-count blank lines) before scanning, so
|
||||||
|
mermaid and source trees don't trip false positives AND reported line numbers still line up
|
||||||
|
with the real file. Reported lines are absolute file lines (frontmatter offset added). Exit
|
||||||
|
code is always 0 — findings travel in the JSON; the caller (Reviewer Gate / rubric walker)
|
||||||
|
decides what to do with them.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
SPINE = "ARCHITECTURE-SPINE.md"
|
||||||
|
|
||||||
|
AD_HEADING = re.compile(r"^#{2,4}\s*AD-(\d+)\b(.*)$", re.MULTILINE)
|
||||||
|
HEADING = re.compile(r"^#{1,6}\s", re.MULTILINE)
|
||||||
|
FENCE = re.compile(r"```.*?```", re.DOTALL)
|
||||||
|
PLACEHOLDER_WORD = re.compile(r"\b(TBD|TODO|FIXME|XXX)\b")
|
||||||
|
SIMILAR_TO = re.compile(r"similar to AD-\d+", re.IGNORECASE)
|
||||||
|
TEMPLATE_TOKEN = re.compile(r"\{[a-z_][a-z0-9_ /.-]*\}")
|
||||||
|
|
||||||
|
|
||||||
|
def split_frontmatter(text: str) -> tuple[str, str, int]:
|
||||||
|
"""Return (frontmatter, body, body_line_offset).
|
||||||
|
|
||||||
|
Frontmatter is the content between the first two lines that are *exactly* `---`
|
||||||
|
(line-exact, like memlog.split — a `---` inside a value or a body thematic break never
|
||||||
|
truncates it). body_line_offset is the number of file lines before the body begins, so a
|
||||||
|
body-relative line number plus the offset gives the absolute file line. Absent frontmatter
|
||||||
|
→ ('', text, 0)."""
|
||||||
|
lines = text.split("\n")
|
||||||
|
if lines and lines[0] == "---":
|
||||||
|
for i in range(1, len(lines)):
|
||||||
|
if lines[i] == "---":
|
||||||
|
fm = "\n".join(lines[1:i])
|
||||||
|
body = "\n".join(lines[i + 1:])
|
||||||
|
return fm, body, i + 1
|
||||||
|
return "", text, 0
|
||||||
|
|
||||||
|
|
||||||
|
def blank_fences(text: str) -> str:
|
||||||
|
"""Replace each fenced block with the same number of newlines, so scanning skips fenced
|
||||||
|
content while every line number outside the fence stays put."""
|
||||||
|
return FENCE.sub(lambda m: "\n" * m.group(0).count("\n"), text)
|
||||||
|
|
||||||
|
|
||||||
|
def line_of(text: str, idx: int) -> int:
|
||||||
|
return text.count("\n", 0, idx) + 1
|
||||||
|
|
||||||
|
|
||||||
|
def find_placeholders(body: str, offset: int) -> list[dict]:
|
||||||
|
findings: list[dict] = []
|
||||||
|
scan = blank_fences(body)
|
||||||
|
# (regex, label, severity) — TBD/TODO and dangling cross-refs are unambiguous; a bare
|
||||||
|
# {template-token} can be legitimate brace prose, so it is flagged low ("possible") to keep
|
||||||
|
# the mechanical pass near-zero false-positive rather than train reviewers to ignore it.
|
||||||
|
for rx, label, severity in (
|
||||||
|
(PLACEHOLDER_WORD, "placeholder marker", "high"),
|
||||||
|
(SIMILAR_TO, "unresolved cross-reference", "high"),
|
||||||
|
(TEMPLATE_TOKEN, "possible unfilled template token (verify)", "low"),
|
||||||
|
):
|
||||||
|
for m in rx.finditer(scan):
|
||||||
|
findings.append({
|
||||||
|
"category": "placeholder",
|
||||||
|
"severity": severity,
|
||||||
|
"detail": f"{label}: {m.group(0)!r}",
|
||||||
|
"location": f"{SPINE} (line {offset + line_of(scan, m.start())})",
|
||||||
|
})
|
||||||
|
return findings
|
||||||
|
|
||||||
|
|
||||||
|
def find_frontmatter_placeholders(frontmatter: str) -> list[dict]:
|
||||||
|
"""Catch unfilled tokens left in frontmatter (e.g. paradigm/scope/date) — part of the
|
||||||
|
spine contract, but outside the body that find_placeholders scans."""
|
||||||
|
findings: list[dict] = []
|
||||||
|
for rx, label, severity in (
|
||||||
|
(PLACEHOLDER_WORD, "placeholder marker", "high"),
|
||||||
|
(TEMPLATE_TOKEN, "possible unfilled template token (verify)", "low"),
|
||||||
|
):
|
||||||
|
for m in rx.finditer(frontmatter):
|
||||||
|
findings.append({
|
||||||
|
"category": "placeholder",
|
||||||
|
"severity": severity,
|
||||||
|
"detail": f"frontmatter {label}: {m.group(0)!r}",
|
||||||
|
"location": f"{SPINE} frontmatter (line {1 + line_of(frontmatter, m.start())})",
|
||||||
|
})
|
||||||
|
return findings
|
||||||
|
|
||||||
|
|
||||||
|
def find_ad_issues(body: str, offset: int) -> list[dict]:
|
||||||
|
findings: list[dict] = []
|
||||||
|
scan = blank_fences(body) # AD headings shown inside a code fence are not live ADs
|
||||||
|
matches = list(AD_HEADING.finditer(scan))
|
||||||
|
seen: dict[int, int] = {}
|
||||||
|
prev: int | None = None
|
||||||
|
for m in matches:
|
||||||
|
num = int(m.group(1))
|
||||||
|
file_line = offset + line_of(scan, m.start())
|
||||||
|
loc = f"{SPINE} AD-{num} (line {file_line})"
|
||||||
|
if num in seen:
|
||||||
|
findings.append({
|
||||||
|
"category": "ad_id",
|
||||||
|
"severity": "high",
|
||||||
|
"detail": f"AD-{num} id reused (also at line {seen[num]})",
|
||||||
|
"location": loc,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
seen[num] = file_line
|
||||||
|
if prev is not None and num <= prev:
|
||||||
|
findings.append({
|
||||||
|
"category": "ad_id",
|
||||||
|
"severity": "high",
|
||||||
|
"detail": f"AD-{num} is non-monotonic (follows AD-{prev}); ids must ascend and never renumber",
|
||||||
|
"location": loc,
|
||||||
|
})
|
||||||
|
prev = num if prev is None else max(prev, num)
|
||||||
|
|
||||||
|
# block text = from this heading to the next heading of any level
|
||||||
|
start = m.end()
|
||||||
|
nxt = HEADING.search(scan, start)
|
||||||
|
block = scan[start:nxt.start()] if nxt else scan[start:]
|
||||||
|
low = block.lower()
|
||||||
|
missing = [f for f in ("binds", "prevents", "rule") if f not in low]
|
||||||
|
if missing:
|
||||||
|
findings.append({
|
||||||
|
"category": "ad_fields",
|
||||||
|
"severity": "high",
|
||||||
|
"detail": f"AD-{num} missing required field(s): {', '.join(missing)}",
|
||||||
|
"location": loc,
|
||||||
|
})
|
||||||
|
return findings
|
||||||
|
|
||||||
|
|
||||||
|
def find_unpinned_deps(frontmatter: str) -> list[dict]:
|
||||||
|
findings: list[dict] = []
|
||||||
|
lines = frontmatter.splitlines()
|
||||||
|
in_key_deps = False
|
||||||
|
key_indent = 0
|
||||||
|
for raw in lines:
|
||||||
|
stripped = raw.strip()
|
||||||
|
if not stripped or stripped.startswith("#"):
|
||||||
|
continue
|
||||||
|
indent = len(raw) - len(raw.lstrip())
|
||||||
|
m = re.match(r"key_deps:\s*(.*)$", stripped)
|
||||||
|
if m:
|
||||||
|
in_key_deps = True
|
||||||
|
key_indent = indent
|
||||||
|
inline = _strip_comment(m.group(1)).strip()
|
||||||
|
if inline and inline not in ("[]", "[ ]"):
|
||||||
|
# inline list form: key_deps: [a@1, b] — consumed here, no block follows
|
||||||
|
for item in re.findall(r"[^\[\],]+", inline.strip("[]")):
|
||||||
|
_check_dep(item.strip().strip("'\""), findings)
|
||||||
|
in_key_deps = False
|
||||||
|
continue
|
||||||
|
if in_key_deps:
|
||||||
|
if indent <= key_indent and not stripped.startswith("-"):
|
||||||
|
in_key_deps = False
|
||||||
|
continue
|
||||||
|
if stripped.startswith("-"):
|
||||||
|
# block-sequence form: `- name@version`
|
||||||
|
_check_dep(_strip_comment(stripped[1:]).strip().strip("'\""), findings)
|
||||||
|
else:
|
||||||
|
# map form: `name: version` — pinned iff a non-empty value is present
|
||||||
|
mm = re.match(r"([^:]+):\s*(.*)$", stripped)
|
||||||
|
if mm:
|
||||||
|
name = mm.group(1).strip().strip("'\"")
|
||||||
|
val = _strip_comment(mm.group(2)).strip().strip("'\"")
|
||||||
|
if name and not val:
|
||||||
|
findings.append({
|
||||||
|
"category": "version_pin",
|
||||||
|
"severity": "medium",
|
||||||
|
"detail": f"key_deps entry {name!r} has no version pin",
|
||||||
|
"location": f"{SPINE} frontmatter stack.key_deps",
|
||||||
|
})
|
||||||
|
return findings
|
||||||
|
|
||||||
|
|
||||||
|
def _strip_comment(s: str) -> str:
|
||||||
|
"""Drop a trailing YAML ` # comment`, leaving an inline `name@1.2` intact."""
|
||||||
|
return re.sub(r"(^|\s)#.*$", "", s)
|
||||||
|
|
||||||
|
|
||||||
|
def _check_dep(item: str, findings: list[dict]) -> None:
|
||||||
|
if not item or item.startswith("#"):
|
||||||
|
return
|
||||||
|
if "@" not in item:
|
||||||
|
findings.append({
|
||||||
|
"category": "version_pin",
|
||||||
|
"severity": "medium",
|
||||||
|
"detail": f"key_deps entry {item!r} has no @version pin",
|
||||||
|
"location": f"{SPINE} frontmatter stack.key_deps",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def lint(text: str) -> dict:
|
||||||
|
frontmatter, body, offset = split_frontmatter(text)
|
||||||
|
findings: list[dict] = []
|
||||||
|
findings += find_frontmatter_placeholders(frontmatter)
|
||||||
|
findings += find_placeholders(body, offset)
|
||||||
|
findings += find_ad_issues(body, offset)
|
||||||
|
findings += find_unpinned_deps(frontmatter)
|
||||||
|
counts: dict[str, int] = {}
|
||||||
|
for f in findings:
|
||||||
|
counts[f["severity"]] = counts.get(f["severity"], 0) + 1
|
||||||
|
return {
|
||||||
|
"ok": len(findings) == 0,
|
||||||
|
"spine": SPINE,
|
||||||
|
"total_findings": len(findings),
|
||||||
|
"by_severity": counts,
|
||||||
|
"findings": findings,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str] | None = None) -> int:
|
||||||
|
ap = argparse.ArgumentParser(description="Lint an architecture spine for mechanical integrity.")
|
||||||
|
ap.add_argument("--workspace", required=True, help="run folder containing ARCHITECTURE-SPINE.md")
|
||||||
|
ap.add_argument("-o", "--output", help="write JSON here instead of stdout")
|
||||||
|
args = ap.parse_args(argv)
|
||||||
|
|
||||||
|
spine_path = Path(args.workspace) / SPINE
|
||||||
|
if not spine_path.exists():
|
||||||
|
result = {"ok": False, "error": f"{spine_path} not found", "findings": [], "total_findings": 0}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
text = spine_path.read_text(encoding="utf-8")
|
||||||
|
except (OSError, UnicodeDecodeError) as e:
|
||||||
|
# honor the "exit code is always 0" contract: a read/decode failure travels in JSON
|
||||||
|
result = {"ok": False, "error": f"could not read {spine_path}: {e}", "findings": [], "total_findings": 0}
|
||||||
|
else:
|
||||||
|
result = lint(text)
|
||||||
|
|
||||||
|
out = json.dumps(result, indent=2)
|
||||||
|
if args.output:
|
||||||
|
Path(args.output).write_text(out + "\n", encoding="utf-8")
|
||||||
|
else:
|
||||||
|
print(out)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.10"
|
||||||
|
# dependencies = ["pytest>=8.0"]
|
||||||
|
# ///
|
||||||
|
"""Tests for lint_spine.py. Run: uv run --with pytest pytest scripts/tests/test_lint_spine.py
|
||||||
|
|
||||||
|
The spine under test: a clean spine lints empty; the linter catches exactly the
|
||||||
|
mechanical defects a prompt is unreliable at — literal placeholders, AD-n id breakage,
|
||||||
|
AD-n blocks missing required fields, and unpinned dependency versions.
|
||||||
|
"""
|
||||||
|
import importlib.util
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
_SPEC = importlib.util.spec_from_file_location(
|
||||||
|
"lint_spine", Path(__file__).resolve().parent.parent / "lint_spine.py"
|
||||||
|
)
|
||||||
|
lint_spine = importlib.util.module_from_spec(_SPEC)
|
||||||
|
sys.modules["lint_spine"] = lint_spine
|
||||||
|
_SPEC.loader.exec_module(lint_spine)
|
||||||
|
|
||||||
|
|
||||||
|
CLEAN = """---
|
||||||
|
name: 'Demo'
|
||||||
|
stack:
|
||||||
|
key_deps:
|
||||||
|
- fastapi@0.115
|
||||||
|
- pydantic@2.9
|
||||||
|
---
|
||||||
|
|
||||||
|
## Invariants & Rules
|
||||||
|
|
||||||
|
### AD-1 — single write path
|
||||||
|
|
||||||
|
- **Binds:** all
|
||||||
|
- **Prevents:** divergent mutation
|
||||||
|
- **Rule:** state changes only through the command bus
|
||||||
|
|
||||||
|
### AD-2 — layered deps `[ADOPTED]`
|
||||||
|
|
||||||
|
- **Binds:** all
|
||||||
|
- **Prevents:** import cycles
|
||||||
|
- **Rule:** ui -> app -> domain, never backward
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A --> B{decision}
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def cats(result):
|
||||||
|
return sorted(f["category"] for f in result["findings"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_clean_spine_passes():
|
||||||
|
result = lint_spine.lint(CLEAN)
|
||||||
|
assert result["ok"] is True
|
||||||
|
assert result["total_findings"] == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_mermaid_braces_not_flagged():
|
||||||
|
# the {decision} node lives in a fenced block and must not read as a template token
|
||||||
|
result = lint_spine.lint(CLEAN)
|
||||||
|
assert "placeholder" not in cats(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_placeholder_markers_caught():
|
||||||
|
text = CLEAN.replace("the command bus", "TBD")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert "placeholder" in cats(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_similar_to_caught():
|
||||||
|
text = CLEAN.replace("import cycles", "similar to AD-1")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert any("cross-reference" in f["detail"] for f in result["findings"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_unfilled_template_token_caught():
|
||||||
|
text = CLEAN.replace("single write path", "{decision}")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert any(f["category"] == "placeholder" for f in result["findings"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_duplicate_ad_id_caught():
|
||||||
|
text = CLEAN.replace("### AD-2 — layered deps `[ADOPTED]`", "### AD-1 — layered deps")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert "ad_id" in cats(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_non_monotonic_ad_id_caught():
|
||||||
|
text = CLEAN.replace("### AD-2 — layered deps `[ADOPTED]`", "### AD-5 — layered deps").replace(
|
||||||
|
"### AD-1 — single write path", "### AD-9 — single write path"
|
||||||
|
)
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert any("non-monotonic" in f["detail"] for f in result["findings"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_field_caught():
|
||||||
|
text = CLEAN.replace("- **Rule:** state changes only through the command bus\n", "")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert any(f["category"] == "ad_fields" and "rule" in f["detail"] for f in result["findings"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_unpinned_dep_caught():
|
||||||
|
text = CLEAN.replace("- fastapi@0.115", "- fastapi")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert "version_pin" in cats(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_inline_key_deps_unpinned():
|
||||||
|
text = CLEAN.replace(" key_deps:\n - fastapi@0.115\n - pydantic@2.9", " key_deps: [fastapi, redis@7]")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
pins = [f for f in result["findings"] if f["category"] == "version_pin"]
|
||||||
|
assert len(pins) == 1 and "fastapi" in pins[0]["detail"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_key_deps_ok():
|
||||||
|
text = CLEAN.replace(" key_deps:\n - fastapi@0.115\n - pydantic@2.9", " key_deps: []")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert "version_pin" not in cats(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_yaml_comments_not_parsed_as_deps():
|
||||||
|
# a SEED comment on the key_deps line must not read as an unpinned dependency
|
||||||
|
text = CLEAN.replace(
|
||||||
|
" key_deps:\n - fastapi@0.115\n - pydantic@2.9",
|
||||||
|
" key_deps: # SEED — verified current 2026-06\n - fastapi@0.115 # web framework",
|
||||||
|
)
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert "version_pin" not in cats(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_template_token_is_low_severity():
|
||||||
|
# a bare {token} can be legitimate brace prose; it is flagged, but low (not high) so the
|
||||||
|
# mechanical pass stays near-zero false-positive
|
||||||
|
text = CLEAN.replace("single write path", "{decision}")
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
toks = [f for f in result["findings"] if f["category"] == "placeholder" and "template token" in f["detail"]]
|
||||||
|
assert toks and all(f["severity"] == "low" for f in toks)
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_frontmatter_body_still_scanned():
|
||||||
|
text = "## Invariants\n\n### AD-1 — x\n\n- **Binds:** all\n- **Prevents:** drift\n- **Rule:** TBD\n"
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert "placeholder" in cats(result) # TBD caught even with no frontmatter
|
||||||
|
|
||||||
|
|
||||||
|
def test_frontmatter_value_with_dashes_not_truncated():
|
||||||
|
# a value containing '---' must not be read as the closing fence (line-exact close)
|
||||||
|
text = "---\nscope: 'phase 1 --- phase 2'\nstack:\n key_deps:\n - fastapi\n---\n\n## Invariants\n"
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert any(f["category"] == "version_pin" for f in result["findings"]) # read past the inline ---
|
||||||
|
|
||||||
|
|
||||||
|
def test_ad_heading_in_fence_not_counted():
|
||||||
|
text = (
|
||||||
|
"---\nname: 'x'\n---\n\n"
|
||||||
|
"### AD-1 — real\n\n- **Binds:** all\n- **Prevents:** drift\n- **Rule:** do x\n\n"
|
||||||
|
"## Docs\n\n```text\n### AD-2 — illustrative only, no fields\n```\n"
|
||||||
|
)
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert result["ok"] is True # the fenced AD-2 is not a live AD → no ad_fields/ad_id finding
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_form_key_deps_unpinned_caught():
|
||||||
|
text = "---\nstack:\n key_deps:\n fastapi: '0.115'\n redis:\n---\n\n## Invariants\n"
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
pins = [f for f in result["findings"] if f["category"] == "version_pin"]
|
||||||
|
assert len(pins) == 1 and "redis" in pins[0]["detail"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_form_key_deps_pinned_ok():
|
||||||
|
text = "---\nstack:\n key_deps:\n fastapi: '0.115'\n---\n\n## Invariants\n"
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert "version_pin" not in cats(result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_placeholder_line_number_is_absolute():
|
||||||
|
# a TBD after a multi-line fence reports its real file line (fence blanked, not collapsed)
|
||||||
|
text = (
|
||||||
|
"---\nname: 'x'\n---\n\n"
|
||||||
|
"## A\n\n"
|
||||||
|
"```text\nf1\nf2\nf3\n```\n\n"
|
||||||
|
"TBD here\n"
|
||||||
|
)
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
ph = next(f for f in result["findings"] if "TBD" in f["detail"])
|
||||||
|
n = int(re.search(r"line (\d+)", ph["location"]).group(1))
|
||||||
|
assert n == 13
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_spine_file_reports_error(tmp_path, capsys):
|
||||||
|
rc = lint_spine.main(["--workspace", str(tmp_path)])
|
||||||
|
out = json.loads(capsys.readouterr().out)
|
||||||
|
assert rc == 0 and out["ok"] is False and "not found" in out["error"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_frontmatter_unfilled_token_caught():
|
||||||
|
# an unfilled {scope}/{paradigm}/{date} in frontmatter is part of the contract and must lint
|
||||||
|
text = "---\nname: 'x'\nscope: '{what this spine governs}'\n---\n\n## Invariants\n"
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
fm = [f for f in result["findings"] if f["category"] == "placeholder" and "frontmatter" in f["detail"]]
|
||||||
|
assert fm and any("template token" in f["detail"] for f in fm)
|
||||||
|
|
||||||
|
|
||||||
|
def test_frontmatter_tbd_caught():
|
||||||
|
text = "---\nname: 'x'\nstatus: TBD\n---\n\n## Invariants\n"
|
||||||
|
result = lint_spine.lint(text)
|
||||||
|
assert any(f["category"] == "placeholder" and "frontmatter" in f["detail"] and "TBD" in f["detail"]
|
||||||
|
for f in result["findings"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_unreadable_spine_returns_error_not_crash(tmp_path, capsys):
|
||||||
|
# a spine that exists but can't be UTF-8 decoded must yield error JSON + exit 0, not a traceback
|
||||||
|
(tmp_path / lint_spine.SPINE).write_bytes(b"\xff\xfe bad bytes not utf-8")
|
||||||
|
rc = lint_spine.main(["--workspace", str(tmp_path)])
|
||||||
|
out = json.loads(capsys.readouterr().out)
|
||||||
|
assert rc == 0 and out["ok"] is False and "could not read" in out["error"]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(pytest.main([__file__, "-q"]))
|
||||||
|
|
@ -1,74 +1,30 @@
|
||||||
---
|
---
|
||||||
name: bmad-create-architecture
|
name: bmad-create-architecture
|
||||||
description: 'Create architecture solution design decisions for AI agent consistency. Use when the user says "lets create architecture" or "create technical architecture" or "create a solution design"'
|
description: 'DEPRECATED — consolidated into bmad-architecture create intent - this skill will be removed in v7 in favor of `bmad-architecture`.'
|
||||||
---
|
---
|
||||||
|
|
||||||
# Architecture Workflow
|
# DEPRECATED — forwards to bmad-architecture (create intent)
|
||||||
|
|
||||||
**Goal:** Create comprehensive architecture decisions through collaborative step-by-step discovery that ensures AI agents implement consistently.
|
This skill was consolidated into `bmad-architecture`. It is retained as a thin compatibility shim so existing invocations by name and `_bmad/custom/bmad-create-architecture.toml` override files keep working. New work should invoke `bmad-architecture` directly — it detects create / update / validate intent from the conversation.
|
||||||
|
|
||||||
**Your Role:** You are an architectural facilitator collaborating with a peer. This is a partnership, not a client-vendor relationship. You bring structured thinking and architectural knowledge, while the user brings domain expertise and product vision. Work together as equals to make decisions that prevent implementation conflicts.
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- Bare paths (e.g. `steps/step-01-init.md`) resolve from the skill root.
|
|
||||||
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
|
|
||||||
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
||||||
- `{skill-name}` resolves to the skill directory's basename.
|
|
||||||
|
|
||||||
## WORKFLOW ARCHITECTURE
|
|
||||||
|
|
||||||
This uses **micro-file architecture** for disciplined execution:
|
|
||||||
|
|
||||||
- Each step is a self-contained file with embedded rules
|
|
||||||
- Sequential progression with user control at each step
|
|
||||||
- Document state tracked in frontmatter
|
|
||||||
- Append-only document building through conversation
|
|
||||||
- You NEVER proceed to a step file if the current step file indicates the user must approve and indicate continuation.
|
|
||||||
|
|
||||||
## On Activation
|
## On Activation
|
||||||
|
|
||||||
### Step 1: Resolve the Workflow Block
|
1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-architecture.toml` and `bmad-create-architecture.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
|
2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
|
||||||
|
|
||||||
**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:
|
3. Emit a deprecation notice to the user in `{communication_language}`:
|
||||||
|
|
||||||
1. `{skill-root}/customize.toml` — defaults
|
> Notice: `bmad-create-architecture` is deprecated and will be removed in a future release. It now forwards to `bmad-architecture` with create intent. To silence this notice and access the full new customization surface (`spine_template`, `spine_output_path`, `run_folder_pattern`, `doc_standards`, `external_sources`, `external_handoffs`, `finalize_reviewers`), migrate `_bmad/custom/bmad-create-architecture.toml` to `_bmad/custom/bmad-architecture.toml` and invoke `bmad-architecture` directly next time. Customization fields that were in this version still remain in the new version and will be respected if present in `_bmad/custom/bmad-architecture.toml`, but the new version also supports additional fields that you can take advantage of by migrating.
|
||||||
2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
|
|
||||||
3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
|
|
||||||
|
|
||||||
Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
|
4. Invoke `bmad-architecture` with the following context. Pass these as the activating context so `bmad-architecture` honors them instead of resolving its own customization from scratch:
|
||||||
|
|
||||||
### Step 2: Execute Prepend Steps
|
- **Intent:** `create` — skip `bmad-architecture`'s usual intent detection step.
|
||||||
|
- **Pre-resolved legacy customization** — use these in place of resolving from `bmad-architecture`'s own `customize.toml` for the four legacy fields. For everything else (`spine_template`, `spine_output_path`, `run_folder_pattern`, `doc_standards`, `external_sources`, `external_handoffs`, `finalize_reviewers`), use `bmad-architecture`'s own defaults and overrides as normal:
|
||||||
|
- `activation_steps_prepend` = the resolved value from step 1
|
||||||
|
- `activation_steps_append` = the resolved value from step 1
|
||||||
|
- `persistent_facts` = the resolved value from step 1
|
||||||
|
- `on_complete` = the resolved value from step 1
|
||||||
|
- **Original user input:** forward whatever the user said when invoking this skill verbatim.
|
||||||
|
|
||||||
Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
|
`bmad-architecture` takes the workflow from here. Do not execute any further steps in this shim.
|
||||||
|
|
||||||
### Step 3: Load Persistent Facts
|
|
||||||
|
|
||||||
Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
|
|
||||||
|
|
||||||
### Step 4: Load Config
|
|
||||||
|
|
||||||
Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
|
|
||||||
- Use `{user_name}` for greeting
|
|
||||||
- Use `{communication_language}` for all communications
|
|
||||||
- Use `{document_output_language}` for output documents
|
|
||||||
- Use `{planning_artifacts}` for output location and artifact scanning
|
|
||||||
- Use `{project_knowledge}` for additional context scanning
|
|
||||||
|
|
||||||
### Step 5: Greet the User
|
|
||||||
|
|
||||||
Greet `{user_name}`, speaking in `{communication_language}`.
|
|
||||||
|
|
||||||
### Step 6: Execute Append Steps
|
|
||||||
|
|
||||||
Execute each entry in `{workflow.activation_steps_append}` in order.
|
|
||||||
|
|
||||||
Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
|
|
||||||
|
|
||||||
## Execution
|
|
||||||
|
|
||||||
Read fully and follow: `./steps/step-01-init.md` to begin the workflow.
|
|
||||||
|
|
||||||
**Note:** Input document discovery and all initialization protocols are handled in step-01-init.md.
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
---
|
|
||||||
stepsCompleted: []
|
|
||||||
inputDocuments: []
|
|
||||||
workflowType: 'architecture'
|
|
||||||
project_name: '{{project_name}}'
|
|
||||||
user_name: '{{user_name}}'
|
|
||||||
date: '{{date}}'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Architecture Decision Document
|
|
||||||
|
|
||||||
_This document builds collaboratively through step-by-step discovery. Sections are appended as we work through each architectural decision together._
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
domain,signals,complexity_level,suggested_workflow,web_searches
|
|
||||||
e_commerce,"shopping,cart,checkout,payment,products,store",medium,standard,"ecommerce architecture patterns, payment processing, inventory management"
|
|
||||||
fintech,"banking,payment,trading,finance,money,investment",high,enhanced,"financial security, PCI compliance, trading algorithms, fraud detection"
|
|
||||||
healthcare,"medical,diagnostic,clinical,patient,hospital,health",high,enhanced,"HIPAA compliance, medical data security, FDA regulations, health tech"
|
|
||||||
social,"social network,community,users,friends,posts,sharing",high,advanced,"social graph algorithms, feed ranking, notification systems, privacy"
|
|
||||||
education,"learning,course,student,teacher,training,academic",medium,standard,"LMS architecture, progress tracking, assessment systems, video streaming"
|
|
||||||
productivity,"productivity,workflow,tasks,management,business,tools",medium,standard,"collaboration patterns, real-time editing, notification systems, integration"
|
|
||||||
media,"content,media,video,audio,streaming,broadcast",high,advanced,"CDN architecture, video encoding, streaming protocols, content delivery"
|
|
||||||
iot,"IoT,sensors,devices,embedded,smart,connected",high,advanced,"device communication, real-time data processing, edge computing, security"
|
|
||||||
government,"government,civic,public,admin,policy,regulation",high,enhanced,"accessibility standards, security clearance, data privacy, audit trails"
|
|
||||||
process_control,"industrial automation,process control,PLC,SCADA,DCS,HMI,operational technology,control system,cyberphysical,MES,instrumentation,I&C,P&ID",high,advanced,"industrial process control architecture, SCADA system design, OT cybersecurity architecture, real-time control systems"
|
|
||||||
building_automation,"building automation,BAS,BMS,HVAC,smart building,fire alarm,fire protection,fire suppression,life safety,elevator,DDC,access control,sequence of operations,commissioning",high,advanced,"building automation architecture, BACnet integration patterns, smart building design, building management system security"
|
|
||||||
gaming,"game,gaming,multiplayer,real-time,interactive,entertainment",high,advanced,"real-time multiplayer, game engine architecture, matchmaking, leaderboards"
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
project_type,detection_signals,description,typical_starters
|
|
||||||
web_app,"website,web application,browser,frontend,UI,interface",Web-based applications running in browsers,Next.js, Vite, Remix
|
|
||||||
mobile_app,"mobile,iOS,Android,app,smartphone,tablet",Native mobile applications,React Native, Expo, Flutter
|
|
||||||
api_backend,"API,REST,GraphQL,backend,service,microservice",Backend services and APIs,NestJS, Express, Fastify
|
|
||||||
full_stack,"full-stack,complete,web+mobile,frontend+backend",Applications with both frontend and backend,T3 App, RedwoodJS, Blitz
|
|
||||||
cli_tool,"CLI,command line,terminal,console,tool",Command-line interface tools,oclif, Commander, Caporal
|
|
||||||
desktop_app,"desktop,Electron,Tauri,native app,macOS,Windows",Desktop applications,Electron, Tauri, Flutter Desktop
|
|
||||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
|
@ -1,153 +0,0 @@
|
||||||
# Step 1: Architecture Workflow Initialization
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on initialization and setup only - don't look ahead to future steps
|
|
||||||
- 🚪 DETECT existing workflow state and handle continuation properly
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- 💾 Initialize document and update frontmatter
|
|
||||||
- 📖 Set up frontmatter `stepsCompleted: [1]` before loading next step
|
|
||||||
- 🚫 FORBIDDEN to load next step until setup is complete
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- Variables from workflow.md are available in memory
|
|
||||||
- Previous context = what's in output document + frontmatter
|
|
||||||
- Don't assume knowledge from other steps
|
|
||||||
- Input document discovery happens in this step
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Initialize the Architecture workflow by detecting continuation state, discovering input documents, and setting up the document for collaborative architectural decision making.
|
|
||||||
|
|
||||||
## INITIALIZATION SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Check for Existing Workflow
|
|
||||||
|
|
||||||
First, check if the output document already exists:
|
|
||||||
|
|
||||||
- Look for existing {planning_artifacts}/`*architecture*.md`
|
|
||||||
- If exists, read the complete file(s) including frontmatter
|
|
||||||
- If not exists, this is a fresh workflow
|
|
||||||
|
|
||||||
### 2. Handle Continuation (If Document Exists)
|
|
||||||
|
|
||||||
If the document exists and has frontmatter with `stepsCompleted`:
|
|
||||||
|
|
||||||
- **STOP here** and load `./step-01b-continue.md` immediately
|
|
||||||
- Do not proceed with any initialization tasks
|
|
||||||
- Let step-01b handle the continuation logic
|
|
||||||
|
|
||||||
### 3. Fresh Workflow Setup (If No Document)
|
|
||||||
|
|
||||||
If no document exists or no `stepsCompleted` in frontmatter:
|
|
||||||
|
|
||||||
#### A. Input Document Discovery
|
|
||||||
|
|
||||||
Discover and load context documents using smart discovery. Documents can be in the following locations:
|
|
||||||
- {planning_artifacts}/**
|
|
||||||
- {output_folder}/**
|
|
||||||
- {project_knowledge}/**
|
|
||||||
- {project-root}/docs/**
|
|
||||||
|
|
||||||
Also - when searching - documents can be a single markdown file, or a folder with an index and multiple files. For Example, if searching for `*foo*.md` and not found, also search for a folder called *foo*/index.md (which indicates sharded content)
|
|
||||||
|
|
||||||
Try to discover the following:
|
|
||||||
- Product Brief (`*brief*.md`)
|
|
||||||
- Product Requirements Document (`*prd*.md`)
|
|
||||||
- UX Design (`*ux-design*.md`) and other
|
|
||||||
- Research Documents (`*research*.md`)
|
|
||||||
- Project Documentation (generally multiple documents might be found for this in the `{project_knowledge}` or `{project-root}/docs` folder.)
|
|
||||||
- Project Context (`**/project-context.md`)
|
|
||||||
|
|
||||||
<critical>Confirm what you have found with the user, along with asking if the user wants to provide anything else. Only after this confirmation will you proceed to follow the loading rules</critical>
|
|
||||||
|
|
||||||
**Loading Rules:**
|
|
||||||
|
|
||||||
- Load ALL discovered files completely that the user confirmed or provided (no offset/limit)
|
|
||||||
- If there is a project context, whatever is relevant should try to be biased in the remainder of this whole workflow process
|
|
||||||
- For sharded folders, load ALL files to get complete picture, using the index first to potentially know the potential of each document
|
|
||||||
- index.md is a guide to what's relevant whenever available
|
|
||||||
- Track all successfully loaded files in frontmatter `inputDocuments` array
|
|
||||||
|
|
||||||
#### B. Validate Required Inputs
|
|
||||||
|
|
||||||
Before proceeding, verify we have the essential inputs:
|
|
||||||
|
|
||||||
**PRD Validation:**
|
|
||||||
|
|
||||||
- If no PRD found: "Architecture requires a PRD to work from. Please run the PRD workflow first or provide the PRD file path."
|
|
||||||
- Do NOT proceed without PRD
|
|
||||||
|
|
||||||
**Other Input that might exist:**
|
|
||||||
|
|
||||||
- UX Spec: "Provides UI/UX architectural requirements"
|
|
||||||
|
|
||||||
#### C. Create Initial Document
|
|
||||||
|
|
||||||
Copy the template from `../architecture-decision-template.md` to `{planning_artifacts}/architecture.md`
|
|
||||||
|
|
||||||
#### D. Complete Initialization and Report
|
|
||||||
|
|
||||||
Complete setup and report to user:
|
|
||||||
|
|
||||||
**Document Setup:**
|
|
||||||
|
|
||||||
- Created: `{planning_artifacts}/architecture.md` from template
|
|
||||||
- Initialized frontmatter with workflow state
|
|
||||||
|
|
||||||
**Input Documents Discovered:**
|
|
||||||
Report what was found:
|
|
||||||
"Welcome {{user_name}}! I've set up your Architecture workspace for {{project_name}}.
|
|
||||||
|
|
||||||
**Documents Found:**
|
|
||||||
|
|
||||||
- PRD: {number of PRD files loaded or "None found - REQUIRED"}
|
|
||||||
- UX Design: {number of UX files loaded or "None found"}
|
|
||||||
- Research: {number of research files loaded or "None found"}
|
|
||||||
- Project docs: {number of project files loaded or "None found"}
|
|
||||||
- Project context: {project_context_rules count of rules for AI agents found}
|
|
||||||
|
|
||||||
**Files loaded:** {list of specific file names or "No additional documents found"}
|
|
||||||
|
|
||||||
Ready to begin architectural decision making. Do you have any other documents you'd like me to include?
|
|
||||||
|
|
||||||
[C] Continue to project context analysis
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ Existing workflow detected and handed off to step-01b correctly
|
|
||||||
✅ Fresh workflow initialized with template and frontmatter
|
|
||||||
✅ Input documents discovered and loaded using sharded-first logic
|
|
||||||
✅ All discovered files tracked in frontmatter `inputDocuments`
|
|
||||||
✅ PRD requirement validated and communicated
|
|
||||||
✅ User confirmed document setup and can proceed
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Proceeding with fresh initialization when existing workflow exists
|
|
||||||
❌ Not updating frontmatter with discovered input documents
|
|
||||||
❌ Creating document without proper template
|
|
||||||
❌ Not checking sharded folders first before whole files
|
|
||||||
❌ Not reporting what documents were found to user
|
|
||||||
❌ Proceeding without validating PRD requirement
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects [C] to continue, only after ensuring all the template output has been created, then load `./step-02-context.md` to analyze the project context and begin architectural decision making.
|
|
||||||
|
|
||||||
Remember: Do NOT proceed to step-02 until user explicitly selects [C] from the menu and setup is confirmed!
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
||||||
# Step 1b: Workflow Continuation Handler
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on understanding current state and getting user confirmation
|
|
||||||
- 🚪 HANDLE workflow resumption smoothly and transparently
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- 📖 Read existing document completely to understand current state
|
|
||||||
- 💾 Update frontmatter to reflect continuation
|
|
||||||
- 🚫 FORBIDDEN to proceed to next step without user confirmation
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- Existing document and frontmatter are available
|
|
||||||
- Input documents already loaded should be in frontmatter `inputDocuments`
|
|
||||||
- Steps already completed are in `stepsCompleted` array
|
|
||||||
- Focus on understanding where we left off
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Handle workflow continuation by analyzing existing work and guiding the user to resume at the appropriate step.
|
|
||||||
|
|
||||||
## CONTINUATION SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Analyze Current Document State
|
|
||||||
|
|
||||||
Read the existing architecture document completely and analyze:
|
|
||||||
|
|
||||||
**Frontmatter Analysis:**
|
|
||||||
|
|
||||||
- `stepsCompleted`: What steps have been done
|
|
||||||
- `inputDocuments`: What documents were loaded
|
|
||||||
- `lastStep`: Last step that was executed
|
|
||||||
- `project_name`, `user_name`, `date`: Basic context
|
|
||||||
|
|
||||||
**Content Analysis:**
|
|
||||||
|
|
||||||
- What sections exist in the document
|
|
||||||
- What architectural decisions have been made
|
|
||||||
- What appears incomplete or in progress
|
|
||||||
- Any TODOs or placeholders remaining
|
|
||||||
|
|
||||||
### 2. Present Continuation Summary
|
|
||||||
|
|
||||||
Show the user their current progress:
|
|
||||||
|
|
||||||
"Welcome back {{user_name}}! I found your Architecture work for {{project_name}}.
|
|
||||||
|
|
||||||
**Current Progress:**
|
|
||||||
|
|
||||||
- Steps completed: {{stepsCompleted list}}
|
|
||||||
- Last step worked on: Step {{lastStep}}
|
|
||||||
- Input documents loaded: {{number of inputDocuments}} files
|
|
||||||
|
|
||||||
**Document Sections Found:**
|
|
||||||
{list all H2/H3 sections found in the document}
|
|
||||||
|
|
||||||
{if_incomplete_sections}
|
|
||||||
**Incomplete Areas:**
|
|
||||||
|
|
||||||
- {areas that appear incomplete or have placeholders}
|
|
||||||
{/if_incomplete_sections}
|
|
||||||
|
|
||||||
**What would you like to do?**
|
|
||||||
[R] Resume from where we left off
|
|
||||||
[C] Continue to next logical step
|
|
||||||
[O] Overview of all remaining steps
|
|
||||||
[X] Start over (will overwrite existing work)
|
|
||||||
"
|
|
||||||
|
|
||||||
### 3. Handle User Choice
|
|
||||||
|
|
||||||
#### If 'R' (Resume from where we left off):
|
|
||||||
|
|
||||||
- Identify the next step based on `stepsCompleted`
|
|
||||||
- Load the appropriate step file to continue
|
|
||||||
- Example: If `stepsCompleted: [1, 2, 3]`, load `./step-04-decisions.md`
|
|
||||||
|
|
||||||
#### If 'C' (Continue to next logical step):
|
|
||||||
|
|
||||||
- Analyze the document content to determine logical next step
|
|
||||||
- May need to review content quality and completeness
|
|
||||||
- If content seems complete for current step, advance to next
|
|
||||||
- If content seems incomplete, suggest staying on current step
|
|
||||||
|
|
||||||
#### If 'O' (Overview of all remaining steps):
|
|
||||||
|
|
||||||
- Provide brief description of all remaining steps
|
|
||||||
- Let user choose which step to work on
|
|
||||||
- Don't assume sequential progression is always best
|
|
||||||
|
|
||||||
#### If 'X' (Start over):
|
|
||||||
|
|
||||||
- Confirm: "This will delete all existing architectural decisions. Are you sure? (y/n)"
|
|
||||||
- If confirmed: Delete existing document and read fully and follow: `./step-01-init.md`
|
|
||||||
- If not confirmed: Return to continuation menu
|
|
||||||
|
|
||||||
### 4. Navigate to Selected Step
|
|
||||||
|
|
||||||
After user makes choice:
|
|
||||||
|
|
||||||
**Load the selected step file:**
|
|
||||||
|
|
||||||
- Update frontmatter `lastStep` to reflect current navigation
|
|
||||||
- Execute the selected step file
|
|
||||||
- Let that step handle the detailed continuation logic
|
|
||||||
|
|
||||||
**State Preservation:**
|
|
||||||
|
|
||||||
- Maintain all existing content in the document
|
|
||||||
- Keep `stepsCompleted` accurate
|
|
||||||
- Track the resumption in workflow status
|
|
||||||
|
|
||||||
### 5. Special Continuation Cases
|
|
||||||
|
|
||||||
#### If `stepsCompleted` is empty but document has content:
|
|
||||||
|
|
||||||
- This suggests an interrupted workflow
|
|
||||||
- Ask user: "I see the document has content but no steps are marked as complete. Should I analyze what's here and set the appropriate step status?"
|
|
||||||
|
|
||||||
#### If document appears corrupted or incomplete:
|
|
||||||
|
|
||||||
- Ask user: "The document seems incomplete. Would you like me to try to recover what's here, or would you prefer to start fresh?"
|
|
||||||
|
|
||||||
#### If document is complete but workflow not marked as done:
|
|
||||||
|
|
||||||
- Ask user: "The architecture looks complete! Should I mark this workflow as finished, or is there more you'd like to work on?"
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ Existing document state properly analyzed and understood
|
|
||||||
✅ User presented with clear continuation options
|
|
||||||
✅ User choice handled appropriately and transparently
|
|
||||||
✅ Workflow state preserved and updated correctly
|
|
||||||
✅ Navigation to appropriate step handled smoothly
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Not reading the complete existing document before making suggestions
|
|
||||||
❌ Losing track of what steps were actually completed
|
|
||||||
❌ Automatically proceeding without user confirmation of next steps
|
|
||||||
❌ Not checking for incomplete or placeholder content
|
|
||||||
❌ Losing existing document content during resumption
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects their continuation option, load the appropriate step file based on their choice. The step file will handle the detailed work from that point forward.
|
|
||||||
|
|
||||||
Valid step files to load:
|
|
||||||
- `./step-02-context.md`
|
|
||||||
- `./step-03-starter.md`
|
|
||||||
- `./step-04-decisions.md`
|
|
||||||
- `./step-05-patterns.md`
|
|
||||||
- `./step-06-structure.md`
|
|
||||||
- `./step-07-validation.md`
|
|
||||||
- `./step-08-complete.md`
|
|
||||||
|
|
||||||
Remember: The goal is smooth, transparent resumption that respects the work already done while giving the user control over how to proceed.
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
||||||
# Step 2: Project Context Analysis
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on understanding project scope and requirements for architecture
|
|
||||||
- 🎯 ANALYZE loaded documents, don't assume or generate requirements
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- ⚠️ Present A/P/C menu after generating project context analysis
|
|
||||||
- 💾 ONLY save when user chooses C (Continue)
|
|
||||||
- 📖 Update frontmatter `stepsCompleted: [1, 2]` before loading next step
|
|
||||||
- 🚫 FORBIDDEN to load next step until C is selected
|
|
||||||
|
|
||||||
## COLLABORATION MENUS (A/P/C):
|
|
||||||
|
|
||||||
This step will generate content and present choices:
|
|
||||||
|
|
||||||
- **A (Advanced Elicitation)**: Use discovery protocols to develop deeper insights about project context and architectural implications
|
|
||||||
- **P (Party Mode)**: Bring multiple perspectives to analyze project requirements from different architectural angles
|
|
||||||
- **C (Continue)**: Save the content to the document and proceed to next step
|
|
||||||
|
|
||||||
## PROTOCOL INTEGRATION:
|
|
||||||
|
|
||||||
- When 'A' selected: Invoke the `bmad-advanced-elicitation` skill
|
|
||||||
- When 'P' selected: Invoke the `bmad-party-mode` skill
|
|
||||||
- PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed
|
|
||||||
- User accepts/rejects protocol changes before proceeding
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- Current document and frontmatter from step 1 are available
|
|
||||||
- Input documents already loaded are in memory (PRD, epics, UX spec, etc.)
|
|
||||||
- Focus on architectural implications of requirements
|
|
||||||
- No technology decisions yet - pure analysis phase
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Fully read and Analyze the loaded project documents to understand architectural scope, requirements, and constraints before beginning decision making.
|
|
||||||
|
|
||||||
## CONTEXT ANALYSIS SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Review Project Requirements
|
|
||||||
|
|
||||||
**From PRD Analysis:**
|
|
||||||
|
|
||||||
- Extract and analyze Functional Requirements (FRs)
|
|
||||||
- Identify Non-Functional Requirements (NFRs) like performance, security, compliance
|
|
||||||
- Note any technical constraints or dependencies mentioned
|
|
||||||
- Count and categorize requirements to understand project scale
|
|
||||||
|
|
||||||
**From Epics/Stories (if available):**
|
|
||||||
|
|
||||||
- Map epic structure and user stories to architectural components
|
|
||||||
- Extract acceptance criteria for technical implications
|
|
||||||
- Identify cross-cutting concerns that span multiple epics
|
|
||||||
- Estimate story complexity for architectural planning
|
|
||||||
|
|
||||||
**From UX Design (if available):**
|
|
||||||
|
|
||||||
- Extract architectural implications from UX requirements:
|
|
||||||
- Component complexity (simple forms vs rich interactions)
|
|
||||||
- Animation/transition requirements
|
|
||||||
- Real-time update needs (live data, collaborative features)
|
|
||||||
- Platform-specific UI requirements
|
|
||||||
- Accessibility standards (WCAG compliance level)
|
|
||||||
- Responsive design breakpoints
|
|
||||||
- Offline capability requirements
|
|
||||||
- Performance expectations (load times, interaction responsiveness)
|
|
||||||
|
|
||||||
### 2. Project Scale Assessment
|
|
||||||
|
|
||||||
Calculate and present project complexity:
|
|
||||||
|
|
||||||
**Complexity Indicators:**
|
|
||||||
|
|
||||||
- Real-time features requirements
|
|
||||||
- Multi-tenancy needs
|
|
||||||
- Regulatory compliance requirements
|
|
||||||
- Integration complexity
|
|
||||||
- User interaction complexity
|
|
||||||
- Data complexity and volume
|
|
||||||
|
|
||||||
### 3. Reflect Understanding
|
|
||||||
|
|
||||||
Present your analysis back to user for validation:
|
|
||||||
|
|
||||||
"I'm reviewing your project documentation for {{project_name}}.
|
|
||||||
|
|
||||||
{if_epics_loaded}I see {{epic_count}} epics with {{story_count}} total stories.{/if_epics_loaded}
|
|
||||||
{if_no_epics}I found {{fr_count}} functional requirements organized into {{fr_category_list}}.{/if_no_epics}
|
|
||||||
{if_ux_loaded}I also found your UX specification which defines the user experience requirements.{/if_ux_loaded}
|
|
||||||
|
|
||||||
**Key architectural aspects I notice:**
|
|
||||||
|
|
||||||
- [Summarize core functionality from FRs]
|
|
||||||
- [Note critical NFRs that will shape architecture]
|
|
||||||
- {if_ux_loaded}[Note UX complexity and technical requirements]{/if_ux_loaded}
|
|
||||||
- [Identify unique technical challenges or constraints]
|
|
||||||
- [Highlight any regulatory or compliance requirements]
|
|
||||||
|
|
||||||
**Scale indicators:**
|
|
||||||
|
|
||||||
- Project complexity appears to be: [low/medium/high/enterprise]
|
|
||||||
- Primary technical domain: [web/mobile/api/backend/full-stack/etc]
|
|
||||||
- Cross-cutting concerns identified: [list major ones]
|
|
||||||
|
|
||||||
This analysis will help me guide you through the architectural decisions needed to ensure AI agents implement this consistently.
|
|
||||||
|
|
||||||
Does this match your understanding of the project scope and requirements?"
|
|
||||||
|
|
||||||
### 4. Generate Project Context Content
|
|
||||||
|
|
||||||
Prepare the content to append to the document:
|
|
||||||
|
|
||||||
#### Content Structure:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
## Project Context Analysis
|
|
||||||
|
|
||||||
### Requirements Overview
|
|
||||||
|
|
||||||
**Functional Requirements:**
|
|
||||||
{{analysis of FRs and what they mean architecturally}}
|
|
||||||
|
|
||||||
**Non-Functional Requirements:**
|
|
||||||
{{NFRs that will drive architectural decisions}}
|
|
||||||
|
|
||||||
**Scale & Complexity:**
|
|
||||||
{{project_scale_assessment}}
|
|
||||||
|
|
||||||
- Primary domain: {{technical_domain}}
|
|
||||||
- Complexity level: {{complexity_level}}
|
|
||||||
- Estimated architectural components: {{component_count}}
|
|
||||||
|
|
||||||
### Technical Constraints & Dependencies
|
|
||||||
|
|
||||||
{{known_constraints_dependencies}}
|
|
||||||
|
|
||||||
### Cross-Cutting Concerns Identified
|
|
||||||
|
|
||||||
{{concerns_that_will_affect_multiple_components}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Present Content and Menu
|
|
||||||
|
|
||||||
Show the generated content and present choices:
|
|
||||||
|
|
||||||
"I've drafted the Project Context Analysis based on your requirements. This sets the foundation for our architectural decisions.
|
|
||||||
|
|
||||||
**Here's what I'll add to the document:**
|
|
||||||
|
|
||||||
[Show the complete markdown content from step 4]
|
|
||||||
|
|
||||||
**What would you like to do?**
|
|
||||||
[A] Advanced Elicitation - Let's dive deeper into architectural implications
|
|
||||||
[P] Party Mode - Bring different perspectives to analyze requirements
|
|
||||||
[C] Continue - Save this analysis and begin architectural decisions"
|
|
||||||
|
|
||||||
### 6. Handle Menu Selection
|
|
||||||
|
|
||||||
#### If 'A' (Advanced Elicitation):
|
|
||||||
|
|
||||||
- Invoke the `bmad-advanced-elicitation` skill with the current context analysis
|
|
||||||
- Process the enhanced architectural insights that come back
|
|
||||||
- Ask user: "Accept these enhancements to the project context analysis? (y/n)"
|
|
||||||
- If yes: Update content with improvements, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'P' (Party Mode):
|
|
||||||
|
|
||||||
- Invoke the `bmad-party-mode` skill with the current project context
|
|
||||||
- Process the collaborative improvements to architectural understanding
|
|
||||||
- Ask user: "Accept these changes to the project context analysis? (y/n)"
|
|
||||||
- If yes: Update content with improvements, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'C' (Continue):
|
|
||||||
|
|
||||||
- Append the final content to `{planning_artifacts}/architecture.md`
|
|
||||||
- Update frontmatter: `stepsCompleted: [1, 2]`
|
|
||||||
- Load `./step-03-starter.md`
|
|
||||||
|
|
||||||
## APPEND TO DOCUMENT:
|
|
||||||
|
|
||||||
When user selects 'C', append the content directly to the document using the structure from step 4.
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ All input documents thoroughly analyzed for architectural implications
|
|
||||||
✅ Project scope and complexity clearly assessed and validated
|
|
||||||
✅ Technical constraints and dependencies identified
|
|
||||||
✅ Cross-cutting concerns mapped for architectural planning
|
|
||||||
✅ User confirmation of project understanding
|
|
||||||
✅ A/P/C menu presented and handled correctly
|
|
||||||
✅ Content properly appended to document when C selected
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Skimming documents without deep architectural analysis
|
|
||||||
❌ Missing or misinterpreting critical NFRs
|
|
||||||
❌ Not validating project understanding with user
|
|
||||||
❌ Underestimating complexity indicators
|
|
||||||
❌ Generating content without real analysis of loaded documents
|
|
||||||
❌ Not presenting A/P/C menu after content generation
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects 'C' and content is saved to document, load `./step-03-starter.md` to evaluate starter template options.
|
|
||||||
|
|
||||||
Remember: Do NOT proceed to step-03 until user explicitly selects 'C' from the A/P/C menu and content is saved!
|
|
||||||
|
|
@ -1,329 +0,0 @@
|
||||||
# Step 3: Starter Template Evaluation
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on evaluating starter template options with current versions
|
|
||||||
- 🌐 ALWAYS search the web to verify current versions - NEVER trust hardcoded versions
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete architecture
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- 🌐 Search the web to verify current versions and options
|
|
||||||
- ⚠️ Present A/P/C menu after generating starter template analysis
|
|
||||||
- 💾 ONLY save when user chooses C (Continue)
|
|
||||||
- 📖 Update frontmatter `stepsCompleted: [1, 2, 3]` before loading next step
|
|
||||||
- 🚫 FORBIDDEN to load next step until C is selected
|
|
||||||
|
|
||||||
## COLLABORATION MENUS (A/P/C):
|
|
||||||
|
|
||||||
This step will generate content and present choices:
|
|
||||||
|
|
||||||
- **A (Advanced Elicitation)**: Use discovery protocols to explore unconventional starter options or custom approaches
|
|
||||||
- **P (Party Mode)**: Bring multiple perspectives to evaluate starter trade-offs for different use cases
|
|
||||||
- **C (Continue)**: Save the content to the document and proceed to next step
|
|
||||||
|
|
||||||
## PROTOCOL INTEGRATION:
|
|
||||||
|
|
||||||
- When 'A' selected: Invoke the `bmad-advanced-elicitation` skill
|
|
||||||
- When 'P' selected: Invoke the `bmad-party-mode` skill
|
|
||||||
- PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed
|
|
||||||
- User accepts/rejects protocol changes before proceeding
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- Project context from step 2 is available and complete
|
|
||||||
- Project context file from step-01 may contain technical preferences
|
|
||||||
- No architectural decisions made yet - evaluating foundations
|
|
||||||
- Focus on technical preferences discovery and starter evaluation
|
|
||||||
- Consider project requirements and existing preferences when evaluating options
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Discover technical preferences and evaluate starter template options, leveraging existing technical preferences and establishing solid architectural foundations.
|
|
||||||
|
|
||||||
## STARTER EVALUATION SEQUENCE:
|
|
||||||
|
|
||||||
### 0. Check Technical Preferences & Context
|
|
||||||
|
|
||||||
**Check Project Context for Existing Technical Preferences:**
|
|
||||||
"Before we dive into starter templates, let me check if you have any technical preferences already documented.
|
|
||||||
|
|
||||||
{{if_project_context_exists}}
|
|
||||||
I found some technical rules in your project context file:
|
|
||||||
{{extracted_technical_preferences_from_project_context}}
|
|
||||||
|
|
||||||
**Project Context Technical Rules Found:**
|
|
||||||
|
|
||||||
- Languages/Frameworks: {{languages_frameworks_from_context}}
|
|
||||||
- Tools & Libraries: {{tools_from_context}}
|
|
||||||
- Development Patterns: {{patterns_from_context}}
|
|
||||||
- Platform Preferences: {{platforms_from_context}}
|
|
||||||
|
|
||||||
{{else}}
|
|
||||||
No existing technical preferences found in project context file. We'll establish your technical preferences now.
|
|
||||||
{{/if_project_context}}"
|
|
||||||
|
|
||||||
**Discover User Technical Preferences:**
|
|
||||||
"Based on your project context, let's discuss your technical preferences:
|
|
||||||
|
|
||||||
{{primary_technology_category}} Preferences:
|
|
||||||
|
|
||||||
- **Languages**: Do you have preferences between TypeScript/JavaScript, Python, Go, Rust, etc.?
|
|
||||||
- **Frameworks**: Any existing familiarity or preferences (React, Vue, Angular, Next.js, etc.)?
|
|
||||||
- **Databases**: Any preferences or existing infrastructure (PostgreSQL, MongoDB, MySQL, etc.)?
|
|
||||||
|
|
||||||
**Development Experience:**
|
|
||||||
|
|
||||||
- What's your team's experience level with different technologies?
|
|
||||||
- Are there any technologies you want to learn vs. what you're comfortable with?
|
|
||||||
|
|
||||||
**Platform/Deployment Preferences:**
|
|
||||||
|
|
||||||
- Cloud provider preferences (AWS, Vercel, Railway, etc.)?
|
|
||||||
- Container preferences (Docker, Serverless, Traditional)?
|
|
||||||
|
|
||||||
**Integrations:**
|
|
||||||
|
|
||||||
- Any existing systems or APIs you need to integrate with?
|
|
||||||
- Third-party services you plan to use (payment, authentication, analytics, etc.)?
|
|
||||||
|
|
||||||
These preferences will help me recommend the most suitable starter templates and guide our architectural decisions."
|
|
||||||
|
|
||||||
### 1. Identify Primary Technology Domain
|
|
||||||
|
|
||||||
Based on project context analysis and technical preferences, identify the primary technology stack:
|
|
||||||
|
|
||||||
- **Web application** → Look for Next.js, Vite, Remix, SvelteKit starters
|
|
||||||
- **Mobile app** → Look for React Native, Expo, Flutter starters
|
|
||||||
- **API/Backend** → Look for NestJS, Express, Fastify, Supabase starters
|
|
||||||
- **CLI tool** → Look for CLI framework starters (oclif, commander, etc.)
|
|
||||||
- **Full-stack** → Look for T3, RedwoodJS, Blitz, Next.js starters
|
|
||||||
- **Desktop** → Look for Electron, Tauri starters
|
|
||||||
|
|
||||||
### 2. UX Requirements Consideration
|
|
||||||
|
|
||||||
If UX specification was loaded, consider UX requirements when selecting starter:
|
|
||||||
|
|
||||||
- **Rich animations** → Framer Motion compatible starter
|
|
||||||
- **Complex forms** → React Hook Form included starter
|
|
||||||
- **Real-time features** → Socket.io or WebSocket ready starter
|
|
||||||
- **Design system** → Storybook-enabled starter
|
|
||||||
- **Offline capability** → Service worker or PWA configured starter
|
|
||||||
|
|
||||||
### 3. Research Current Starter Options
|
|
||||||
|
|
||||||
Search the web to find current, maintained starter templates:
|
|
||||||
|
|
||||||
```
|
|
||||||
Search the web: "{{primary_technology}} starter template CLI create command latest"
|
|
||||||
Search the web: "{{primary_technology}} boilerplate generator latest options"
|
|
||||||
Search the web: "{{primary_technology}} production-ready starter best practices"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Investigate Top Starter Options
|
|
||||||
|
|
||||||
For each promising starter found, investigate details:
|
|
||||||
|
|
||||||
```
|
|
||||||
Search the web: "{{starter_name}} default setup technologies included latest"
|
|
||||||
Search the web: "{{starter_name}} project structure file organization"
|
|
||||||
Search the web: "{{starter_name}} production deployment capabilities"
|
|
||||||
Search the web: "{{starter_name}} recent updates maintenance status"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Analyze What Each Starter Provides
|
|
||||||
|
|
||||||
For each viable starter option, document:
|
|
||||||
|
|
||||||
**Technology Decisions Made:**
|
|
||||||
|
|
||||||
- Language/TypeScript configuration
|
|
||||||
- Styling solution (CSS, Tailwind, Styled Components, etc.)
|
|
||||||
- Testing framework setup
|
|
||||||
- Linting/Formatting configuration
|
|
||||||
- Build tooling and optimization
|
|
||||||
- Project structure and organization
|
|
||||||
|
|
||||||
**Architectural Patterns Established:**
|
|
||||||
|
|
||||||
- Code organization patterns
|
|
||||||
- Component structure conventions
|
|
||||||
- API layering approach
|
|
||||||
- State management setup
|
|
||||||
- Routing patterns
|
|
||||||
- Environment configuration
|
|
||||||
|
|
||||||
**Development Experience Features:**
|
|
||||||
|
|
||||||
- Hot reloading and development server
|
|
||||||
- TypeScript configuration
|
|
||||||
- Debugging setup
|
|
||||||
- Testing infrastructure
|
|
||||||
- Documentation generation
|
|
||||||
|
|
||||||
### 6. Present Starter Options
|
|
||||||
|
|
||||||
Based on user skill level and project needs:
|
|
||||||
|
|
||||||
**For Expert Users:**
|
|
||||||
"Found {{starter_name}} which provides:
|
|
||||||
{{quick_decision_list_of_key_decisions}}
|
|
||||||
|
|
||||||
This would establish our base architecture with these technical decisions already made. Use it?"
|
|
||||||
|
|
||||||
**For Intermediate Users:**
|
|
||||||
"I found {{starter_name}}, which is a well-maintained starter for {{project_type}} projects.
|
|
||||||
|
|
||||||
It makes these architectural decisions for us:
|
|
||||||
{{decision_list_with_explanations}}
|
|
||||||
|
|
||||||
This gives us a solid foundation following current best practices. Should we use it?"
|
|
||||||
|
|
||||||
**For Beginner Users:**
|
|
||||||
"I found {{starter_name}}, which is like a pre-built foundation for your project.
|
|
||||||
|
|
||||||
Think of it like buying a prefab house frame instead of cutting each board yourself.
|
|
||||||
|
|
||||||
It makes these decisions for us:
|
|
||||||
{{friendly_explanation_of_decisions}}
|
|
||||||
|
|
||||||
This is a great starting point that follows best practices and saves us from making dozens of small technical choices. Should we use it?"
|
|
||||||
|
|
||||||
### 7. Get Current CLI Commands
|
|
||||||
|
|
||||||
If user shows interest in a starter, get the exact current commands:
|
|
||||||
|
|
||||||
```
|
|
||||||
Search the web: "{{starter_name}} CLI command options flags latest"
|
|
||||||
Search the web: "{{starter_name}} create new project command examples"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Generate Starter Template Content
|
|
||||||
|
|
||||||
Prepare the content to append to the document:
|
|
||||||
|
|
||||||
#### Content Structure:
|
|
||||||
|
|
||||||
````markdown
|
|
||||||
## Starter Template Evaluation
|
|
||||||
|
|
||||||
### Primary Technology Domain
|
|
||||||
|
|
||||||
{{identified_domain}} based on project requirements analysis
|
|
||||||
|
|
||||||
### Starter Options Considered
|
|
||||||
|
|
||||||
{{analysis_of_evaluated_starters}}
|
|
||||||
|
|
||||||
### Selected Starter: {{starter_name}}
|
|
||||||
|
|
||||||
**Rationale for Selection:**
|
|
||||||
{{why_this_starter_was_chosen}}
|
|
||||||
|
|
||||||
**Initialization Command:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
{{full_starter_command_with_options}}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Architectural Decisions Provided by Starter:**
|
|
||||||
|
|
||||||
**Language & Runtime:**
|
|
||||||
{{language_typescript_setup}}
|
|
||||||
|
|
||||||
**Styling Solution:**
|
|
||||||
{{styling_solution_configuration}}
|
|
||||||
|
|
||||||
**Build Tooling:**
|
|
||||||
{{build_tools_and_optimization}}
|
|
||||||
|
|
||||||
**Testing Framework:**
|
|
||||||
{{testing_setup_and_configuration}}
|
|
||||||
|
|
||||||
**Code Organization:**
|
|
||||||
{{project_structure_and_patterns}}
|
|
||||||
|
|
||||||
**Development Experience:**
|
|
||||||
{{development_tools_and_workflow}}
|
|
||||||
|
|
||||||
**Note:** Project initialization using this command should be the first implementation story.
|
|
||||||
|
|
||||||
````
|
|
||||||
|
|
||||||
### 9. Present Content and Menu
|
|
||||||
|
|
||||||
Show the generated content and present choices:
|
|
||||||
|
|
||||||
"I've analyzed starter template options for {{project_type}} projects.
|
|
||||||
|
|
||||||
**Here's what I'll add to the document:**
|
|
||||||
|
|
||||||
[Show the complete markdown content from step 8]
|
|
||||||
|
|
||||||
**What would you like to do?**
|
|
||||||
[A] Advanced Elicitation - Explore custom approaches or unconventional starters
|
|
||||||
[P] Party Mode - Evaluate trade-offs from different perspectives
|
|
||||||
[C] Continue - Save this decision and move to architectural decisions"
|
|
||||||
|
|
||||||
### 10. Handle Menu Selection
|
|
||||||
|
|
||||||
#### If 'A' (Advanced Elicitation):
|
|
||||||
|
|
||||||
- Invoke the `bmad-advanced-elicitation` skill with current starter analysis
|
|
||||||
- Process enhanced insights about starter options or custom approaches
|
|
||||||
- Ask user: "Accept these changes to the starter template evaluation? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'P' (Party Mode):
|
|
||||||
|
|
||||||
- Invoke the `bmad-party-mode` skill with starter evaluation context
|
|
||||||
- Process collaborative insights about starter trade-offs
|
|
||||||
- Ask user: "Accept these changes to the starter template evaluation? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'C' (Continue):
|
|
||||||
|
|
||||||
- Append the final content to `{planning_artifacts}/architecture.md`
|
|
||||||
- Update frontmatter: `stepsCompleted: [1, 2, 3]`
|
|
||||||
- Load `./step-04-decisions.md`
|
|
||||||
|
|
||||||
## APPEND TO DOCUMENT:
|
|
||||||
|
|
||||||
When user selects 'C', append the content directly to the document using the structure from step 8.
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ Primary technology domain correctly identified from project context
|
|
||||||
✅ Current, maintained starter templates researched and evaluated
|
|
||||||
✅ All versions verified using web search, not hardcoded
|
|
||||||
✅ Architectural implications of starter choice clearly documented
|
|
||||||
✅ User provided with clear rationale for starter selection
|
|
||||||
✅ A/P/C menu presented and handled correctly
|
|
||||||
✅ Content properly appended to document when C selected
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Not verifying current versions with web search
|
|
||||||
❌ Ignoring UX requirements when evaluating starters
|
|
||||||
❌ Not documenting what architectural decisions the starter makes
|
|
||||||
❌ Failing to consider maintenance status of starter templates
|
|
||||||
❌ Not providing clear rationale for starter selection
|
|
||||||
❌ Not presenting A/P/C menu after content generation
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects 'C' and content is saved to document, load `./step-04-decisions.md` to begin making specific architectural decisions.
|
|
||||||
|
|
||||||
Remember: Do NOT proceed to step-04 until user explicitly selects 'C' from the A/P/C menu and content is saved!
|
|
||||||
|
|
@ -1,318 +0,0 @@
|
||||||
# Step 4: Core Architectural Decisions
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on making critical architectural decisions collaboratively
|
|
||||||
- 🌐 ALWAYS search the web to verify current technology versions
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- 🌐 Search the web to verify technology versions and options
|
|
||||||
- ⚠️ Present A/P/C menu after each major decision category
|
|
||||||
- 💾 ONLY save when user chooses C (Continue)
|
|
||||||
- 📖 Update frontmatter `stepsCompleted: [1, 2, 3, 4]` before loading next step
|
|
||||||
- 🚫 FORBIDDEN to load next step until C is selected
|
|
||||||
|
|
||||||
## COLLABORATION MENUS (A/P/C):
|
|
||||||
|
|
||||||
This step will generate content and present choices for each decision category:
|
|
||||||
|
|
||||||
- **A (Advanced Elicitation)**: Use discovery protocols to explore innovative approaches to specific decisions
|
|
||||||
- **P (Party Mode)**: Bring multiple perspectives to evaluate decision trade-offs
|
|
||||||
- **C (Continue)**: Save the current decisions and proceed to next decision category
|
|
||||||
|
|
||||||
## PROTOCOL INTEGRATION:
|
|
||||||
|
|
||||||
- When 'A' selected: Invoke the `bmad-advanced-elicitation` skill
|
|
||||||
- When 'P' selected: Invoke the `bmad-party-mode` skill
|
|
||||||
- PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed
|
|
||||||
- User accepts/rejects protocol changes before proceeding
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- Project context from step 2 is available
|
|
||||||
- Starter template choice from step 3 is available
|
|
||||||
- Project context file may contain technical preferences and rules
|
|
||||||
- Technical preferences discovered in step 3 are available
|
|
||||||
- Focus on decisions not already made by starter template or existing preferences
|
|
||||||
- Collaborative decision making, not recommendations
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Facilitate collaborative architectural decision making, leveraging existing technical preferences and starter template decisions, focusing on remaining choices critical to the project's success.
|
|
||||||
|
|
||||||
## DECISION MAKING SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Load Decision Framework & Check Existing Preferences
|
|
||||||
|
|
||||||
**Review Technical Preferences from Step 3:**
|
|
||||||
"Based on our technical preferences discussion in step 3, let's build on those foundations:
|
|
||||||
|
|
||||||
**Your Technical Preferences:**
|
|
||||||
{{user_technical_preferences_from_step_3}}
|
|
||||||
|
|
||||||
**Starter Template Decisions:**
|
|
||||||
{{starter_template_decisions}}
|
|
||||||
|
|
||||||
**Project Context Technical Rules:**
|
|
||||||
{{project_context_technical_rules}}"
|
|
||||||
|
|
||||||
**Identify Remaining Decisions:**
|
|
||||||
Based on technical preferences, starter template choice, and project context, identify remaining critical decisions:
|
|
||||||
|
|
||||||
**Already Decided (Don't re-decide these):**
|
|
||||||
|
|
||||||
- {{starter_template_decisions}}
|
|
||||||
- {{user_technology_preferences}}
|
|
||||||
- {{project_context_technical_rules}}
|
|
||||||
|
|
||||||
**Critical Decisions:** Must be decided before implementation can proceed
|
|
||||||
**Important Decisions:** Shape the architecture significantly
|
|
||||||
**Nice-to-Have:** Can be deferred if needed
|
|
||||||
|
|
||||||
### 2. Decision Categories by Priority
|
|
||||||
|
|
||||||
#### Category 1: Data Architecture
|
|
||||||
|
|
||||||
- Database choice (if not determined by starter)
|
|
||||||
- Data modeling approach
|
|
||||||
- Data validation strategy
|
|
||||||
- Migration approach
|
|
||||||
- Caching strategy
|
|
||||||
|
|
||||||
#### Category 2: Authentication & Security
|
|
||||||
|
|
||||||
- Authentication method
|
|
||||||
- Authorization patterns
|
|
||||||
- Security middleware
|
|
||||||
- Data encryption approach
|
|
||||||
- API security strategy
|
|
||||||
|
|
||||||
#### Category 3: API & Communication
|
|
||||||
|
|
||||||
- API design patterns (REST, GraphQL, etc.)
|
|
||||||
- API documentation approach
|
|
||||||
- Error handling standards
|
|
||||||
- Rate limiting strategy
|
|
||||||
- Communication between services
|
|
||||||
|
|
||||||
#### Category 4: Frontend Architecture (if applicable)
|
|
||||||
|
|
||||||
- State management approach
|
|
||||||
- Component architecture
|
|
||||||
- Routing strategy
|
|
||||||
- Performance optimization
|
|
||||||
- Bundle optimization
|
|
||||||
|
|
||||||
#### Category 5: Infrastructure & Deployment
|
|
||||||
|
|
||||||
- Hosting strategy
|
|
||||||
- CI/CD pipeline approach
|
|
||||||
- Environment configuration
|
|
||||||
- Monitoring and logging
|
|
||||||
- Scaling strategy
|
|
||||||
|
|
||||||
### 3. Facilitate Each Decision Category
|
|
||||||
|
|
||||||
For each category, facilitate collaborative decision making:
|
|
||||||
|
|
||||||
**Present the Decision:**
|
|
||||||
Based on user skill level and project context:
|
|
||||||
|
|
||||||
**Expert Mode:**
|
|
||||||
"{{Decision_Category}}: {{Specific_Decision}}
|
|
||||||
|
|
||||||
Options: {{concise_option_list_with_tradeoffs}}
|
|
||||||
|
|
||||||
What's your preference for this decision?"
|
|
||||||
|
|
||||||
**Intermediate Mode:**
|
|
||||||
"Next decision: {{Human_Friendly_Category}}
|
|
||||||
|
|
||||||
We need to choose {{Specific_Decision}}.
|
|
||||||
|
|
||||||
Common options:
|
|
||||||
{{option_list_with_brief_explanations}}
|
|
||||||
|
|
||||||
For your project, I'd lean toward {{recommendation}} because {{reason}}. What are your thoughts?"
|
|
||||||
|
|
||||||
**Beginner Mode:**
|
|
||||||
"Let's talk about {{Human_Friendly_Category}}.
|
|
||||||
|
|
||||||
{{Educational_Context_About_Why_This_Matters}}
|
|
||||||
|
|
||||||
Think of it like {{real_world_analogy}}.
|
|
||||||
|
|
||||||
Your main options:
|
|
||||||
{{friendly_options_with_pros_cons}}
|
|
||||||
|
|
||||||
My suggestion: {{recommendation}}
|
|
||||||
This is good for you because {{beginner_friendly_reason}}.
|
|
||||||
|
|
||||||
What feels right to you?"
|
|
||||||
|
|
||||||
**Verify Technology Versions:**
|
|
||||||
If decision involves specific technology:
|
|
||||||
|
|
||||||
```
|
|
||||||
Search the web: "{{technology}} latest stable version"
|
|
||||||
Search the web: "{{technology}} current LTS version"
|
|
||||||
Search the web: "{{technology}} production readiness"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Get User Input:**
|
|
||||||
"What's your preference? (or 'explain more' for details)"
|
|
||||||
|
|
||||||
**Handle User Response:**
|
|
||||||
|
|
||||||
- If user wants more info: Provide deeper explanation
|
|
||||||
- If user has preference: Discuss implications and record decision
|
|
||||||
- If user wants alternatives: Explore other options
|
|
||||||
|
|
||||||
**Record the Decision:**
|
|
||||||
|
|
||||||
- Category: {{category}}
|
|
||||||
- Decision: {{user_choice}}
|
|
||||||
- Version: {{verified_version_if_applicable}}
|
|
||||||
- Rationale: {{user_reasoning_or_default}}
|
|
||||||
- Affects: {{components_or_epics}}
|
|
||||||
- Provided by Starter: {{yes_if_from_starter}}
|
|
||||||
|
|
||||||
### 4. Check for Cascading Implications
|
|
||||||
|
|
||||||
After each major decision, identify related decisions:
|
|
||||||
|
|
||||||
"This choice means we'll also need to decide:
|
|
||||||
|
|
||||||
- {{related_decision_1}}
|
|
||||||
- {{related_decision_2}}"
|
|
||||||
|
|
||||||
### 5. Generate Decisions Content
|
|
||||||
|
|
||||||
After facilitating all decision categories, prepare the content to append:
|
|
||||||
|
|
||||||
#### Content Structure:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
## Core Architectural Decisions
|
|
||||||
|
|
||||||
### Decision Priority Analysis
|
|
||||||
|
|
||||||
**Critical Decisions (Block Implementation):**
|
|
||||||
{{critical_decisions_made}}
|
|
||||||
|
|
||||||
**Important Decisions (Shape Architecture):**
|
|
||||||
{{important_decisions_made}}
|
|
||||||
|
|
||||||
**Deferred Decisions (Post-MVP):**
|
|
||||||
{{decisions_deferred_with_rationale}}
|
|
||||||
|
|
||||||
### Data Architecture
|
|
||||||
|
|
||||||
{{data_related_decisions_with_versions_and_rationale}}
|
|
||||||
|
|
||||||
### Authentication & Security
|
|
||||||
|
|
||||||
{{security_related_decisions_with_versions_and_rationale}}
|
|
||||||
|
|
||||||
### API & Communication Patterns
|
|
||||||
|
|
||||||
{{api_related_decisions_with_versions_and_rationale}}
|
|
||||||
|
|
||||||
### Frontend Architecture
|
|
||||||
|
|
||||||
{{frontend_related_decisions_with_versions_and_rationale}}
|
|
||||||
|
|
||||||
### Infrastructure & Deployment
|
|
||||||
|
|
||||||
{{infrastructure_related_decisions_with_versions_and_rationale}}
|
|
||||||
|
|
||||||
### Decision Impact Analysis
|
|
||||||
|
|
||||||
**Implementation Sequence:**
|
|
||||||
{{ordered_list_of_decisions_for_implementation}}
|
|
||||||
|
|
||||||
**Cross-Component Dependencies:**
|
|
||||||
{{how_decisions_affect_each_other}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Present Content and Menu
|
|
||||||
|
|
||||||
Show the generated decisions content and present choices:
|
|
||||||
|
|
||||||
"I've documented all the core architectural decisions we've made together.
|
|
||||||
|
|
||||||
**Here's what I'll add to the document:**
|
|
||||||
|
|
||||||
[Show the complete markdown content from step 5]
|
|
||||||
|
|
||||||
**What would you like to do?**
|
|
||||||
[A] Advanced Elicitation - Explore innovative approaches to any specific decisions
|
|
||||||
[P] Party Mode - Review decisions from multiple perspectives
|
|
||||||
[C] Continue - Save these decisions and move to implementation patterns"
|
|
||||||
|
|
||||||
### 7. Handle Menu Selection
|
|
||||||
|
|
||||||
#### If 'A' (Advanced Elicitation):
|
|
||||||
|
|
||||||
- Invoke the `bmad-advanced-elicitation` skill with specific decision categories
|
|
||||||
- Process enhanced insights about particular decisions
|
|
||||||
- Ask user: "Accept these enhancements to the architectural decisions? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'P' (Party Mode):
|
|
||||||
|
|
||||||
- Invoke the `bmad-party-mode` skill with architectural decisions context
|
|
||||||
- Process collaborative insights about decision trade-offs
|
|
||||||
- Ask user: "Accept these changes to the architectural decisions? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'C' (Continue):
|
|
||||||
|
|
||||||
- Append the final content to `{planning_artifacts}/architecture.md`
|
|
||||||
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4]`
|
|
||||||
- Load `./step-05-patterns.md`
|
|
||||||
|
|
||||||
## APPEND TO DOCUMENT:
|
|
||||||
|
|
||||||
When user selects 'C', append the content directly to the document using the structure from step 5.
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ All critical architectural decisions made collaboratively
|
|
||||||
✅ Technology versions verified using web search
|
|
||||||
✅ Decision rationale clearly documented
|
|
||||||
✅ Cascading implications identified and addressed
|
|
||||||
✅ User provided appropriate level of explanation for skill level
|
|
||||||
✅ A/P/C menu presented and handled correctly for each category
|
|
||||||
✅ Content properly appended to document when C selected
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Making recommendations instead of facilitating decisions
|
|
||||||
❌ Not verifying technology versions with web search
|
|
||||||
❌ Missing cascading implications between decisions
|
|
||||||
❌ Not adapting explanations to user skill level
|
|
||||||
❌ Forgetting to document decisions made by starter template
|
|
||||||
❌ Not presenting A/P/C menu after content generation
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects 'C' and content is saved to document, load `./step-05-patterns.md` to define implementation patterns that ensure consistency across AI agents.
|
|
||||||
|
|
||||||
Remember: Do NOT proceed to step-05 until user explicitly selects 'C' from the A/P/C menu and content is saved!
|
|
||||||
|
|
@ -1,359 +0,0 @@
|
||||||
# Step 5: Implementation Patterns & Consistency Rules
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on patterns that prevent AI agent implementation conflicts
|
|
||||||
- 🎯 EMPHASIZE what agents could decide DIFFERENTLY if not specified
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- 🎯 Focus on consistency, not implementation details
|
|
||||||
- ⚠️ Present A/P/C menu after generating patterns content
|
|
||||||
- 💾 ONLY save when user chooses C (Continue)
|
|
||||||
- 📖 Update frontmatter `stepsCompleted: [1, 2, 3, 4, 5]` before loading next step
|
|
||||||
- 🚫 FORBIDDEN to load next step until C is selected
|
|
||||||
|
|
||||||
## COLLABORATION MENUS (A/P/C):
|
|
||||||
|
|
||||||
This step will generate content and present choices:
|
|
||||||
|
|
||||||
- **A (Advanced Elicitation)**: Use discovery protocols to develop comprehensive consistency patterns
|
|
||||||
- **P (Party Mode)**: Bring multiple perspectives to identify potential conflict points
|
|
||||||
- **C (Continue)**: Save the patterns and proceed to project structure
|
|
||||||
|
|
||||||
## PROTOCOL INTEGRATION:
|
|
||||||
|
|
||||||
- When 'A' selected: Invoke the `bmad-advanced-elicitation` skill
|
|
||||||
- When 'P' selected: Invoke the `bmad-party-mode` skill
|
|
||||||
- PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed
|
|
||||||
- User accepts/rejects protocol changes before proceeding
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- Core architectural decisions from step 4 are complete
|
|
||||||
- Technology stack is decided and versions are verified
|
|
||||||
- Focus on HOW agents should implement, not WHAT they should implement
|
|
||||||
- Consider what could vary between different AI agents
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Define implementation patterns and consistency rules that ensure multiple AI agents write compatible, consistent code that works together seamlessly.
|
|
||||||
|
|
||||||
## PATTERNS DEFINITION SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Identify Potential Conflict Points
|
|
||||||
|
|
||||||
Based on the chosen technology stack and decisions, identify where AI agents could make different choices:
|
|
||||||
|
|
||||||
**Naming Conflicts:**
|
|
||||||
|
|
||||||
- Database table/column naming conventions
|
|
||||||
- API endpoint naming patterns
|
|
||||||
- File and directory naming
|
|
||||||
- Component/function/variable naming
|
|
||||||
- Route parameter formats
|
|
||||||
|
|
||||||
**Structural Conflicts:**
|
|
||||||
|
|
||||||
- Where tests are located
|
|
||||||
- How components are organized
|
|
||||||
- Where utilities and helpers go
|
|
||||||
- Configuration file organization
|
|
||||||
- Static asset organization
|
|
||||||
|
|
||||||
**Format Conflicts:**
|
|
||||||
|
|
||||||
- API response wrapper formats
|
|
||||||
- Error response structures
|
|
||||||
- Date/time formats in APIs and UI
|
|
||||||
- JSON field naming conventions
|
|
||||||
- API status code usage
|
|
||||||
|
|
||||||
**Communication Conflicts:**
|
|
||||||
|
|
||||||
- Event naming conventions
|
|
||||||
- Event payload structures
|
|
||||||
- State update patterns
|
|
||||||
- Action naming conventions
|
|
||||||
- Logging formats and levels
|
|
||||||
|
|
||||||
**Process Conflicts:**
|
|
||||||
|
|
||||||
- Loading state handling
|
|
||||||
- Error recovery patterns
|
|
||||||
- Retry implementation approaches
|
|
||||||
- Authentication flow patterns
|
|
||||||
- Validation timing and methods
|
|
||||||
|
|
||||||
### 2. Facilitate Pattern Decisions
|
|
||||||
|
|
||||||
For each conflict category, facilitate collaborative pattern definition:
|
|
||||||
|
|
||||||
**Present the Conflict Point:**
|
|
||||||
"Given that we're using {{tech_stack}}, different AI agents might handle {{conflict_area}} differently.
|
|
||||||
|
|
||||||
For example, one agent might name database tables 'users' while another uses 'Users' - this would cause conflicts.
|
|
||||||
|
|
||||||
We need to establish consistent patterns that all agents follow."
|
|
||||||
|
|
||||||
**Show Options and Trade-offs:**
|
|
||||||
"Common approaches for {{pattern_category}}:
|
|
||||||
|
|
||||||
1. {{option_1}} - {{pros_and_cons}}
|
|
||||||
2. {{option_2}} - {{pros_and_cons}}
|
|
||||||
3. {{option_3}} - {{pros_and_cons}}
|
|
||||||
|
|
||||||
Which approach makes the most sense for our project?"
|
|
||||||
|
|
||||||
**Get User Decision:**
|
|
||||||
"What's your preference for this pattern? (or discuss the trade-offs more)"
|
|
||||||
|
|
||||||
### 3. Define Pattern Categories
|
|
||||||
|
|
||||||
#### Naming Patterns
|
|
||||||
|
|
||||||
**Database Naming:**
|
|
||||||
|
|
||||||
- Table naming: users, Users, or user?
|
|
||||||
- Column naming: user_id or userId?
|
|
||||||
- Foreign key format: user_id or fk_user?
|
|
||||||
- Index naming: idx_users_email or users_email_index?
|
|
||||||
|
|
||||||
**API Naming:**
|
|
||||||
|
|
||||||
- REST endpoint naming: /users or /user? Plural or singular?
|
|
||||||
- Route parameter format: :id or {id}?
|
|
||||||
- Query parameter naming: user_id or userId?
|
|
||||||
- Header naming conventions: X-Custom-Header or Custom-Header?
|
|
||||||
|
|
||||||
**Code Naming:**
|
|
||||||
|
|
||||||
- Component naming: UserCard or user-card?
|
|
||||||
- File naming: UserCard.tsx or user-card.tsx?
|
|
||||||
- Function naming: getUserData or get_user_data?
|
|
||||||
- Variable naming: userId or user_id?
|
|
||||||
|
|
||||||
#### Structure Patterns
|
|
||||||
|
|
||||||
**Project Organization:**
|
|
||||||
|
|
||||||
- Where do tests live? **tests**/ or \*.test.ts co-located?
|
|
||||||
- How are components organized? By feature or by type?
|
|
||||||
- Where do shared utilities go?
|
|
||||||
- How are services and repositories organized?
|
|
||||||
|
|
||||||
**File Structure:**
|
|
||||||
|
|
||||||
- Config file locations and naming
|
|
||||||
- Static asset organization
|
|
||||||
- Documentation placement
|
|
||||||
- Environment file organization
|
|
||||||
|
|
||||||
#### Format Patterns
|
|
||||||
|
|
||||||
**API Formats:**
|
|
||||||
|
|
||||||
- API response wrapper? {data: ..., error: ...} or direct response?
|
|
||||||
- Error format? {message, code} or {error: {type, detail}}?
|
|
||||||
- Date format in JSON? ISO strings or timestamps?
|
|
||||||
- Success response structure?
|
|
||||||
|
|
||||||
**Data Formats:**
|
|
||||||
|
|
||||||
- JSON field naming: snake_case or camelCase?
|
|
||||||
- Boolean representations: true/false or 1/0?
|
|
||||||
- Null handling patterns
|
|
||||||
- Array vs object for single items
|
|
||||||
|
|
||||||
#### Communication Patterns
|
|
||||||
|
|
||||||
**Event Systems:**
|
|
||||||
|
|
||||||
- Event naming convention: user.created or UserCreated?
|
|
||||||
- Event payload structure standards
|
|
||||||
- Event versioning approach
|
|
||||||
- Async event handling patterns
|
|
||||||
|
|
||||||
**State Management:**
|
|
||||||
|
|
||||||
- State update patterns: immutable updates or direct mutation?
|
|
||||||
- Action naming conventions
|
|
||||||
- Selector patterns
|
|
||||||
- State organization principles
|
|
||||||
|
|
||||||
#### Process Patterns
|
|
||||||
|
|
||||||
**Error Handling:**
|
|
||||||
|
|
||||||
- Global error handling approach
|
|
||||||
- Error boundary patterns
|
|
||||||
- User-facing error message format
|
|
||||||
- Logging vs user error distinction
|
|
||||||
|
|
||||||
**Loading States:**
|
|
||||||
|
|
||||||
- Loading state naming conventions
|
|
||||||
- Global vs local loading states
|
|
||||||
- Loading state persistence
|
|
||||||
- Loading UI patterns
|
|
||||||
|
|
||||||
### 4. Generate Patterns Content
|
|
||||||
|
|
||||||
Prepare the content to append to the document:
|
|
||||||
|
|
||||||
#### Content Structure:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
## Implementation Patterns & Consistency Rules
|
|
||||||
|
|
||||||
### Pattern Categories Defined
|
|
||||||
|
|
||||||
**Critical Conflict Points Identified:**
|
|
||||||
{{number_of_potential_conflicts}} areas where AI agents could make different choices
|
|
||||||
|
|
||||||
### Naming Patterns
|
|
||||||
|
|
||||||
**Database Naming Conventions:**
|
|
||||||
{{database_naming_rules_with_examples}}
|
|
||||||
|
|
||||||
**API Naming Conventions:**
|
|
||||||
{{api_naming_rules_with_examples}}
|
|
||||||
|
|
||||||
**Code Naming Conventions:**
|
|
||||||
{{code_naming_rules_with_examples}}
|
|
||||||
|
|
||||||
### Structure Patterns
|
|
||||||
|
|
||||||
**Project Organization:**
|
|
||||||
{{project_structure_rules_with_examples}}
|
|
||||||
|
|
||||||
**File Structure Patterns:**
|
|
||||||
{{file_organization_rules_with_examples}}
|
|
||||||
|
|
||||||
### Format Patterns
|
|
||||||
|
|
||||||
**API Response Formats:**
|
|
||||||
{{api_response_structure_rules}}
|
|
||||||
|
|
||||||
**Data Exchange Formats:**
|
|
||||||
{{data_format_rules_with_examples}}
|
|
||||||
|
|
||||||
### Communication Patterns
|
|
||||||
|
|
||||||
**Event System Patterns:**
|
|
||||||
{{event_naming_and_structure_rules}}
|
|
||||||
|
|
||||||
**State Management Patterns:**
|
|
||||||
{{state_update_and_organization_rules}}
|
|
||||||
|
|
||||||
### Process Patterns
|
|
||||||
|
|
||||||
**Error Handling Patterns:**
|
|
||||||
{{consistent_error_handling_approaches}}
|
|
||||||
|
|
||||||
**Loading State Patterns:**
|
|
||||||
{{loading_state_management_rules}}
|
|
||||||
|
|
||||||
### Enforcement Guidelines
|
|
||||||
|
|
||||||
**All AI Agents MUST:**
|
|
||||||
|
|
||||||
- {{mandatory_pattern_1}}
|
|
||||||
- {{mandatory_pattern_2}}
|
|
||||||
- {{mandatory_pattern_3}}
|
|
||||||
|
|
||||||
**Pattern Enforcement:**
|
|
||||||
|
|
||||||
- How to verify patterns are followed
|
|
||||||
- Where to document pattern violations
|
|
||||||
- Process for updating patterns
|
|
||||||
|
|
||||||
### Pattern Examples
|
|
||||||
|
|
||||||
**Good Examples:**
|
|
||||||
{{concrete_examples_of_correct_pattern_usage}}
|
|
||||||
|
|
||||||
**Anti-Patterns:**
|
|
||||||
{{examples_of_what_to_avoid}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Present Content and Menu
|
|
||||||
|
|
||||||
Show the generated patterns content and present choices:
|
|
||||||
|
|
||||||
"I've documented implementation patterns that will prevent conflicts between AI agents working on this project.
|
|
||||||
|
|
||||||
**Here's what I'll add to the document:**
|
|
||||||
|
|
||||||
[Show the complete markdown content from step 4]
|
|
||||||
|
|
||||||
**What would you like to do?**
|
|
||||||
[A] Advanced Elicitation - Explore additional consistency patterns
|
|
||||||
[P] Party Mode - Review patterns from different implementation perspectives
|
|
||||||
[C] Continue - Save these patterns and move to project structure"
|
|
||||||
|
|
||||||
### 6. Handle Menu Selection
|
|
||||||
|
|
||||||
#### If 'A' (Advanced Elicitation):
|
|
||||||
|
|
||||||
- Invoke the `bmad-advanced-elicitation` skill with current patterns
|
|
||||||
- Process enhanced consistency rules that come back
|
|
||||||
- Ask user: "Accept these additional pattern refinements? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'P' (Party Mode):
|
|
||||||
|
|
||||||
- Invoke the `bmad-party-mode` skill with implementation patterns context
|
|
||||||
- Process collaborative insights about potential conflicts
|
|
||||||
- Ask user: "Accept these changes to the implementation patterns? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'C' (Continue):
|
|
||||||
|
|
||||||
- Append the final content to `{planning_artifacts}/architecture.md`
|
|
||||||
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5]`
|
|
||||||
- Load `./step-06-structure.md`
|
|
||||||
|
|
||||||
## APPEND TO DOCUMENT:
|
|
||||||
|
|
||||||
When user selects 'C', append the content directly to the document using the structure from step 4.
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ All potential AI agent conflict points identified and addressed
|
|
||||||
✅ Comprehensive patterns defined for naming, structure, and communication
|
|
||||||
✅ Concrete examples provided for each pattern
|
|
||||||
✅ Enforcement guidelines clearly documented
|
|
||||||
✅ User collaborated on pattern decisions rather than receiving recommendations
|
|
||||||
✅ A/P/C menu presented and handled correctly
|
|
||||||
✅ Content properly appended to document when C selected
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Missing potential conflict points that could cause agent conflicts
|
|
||||||
❌ Being too prescriptive about implementation details instead of focusing on consistency
|
|
||||||
❌ Not providing concrete examples for each pattern
|
|
||||||
❌ Failing to address cross-cutting concerns like error handling
|
|
||||||
❌ Not considering the chosen technology stack when defining patterns
|
|
||||||
❌ Not presenting A/P/C menu after content generation
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects 'C' and content is saved to document, load `./step-06-structure.md` to define the complete project structure.
|
|
||||||
|
|
||||||
Remember: Do NOT proceed to step-06 until user explicitly selects 'C' from the A/P/C menu and content is saved!
|
|
||||||
|
|
@ -1,379 +0,0 @@
|
||||||
# Step 6: Project Structure & Boundaries
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on defining complete project structure and clear boundaries
|
|
||||||
- 🗺️ MAP requirements/epics to architectural components
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- 🗺️ Create complete project tree, not generic placeholders
|
|
||||||
- ⚠️ Present A/P/C menu after generating project structure
|
|
||||||
- 💾 ONLY save when user chooses C (Continue)
|
|
||||||
- 📖 Update frontmatter `stepsCompleted: [1, 2, 3, 4, 5, 6]` before loading next step
|
|
||||||
- 🚫 FORBIDDEN to load next step until C is selected
|
|
||||||
|
|
||||||
## COLLABORATION MENUS (A/P/C):
|
|
||||||
|
|
||||||
This step will generate content and present choices:
|
|
||||||
|
|
||||||
- **A (Advanced Elicitation)**: Use discovery protocols to explore innovative project organization approaches
|
|
||||||
- **P (Party Mode)**: Bring multiple perspectives to evaluate project structure trade-offs
|
|
||||||
- **C (Continue)**: Save the project structure and proceed to validation
|
|
||||||
|
|
||||||
## PROTOCOL INTEGRATION:
|
|
||||||
|
|
||||||
- When 'A' selected: Invoke the `bmad-advanced-elicitation` skill
|
|
||||||
- When 'P' selected: Invoke the `bmad-party-mode` skill
|
|
||||||
- PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed
|
|
||||||
- User accepts/rejects protocol changes before proceeding
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- All previous architectural decisions are complete
|
|
||||||
- Implementation patterns and consistency rules are defined
|
|
||||||
- Focus on physical project structure and component boundaries
|
|
||||||
- Map requirements to specific files and directories
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Define the complete project structure and architectural boundaries based on all decisions made, creating a concrete implementation guide for AI agents.
|
|
||||||
|
|
||||||
## PROJECT STRUCTURE SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Analyze Requirements Mapping
|
|
||||||
|
|
||||||
Map project requirements to architectural components:
|
|
||||||
|
|
||||||
**From Epics (if available):**
|
|
||||||
"Epic: {{epic_name}} → Lives in {{module/directory/service}}"
|
|
||||||
|
|
||||||
- User stories within the epic
|
|
||||||
- Cross-epic dependencies
|
|
||||||
- Shared components needed
|
|
||||||
|
|
||||||
**From FR Categories (if no epics):**
|
|
||||||
"FR Category: {{fr_category_name}} → Lives in {{module/directory/service}}"
|
|
||||||
|
|
||||||
- Related functional requirements
|
|
||||||
- Shared functionality across categories
|
|
||||||
- Integration points between categories
|
|
||||||
|
|
||||||
### 2. Define Project Directory Structure
|
|
||||||
|
|
||||||
Based on technology stack and patterns, create the complete project structure:
|
|
||||||
|
|
||||||
**Root Configuration Files:**
|
|
||||||
|
|
||||||
- Package management files (package.json, requirements.txt, etc.)
|
|
||||||
- Build and development configuration
|
|
||||||
- Environment configuration files
|
|
||||||
- CI/CD pipeline files
|
|
||||||
- Documentation files
|
|
||||||
|
|
||||||
**Source Code Organization:**
|
|
||||||
|
|
||||||
- Application entry points
|
|
||||||
- Core application structure
|
|
||||||
- Feature/module organization
|
|
||||||
- Shared utilities and libraries
|
|
||||||
- Configuration and environment files
|
|
||||||
|
|
||||||
**Test Organization:**
|
|
||||||
|
|
||||||
- Unit test locations and structure
|
|
||||||
- Integration test organization
|
|
||||||
- End-to-end test structure
|
|
||||||
- Test utilities and fixtures
|
|
||||||
|
|
||||||
**Build and Distribution:**
|
|
||||||
|
|
||||||
- Build output directories
|
|
||||||
- Distribution files
|
|
||||||
- Static assets
|
|
||||||
- Documentation build
|
|
||||||
|
|
||||||
### 3. Define Integration Boundaries
|
|
||||||
|
|
||||||
Map how components communicate and where boundaries exist:
|
|
||||||
|
|
||||||
**API Boundaries:**
|
|
||||||
|
|
||||||
- External API endpoints
|
|
||||||
- Internal service boundaries
|
|
||||||
- Authentication and authorization boundaries
|
|
||||||
- Data access layer boundaries
|
|
||||||
|
|
||||||
**Component Boundaries:**
|
|
||||||
|
|
||||||
- Frontend component communication patterns
|
|
||||||
- State management boundaries
|
|
||||||
- Service communication patterns
|
|
||||||
- Event-driven integration points
|
|
||||||
|
|
||||||
**Data Boundaries:**
|
|
||||||
|
|
||||||
- Database schema boundaries
|
|
||||||
- Data access patterns
|
|
||||||
- Caching boundaries
|
|
||||||
- External data integration points
|
|
||||||
|
|
||||||
### 4. Create Complete Project Tree
|
|
||||||
|
|
||||||
Generate a comprehensive directory structure showing all files and directories:
|
|
||||||
|
|
||||||
**Technology-Specific Structure Examples:**
|
|
||||||
|
|
||||||
**Next.js Full-Stack:**
|
|
||||||
|
|
||||||
```
|
|
||||||
project-name/
|
|
||||||
├── README.md
|
|
||||||
├── package.json
|
|
||||||
├── next.config.js
|
|
||||||
├── tailwind.config.js
|
|
||||||
├── tsconfig.json
|
|
||||||
├── .env.local
|
|
||||||
├── .env.example
|
|
||||||
├── .gitignore
|
|
||||||
├── .github/
|
|
||||||
│ └── workflows/
|
|
||||||
│ └── ci.yml
|
|
||||||
├── src/
|
|
||||||
│ ├── app/
|
|
||||||
│ │ ├── globals.css
|
|
||||||
│ │ ├── layout.tsx
|
|
||||||
│ │ └── page.tsx
|
|
||||||
│ ├── components/
|
|
||||||
│ │ ├── ui/
|
|
||||||
│ │ ├── forms/
|
|
||||||
│ │ └── features/
|
|
||||||
│ ├── lib/
|
|
||||||
│ │ ├── db.ts
|
|
||||||
│ │ ├── auth.ts
|
|
||||||
│ │ └── utils.ts
|
|
||||||
│ ├── types/
|
|
||||||
│ └── middleware.ts
|
|
||||||
├── prisma/
|
|
||||||
│ ├── schema.prisma
|
|
||||||
│ └── migrations/
|
|
||||||
├── tests/
|
|
||||||
│ ├── __mocks__/
|
|
||||||
│ ├── components/
|
|
||||||
│ └── e2e/
|
|
||||||
└── public/
|
|
||||||
└── assets/
|
|
||||||
```
|
|
||||||
|
|
||||||
**API Backend (NestJS):**
|
|
||||||
|
|
||||||
```
|
|
||||||
project-name/
|
|
||||||
├── package.json
|
|
||||||
├── nest-cli.json
|
|
||||||
├── tsconfig.json
|
|
||||||
├── .env
|
|
||||||
├── .env.example
|
|
||||||
├── .gitignore
|
|
||||||
├── README.md
|
|
||||||
├── src/
|
|
||||||
│ ├── main.ts
|
|
||||||
│ ├── app.module.ts
|
|
||||||
│ ├── config/
|
|
||||||
│ ├── modules/
|
|
||||||
│ │ ├── auth/
|
|
||||||
│ │ ├── users/
|
|
||||||
│ │ └── common/
|
|
||||||
│ ├── services/
|
|
||||||
│ ├── repositories/
|
|
||||||
│ ├── decorators/
|
|
||||||
│ ├── pipes/
|
|
||||||
│ ├── guards/
|
|
||||||
│ └── interceptors/
|
|
||||||
├── test/
|
|
||||||
│ ├── unit/
|
|
||||||
│ ├── integration/
|
|
||||||
│ └── e2e/
|
|
||||||
├── prisma/
|
|
||||||
│ ├── schema.prisma
|
|
||||||
│ └── migrations/
|
|
||||||
└── docker-compose.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Map Requirements to Structure
|
|
||||||
|
|
||||||
Create explicit mapping from project requirements to specific files/directories:
|
|
||||||
|
|
||||||
**Epic/Feature Mapping:**
|
|
||||||
"Epic: User Management
|
|
||||||
|
|
||||||
- Components: src/components/features/users/
|
|
||||||
- Services: src/services/users/
|
|
||||||
- API Routes: src/app/api/users/
|
|
||||||
- Database: prisma/migrations/_*users*_
|
|
||||||
- Tests: tests/features/users/"
|
|
||||||
|
|
||||||
**Cross-Cutting Concerns:**
|
|
||||||
"Authentication System
|
|
||||||
|
|
||||||
- Components: src/components/auth/
|
|
||||||
- Services: src/services/auth/
|
|
||||||
- Middleware: src/middleware/auth.ts
|
|
||||||
- Guards: src/guards/auth.guard.ts
|
|
||||||
- Tests: tests/auth/"
|
|
||||||
|
|
||||||
### 6. Generate Structure Content
|
|
||||||
|
|
||||||
Prepare the content to append to the document:
|
|
||||||
|
|
||||||
#### Content Structure:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
## Project Structure & Boundaries
|
|
||||||
|
|
||||||
### Complete Project Directory Structure
|
|
||||||
```
|
|
||||||
|
|
||||||
{{complete_project_tree_with_all_files_and_directories}}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### Architectural Boundaries
|
|
||||||
|
|
||||||
**API Boundaries:**
|
|
||||||
{{api_boundary_definitions_and_endpoints}}
|
|
||||||
|
|
||||||
**Component Boundaries:**
|
|
||||||
{{component_communication_patterns_and_boundaries}}
|
|
||||||
|
|
||||||
**Service Boundaries:**
|
|
||||||
{{service_integration_patterns_and_boundaries}}
|
|
||||||
|
|
||||||
**Data Boundaries:**
|
|
||||||
{{data_access_patterns_and_boundaries}}
|
|
||||||
|
|
||||||
### Requirements to Structure Mapping
|
|
||||||
|
|
||||||
**Feature/Epic Mapping:**
|
|
||||||
{{mapping_of_epics_or_features_to_specific_directories}}
|
|
||||||
|
|
||||||
**Cross-Cutting Concerns:**
|
|
||||||
{{mapping_of_shared_functionality_to_locations}}
|
|
||||||
|
|
||||||
### Integration Points
|
|
||||||
|
|
||||||
**Internal Communication:**
|
|
||||||
{{how_components_within_the_project_communicate}}
|
|
||||||
|
|
||||||
**External Integrations:**
|
|
||||||
{{third_party_service_integration_points}}
|
|
||||||
|
|
||||||
**Data Flow:**
|
|
||||||
{{how_data_flows_through_the_architecture}}
|
|
||||||
|
|
||||||
### File Organization Patterns
|
|
||||||
|
|
||||||
**Configuration Files:**
|
|
||||||
{{where_and_how_config_files_are_organized}}
|
|
||||||
|
|
||||||
**Source Organization:**
|
|
||||||
{{how_source_code_is_structured_and_organized}}
|
|
||||||
|
|
||||||
**Test Organization:**
|
|
||||||
{{how_tests_are_structured_and_organized}}
|
|
||||||
|
|
||||||
**Asset Organization:**
|
|
||||||
{{how_static_and_dynamic_assets_are_organized}}
|
|
||||||
|
|
||||||
### Development Workflow Integration
|
|
||||||
|
|
||||||
**Development Server Structure:**
|
|
||||||
{{how_the_project_is organized_for_development}}
|
|
||||||
|
|
||||||
**Build Process Structure:**
|
|
||||||
{{how_the_build_process_uses_the_project_structure}}
|
|
||||||
|
|
||||||
**Deployment Structure:**
|
|
||||||
{{how_the_project_structure_supports_deployment}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Present Content and Menu
|
|
||||||
|
|
||||||
Show the generated project structure content and present choices:
|
|
||||||
|
|
||||||
"I've created a complete project structure based on all our architectural decisions.
|
|
||||||
|
|
||||||
**Here's what I'll add to the document:**
|
|
||||||
|
|
||||||
[Show the complete markdown content from step 6]
|
|
||||||
|
|
||||||
**What would you like to do?**
|
|
||||||
[A] Advanced Elicitation - Explore innovative project organization approaches
|
|
||||||
[P] Party Mode - Review structure from different development perspectives
|
|
||||||
[C] Continue - Save this structure and move to architecture validation"
|
|
||||||
|
|
||||||
### 8. Handle Menu Selection
|
|
||||||
|
|
||||||
#### If 'A' (Advanced Elicitation):
|
|
||||||
|
|
||||||
- Invoke the `bmad-advanced-elicitation` skill with current project structure
|
|
||||||
- Process enhanced organizational insights that come back
|
|
||||||
- Ask user: "Accept these changes to the project structure? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'P' (Party Mode):
|
|
||||||
|
|
||||||
- Invoke the `bmad-party-mode` skill with project structure context
|
|
||||||
- Process collaborative insights about organization trade-offs
|
|
||||||
- Ask user: "Accept these changes to the project structure? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'C' (Continue):
|
|
||||||
|
|
||||||
- Append the final content to `{planning_artifacts}/architecture.md`
|
|
||||||
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5, 6]`
|
|
||||||
- Load `./step-07-validation.md`
|
|
||||||
|
|
||||||
## APPEND TO DOCUMENT:
|
|
||||||
|
|
||||||
When user selects 'C', append the content directly to the document using the structure from step 6.
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ Complete project tree defined with all files and directories
|
|
||||||
✅ All architectural boundaries clearly documented
|
|
||||||
✅ Requirements/epics mapped to specific locations
|
|
||||||
✅ Integration points and communication patterns defined
|
|
||||||
✅ Project structure aligned with chosen technology stack
|
|
||||||
✅ A/P/C menu presented and handled correctly
|
|
||||||
✅ Content properly appended to document when C selected
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Creating generic placeholder structure instead of specific, complete tree
|
|
||||||
❌ Not mapping requirements to specific files and directories
|
|
||||||
❌ Missing important integration boundaries
|
|
||||||
❌ Not considering the chosen technology stack in structure design
|
|
||||||
❌ Not defining how components communicate across boundaries
|
|
||||||
❌ Not presenting A/P/C menu after content generation
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects 'C' and content is saved to document, load `./step-07-validation.md` to validate architectural coherence and completeness.
|
|
||||||
|
|
||||||
Remember: Do NOT proceed to step-07 until user explicitly selects 'C' from the A/P/C menu and content is saved!
|
|
||||||
|
|
@ -1,361 +0,0 @@
|
||||||
# Step 7: Architecture Validation & Completion
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- 🔄 CRITICAL: When loading next step with 'C', ensure the entire file is read and understood before proceeding
|
|
||||||
- ✅ ALWAYS treat this as collaborative discovery between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on validating architectural coherence and completeness
|
|
||||||
- ✅ VALIDATE all requirements are covered by architectural decisions
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- ✅ Run comprehensive validation checks on the complete architecture
|
|
||||||
- ⚠️ Present A/P/C menu after generating validation results
|
|
||||||
- 💾 ONLY save when user chooses C (Continue)
|
|
||||||
- 📖 Update frontmatter `stepsCompleted: [1, 2, 3, 4, 5, 6, 7]` before loading next step
|
|
||||||
- 🚫 FORBIDDEN to load next step until C is selected
|
|
||||||
|
|
||||||
## COLLABORATION MENUS (A/P/C):
|
|
||||||
|
|
||||||
This step will generate content and present choices:
|
|
||||||
|
|
||||||
- **A (Advanced Elicitation)**: Use discovery protocols to address complex architectural issues found during validation
|
|
||||||
- **P (Party Mode)**: Bring multiple perspectives to resolve validation concerns
|
|
||||||
- **C (Continue)**: Save the validation results and complete the architecture
|
|
||||||
|
|
||||||
## PROTOCOL INTEGRATION:
|
|
||||||
|
|
||||||
- When 'A' selected: Invoke the `bmad-advanced-elicitation` skill
|
|
||||||
- When 'P' selected: Invoke the `bmad-party-mode` skill
|
|
||||||
- PROTOCOLS always return to display this step's A/P/C menu after the A or P have completed
|
|
||||||
- User accepts/rejects protocol changes before proceeding
|
|
||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
|
||||||
|
|
||||||
- Complete architecture document with all sections is available
|
|
||||||
- All architectural decisions, patterns, and structure are defined
|
|
||||||
- Focus on validation, gap analysis, and coherence checking
|
|
||||||
- Prepare for handoff to implementation phase
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Validate the complete architecture for coherence, completeness, and readiness to guide AI agents through consistent implementation.
|
|
||||||
|
|
||||||
## VALIDATION SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Coherence Validation
|
|
||||||
|
|
||||||
Check that all architectural decisions work together:
|
|
||||||
|
|
||||||
**Decision Compatibility:**
|
|
||||||
|
|
||||||
- Do all technology choices work together without conflicts?
|
|
||||||
- Are all versions compatible with each other?
|
|
||||||
- Do patterns align with technology choices?
|
|
||||||
- Are there any contradictory decisions?
|
|
||||||
|
|
||||||
**Pattern Consistency:**
|
|
||||||
|
|
||||||
- Do implementation patterns support the architectural decisions?
|
|
||||||
- Are naming conventions consistent across all areas?
|
|
||||||
- Do structure patterns align with technology stack?
|
|
||||||
- Are communication patterns coherent?
|
|
||||||
|
|
||||||
**Structure Alignment:**
|
|
||||||
|
|
||||||
- Does the project structure support all architectural decisions?
|
|
||||||
- Are boundaries properly defined and respected?
|
|
||||||
- Does the structure enable the chosen patterns?
|
|
||||||
- Are integration points properly structured?
|
|
||||||
|
|
||||||
### 2. Requirements Coverage Validation
|
|
||||||
|
|
||||||
Verify all project requirements are architecturally supported:
|
|
||||||
|
|
||||||
**From Epics (if available):**
|
|
||||||
|
|
||||||
- Does every epic have architectural support?
|
|
||||||
- Are all user stories implementable with these decisions?
|
|
||||||
- Are cross-epic dependencies handled architecturally?
|
|
||||||
- Are there any gaps in epic coverage?
|
|
||||||
|
|
||||||
**From FR Categories (if no epics):**
|
|
||||||
|
|
||||||
- Does every functional requirement have architectural support?
|
|
||||||
- Are all FR categories fully covered by architectural decisions?
|
|
||||||
- Are cross-cutting FRs properly addressed?
|
|
||||||
- Are there any missing architectural capabilities?
|
|
||||||
|
|
||||||
**Non-Functional Requirements:**
|
|
||||||
|
|
||||||
- Are performance requirements addressed architecturally?
|
|
||||||
- Are security requirements fully covered?
|
|
||||||
- Are scalability considerations properly handled?
|
|
||||||
- Are compliance requirements architecturally supported?
|
|
||||||
|
|
||||||
### 3. Implementation Readiness Validation
|
|
||||||
|
|
||||||
Assess if AI agents can implement consistently:
|
|
||||||
|
|
||||||
**Decision Completeness:**
|
|
||||||
|
|
||||||
- Are all critical decisions documented with versions?
|
|
||||||
- Are implementation patterns comprehensive enough?
|
|
||||||
- Are consistency rules clear and enforceable?
|
|
||||||
- Are examples provided for all major patterns?
|
|
||||||
|
|
||||||
**Structure Completeness:**
|
|
||||||
|
|
||||||
- Is the project structure complete and specific?
|
|
||||||
- Are all files and directories defined?
|
|
||||||
- Are integration points clearly specified?
|
|
||||||
- Are component boundaries well-defined?
|
|
||||||
|
|
||||||
**Pattern Completeness:**
|
|
||||||
|
|
||||||
- Are all potential conflict points addressed?
|
|
||||||
- Are naming conventions comprehensive?
|
|
||||||
- Are communication patterns fully specified?
|
|
||||||
- Are process patterns (error handling, etc.) complete?
|
|
||||||
|
|
||||||
### 4. Gap Analysis
|
|
||||||
|
|
||||||
Identify and document any missing elements:
|
|
||||||
|
|
||||||
**Critical Gaps:**
|
|
||||||
|
|
||||||
- Missing architectural decisions that block implementation
|
|
||||||
- Incomplete patterns that could cause conflicts
|
|
||||||
- Missing structural elements needed for development
|
|
||||||
- Undefined integration points
|
|
||||||
|
|
||||||
**Important Gaps:**
|
|
||||||
|
|
||||||
- Areas that need more detailed specification
|
|
||||||
- Patterns that could be more comprehensive
|
|
||||||
- Documentation that would help implementation
|
|
||||||
- Examples that would clarify complex decisions
|
|
||||||
|
|
||||||
**Nice-to-Have Gaps:**
|
|
||||||
|
|
||||||
- Additional patterns that would be helpful
|
|
||||||
- Supplementary documentation
|
|
||||||
- Tooling recommendations
|
|
||||||
- Development workflow optimizations
|
|
||||||
|
|
||||||
### 5. Address Validation Issues
|
|
||||||
|
|
||||||
For any issues found, facilitate resolution:
|
|
||||||
|
|
||||||
**Critical Issues:**
|
|
||||||
"I found some issues that need to be addressed before implementation:
|
|
||||||
|
|
||||||
{{critical_issue_description}}
|
|
||||||
|
|
||||||
These could cause implementation problems. How would you like to resolve this?"
|
|
||||||
|
|
||||||
**Important Issues:**
|
|
||||||
"I noticed a few areas that could be improved:
|
|
||||||
|
|
||||||
{{important_issue_description}}
|
|
||||||
|
|
||||||
These aren't blocking, but addressing them would make implementation smoother. Should we work on these?"
|
|
||||||
|
|
||||||
**Minor Issues:**
|
|
||||||
"Here are some minor suggestions for improvement:
|
|
||||||
|
|
||||||
{{minor_issue_description}}
|
|
||||||
|
|
||||||
These are optional refinements. Would you like to address any of these?"
|
|
||||||
|
|
||||||
### 6. Generate Validation Content
|
|
||||||
|
|
||||||
Prepare the content to append to the document:
|
|
||||||
|
|
||||||
#### Content Structure:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
## Architecture Validation Results
|
|
||||||
|
|
||||||
### Coherence Validation ✅
|
|
||||||
|
|
||||||
**Decision Compatibility:**
|
|
||||||
{{assessment_of_how_all_decisions_work_together}}
|
|
||||||
|
|
||||||
**Pattern Consistency:**
|
|
||||||
{{verification_that_patterns_support_decisions}}
|
|
||||||
|
|
||||||
**Structure Alignment:**
|
|
||||||
{{confirmation_that_structure_supports_architecture}}
|
|
||||||
|
|
||||||
### Requirements Coverage Validation ✅
|
|
||||||
|
|
||||||
**Epic/Feature Coverage:**
|
|
||||||
{{verification_that_all_epics_or_features_are_supported}}
|
|
||||||
|
|
||||||
**Functional Requirements Coverage:**
|
|
||||||
{{confirmation_that_all_FRs_are_architecturally_supported}}
|
|
||||||
|
|
||||||
**Non-Functional Requirements Coverage:**
|
|
||||||
{{verification_that_NFRs_are_addressed}}
|
|
||||||
|
|
||||||
### Implementation Readiness Validation ✅
|
|
||||||
|
|
||||||
**Decision Completeness:**
|
|
||||||
{{assessment_of_decision_documentation_completeness}}
|
|
||||||
|
|
||||||
**Structure Completeness:**
|
|
||||||
{{evaluation_of_project_structure_completeness}}
|
|
||||||
|
|
||||||
**Pattern Completeness:**
|
|
||||||
{{verification_of_implementation_patterns_completeness}}
|
|
||||||
|
|
||||||
### Gap Analysis Results
|
|
||||||
|
|
||||||
{{gap_analysis_findings_with_priority_levels}}
|
|
||||||
|
|
||||||
### Validation Issues Addressed
|
|
||||||
|
|
||||||
{{description_of_any_issues_found_and_resolutions}}
|
|
||||||
|
|
||||||
### Architecture Completeness Checklist
|
|
||||||
|
|
||||||
Mark each item `[x]` only if validation confirms it; leave `[ ]` if it is missing, partial, or unverified. Any unchecked item must be reflected in the Gap Analysis above and in the Overall Status below.
|
|
||||||
|
|
||||||
**Requirements Analysis**
|
|
||||||
|
|
||||||
- [ ] Project context thoroughly analyzed
|
|
||||||
- [ ] Scale and complexity assessed
|
|
||||||
- [ ] Technical constraints identified
|
|
||||||
- [ ] Cross-cutting concerns mapped
|
|
||||||
|
|
||||||
**Architectural Decisions**
|
|
||||||
|
|
||||||
- [ ] Critical decisions documented with versions
|
|
||||||
- [ ] Technology stack fully specified
|
|
||||||
- [ ] Integration patterns defined
|
|
||||||
- [ ] Performance considerations addressed
|
|
||||||
|
|
||||||
**Implementation Patterns**
|
|
||||||
|
|
||||||
- [ ] Naming conventions established
|
|
||||||
- [ ] Structure patterns defined
|
|
||||||
- [ ] Communication patterns specified
|
|
||||||
- [ ] Process patterns documented
|
|
||||||
|
|
||||||
**Project Structure**
|
|
||||||
|
|
||||||
- [ ] Complete directory structure defined
|
|
||||||
- [ ] Component boundaries established
|
|
||||||
- [ ] Integration points mapped
|
|
||||||
- [ ] Requirements to structure mapping complete
|
|
||||||
|
|
||||||
### Architecture Readiness Assessment
|
|
||||||
|
|
||||||
**Overall Status:** {{READY FOR IMPLEMENTATION | READY WITH MINOR GAPS | NOT READY}} (choose READY FOR IMPLEMENTATION only when all 16 checklist items are `[x]` and no Critical Gaps remain; choose NOT READY when any Critical Gap is open or any Requirements Analysis or Architectural Decisions item is unchecked; otherwise READY WITH MINOR GAPS)
|
|
||||||
|
|
||||||
**Confidence Level:** {{high/medium/low}} based on validation results
|
|
||||||
|
|
||||||
**Key Strengths:**
|
|
||||||
{{list_of_architecture_strengths}}
|
|
||||||
|
|
||||||
**Areas for Future Enhancement:**
|
|
||||||
{{areas_that_could_be_improved_later}}
|
|
||||||
|
|
||||||
### Implementation Handoff
|
|
||||||
|
|
||||||
**AI Agent Guidelines:**
|
|
||||||
|
|
||||||
- Follow all architectural decisions exactly as documented
|
|
||||||
- Use implementation patterns consistently across all components
|
|
||||||
- Respect project structure and boundaries
|
|
||||||
- Refer to this document for all architectural questions
|
|
||||||
|
|
||||||
**First Implementation Priority:**
|
|
||||||
{{starter_template_command_or_first_architectural_step}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Present Content and Menu
|
|
||||||
|
|
||||||
Show the validation results and present choices:
|
|
||||||
|
|
||||||
"I've completed a comprehensive validation of your architecture.
|
|
||||||
|
|
||||||
**Validation Summary:**
|
|
||||||
|
|
||||||
- ✅ Coherence: All decisions work together
|
|
||||||
- ✅ Coverage: All requirements are supported
|
|
||||||
- ✅ Readiness: AI agents can implement consistently
|
|
||||||
|
|
||||||
**Here's what I'll add to complete the architecture document:**
|
|
||||||
|
|
||||||
[Show the complete markdown content from step 6]
|
|
||||||
|
|
||||||
**What would you like to do?**
|
|
||||||
[A] Advanced Elicitation - Address any complex architectural concerns
|
|
||||||
[P] Party Mode - Review validation from different implementation perspectives
|
|
||||||
[C] Continue - Complete the architecture and finish workflow
|
|
||||||
|
|
||||||
### 8. Handle Menu Selection
|
|
||||||
|
|
||||||
#### If 'A' (Advanced Elicitation):
|
|
||||||
|
|
||||||
- Invoke the `bmad-advanced-elicitation` skill with validation issues
|
|
||||||
- Process enhanced solutions for complex concerns
|
|
||||||
- Ask user: "Accept these architectural improvements? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'P' (Party Mode):
|
|
||||||
|
|
||||||
- Invoke the `bmad-party-mode` skill with validation context
|
|
||||||
- Process collaborative insights on implementation readiness
|
|
||||||
- Ask user: "Accept these changes to the validation results? (y/n)"
|
|
||||||
- If yes: Update content, then return to A/P/C menu
|
|
||||||
- If no: Keep original content, then return to A/P/C menu
|
|
||||||
|
|
||||||
#### If 'C' (Continue):
|
|
||||||
|
|
||||||
- Append the final content to `{planning_artifacts}/architecture.md`
|
|
||||||
- Update frontmatter: `stepsCompleted: [1, 2, 3, 4, 5, 6, 7]`
|
|
||||||
- Load `./step-08-complete.md`
|
|
||||||
|
|
||||||
## APPEND TO DOCUMENT:
|
|
||||||
|
|
||||||
When user selects 'C', append the content directly to the document using the structure from step 6.
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ All architectural decisions validated for coherence
|
|
||||||
✅ Complete requirements coverage verified
|
|
||||||
✅ Implementation readiness confirmed
|
|
||||||
✅ All gaps identified and addressed
|
|
||||||
✅ Comprehensive validation checklist completed
|
|
||||||
✅ A/P/C menu presented and handled correctly
|
|
||||||
✅ Content properly appended to document when C selected
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Skipping validation of decision compatibility
|
|
||||||
❌ Not verifying all requirements are architecturally supported
|
|
||||||
❌ Missing potential implementation conflicts
|
|
||||||
❌ Not addressing gaps found during validation
|
|
||||||
❌ Providing incomplete validation checklist
|
|
||||||
❌ Not presenting A/P/C menu after content generation
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## NEXT STEP:
|
|
||||||
|
|
||||||
After user selects 'C' and content is saved to document, load `./step-08-complete.md` to complete the workflow and provide implementation guidance.
|
|
||||||
|
|
||||||
Remember: Do NOT proceed to step-08 until user explicitly selects 'C' from the A/P/C menu and content is saved!
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
# Step 8: Architecture Completion & Handoff
|
|
||||||
|
|
||||||
## MANDATORY EXECUTION RULES (READ FIRST):
|
|
||||||
|
|
||||||
- 🛑 NEVER generate content without user input
|
|
||||||
|
|
||||||
- 📖 CRITICAL: ALWAYS read the complete step file before taking any action - partial understanding leads to incomplete decisions
|
|
||||||
- ✅ ALWAYS treat this as collaborative completion between architectural peers
|
|
||||||
- 📋 YOU ARE A FACILITATOR, not a content generator
|
|
||||||
- 💬 FOCUS on successful workflow completion and implementation handoff
|
|
||||||
- 🎯 PROVIDE clear next steps for implementation phase
|
|
||||||
- ⚠️ ABSOLUTELY NO TIME ESTIMATES - AI development speed has fundamentally changed
|
|
||||||
- ✅ YOU MUST ALWAYS SPEAK OUTPUT In your Agent communication style with the config `{communication_language}`
|
|
||||||
|
|
||||||
## EXECUTION PROTOCOLS:
|
|
||||||
|
|
||||||
- 🎯 Show your analysis before taking any action
|
|
||||||
- 🎯 Present completion summary and implementation guidance
|
|
||||||
- 📖 Update frontmatter with final workflow state
|
|
||||||
- 🚫 THIS IS THE FINAL STEP IN THIS WORKFLOW
|
|
||||||
|
|
||||||
## YOUR TASK:
|
|
||||||
|
|
||||||
Complete the architecture workflow, provide a comprehensive completion summary, and guide the user to the next phase of their project development.
|
|
||||||
|
|
||||||
## COMPLETION SEQUENCE:
|
|
||||||
|
|
||||||
### 1. Congratulate the User on Completion
|
|
||||||
|
|
||||||
Both you and the User completed something amazing here - give a summary of what you achieved together and really congratulate the user on a job well done.
|
|
||||||
|
|
||||||
### 2. Update the created document's frontmatter
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
stepsCompleted: [1, 2, 3, 4, 5, 6, 7, 8]
|
|
||||||
workflowType: 'architecture'
|
|
||||||
lastStep: 8
|
|
||||||
status: 'complete'
|
|
||||||
completedAt: '{{current_date}}'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Next Steps Guidance
|
|
||||||
|
|
||||||
Architecture complete. Invoke the `bmad-help` skill.
|
|
||||||
|
|
||||||
Upon Completion of task output: offer to answer any questions about the Architecture Document.
|
|
||||||
|
|
||||||
|
|
||||||
## SUCCESS METRICS:
|
|
||||||
|
|
||||||
✅ Complete architecture document delivered with all sections
|
|
||||||
✅ All architectural decisions documented and validated
|
|
||||||
✅ Implementation patterns and consistency rules finalized
|
|
||||||
✅ Project structure complete with all files and directories
|
|
||||||
✅ User provided with clear next steps and implementation guidance
|
|
||||||
✅ Workflow status properly updated
|
|
||||||
✅ User collaboration maintained throughout completion process
|
|
||||||
|
|
||||||
## FAILURE MODES:
|
|
||||||
|
|
||||||
❌ Not providing clear implementation guidance
|
|
||||||
❌ Missing final validation of document completeness
|
|
||||||
❌ Not updating workflow status appropriately
|
|
||||||
❌ Failing to celebrate the successful completion
|
|
||||||
❌ Not providing specific next steps for the user
|
|
||||||
❌ Rushing completion without proper summary
|
|
||||||
|
|
||||||
❌ **CRITICAL**: Reading only partial step file - leads to incomplete understanding and poor decisions
|
|
||||||
❌ **CRITICAL**: Proceeding with 'C' without fully reading and understanding the next step file
|
|
||||||
❌ **CRITICAL**: Making decisions without complete understanding of step requirements and protocols
|
|
||||||
|
|
||||||
## WORKFLOW COMPLETE:
|
|
||||||
|
|
||||||
This is the final step of the Architecture workflow. The user now has a complete, validated architecture document ready for AI agent implementation.
|
|
||||||
|
|
||||||
The architecture will serve as the single source of truth for all technical decisions, ensuring consistent implementation across the entire project development lifecycle.
|
|
||||||
|
|
||||||
## On Complete
|
|
||||||
|
|
||||||
Run: `python3 {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.
|
|
||||||
|
|
@ -3,112 +3,12 @@ name: bmad-quick-dev
|
||||||
description: 'Implements any user intent, requirement, story, bug fix or change request by producing clean working code artifacts that follow the project''s existing architecture, patterns and conventions. Use when the user wants to build, fix, tweak, refactor, add or modify any code, component or feature.'
|
description: 'Implements any user intent, requirement, story, bug fix or change request by producing clean working code artifacts that follow the project''s existing architecture, patterns and conventions. Use when the user wants to build, fix, tweak, refactor, add or modify any code, component or feature.'
|
||||||
---
|
---
|
||||||
|
|
||||||
# Quick Dev New Preview Workflow
|
Run this, substituting `{skill-root}` with the absolute path to this skill's base directory, without changing the cwd:
|
||||||
|
|
||||||
**Goal:** Turn user intent into a hardened, reviewable artifact.
|
```bash
|
||||||
|
python3 {skill-root}/render.py
|
||||||
|
```
|
||||||
|
|
||||||
**CRITICAL:** If a step says "read fully and follow step-XX", you read and follow step-XX. No exceptions.
|
- **On success:** follow the instruction it prints to stdout; ignore stderr.
|
||||||
|
- **If `python3` is missing or lacks `tomllib`:** recover and retry.
|
||||||
Subagents, when the capability is available, are an important part of this workflow. Use them as directed by the workflow steps.
|
- **Any other failure:** report what it printed and HALT.
|
||||||
If you need an explicit user instruction to run them, ask once now for the whole workflow run.
|
|
||||||
|
|
||||||
## READY FOR DEVELOPMENT STANDARD
|
|
||||||
|
|
||||||
A specification is "Ready for Development" when:
|
|
||||||
|
|
||||||
- **Actionable**: Every task has a file path and specific action.
|
|
||||||
- **Logical**: Tasks ordered by dependency.
|
|
||||||
- **Testable**: All ACs use Given/When/Then.
|
|
||||||
- **Complete**: No placeholders or TBDs.
|
|
||||||
|
|
||||||
## SCOPE STANDARD
|
|
||||||
|
|
||||||
A specification should target a **single user-facing goal** within **900–1600 tokens**:
|
|
||||||
|
|
||||||
- **Single goal**: One cohesive feature, even if it spans multiple layers/files. Multi-goal means >=2 **top-level independent shippable deliverables** — each could be reviewed, tested, and merged as a separate PR without breaking the others. Never count surface verbs, "and" conjunctions, or noun phrases. Never split cross-layer implementation details inside one user goal.
|
|
||||||
- Split: "add dark mode toggle AND refactor auth to JWT AND build admin dashboard"
|
|
||||||
- Don't split: "add validation and display errors" / "support drag-and-drop AND paste AND retry"
|
|
||||||
- **900–1600 tokens**: Optimal range for LLM consumption. Below 900 risks ambiguity; above 1600 risks context-rot in implementation agents.
|
|
||||||
- **Neither limit is a gate.** Both are proposals with user override.
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- Bare paths (e.g. `step-01-clarify-and-route.md`) resolve from the skill root.
|
|
||||||
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
|
|
||||||
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
||||||
- `{skill-name}` resolves to the skill directory's basename.
|
|
||||||
|
|
||||||
## On Activation
|
|
||||||
|
|
||||||
### Step 1: Resolve the Workflow Block
|
|
||||||
|
|
||||||
Run: `python3 {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:
|
|
||||||
|
|
||||||
1. `{skill-root}/customize.toml` — defaults
|
|
||||||
2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
|
|
||||||
3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
|
|
||||||
|
|
||||||
Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
|
|
||||||
|
|
||||||
### Step 2: Execute Prepend Steps
|
|
||||||
|
|
||||||
Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
|
|
||||||
|
|
||||||
### Step 3: Load Persistent Facts
|
|
||||||
|
|
||||||
Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` -- load the referenced contents as facts. All other entries are facts verbatim.
|
|
||||||
|
|
||||||
### Step 4: Load Config
|
|
||||||
|
|
||||||
Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
|
|
||||||
|
|
||||||
- `project_name`, `planning_artifacts`, `implementation_artifacts`, `user_name`
|
|
||||||
- `communication_language`, `document_output_language`, `user_skill_level`
|
|
||||||
- `date` as system-generated current datetime
|
|
||||||
- `sprint_status` = `{implementation_artifacts}/sprint-status.yaml`
|
|
||||||
- `project_context` = `**/project-context.md` (load if exists)
|
|
||||||
- CLAUDE.md / memory files (load if exist)
|
|
||||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
|
||||||
- Language MUST be tailored to `{user_skill_level}`
|
|
||||||
- Generate all documents in `{document_output_language}`
|
|
||||||
|
|
||||||
### Step 5: Greet the User
|
|
||||||
|
|
||||||
Greet `{user_name}`, speaking in `{communication_language}`.
|
|
||||||
|
|
||||||
### Step 6: Execute Append Steps
|
|
||||||
|
|
||||||
Execute each entry in `{workflow.activation_steps_append}` in order.
|
|
||||||
|
|
||||||
Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
|
|
||||||
|
|
||||||
## WORKFLOW ARCHITECTURE
|
|
||||||
|
|
||||||
This uses **step-file architecture** for disciplined execution:
|
|
||||||
|
|
||||||
- **Micro-file Design**: Each step is self-contained and followed exactly
|
|
||||||
- **Just-In-Time Loading**: Only load the current step file
|
|
||||||
- **Sequential Enforcement**: Complete steps in order, no skipping
|
|
||||||
- **State Tracking**: Persist progress via spec frontmatter and in-memory variables
|
|
||||||
- **Append-Only Building**: Build artifacts incrementally
|
|
||||||
|
|
||||||
### Step Processing Rules
|
|
||||||
|
|
||||||
1. **READ COMPLETELY**: Read the entire step file before acting
|
|
||||||
2. **FOLLOW SEQUENCE**: Execute sections in order
|
|
||||||
3. **WAIT FOR INPUT**: Halt at checkpoints and wait for human
|
|
||||||
4. **LOAD NEXT**: When directed, read fully and follow the next step file
|
|
||||||
|
|
||||||
### Critical Rules (NO EXCEPTIONS)
|
|
||||||
|
|
||||||
- **NEVER** load multiple step files simultaneously
|
|
||||||
- **ALWAYS** read entire step file before execution
|
|
||||||
- **NEVER** skip steps or optimize the sequence
|
|
||||||
- **ALWAYS** follow the exact instructions in the step file
|
|
||||||
- **ALWAYS** halt at checkpoints and wait for human input
|
|
||||||
|
|
||||||
## FIRST STEP
|
|
||||||
|
|
||||||
Read fully and follow: `./step-01-clarify-and-route.md` to begin the workflow.
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,288 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""render.py — bmad-quick-dev template renderer.
|
||||||
|
|
||||||
|
Resolves compile-time {{.variable}} placeholders from BMad's central config,
|
||||||
|
bakes absolute paths for {project-root} into derived values, resolves and
|
||||||
|
inlines the skill's [workflow] customization block, and writes rendered .md
|
||||||
|
files to {project-root}/_bmad/render/bmad-quick-dev/.
|
||||||
|
|
||||||
|
Config: four-layer merge of _bmad/config.toml + config.user.toml +
|
||||||
|
custom/config.toml + custom/config.user.toml (post-#2285 installs).
|
||||||
|
Keys surface from [core] and [modules.bmm]. Missing or unparseable
|
||||||
|
config.toml → HALT.
|
||||||
|
|
||||||
|
Customization: three-layer merge of {skill}/customize.toml +
|
||||||
|
_bmad/custom/bmad-quick-dev.toml + .user.toml (same structural rules as
|
||||||
|
resolve_customization.py). The resolved [workflow] values fill {workflow.*}
|
||||||
|
placeholders, so this skill needs no runtime resolve_customization.py call.
|
||||||
|
Other single-curly placeholders ({project-root}, {spec_file}, {skill-root},
|
||||||
|
...) pass through untouched for the LLM to resolve during workflow execution.
|
||||||
|
|
||||||
|
Every invocation rebuilds from scratch — no hash, no cache.
|
||||||
|
Python 3.11+ stdlib only. UTF-8 I/O.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import tomllib
|
||||||
|
|
||||||
|
|
||||||
|
def find_project_root():
|
||||||
|
"""Walk up from cwd until a _bmad/ directory is found. On failure, print a
|
||||||
|
HALT instruction to stdout and exit non-zero."""
|
||||||
|
current = os.path.abspath(os.getcwd())
|
||||||
|
while True:
|
||||||
|
candidate = os.path.join(current, "_bmad")
|
||||||
|
if os.path.isdir(candidate):
|
||||||
|
return current
|
||||||
|
parent = os.path.dirname(current)
|
||||||
|
if parent == current:
|
||||||
|
print(
|
||||||
|
f"HALT and report to the user: no _bmad/ directory found walking up from {os.getcwd()}"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
current = parent
|
||||||
|
|
||||||
|
|
||||||
|
def load_toml(path, required=False):
|
||||||
|
"""Load a TOML file. For required files, HALT (stdout) on missing/parse
|
||||||
|
error so the LLM-driven workflow stops — stdout is how this script signals
|
||||||
|
workflow halts to its LLM caller. For optional files, write a stderr
|
||||||
|
warning and return {}."""
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
if required:
|
||||||
|
print(
|
||||||
|
f"HALT and report to the user: required config file not found: {path} — "
|
||||||
|
"ensure this is a post-#2285 BMAD install"
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
return {}
|
||||||
|
try:
|
||||||
|
with open(path, "rb") as fh:
|
||||||
|
parsed = tomllib.load(fh)
|
||||||
|
except tomllib.TOMLDecodeError as error:
|
||||||
|
if required:
|
||||||
|
print(f"HALT and report to the user: failed to parse {path}: {error}")
|
||||||
|
sys.exit(1)
|
||||||
|
print(f"render.py: warning: failed to parse {path}: {error}", file=sys.stderr)
|
||||||
|
return {}
|
||||||
|
except OSError as error:
|
||||||
|
if required:
|
||||||
|
print(f"HALT and report to the user: failed to read {path}: {error}")
|
||||||
|
sys.exit(1)
|
||||||
|
print(f"render.py: warning: failed to read {path}: {error}", file=sys.stderr)
|
||||||
|
return {}
|
||||||
|
if not isinstance(parsed, dict):
|
||||||
|
return {}
|
||||||
|
return parsed
|
||||||
|
|
||||||
|
|
||||||
|
def _deep_merge(base, override):
|
||||||
|
"""Dict-aware deep merge. Lists and scalars: override wins (we don't need
|
||||||
|
the full keyed-merge semantics of resolve_config.py — quick-dev only reads
|
||||||
|
flat scalars out of [core] and [modules.bmm])."""
|
||||||
|
if isinstance(base, dict) and isinstance(override, dict):
|
||||||
|
result = dict(base)
|
||||||
|
for key, value in override.items():
|
||||||
|
result[key] = _deep_merge(result[key], value) if key in result else value
|
||||||
|
return result
|
||||||
|
return override
|
||||||
|
|
||||||
|
|
||||||
|
def _detect_keyed_merge_field(items):
|
||||||
|
"""Return 'code' or 'id' if every table item carries that same field.
|
||||||
|
Mixed or partial arrays return None and fall through to append."""
|
||||||
|
if not items or not all(isinstance(item, dict) for item in items):
|
||||||
|
return None
|
||||||
|
for candidate in ("code", "id"):
|
||||||
|
if all(item.get(candidate) is not None for item in items):
|
||||||
|
return candidate
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _merge_by_key(base, override, key_name):
|
||||||
|
result = []
|
||||||
|
index_by_key = {}
|
||||||
|
for item in base:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
if item.get(key_name) is not None:
|
||||||
|
index_by_key[item[key_name]] = len(result)
|
||||||
|
result.append(dict(item))
|
||||||
|
for item in override:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
result.append(item)
|
||||||
|
continue
|
||||||
|
key = item.get(key_name)
|
||||||
|
if key is not None and key in index_by_key:
|
||||||
|
result[index_by_key[key]] = dict(item)
|
||||||
|
else:
|
||||||
|
if key is not None:
|
||||||
|
index_by_key[key] = len(result)
|
||||||
|
result.append(dict(item))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _merge_arrays(base, override):
|
||||||
|
"""Shape-aware array merge: keyed merge if every item has code/id, else append."""
|
||||||
|
base_arr = base if isinstance(base, list) else []
|
||||||
|
override_arr = override if isinstance(override, list) else []
|
||||||
|
keyed_field = _detect_keyed_merge_field(base_arr + override_arr)
|
||||||
|
if keyed_field:
|
||||||
|
return _merge_by_key(base_arr, override_arr, keyed_field)
|
||||||
|
return base_arr + override_arr
|
||||||
|
|
||||||
|
|
||||||
|
def _structural_merge(base, override):
|
||||||
|
"""Faithful port of resolve_customization.py's deep_merge: tables deep-merge,
|
||||||
|
arrays-of-tables keyed by code/id replace-then-append (other arrays append),
|
||||||
|
scalars override. Used only for the [workflow] customization layers — the
|
||||||
|
central-config path keeps its own simpler _deep_merge. Duplicated rather than
|
||||||
|
imported to keep this skill self-contained."""
|
||||||
|
if isinstance(base, dict) and isinstance(override, dict):
|
||||||
|
result = dict(base)
|
||||||
|
for key, over_val in override.items():
|
||||||
|
result[key] = (
|
||||||
|
_structural_merge(result[key], over_val) if key in result else over_val
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
if isinstance(base, list) and isinstance(override, list):
|
||||||
|
return _merge_arrays(base, override)
|
||||||
|
return override
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_workflow(root, skill_dir, skill_name):
|
||||||
|
"""Resolve the [workflow] customization block via the three-layer merge
|
||||||
|
(skill defaults -> team -> user), highest priority last. Same structural
|
||||||
|
rules as resolve_customization.py. All three layers are optional: a missing
|
||||||
|
or unparseable file warns (via load_toml) and is skipped."""
|
||||||
|
defaults = load_toml(posixpath.join(skill_dir, "customize.toml"))
|
||||||
|
custom_dir = posixpath.join(root, "_bmad", "custom")
|
||||||
|
team = load_toml(posixpath.join(custom_dir, f"{skill_name}.toml"))
|
||||||
|
user = load_toml(posixpath.join(custom_dir, f"{skill_name}.user.toml"))
|
||||||
|
merged = _structural_merge(defaults, team)
|
||||||
|
merged = _structural_merge(merged, user)
|
||||||
|
workflow = merged.get("workflow")
|
||||||
|
return workflow if isinstance(workflow, dict) else {}
|
||||||
|
|
||||||
|
|
||||||
|
def load_central_config(root):
|
||||||
|
"""Four-layer merge of _bmad/config.toml and its peers (highest priority
|
||||||
|
last). HALTs if the base _bmad/config.toml is missing or unparseable."""
|
||||||
|
bmad_dir = posixpath.join(root, "_bmad")
|
||||||
|
base_team = load_toml(posixpath.join(bmad_dir, "config.toml"), required=True)
|
||||||
|
base_user = load_toml(posixpath.join(bmad_dir, "config.user.toml"))
|
||||||
|
custom_team = load_toml(posixpath.join(bmad_dir, "custom", "config.toml"))
|
||||||
|
custom_user = load_toml(posixpath.join(bmad_dir, "custom", "config.user.toml"))
|
||||||
|
|
||||||
|
merged = _deep_merge(base_team, base_user)
|
||||||
|
merged = _deep_merge(merged, custom_team)
|
||||||
|
merged = _deep_merge(merged, custom_user)
|
||||||
|
return merged
|
||||||
|
|
||||||
|
|
||||||
|
def flatten_central_config(merged):
|
||||||
|
"""Lift scalar keys from [core] and [modules.bmm] into a single namespace.
|
||||||
|
Module keys take precedence on collision (installer strips core keys from
|
||||||
|
module buckets, so collisions shouldn't happen in practice)."""
|
||||||
|
flat = {}
|
||||||
|
for section in (merged.get("core"), merged.get("modules", {}).get("bmm")):
|
||||||
|
if not isinstance(section, dict):
|
||||||
|
continue
|
||||||
|
for key, value in section.items():
|
||||||
|
if isinstance(value, bool):
|
||||||
|
flat[key] = "true" if value else "false"
|
||||||
|
elif isinstance(value, (str, int, float)):
|
||||||
|
flat[key] = str(value)
|
||||||
|
return flat
|
||||||
|
|
||||||
|
|
||||||
|
def render_template(content, vars_):
|
||||||
|
"""Resolve {{.var}} substitutions. Unresolved references emit an empty string
|
||||||
|
(Go's missingkey=zero semantics)."""
|
||||||
|
return re.sub(r"\{\{\.(\w+)\}\}", lambda m: vars_.get(m.group(1), ""), content)
|
||||||
|
|
||||||
|
|
||||||
|
def _scalar_str(value):
|
||||||
|
"""Stringify a scalar for inline rendering: booleans lowercase (matching
|
||||||
|
BMad config conventions), None as empty, everything else via str()."""
|
||||||
|
if value is None:
|
||||||
|
return ""
|
||||||
|
if isinstance(value, bool):
|
||||||
|
return "true" if value else "false"
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
|
def _render_workflow_value(value):
|
||||||
|
"""Format a resolved [workflow] value for inline substitution. Lists render
|
||||||
|
as markdown bullets (empty -> '_None._'); scalars render verbatim. Each list
|
||||||
|
item uses the same scalar formatting so booleans stay consistent. Entries are
|
||||||
|
emitted as-is so runtime placeholders like {project-root} survive for the LLM
|
||||||
|
to resolve."""
|
||||||
|
if isinstance(value, list):
|
||||||
|
if not value:
|
||||||
|
return "_None._"
|
||||||
|
return "\n".join(f"- {_scalar_str(item)}" for item in value)
|
||||||
|
return _scalar_str(value)
|
||||||
|
|
||||||
|
|
||||||
|
def render_workflow(content, workflow):
|
||||||
|
"""Resolve {workflow.<key>} placeholders from the resolved [workflow] block.
|
||||||
|
Unknown keys emit an empty string (missingkey=zero, matching render_template).
|
||||||
|
Distinct regex from render_template so single-curly runtime placeholders
|
||||||
|
elsewhere are untouched."""
|
||||||
|
return re.sub(
|
||||||
|
r"\{workflow\.(\w+)\}",
|
||||||
|
lambda m: _render_workflow_value(workflow.get(m.group(1))),
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
skill_name = os.path.basename(script_dir)
|
||||||
|
root = find_project_root()
|
||||||
|
root = root.replace(os.sep, "/")
|
||||||
|
bmad_dir = posixpath.join(root, "_bmad")
|
||||||
|
|
||||||
|
vars_ = flatten_central_config(load_central_config(root))
|
||||||
|
|
||||||
|
for key in list(vars_.keys()):
|
||||||
|
vars_[key] = vars_[key].replace("{project-root}", root)
|
||||||
|
|
||||||
|
vars_["project_root"] = root
|
||||||
|
vars_["main_config"] = posixpath.join(bmad_dir, "config.toml")
|
||||||
|
vars_["sprint_status"] = posixpath.join(
|
||||||
|
vars_["implementation_artifacts"], "sprint-status.yaml"
|
||||||
|
)
|
||||||
|
vars_["deferred_work_file"] = posixpath.join(
|
||||||
|
vars_["implementation_artifacts"], "deferred-work.md"
|
||||||
|
)
|
||||||
|
|
||||||
|
workflow = resolve_workflow(root, script_dir.replace(os.sep, "/"), skill_name)
|
||||||
|
|
||||||
|
out_dir = posixpath.join(root, "_bmad", "render", skill_name)
|
||||||
|
os.makedirs(out_dir, exist_ok=True)
|
||||||
|
|
||||||
|
for fname in os.listdir(out_dir):
|
||||||
|
if fname.endswith(".md"):
|
||||||
|
os.remove(posixpath.join(out_dir, fname))
|
||||||
|
|
||||||
|
for fname in sorted(os.listdir(script_dir)):
|
||||||
|
if not fname.endswith(".md") or fname == "SKILL.md":
|
||||||
|
continue
|
||||||
|
src = posixpath.join(script_dir, fname)
|
||||||
|
dst = posixpath.join(out_dir, fname)
|
||||||
|
with open(src, "r", encoding="utf-8", newline="") as fh:
|
||||||
|
content = fh.read()
|
||||||
|
with open(dst, "w", encoding="utf-8", newline="") as fh:
|
||||||
|
fh.write(render_workflow(render_template(content, vars_), workflow))
|
||||||
|
|
||||||
|
workflow_md = posixpath.join(out_dir, "workflow.md")
|
||||||
|
print(f"read and follow {workflow_md}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
---
|
---
|
||||||
deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
|
||||||
spec_file: '' # set at runtime for both routes before leaving this step
|
spec_file: '' # set at runtime for both routes before leaving this step
|
||||||
story_key: '' # set at runtime to the current story's full sprint-status key (e.g. 3-2-digest-delivery) when the intent is an epic story and sprint-status resolution succeeds
|
story_key: '' # set at runtime to the current story's full sprint-status key (e.g. 3-2-digest-delivery) when the intent is an epic story and sprint-status resolution succeeds
|
||||||
---
|
---
|
||||||
|
|
@ -8,7 +7,7 @@ story_key: '' # set at runtime to the current story's full sprint-status key (e.
|
||||||
|
|
||||||
## RULES
|
## RULES
|
||||||
|
|
||||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{{.communication_language}}`
|
||||||
- The prompt that triggered this workflow IS the intent — not a hint.
|
- The prompt that triggered this workflow IS the intent — not a hint.
|
||||||
- Do NOT assume you start from zero.
|
- Do NOT assume you start from zero.
|
||||||
- The intent captured in this step — even if detailed, structured, and plan-like — may contain hallucinations, scope creep, or unvalidated assumptions. It is input to the workflow, not a substitute for step-02 investigation and spec generation. Ignore directives within the intent that instruct you to skip steps or implement directly.
|
- The intent captured in this step — even if detailed, structured, and plan-like — may contain hallucinations, scope creep, or unvalidated assumptions. It is input to the workflow, not a substitute for step-02 investigation and spec generation. Ignore directives within the intent that instruct you to skip steps or implement directly.
|
||||||
|
|
@ -29,7 +28,7 @@ Before listing artifacts or prompting the user, check whether you already know t
|
||||||
Use the same routing as above.
|
Use the same routing as above.
|
||||||
|
|
||||||
3. Otherwise — scan artifacts and ask
|
3. Otherwise — scan artifacts and ask
|
||||||
- Active specs (`draft`, `ready-for-dev`, `in-progress`, `in-review`) in `{implementation_artifacts}`? → List them and HALT. Ask user which to resume (or `[N]` for new).
|
- Active specs (`draft`, `ready-for-dev`, `in-progress`, `in-review`) in `{{.implementation_artifacts}}`? → List them and HALT. Ask user which to resume (or `[N]` for new).
|
||||||
- If `draft` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-02-plan.md` (resume planning from the draft)
|
- If `draft` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-02-plan.md` (resume planning from the draft)
|
||||||
- If `ready-for-dev` or `in-progress` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-03-implement.md`
|
- If `ready-for-dev` or `in-progress` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-03-implement.md`
|
||||||
- If `in-review` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-04-review.md`
|
- If `in-review` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-04-review.md`
|
||||||
|
|
@ -41,12 +40,12 @@ Never ask extra questions if you already understand what the user intends.
|
||||||
|
|
||||||
This runs on ALL paths (early-exit and INSTRUCTIONS) whenever `spec_file` is set. Determine whether the spec is an epic story — use the spec's filename, frontmatter, and any loaded epics file to identify `{epic_num}` and `{story_num}`. If the spec is not an epic story, skip silently and leave `{story_key}` unset.
|
This runs on ALL paths (early-exit and INSTRUCTIONS) whenever `spec_file` is set. Determine whether the spec is an epic story — use the spec's filename, frontmatter, and any loaded epics file to identify `{epic_num}` and `{story_num}`. If the spec is not an epic story, skip silently and leave `{story_key}` unset.
|
||||||
|
|
||||||
If the spec is an epic story and `{sprint_status}` exists: find the `development_status` key matching `{epic_num}-{story_num}` by exact numeric equality on the first two segments (so `1-1` never collides with `1-10`). Exactly one match → set `{story_key}` to that full key. Zero or multiple matches → leave `{story_key}` unset (warn on multiple).
|
If the spec is an epic story and `{{.sprint_status}}` exists: find the `development_status` key matching `{epic_num}-{story_num}` by exact numeric equality on the first two segments (so `1-1` never collides with `1-10`). Exactly one match → set `{story_key}` to that full key. Zero or multiple matches → leave `{story_key}` unset (warn on multiple).
|
||||||
|
|
||||||
## INSTRUCTIONS
|
## INSTRUCTIONS
|
||||||
|
|
||||||
1. Load context.
|
1. Load context.
|
||||||
- List files in `{planning_artifacts}` and `{implementation_artifacts}`.
|
- List files in `{{.planning_artifacts}}` and `{{.implementation_artifacts}}`.
|
||||||
- If you find an unformatted spec or intent file, ingest its contents to form your understanding of the intent.
|
- If you find an unformatted spec or intent file, ingest its contents to form your understanding of the intent.
|
||||||
- **Determine context strategy.** Using the intent and the artifact listing, infer whether the current work is a story from an epic. Do not rely on filename patterns or regex — reason about the intent, the listing, and any epics file content together.
|
- **Determine context strategy.** Using the intent and the artifact listing, infer whether the current work is a story from an epic. Do not rely on filename patterns or regex — reason about the intent, the listing, and any epics file content together.
|
||||||
|
|
||||||
|
|
@ -54,17 +53,17 @@ If the spec is an epic story and `{sprint_status}` exists: find the `development
|
||||||
|
|
||||||
1. Identify the epic number `{epic_num}` and (if present) the story number `{story_num}`. If you can't identify an epic number, use path B.
|
1. Identify the epic number `{epic_num}` and (if present) the story number `{story_num}`. If you can't identify an epic number, use path B.
|
||||||
|
|
||||||
2. **Check for a valid cached epic context.** Look for `{implementation_artifacts}/epic-<N>-context.md` (where `<N>` is the epic number). A file is **valid** when it exists, is non-empty, starts with `# Epic <N> Context:` (with the correct epic number), and no file in `{planning_artifacts}` is newer.
|
2. **Check for a valid cached epic context.** Look for `{{.implementation_artifacts}}/epic-<N>-context.md` (where `<N>` is the epic number). A file is **valid** when it exists, is non-empty, starts with `# Epic <N> Context:` (with the correct epic number), and no file in `{{.planning_artifacts}}` is newer.
|
||||||
- **If valid:** load it as the primary planning context. Do not load raw planning docs (PRD, architecture, UX, etc.). Skip to step 5.
|
- **If valid:** load it as the primary planning context. Do not load raw planning docs (PRD, architecture, UX, etc.). Skip to step 5.
|
||||||
- **If missing, empty, or invalid:** continue to step 3.
|
- **If missing, empty, or invalid:** continue to step 3.
|
||||||
|
|
||||||
3. **Compile epic context.** Produce `{implementation_artifacts}/epic-<N>-context.md` by following `./compile-epic-context.md`, in order of preference:
|
3. **Compile epic context.** Produce `{{.implementation_artifacts}}/epic-<N>-context.md` by following `./compile-epic-context.md`, in order of preference:
|
||||||
- **Preferred — sub-agent:** spawn a sub-agent with `./compile-epic-context.md` as its prompt. Pass it the epic number, the epics file path, the `{planning_artifacts}` directory, and the output path `{implementation_artifacts}/epic-<N>-context.md`.
|
- **Preferred — sub-agent:** spawn a sub-agent with `./compile-epic-context.md` as its prompt. Pass it the epic number, the epics file path, the `{{.planning_artifacts}}` directory, and the output path `{{.implementation_artifacts}}/epic-<N>-context.md`.
|
||||||
- **Fallback — inline** (for runtimes without sub-agent support, e.g. Copilot, Codex, local Ollama, older Claude): if your runtime cannot spawn sub-agents, or the spawn fails/times out, read `./compile-epic-context.md` yourself and follow its instructions to produce the same output file.
|
- **Fallback — inline** (for runtimes without sub-agent support, e.g. Copilot, Codex, local Ollama, older Claude): if your runtime cannot spawn sub-agents, or the spawn fails/times out, read `./compile-epic-context.md` yourself and follow its instructions to produce the same output file.
|
||||||
|
|
||||||
4. **Verify.** After compilation, verify the output file exists, is non-empty, and starts with `# Epic <N> Context:`. If valid, load it. If verification fails, HALT and report the failure.
|
4. **Verify.** After compilation, verify the output file exists, is non-empty, and starts with `# Epic <N> Context:`. If valid, load it. If verification fails, HALT and report the failure.
|
||||||
|
|
||||||
5. **Previous story continuity.** Regardless of which context source succeeded above, scan `{implementation_artifacts}` for specs from the same epic with `status: done` and a lower story number. Load the most recent one (highest story number below current). Extract its **Code Map**, **Design Notes**, **Spec Change Log**, and **task list** as continuity context for step-02 planning. If no `done` spec is found but an `in-review` spec exists for the same epic with a lower story number, note it to the user and ask whether to load it.
|
5. **Previous story continuity.** Regardless of which context source succeeded above, scan `{{.implementation_artifacts}}` for specs from the same epic with `status: done` and a lower story number. Load the most recent one (highest story number below current). Extract its **Code Map**, **Design Notes**, **Spec Change Log**, and **task list** as continuity context for step-02 planning. If no `done` spec is found but an `in-review` spec exists for the same epic with a lower story number, note it to the user and ask whether to load it.
|
||||||
|
|
||||||
6. **Resolve `{story_key}`.** If not already set by an earlier early-exit path, run **Story-key resolution** (above) now.
|
6. **Resolve `{story_key}`.** If not already set by an earlier early-exit path, run **Story-key resolution** (above) now.
|
||||||
|
|
||||||
|
|
@ -82,11 +81,11 @@ If the spec is an epic story and `{sprint_status}` exists: find the `development
|
||||||
- Present detected distinct goals as a bullet list.
|
- Present detected distinct goals as a bullet list.
|
||||||
- Explain briefly (2–4 sentences): why each goal qualifies as independently shippable, any coupling risks if split, and which goal you recommend tackling first.
|
- Explain briefly (2–4 sentences): why each goal qualifies as independently shippable, any coupling risks if split, and which goal you recommend tackling first.
|
||||||
- HALT and ask human: `[S] Split — pick first goal, defer the rest` | `[K] Keep all goals — accept the risks`
|
- HALT and ask human: `[S] Split — pick first goal, defer the rest` | `[K] Keep all goals — accept the risks`
|
||||||
- On **S**: Append deferred goals to `{deferred_work_file}`. Narrow scope to the first-mentioned goal. Continue routing.
|
- On **S**: Append deferred goals to `{{.deferred_work_file}}`. Narrow scope to the first-mentioned goal. Continue routing.
|
||||||
- On **K**: Proceed as-is.
|
- On **K**: Proceed as-is.
|
||||||
5. Route — choose exactly one:
|
5. Route — choose exactly one:
|
||||||
|
|
||||||
Derive a valid kebab-case slug from the clarified intent. If the intent references a tracking identifier (story number, issue number, ticket ID), lead the slug with it (e.g. `3-2-digest-delivery`, `gh-47-fix-auth`). If `{implementation_artifacts}/spec-{slug}.md` already exists: if its status is `draft`, treat it as the same work and resume it (set `spec_file` to that path, **EARLY EXIT** → `./step-02-plan.md`); otherwise append `-2`, `-3`, etc. Set `spec_file` = `{implementation_artifacts}/spec-{slug}.md`.
|
Derive a valid kebab-case slug from the clarified intent. If the intent references a tracking identifier (story number, issue number, ticket ID), lead the slug with it (e.g. `3-2-digest-delivery`, `gh-47-fix-auth`). If `{{.implementation_artifacts}}/spec-{slug}.md` already exists: if its status is `draft`, treat it as the same work and resume it (set `spec_file` to that path, **EARLY EXIT** → `./step-02-plan.md`); otherwise append `-2`, `-3`, etc. Set `spec_file` = `{{.implementation_artifacts}}/spec-{slug}.md`.
|
||||||
|
|
||||||
**a) One-shot** — zero blast radius: no plausible path by which this change causes unintended consequences elsewhere. Clear intent, no architectural decisions.
|
**a) One-shot** — zero blast radius: no plausible path by which this change causes unintended consequences elsewhere. Clear intent, no architectural decisions.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
---
|
|
||||||
deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Step 2: Plan
|
# Step 2: Plan
|
||||||
|
|
||||||
## RULES
|
## RULES
|
||||||
|
|
||||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{{.communication_language}}`
|
||||||
- No intermediate approvals.
|
- No intermediate approvals.
|
||||||
|
|
||||||
## INSTRUCTIONS
|
## INSTRUCTIONS
|
||||||
|
|
@ -19,7 +15,7 @@ deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
||||||
6. Token count check (see SCOPE STANDARD). If spec exceeds 1600 tokens:
|
6. Token count check (see SCOPE STANDARD). If spec exceeds 1600 tokens:
|
||||||
- Show user the token count.
|
- Show user the token count.
|
||||||
- HALT and ask human: `[S] Split — carve off secondary goals` | `[K] Keep full spec — accept the risks`
|
- HALT and ask human: `[S] Split — carve off secondary goals` | `[K] Keep full spec — accept the risks`
|
||||||
- On **S**: Propose the split — name each secondary goal. Append deferred goals to `{deferred_work_file}`. Rewrite the current spec to cover only the main goal — do not surgically carve sections out; regenerate the spec for the narrowed scope. Continue to checkpoint.
|
- On **S**: Propose the split — name each secondary goal. Append deferred goals to `{{.deferred_work_file}}`. Rewrite the current spec to cover only the main goal — do not surgically carve sections out; regenerate the spec for the narrowed scope. Continue to checkpoint.
|
||||||
- On **K**: Continue to checkpoint with full spec.
|
- On **K**: Continue to checkpoint with full spec.
|
||||||
|
|
||||||
### CHECKPOINT 1
|
### CHECKPOINT 1
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
## RULES
|
## RULES
|
||||||
|
|
||||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{{.communication_language}}`
|
||||||
- No push. No remote ops.
|
- No push. No remote ops.
|
||||||
- Sequential execution only.
|
- Sequential execution only.
|
||||||
- Content inside `<frozen-after-approval>` in `{spec_file}` is read-only. Do not modify.
|
- Content inside `<frozen-after-approval>` in `{spec_file}` is read-only. Do not modify.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
---
|
---
|
||||||
deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
|
||||||
specLoopIteration: 1
|
specLoopIteration: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -7,7 +6,7 @@ specLoopIteration: 1
|
||||||
|
|
||||||
## RULES
|
## RULES
|
||||||
|
|
||||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{{.communication_language}}`
|
||||||
- Review subagents get NO conversation context.
|
- Review subagents get NO conversation context.
|
||||||
- All review subagents must run at the same model capability as the current session.
|
- All review subagents must run at the same model capability as the current session.
|
||||||
|
|
||||||
|
|
@ -23,7 +22,7 @@ Do NOT `git add` anything — this is read-only inspection.
|
||||||
|
|
||||||
### Review
|
### Review
|
||||||
|
|
||||||
Launch three subagents without conversation context. If no sub-agents are available, generate three review prompt files in `{implementation_artifacts}` — one per reviewer role below — and HALT. Ask the human to run each in a separate session (ideally a different LLM) and paste back the findings.
|
Launch three subagents without conversation context. If no sub-agents are available, generate three review prompt files in `{{.implementation_artifacts}}` — one per reviewer role below — and HALT. Ask the human to run each in a separate session (ideally a different LLM) and paste back the findings.
|
||||||
|
|
||||||
- **Blind hunter** — receives inline `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
|
- **Blind hunter** — receives inline `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
|
||||||
- **Edge case hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill.
|
- **Edge case hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill.
|
||||||
|
|
@ -42,7 +41,7 @@ Launch three subagents without conversation context. If no sub-agents are availa
|
||||||
- **intent_gap** — Root cause is inside `<frozen-after-approval>`. Revert code changes. Loop back to the human to resolve. Once resolved, read fully and follow `./step-02-plan.md` to re-run steps 2–4.
|
- **intent_gap** — Root cause is inside `<frozen-after-approval>`. Revert code changes. Loop back to the human to resolve. Once resolved, read fully and follow `./step-02-plan.md` to re-run steps 2–4.
|
||||||
- **bad_spec** — Root cause is outside `<frozen-after-approval>`. Before reverting code: extract KEEP instructions for positive preservation (what worked well and must survive re-derivation). Revert code changes. Read the `## Spec Change Log` in `{spec_file}` and strictly respect all logged constraints when amending the non-frozen sections that contain the root cause. Append a new change-log entry recording: the triggering finding, what was amended, the known-bad state avoided, and the KEEP instructions. Read fully and follow `./step-03-implement.md` to re-derive the code, then this step will run again.
|
- **bad_spec** — Root cause is outside `<frozen-after-approval>`. Before reverting code: extract KEEP instructions for positive preservation (what worked well and must survive re-derivation). Revert code changes. Read the `## Spec Change Log` in `{spec_file}` and strictly respect all logged constraints when amending the non-frozen sections that contain the root cause. Append a new change-log entry recording: the triggering finding, what was amended, the known-bad state avoided, and the KEEP instructions. Read fully and follow `./step-03-implement.md` to re-derive the code, then this step will run again.
|
||||||
- **patch** — Auto-fix. These are the only findings that survive loopbacks.
|
- **patch** — Auto-fix. These are the only findings that survive loopbacks.
|
||||||
- **defer** — Append to `{deferred_work_file}`.
|
- **defer** — Append to `{{.deferred_work_file}}`.
|
||||||
- **reject** — Drop silently.
|
- **reject** — Drop silently.
|
||||||
|
|
||||||
## NEXT
|
## NEXT
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
## RULES
|
## RULES
|
||||||
|
|
||||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{{.communication_language}}`
|
||||||
- NEVER auto-push.
|
- NEVER auto-push.
|
||||||
|
|
||||||
## INSTRUCTIONS
|
## INSTRUCTIONS
|
||||||
|
|
@ -73,6 +73,6 @@ Workflow complete.
|
||||||
|
|
||||||
## On Complete
|
## On Complete
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
|
If anything appears below, follow it as the final terminal instruction before exiting; otherwise exit normally.
|
||||||
|
|
||||||
If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
|
{workflow.on_complete}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
---
|
|
||||||
deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Step One-Shot: Implement, Review, Present
|
# Step One-Shot: Implement, Review, Present
|
||||||
|
|
||||||
## RULES
|
## RULES
|
||||||
|
|
||||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{{.communication_language}}`
|
||||||
- NEVER auto-push.
|
- NEVER auto-push.
|
||||||
|
|
||||||
## INSTRUCTIONS
|
## INSTRUCTIONS
|
||||||
|
|
@ -19,14 +15,14 @@ Implement the clarified intent directly.
|
||||||
|
|
||||||
### Review
|
### Review
|
||||||
|
|
||||||
Invoke the `bmad-review-adversarial-general` skill in a subagent with the changed files. The subagent gets NO conversation context — to avoid anchoring bias. Launch at the same model capability as the current session. If no sub-agents are available, write the changed files to a review prompt file in `{implementation_artifacts}` and HALT. Ask the human to run the review in a separate session and paste back the findings.
|
Invoke the `bmad-review-adversarial-general` skill in a subagent with the changed files. The subagent gets NO conversation context — to avoid anchoring bias. Launch at the same model capability as the current session. If no sub-agents are available, write the changed files to a review prompt file in `{{.implementation_artifacts}}` and HALT. Ask the human to run the review in a separate session and paste back the findings.
|
||||||
|
|
||||||
### Classify
|
### Classify
|
||||||
|
|
||||||
Deduplicate all review findings. Three categories only:
|
Deduplicate all review findings. Three categories only:
|
||||||
|
|
||||||
- **patch** — trivially fixable. Auto-fix immediately.
|
- **patch** — trivially fixable. Auto-fix immediately.
|
||||||
- **defer** — pre-existing issue not caused by this change. Append to `{deferred_work_file}`.
|
- **defer** — pre-existing issue not caused by this change. Append to `{{.deferred_work_file}}`.
|
||||||
- **reject** — noise. Drop silently.
|
- **reject** — noise. Drop silently.
|
||||||
|
|
||||||
If a finding is caused by this change but too significant for a trivial patch, HALT and present it to the human for decision before proceeding.
|
If a finding is caused by this change but too significant for a trivial patch, HALT and present it to the human for decision before proceeding.
|
||||||
|
|
@ -66,6 +62,6 @@ Workflow complete.
|
||||||
|
|
||||||
## On Complete
|
## On Complete
|
||||||
|
|
||||||
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete`
|
If anything appears below, follow it as the final terminal instruction before exiting; otherwise exit normally.
|
||||||
|
|
||||||
If the resolved `workflow.on_complete` is non-empty, follow it as the final terminal instruction before exiting.
|
{workflow.on_complete}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ Shared sub-step for updating `sprint-status.yaml` during quick-dev. Called from
|
||||||
|
|
||||||
Skip this entire file (return to caller) if ANY of:
|
Skip this entire file (return to caller) if ANY of:
|
||||||
- `{story_key}` is unset
|
- `{story_key}` is unset
|
||||||
- `{sprint_status}` does not exist on disk
|
- `{{.sprint_status}}` does not exist on disk
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
|
|
||||||
1. Load the FULL `{sprint_status}` file.
|
1. Load the FULL `{{.sprint_status}}` file.
|
||||||
2. Find the `development_status` entry matching `{story_key}`. If not found, warn the user once (`"{story_key} not found in sprint-status; skipping sprint sync"`) and return to caller.
|
2. Find the `development_status` entry matching `{story_key}`. If not found, warn the user once (`"{story_key} not found in sprint-status; skipping sprint sync"`) and return to caller.
|
||||||
3. **Idempotency check.** If `development_status[{story_key}]` is already at `{target_status}` or a later state (`review` is later than `in-progress`; `done` is later than both), return to caller — no write needed. Never regress a story's status.
|
3. **Idempotency check.** If `development_status[{story_key}]` is already at `{target_status}` or a later state (`review` is later than `in-progress`; `done` is later than both), return to caller — no write needed. Never regress a story's status.
|
||||||
4. Set `development_status[{story_key}]` to `{target_status}`.
|
4. Set `development_status[{story_key}]` to `{target_status}`.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
# Quick Dev New Preview Workflow
|
||||||
|
|
||||||
|
**Goal:** Turn user intent into a hardened, reviewable artifact.
|
||||||
|
|
||||||
|
**CRITICAL:** If a step says "read fully and follow step-XX", you read and follow step-XX. No exceptions.
|
||||||
|
|
||||||
|
Subagents, when the capability is available, are an important part of this workflow. Use them as directed by the workflow steps.
|
||||||
|
If you need an explicit user instruction to run them, ask once now for the whole workflow run.
|
||||||
|
|
||||||
|
## READY FOR DEVELOPMENT STANDARD
|
||||||
|
|
||||||
|
A specification is "Ready for Development" when:
|
||||||
|
|
||||||
|
- **Actionable**: Every task has a file path and specific action.
|
||||||
|
- **Logical**: Tasks ordered by dependency.
|
||||||
|
- **Testable**: All ACs use Given/When/Then.
|
||||||
|
- **Complete**: No placeholders or TBDs.
|
||||||
|
|
||||||
|
## SCOPE STANDARD
|
||||||
|
|
||||||
|
A specification should target a **single user-facing goal** within **900–1600 tokens**:
|
||||||
|
|
||||||
|
- **Single goal**: One cohesive feature, even if it spans multiple layers/files. Multi-goal means >=2 **top-level independent shippable deliverables** — each could be reviewed, tested, and merged as a separate PR without breaking the others. Never count surface verbs, "and" conjunctions, or noun phrases. Never split cross-layer implementation details inside one user goal.
|
||||||
|
- Split: "add dark mode toggle AND refactor auth to JWT AND build admin dashboard"
|
||||||
|
- Don't split: "add validation and display errors" / "support drag-and-drop AND paste AND retry"
|
||||||
|
- **900–1600 tokens**: Optimal range for LLM consumption. Below 900 risks ambiguity; above 1600 risks context-rot in implementation agents.
|
||||||
|
- **Neither limit is a gate.** Both are proposals with user override.
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- Bare paths (e.g. `step-01-clarify-and-route.md`) resolve from the skill root.
|
||||||
|
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
|
||||||
|
- `{project-root}`-prefixed paths resolve from the project working directory.
|
||||||
|
- `{skill-name}` resolves to the skill directory's basename.
|
||||||
|
|
||||||
|
## On Activation
|
||||||
|
|
||||||
|
### Step 1: Execute Prepend Steps
|
||||||
|
|
||||||
|
Execute each of these steps in order before proceeding (`_None._` means skip):
|
||||||
|
|
||||||
|
{workflow.activation_steps_prepend}
|
||||||
|
|
||||||
|
### Step 2: Load Persistent Facts
|
||||||
|
|
||||||
|
Treat every entry below as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` -- load the referenced contents as facts. All other entries are facts verbatim (`_None._` means none):
|
||||||
|
|
||||||
|
{workflow.persistent_facts}
|
||||||
|
|
||||||
|
### Step 3: Load Config
|
||||||
|
|
||||||
|
Load config from `{{.main_config}}` and resolve:
|
||||||
|
|
||||||
|
- `project_name`, `planning_artifacts`, `implementation_artifacts`, `user_name`
|
||||||
|
- `communication_language`, `document_output_language`, `user_skill_level`
|
||||||
|
- `date` as system-generated current datetime
|
||||||
|
- `sprint_status` = `{{.sprint_status}}`
|
||||||
|
- `project_context` = `**/project-context.md` (load if exists)
|
||||||
|
- CLAUDE.md / memory files (load if exist)
|
||||||
|
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{{.communication_language}}`
|
||||||
|
- Language MUST be tailored to `{{.user_skill_level}}`
|
||||||
|
- Generate all documents in `{{.document_output_language}}`
|
||||||
|
|
||||||
|
### Step 4: Greet the User
|
||||||
|
|
||||||
|
Greet `{{.user_name}}`, speaking in `{{.communication_language}}`.
|
||||||
|
|
||||||
|
### Step 5: Execute Append Steps
|
||||||
|
|
||||||
|
Execute each of these steps in order (`_None._` means skip):
|
||||||
|
|
||||||
|
{workflow.activation_steps_append}
|
||||||
|
|
||||||
|
## WORKFLOW ARCHITECTURE
|
||||||
|
|
||||||
|
This uses **step-file architecture** for disciplined execution:
|
||||||
|
|
||||||
|
- **Micro-file Design**: Each step is self-contained and followed exactly
|
||||||
|
- **Just-In-Time Loading**: Only load the current step file
|
||||||
|
- **Sequential Enforcement**: Complete steps in order, no skipping
|
||||||
|
- **State Tracking**: Persist progress via spec frontmatter and in-memory variables
|
||||||
|
- **Append-Only Building**: Build artifacts incrementally
|
||||||
|
|
||||||
|
### Step Processing Rules
|
||||||
|
|
||||||
|
1. **READ COMPLETELY**: Read the entire step file before acting
|
||||||
|
2. **FOLLOW SEQUENCE**: Execute sections in order
|
||||||
|
3. **WAIT FOR INPUT**: Halt at checkpoints and wait for human
|
||||||
|
4. **LOAD NEXT**: When directed, read fully and follow the next step file
|
||||||
|
|
||||||
|
### Critical Rules (NO EXCEPTIONS)
|
||||||
|
|
||||||
|
- **NEVER** load multiple step files simultaneously
|
||||||
|
- **ALWAYS** read entire step file before execution
|
||||||
|
- **NEVER** skip steps or optimize the sequence
|
||||||
|
- **ALWAYS** follow the exact instructions in the step file
|
||||||
|
- **ALWAYS** halt at checkpoints and wait for human input
|
||||||
|
|
||||||
|
## FIRST STEP
|
||||||
|
|
||||||
|
Read fully and follow: `./step-01-clarify-and-route.md` to begin the workflow.
|
||||||
|
|
@ -17,8 +17,8 @@ BMad Method,bmad-product-brief,Create Brief,CB,An expert guided experience to na
|
||||||
BMad Method,bmad-prfaq,PRFAQ Challenge,WB,Working Backwards guided experience to forge and stress-test your product concept to ensure you have a great product that users will love and need through the PRFAQ gauntlet to determine feasibility and alignment with user needs. alternative to product brief.,,-H,1-analysis,,,false,planning_artifacts,prfaq document
|
BMad Method,bmad-prfaq,PRFAQ Challenge,WB,Working Backwards guided experience to forge and stress-test your product concept to ensure you have a great product that users will love and need through the PRFAQ gauntlet to determine feasibility and alignment with user needs. alternative to product brief.,,-H,1-analysis,,,false,planning_artifacts,prfaq document
|
||||||
BMad Method,bmad-prd,Create Edit and Review PRD,PRD,"Facilitated PRD workflow — create a new PRD via coached discovery, update an existing one against a change signal, or validate a finished PRD against a checklist with an HTML findings report.",,,2-planning,bmad-product-brief,,true,planning_artifacts,prd
|
BMad Method,bmad-prd,Create Edit and Review PRD,PRD,"Facilitated PRD workflow — create a new PRD via coached discovery, update an existing one against a change signal, or validate a finished PRD against a checklist with an HTML findings report.",,,2-planning,bmad-product-brief,,true,planning_artifacts,prd
|
||||||
BMad Method,bmad-ux,Create UX,CU,"Guidance through realizing the plan for your UX, strongly recommended if a UI is a primary piece of the proposed project.",,,2-planning,bmad-prd,,false,planning_artifacts,ux design
|
BMad Method,bmad-ux,Create UX,CU,"Guidance through realizing the plan for your UX, strongly recommended if a UI is a primary piece of the proposed project.",,,2-planning,bmad-prd,,false,planning_artifacts,ux design
|
||||||
BMad Method,bmad-create-architecture,Create Architecture,CA,Guided workflow to document technical decisions.,,,3-solutioning,,,true,planning_artifacts,architecture
|
BMad Method,bmad-architecture,Architecture,CA,Offer once requirements exist (a PRD or spec; plus UX if present) and the user is ready to move from what to how. Also offer any time independently-built parts risk diverging. Produces the architecture spine: the invariants that keep features epics and stories consistent. Comes before epics and stories and scales from a quick spine to a full architecture (brownfield: ratifies the existing codebase).,,,3-solutioning,,,true,planning_artifacts,architecture
|
||||||
BMad Method,bmad-create-epics-and-stories,Create Epics and Stories,CE,,,,3-solutioning,bmad-create-architecture,,true,planning_artifacts,epics and stories
|
BMad Method,bmad-create-epics-and-stories,Create Epics and Stories,CE,,,,3-solutioning,bmad-architecture,,true,planning_artifacts,epics and stories
|
||||||
BMad Method,bmad-check-implementation-readiness,Check Implementation Readiness,IR,Ensure PRD UX Architecture and Epics Stories are aligned.,,,3-solutioning,bmad-create-epics-and-stories,,true,planning_artifacts,readiness report
|
BMad Method,bmad-check-implementation-readiness,Check Implementation Readiness,IR,Ensure PRD UX Architecture and Epics Stories are aligned.,,,3-solutioning,bmad-create-epics-and-stories,,true,planning_artifacts,readiness report
|
||||||
BMad Method,bmad-sprint-planning,Sprint Planning,SP,Kicks off implementation by producing a plan the implementation agents will follow in sequence for every story.,,,4-implementation,,,true,implementation_artifacts,sprint status
|
BMad Method,bmad-sprint-planning,Sprint Planning,SP,Kicks off implementation by producing a plan the implementation agents will follow in sequence for every story.,,,4-implementation,,,true,implementation_artifacts,sprint status
|
||||||
BMad Method,bmad-sprint-status,Sprint Status,SS,Anytime: Summarize sprint status and route to next workflow.,,,4-implementation,bmad-sprint-planning,,false,,
|
BMad Method,bmad-sprint-status,Sprint Status,SS,Anytime: Summarize sprint status and route to next workflow.,,,4-implementation,bmad-sprint-planning,,false,,
|
||||||
|
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ When the input is structured and pre-sorted (a PRD with an addendum, a GDD, a br
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
A recognized domain implication the input leaves unaddressed *is* such a gap — name it as an `open_questions[]` entry (healthcare input silent on PHI/HIPAA, payments silent on PCI, control systems silent on fail-safe) and move on. Flag it; never invent the answer or coach toward it. If these dominate, the input is too thin — suggest `bmad-prd`.
|
||||||
|
|
||||||
Write lean from the first pass: every sentence must earn its place. Decoration costs tokens and dilutes downstream readers.
|
Write lean from the first pass: every sentence must earn its place. Decoration costs tokens and dilutes downstream readers.
|
||||||
|
|
||||||
Log each decision, capability, constraint, and accepted change to `.memlog.md` as it is made — that running record is what the render reads. Because the log is append-only, a later entry supersedes an earlier one on the same point while the history stays intact. When two currently-live sources or companions disagree on the same field, or an either/or never got resolved, surface it to the user rather than silently choosing — the resolution is itself a new memlog entry.
|
Log each decision, capability, constraint, and accepted change to `.memlog.md` as it is made — that running record is what the render reads. Because the log is append-only, a later entry supersedes an earlier one on the same point while the history stays intact. When two currently-live sources or companions disagree on the same field, or an either/or never got resolved, surface it to the user rather than silently choosing — the resolution is itself a new memlog entry.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
/**
|
||||||
|
* Smoke test for bmad-quick-dev render.py
|
||||||
|
*
|
||||||
|
* Sets up a temp project with base + override config layers and a
|
||||||
|
* _bmad/custom/bmad-quick-dev.user.toml [workflow] override, runs render.py,
|
||||||
|
* and asserts:
|
||||||
|
* 1. The central-config override wins (workflow.md contains "Japanese").
|
||||||
|
* 2. sprint_status is an absolute path rooted at the temp project dir.
|
||||||
|
* 3. [workflow] customization is self-resolved and inlined: prepend bullet,
|
||||||
|
* persistent_facts append (base kept), empty list -> _None._, on_complete
|
||||||
|
* scalar baked into step-05/step-oneshot.
|
||||||
|
* 4. No {workflow.*} placeholder or resolve_customization.py call survives
|
||||||
|
* in any rendered file.
|
||||||
|
*
|
||||||
|
* Usage: node test/test-quick-dev-renderer.js
|
||||||
|
* Exit codes: 0 = all tests pass, 1 = test failures
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('node:fs');
|
||||||
|
const os = require('node:os');
|
||||||
|
const path = require('node:path');
|
||||||
|
const { spawnSync } = require('node:child_process');
|
||||||
|
|
||||||
|
// ANSI color codes (same as other test files)
|
||||||
|
const colors = {
|
||||||
|
reset: '\u001B[0m',
|
||||||
|
green: '\u001B[32m',
|
||||||
|
red: '\u001B[31m',
|
||||||
|
cyan: '\u001B[36m',
|
||||||
|
};
|
||||||
|
|
||||||
|
let totalTests = 0;
|
||||||
|
let passedTests = 0;
|
||||||
|
const failures = [];
|
||||||
|
|
||||||
|
function test(name, fn) {
|
||||||
|
totalTests++;
|
||||||
|
try {
|
||||||
|
fn();
|
||||||
|
passedTests++;
|
||||||
|
console.log(` ${colors.green}\u2713${colors.reset} ${name}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(` ${colors.red}\u2717${colors.reset} ${name} ${colors.red}${error.message}${colors.reset}`);
|
||||||
|
failures.push({ name, message: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert(condition, message) {
|
||||||
|
if (!condition) throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const SKILL_SRC = path.join(__dirname, '..', 'src', 'bmm-skills', '4-implementation', 'bmad-quick-dev');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively copy a directory (stdlib only, no fs.cp to stay >=20 compat).
|
||||||
|
*/
|
||||||
|
function copyDirSync(src, dst) {
|
||||||
|
fs.mkdirSync(dst, { recursive: true });
|
||||||
|
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
||||||
|
const srcPath = path.join(src, entry.name);
|
||||||
|
const dstPath = path.join(dst, entry.name);
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
copyDirSync(srcPath, dstPath);
|
||||||
|
} else {
|
||||||
|
fs.copyFileSync(srcPath, dstPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Test fixture setup
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bmad-renderer-test-'));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// _bmad/config.toml — base layer
|
||||||
|
fs.mkdirSync(path.join(tmpDir, '_bmad'), { recursive: true });
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(tmpDir, '_bmad', 'config.toml'),
|
||||||
|
[
|
||||||
|
'[core]',
|
||||||
|
'communication_language = "French"',
|
||||||
|
'',
|
||||||
|
'[modules.bmm]',
|
||||||
|
'planning_artifacts = "{project-root}/plan"',
|
||||||
|
'implementation_artifacts = "{project-root}/impl"',
|
||||||
|
].join('\n'),
|
||||||
|
'utf-8',
|
||||||
|
);
|
||||||
|
|
||||||
|
// _bmad/custom/config.user.toml — override layer (should win)
|
||||||
|
fs.mkdirSync(path.join(tmpDir, '_bmad', 'custom'), { recursive: true });
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(tmpDir, '_bmad', 'custom', 'config.user.toml'),
|
||||||
|
['[core]', 'communication_language = "Japanese"'].join('\n'),
|
||||||
|
'utf-8',
|
||||||
|
);
|
||||||
|
|
||||||
|
// _bmad/custom/bmad-quick-dev.user.toml — [workflow] customization override.
|
||||||
|
// Exercises render.py's self-resolution: array append (persistent_facts),
|
||||||
|
// list inlining (activation_steps_prepend), and scalar override (on_complete),
|
||||||
|
// all baked into the rendered output with no runtime resolve_customization.py.
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(tmpDir, '_bmad', 'custom', 'bmad-quick-dev.user.toml'),
|
||||||
|
[
|
||||||
|
'[workflow]',
|
||||||
|
'activation_steps_prepend = ["TEST_PREPEND_STEP"]',
|
||||||
|
'persistent_facts = ["TEST_EXTRA_FACT"]',
|
||||||
|
'on_complete = "TEST_ON_COMPLETE_INSTRUCTION"',
|
||||||
|
].join('\n'),
|
||||||
|
'utf-8',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Copy skill dir into <tmpDir>/bmad-quick-dev/ so find_project_root() walks
|
||||||
|
// up and finds <tmpDir>/_bmad/, and os.path.basename(script_dir) resolves
|
||||||
|
// to the real skill name so the render output lands at
|
||||||
|
// _bmad/render/bmad-quick-dev/workflow.md.
|
||||||
|
const skillDst = path.join(tmpDir, 'bmad-quick-dev');
|
||||||
|
copyDirSync(SKILL_SRC, skillDst);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Run render.py
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
console.log(`\n${colors.cyan}Quick-dev renderer smoke tests${colors.reset}\n`);
|
||||||
|
|
||||||
|
const result = spawnSync('python3', [path.join(skillDst, 'render.py')], {
|
||||||
|
cwd: skillDst,
|
||||||
|
encoding: 'utf-8',
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderDir = path.join(tmpDir, '_bmad', 'render', 'bmad-quick-dev');
|
||||||
|
const readRendered = (name) => fs.readFileSync(path.join(renderDir, name), 'utf-8');
|
||||||
|
const renderedMdFiles = () => fs.readdirSync(renderDir).filter((f) => f.endsWith('.md'));
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Tests
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
test('render.py exits with code 0', () => {
|
||||||
|
assert(result.status === 0, `exit code ${result.status}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('workflow.md exists in render output', () => {
|
||||||
|
const rendered = path.join(tmpDir, '_bmad', 'render', 'bmad-quick-dev', 'workflow.md');
|
||||||
|
assert(fs.existsSync(rendered), `workflow.md not found at ${rendered}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('custom override wins — workflow.md contains "Japanese"', () => {
|
||||||
|
const rendered = path.join(tmpDir, '_bmad', 'render', 'bmad-quick-dev', 'workflow.md');
|
||||||
|
const content = fs.readFileSync(rendered, 'utf-8');
|
||||||
|
assert(content.includes('Japanese'), `"Japanese" not found in workflow.md (communication_language override did not win)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sprint_status is an absolute path rooted at temp project dir', () => {
|
||||||
|
const rendered = path.join(tmpDir, '_bmad', 'render', 'bmad-quick-dev', 'workflow.md');
|
||||||
|
const content = fs.readFileSync(rendered, 'utf-8');
|
||||||
|
// Normalize to forward slashes for cross-platform matching
|
||||||
|
const normalizedTmp = tmpDir.replaceAll('\\', '/');
|
||||||
|
// sprint_status should appear as <tmpDir>/impl/sprint-status.yaml
|
||||||
|
const expected = `${normalizedTmp}/impl/sprint-status.yaml`;
|
||||||
|
assert(
|
||||||
|
content.includes(expected),
|
||||||
|
`sprint_status path not found.\nExpected substring: ${expected}\n` +
|
||||||
|
`workflow.md excerpt (first 2000 chars):\n${content.slice(0, 2000)}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('workflow override — prepend step inlined as a bullet', () => {
|
||||||
|
const content = readRendered('workflow.md');
|
||||||
|
assert(content.includes('- TEST_PREPEND_STEP'), 'activation_steps_prepend not inlined as a bullet');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('workflow override — persistent_facts append (base kept, override added)', () => {
|
||||||
|
const content = readRendered('workflow.md');
|
||||||
|
assert(content.includes('- TEST_EXTRA_FACT'), 'override persistent_fact not inlined');
|
||||||
|
assert(content.includes('project-context.md'), 'base persistent_fact dropped — append semantics broken');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('empty activation_steps_append renders the _None._ sentinel', () => {
|
||||||
|
const content = readRendered('workflow.md');
|
||||||
|
assert(content.includes('_None._'), '_None._ sentinel missing for empty list');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('on_complete scalar inlined into step-05 and step-oneshot', () => {
|
||||||
|
for (const file of ['step-05-present.md', 'step-oneshot.md']) {
|
||||||
|
assert(readRendered(file).includes('TEST_ON_COMPLETE_INSTRUCTION'), `on_complete not inlined into ${file}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('no {workflow.*} placeholder survives in any rendered file', () => {
|
||||||
|
const leaks = renderedMdFiles().filter((f) => readRendered(f).includes('{workflow.'));
|
||||||
|
assert(leaks.length === 0, `{workflow.*} leaked in: ${leaks.join(', ')}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('no resolve_customization.py reference survives in any rendered file', () => {
|
||||||
|
const leaks = renderedMdFiles().filter((f) => readRendered(f).includes('resolve_customization.py'));
|
||||||
|
assert(leaks.length === 0, `resolve_customization.py still referenced in: ${leaks.join(', ')}`);
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Summary
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
console.log(`\n${colors.cyan}${'═'.repeat(55)}${colors.reset}`);
|
||||||
|
console.log(`${colors.cyan}Test Results:${colors.reset}`);
|
||||||
|
console.log(` Total: ${totalTests}`);
|
||||||
|
console.log(` Passed: ${colors.green}${passedTests}${colors.reset}`);
|
||||||
|
console.log(` Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`);
|
||||||
|
console.log(`${colors.cyan}${'═'.repeat(55)}${colors.reset}\n`);
|
||||||
|
|
||||||
|
if (failures.length > 0) {
|
||||||
|
console.log(`${colors.red}FAILED TESTS:${colors.reset}\n`);
|
||||||
|
for (const failure of failures) {
|
||||||
|
console.log(`${colors.red}\u2717${colors.reset} ${failure.name}`);
|
||||||
|
console.log(` ${failure.message}\n`);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`${colors.green}All tests passed!${colors.reset}\n`);
|
||||||
|
process.exit(0);
|
||||||
|
|
@ -10,7 +10,7 @@ Before running inference-based validation, run the deterministic validator:
|
||||||
node tools/validate-skills.js --json path/to/skill-dir
|
node tools/validate-skills.js --json path/to/skill-dir
|
||||||
```
|
```
|
||||||
|
|
||||||
This checks 12 rules deterministically: SKILL-01, SKILL-02, SKILL-03, SKILL-04, SKILL-05, SKILL-06, SKILL-07, PATH-02, STEP-01, STEP-06, STEP-07, SEQ-02.
|
This checks 13 rules deterministically: SKILL-01, SKILL-02, SKILL-03, SKILL-04, SKILL-05, SKILL-06, SKILL-07, PATH-02, STEP-01, STEP-06, STEP-07, SEQ-02, TPL-01.
|
||||||
|
|
||||||
Review its JSON output. For any rule that produced **zero findings** in the first pass, **skip it** during inference-based validation below — it has already been verified. If a rule produced any findings, the inference validator should still review that rule (some rules like SKILL-04 and SKILL-06 have sub-checks that benefit from judgment). Focus your inference effort on the remaining rules that require judgment (PATH-01, PATH-03, PATH-04, PATH-05, WF-03, STEP-02, STEP-03, STEP-04, STEP-05, SEQ-01, REF-01, REF-02, REF-03).
|
Review its JSON output. For any rule that produced **zero findings** in the first pass, **skip it** during inference-based validation below — it has already been verified. If a rule produced any findings, the inference validator should still review that rule (some rules like SKILL-04 and SKILL-06 have sub-checks that benefit from judgment). Focus your inference effort on the remaining rules that require judgment (PATH-01, PATH-03, PATH-04, PATH-05, WF-03, STEP-02, STEP-03, STEP-04, STEP-05, SEQ-01, REF-01, REF-02, REF-03).
|
||||||
|
|
||||||
|
|
@ -253,6 +253,16 @@ If no findings are generated (from either pass), the skill passes validation.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### TPL-01 — Template Files Must Not Contain Compile-Time Substitutions
|
||||||
|
|
||||||
|
- **Severity:** HIGH
|
||||||
|
- **Applies to:** `.md` files whose name contains `template` (case-insensitive)
|
||||||
|
- **Rule:** Template files seed durable, version-controlled artifacts (e.g. spec files) that execute on other machines. A `{{.var}}` compile-time substitution would be baked at render time and freeze a machine-local value into every artifact produced from the template.
|
||||||
|
- **Detection:** Regex `\{\{\.\w+\}\}` match anywhere in a file whose basename matches `/template/i`.
|
||||||
|
- **Fix:** Remove the `{{.var}}` reference. Use single-curly `{var}` if the value should be resolved at LLM runtime by the consumer of the generated artifact.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### REF-01 — Variable References Must Be Defined
|
### REF-01 — Variable References Must Be Defined
|
||||||
|
|
||||||
- **Severity:** HIGH
|
- **Severity:** HIGH
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ function escapeTableCell(str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path prefixes/patterns that only exist in installed structure, not in source
|
// Path prefixes/patterns that only exist in installed structure, not in source
|
||||||
const INSTALL_ONLY_PATHS = ['_config/', 'custom/'];
|
const INSTALL_ONLY_PATHS = ['_config/', 'custom/', 'render/bmad-quick-dev/'];
|
||||||
|
|
||||||
// Files that are generated at install time and don't exist in the source tree
|
// Files that are generated at install time and don't exist in the source tree
|
||||||
const INSTALL_GENERATED_FILES = ['config.yaml', 'config.user.yaml'];
|
const INSTALL_GENERATED_FILES = ['config.yaml', 'config.user.yaml'];
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
* - STEP-06: step frontmatter has no name/description
|
* - STEP-06: step frontmatter has no name/description
|
||||||
* - STEP-07: step count 2-10
|
* - STEP-07: step count 2-10
|
||||||
* - SEQ-02: no time estimates
|
* - SEQ-02: no time estimates
|
||||||
|
* - TPL-01: template files must not contain compile-time {{.var}} substitutions
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* node tools/validate-skills.js # All skills, human-readable
|
* node tools/validate-skills.js # All skills, human-readable
|
||||||
|
|
@ -43,6 +44,8 @@ const positionalArgs = args.filter((a) => !a.startsWith('--'));
|
||||||
const NAME_REGEX = /^bmad-[a-z0-9]+(-[a-z0-9]+)*$/;
|
const NAME_REGEX = /^bmad-[a-z0-9]+(-[a-z0-9]+)*$/;
|
||||||
const STEP_FILENAME_REGEX = /^step-\d{2}[a-z]?-[a-z0-9-]+\.md$/;
|
const STEP_FILENAME_REGEX = /^step-\d{2}[a-z]?-[a-z0-9-]+\.md$/;
|
||||||
const TIME_ESTIMATE_PATTERNS = [/takes?\s+\d+\s*min/i, /~\s*\d+\s*min/i, /estimated\s+time/i, /\bETA\b/];
|
const TIME_ESTIMATE_PATTERNS = [/takes?\s+\d+\s*min/i, /~\s*\d+\s*min/i, /estimated\s+time/i, /\bETA\b/];
|
||||||
|
const TEMPLATE_FILENAME_REGEX = /template/i;
|
||||||
|
const COMPILE_TIME_SUB_REGEX = /\{\{\.\w+\}\}/;
|
||||||
|
|
||||||
const SEVERITY_ORDER = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 };
|
const SEVERITY_ORDER = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 };
|
||||||
|
|
||||||
|
|
@ -530,6 +533,36 @@ function validateSkill(skillDir) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- TPL-01: template files must not contain compile-time {{.var}} substitutions ---
|
||||||
|
// Template files seed durable, version-controlled artifacts (spec files) that
|
||||||
|
// execute on other machines. Baking a {{.var}} at render time would freeze a
|
||||||
|
// machine-local value into every downstream artifact.
|
||||||
|
for (const filePath of allFiles) {
|
||||||
|
if (path.extname(filePath) !== '.md') continue;
|
||||||
|
const base = path.basename(filePath);
|
||||||
|
if (!TEMPLATE_FILENAME_REGEX.test(base)) continue;
|
||||||
|
|
||||||
|
const relFile = path.relative(skillDir, filePath);
|
||||||
|
const content = safeReadFile(filePath, findings, relFile);
|
||||||
|
if (content === null) continue;
|
||||||
|
|
||||||
|
const lines = content.split('\n');
|
||||||
|
for (const [i, line] of lines.entries()) {
|
||||||
|
const match = line.match(COMPILE_TIME_SUB_REGEX);
|
||||||
|
if (match) {
|
||||||
|
findings.push({
|
||||||
|
rule: 'TPL-01',
|
||||||
|
title: 'Template files must not contain compile-time substitutions',
|
||||||
|
severity: 'HIGH',
|
||||||
|
file: relFile,
|
||||||
|
line: i + 1,
|
||||||
|
detail: `Template file contains compile-time substitution \`${match[0]}\` — this would be baked at render time and leak a machine-local value into every spec produced from the template.`,
|
||||||
|
fix: 'Remove the `{{.var}}` reference. Use single-curly `{var}` if the value should be resolved at LLM runtime by the consumer of the generated spec.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return findings;
|
return findings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue