bmad-method 6.6.1-next.9 → 6.7.1-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{tools/installer/modules/registry-fallback.yaml → bmad-modules.yaml} +29 -15
- package/package.json +1 -1
- package/src/bmm-skills/1-analysis/bmad-product-brief/SKILL.md +18 -11
- package/src/bmm-skills/1-analysis/bmad-product-brief/customize.toml +13 -8
- package/src/bmm-skills/2-plan-workflows/bmad-prd/SKILL.md +54 -57
- package/src/bmm-skills/2-plan-workflows/bmad-prd/assets/headless-schemas.md +2 -2
- package/src/bmm-skills/2-plan-workflows/bmad-prd/assets/prd-template.md +40 -30
- package/src/bmm-skills/2-plan-workflows/bmad-prd/assets/prd-validation-checklist.md +126 -21
- package/src/bmm-skills/2-plan-workflows/bmad-prd/assets/validation-report-template.html +193 -58
- package/src/bmm-skills/2-plan-workflows/bmad-prd/customize.toml +47 -13
- package/src/bmm-skills/2-plan-workflows/bmad-prd/references/headless.md +27 -12
- package/src/bmm-skills/2-plan-workflows/bmad-prd/references/validate.md +97 -0
- package/src/bmm-skills/module.yaml +2 -2
- package/src/core-skills/module.yaml +1 -1
- package/tools/installer/core/installer.js +101 -45
- package/tools/installer/core/manifest.js +0 -22
- package/tools/installer/ide/_config-driven.js +2 -2
- package/tools/installer/modules/channel-plan.js +1 -1
- package/tools/installer/modules/external-manager.js +9 -27
- package/tools/installer/modules/official-modules.js +9 -48
- package/tools/installer/ui.js +63 -196
- package/src/bmm-skills/2-plan-workflows/bmad-prd/references/facilitation-guide.md +0 -79
- package/src/bmm-skills/2-plan-workflows/bmad-prd/references/validation-render.md +0 -58
- package/src/bmm-skills/2-plan-workflows/bmad-prd/scripts/render-validation-html.py +0 -290
- package/tools/installer/modules/community-manager.js +0 -704
- package/tools/installer/modules/registry-client.js +0 -187
|
@@ -1,30 +1,135 @@
|
|
|
1
|
-
# PRD
|
|
1
|
+
# PRD Quality Rubric
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
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.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
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.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Q-2. Measurability.** Where measurement matters, FRs and Success Metrics are measurable; subjective adjectives flagged. Counter-metrics named when Success Metrics exist.
|
|
9
|
-
- **Q-3. Traceability.** Where the chain matters, FRs name their link to a user journey or success criterion inline.
|
|
10
|
-
- **Q-4. Vision and JTBDs concrete.** Vision is specific and stands alone — not a generic feature list. JTBDs are audience-grounded, not abstract.
|
|
11
|
-
- **Q-5. Non-Goals explicit.** A Non-Goals section is present where it would do real work; inline `[NON-GOAL]` and `[v2]` callouts where omissions would otherwise be silently assumed.
|
|
12
|
-
- **Q-6. Dual-audience and self-contained.** Each section makes sense pulled out alone (cross-references via Glossary terms, not "see above"); the PRD is readable by humans and structured cleanly for downstream source-extraction by UX, architecture, and story-creation workflows.
|
|
7
|
+
## How to use this rubric
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
1. Read the full PRD (and addendum.md if present) before writing anything.
|
|
10
|
+
2. For each of the seven dimensions below, form a judgment — *strong / adequate / thin / broken* — backed by specifics from the PRD.
|
|
11
|
+
3. Write findings only where they add information. A `strong` dimension may need no findings; a `broken` one needs concrete, fixable ones.
|
|
12
|
+
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.
|
|
13
|
+
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.
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
- **D-2. Input fidelity.** Requirements from input documents (brief, research, prior PRD) are still in scope or explicitly handled via Non-Goals or `[ASSUMPTION]`.
|
|
18
|
-
- **D-3. Personas grounded.** If personas exist, they are research-grounded or marked `[ILLUSTRATIVE]`. Each persona drives at least one decision.
|
|
19
|
-
- **D-4. No innovation theater.** Novelty claims are real, not invented.
|
|
15
|
+
## Output format
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
Write findings to `{doc_workspace}/review-rubric.md`:
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- **S-3. Assumptions Index.** Every inline `[ASSUMPTION: ...]` appears in the Assumptions Index and vice versa.
|
|
26
|
-
- **S-4. Open-items density.** Count Open Questions + `[ASSUMPTION]` + `[NOTE FOR PM]`. Red flag if density is high relative to the agreed stakes.
|
|
19
|
+
```markdown
|
|
20
|
+
# PRD Quality Review — {prd_name}
|
|
27
21
|
|
|
28
|
-
##
|
|
22
|
+
## Overall verdict
|
|
23
|
+
[2–3 sentences. What holds up, what's at risk. Earned by the dimension judgments below.]
|
|
29
24
|
|
|
30
|
-
|
|
25
|
+
## Decision-readiness — [strong | adequate | thin | broken]
|
|
26
|
+
[1–3 paragraphs of judgment with specific PRD locations.]
|
|
27
|
+
|
|
28
|
+
### Findings
|
|
29
|
+
- **[critical|high|medium|low]** [Title] (§ location) — [Note]. *Fix:* [suggested fix].
|
|
30
|
+
|
|
31
|
+
## Substance over theater — [verdict]
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
(repeat for each dimension)
|
|
35
|
+
|
|
36
|
+
## Mechanical notes
|
|
37
|
+
[Glossary drift, ID continuity, broken cross-refs, Assumptions Index roundtrip. Lighter weight — these matter for downstream but don't drive the overall verdict.]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## The seven dimensions
|
|
41
|
+
|
|
42
|
+
### 1. Decision-readiness
|
|
43
|
+
|
|
44
|
+
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?
|
|
45
|
+
|
|
46
|
+
Look for:
|
|
47
|
+
- Decisions that are stated as decisions, not buried as "considerations."
|
|
48
|
+
- Trade-offs named with what was given up, not just what was chosen.
|
|
49
|
+
- Open Questions that are actually open — not rhetorical questions with an answer in the next sentence.
|
|
50
|
+
- `[NOTE FOR PM]` callouts at real tensions, not at safe checkpoints.
|
|
51
|
+
|
|
52
|
+
Red flag: a PRD where every choice "balances" everything, every NFR is "important," every persona "values" the product.
|
|
53
|
+
|
|
54
|
+
### 2. Substance over theater
|
|
55
|
+
|
|
56
|
+
Is the content earned, or is it furniture? Distinguish:
|
|
57
|
+
|
|
58
|
+
- **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.
|
|
59
|
+
- **Innovation theater** — claimed novelty that isn't novel. Differentiation sections written because the template had one, not because Discovery surfaced something.
|
|
60
|
+
- **NFR theater** — copied boilerplate ("system must be scalable / secure / reliable") without product-specific thresholds.
|
|
61
|
+
- **Vision theater** — a Vision statement that could swap into any PRD in this category without change.
|
|
62
|
+
|
|
63
|
+
Flag what reads like furniture, even if it's well-written furniture.
|
|
64
|
+
|
|
65
|
+
### 3. Strategic coherence
|
|
66
|
+
|
|
67
|
+
Does the PRD have a thesis? Do the features serve a unified arc, or is it a list of capabilities someone wanted?
|
|
68
|
+
|
|
69
|
+
Look for:
|
|
70
|
+
- A stated thesis the PRD bets on (problem framing, user insight, market move).
|
|
71
|
+
- Feature prioritization that follows from the thesis — not from "what's easy first."
|
|
72
|
+
- Success Metrics that validate the thesis, not metrics that just measure activity (DAU/MAU when the thesis is about engagement quality is a tell).
|
|
73
|
+
- Counter-metrics named when SMs exist.
|
|
74
|
+
- Coherent MVP scope kind — problem-solving, experience, platform, or revenue — with scope logic that matches.
|
|
75
|
+
|
|
76
|
+
Red flag: a PRD that reads as a backlog with section headings.
|
|
77
|
+
|
|
78
|
+
### 4. Done-ness clarity
|
|
79
|
+
|
|
80
|
+
Would an engineer reading this PRD know what "done" looks like for each FR?
|
|
81
|
+
|
|
82
|
+
Look for:
|
|
83
|
+
- FRs with at least one testable consequence per FR — verifiable condition, measurable outcome.
|
|
84
|
+
- "System handles X gracefully," "reasonable performance," "user-friendly" — flag every one.
|
|
85
|
+
- Acceptance criteria implied or explicit. Sometimes the FR's consequences carry this; sometimes the PRD genuinely needs an Acceptance section.
|
|
86
|
+
- For non-functional sections (UX, performance, security): bounds, not adjectives.
|
|
87
|
+
|
|
88
|
+
This is the dimension downstream story creation will lean on hardest. Be unforgiving here.
|
|
89
|
+
|
|
90
|
+
### 5. Scope honesty
|
|
91
|
+
|
|
92
|
+
Are omissions explicit, or is the reader meant to infer them?
|
|
93
|
+
|
|
94
|
+
Look for:
|
|
95
|
+
- A Non-Goals section where it would do real work — and `[NON-GOAL for MVP]` callouts where omissions could be silently assumed.
|
|
96
|
+
- `[ASSUMPTION: …]` tags on inferences the user didn't directly confirm, indexed at the end.
|
|
97
|
+
- `[NOTE FOR PM]` callouts at deferred decisions and unresolved tensions.
|
|
98
|
+
- De-scoping proposed honestly, not done silently.
|
|
99
|
+
|
|
100
|
+
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.
|
|
101
|
+
|
|
102
|
+
### 6. Downstream usability
|
|
103
|
+
|
|
104
|
+
If this PRD feeds UX, architecture, or story creation, can those workflows source-extract from it cleanly?
|
|
105
|
+
|
|
106
|
+
Look for:
|
|
107
|
+
- Glossary present; every domain noun used identically across FRs, UJs, SM definitions.
|
|
108
|
+
- FR / UJ / SM IDs contiguous, unique, and cross-references that resolve.
|
|
109
|
+
- Each section makes sense pulled out alone — cross-references via Glossary terms, not "see above."
|
|
110
|
+
- UJs each name a persona from §2 by exact label; no floating UJs.
|
|
111
|
+
|
|
112
|
+
For standalone PRDs (no downstream), this dimension matters less — say so.
|
|
113
|
+
|
|
114
|
+
### 7. Shape fit
|
|
115
|
+
|
|
116
|
+
Has the PRD been forced into a shape that doesn't match the product?
|
|
117
|
+
|
|
118
|
+
- Consumer product / multi-stakeholder B2B / meaningful UX → UJs and personas are load-bearing.
|
|
119
|
+
- Internal tool, single-operator role → capability spec shape; UJs may be overhead; SMs may be operational rather than user-facing.
|
|
120
|
+
- Regulatory or compliance update → constraint traceability is non-negotiable; UJs may be irrelevant.
|
|
121
|
+
- Hobby / solo → rigor light, substance bar still applies.
|
|
122
|
+
- Brownfield → existing-code references must be accurate; new UJs and existing UJs must be distinguished.
|
|
123
|
+
- Chain-top (feeds UX → architecture → stories) → downstream usability matters more; standalone PRDs can be lighter on traceability.
|
|
124
|
+
|
|
125
|
+
Flag PRDs that are over-formalized (UJ density for a single-operator tool) or under-formalized (consumer product with no personas or UJs).
|
|
126
|
+
|
|
127
|
+
## Mechanical notes
|
|
128
|
+
|
|
129
|
+
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.
|
|
130
|
+
|
|
131
|
+
- Glossary drift (case, plural, synonyms across the PRD).
|
|
132
|
+
- ID continuity (gaps, duplicates, unresolved cross-references).
|
|
133
|
+
- Assumptions Index roundtrip (every inline `[ASSUMPTION]` indexed; index entries all appear inline).
|
|
134
|
+
- UJ persona linkage (each UJ names a defined persona by exact label).
|
|
135
|
+
- Required sections present for the agreed stakes and product type.
|
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
+
<!--
|
|
3
|
+
PRD Validation Report — skeleton template.
|
|
4
|
+
|
|
5
|
+
This file is a starter the synthesis pass fills in directly. There is no
|
|
6
|
+
substitution engine. The LLM:
|
|
7
|
+
1. Reads {doc_workspace}/review-rubric.md and every review-{slug}.md from
|
|
8
|
+
additional reviewers.
|
|
9
|
+
2. Copies this skeleton.
|
|
10
|
+
3. Replaces the placeholder content (everything between TEMPLATE markers)
|
|
11
|
+
with the consolidated review, preserving the structure and CSS.
|
|
12
|
+
4. Writes the result to {doc_workspace}/validation-report.html.
|
|
13
|
+
5. Writes a markdown twin to {doc_workspace}/validation-report.md.
|
|
14
|
+
|
|
15
|
+
Visual rules the LLM must preserve:
|
|
16
|
+
- The container width, the color tokens, the typography.
|
|
17
|
+
- One dimension = one collapsible <section class="dimension">.
|
|
18
|
+
- Verdict pill uses the verdict-* class matching its judgment.
|
|
19
|
+
- Severity badge uses the sev-* class matching its level.
|
|
20
|
+
- Each extra reviewer (adversarial, etc.) gets its own collapsible section
|
|
21
|
+
below the rubric dimensions.
|
|
22
|
+
- The footer always shows the artifact paths and timestamp.
|
|
23
|
+
-->
|
|
2
24
|
<html lang="en">
|
|
3
25
|
<head>
|
|
4
26
|
<meta charset="utf-8">
|
|
5
|
-
<title>PRD Validation:
|
|
27
|
+
<title>PRD Validation: TEMPLATE_PRD_NAME</title>
|
|
6
28
|
<style>
|
|
7
29
|
:root {
|
|
8
30
|
--bg: #fafaf9;
|
|
@@ -10,14 +32,17 @@
|
|
|
10
32
|
--border: #e7e5e4;
|
|
11
33
|
--text: #1c1917;
|
|
12
34
|
--muted: #78716c;
|
|
13
|
-
|
|
14
|
-
--
|
|
15
|
-
--
|
|
16
|
-
--
|
|
35
|
+
|
|
36
|
+
--verdict-strong: #16a34a;
|
|
37
|
+
--verdict-adequate: #65a30d;
|
|
38
|
+
--verdict-thin: #d97706;
|
|
39
|
+
--verdict-broken: #dc2626;
|
|
40
|
+
|
|
17
41
|
--sev-low: #64748b;
|
|
18
42
|
--sev-medium: #ca8a04;
|
|
19
43
|
--sev-high: #ea580c;
|
|
20
44
|
--sev-critical: #dc2626;
|
|
45
|
+
|
|
21
46
|
--grade-exc: #16a34a;
|
|
22
47
|
--grade-good: #65a30d;
|
|
23
48
|
--grade-fair: #d97706;
|
|
@@ -29,14 +54,14 @@
|
|
|
29
54
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
|
|
30
55
|
background: var(--bg);
|
|
31
56
|
color: var(--text);
|
|
32
|
-
line-height: 1.
|
|
57
|
+
line-height: 1.6;
|
|
33
58
|
font-size: 15px;
|
|
34
59
|
}
|
|
35
60
|
.container { max-width: 960px; margin: 0 auto; padding: 32px 24px 64px; }
|
|
36
61
|
|
|
37
62
|
header.report-header {
|
|
38
63
|
display: flex;
|
|
39
|
-
align-items:
|
|
64
|
+
align-items: flex-start;
|
|
40
65
|
justify-content: space-between;
|
|
41
66
|
gap: 24px;
|
|
42
67
|
padding-bottom: 16px;
|
|
@@ -63,63 +88,90 @@
|
|
|
63
88
|
border: 1px solid var(--border);
|
|
64
89
|
border-left: 3px solid var(--muted);
|
|
65
90
|
border-radius: 8px;
|
|
66
|
-
padding:
|
|
91
|
+
padding: 18px 22px;
|
|
67
92
|
margin-bottom: 24px;
|
|
68
|
-
|
|
69
|
-
font-size: 15px;
|
|
93
|
+
font-size: 15.5px;
|
|
70
94
|
}
|
|
71
|
-
.synthesis
|
|
95
|
+
.synthesis p { margin: 0 0 10px; }
|
|
96
|
+
.synthesis p:last-child { margin-bottom: 0; }
|
|
72
97
|
|
|
73
|
-
.
|
|
98
|
+
.dimension-summary {
|
|
99
|
+
display: grid;
|
|
100
|
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
101
|
+
gap: 10px;
|
|
102
|
+
margin-bottom: 24px;
|
|
103
|
+
}
|
|
104
|
+
.dim-card {
|
|
74
105
|
background: var(--surface);
|
|
75
106
|
border: 1px solid var(--border);
|
|
76
107
|
border-radius: 8px;
|
|
77
|
-
padding:
|
|
78
|
-
margin-bottom: 24px;
|
|
108
|
+
padding: 12px 14px;
|
|
79
109
|
}
|
|
80
|
-
.
|
|
81
|
-
.
|
|
82
|
-
|
|
83
|
-
.
|
|
84
|
-
.
|
|
85
|
-
.dot-warn { background: var(--warn); }
|
|
86
|
-
.dot-fail { background: var(--fail); }
|
|
87
|
-
.dot-na { background: var(--na); }
|
|
88
|
-
.total-count { margin-left: auto; color: var(--muted); }
|
|
89
|
-
|
|
90
|
-
section.category { margin-bottom: 16px; }
|
|
91
|
-
section.category details {
|
|
110
|
+
.dim-card .dim-name { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
|
|
111
|
+
.dim-card .dim-verdict { font-size: 14px; font-weight: 600; }
|
|
112
|
+
|
|
113
|
+
section.dimension, section.reviewer-section { margin-bottom: 14px; }
|
|
114
|
+
section.dimension details, section.reviewer-section details {
|
|
92
115
|
background: var(--surface);
|
|
93
116
|
border: 1px solid var(--border);
|
|
94
117
|
border-radius: 8px;
|
|
95
118
|
overflow: hidden;
|
|
96
119
|
}
|
|
97
|
-
section
|
|
120
|
+
section summary {
|
|
98
121
|
padding: 14px 20px;
|
|
99
122
|
cursor: pointer;
|
|
100
123
|
user-select: none;
|
|
101
124
|
list-style: none;
|
|
125
|
+
display: flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
gap: 12px;
|
|
102
128
|
}
|
|
103
|
-
section
|
|
104
|
-
section
|
|
129
|
+
section summary::-webkit-details-marker { display: none; }
|
|
130
|
+
section summary::before {
|
|
105
131
|
content: "▸";
|
|
106
132
|
display: inline-block;
|
|
107
|
-
margin-right: 10px;
|
|
108
133
|
color: var(--muted);
|
|
109
134
|
transition: transform 0.15s ease;
|
|
110
135
|
}
|
|
111
|
-
section
|
|
112
|
-
section
|
|
113
|
-
|
|
136
|
+
section details[open] summary::before { transform: rotate(90deg); }
|
|
137
|
+
section summary h2 {
|
|
138
|
+
display: inline;
|
|
139
|
+
margin: 0;
|
|
140
|
+
font-size: 16px;
|
|
141
|
+
font-weight: 600;
|
|
142
|
+
letter-spacing: -0.005em;
|
|
143
|
+
flex: 1;
|
|
144
|
+
}
|
|
145
|
+
.verdict-pill {
|
|
146
|
+
font-size: 11px;
|
|
147
|
+
padding: 3px 10px;
|
|
148
|
+
border-radius: 999px;
|
|
149
|
+
font-weight: 600;
|
|
150
|
+
text-transform: uppercase;
|
|
151
|
+
letter-spacing: 0.04em;
|
|
152
|
+
color: white;
|
|
153
|
+
}
|
|
154
|
+
.verdict-strong { background: var(--verdict-strong); }
|
|
155
|
+
.verdict-adequate { background: var(--verdict-adequate); }
|
|
156
|
+
.verdict-thin { background: var(--verdict-thin); }
|
|
157
|
+
.verdict-broken { background: var(--verdict-broken); }
|
|
158
|
+
|
|
159
|
+
.dim-body { padding: 4px 20px 18px; }
|
|
160
|
+
.dim-judgment { color: var(--text); font-size: 14.5px; }
|
|
161
|
+
.dim-judgment p { margin: 0 0 10px; }
|
|
114
162
|
|
|
115
|
-
|
|
116
|
-
article.finding
|
|
163
|
+
.findings-list { padding: 0 20px 4px; }
|
|
164
|
+
article.finding {
|
|
165
|
+
padding: 14px 0;
|
|
166
|
+
border-top: 1px solid var(--border);
|
|
167
|
+
}
|
|
168
|
+
article.finding:first-child { border-top: none; }
|
|
117
169
|
article.finding header {
|
|
118
170
|
display: flex;
|
|
119
171
|
align-items: center;
|
|
120
172
|
gap: 10px;
|
|
121
173
|
flex-wrap: wrap;
|
|
122
|
-
margin-bottom:
|
|
174
|
+
margin-bottom: 6px;
|
|
123
175
|
}
|
|
124
176
|
.badge {
|
|
125
177
|
font-size: 10.5px;
|
|
@@ -130,18 +182,32 @@
|
|
|
130
182
|
letter-spacing: 0.04em;
|
|
131
183
|
line-height: 1.4;
|
|
132
184
|
}
|
|
133
|
-
.badge-pass { background: rgba(34, 197, 94, 0.12); color: #15803d; }
|
|
134
|
-
.badge-warn { background: rgba(234, 179, 8, 0.14); color: #854d0e; }
|
|
135
|
-
.badge-fail { background: rgba(239, 68, 68, 0.12); color: #b91c1c; }
|
|
136
|
-
.badge-na { background: rgba(148, 163, 184, 0.16); color: #475569; }
|
|
137
185
|
.badge-sev-low { background: rgba(100, 116, 139, 0.12); color: var(--sev-low); }
|
|
138
186
|
.badge-sev-medium { background: rgba(202, 138, 4, 0.14); color: var(--sev-medium); }
|
|
139
187
|
.badge-sev-high { background: rgba(234, 88, 12, 0.14); color: var(--sev-high); }
|
|
140
188
|
.badge-sev-critical { background: rgba(220, 38, 38, 0.14); color: var(--sev-critical); }
|
|
141
|
-
.finding-id { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12px; color: var(--muted); }
|
|
142
189
|
.finding-title { margin: 0; font-size: 15px; font-weight: 500; flex: 1; min-width: 200px; }
|
|
143
|
-
.finding-location
|
|
144
|
-
.finding-
|
|
190
|
+
.finding-location { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12.5px; color: var(--muted); }
|
|
191
|
+
.finding-note, .finding-fix { margin-top: 6px; font-size: 14px; }
|
|
192
|
+
.finding-fix strong { color: var(--muted); font-weight: 500; }
|
|
193
|
+
|
|
194
|
+
.reviewer-source {
|
|
195
|
+
font-size: 12px;
|
|
196
|
+
color: var(--muted);
|
|
197
|
+
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.mechanical {
|
|
201
|
+
background: var(--surface);
|
|
202
|
+
border: 1px solid var(--border);
|
|
203
|
+
border-radius: 8px;
|
|
204
|
+
padding: 16px 20px;
|
|
205
|
+
margin-top: 24px;
|
|
206
|
+
font-size: 14px;
|
|
207
|
+
}
|
|
208
|
+
.mechanical h3 { margin: 0 0 10px; font-size: 14px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
209
|
+
.mechanical ul { margin: 0; padding-left: 20px; }
|
|
210
|
+
.mechanical li { margin-bottom: 4px; color: var(--text); }
|
|
145
211
|
|
|
146
212
|
footer.report-footer {
|
|
147
213
|
margin-top: 40px;
|
|
@@ -156,33 +222,102 @@
|
|
|
156
222
|
</head>
|
|
157
223
|
<body>
|
|
158
224
|
<div class="container">
|
|
225
|
+
|
|
226
|
+
<!-- TEMPLATE: header. Fill prd name, prd path, grade text & class. -->
|
|
159
227
|
<header class="report-header">
|
|
160
228
|
<div class="title">
|
|
161
|
-
<h1
|
|
162
|
-
<div class="subtitle"
|
|
229
|
+
<h1>TEMPLATE_PRD_NAME — Validation Report</h1>
|
|
230
|
+
<div class="subtitle">TEMPLATE_PRD_PATH</div>
|
|
163
231
|
</div>
|
|
164
|
-
<div class="grade
|
|
232
|
+
<div class="grade TEMPLATE_GRADE_CLASS">TEMPLATE_GRADE</div>
|
|
165
233
|
</header>
|
|
166
234
|
|
|
167
|
-
|
|
235
|
+
<!-- TEMPLATE: overall synthesis paragraphs. Lift directly from
|
|
236
|
+
review-rubric.md "Overall verdict" section; expand if extra reviewers
|
|
237
|
+
materially shift the picture. Wrap each paragraph in <p>. -->
|
|
238
|
+
<div class="synthesis">
|
|
239
|
+
<p>TEMPLATE_SYNTHESIS_PARAGRAPH</p>
|
|
240
|
+
</div>
|
|
168
241
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
<
|
|
174
|
-
<
|
|
175
|
-
<span><span class="dot dot-na"></span>$na n/a</span>
|
|
176
|
-
<span class="total-count">$total items checked</span>
|
|
242
|
+
<!-- TEMPLATE: dimension summary cards. One per rubric dimension. The
|
|
243
|
+
dim-verdict text uses one of: strong | adequate | thin | broken. -->
|
|
244
|
+
<div class="dimension-summary">
|
|
245
|
+
<div class="dim-card">
|
|
246
|
+
<div class="dim-name">Decision-readiness</div>
|
|
247
|
+
<div class="dim-verdict" style="color: var(--verdict-TEMPLATE_VERDICT)">TEMPLATE_VERDICT_TEXT</div>
|
|
177
248
|
</div>
|
|
249
|
+
<!-- repeat for each of the seven dimensions -->
|
|
178
250
|
</div>
|
|
179
251
|
|
|
180
|
-
|
|
252
|
+
<!-- TEMPLATE: one section per rubric dimension. Skip a dimension entirely
|
|
253
|
+
if the rubric review marked it n/a for this PRD (e.g. downstream
|
|
254
|
+
usability for a standalone PRD). Open the section by default if
|
|
255
|
+
verdict is thin or broken. -->
|
|
256
|
+
<section class="dimension">
|
|
257
|
+
<details open>
|
|
258
|
+
<summary>
|
|
259
|
+
<h2>Decision-readiness</h2>
|
|
260
|
+
<span class="verdict-pill verdict-TEMPLATE_VERDICT">TEMPLATE_VERDICT_TEXT</span>
|
|
261
|
+
</summary>
|
|
262
|
+
<div class="dim-body">
|
|
263
|
+
<div class="dim-judgment">
|
|
264
|
+
<p>TEMPLATE_DIMENSION_JUDGMENT</p>
|
|
265
|
+
</div>
|
|
266
|
+
</div>
|
|
267
|
+
<div class="findings-list">
|
|
268
|
+
<!-- TEMPLATE: zero or more findings -->
|
|
269
|
+
<article class="finding">
|
|
270
|
+
<header>
|
|
271
|
+
<span class="badge badge-sev-TEMPLATE_SEVERITY">TEMPLATE_SEVERITY</span>
|
|
272
|
+
<h3 class="finding-title">TEMPLATE_FINDING_TITLE</h3>
|
|
273
|
+
<span class="finding-location">TEMPLATE_LOCATION</span>
|
|
274
|
+
</header>
|
|
275
|
+
<div class="finding-note">TEMPLATE_FINDING_NOTE</div>
|
|
276
|
+
<div class="finding-fix"><strong>Fix:</strong> TEMPLATE_SUGGESTED_FIX</div>
|
|
277
|
+
</article>
|
|
278
|
+
</div>
|
|
279
|
+
</details>
|
|
280
|
+
</section>
|
|
281
|
+
|
|
282
|
+
<!-- TEMPLATE: one section per extra reviewer that ran (adversarial, etc.).
|
|
283
|
+
Skip this block entirely if only the rubric walker ran. -->
|
|
284
|
+
<section class="reviewer-section">
|
|
285
|
+
<details>
|
|
286
|
+
<summary>
|
|
287
|
+
<h2>Adversarial review</h2>
|
|
288
|
+
<span class="reviewer-source">TEMPLATE_REVIEWER_SOURCE_FILE</span>
|
|
289
|
+
</summary>
|
|
290
|
+
<div class="dim-body">
|
|
291
|
+
<div class="dim-judgment">
|
|
292
|
+
<p>TEMPLATE_REVIEWER_PREAMBLE</p>
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
<div class="findings-list">
|
|
296
|
+
<article class="finding">
|
|
297
|
+
<header>
|
|
298
|
+
<span class="badge badge-sev-TEMPLATE_SEVERITY">TEMPLATE_SEVERITY</span>
|
|
299
|
+
<h3 class="finding-title">TEMPLATE_FINDING_TITLE</h3>
|
|
300
|
+
<span class="finding-location">TEMPLATE_LOCATION</span>
|
|
301
|
+
</header>
|
|
302
|
+
<div class="finding-note">TEMPLATE_FINDING_NOTE</div>
|
|
303
|
+
<div class="finding-fix"><strong>Fix:</strong> TEMPLATE_SUGGESTED_FIX</div>
|
|
304
|
+
</article>
|
|
305
|
+
</div>
|
|
306
|
+
</details>
|
|
307
|
+
</section>
|
|
308
|
+
|
|
309
|
+
<!-- TEMPLATE: mechanical notes — short, bulleted. Skip if there are none. -->
|
|
310
|
+
<div class="mechanical">
|
|
311
|
+
<h3>Mechanical notes</h3>
|
|
312
|
+
<ul>
|
|
313
|
+
<li>TEMPLATE_MECHANICAL_NOTE</li>
|
|
314
|
+
</ul>
|
|
315
|
+
</div>
|
|
181
316
|
|
|
182
317
|
<footer class="report-footer">
|
|
183
318
|
<div class="meta">
|
|
184
|
-
<span>
|
|
185
|
-
<span>Generated:
|
|
319
|
+
<span>Rubric: TEMPLATE_RUBRIC_PATH</span>
|
|
320
|
+
<span>Generated: TEMPLATE_TIMESTAMP</span>
|
|
186
321
|
</div>
|
|
187
322
|
</footer>
|
|
188
323
|
</div>
|
|
@@ -43,23 +43,28 @@ on_complete = ""
|
|
|
43
43
|
# to enforce a different structure (e.g. regulated-industry, internal-tool, investor-input).
|
|
44
44
|
prd_template = "assets/prd-template.md"
|
|
45
45
|
|
|
46
|
-
#
|
|
47
|
-
# A subagent walks the
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
|
|
46
|
+
# PRD quality rubric used at the Validate intent and at Finalize step 3.
|
|
47
|
+
# A subagent walks the rubric against prd.md and writes a substantive review
|
|
48
|
+
# organized by quality dimensions (decision-readiness, substance, strategic
|
|
49
|
+
# coherence, etc.). Override the path in team/user TOML to enforce an
|
|
50
|
+
# org-specific rubric (regulated-industry compliance, investor-pitch standards,
|
|
51
|
+
# etc.). The filename "checklist" is retained for back-compat with override
|
|
52
|
+
# files; the content is a judgment rubric, not a boolean checklist.
|
|
53
|
+
validation_checklist_template = "assets/prd-validation-checklist.md"
|
|
51
54
|
|
|
52
|
-
# HTML
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
# external dependencies, and native HTML <details> for
|
|
55
|
+
# HTML skeleton the synthesis pass fills directly when consolidating reviewer
|
|
56
|
+
# outputs into a validation report. No substitution engine — the parent LLM
|
|
57
|
+
# reads every {doc_workspace}/review-*.md, fills the skeleton's TEMPLATE_*
|
|
58
|
+
# placeholders, and writes the result. Fully overridable to match org branding.
|
|
59
|
+
# Uses inline CSS, no external dependencies, and native HTML <details> for
|
|
60
|
+
# collapse — no JS.
|
|
57
61
|
validation_report_template = "assets/validation-report-template.html"
|
|
58
62
|
|
|
59
63
|
# Run folder location. The PRD, optional addendum, decision log, and optional
|
|
60
|
-
# validation report all land inside `{
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
# validation report all land inside `{prd_output_path}/{run_folder_pattern}/`.
|
|
65
|
+
# Resume-check scans `{prd_output_path}` for prior unfinished runs.
|
|
66
|
+
prd_output_path = "{planning_artifacts}/prds"
|
|
67
|
+
run_folder_pattern = "prd-{project_name}-{date}"
|
|
63
68
|
|
|
64
69
|
# Document standards applied to human-consumed docs at finalize. Each entry is
|
|
65
70
|
# a `skill:`, `file:`, or plain-text directive; the parent LLM applies the
|
|
@@ -90,6 +95,11 @@ doc_standards = [
|
|
|
90
95
|
# tool needs. If a named MCP tool is unavailable at runtime, the LLM falls
|
|
91
96
|
# back to standard behavior and notes the gap. Empty by default.
|
|
92
97
|
#
|
|
98
|
+
# Lifecycle note: distinct from persistent_facts. persistent_facts are loaded
|
|
99
|
+
# once at activation and kept in mind for the whole run; external_sources are
|
|
100
|
+
# a registry consulted on demand and only when the conversation surfaces a
|
|
101
|
+
# matching need.
|
|
102
|
+
#
|
|
93
103
|
# Examples (set in team/user override TOML):
|
|
94
104
|
# "When researching internal product context, consult corp:kb_search (database='product-docs') before web search."
|
|
95
105
|
# "For competitive landscape during Discovery, query corp:competitive_db with category={project_name}."
|
|
@@ -106,8 +116,32 @@ external_sources = []
|
|
|
106
116
|
# status; local files always exist regardless. Fires automatically — users
|
|
107
117
|
# can opt out in their prompt for a specific run. Empty by default.
|
|
108
118
|
#
|
|
119
|
+
# Lifecycle note: distinct from persistent_facts and external_sources.
|
|
120
|
+
# Fired once at Finalize step 6, never during Discovery or drafting.
|
|
121
|
+
#
|
|
109
122
|
# Examples (set in team/user override TOML):
|
|
110
123
|
# "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})."
|
|
111
124
|
# "Mirror the PRD to Notion via notion:create_page (database_id='abc123', title='PRD: '+{project_name})."
|
|
112
125
|
# "When the PRD references a parent initiative, link via corp:jira_link on the epic key in frontmatter."
|
|
113
126
|
external_handoffs = []
|
|
127
|
+
|
|
128
|
+
# --- Finalize reviewers ---
|
|
129
|
+
# Reviewers spawned at Finalize step 3 (and at the Validate intent) alongside
|
|
130
|
+
# the structural checklist validator. The authoring skill assembles the gate
|
|
131
|
+
# menu (validator + these reviewers + any ad-hoc reviewers it judges warranted
|
|
132
|
+
# by the artifact content) and lets the user pick all, a subset, or skip. Gate
|
|
133
|
+
# UX is stakes-calibrated: hobby/solo scope may run defaults quietly or skip;
|
|
134
|
+
# higher stakes get the explicit menu.
|
|
135
|
+
#
|
|
136
|
+
# Entries follow the standard prefix convention (same as persistent_facts and
|
|
137
|
+
# doc_standards):
|
|
138
|
+
# "skill:NAME" invoke the named review skill as a subagent against prd.md
|
|
139
|
+
# "file:PATH" load the file as a review prompt; spawn an adversarial
|
|
140
|
+
# subagent applying that prompt to prd.md
|
|
141
|
+
# plain text use the text directly as the subagent's review prompt
|
|
142
|
+
#
|
|
143
|
+
# Override TOML may append additional reviewers. Arrays append per BMad rules.
|
|
144
|
+
#
|
|
145
|
+
# Resolved on-demand by the authoring skill (not pulled at activation): only
|
|
146
|
+
# when entering the Validate intent or assembling the gate at Finalize step 3.
|
|
147
|
+
finalize_reviewers = []
|
|
@@ -2,23 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
Load this file when bmad-prd is invoked headless (no interactive user). Follow it for the whole run.
|
|
4
4
|
|
|
5
|
+
## Detection
|
|
6
|
+
|
|
7
|
+
Headless mode is in effect when any of the following is true:
|
|
8
|
+
|
|
9
|
+
- the invoking caller sets a `headless: true` flag (or equivalent argument the harness exposes),
|
|
10
|
+
- the invocation is from another skill or a non-interactive runner (no TTY, no user message stream),
|
|
11
|
+
- `{workflow.activation_steps_prepend}` includes an entry that explicitly declares headless,
|
|
12
|
+
- the first message comes from an automation context that pre-supplies all inputs and asks for an artifact path back.
|
|
13
|
+
|
|
14
|
+
When ambiguous, default to interactive.
|
|
15
|
+
|
|
16
|
+
## Inputs the caller is expected to provide
|
|
17
|
+
|
|
18
|
+
The caller passes inputs in their first message (free-form structured payload; no fixed schema, but every field below should be present when applicable):
|
|
19
|
+
|
|
20
|
+
- `intent` — `"create"`, `"update"`, or `"validate"`. If absent, infer from the artifact set.
|
|
21
|
+
- 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).
|
|
22
|
+
- 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).
|
|
23
|
+
- For **Validate**: the existing `prd.md` path (or workspace path), and optionally a checklist override path. Workspace defaults to the PRD's containing directory.
|
|
24
|
+
|
|
25
|
+
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.
|
|
26
|
+
|
|
5
27
|
## General
|
|
6
28
|
|
|
7
|
-
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
|
|
29
|
+
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.
|
|
8
30
|
|
|
9
|
-
|
|
31
|
+
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.
|
|
10
32
|
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
"status": "complete",
|
|
14
|
-
"intent": "validate",
|
|
15
|
-
"validation_report": "{doc_workspace}/validation-report.md",
|
|
16
|
-
"offer_to_update": true
|
|
17
|
-
}
|
|
18
|
-
```
|
|
33
|
+
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.
|
|
19
34
|
|
|
20
35
|
## Mode-specific overrides
|
|
21
36
|
|
|
22
|
-
**Update.**
|
|
37
|
+
**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.
|
|
23
38
|
|
|
24
|
-
**Validate.** Always write `validation-report.md` to `{doc_workspace}` regardless of finding count. Always include `"offer_to_update": true` in the JSON status
|
|
39
|
+
**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.
|