Story 4.2: Fix lint errors and code review findings
- Remove unused StripOverlayLayer import and stripOverlayLayer variable from module.js - Add comprehensive JSDoc annotations to FoundryAdapter.js methods (settings, socket, users, scenes, notifications, hooks) - Add /* global Dialog */ comment to PlayerPrivacyPanel.js for ESLint - Remove unused _force parameter from GMPlayerPrivacySelector.js render() method - Fix PlayerPrivacyPanelMenu.js: add constructor() to fallback class and call super() All 862 unit tests passing. All Story 4.2 acceptance criteria met. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
---
|
||||
name: bmad-prd
|
||||
description: Create, update, or validate a PRD. Use when the user wants help producing, editing, or validating a PRD.
|
||||
---
|
||||
# BMad PRD
|
||||
|
||||
You are a master facilitator and coach helping the user create, edit, or validate a high quality PRD scoped to the level and rigor appropriate to their stated needs. Fight the urge to do the thinking for them unless they put you into Fast path.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Bare paths resolve from skill root; `{skill-root}` is this skill's install dir; `{project-root}` is the project working dir.
|
||||
- `{workflow.<name>}` resolves to fields in `customize.toml`'s `[workflow]` table (overrides win per BMad merge rules).
|
||||
- `{doc_workspace}` is the bound run folder.
|
||||
- **File roles.** `.decision-log.md` is canonical memory and audit trail — every decision, change, and override (including headless overrides) is recorded there as the conversation unfolds. `addendum.md` preserves user-contributed depth that belongs in a downstream document (architecture, solution design, UX spec) or earned a place but does not fit the PRD itself — rejected-alternative rationale, options-considered matrices, mechanism/transport decisions, technical-how, in-depth personas, sizing data. Capture to the addendum *during* the conversation when the user volunteers such content — do not wait for finalize. Audit and override information never goes in the addendum.
|
||||
|
||||
## On Activation
|
||||
|
||||
1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. On failure, read `{skill-root}/customize.toml` directly 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 (knowledge bases, MCP tools); consult them alongside generic web research on the same triggers, org tools preferred when their directive matches. Research itself fires during Discovery — see **Research subagents**.
|
||||
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 for the entire run, not just the greeting. In the greeting, let the user know that at any point they can invoke `bmad-party-mode` for multi-agent perspectives or `bmad-advanced-elicitation` for deeper exploration on a specific section. Then scan for misroute on the first message: if the signal points elsewhere (game → BMad GDS; express build → `bmad-quick-dev`; one-pager → `bmad-product-brief`; vet product idea → `bmad-prfaq`; agent skill or custom agent → `bmad-workflow-builder`), suggest they might want the other options before continuing.
|
||||
5. Detect intent: **Create** (no PRD), **Update** (existing PRD), **Validate** (critique only). If ambiguous, ask. For Create intent, before binding a fresh workspace, scan `{workflow.prd_output_path}` for prior in-progress runs (folders matching `{workflow.run_folder_pattern}` whose `prd.md` frontmatter `status` is not `final`); if any exist, offer to resume rather than starting over.
|
||||
6. Run `{workflow.activation_steps_append}`.
|
||||
|
||||
## Intent Modes
|
||||
|
||||
**Create.** Bind `{doc_workspace}` to `{workflow.prd_output_path}/{workflow.run_folder_pattern}/`. Write `prd.md` with YAML frontmatter (title, status, created, updated — initial `status: draft`), and create the `.decision-log.md` skeleton at the workspace root so subsequent decisions land in a known file. Tell the user the path. Run `## Discovery`, then `## Finalize`.
|
||||
|
||||
**Update.** Reconcile the PRD with a change signal. Source-extract against PRD, addendum, `.decision-log.md`, and original inputs (extract, don't ingest). If `.decision-log.md` is missing, spawn a one-time bootstrap subagent to reverse-engineer a thin log from the PRD before continuing. Surface conflicts with prior decisions before applying. Then `## Finalize`.
|
||||
|
||||
**Validate** (or *analyze*). Critique without changing. Load `references/validate.md`.
|
||||
|
||||
## Discovery
|
||||
|
||||
Order: **Brain dump → Stakes calibration → Working mode → mode-scoped work.** Get to working mode fast — two or three turns, not ten. Users in a hurry must not be held hostage by upstream probing.
|
||||
|
||||
**Brain dump.** Always the first move, even when the user opens with paragraphs of context (that is intake, not the dump). Ask for verbal context *and* any existing inputs they want you to read — product brief, research, customer transcripts, competitive analysis, prior PRD draft, design docs. Paths or paste; big docs are fine, you will subagent-extract. A simple "anything else?" surfaces what they almost forgot.
|
||||
|
||||
**Research subagents (default).** During Discovery, spawn web-research subagents to ground the picture: what exists in the space, how comparables position themselves, current landscape. Subagent does the search; parent receives a digest.
|
||||
|
||||
**Elicitation, not direction.** Discovery pulls the user's vision out; it does not insert yours. Open-ended "tell me about X" beats multiple choice. When you find yourself naming wedges, picking MVP cuts, or proposing phases, stop — you have crossed from elicitation into authoring. Hand the pen back. Infer-and-confirm ("I'm assuming X works like Y — right?") is fine; quizzing the user through a tree of LLM-shaped choices is not.
|
||||
|
||||
**Stakes calibration.** One short probe before working mode: hobby / internal / launch — enough to calibrate rigor and section depth. Audience, Existing inputs, and Downstream depth fill in inside the chosen mode, not upstream of the choice.
|
||||
|
||||
**Working mode.** Offer the choice in the user's language:
|
||||
|
||||
- **Fast path** — I batch remaining gaps into one or two consolidated questions, then draft the full PRD with `[ASSUMPTION]` tags where I inferred. You review and we iterate. The initial quality depends on how much you gave me upfront.
|
||||
- **Coaching path** — we walk PM-thinking sections together. Once chosen, I ask which entry point fits: **Vision + Features** (capability-first — for enterprise, dev products, internal tools, anyone who thinks in features), **Personas + Journeys** (user-first — for consumer, UX-heavy, multi-stakeholder products), or *let me suggest* based on what I heard. The chosen entry sets the section order.
|
||||
|
||||
The workspace persists; stop and resume freely.
|
||||
|
||||
**Concern scan.** As you read what the user gave you, name the concerns this product actually carries — compliance, integration density, operational SLAs, hardware constraints, public-API contracts, monetization, data governance, whatever applies. The list is open; recognize what's there, do not classify into a fixed shape. These concerns drive which template sections to pull in from the Adapt-In Menu and which to invent when no cluster names them.
|
||||
|
||||
**User Journeys are captured, not authored.** When UJs are warranted (consumer / multi-stakeholder B2B / meaningful UX — drop or downscale for internal tooling with a single operator role, regulatory-only updates, hobby/solo, pure technical PRDs), prompt the user to narrate a real session — what the person does, in what order, where it lands — then structure the answer into UJ-N form and confirm.
|
||||
|
||||
## PRD Discipline
|
||||
|
||||
**Shape.** Features grouped; FRs nested with globally numbered stable IDs. Cross-cutting NFRs in their own section; skip traceability matrices. Capabilities, not implementation — tech choices live in `addendum.md`. Treat `{workflow.prd_template}` as expert prior knowledge, not a checklist. The **Essential Spine** is the expected default — present it unless the product genuinely doesn't need a section, and when you drop one, do so for a reason a reviewer would agree with. The **Adapt-In Menu** is conditional: pull in the clusters the product's concerns need to best define the requirements. When the product carries a concern the menu doesn't name, invent the section — name it well, decide what belongs in it, place it where it serves the reader or the PRD. Reorder and combine for readability. Never include a section because it appears; never skip a concern because no template section covered it. Counter-metrics named when Success Metrics exist.
|
||||
|
||||
**Extract, don't ingest.** Source documents go to subagents for extraction; the parent assembles from extracts. Only load source documents into the parent context wholesale when no subagents are available.
|
||||
|
||||
**Length scales with stakes.** Hobby / solo PRDs aim for about two pages. Internal tools land around five to eight. Launch and chain-top PRDs run as long as their FRs and concerns require. Whatever the length, detail that doesn't earn its place in the PRD's main narrative belongs in `addendum.md` — moving overflow there is correct; padding the PRD to look thorough is not.
|
||||
|
||||
## Reviewer Gate
|
||||
|
||||
Used by the Validate intent and at Finalize step 3.
|
||||
|
||||
Assemble the menu: rubric walker against `{workflow.validation_checklist_template}` (the PRD quality rubric) + each entry in `{workflow.finalize_reviewers}` + any ad-hoc reviewers the artifact warrants. Stakes-calibrated — hobby/solo may run quietly or skip; higher stakes get the explicit all/subset/skip menu.
|
||||
|
||||
Dispatch entries as parallel subagents against `prd.md` (and `addendum.md` if present) using the standard 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. The rubric walker uses the prompt and output format in `references/validate.md`. If subagents are unavailable, run sequentially: write the file *before* anything else, then flush the review from working context.
|
||||
|
||||
Surface findings tiered, never dumped. Lead with a one-sentence gate verdict, then walk critical + high findings; medium/low roll into a single tail ("plus N more in {file}"). Read the full `review-{slug}.md` only when the user drills into a specific finding. Per finding: autofix, discuss, defer to open items, or ignore.
|
||||
|
||||
Under Validate intent, the parent additionally runs the synthesis pipeline in `references/validate.md` — folding every selected reviewer's output into a single HTML + markdown report and opening the HTML.
|
||||
|
||||
## Finalize
|
||||
|
||||
Tell the user the sequence in one sentence, then walk it. Polish goes last so it does not redo work after reviewer fixes.
|
||||
|
||||
1. **Decision log audit.** Walk `.decision-log.md` with the user; each entry captured in PRD, in addendum, or set aside.
|
||||
2. **Input reconciliation.** Subagent per user-supplied input against `prd.md` + `addendum.md`. Each writes its extract to `{doc_workspace}/reconcile-{slug}.md` and returns ONLY a compact summary (input name, gaps 2-5, file path). Surface gaps — especially qualitative ideas (tone, voice, feel) the FR structure silently drops. Must happen before polish.
|
||||
3. **Reviewer pass.** Run `## Reviewer Gate`. Resolve before polish.
|
||||
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.
|
||||
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-create-ux-design`, `bmad-create-architecture`, `bmad-create-epics-and-stories`; invoke `bmad-help` for authoritative routing.
|
||||
8. Run `{workflow.on_complete}` if non-empty.
|
||||
@@ -0,0 +1,76 @@
|
||||
# Headless Mode JSON Schemas
|
||||
|
||||
Every headless run ends with one of these payloads. Omit keys for artifacts not produced.
|
||||
|
||||
## Common fields
|
||||
|
||||
- `status` — `"complete"`, `"blocked"`, or `"partial"`
|
||||
- `intent` — `"create"`, `"update"`, or `"validate"` (matches the detected intent)
|
||||
- `reason` — required when `status` is `"blocked"`; one-sentence explanation
|
||||
- `assumptions` — array of inferred values that were not directly confirmed by inputs
|
||||
- `open_questions` — array of items that need a human decision before the artifact can be considered final
|
||||
|
||||
## Create
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "complete",
|
||||
"intent": "create",
|
||||
"prd": "{doc_workspace}/prd.md",
|
||||
"addendum": "{doc_workspace}/addendum.md",
|
||||
"decision_log": "{doc_workspace}/.decision-log.md",
|
||||
"open_questions": [],
|
||||
"assumptions": [],
|
||||
"external_handoffs": [
|
||||
{"directive": "Confluence upload", "tool": "corp:confluence_upload", "url": "https://confluence.corp/PROD/123", "status": "ok"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Update
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "complete",
|
||||
"intent": "update",
|
||||
"prd": "{doc_workspace}/prd.md",
|
||||
"decision_log": "{doc_workspace}/.decision-log.md",
|
||||
"changes_summary": "1-3 sentences describing what changed and why",
|
||||
"conflicts_with_prior_decisions": [],
|
||||
"open_questions": [],
|
||||
"external_handoffs": [
|
||||
{"directive": "Confluence upload", "tool": "corp:confluence_upload", "url": "https://confluence.corp/PROD/123", "status": "ok"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Validate
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "complete",
|
||||
"intent": "validate",
|
||||
"validation_report": "{doc_workspace}/validation-report.md",
|
||||
"findings_summary": {
|
||||
"critical": 0,
|
||||
"high": 0,
|
||||
"medium": 0,
|
||||
"low": 0
|
||||
},
|
||||
"offer_to_update": true
|
||||
}
|
||||
```
|
||||
|
||||
`validation_report` is always written for Validate intent — the path here is required, not optional.
|
||||
|
||||
## Blocked
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "blocked",
|
||||
"intent": "update",
|
||||
"reason": "Change signal ambiguous — could be a scope expansion or a clarification; no inferred direction"
|
||||
}
|
||||
```
|
||||
|
||||
Always include the intent (best-guess if not certain) and a one-sentence `reason`.
|
||||
@@ -0,0 +1,168 @@
|
||||
# PRD Template
|
||||
|
||||
## Essential Spine *(almost always present)*
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: {Product Name}
|
||||
created: {YYYY-MM-DD}
|
||||
updated: {YYYY-MM-DD}
|
||||
---
|
||||
|
||||
# PRD: {Product Name}
|
||||
*Working title — confirm.*
|
||||
|
||||
## 0. Document Purpose
|
||||
[1 paragraph: who this PRD is for (PM, stakeholders, downstream workflow owners), how it's structured (Glossary-anchored vocabulary, features grouped with FRs nested, assumptions tagged inline and indexed). If UX work or other inputs already exist, name them here and reference where they live — this PRD builds on them, it does not duplicate.]
|
||||
|
||||
## 1. Vision
|
||||
[2-3 paragraphs: what this is, what it does for the user, why it matters. Compelling enough to stand alone.]
|
||||
|
||||
## 2. Target User
|
||||
|
||||
### 2.1 Primary Persona
|
||||
[Vivid but tight. Who they are, how this product fits their context.]
|
||||
|
||||
### 2.2 Jobs To Be Done
|
||||
[Bulleted. Emotional, social, functional, contextual — whichever apply. Even "this is for me as the builder" is a valid persona for a hobby project.]
|
||||
|
||||
### 2.3 Non-Users (v1) *(add when the audience boundary is non-obvious)*
|
||||
[Who this is explicitly not for in v1.]
|
||||
|
||||
### 2.4 Key User Journeys
|
||||
*Named-persona narratives the product enables. Numbered globally as UJ-1 through UJ-N. FRs reference journeys by ID inline ("realizes UJ-3"); SMs may also cross-reference. If a UX doc already exists, mirror its UJ IDs here and point to the source.*
|
||||
|
||||
**Default shape:** a named scene with entry state, path, climax, and resolution. Each beat forces specificity the team would otherwise leave implicit — auth assumptions, screen order, what tells the user value landed. Read together as a short narrative; the example below shows the form.
|
||||
|
||||
- **UJ-1. {One-line title — persona doing the thing.}**
|
||||
- **Persona + context:** one line, grounded enough to explain the *why*.
|
||||
- **Entry state:** authenticated? which surface? coming from where?
|
||||
- **Path:** 3-5 concrete beats — taps, screens, decisions.
|
||||
- **Climax:** the moment value is delivered and how the user knows.
|
||||
- **Resolution:** state they're left in, what's next.
|
||||
- **Edge case** *(optional)*: one real failure mode and what the user does next.
|
||||
|
||||
*Written out, that becomes:*
|
||||
> **UJ-3. Priya checks the trip damage before she's even home.**
|
||||
> Priya, budgeting on a single income with a new baby, finishes a grocery run and gets in the car. Already authenticated via biometric on a previous session. She opens the app, taps the FAB camera, and scans the receipt. The app OCRs the total and shows a single-screen overlay: this trip $84.20, weekly cap $250, $172.10 remaining, three days left in the week. She closes the app and drives home. **Edge case:** if she scanned a receipt earlier today, the app asks whether this replaces or adds to that trip before counting it against the cap.
|
||||
|
||||
- **UJ-2. ...**
|
||||
|
||||
**Scope dial:**
|
||||
- **Lighter** — hobby/solo, library/CLI, or when the UJ is essentially a JTBD restated: a single sentence works (`{Persona}, {context}, {what they do and why}.`).
|
||||
- **Heavier** — auth, multi-device handoff, complex navigation, or anything feeding downstream UX/architecture: add a numbered Flow, an Edge cases list, and a capability → FR mapping (`The system must {capability}. → FR-N`).
|
||||
|
||||
## 3. Glossary
|
||||
*Downstream workflows and readers must use these terms exactly. FRs, UJs, and SMs use Glossary terms verbatim; introducing a synonym anywhere in the PRD is a discipline violation. If §4 introduces a new domain noun, add it to the Glossary in the same pass.*
|
||||
|
||||
- **Term** — Definition. Relationships to other Glossary terms. Cardinality where relevant.
|
||||
- **Term** — ...
|
||||
|
||||
[Every domain noun the rest of the document uses. Defined once. No synonyms anywhere else in the PRD.]
|
||||
|
||||
## 4. Features
|
||||
*Each subsection is a coherent feature: behavioral description first, FRs nested under it, optional feature-specific NFRs and notes. FRs are numbered globally (FR-1 through FR-N) so downstream artifacts have stable references even if features get reorganized. Reference user journeys by ID inline ("realizes UJ-2") where the chain matters.*
|
||||
|
||||
### 4.1 {Feature Name}
|
||||
**Description:** [Behavioral narrative — how this feature works, who uses it, the user experience, edge cases. Realizes UJ-X, UJ-Y. Use Glossary terms exactly. Embed inline `[ASSUMPTION: ...]` tags where you inferred without confirmation.]
|
||||
|
||||
**Functional Requirements:**
|
||||
|
||||
#### FR-1: {Short capability name}
|
||||
|
||||
[Actor] can [capability] [under conditions]. Realizes UJ-X.
|
||||
|
||||
**Consequences (testable):**
|
||||
- {Specific testable condition, e.g. "System returns HTTP 429 when request rate exceeds 100/sec per merchant."}
|
||||
- {Another testable condition.}
|
||||
|
||||
**Out of Scope:** *(optional — what this FR explicitly does NOT cover)*
|
||||
- {bound}
|
||||
|
||||
#### FR-2: ...
|
||||
|
||||
**Feature-specific NFRs:** *(only if any apply uniquely to this feature)*
|
||||
- Performance / security / accessibility / etc. specific to this feature.
|
||||
|
||||
**Notes:** *(optional — open questions specific to this feature, `[NOTE FOR PM]` callouts)*
|
||||
|
||||
### 4.2 {Feature Name}
|
||||
...
|
||||
|
||||
## 5. Non-Goals (Explicit)
|
||||
[Bulleted. What this product is *not* and what it will *not* do in v1. Does outsized work for downstream readers and workflows — prevents the "let me also add this nearby thing" failure mode at every level (epic, ticket, code). Inline `[NON-GOAL for MVP]` callouts within §4 Features cover deferred items within features; this section captures the broader "we are not building X / we are not becoming Y" statements.]
|
||||
|
||||
## 6. MVP Scope
|
||||
|
||||
### 6.1 In Scope
|
||||
[Bulleted, crisp.]
|
||||
|
||||
### 6.2 Out of Scope for MVP
|
||||
[Bulleted. Each item with a one-line reason if the reason matters. Mark items deferred to v2/v3 explicitly. Add `[NOTE FOR PM]` callouts where a deferred item is emotionally load-bearing — flags it for revisit if timeline permits.]
|
||||
|
||||
## 7. Success Metrics
|
||||
|
||||
*Each SM cross-references the FR(s) it validates. Counter-metrics counterbalance specific primary or secondary metrics.*
|
||||
|
||||
**Primary**
|
||||
- **SM-1**: Metric — definition, target. Validates FR-X, FR-Y.
|
||||
|
||||
**Secondary**
|
||||
- **SM-2**: Metric — definition, target. Validates FR-Z.
|
||||
|
||||
**Counter-metrics (do not optimize)**
|
||||
- **SM-C1**: Metric — why this should *not* be optimized. Counterbalances SM-1.
|
||||
|
||||
[Length scales with stakes. Hobby/utility PRD: a single sentence may be enough ("Success: I use this weekly and don't abandon it after a month"). Public launch / enterprise: full quantitative breakdown with measurement methods. Counter-metrics are as load-bearing as primary metrics — they prevent the architect from optimizing the wrong thing and the dev from gaming the wrong target.]
|
||||
|
||||
## 8. Open Questions
|
||||
[Numbered. Things still unknown — they become future tickets or follow-up research, not silent gaps.]
|
||||
|
||||
## 9. Assumptions Index
|
||||
*Every `[ASSUMPTION]` from the document, surfaced for explicit confirmation:*
|
||||
- Inline assumption from §X.Y — short description.
|
||||
- ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Adapt-In Menu *(add the clusters the product calls for)*
|
||||
|
||||
### Cross-cutting quality and shape *(most non-trivial PRDs)*
|
||||
- **Cross-Cutting NFRs** — system-wide non-functional requirements not tied to a single feature (performance, security, reliability, observability). Add when system-wide quality attributes are meaningful.
|
||||
- **Constraints and Guardrails** — Safety, Privacy, Cost. Subsection per cluster. Add when any of these are real concerns.
|
||||
- **Why Now** — add when timing is load-bearing (a market shift, a technology enabler, a regulatory deadline). Drop when timing is incidental.
|
||||
|
||||
### Consumer / branded products
|
||||
- **Aesthetic and Tone** — visual references, anti-references, voice/tone for any product-generated text.
|
||||
- **Information Architecture** — top-level surfaces, navigation, screens.
|
||||
- **Monetization** — free vs. paid, pricing assumptions, ads policy.
|
||||
- **Platform** — web, mobile, PWA, native, v1 vs. v2+.
|
||||
|
||||
### Enterprise initiatives
|
||||
- **Stakeholders and Approvals** — who must sign off, at what stage.
|
||||
- **Risk and Mitigations** — operational, security, business, reputational risk register.
|
||||
- **ROI / Business Case** — quantified benefit, cost, payback period.
|
||||
- **Operational Requirements** — SLAs, RTO/RPO, support tier, on-call expectations.
|
||||
- **Integration and Dependencies** — SSO, existing enterprise systems, data sources, downstream consumers.
|
||||
- **Rollout and Change Management** — phased rollout plan, training, internal communication.
|
||||
- **Data Governance** — residency, sovereignty, classification, retention.
|
||||
- **Audit Trail / Decision Provenance** — formal documentation requirements for regulated environments.
|
||||
|
||||
### Regulated domains
|
||||
- **Compliance and Regulatory** — HIPAA, PCI-DSS, GDPR, SOX, SOC 2, Section 508 / WCAG 2.1 AA, FedRAMP, etc. — whichever apply. If any item needs depth, add a `[NOTE FOR PM]` callout to revisit or move to an addendum.
|
||||
|
||||
### Developer products (libraries, APIs, CLIs, SDKs)
|
||||
- **API Contracts / Public Surface** — endpoint shapes, breaking change policy.
|
||||
- **Versioning and Deprecation Policy**.
|
||||
- **Performance Budgets** — latency, throughput, resource use.
|
||||
- **Language / Runtime Targets and Dependency Policy**.
|
||||
|
||||
### Embedded / hardware
|
||||
- **Hardware Constraints** — memory, power, form factor.
|
||||
- **Deployment and Update Mechanism** — OTA, manual, image-based.
|
||||
- **Environmental and Reliability Requirements**.
|
||||
|
||||
### Small-scope all-inclusive *(use when scope is 1-2 stories' worth and the user wants a single captured artifact — chosen during the Right-skill check in Discovery)*
|
||||
- **Stories** — story-level specs listed inline at the end of the doc. Each story: *"As a [persona], I can [action] [under conditions]. Acceptance: [testable criteria]."* Numbered Story-1, Story-2, ... for reference. Pair with very lean §1 Vision, §2 Target User (often just JTBD + one UJ), §3 Glossary (handful of terms), §4 Features (often a single feature), §6 MVP Scope (in/out very tight). The whole doc fits on a page or two and captures intent + implementable stories in one place. If the user doesn't want the captured artifact at all, `bmad-quick-dev` is the better path — this cluster is only for "I want a doc *and* the stories."
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
# PRD Quality Rubric
|
||||
|
||||
A judgment rubric for the validator subagent. Walk the PRD with these dimensions in mind and write substantive findings — not box-ticking. The goal is a review that tells the user whether this PRD is *good*, not whether it has the right section headers.
|
||||
|
||||
Most PRDs do not need every dimension scrutinized equally. Calibrate to the agreed stakes, the PRD's shape (consumer product, internal tool, regulatory update, technical capability spec), and what the PRD itself is trying to do. Be specific — cite locations, quote phrases, name what's missing. Abstract criticism is failure of nerve.
|
||||
|
||||
## How to use this rubric
|
||||
|
||||
1. Read the full PRD (and addendum.md if present) before writing anything.
|
||||
2. For each of the seven dimensions below, form a judgment — *strong / adequate / thin / broken* — backed by specifics from the PRD.
|
||||
3. Write findings only where they add information. A `strong` dimension may need no findings; a `broken` one needs concrete, fixable ones.
|
||||
4. Severity ranks impact on the PRD's usefulness, not how easy the fix is. A vague Vision statement is *critical* even though it's a one-paragraph fix; a glossary drift might be *low* even though it appears in many places.
|
||||
5. The overall verdict is your synthesis — 2–3 sentences that name what holds up and what's at risk. Earn it with the dimension judgments.
|
||||
|
||||
## Output format
|
||||
|
||||
Write findings to `{doc_workspace}/review-rubric.md`:
|
||||
|
||||
```markdown
|
||||
# PRD Quality Review — {prd_name}
|
||||
|
||||
## Overall verdict
|
||||
[2–3 sentences. What holds up, what's at risk. Earned by the dimension judgments below.]
|
||||
|
||||
## Decision-readiness — [strong | adequate | thin | broken]
|
||||
[1–3 paragraphs of judgment with specific PRD locations.]
|
||||
|
||||
### Findings
|
||||
- **[critical|high|medium|low]** [Title] (§ location) — [Note]. *Fix:* [suggested fix].
|
||||
|
||||
## Substance over theater — [verdict]
|
||||
...
|
||||
|
||||
(repeat for each dimension)
|
||||
|
||||
## Mechanical notes
|
||||
[Glossary drift, ID continuity, broken cross-refs, Assumptions Index roundtrip. Lighter weight — these matter for downstream but don't drive the overall verdict.]
|
||||
```
|
||||
|
||||
## The seven dimensions
|
||||
|
||||
### 1. Decision-readiness
|
||||
|
||||
Can a decision-maker act on this PRD? Are the trade-offs surfaced honestly, or has the PRD smoothed everything to neutral? Would someone pushing back find their objection acknowledged or dodged?
|
||||
|
||||
Look for:
|
||||
- Decisions that are stated as decisions, not buried as "considerations."
|
||||
- Trade-offs named with what was given up, not just what was chosen.
|
||||
- Open Questions that are actually open — not rhetorical questions with an answer in the next sentence.
|
||||
- `[NOTE FOR PM]` callouts at real tensions, not at safe checkpoints.
|
||||
|
||||
Red flag: a PRD where every choice "balances" everything, every NFR is "important," every persona "values" the product.
|
||||
|
||||
### 2. Substance over theater
|
||||
|
||||
Is the content earned, or is it furniture? Distinguish:
|
||||
|
||||
- **Persona theater** — Personas that don't drive a single decision in the PRD. More than four personas. Personas whose only function is to make the PRD look thorough.
|
||||
- **Innovation theater** — claimed novelty that isn't novel. Differentiation sections written because the template had one, not because Discovery surfaced something.
|
||||
- **NFR theater** — copied boilerplate ("system must be scalable / secure / reliable") without product-specific thresholds.
|
||||
- **Vision theater** — a Vision statement that could swap into any PRD in this category without change.
|
||||
|
||||
Flag what reads like furniture, even if it's well-written furniture.
|
||||
|
||||
### 3. Strategic coherence
|
||||
|
||||
Does the PRD have a thesis? Do the features serve a unified arc, or is it a list of capabilities someone wanted?
|
||||
|
||||
Look for:
|
||||
- A stated thesis the PRD bets on (problem framing, user insight, market move).
|
||||
- Feature prioritization that follows from the thesis — not from "what's easy first."
|
||||
- Success Metrics that validate the thesis, not metrics that just measure activity (DAU/MAU when the thesis is about engagement quality is a tell).
|
||||
- Counter-metrics named when SMs exist.
|
||||
- Coherent MVP scope kind — problem-solving, experience, platform, or revenue — with scope logic that matches.
|
||||
|
||||
Red flag: a PRD that reads as a backlog with section headings.
|
||||
|
||||
### 4. Done-ness clarity
|
||||
|
||||
Would an engineer reading this PRD know what "done" looks like for each FR?
|
||||
|
||||
Look for:
|
||||
- FRs with at least one testable consequence per FR — verifiable condition, measurable outcome.
|
||||
- "System handles X gracefully," "reasonable performance," "user-friendly" — flag every one.
|
||||
- Acceptance criteria implied or explicit. Sometimes the FR's consequences carry this; sometimes the PRD genuinely needs an Acceptance section.
|
||||
- For non-functional sections (UX, performance, security): bounds, not adjectives.
|
||||
|
||||
This is the dimension downstream story creation will lean on hardest. Be unforgiving here.
|
||||
|
||||
### 5. Scope honesty
|
||||
|
||||
Are omissions explicit, or is the reader meant to infer them?
|
||||
|
||||
Look for:
|
||||
- A Non-Goals section where it would do real work — and `[NON-GOAL for MVP]` callouts where omissions could be silently assumed.
|
||||
- `[ASSUMPTION: …]` tags on inferences the user didn't directly confirm, indexed at the end.
|
||||
- `[NOTE FOR PM]` callouts at deferred decisions and unresolved tensions.
|
||||
- De-scoping proposed honestly, not done silently.
|
||||
|
||||
Open-items density: count Open Questions + `[ASSUMPTION]` + `[NOTE FOR PM]` callouts relative to stakes. High counts on a low-stakes PRD is fine; high counts on a green-light-to-build PRD is a blocker.
|
||||
|
||||
### 6. Downstream usability
|
||||
|
||||
If this PRD feeds UX, architecture, or story creation, can those workflows source-extract from it cleanly?
|
||||
|
||||
Look for:
|
||||
- Glossary present; every domain noun used identically across FRs, UJs, SM definitions.
|
||||
- FR / UJ / SM IDs contiguous, unique, and cross-references that resolve.
|
||||
- Each section makes sense pulled out alone — cross-references via Glossary terms, not "see above."
|
||||
- UJs each name a persona from §2 by exact label; no floating UJs.
|
||||
|
||||
For standalone PRDs (no downstream), this dimension matters less — say so.
|
||||
|
||||
### 7. Shape fit
|
||||
|
||||
Has the PRD been forced into a shape that doesn't match the product?
|
||||
|
||||
- Consumer product / multi-stakeholder B2B / meaningful UX → UJs and personas are load-bearing.
|
||||
- Internal tool, single-operator role → capability spec shape; UJs may be overhead; SMs may be operational rather than user-facing.
|
||||
- Regulatory or compliance update → constraint traceability is non-negotiable; UJs may be irrelevant.
|
||||
- Hobby / solo → rigor light, substance bar still applies.
|
||||
- Brownfield → existing-code references must be accurate; new UJs and existing UJs must be distinguished.
|
||||
- Chain-top (feeds UX → architecture → stories) → downstream usability matters more; standalone PRDs can be lighter on traceability.
|
||||
|
||||
Flag PRDs that are over-formalized (UJ density for a single-operator tool) or under-formalized (consumer product with no personas or UJs).
|
||||
|
||||
## Mechanical notes
|
||||
|
||||
Cover these as a tail section, not a primary dimension. They matter for downstream but don't drive the verdict on whether the PRD is good.
|
||||
|
||||
- Glossary drift (case, plural, synonyms across the PRD).
|
||||
- ID continuity (gaps, duplicates, unresolved cross-references).
|
||||
- Assumptions Index roundtrip (every inline `[ASSUMPTION]` indexed; index entries all appear inline).
|
||||
- UJ persona linkage (each UJ names a defined persona by exact label).
|
||||
- Required sections present for the agreed stakes and product type.
|
||||
@@ -0,0 +1,325 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
PRD Validation Report — skeleton template.
|
||||
|
||||
This file is a starter the synthesis pass fills in directly. There is no
|
||||
substitution engine. The LLM:
|
||||
1. Reads {doc_workspace}/review-rubric.md and every review-{slug}.md from
|
||||
additional reviewers.
|
||||
2. Copies this skeleton.
|
||||
3. Replaces the placeholder content (everything between TEMPLATE markers)
|
||||
with the consolidated review, preserving the structure and CSS.
|
||||
4. Writes the result to {doc_workspace}/validation-report.html.
|
||||
5. Writes a markdown twin to {doc_workspace}/validation-report.md.
|
||||
|
||||
Visual rules the LLM must preserve:
|
||||
- The container width, the color tokens, the typography.
|
||||
- One dimension = one collapsible <section class="dimension">.
|
||||
- Verdict pill uses the verdict-* class matching its judgment.
|
||||
- Severity badge uses the sev-* class matching its level.
|
||||
- Each extra reviewer (adversarial, etc.) gets its own collapsible section
|
||||
below the rubric dimensions.
|
||||
- The footer always shows the artifact paths and timestamp.
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>PRD Validation: TEMPLATE_PRD_NAME</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #fafaf9;
|
||||
--surface: #ffffff;
|
||||
--border: #e7e5e4;
|
||||
--text: #1c1917;
|
||||
--muted: #78716c;
|
||||
|
||||
--verdict-strong: #16a34a;
|
||||
--verdict-adequate: #65a30d;
|
||||
--verdict-thin: #d97706;
|
||||
--verdict-broken: #dc2626;
|
||||
|
||||
--sev-low: #64748b;
|
||||
--sev-medium: #ca8a04;
|
||||
--sev-high: #ea580c;
|
||||
--sev-critical: #dc2626;
|
||||
|
||||
--grade-exc: #16a34a;
|
||||
--grade-good: #65a30d;
|
||||
--grade-fair: #d97706;
|
||||
--grade-poor: #dc2626;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
font-size: 15px;
|
||||
}
|
||||
.container { max-width: 960px; margin: 0 auto; padding: 32px 24px 64px; }
|
||||
|
||||
header.report-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.title h1 { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
|
||||
.title .subtitle { color: var(--muted); font-size: 13px; margin-top: 4px; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
|
||||
.grade {
|
||||
padding: 10px 18px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.grade-excellent { background: var(--grade-exc); }
|
||||
.grade-good { background: var(--grade-good); }
|
||||
.grade-fair { background: var(--grade-fair); }
|
||||
.grade-poor { background: var(--grade-poor); }
|
||||
|
||||
.synthesis {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-left: 3px solid var(--muted);
|
||||
border-radius: 8px;
|
||||
padding: 18px 22px;
|
||||
margin-bottom: 24px;
|
||||
font-size: 15.5px;
|
||||
}
|
||||
.synthesis p { margin: 0 0 10px; }
|
||||
.synthesis p:last-child { margin-bottom: 0; }
|
||||
|
||||
.dimension-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 10px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.dim-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 12px 14px;
|
||||
}
|
||||
.dim-card .dim-name { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
|
||||
.dim-card .dim-verdict { font-size: 14px; font-weight: 600; }
|
||||
|
||||
section.dimension, section.reviewer-section { margin-bottom: 14px; }
|
||||
section.dimension details, section.reviewer-section details {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
section summary {
|
||||
padding: 14px 20px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
section summary::-webkit-details-marker { display: none; }
|
||||
section summary::before {
|
||||
content: "▸";
|
||||
display: inline-block;
|
||||
color: var(--muted);
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
section details[open] summary::before { transform: rotate(90deg); }
|
||||
section summary h2 {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.005em;
|
||||
flex: 1;
|
||||
}
|
||||
.verdict-pill {
|
||||
font-size: 11px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 999px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: white;
|
||||
}
|
||||
.verdict-strong { background: var(--verdict-strong); }
|
||||
.verdict-adequate { background: var(--verdict-adequate); }
|
||||
.verdict-thin { background: var(--verdict-thin); }
|
||||
.verdict-broken { background: var(--verdict-broken); }
|
||||
|
||||
.dim-body { padding: 4px 20px 18px; }
|
||||
.dim-judgment { color: var(--text); font-size: 14.5px; }
|
||||
.dim-judgment p { margin: 0 0 10px; }
|
||||
|
||||
.findings-list { padding: 0 20px 4px; }
|
||||
article.finding {
|
||||
padding: 14px 0;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
article.finding:first-child { border-top: none; }
|
||||
article.finding header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.badge {
|
||||
font-size: 10.5px;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.badge-sev-low { background: rgba(100, 116, 139, 0.12); color: var(--sev-low); }
|
||||
.badge-sev-medium { background: rgba(202, 138, 4, 0.14); color: var(--sev-medium); }
|
||||
.badge-sev-high { background: rgba(234, 88, 12, 0.14); color: var(--sev-high); }
|
||||
.badge-sev-critical { background: rgba(220, 38, 38, 0.14); color: var(--sev-critical); }
|
||||
.finding-title { margin: 0; font-size: 15px; font-weight: 500; flex: 1; min-width: 200px; }
|
||||
.finding-location { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12.5px; color: var(--muted); }
|
||||
.finding-note, .finding-fix { margin-top: 6px; font-size: 14px; }
|
||||
.finding-fix strong { color: var(--muted); font-weight: 500; }
|
||||
|
||||
.reviewer-source {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
||||
}
|
||||
|
||||
.mechanical {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 16px 20px;
|
||||
margin-top: 24px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.mechanical h3 { margin: 0 0 10px; font-size: 14px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
|
||||
.mechanical ul { margin: 0; padding-left: 20px; }
|
||||
.mechanical li { margin-bottom: 4px; color: var(--text); }
|
||||
|
||||
footer.report-footer {
|
||||
margin-top: 40px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--border);
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
||||
}
|
||||
footer .meta { display: flex; gap: 24px; flex-wrap: wrap; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<!-- TEMPLATE: header. Fill prd name, prd path, grade text & class. -->
|
||||
<header class="report-header">
|
||||
<div class="title">
|
||||
<h1>TEMPLATE_PRD_NAME — Validation Report</h1>
|
||||
<div class="subtitle">TEMPLATE_PRD_PATH</div>
|
||||
</div>
|
||||
<div class="grade TEMPLATE_GRADE_CLASS">TEMPLATE_GRADE</div>
|
||||
</header>
|
||||
|
||||
<!-- TEMPLATE: overall synthesis paragraphs. Lift directly from
|
||||
review-rubric.md "Overall verdict" section; expand if extra reviewers
|
||||
materially shift the picture. Wrap each paragraph in <p>. -->
|
||||
<div class="synthesis">
|
||||
<p>TEMPLATE_SYNTHESIS_PARAGRAPH</p>
|
||||
</div>
|
||||
|
||||
<!-- TEMPLATE: dimension summary cards. One per rubric dimension. The
|
||||
dim-verdict text uses one of: strong | adequate | thin | broken. -->
|
||||
<div class="dimension-summary">
|
||||
<div class="dim-card">
|
||||
<div class="dim-name">Decision-readiness</div>
|
||||
<div class="dim-verdict" style="color: var(--verdict-TEMPLATE_VERDICT)">TEMPLATE_VERDICT_TEXT</div>
|
||||
</div>
|
||||
<!-- repeat for each of the seven dimensions -->
|
||||
</div>
|
||||
|
||||
<!-- TEMPLATE: one section per rubric dimension. Skip a dimension entirely
|
||||
if the rubric review marked it n/a for this PRD (e.g. downstream
|
||||
usability for a standalone PRD). Open the section by default if
|
||||
verdict is thin or broken. -->
|
||||
<section class="dimension">
|
||||
<details open>
|
||||
<summary>
|
||||
<h2>Decision-readiness</h2>
|
||||
<span class="verdict-pill verdict-TEMPLATE_VERDICT">TEMPLATE_VERDICT_TEXT</span>
|
||||
</summary>
|
||||
<div class="dim-body">
|
||||
<div class="dim-judgment">
|
||||
<p>TEMPLATE_DIMENSION_JUDGMENT</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="findings-list">
|
||||
<!-- TEMPLATE: zero or more findings -->
|
||||
<article class="finding">
|
||||
<header>
|
||||
<span class="badge badge-sev-TEMPLATE_SEVERITY">TEMPLATE_SEVERITY</span>
|
||||
<h3 class="finding-title">TEMPLATE_FINDING_TITLE</h3>
|
||||
<span class="finding-location">TEMPLATE_LOCATION</span>
|
||||
</header>
|
||||
<div class="finding-note">TEMPLATE_FINDING_NOTE</div>
|
||||
<div class="finding-fix"><strong>Fix:</strong> TEMPLATE_SUGGESTED_FIX</div>
|
||||
</article>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<!-- TEMPLATE: one section per extra reviewer that ran (adversarial, etc.).
|
||||
Skip this block entirely if only the rubric walker ran. -->
|
||||
<section class="reviewer-section">
|
||||
<details>
|
||||
<summary>
|
||||
<h2>Adversarial review</h2>
|
||||
<span class="reviewer-source">TEMPLATE_REVIEWER_SOURCE_FILE</span>
|
||||
</summary>
|
||||
<div class="dim-body">
|
||||
<div class="dim-judgment">
|
||||
<p>TEMPLATE_REVIEWER_PREAMBLE</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="findings-list">
|
||||
<article class="finding">
|
||||
<header>
|
||||
<span class="badge badge-sev-TEMPLATE_SEVERITY">TEMPLATE_SEVERITY</span>
|
||||
<h3 class="finding-title">TEMPLATE_FINDING_TITLE</h3>
|
||||
<span class="finding-location">TEMPLATE_LOCATION</span>
|
||||
</header>
|
||||
<div class="finding-note">TEMPLATE_FINDING_NOTE</div>
|
||||
<div class="finding-fix"><strong>Fix:</strong> TEMPLATE_SUGGESTED_FIX</div>
|
||||
</article>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<!-- TEMPLATE: mechanical notes — short, bulleted. Skip if there are none. -->
|
||||
<div class="mechanical">
|
||||
<h3>Mechanical notes</h3>
|
||||
<ul>
|
||||
<li>TEMPLATE_MECHANICAL_NOTE</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<footer class="report-footer">
|
||||
<div class="meta">
|
||||
<span>Rubric: TEMPLATE_RUBRIC_PATH</span>
|
||||
<span>Generated: TEMPLATE_TIMESTAMP</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,147 @@
|
||||
# DO NOT EDIT -- overwritten on every update.
|
||||
#
|
||||
# Workflow customization surface for bmad-prd.
|
||||
#
|
||||
# Override files (not edited here):
|
||||
# {project-root}/_bmad/custom/bmad-prd.toml (team)
|
||||
# {project-root}/_bmad/custom/bmad-prd.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, compliance 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
|
||||
# (standards, compliance constraints, stylistic 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 has produced one — this gives
|
||||
# the facilitator persistent awareness of the project's tech, domain, and constraints without
|
||||
# re-asking. Common opt-ins (set in team/user override TOML):
|
||||
# "skill:acme-co:terms-and-conditions" # a skill that contains some relevant info
|
||||
# "Investor PRDs must include a market sizing section." # generic agent instruction
|
||||
persistent_facts = [
|
||||
"file:{project-root}/**/project-context.md",
|
||||
]
|
||||
|
||||
# Executed when the workflow completes (after the user has been told the
|
||||
# PRD is ready). Accepts either a string scalar (single instruction)
|
||||
# or an array of instructions executed in order. Empty for none.
|
||||
on_complete = ""
|
||||
|
||||
# Default PRD structure. Treated as a starting point — the LLM adapts it
|
||||
# to the product, project type, and domain. Override the path in team/user TOML
|
||||
# to enforce a different structure (e.g. regulated-industry, internal-tool, investor-input).
|
||||
prd_template = "assets/prd-template.md"
|
||||
|
||||
# PRD quality rubric used at the Validate intent and at Finalize step 3.
|
||||
# A subagent walks the rubric against prd.md and writes a substantive review
|
||||
# organized by quality dimensions (decision-readiness, substance, strategic
|
||||
# coherence, etc.). Override the path in team/user TOML to enforce an
|
||||
# org-specific rubric (regulated-industry compliance, investor-pitch standards,
|
||||
# etc.). The filename "checklist" is retained for back-compat with override
|
||||
# files; the content is a judgment rubric, not a boolean checklist.
|
||||
validation_checklist_template = "assets/prd-validation-checklist.md"
|
||||
|
||||
# HTML skeleton the synthesis pass fills directly when consolidating reviewer
|
||||
# outputs into a validation report. No substitution engine — the parent LLM
|
||||
# reads every {doc_workspace}/review-*.md, fills the skeleton's TEMPLATE_*
|
||||
# placeholders, and writes the result. Fully overridable to match org branding.
|
||||
# Uses inline CSS, no external dependencies, and native HTML <details> for
|
||||
# collapse — no JS.
|
||||
validation_report_template = "assets/validation-report-template.html"
|
||||
|
||||
# Run folder location. The PRD, optional addendum, decision log, and optional
|
||||
# validation report all land inside `{prd_output_path}/{run_folder_pattern}/`.
|
||||
# Resume-check scans `{prd_output_path}` for prior unfinished runs.
|
||||
prd_output_path = "{planning_artifacts}/prds"
|
||||
run_folder_pattern = "prd-{project_name}-{date}"
|
||||
|
||||
# Document standards applied to human-consumed docs at finalize. Each entry is
|
||||
# a `skill:`, `file:`, or plain-text directive; the parent LLM applies the
|
||||
# findings before the user sees the draft. Encodes standards, not options.
|
||||
#
|
||||
# Examples:
|
||||
# "skill:bmad-editorial-review-prose"
|
||||
# "file:{project-root}/_bmad/style-guides/company-voice.md"
|
||||
# "Convert all dates to ISO 8601 format."
|
||||
#
|
||||
# Suggested order (broader passes first, narrower last):
|
||||
# 1. Structural (cuts, reorganization, section sizing)
|
||||
# 2. Content/voice/conventions (org standards, tone, terminology, compliance)
|
||||
# 3. Prose mechanics (grammar, clarity, typos)
|
||||
#
|
||||
# Override the array in team/user TOML to add additional standards. Append-only:
|
||||
# base entries cannot be removed or replaced (resolver has no removal mechanism).
|
||||
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 during the workflow
|
||||
# when a relevant need surfaces. The LLM does NOT query these preemptively —
|
||||
# it consults them on demand (during Discovery, validation, drafting, etc.).
|
||||
# Each entry names the tool, the conditions for using it, and any fields the
|
||||
# tool needs. If a named MCP tool is unavailable at runtime, the LLM falls
|
||||
# back to standard behavior and notes the gap. Empty by default.
|
||||
#
|
||||
# Lifecycle note: distinct from persistent_facts. persistent_facts are loaded
|
||||
# once at activation and kept in mind for the whole run; external_sources are
|
||||
# a registry consulted on demand and only when the conversation surfaces a
|
||||
# matching need.
|
||||
#
|
||||
# Examples (set in team/user override TOML):
|
||||
# "When researching internal product context, consult corp:kb_search (database='product-docs') before web search."
|
||||
# "For competitive landscape during Discovery, query corp:competitive_db with category={project_name}."
|
||||
# "When validating domain-compliance claims, cross-check against corp:hipaa_reference for healthcare or corp:pci_reference for fintech."
|
||||
external_sources = []
|
||||
|
||||
# External-handoff routing. Natural-language directives the LLM applies at
|
||||
# Finalize to route outputs beyond local files (Confluence, Notion, Google
|
||||
# Drive, ticket systems, etc.). Each entry names the MCP tool, the destination,
|
||||
# and the fields the tool needs. Handoffs run after the artifact is polished
|
||||
# and before the final user-facing message. URLs or IDs returned by the
|
||||
# destination are captured and surfaced to the user. If a named tool is
|
||||
# unavailable at runtime, the handoff is skipped and flagged in the JSON
|
||||
# status; local files always exist regardless. Fires automatically — users
|
||||
# can opt out in their prompt for a specific run. Empty by default.
|
||||
#
|
||||
# Lifecycle note: distinct from persistent_facts and external_sources.
|
||||
# Fired once at Finalize step 6, never during Discovery or drafting.
|
||||
#
|
||||
# Examples (set in team/user override TOML):
|
||||
# "After finalize, upload prd.md and addendum.md to Confluence via corp:confluence_upload (space_key='PROD', parent_page='PRDs', label='prd', author={user_name})."
|
||||
# "Mirror the PRD to Notion via notion:create_page (database_id='abc123', title='PRD: '+{project_name})."
|
||||
# "When the PRD references a parent initiative, link via corp:jira_link on the epic key in frontmatter."
|
||||
external_handoffs = []
|
||||
|
||||
# --- Finalize reviewers ---
|
||||
# Reviewers spawned at Finalize step 3 (and at the Validate intent) alongside
|
||||
# the structural checklist validator. The authoring skill assembles the gate
|
||||
# menu (validator + these reviewers + any ad-hoc reviewers it judges warranted
|
||||
# by the artifact content) and lets the user pick all, a subset, or skip. Gate
|
||||
# UX is stakes-calibrated: hobby/solo scope may run defaults quietly or skip;
|
||||
# higher stakes get the explicit menu.
|
||||
#
|
||||
# Entries follow the standard prefix convention (same as persistent_facts and
|
||||
# doc_standards):
|
||||
# "skill:NAME" invoke the named review skill as a subagent against prd.md
|
||||
# "file:PATH" load the file as a review prompt; spawn an adversarial
|
||||
# subagent applying that prompt to prd.md
|
||||
# plain text use the text directly as the subagent's review prompt
|
||||
#
|
||||
# Override TOML may append additional reviewers. Arrays append per BMad rules.
|
||||
#
|
||||
# Resolved on-demand by the authoring skill (not pulled at activation): only
|
||||
# when entering the Validate intent or assembling the gate at Finalize step 3.
|
||||
finalize_reviewers = []
|
||||
@@ -0,0 +1,39 @@
|
||||
# Headless Mode
|
||||
|
||||
Load this file when bmad-prd is invoked headless (no interactive user). Follow it for the whole run.
|
||||
|
||||
## Detection
|
||||
|
||||
Headless mode is in effect when any of the following is true:
|
||||
|
||||
- the invoking caller sets a `headless: true` flag (or equivalent argument the harness exposes),
|
||||
- the invocation is from another skill or a non-interactive runner (no TTY, no user message stream),
|
||||
- `{workflow.activation_steps_prepend}` includes an entry that explicitly declares headless,
|
||||
- the first message comes from an automation context that pre-supplies all inputs and asks for an artifact path back.
|
||||
|
||||
When ambiguous, default to interactive.
|
||||
|
||||
## Inputs the caller is expected to provide
|
||||
|
||||
The caller passes inputs in their first message (free-form structured payload; no fixed schema, but every field below should be present when applicable):
|
||||
|
||||
- `intent` — `"create"`, `"update"`, or `"validate"`. If absent, infer from the artifact set.
|
||||
- For **Create**: a brief or product spec the LLM works from (plain text, file path, or URL), plus any persona/scope notes; `doc_workspace` if a specific run folder is required (otherwise the workflow binds the default).
|
||||
- For **Update**: the existing `prd.md` path (or a workspace path that contains one), and a change signal (the request: what to change and why).
|
||||
- For **Validate**: the existing `prd.md` path (or workspace path), and optionally a checklist override path. Workspace defaults to the PRD's containing directory.
|
||||
|
||||
Anything the caller does not provide is either inferred from inputs/workspace or recorded as `assumptions[]` / `open_questions[]` in the JSON status. Do not invent persona detail, success metrics, or scope decisions to fill gaps — record them.
|
||||
|
||||
## General
|
||||
|
||||
Do not ask. Complete the intent using what is provided, what exists in `{doc_workspace}`, or what you can discover yourself. If intent remains ambiguous after inference, halt with `status: "blocked"` and a `reason` field — do not prompt. Do not greet.
|
||||
|
||||
Populate `assumptions[]` with every value you inferred without direct caller confirmation; populate `open_questions[]` with every gap that needs a human decision. Use `status: "partial"` when the artifact was produced but `open_questions[]` is non-empty or critical inputs were inferred (Create with no brief; Update with a vague signal acted on best-effort; Validate that could not load the checklist). `complete` = stands on its own; `partial` = caller should review before downstream use; `blocked` = no artifact produced.
|
||||
|
||||
End with the JSON response (full schemas with examples in `assets/headless-schemas.md`). The `intent` field must match the detected intent. Omit keys for artifacts not produced.
|
||||
|
||||
## Mode-specific overrides
|
||||
|
||||
**Update.** Apply the change, log to `.decision-log.md` with rationale, and surface any conflict-with-prior-decision in `conflicts_with_prior_decisions[]` in the JSON status. Halt `blocked` if intent is ambiguous.
|
||||
|
||||
**Validate.** Always write both `validation-report.html` and `validation-report.md` to `{doc_workspace}` regardless of finding count. Always include `"offer_to_update": true` in the JSON status. Skip the browser-open step in `references/validate.md` — write the artifacts and return.
|
||||
@@ -0,0 +1,97 @@
|
||||
# Validate
|
||||
|
||||
The Validate intent playbook. Standalone — this intent critiques an existing PRD without changing it and ends after the user has seen the report; it does not run Finalize. The synthesis pipeline below is also reused for mid-session report requests during Create/Update.
|
||||
|
||||
## Orient
|
||||
|
||||
Source-extract against `.decision-log.md`, any original inputs, and the PRD/addendum themselves. Delegate to subagents per PRD Discipline → "Extract, don't ingest" (in SKILL.md); the parent assembles from extracts.
|
||||
|
||||
## Run the Reviewer Gate
|
||||
|
||||
Run the Reviewer Gate (see SKILL.md) against `prd.md` (and `addendum.md` if present). The rubric walker is the default entry in the gate menu; under Validate intent it additionally runs the synthesis pipeline below. The Finalize discipline pass during Create/Update does NOT render a report — findings stay in-conversation.
|
||||
|
||||
## Rubric-walker pipeline
|
||||
|
||||
The rubric walker is the primary review entry. Spawn it as a subagent with this prompt:
|
||||
|
||||
> You are validating a PRD against the quality rubric at `{workflow.validation_checklist_template}`. Read the full rubric first, then read `prd.md` (and `addendum.md` if present). Form a judgment per dimension — *strong / adequate / thin / broken* — and write findings only where they add information. Cite specific PRD locations and quote phrases. Severity ranks impact on the PRD's usefulness, not how easy the fix is. Write your review to `{doc_workspace}/review-rubric.md` in the format the rubric specifies. Return ONLY a compact summary (overall verdict, dimension verdicts, finding counts by severity, file path).
|
||||
|
||||
The Reviewer Gate may also dispatch additional reviewers from `{workflow.finalize_reviewers}` (adversarial-general by default) and any ad-hoc reviewers the parent judges warranted. Each writes its review to `{doc_workspace}/review-{slug}.md` and returns a compact summary. Run in parallel.
|
||||
|
||||
## Synthesis pipeline
|
||||
|
||||
Once every selected reviewer has returned, the parent synthesizes one consolidated report. **Do not skip this step under Validate intent** — it produces the persistent artifact the user opens.
|
||||
|
||||
### Inputs
|
||||
|
||||
- `{doc_workspace}/review-rubric.md` — primary, structured by the seven dimensions
|
||||
- Zero or more `{doc_workspace}/review-{slug}.md` files — extra reviewers (adversarial, etc.)
|
||||
- `{workflow.validation_report_template}` — the HTML skeleton
|
||||
|
||||
### What the synthesis pass does
|
||||
|
||||
1. Read every reviewer file in `{doc_workspace}/review-*.md`.
|
||||
2. Fill the HTML skeleton:
|
||||
- **Header.** PRD name, path. Grade derived from the rubric verdicts and severity counts: *Excellent* = all dimensions strong/adequate, no high/critical findings · *Good* = ≤1 thin dimension, no critical findings · *Fair* = multiple thin dimensions or any high finding · *Poor* = any broken dimension or any critical finding. Set the matching `grade-excellent | grade-good | grade-fair | grade-poor` class.
|
||||
- **Synthesis block.** Lift the rubric's *Overall verdict* paragraph as the lead; if adversarial or ad-hoc reviewers materially shift the picture, add a second paragraph that names what they surfaced.
|
||||
- **Dimension summary cards.** One per dimension that was assessed. Colored verdict text. Skip dimensions the rubric marked n/a for this PRD (e.g. downstream usability for a standalone PRD).
|
||||
- **Dimension sections.** One `<section class="dimension">` per assessed dimension, in rubric order. `<details open>` for *thin* and *broken*; closed for *strong* and *adequate*. Each contains the dimension judgment (the prose from review-rubric.md) and the findings list.
|
||||
- **Reviewer sections.** One `<section class="reviewer-section">` per extra reviewer that ran. The source file path goes in the `<span class="reviewer-source">`. Closed by default. Adversarial findings keep their adversarial voice — do not soften.
|
||||
- **Mechanical notes.** Bullet list from the rubric's "Mechanical notes" section. Skip the block if empty.
|
||||
- **Footer.** Rubric path, ISO timestamp.
|
||||
3. Write the filled HTML to `{doc_workspace}/validation-report.html`.
|
||||
4. Write the markdown twin to `{doc_workspace}/validation-report.md` (same content, grouped by severity rather than by dimension — see format below; this is the canonical form for downstream re-reading).
|
||||
5. Open the HTML in the default browser:
|
||||
```bash
|
||||
python3 -c "import webbrowser, pathlib; webbrowser.open(pathlib.Path('{doc_workspace}/validation-report.html').resolve().as_uri())"
|
||||
```
|
||||
Skip the open step in headless mode (see `references/headless.md`).
|
||||
|
||||
### Markdown twin format
|
||||
|
||||
```markdown
|
||||
# Validation Report — {prd_name}
|
||||
|
||||
- **PRD:** `{prd_path}`
|
||||
- **Rubric:** `{rubric_path}`
|
||||
- **Run at:** {ISO timestamp}
|
||||
- **Grade:** {Excellent | Good | Fair | Poor}
|
||||
|
||||
## Overall verdict
|
||||
{synthesis paragraphs}
|
||||
|
||||
## Dimension verdicts
|
||||
- Decision-readiness — {verdict}
|
||||
- Substance over theater — {verdict}
|
||||
- (etc. for each assessed dimension)
|
||||
|
||||
## Findings by severity
|
||||
|
||||
### Critical (n)
|
||||
**[Dimension or Reviewer]** — Title (§ location)
|
||||
{Note}
|
||||
Fix: {suggested fix}
|
||||
|
||||
### High (n)
|
||||
...
|
||||
|
||||
### Medium (n)
|
||||
...
|
||||
|
||||
### Low (n)
|
||||
...
|
||||
|
||||
## Mechanical notes
|
||||
- {bullet}
|
||||
|
||||
## Reviewer files
|
||||
- `review-rubric.md`
|
||||
- `review-adversarial-general.md` (if present)
|
||||
- (etc.)
|
||||
```
|
||||
|
||||
Re-running validation overwrites the consolidated report in place. The individual `review-*.md` files are preserved so the user can drill in.
|
||||
|
||||
## Close
|
||||
|
||||
Surface artifact paths; the rendered HTML/markdown is the persistent artifact. Always offer to roll findings into an Update.
|
||||
Reference in New Issue
Block a user