@hegemonart/get-design-done 1.28.0 → 1.28.6

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.
Files changed (98) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +134 -0
  4. package/SKILL.md +1 -1
  5. package/hooks/gdd-decision-injector.js +149 -3
  6. package/package.json +1 -1
  7. package/reference/adr-format.md +96 -0
  8. package/reference/architecture-vocabulary.md +102 -0
  9. package/reference/context-md-format.md +106 -0
  10. package/reference/heuristics.md +84 -0
  11. package/reference/registry.json +29 -1
  12. package/reference/registry.schema.json +1 -1
  13. package/reference/shared-preamble.md +78 -6
  14. package/reference/skill-authoring-contract.md +159 -0
  15. package/scripts/validate-skill-length.cjs +283 -0
  16. package/skills/add-backlog/SKILL.md +1 -0
  17. package/skills/analyze-dependencies/SKILL.md +33 -122
  18. package/skills/apply-reflections/SKILL.md +1 -40
  19. package/skills/apply-reflections/apply-reflections-procedure.md +68 -0
  20. package/skills/audit/SKILL.md +3 -1
  21. package/skills/bandit-status/SKILL.md +31 -66
  22. package/skills/benchmark/SKILL.md +15 -55
  23. package/skills/brief/SKILL.md +12 -1
  24. package/skills/cache-manager/SKILL.md +3 -57
  25. package/skills/cache-manager/cache-policy.md +126 -0
  26. package/skills/check-update/SKILL.md +38 -75
  27. package/skills/compare/SKILL.md +29 -269
  28. package/skills/compare/compare-rubric.md +171 -0
  29. package/skills/complete-cycle/SKILL.md +1 -1
  30. package/skills/connections/SKILL.md +21 -427
  31. package/skills/connections/connections-onboarding.md +417 -0
  32. package/skills/continue/SKILL.md +1 -0
  33. package/skills/darkmode/SKILL.md +32 -287
  34. package/skills/darkmode/darkmode-audit-procedure.md +258 -0
  35. package/skills/debug/SKILL.md +11 -8
  36. package/skills/debug/debug-feedback-loops.md +119 -0
  37. package/skills/design/SKILL.md +27 -245
  38. package/skills/design/design-procedure.md +304 -0
  39. package/skills/discover/SKILL.md +26 -133
  40. package/skills/discover/discover-procedure.md +204 -0
  41. package/skills/discuss/SKILL.md +18 -2
  42. package/skills/explore/SKILL.md +40 -205
  43. package/skills/explore/explore-procedure.md +267 -0
  44. package/skills/fast/SKILL.md +1 -0
  45. package/skills/figma-write/SKILL.md +2 -2
  46. package/skills/health/SKILL.md +11 -33
  47. package/skills/health/health-mcp-detection.md +44 -0
  48. package/skills/health/health-skill-length-report.md +69 -0
  49. package/skills/help/SKILL.md +1 -0
  50. package/skills/list-assumptions/SKILL.md +1 -0
  51. package/skills/map/SKILL.md +8 -31
  52. package/skills/new-cycle/SKILL.md +3 -1
  53. package/skills/new-cycle/milestone-completeness-rubric.md +87 -0
  54. package/skills/next/SKILL.md +1 -0
  55. package/skills/note/SKILL.md +1 -0
  56. package/skills/optimize/SKILL.md +21 -44
  57. package/skills/pause/SKILL.md +1 -0
  58. package/skills/peer-cli-add/SKILL.md +26 -108
  59. package/skills/peer-cli-add/peer-cli-protocol.md +161 -0
  60. package/skills/peer-cli-customize/SKILL.md +22 -42
  61. package/skills/peers/SKILL.md +33 -57
  62. package/skills/plan/SKILL.md +33 -220
  63. package/skills/plan/plan-procedure.md +278 -0
  64. package/skills/plant-seed/SKILL.md +1 -0
  65. package/skills/pr-branch/SKILL.md +1 -0
  66. package/skills/progress/SKILL.md +1 -7
  67. package/skills/quality-gate/SKILL.md +34 -166
  68. package/skills/quality-gate/threat-modeling.md +101 -0
  69. package/skills/quick/SKILL.md +1 -0
  70. package/skills/reapply-patches/SKILL.md +1 -0
  71. package/skills/recall/SKILL.md +1 -0
  72. package/skills/resume/SKILL.md +1 -0
  73. package/skills/review-backlog/SKILL.md +1 -0
  74. package/skills/router/SKILL.md +3 -59
  75. package/skills/router/router-rules.md +84 -0
  76. package/skills/scan/SKILL.md +36 -675
  77. package/skills/scan/scan-procedure.md +731 -0
  78. package/skills/settings/SKILL.md +1 -0
  79. package/skills/ship/SKILL.md +1 -0
  80. package/skills/sketch/SKILL.md +1 -1
  81. package/skills/sketch-wrap-up/SKILL.md +13 -54
  82. package/skills/spike/SKILL.md +1 -1
  83. package/skills/spike-wrap-up/SKILL.md +12 -46
  84. package/skills/start/SKILL.md +13 -112
  85. package/skills/start/start-procedure.md +115 -0
  86. package/skills/stats/SKILL.md +1 -0
  87. package/skills/style/SKILL.md +18 -140
  88. package/skills/style/style-doc-procedure.md +150 -0
  89. package/skills/synthesize/SKILL.md +1 -0
  90. package/skills/timeline/SKILL.md +1 -0
  91. package/skills/todo/SKILL.md +1 -0
  92. package/skills/turn-closeout/SKILL.md +36 -56
  93. package/skills/undo/SKILL.md +1 -0
  94. package/skills/update/SKILL.md +1 -0
  95. package/skills/verify/SKILL.md +42 -457
  96. package/skills/verify/verify-procedure.md +512 -0
  97. package/skills/warm-cache/SKILL.md +3 -35
  98. package/skills/zoom-out/SKILL.md +26 -0
@@ -0,0 +1,278 @@
1
+ ---
2
+ name: plan-procedure
3
+ type: meta-rules
4
+ version: 1.0.0
5
+ phase: 28.5
6
+ tags: [plan, procedure, extracted, pipeline-stage, research, planner, checker]
7
+ last_updated: 2026-05-18
8
+ ---
9
+
10
+ Source: extracted from `skills/plan/SKILL.md` (Phase 28.5 rework — D-10 extract-then-link).
11
+ The skill's load-bearing workflow stays in `../skills/plan/SKILL.md`; this file holds the
12
+ detail the agent reaches for when executing a specific step (agent spawn prompts, chromatic
13
+ scoping, synthesizer wiring, research-synthesis persistence, exploration artifact globbing).
14
+
15
+ # Plan Procedure
16
+
17
+ Detailed procedure for the get-design-done `plan` Stage 3 orchestrator. Companion to
18
+ `../skills/plan/SKILL.md`. Read this file when executing a specific plan step; the
19
+ SKILL.md keeps the load-bearing workflow + decision tree, this file holds the deep
20
+ agent prompts and pre-plan research wiring.
21
+
22
+ ---
23
+
24
+ ## Stage entry
25
+
26
+ 1. `mcp__gdd_state__transition_stage` with `to: "plan"`.
27
+ - Gate failure surfaces `error.context.blockers` to the user; do not advance.
28
+ 2. `mcp__gdd_state__get` -> snapshot `state`. Use this snapshot for `<position>`, `<connections>`, `<must_haves>`, `<blockers>`, `<decisions>` in the current stage; do not re-read STATE.md directly.
29
+
30
+ Abort with a clear error only if the user is trying to plan without DESIGN-CONTEXT.md — that is the true prerequisite, not STATE.md.
31
+
32
+ ## Flag Parsing
33
+
34
+ Parse $ARGUMENTS:
35
+ - `--auto` -> auto_mode=true (skip approvals, skip optional research)
36
+ - `--parallel` -> parallel_mode=true (planner fills Touches:/Parallel: fields)
37
+
38
+ ## Parallelism Decision (before any multi-agent spawn)
39
+
40
+ - Read `.design/config.json` `parallelism` (or defaults from `reference/config-schema.md`).
41
+ - Apply rules from `reference/parallelism-rules.md`.
42
+ - Plan's pipeline is inherently sequential (researcher -> pattern-mapper -> planner -> checker). Expected verdict: **serial** (rule 1).
43
+
44
+ <!-- Parallelism decision is currently carried as the status string of an update_progress call. A dedicated tool may be added in a follow-on plan; until then, the status string is the canonical carrier. -->
45
+
46
+ After the parallelism decision is made:
47
+ - Call `mcp__gdd_state__update_progress` with `task_progress: "<current>/<total>"` and `status: "plan_parallelism_decided: batch_size=<N>, reason=<short-reason>"`.
48
+
49
+ ## Probe Chromatic connection
50
+
51
+ Run at stage entry, after reading STATE.md:
52
+
53
+ Step C1 — CLI presence:
54
+ Bash: command -v chromatic 2>/dev/null || npx chromatic --version 2>/dev/null
55
+ -> found -> proceed to Step C2
56
+ -> not found -> chromatic: not_configured (skip all Chromatic steps)
57
+
58
+ Step C2 — Token check:
59
+ Bash: test -n "${CHROMATIC_PROJECT_TOKEN}"
60
+ -> true -> chromatic: available
61
+ -> false -> chromatic: unavailable
62
+
63
+ Also check: if storybook: not_configured -> chromatic effectively unavailable (emit note, do not run).
64
+
65
+ Write chromatic status to STATE.md `<connections>` via `mcp__gdd_state__probe_connections` — pass the single-entry probe result (`[{ name: "chromatic", status: "<verdict>" }]`). Do not edit `<connections>` directly.
66
+
67
+ ## Chromatic Change-Risk Scoping (when chromatic: available)
68
+
69
+ Before writing DESIGN-PLAN.md, if chromatic: available:
70
+ 1. Identify token/component files to be changed (from DESIGN-CONTEXT.md scope)
71
+ 2. Run: Bash: npx chromatic --project-token $CHROMATIC_PROJECT_TOKEN --trace-changed=expanded --dry-run 2>&1
72
+ 3. Parse output — count story files that depend on changed source files
73
+ 4. Pass story count to design-planner.md (see design-planner.md Chromatic Change-Risk section)
74
+ If unavailable: design-planner proceeds without story-count annotation.
75
+
76
+ ---
77
+
78
+ ## Step 1 — Optional Research (skip if auto_mode)
79
+
80
+ Complexity heuristic: if DESIGN-CONTEXT.md `<domain>` spans 3+ scopes OR `<decisions>` count > 6 -> spawn design-phase-researcher. Otherwise skip.
81
+
82
+ If spawning:
83
+
84
+ ```
85
+ Task("design-phase-researcher", """
86
+ <required_reading>
87
+ @.design/STATE.md
88
+ @.design/DESIGN-CONTEXT.md
89
+ </required_reading>
90
+
91
+ You are the design-phase-researcher agent. Identify the project type from DESIGN-CONTEXT.md
92
+ and research relevant design patterns, pitfalls, and stack-specific conventions.
93
+
94
+ Output file: .design/DESIGN-RESEARCH.md
95
+ Target: ~100 lines, ~2 min budget.
96
+
97
+ Emit `## RESEARCH COMPLETE` when done.
98
+ """)
99
+ ```
100
+
101
+ Wait for `## RESEARCH COMPLETE`. Call `mcp__gdd_state__update_progress` with `task_progress: "1/3"` and a short `status` summary.
102
+
103
+ ## Step 1.5 — Pattern Mapping (mandatory, brownfield protection)
104
+
105
+ ```
106
+ Task("design-pattern-mapper", """
107
+ <required_reading>
108
+ @.design/STATE.md
109
+ @.design/DESIGN-CONTEXT.md
110
+ @reference/audit-scoring.md
111
+ </required_reading>
112
+
113
+ You are design-pattern-mapper. Grep the codebase for existing design patterns
114
+ (color tokens, spacing scale, typography conventions, component styling) and
115
+ write .design/DESIGN-PATTERNS.md. Classify by design concern — NOT by code
116
+ architecture (no controllers, services, middleware vocabulary).
117
+
118
+ Output file: .design/DESIGN-PATTERNS.md
119
+ Emit `## MAPPING COMPLETE` when done.
120
+ """)
121
+ ```
122
+
123
+ Wait for `## MAPPING COMPLETE`. Call `mcp__gdd_state__update_progress` with `task_progress: "1/3"` and a short `status` summary.
124
+
125
+ ## Step 1.6 — Assumptions Analysis (optional, same flag as research)
126
+
127
+ If assumptions analysis enabled (skip if auto_mode):
128
+
129
+ ```
130
+ Task("design-assumptions-analyzer", """
131
+ <required_reading>
132
+ @.design/STATE.md
133
+ @.design/DESIGN-CONTEXT.md
134
+ @.design/DESIGN-PATTERNS.md
135
+ </required_reading>
136
+
137
+ You are design-assumptions-analyzer. Surface hidden design assumptions with
138
+ confidence levels and evidence citations.
139
+
140
+ Emit `## ANALYSIS COMPLETE` when done.
141
+ """)
142
+ ```
143
+
144
+ Wait for `## ANALYSIS COMPLETE`.
145
+
146
+ ## Step 1.7 — Synthesize pre-plan research inputs (Plan 10.1-04, D-13/D-15)
147
+
148
+ If 2+ of the pre-plan research agents ran (`design-phase-researcher` Step 1, `design-pattern-mapper` Step 1.5, `design-assumptions-analyzer` Step 1.6), invoke synthesize to merge their outputs into a single compact brief. If only one ran, skip this step.
149
+
150
+ Skill("synthesize", {
151
+ outputs: [
152
+ (if Step 1 ran) "=== from design-phase-researcher ===\n" + <read .design/DESIGN-RESEARCH.md>,
153
+ (if Step 1.5 ran) "=== from design-pattern-mapper ===\n" + <read .design/DESIGN-PATTERNS.md>,
154
+ (if Step 1.6 ran) "=== from design-assumptions-analyzer ===\n" + <read .design/DESIGN-ASSUMPTIONS.md>
155
+ ],
156
+ directive: "Merge into a single compact pre-plan brief. Preserve per-source section headers so the planner can trace provenance. Consolidate duplicate recommendations with source tags. Target ~150 lines.",
157
+ output_shape: "markdown"
158
+ })
159
+
160
+ Wait for `## SYNTHESIS COMPLETE`. Write to `.design/DESIGN-PREPLAN-BRIEF.md` (overwrite if present). Add `@.design/DESIGN-PREPLAN-BRIEF.md` to the planner's `<required_reading>` in Step 2 — individual files remain on disk for drill-down.
161
+
162
+ **Parallel synthesizer note (future):** if a future plan variant spawns N parallel phase-researchers (e.g., one per project-type family), wire synthesize the same way as `skills/map/` Step 3.5.
163
+
164
+ ## Research-synthesis persistence (decisions + must-haves)
165
+
166
+ When the synthesizer (design-phase-researcher / design-pattern-mapper / design-assumptions-analyzer) produces D-XX decisions and M-XX must-haves, persist each one through MCP instead of editing STATE.md directly.
167
+
168
+ For each D-XX decision the synthesizer produces:
169
+ - Call `mcp__gdd_state__add_decision` with `{ id: "D-XX", text: "...", status: "locked"|"tentative" }`.
170
+
171
+ For each M-XX must-have the synthesizer produces:
172
+ - Call `mcp__gdd_state__add_must_have` with `{ id: "M-XX", text: "...", status: "pending" }`.
173
+
174
+ Issue these sequentially. Each call is event-emitting and lockfile-safe. Parallel issuance would serialize on the STATE.md lockfile with no throughput gain.
175
+
176
+ ## Step 2 — Plan
177
+
178
+ ```
179
+ Task("design-planner", """
180
+ <required_reading>
181
+ @.design/STATE.md
182
+ @.design/DESIGN-CONTEXT.md
183
+ @reference/audit-scoring.md
184
+ @.design/DESIGN-PATTERNS.md
185
+ [@.design/DESIGN-RESEARCH.md — only include if research step ran]
186
+ [@.design/DESIGN-ASSUMPTIONS.md — only include if assumptions analysis ran]
187
+ [@.design/DESIGN-PREPLAN-BRIEF.md — include if Step 1.7 synthesize ran; planner prefers this compact brief over the individual files above]
188
+ [@.design/sketches/*/WINNER.md — include all completed sketch winners if present]
189
+ [@.design/spikes/*/FINDINGS.md — include all completed spike findings if present]
190
+ [@./.claude/skills/design-*-conventions.md — include all project-local design conventions if present]
191
+ [@~/.claude/gdd/global-skills/*.md — include all global skills if directory exists; global conventions inform but do not override project-local D-XX decisions]
192
+ </required_reading>
193
+
194
+ You are the design-planner agent. Read DESIGN-CONTEXT.md and produce .design/DESIGN-PLAN.md
195
+ with wave-ordered tasks, acceptance criteria, and (if parallel mode) Touches:/Parallel: fields.
196
+
197
+ Context:
198
+ - Pipeline stage: plan
199
+ - auto_mode: <true|false>
200
+ - parallel_mode: <true|false>
201
+
202
+ Output file: .design/DESIGN-PLAN.md
203
+ Format: per agents/design-planner.md Output Format section.
204
+
205
+ Emit `## PLANNING COMPLETE` when done.
206
+ """)
207
+ ```
208
+
209
+ Wait for `## PLANNING COMPLETE`. Call `mcp__gdd_state__update_progress` with `task_progress: "2/3"` and a short `status` summary.
210
+
211
+ ## Step 3 — Check
212
+
213
+ ```
214
+ Task("design-plan-checker", """
215
+ <required_reading>
216
+ @.design/STATE.md
217
+ @.design/DESIGN-PLAN.md
218
+ @.design/DESIGN-CONTEXT.md
219
+ </required_reading>
220
+
221
+ You are the design-plan-checker agent. Validate DESIGN-PLAN.md will achieve DESIGN-CONTEXT.md
222
+ brief goals across 5 dimensions: requirement coverage, task completeness, wave ordering,
223
+ must-have derivation, auto mode compliance.
224
+
225
+ Context:
226
+ - auto_mode: <true|false>
227
+
228
+ Output: structured result as response text (no file). Start with `## PLAN CHECK RESULT: PASS`
229
+ or `## PLAN CHECK RESULT: ISSUES FOUND`.
230
+
231
+ Emit `## PLAN CHECK COMPLETE` when done.
232
+ """)
233
+ ```
234
+
235
+ Wait for `## PLAN CHECK COMPLETE`. Call `mcp__gdd_state__update_progress` with `task_progress: "3/3"` and a short `status` summary.
236
+
237
+ If `## PLAN CHECK RESULT: ISSUES FOUND` and any BLOCKER issues:
238
+ - Present issues to user and offer: (a) revise plan now — re-spawn design-planner with issue list, (b) accept and proceed, (c) abort.
239
+ - If auto_mode: auto-accept WARNING issues, abort on BLOCKER issues.
240
+
241
+ ## Stage exit
242
+
243
+ 1. Call `mcp__gdd_state__set_status` with `status: "plan_complete"`.
244
+ 2. Call `mcp__gdd_state__checkpoint` to stamp `last_checkpoint` and finalize the plan stage.
245
+
246
+ The next stage (design) calls `mcp__gdd_state__transition_stage` on entry — this skill does NOT issue the transition itself, preserving the stage-owned-transition discipline established by brief->explore and explore->plan.
247
+
248
+ ## After Completion
249
+
250
+ Print user-facing summary:
251
+ - Plan tasks: N waves, M total tasks
252
+ - Files: .design/DESIGN-PLAN.md (and .design/DESIGN-RESEARCH.md if research ran)
253
+ - Next: `/get-design-done:design` to execute the plan
254
+
255
+ ---
256
+
257
+ ## Exploration artifacts & project-local conventions
258
+
259
+ When building the planner spawn prompt, also glob for:
260
+ - `.design/sketches/*/WINNER.md` — winning sketch rationale (informs directional tasks)
261
+ - `.design/spikes/*/FINDINGS.md` — spike verdicts (inform task feasibility)
262
+ - `./.claude/skills/design-*-conventions.md` — project-local design conventions
263
+
264
+ Include each matching file in `<files_to_read>` / `<required_reading>` so the planner sees them when creating tasks. Spike findings from `.design/spikes/` inform task feasibility; sketch winners inform directional choice; project-local conventions override defaults.
265
+
266
+ ## --research mode (removed)
267
+
268
+ V2-04 deferred the `--research` flag. Rationale: complexity of an additional
269
+ agent spawn + Context7 integration outweighs the benefit of discover-stage
270
+ auto-detect for most projects. Use /discover's Auto Mode for research-assisted
271
+ discovery instead.
272
+
273
+ The optional research step that already exists (Step 1, triggered by complexity
274
+ heuristic: 3+ domain scopes OR 6+ decisions) covers the core use case without
275
+ a separate CLI flag.
276
+
277
+ If --research is reintroduced in a future version, define its scope in
278
+ ROADMAP.md V2+ and update this section.
@@ -3,6 +3,7 @@ name: gdd-plant-seed
3
3
  description: "Forward-looking design idea with a trigger condition. Seeds surface automatically when trigger is met. Writes to .design/SEEDS.md."
4
4
  argument-hint: "[--trigger <condition>] [text]"
5
5
  tools: Read, Write, AskUserQuestion
6
+ disable-model-invocation: true
6
7
  ---
7
8
 
8
9
  # /gdd:plant-seed
@@ -3,6 +3,7 @@ name: gdd-pr-branch
3
3
  description: "Create a clean PR branch by filtering out .design/ and .planning/ commits. Code-review-ready branch for the design implementation work."
4
4
  argument-hint: "[<base-branch>]"
5
5
  tools: Read, Write, Bash
6
+ disable-model-invocation: true
6
7
  ---
7
8
 
8
9
  # /gdd:pr-branch
@@ -50,13 +50,7 @@ Recommend next stage via the same logic as `/gdd:next` (route by which artifacts
50
50
 
51
51
  ### First-run connection nudge
52
52
 
53
- After the pipeline state block, check the `<connections>` field from the `mcp__gdd_state__get` snapshot. If every entry is `not_configured` AND `.design/config.json > connections_onboarding` is absent (user has never run the wizard), append once:
54
-
55
- ```
56
- Tip: run /gdd:connections to see what integrations can plug in (Figma, Storybook, Chromatic, etc.).
57
- ```
58
-
59
- Suppress the nudge on subsequent invocations in the same session (track via a transient marker file `.design/.connections-nudge-shown` written at first emit, deleted on next session start by no mechanism — so effectively once per session).
53
+ After the pipeline state block, if every `<connections>` entry from the snapshot is `not_configured` AND `.design/config.json > connections_onboarding` is absent, append once per session (transient marker `.design/.connections-nudge-shown`): `Tip: run /gdd:connections to see what integrations can plug in (Figma, Storybook, Chromatic, etc.).`
60
54
 
61
55
  ## Step 3 — Forensic audit (only if `--forensic`)
62
56
 
@@ -5,7 +5,6 @@ tools: Read, Write, Edit, Bash, Grep, Glob, Task
5
5
  color: amber
6
6
  model: inherit
7
7
  default-tier: haiku
8
- tier-rationale: "Orchestration of pre-detected commands and a downstream Haiku classifier. The skill itself does no synthesis — Bash runs do all the work, the classifier agent owns the routing decision."
9
8
  size_budget: M
10
9
  parallel-safe: conditional-on-touches
11
10
  typical-duration-seconds: 180
@@ -21,202 +20,71 @@ writes:
21
20
 
22
21
  ## Role
23
22
 
24
- You are the Stage 4.5 gate that runs between `/gdd:design` and `/gdd:verify`. You answer one question: *does this project's own quality tooling pass against the current working tree?*
23
+ You are the Stage 4.5 gate that runs between `/gdd:design` and `/gdd:verify`. You answer one question: *does this project's own quality tooling pass against the current working tree?* You are NOT a design checker, an a11y checker, or a verifier — you are a thin façade over the project's `lint` / `typecheck` / `test` / visual-regression scripts. Verify refuses entry when those scripts fail.
25
24
 
26
- You are NOT a design checker, an a11y checker, or a verifier. You are a thin façade over the project's existing `lint` / `typecheck` / `test` / visual-regression scripts. You exist so that the verify stage can refuse entry when those scripts fail (and so that the fix loop can be bounded and observable).
25
+ You write exactly two artifacts: the `<quality_gate>` block in `.design/STATE.md`, and lifecycle events to `.design/events.jsonl`. You never block on timeout. You never block on a "skipped" result. You only mark `status="fail"` when the fix loop reaches `max_iters` even then YOU exit successfully (verify is the consumer that refuses entry).
27
26
 
28
- You write exactly two artifacts:
29
- 1. The `<quality_gate>` block in `.design/STATE.md` (one most-recent `<run/>` element).
30
- 2. Lifecycle events in `.design/events.jsonl` (per Step 6 below).
27
+ ## Configuration
31
28
 
32
- You never block on timeout. You never block on a "skipped" detection result. You only mark `status="fail"` when the fix loop reaches `max_iters` without converging — and even then it is the verify stage's job to refuse entry; YOU exit successfully so the user sees the report regardless.
33
-
34
- ## Configuration Surface
35
-
36
- Read once at start, from `.design/config.json` (all keys optional; defaults documented):
29
+ Read once at start from `.design/config.json` (all optional; defaults in parens):
37
30
 
38
31
  | Key | Default | Purpose |
39
32
  |-----|---------|---------|
40
- | `quality_gate.commands` | `null` | Authoritative list of commands. When provided, skips auto-detection. Each entry is a string the shell can run (e.g. `"npm run lint"`). |
33
+ | `quality_gate.commands` | `null` | Authoritative command list. When provided, skips auto-detection. |
41
34
  | `quality_gate.timeout_seconds` | `600` | Total wall-clock budget for Step 2. On timeout: warn + proceed (D-07). |
42
35
  | `quality_gate.max_iters` | `3` | Hard cap on Step 4 fix-loop iterations. |
43
36
 
44
- Missing config file is not an error defaults apply.
45
-
46
- ## Step 1 — Detection chain
47
-
48
- Per D-06, resolve the active command list with this 3-tier fallback. Stop at the first tier that produces ≥ 1 command:
49
-
50
- ### Tier 1 — Authoritative config
51
-
52
- If `.design/config.json` carries `quality_gate.commands` and the array is non-empty, use it verbatim. Skip Tier 2 and Tier 3.
53
-
54
- ### Tier 2 — Auto-detect from `package.json#scripts`
55
-
56
- If `package.json` exists at the project root, read its `scripts` object. Match script names against the following allowlist (case-sensitive, exact match unless noted):
57
-
58
- | Script name | Notes |
59
- |-------------|-------|
60
- | `lint` | Always include if present. |
61
- | `typecheck` | Always include if present. |
62
- | `tsc` | Include if `typecheck` is absent (substitute, not duplicate). |
63
- | `test` | Include if present. |
64
- | `chromatic` | Include if present (visual-regression). |
65
- | `test:visual` | Include if present (visual-regression). |
37
+ ## Step 1 Detection chain (D-06 3-tier fallback)
66
38
 
67
- **Excluded by name** (intentionally too slow for a Stage 4.5 gate):
68
- - `test:e2e`
69
- - `test:integration` (only if a separate `test` exists)
70
- - Any script whose name starts with `dev:`, `build:`, `start:`.
39
+ Stop at the first tier that produces 1 command:
71
40
 
72
- For each matched script, the command to run is `npm run <script-name>` (use `pnpm run` or `yarn` only if the project's root carries a corresponding lockfile and the user's `.design/config.json` lists `quality_gate.package_manager`; otherwise default to `npm run` for portability).
73
-
74
- If `package.json` does not exist, or `scripts` is empty, or no allowlisted name matches, advance to Tier 3.
75
-
76
- ### Tier 3 — Skip with notice
77
-
78
- Emit a `quality_gate_skipped` event with `reason: "no commands resolved"` (Step 6). Write a `<run/>` element with `status="skipped"`, `commands_run=""`, `iteration=0`, `started_at` and `completed_at` set to the same timestamp. Exit successfully with status `skipped`. The verify-entry gate (Plan 25-07 territory) does NOT block on `skipped`.
41
+ 1. **Authoritative config.** If `.design/config.json` has `quality_gate.commands` non-empty, use verbatim.
42
+ 2. **Auto-detect from `package.json#scripts`** — match against allowlist: `lint`, `typecheck`, `tsc` (only if `typecheck` absent), `test`, `chromatic`, `test:visual`. Exclude by name: `test:e2e`, `test:integration` (if separate `test`), anything starting `dev:`, `build:`, `start:`. Run via `npm run <name>` unless `quality_gate.package_manager` overrides.
43
+ 3. **Skip with notice.** Emit `quality_gate_skipped` (Step 6) and write a `<run/>` with `status="skipped"`. Verify treats skipped as non-blocking.
79
44
 
80
45
  ## Step 2 — Parallel run
81
46
 
82
- Open Step 2 by emitting `quality_gate_started` with the resolved command list (Step 6).
83
-
84
- For each command produced by Step 1, spawn a **separate** `Bash` invocation; collect `{command, exit_code, stdout, stderr}` for each. Run them concurrently — the gate's wall-clock budget is the slowest command, not their sum.
85
-
86
- The combined wall-clock budget is `quality_gate.timeout_seconds` (default 600). If the budget elapses before all commands complete:
87
-
88
- 1. Emit `quality_gate_timeout` with the names of commands that did not finish.
89
- 2. Mark `status="timeout"`, `commands_run=<comma-joined attempted names>`, and treat unfinished commands as having no failure to classify.
90
- 3. Skip Step 3 / Step 4 (no fix loop on timeout — it would just compound the slowness).
91
- 4. Proceed to Step 5 (STATE write) and Step 6 (final event).
92
- 5. **Exit successfully.** Verify entry treats `timeout` as a warn, not a block.
93
-
94
- If all commands complete within budget, advance to Step 3.
47
+ Emit `quality_gate_started`. Spawn each command in a separate `Bash`; collect `{command, exit_code, stdout, stderr}`. Wall-clock budget is `timeout_seconds` (default 600). On timeout: emit `quality_gate_timeout`, mark `status="timeout"`, skip Steps 3–4, proceed to Step 5. Exit successfully — verify treats timeout as a warn.
95
48
 
96
49
  ## Step 3 — Classification
97
50
 
98
- Spawn the `quality-gate-runner` agent via the `Task` tool. Pass an input payload of the shape:
99
-
100
- ```json
101
- {
102
- "outputs": [
103
- {"command": "npm run lint", "exit_code": 0, "stderr": ""},
104
- {"command": "npm run typecheck", "exit_code": 1, "stderr": "<verbatim stderr>"},
105
- {"command": "npm run test", "exit_code": 0, "stderr": ""}
106
- ]
107
- }
108
- ```
109
-
110
- The agent emits a single JSON object on stdout (see `agents/quality-gate-runner.md`):
111
-
112
- ```json
113
- {
114
- "status": "pass" | "fail",
115
- "classified_failures": {
116
- "lint": ["…"],
117
- "type": ["…"],
118
- "test": ["…"],
119
- "visual": ["…"]
120
- }
121
- }
122
- ```
123
-
124
- When `status === "pass"`, advance directly to Step 5 with `iteration` equal to the current loop counter (starts at `1` on the first pass).
125
-
126
- When `status === "fail"`, advance to Step 4.
51
+ Spawn `quality-gate-runner` agent via `Task` with payload `{outputs: [{command, exit_code, stderr}, ...]}`. Agent returns `{status: "pass"|"fail", classified_failures: {lint, type, test, visual}}`. `pass` → Step 5. `fail` → Step 4.
127
52
 
128
53
  ## Step 4 — Fix loop (D-08)
129
54
 
130
- If `iteration >= quality_gate.max_iters` (default 3), the loop is exhausted:
131
- - Emit `quality_gate_fail` with the final classified failures.
132
- - Mark `status="fail"`, persist the final `iteration`, and proceed to Step 5.
133
- - **Exit successfully.** Verify entry refuses on `status="fail"`; YOU do not throw.
55
+ If `iteration >= max_iters`: emit `quality_gate_fail`, mark `status="fail"`, Step 5, exit successfully. Verify-entry refuses on `fail`; YOU do not throw.
134
56
 
135
- Otherwise, increment `iteration` and emit `quality_gate_iteration` with the current value. Spawn the existing `design-fixer` agent (Phase 5) via `Task` with classified failures as context — pass the same shape produced by Step 3 plus the original `outputs[]` for verbatim error context. After the fixer returns, restart from Step 2 (re-run all commands; do not prune to "only the previously failing ones" — fixes can introduce regressions in formerly-clean commands).
136
-
137
- The loop terminates when either Step 3 returns `status="pass"` or `iteration` reaches `max_iters`.
57
+ Else: increment `iteration`, emit `quality_gate_iteration`, spawn `design-fixer` via `Task` with classified failures + original outputs. After fixer returns, restart from Step 2 (re-run all commands — fixes can introduce regressions).
138
58
 
139
59
  ## Step 5 — STATE write
140
60
 
141
- Open `.design/STATE.md`. Mutate the parsed state's `quality_gate` field to:
142
-
143
- ```ts
144
- {
145
- run: {
146
- started_at: <ISO 8601 — captured at Step 2 entry>,
147
- completed_at: <ISO 8601 — now>,
148
- status: <"pass" | "fail" | "timeout" | "skipped">,
149
- iteration: <final loop counter>,
150
- commands_run: <comma-joined names of commands that completed>,
151
- extra_attrs: {},
152
- },
153
- }
154
- ```
155
-
156
- Persist via `mcp__gdd_state__set_quality_gate` (the underlying mutator wiring is named in this contract; the SDK MCP layer wraps every mutator method, so the surface inherits free from the parser/mutator extension landed in this plan). Until the MCP tool exists (Plan 25-07 surfaces it in the verify-stage integration), use the `apply()` mutator from `scripts/lib/gdd-state/mutator.ts` directly:
157
-
158
- ```ts
159
- apply(raw, (state) => {
160
- state.quality_gate = { run };
161
- return state;
162
- });
163
- ```
164
-
165
- Either path is acceptable. The on-disk shape is identical.
61
+ Mutate `state.quality_gate.run` to `{started_at, completed_at, status, iteration, commands_run, extra_attrs:{}}`. Persist via `mcp__gdd_state__set_quality_gate` or `apply()` mutator from `scripts/lib/gdd-state/mutator.ts` — identical on-disk shape.
166
62
 
167
63
  ## Step 6 — Event emission (D-09)
168
64
 
169
- Emit lifecycle events to `.design/events.jsonl` via the existing `appendEvent()` surface exported from `scripts/lib/event-stream/index.ts` — the same module Phase 22 telemetry, the budget-enforcer, the read-injection scanner, and the gdd-state MCP server already write through. Do not roll a bespoke writer; the singleton in `event-stream/index.ts` is persist-first / broadcast-second and never throws on the persist path, which is the contract this skill relies on.
170
-
171
- Import shape:
65
+ Use `appendEvent` from `scripts/lib/event-stream/index.ts` — persist-first / broadcast-second; never throws on persist path. `ts` / `cycle` / `stage` are stamped by the writer. Six event types (one per lifecycle position):
172
66
 
173
- ```ts
174
- import { appendEvent } from '../../scripts/lib/event-stream/index.ts';
175
- ```
67
+ | Event | When | Payload |
68
+ |-------|------|---------|
69
+ | `quality_gate_started` | Step 2 entry, once | `commands`, `timeout_seconds`, `max_iters` |
70
+ | `quality_gate_iteration` | Step 4 retry (iter ≥ 2) | `iteration` |
71
+ | `quality_gate_pass` | Step 3 returned pass — terminal | `iteration`, `commands_run` |
72
+ | `quality_gate_fail` | Step 4 hit `max_iters` — terminal | `iteration`, `classified_failures` |
73
+ | `quality_gate_timeout` | Step 2 budget elapsed — terminal warn | `unfinished_commands` |
74
+ | `quality_gate_skipped` | Step 1 tier 3 — terminal no-op | `reason` |
176
75
 
177
- Each emission is a single `appendEvent({...})` call with `type` set to one of the six names in the table below. Pass the event-specific payload fields verbatim — `appendEvent` stamps `_meta` (pid, host, source) and the JSONL writer captures the canonical `ts` from the writer surface. The `cycle` and `stage` fields are stamped by the same path used elsewhere in Phase 22+ (consumers match on `type`; treat `ts`, `cycle`, `stage` as injected, not caller-supplied).
76
+ `appendEvent` swallows persist failures events are observability, not correctness. STATE.md (Step 5) is the durable record.
178
77
 
179
- One event per JSONL line. Schema and lifecycle map:
78
+ ## Output
180
79
 
181
- | Event | When (lifecycle position) | Required fields |
182
- |-------|---------------------------|-----------------|
183
- | `quality_gate_started` | Step 2 entry — fired ONCE per skill invocation, immediately before any `Bash` spawn. Carries the resolved command list from Step 1 so downstream telemetry can correlate `started` → terminal event. | `commands` (string[]), `timeout_seconds` (number), `max_iters` (number) |
184
- | `quality_gate_iteration` | Step 4 entry — fired ONCE per retry, with `iteration` set to the new (post-increment) loop counter. The first run is implicit (covered by `started`); only retries `≥ 2` emit `iteration`. | `iteration` (int ≥ 2) |
185
- | `quality_gate_pass` | Step 3 returned `status: "pass"` — terminal happy path. Fires before Step 5 (STATE write) so a consumer tailing the stream sees the verdict before the on-disk run record. | `iteration` (final loop counter), `commands_run` (string[]) |
186
- | `quality_gate_fail` | Step 4 reached `max_iters` without convergence — terminal failure path. The verify-entry gate (Step 2.5 of `skills/verify/SKILL.md`) is the sole consumer that *acts* on this; this skill exits successfully regardless. | `iteration` (final loop counter, equal to `max_iters`), `classified_failures` (object — same shape as `quality-gate-runner` agent output) |
187
- | `quality_gate_timeout` | Step 2 wall-clock budget elapsed — terminal warn path (per D-07 verify treats this as a warning, not a block). Fires before Step 5 STATE write, same ordering as `pass`/`fail`. | `unfinished_commands` (string[]) |
188
- | `quality_gate_skipped` | Step 1 Tier 3 fired (no commands resolved) — terminal no-op path. Fires before the synthetic `<run/>` is written to STATE.md. | `reason` (string — e.g. `"no commands resolved"`) |
189
-
190
- All six events carry the standard `ts`, `cycle`, `stage` fields injected by `appendEvent` / the writer. Do not invent additional event names — the verify-entry gate, reflector, and Phase 22 telemetry consumers match on this exact list. Do not emit any of these names from any path other than the lifecycle positions above (e.g., do not emit `quality_gate_started` again on a Step 4 retry — that's what `quality_gate_iteration` is for).
191
-
192
- **Failure-mode contract:** `appendEvent()` swallows persist failures internally. If the writer cannot open `.design/events.jsonl`, the skill MUST still proceed — the event stream is observability, not correctness. The STATE.md write in Step 5 is the durable record consumers MUST rely on; events.jsonl is the supplementary timeline.
193
-
194
- ## Output Contract
195
-
196
- Emit a single JSON object on stdout summarizing the run for the caller:
197
-
198
- ```json
199
- {
200
- "status": "pass",
201
- "iteration": 1,
202
- "commands_run": ["npm run lint", "npm run typecheck", "npm run test"],
203
- "started_at": "2026-04-29T10:00:00Z",
204
- "completed_at": "2026-04-29T10:01:42Z"
205
- }
206
- ```
207
-
208
- Schema:
209
- - `status` — `pass | fail | timeout | skipped`.
210
- - `iteration` — final loop counter; `0` for `skipped`.
211
- - `commands_run` — array of command strings actually executed.
212
- - `started_at` / `completed_at` — ISO 8601, copied from the STATE write.
213
-
214
- The skill exits with shell exit code `0` on every terminal status — including `fail`. The verify-entry gate is the sole consumer of the `fail` status; this skill never throws to the orchestrator.
80
+ Emit one JSON object on stdout: `{status, iteration, commands_run, started_at, completed_at}`. Shell exit code `0` on every terminal status — `fail` included. Verify-entry is the sole consumer that acts on `fail`.
215
81
 
216
82
  ## Constraints
217
83
 
218
- - **Do not** prune the command list across iterations — always re-run everything in Step 2.
219
- - **Do not** spawn `quality-gate-runner` more than once per loop iteration. Spawn `design-fixer` more than once if and only if the loop iterates.
220
- - **Do not** read or write any STATE block other than `<quality_gate>` and `<position>` (the latter only as required by the standard write contract; the gate is a checkpoint, not a stage transition, so `<position>` updates are limited to `last_checkpoint`).
221
- - **Do not** invoke verify or design — Stage 4.5 sits strictly between them.
222
- - Treat exit codes via the standard convention: `0` = clean; non-zero = failure to be classified. Do not interpret stderr content for the pass/fail decision — the agent does that classification, you do not.
84
+ - Do not prune the command list across iterations — re-run everything in Step 2.
85
+ - Do not spawn `quality-gate-runner` more than once per iteration.
86
+ - Do not read/write any STATE block other than `<quality_gate>` (and `<position>.last_checkpoint`).
87
+ - Do not invoke verify or design — Stage 4.5 sits strictly between.
88
+ - Exit-code convention: `0` clean; non-zero classified as failure. Do not interpret stderr for pass/fail.
89
+
90
+ For verify-side severity classification (when this gate's `status="fail"` reaches the verify entry gate), see `./threat-modeling.md` — STRIDE dispositions are the audit-side framework that informs whether a failed quality gate blocks ship.