@hegemonart/get-design-done 1.31.5 → 1.32.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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Get Design Done — 5-stage agent-orchestrated design pipeline with 9 connections, handoff-first workflow, bidirectional Figma write-back, 22+ specialized agents, queryable knowledge layer (intel store, dependency analysis, learnings extraction), and a self-improvement loop (reflector, frontmatter + budget feedback, global-skills layer). v1.20.0 ships the SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream, and resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) for rate-limit + 429 + context-overflow recovery. Full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation (auto-tag + GitHub Release + release-time smoke test).",
8
- "version": "1.31.5"
8
+ "version": "1.32.0"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "get-design-done",
13
13
  "source": "./",
14
14
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), Claude Design handoff, bidirectional Figma write-back, and a queryable intel store (.design/intel/) for dependency and learnings queries. Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation. Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain.",
15
- "version": "1.31.5",
15
+ "version": "1.32.0",
16
16
  "author": {
17
17
  "name": "hegemonart"
18
18
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "get-design-done",
3
3
  "short_name": "gdd",
4
- "version": "1.31.5",
4
+ "version": "1.32.0",
5
5
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), handoff-first workflow via Claude Design bundles, bidirectional Figma write-back (annotations, Code Connect), queryable intel store (`.design/intel/`) for O(1) design surface lookups, and self-improvement loop (reflector agent, frontmatter + budget feedback, global-skills layer at `~/.claude/gdd/global-skills/`). Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings, reflect, apply-reflections. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows, lint + schema + frontmatter + stale-ref + shellcheck + gitleaks + injection-scan + blocking size-budget) and release automation (auto-tag + GitHub Release + release-time smoke test). Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain. v1.27.7 ships gdd-mcp (Phase 27.7): 12 read-only MCP tools for sub-3s priming. v1.28.0 (Phase 28): Foundational References Tier 2 — 5 new reference files (color-theory, composition, proportion-systems, i18n, contrast-advanced), 2 verifier i18n probes + 1 explore i18n-readiness probe, 12 additive cross-link insertions across 10 existing references, 2 orthogonal audit-scoring lens-tags (composition_alignment + i18n_readiness).",
6
6
  "author": {
7
7
  "name": "hegemonart",
package/CHANGELOG.md CHANGED
@@ -4,6 +4,37 @@ All notable changes to get-design-done are documented here. Versions follow [sem
4
4
 
5
5
  ---
6
6
 
7
+ ## [1.32.0] - 2026-05-30
8
+
9
+ ### Phase 32 — Skill Auto-Trigger Discipline + Defensive Guardrails
10
+
11
+ Closes the auto-trigger gap between GDD's 70+ skills and the harness's description-match skill-discovery layer. GDD had zero forcing functions — agents consulted skills opportunistically, not disciplinedly. This release ports the skill-discipline **mechanism** (not content) from [`obra/superpowers`](https://github.com/obra/superpowers) (MIT): a SessionStart-injected bootstrap contract, defensive guardrails at every stage transition, and two lightweight skill-discovery instruments that feed Phase 33's behavioral A/B. 9 plans across Waves A–C.
12
+
13
+ ### Added
14
+
15
+ - **`using-gdd` SessionStart bootstrap (the forcing function GDD lacked).** A new `skills/using-gdd/SKILL.md` discipline contract — the **1%-rule** ("if you think there is even a 1% chance a skill applies, you ABSOLUTELY MUST invoke it"), a ≥10-row **red-flags table** (Thought → Reality), a skill-priority order (Process → Implementation → Audit), an instruction-priority precedence (user CLAUDE.md > GDD skill > defaults), and the GDD pipeline flow. Carries `disable-model-invocation: true` (it is injected, not model-invoked) and a pure-trigger description (no `<what>` clause, per superpowers' shortcut finding — proof-by-implementation; Phase 28.5's description-format validator stays open pending Phase 33's A/B evidence).
16
+ - **Per-harness SessionStart inject emitter.** `hooks/inject-using-gdd.sh` is a single polyglot script that reads `using-gdd` and emits it as the host harness's SessionStart `additionalContext` shape — Cursor (`additional_context`), Claude Code (`hookSpecificOutput.additionalContext`), and SDK-standard (top-level `additionalContext`) branches via env-var detection, with a pure-bash JSON escaper (no jq/python dependency). A `hooks/run-hook.cmd` polyglot Windows wrapper and a 5th `hooks/hooks.json` SessionStart entry (matcher `startup|clear|compact`) wire it in.
17
+ - **`<SUBAGENT-STOP>` no-cascade structural guarantee.** The inject is wired ONLY under the SessionStart hook event; subagent spawns do not fire SessionStart, so the bootstrap contract cannot cascade into a subagent's context. The `using-gdd` body opens with a `<SUBAGENT-STOP>` tag. (Structural guarantee here; the behavioral proof under pressure is deferred to Phase 33.)
18
+ - **`<HARD-GATE>` at the 5 stage transitions.** `skills/{brief,explore,plan,design,verify}/SKILL.md` each gain a `<HARD-GATE>` block that refuses to advance the pipeline until the stage's required artifact (`.design/BRIEF.md`, `DESIGN.md` + `DESIGN-CONTEXT.md`, etc.) exists and is approved — reading the artifact path from `.design/STATE.md` when a project uses a custom location.
19
+ - **Rationalization tables in the 7 stage-orchestrator skills.** `brief / explore / plan / design / verify / discuss / audit` each carry a `| Thought | Reality |` rationalization table (≥6 rows) that names the common "skip the stage" justifications and rebuts each.
20
+ - **Inline self-review blocks** in `brief` and `plan` (the 2 spec-producing transitions) — a 4-line inline checklist (Phase 28.5 progressive-disclosure: a short check belongs at the transition surface, not behind a skill-discovery hop).
21
+ - **Portable discipline blocks** in `AGENTS.md` + `GEMINI.md` so non-Claude-Code harnesses (Codex, Gemini, etc.) inherit the same skill-discipline contract.
22
+ - **`router_pick` skill-discovery telemetry** — a new `router_pick` event in `reference/schemas/events.schema.json` plus an emit point (`skills/router/router-pick-emitter.md`). Records a sha256 `context_hash` (never the raw intent — no PII) so Phase 33 can measure which skill the router actually selected.
23
+ - **`lint-skill-descriptions.cjs` drift detector** — a maintainer/CI script (not shipped to npm) that flags any skill whose one-line `description:` is stale while its body changed ≥3 times since (the D-02 heuristic).
24
+ - **`gdd-health` `skill_discipline` check (#7).** `scripts/lib/health-mirror/index.cjs` gains a 7th read-only check reporting `skill-discipline: ready` (using-gdd present AND `hooks.json` SessionStart wires the inject), `skill-discipline: missing using-gdd`, or `skill-discipline: hook not wired`. Documented in `skills/health/SKILL.md`.
25
+
26
+ ### Attribution
27
+
28
+ - **Mechanism ported from [`obra/superpowers`](https://github.com/obra/superpowers) (MIT).** Three artifacts: the SessionStart hook-script structure, the 1%-rule + red-flags-table format, and the defensive-guardrail patterns (`<HARD-GATE>` / `<SUBAGENT-STOP>` / rationalization-table). See `NOTICE`. We port the MECHANISM, not the content — GDD's skills, gates, and tables are GDD-specific.
29
+
30
+ ### Notes
31
+
32
+ - The pure-trigger `using-gdd` description ships as **proof-by-implementation** of superpowers' shortcut finding (a `<what>`-clause can make agents follow the description summary instead of reading the body). The counterfactual A/B description test and the pressure-scenario behavior runner are **deferred to Phase 33** (D-02); Phase 32 ships the `router_pick` events + drift-lint instruments that Phase 33 consumes. Phase 28.5's global description-format validator regex stays open until that evidence lands.
33
+ - 4 stage skills (`brief`, `explore`, `plan`, `verify`) sit in the validator's advisory **warn** band (≥100 lines) after gaining the mandatory discipline blocks — well under the **block** threshold (250). Accepted by design: the gates + tables are the deliverable.
34
+ - 6-manifest lockstep at **v1.32.0** (`package.json` + `.claude-plugin/plugin.json` + `.claude-plugin/marketplace.json` (metadata.version + plugins[0].version) + `.cursor-plugin/plugin.json` + `.codex-plugin/plugin.json`).
35
+
36
+ ---
37
+
7
38
  ## [1.31.5] - 2026-05-29
8
39
 
9
40
  ### Phase 31.5 — Repo Structure Consolidation
package/NOTICE CHANGED
@@ -211,14 +211,52 @@ See `.planning/phases/30.6-graphify-self-ownership/` for full phase
211
211
  documentation including the 10 architectural decisions (D-01 through D-10)
212
212
  and the migration of the 8 dispatching callsites to native `bin/gdd-graph`.
213
213
 
214
+ ──────────────────────────────────────────────────────────────────────────────
215
+ Phase 32 — Skill Auto-Trigger Discipline + Defensive Guardrails (v1.32.0, 2026-05-30)
216
+ ──────────────────────────────────────────────────────────────────────────────
217
+
218
+ The skill-discipline layer shipped in v1.32.0 ports the MECHANISM (not the
219
+ content) from:
220
+
221
+ obra/superpowers (https://github.com/obra/superpowers)
222
+ License: MIT
223
+
224
+ GDD had 70+ skills and zero forcing functions; superpowers ships exactly one
225
+ (`using-superpowers` SessionStart inject) plus the `<HARD-GATE>` /
226
+ `<SUBAGENT-STOP>` / rationalization-table guardrail patterns, and reliably
227
+ auto-triggers its skills. We re-derive the mechanism in GDD's own runtime and
228
+ skill set; the skill bodies, gates, tables, and pipeline flow are GDD-specific.
229
+ Three ported artifacts:
230
+
231
+ hooks/inject-using-gdd.sh
232
+ └─ SessionStart hook-script structure adapted from superpowers'
233
+ `using-superpowers` inject: one polyglot script, env-var branch per
234
+ harness, pure-bash escape_for_json (no jq/python dependency).
235
+
236
+ skills/using-gdd/SKILL.md
237
+ └─ The 1%-rule ("even a 1% chance a skill applies → invoke it") + the
238
+ red-flags `| Thought | Reality |` table format adapted from
239
+ superpowers' using-superpowers discipline contract. GDD content:
240
+ GDD pipeline stages, skill-priority order, instruction-priority.
241
+
242
+ skills/{brief,explore,plan,design,verify,discuss,audit}/SKILL.md
243
+ └─ The defensive-guardrail patterns — `<HARD-GATE>` (refuse to advance a
244
+ stage without its artifact), `<SUBAGENT-STOP>` (no-cascade into
245
+ subagents), and the rationalization-table pattern — adapted from
246
+ superpowers. The specific gates, artifact paths, and table rows are
247
+ GDD-specific.
248
+
249
+ The mechanism is the contribution being attributed; the discipline content is
250
+ original to get-design-done.
251
+
214
252
  ────────────────────────────────────────────────────────────────────────
215
253
 
216
254
  Note on the broader codebase: get-design-done as a whole is licensed under
217
255
  the MIT License (see LICENSE). The Apache 2.0 attribution above applies
218
256
  specifically to the cc-multi-cli-derived files listed under the Phase 27
219
- block. The MIT attributions under Phase 28.5 and Phase 28.7 cover content
220
- adapted from mattpocock/skills (MIT) and gsd-build/get-shit-done (MIT)
221
- respectively — the MIT-to-MIT re-licensing is straightforward and the
222
- attributions above provide the required source citation. The MIT and
223
- Apache 2.0 licenses are compatible — see
257
+ block. The MIT attributions under Phase 28.5, Phase 28.7, and Phase 32 cover
258
+ content/mechanism adapted from mattpocock/skills (MIT), gsd-build/get-shit-done
259
+ (MIT), and obra/superpowers (MIT) respectively — the MIT-to-MIT re-licensing is
260
+ straightforward and the attributions above provide the required source
261
+ citation. The MIT and Apache 2.0 licenses are compatible — see
224
262
  https://www.apache.org/legal/resolved.html#category-a.
package/README.md CHANGED
@@ -276,6 +276,18 @@ node scripts/lib/figma-extract/digest.cjs --raw <cache>/raw/<key> --out .design/
276
276
 
277
277
  See [`skills/figma-extract/SKILL.md`](skills/figma-extract/SKILL.md) and [`figma-plugin/README.md`](figma-plugin/README.md) for the full flow.
278
278
 
279
+ ### Skill discipline bootstrap (v1.32.0+)
280
+
281
+ GDD ships 70+ skills, but a description-match skill router consults them opportunistically — easy to skip a stage under pressure. v1.32.0 adds the forcing function GDD lacked, porting the skill-discipline **mechanism** (not content) from [`obra/superpowers`](https://github.com/obra/superpowers) (MIT):
282
+
283
+ - **SessionStart inject.** A `using-gdd` bootstrap contract is injected at every session start / `/clear` / compact (`hooks/inject-using-gdd.sh`, per-harness: Cursor / Claude Code / SDK). It carries the **1%-rule** ("even a 1% chance a skill applies → invoke it"), a red-flags `Thought → Reality` table, and the skill-priority + instruction-priority order — so the agent is primed to find the right skill before it acts.
284
+ - **`<HARD-GATE>` at every stage transition.** Brief / Explore / Plan / Design / Verify each refuse to advance until the stage's artifact exists and is approved — no free-handing a stage.
285
+ - **Rationalization tables** in all 7 stage skills name the common "skip it" justifications and rebut each; **inline self-review** blocks gate the brief and plan specs.
286
+ - **`<SUBAGENT-STOP>` no-cascade.** The inject fires only on SessionStart, so the bootstrap never cascades into spawned subagents.
287
+ - **Portable + health-aware.** `AGENTS.md` + `GEMINI.md` carry the same discipline block for non-Claude-Code harnesses, and `/gdd:health` reports a `skill-discipline` readiness line.
288
+
289
+ See [`skills/using-gdd/SKILL.md`](skills/using-gdd/SKILL.md) and the `NOTICE` attribution for details.
290
+
279
291
 
280
292
  ## How It Works
281
293
 
package/SKILL.md CHANGED
@@ -243,6 +243,10 @@ If `$ARGUMENTS` is a stage or command name — invoke it directly, no state chec
243
243
  /gdd:sketch-wrap-up → Skill("get-design-done:gdd-sketch-wrap-up")
244
244
  /gdd:spike → Skill("get-design-done:gdd-spike")
245
245
  /gdd:spike-wrap-up → Skill("get-design-done:gdd-spike-wrap-up")
246
+ # --- Bootstrap (not slash-routed) ---
247
+ # using-gdd → injected at SessionStart by hooks/inject-using-gdd.sh
248
+ # (disable-model-invocation: true). The skill-discipline contract;
249
+ # not a user-invoked command — see skills/using-gdd/SKILL.md.
246
250
  ```
247
251
 
248
252
  Pass remaining arguments through: `/gdd:explore --skip-interview` → `Skill("get-design-done:gdd-explore", "--skip-interview")`.
package/hooks/hooks.json CHANGED
@@ -32,6 +32,15 @@
32
32
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gdd-sessionstart-recap.js\""
33
33
  }
34
34
  ]
35
+ },
36
+ {
37
+ "matcher": "startup|clear|compact",
38
+ "hooks": [
39
+ {
40
+ "type": "command",
41
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/inject-using-gdd.sh\""
42
+ }
43
+ ]
35
44
  }
36
45
  ],
37
46
  "PreToolUse": [
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env bash
2
+ # hooks/inject-using-gdd.sh — SessionStart per-harness context injector (D-07).
3
+ #
4
+ # The forcing function GDD lacked: on every session start / /clear / compact this
5
+ # reads skills/using-gdd/SKILL.md (the bootstrap discipline contract) and emits it
6
+ # as the host harness's SessionStart "additionalContext" shape so the agent is
7
+ # primed with the 1%-rule + red-flags + skill-priority before it acts.
8
+ #
9
+ # Ported MECHANISM (not content) from obra/superpowers (MIT): one polyglot script,
10
+ # env-var branch, pure-bash escape_for_json (no jq/python dependency). See NOTICE.
11
+ #
12
+ # Three emitted shapes (ONE JSON object on stdout, nothing else):
13
+ # Cursor (CURSOR_PLUGIN_ROOT set) -> {"additional_context": "<escaped>"}
14
+ # Claude Code (CLAUDE_PLUGIN_ROOT set, no Cursor)
15
+ # -> {"hookSpecificOutput":
16
+ # {"hookEventName":"SessionStart",
17
+ # "additionalContext":"<escaped>"}}
18
+ # SDK-standard (neither; e.g. COPILOT_CLI) -> {"additionalContext": "<escaped>"}
19
+ #
20
+ # Branch order: check Cursor BEFORE Claude Code — a Cursor session may also export
21
+ # CLAUDE_PLUGIN_ROOT, and Cursor's own var must win.
22
+ #
23
+ # NO-CASCADE (D-06): this script is wired ONLY under the SessionStart hook event in
24
+ # hooks/hooks.json. Subagent spawns do not fire SessionStart, so the inject cannot
25
+ # cascade into a subagent's context. (Structural guarantee; behavioral proof = P33.)
26
+
27
+ set -u
28
+
29
+ # --- Resolve the plugin root so we can locate skills/using-gdd/SKILL.md ---------
30
+ # Prefer the harness-provided roots; fall back to this script's parent dir so the
31
+ # emitter is runnable straight from hooks/ in tests and in bare shells.
32
+ SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
33
+ ROOT="${CURSOR_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${SELF_DIR}/..}}"
34
+ ROOT="${ROOT//\\//}" # normalize Windows backslashes to forward slashes
35
+ SKILL="${ROOT}/skills/using-gdd/SKILL.md"
36
+
37
+ # Defensive: if the skill file is missing we must STILL emit a syntactically valid
38
+ # JSON object (an empty additionalContext) so the SessionStart pipeline never
39
+ # breaks on a partial install. Never crash the session start.
40
+ if [[ -r "${SKILL}" ]]; then
41
+ CONTENT="$(cat "${SKILL}")"
42
+ else
43
+ CONTENT=""
44
+ fi
45
+
46
+ # --- escape_for_json (superpowers pattern; pure bash param-substitution) --------
47
+ # Order matters: backslash FIRST (so escapes we add next aren't re-escaped), then
48
+ # double-quote, then the control chars newline / tab / carriage-return. Emits the
49
+ # value WITH surrounding double-quotes so callers can splice it directly.
50
+ escape_for_json() {
51
+ local s="$1"
52
+ s="${s//\\/\\\\}" # \ -> \\
53
+ s="${s//\"/\\\"}" # " -> \"
54
+ s="${s//$'\t'/\\t}" # tab -> \t
55
+ s="${s//$'\r'/\\r}" # CR -> \r
56
+ s="${s//$'\n'/\\n}" # LF -> \n (do last: newlines are the record separator)
57
+ printf '"%s"' "$s"
58
+ }
59
+
60
+ ESCAPED="$(escape_for_json "${CONTENT}")"
61
+
62
+ # --- Branch on harness env vars and emit the matching single JSON object --------
63
+ if [[ -n "${CURSOR_PLUGIN_ROOT:-}" ]]; then
64
+ # Cursor: top-level additional_context.
65
+ printf '{"additional_context": %s}\n' "${ESCAPED}"
66
+ elif [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
67
+ # Claude Code: hookSpecificOutput envelope (mirrors hooks/gdd-decision-injector.js).
68
+ printf '{"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": %s}}\n' "${ESCAPED}"
69
+ else
70
+ # SDK-standard (COPILOT_CLI or none): top-level additionalContext.
71
+ printf '{"additionalContext": %s}\n' "${ESCAPED}"
72
+ fi
@@ -0,0 +1,35 @@
1
+ @echo off
2
+ REM hooks/run-hook.cmd — Windows polyglot wrapper that invokes a GDD .sh hook
3
+ REM through bash.
4
+ REM
5
+ REM Workaround for Claude Code's Windows auto-bash bug: CC can mis-handle a
6
+ REM SessionStart `command` that points directly at a `.sh` file on Windows
7
+ REM shells. This .cmd shim locates bash and runs the script explicitly, so the
8
+ REM SessionStart inject (hooks/inject-using-gdd.sh) fires on Windows too.
9
+ REM
10
+ REM Usage: run-hook.cmd <script-name.sh> [args...]
11
+ REM Default (no arg): inject-using-gdd.sh — the SessionStart using-gdd injector.
12
+ REM The host harness's env (CLAUDE_PLUGIN_ROOT / CURSOR_PLUGIN_ROOT / COPILOT_CLI)
13
+ REM is inherited by bash and drives the emitter's per-harness branch.
14
+ setlocal
15
+
16
+ REM Script to run, relative to this .cmd's own directory (%~dp0 ends with a backslash).
17
+ set "HOOK_SCRIPT=%~1"
18
+ if "%HOOK_SCRIPT%"=="" set "HOOK_SCRIPT=inject-using-gdd.sh"
19
+ if not "%~1"=="" shift
20
+
21
+ set "HOOK_PATH=%~dp0%HOOK_SCRIPT%"
22
+
23
+ REM Prefer bash on PATH; fall back to a typical Git-for-Windows install location.
24
+ where bash >nul 2>nul
25
+ if %ERRORLEVEL%==0 (
26
+ bash "%HOOK_PATH%" %*
27
+ ) else if exist "%ProgramFiles%\Git\bin\bash.exe" (
28
+ "%ProgramFiles%\Git\bin\bash.exe" "%HOOK_PATH%" %*
29
+ ) else (
30
+ REM No bash available: emit a valid empty SDK-shape JSON object so the
31
+ REM SessionStart pipeline still receives parseable output and never breaks.
32
+ echo {"additionalContext": ""}
33
+ )
34
+
35
+ endlocal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hegemonart/get-design-done",
3
- "version": "1.31.5",
3
+ "version": "1.32.0",
4
4
  "description": "A design-quality pipeline for AI coding agents: brief, plan, implement, and verify UI work against your design system.",
5
5
  "author": "Hegemon",
6
6
  "homepage": "https://github.com/hegemonart/get-design-done",
@@ -10,7 +10,7 @@
10
10
  "type": {
11
11
  "type": "string",
12
12
  "minLength": 1,
13
- "description": "Free-form event type identifier. Pre-registered seeds: state.mutation, state.transition, stage.entered, stage.exited, hook.fired, error, capability_gap."
13
+ "description": "Free-form event type identifier. Pre-registered seeds: state.mutation, state.transition, stage.entered, stage.exited, hook.fired, error, capability_gap, kfm-candidate, router_pick."
14
14
  },
15
15
  "timestamp": {
16
16
  "type": "string",
@@ -181,6 +181,57 @@
181
181
  }
182
182
  },
183
183
  "description": "Phase 30.5-03 D-06 kfm-candidate payload — 7 fields, additionalProperties: false. Validated when the envelope's type === 'kfm-candidate' via the allOf[1] conditional."
184
+ },
185
+ "RouterPickPayload": {
186
+ "type": "object",
187
+ "additionalProperties": false,
188
+ "required": [
189
+ "event_id",
190
+ "source",
191
+ "picked_skill",
192
+ "context_hash",
193
+ "rank",
194
+ "alternatives",
195
+ "ts"
196
+ ],
197
+ "properties": {
198
+ "event_id": {
199
+ "type": "string",
200
+ "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
201
+ "description": "UUIDv4 identifying this router_pick event. Stable across emit + read cycles."
202
+ },
203
+ "source": {
204
+ "type": "string",
205
+ "const": "router",
206
+ "description": "Phase 32-08 D-02 — the router_pick event class is emitted EXCLUSIVELY by the gdd-router skill at its resolved-pick point. No other producer is authorised."
207
+ },
208
+ "picked_skill": {
209
+ "type": "string",
210
+ "minLength": 1,
211
+ "description": "The skill or agent the router auto-picked for this intent. Phase 33 baselines per-skill auto-pick rates from this field (pick-rate regression)."
212
+ },
213
+ "context_hash": {
214
+ "type": "string",
215
+ "minLength": 1,
216
+ "description": "sha256 of the intent/context that drove the pick — NEVER the raw prompt (no PII, mirrors CapabilityGapPayload.context_hash discipline). Used by Phase 33 aggregation to cluster picks for the same context."
217
+ },
218
+ "rank": {
219
+ "type": "integer",
220
+ "minimum": 0,
221
+ "description": "Rank of the picked_skill among the candidates considered (0 = top pick). Lets Phase 33 distinguish confident top picks from close calls."
222
+ },
223
+ "alternatives": {
224
+ "type": "array",
225
+ "items": { "type": "string" },
226
+ "description": "Other candidate skill/agent names the router considered (names only — no scores, no prompt text). May be empty when the router had a single match. Surfaces which skills the router weighs but does not reach for."
227
+ },
228
+ "ts": {
229
+ "type": "string",
230
+ "format": "date-time",
231
+ "description": "ISO-8601 timestamp of the pick emission."
232
+ }
233
+ },
234
+ "description": "Phase 32-08 D-02 router_pick payload — 7 fields, additionalProperties: false, NO PII (context_hash only). Records which skill the router auto-picked per intent — the instrument that surfaces under-reached skills. Validated when the envelope's type === 'router_pick' via the allOf[2] conditional."
184
235
  }
185
236
  },
186
237
  "allOf": [
@@ -205,6 +256,17 @@
205
256
  "payload": { "$ref": "#/definitions/KfmCandidatePayload" }
206
257
  }
207
258
  }
259
+ },
260
+ {
261
+ "if": {
262
+ "properties": { "type": { "const": "router_pick" } },
263
+ "required": ["type"]
264
+ },
265
+ "then": {
266
+ "properties": {
267
+ "payload": { "$ref": "#/definitions/RouterPickPayload" }
268
+ }
269
+ }
208
270
  }
209
271
  ]
210
272
  }
@@ -8,13 +8,14 @@
8
8
  // Surface:
9
9
  // async getHealthChecks(rootDir) → { checks: HealthCheck[] }
10
10
  //
11
- // The 6 checks (in stable order) are:
11
+ // The 7 checks (in stable order) are:
12
12
  // 1. claude_md — CLAUDE.md presence
13
13
  // 2. planning_dir — .planning/ presence
14
14
  // 3. design_dir — .design/ presence
15
15
  // 4. package_json — package.json present AND parseable
16
16
  // 5. issue_reporter — kill-switch state (Plan 30-06 / D-08)
17
17
  // 6. figma_extract — extract readiness + Free-tier signal (Plan 31-09)
18
+ // 7. skill_discipline — using-gdd bootstrap + SessionStart inject (Plan 32-07)
18
19
  //
19
20
  // Check 5 was added in Plan 30-06 — surfaces the report-issue kill-switch
20
21
  // (env or config disable) so users can verify why the command is
@@ -34,6 +35,17 @@
34
35
  // logged, or placed in the detail. The Free-tier state is derived from a LOCAL
35
36
  // signal only (a prior pull's _meta.json recording a 403/skip on the Variables
36
37
  // endpoint) — never a live network call (health-mirror is pure read-only).
38
+ //
39
+ // Check 7 was added in Plan 32-07 — surfaces whether the skill-discipline
40
+ // bootstrap (Phase 32) is live so a user can confirm the using-gdd SessionStart
41
+ // inject is wired. The detail line is one of three exact strings:
42
+ // - "skill-discipline: ready" (using-gdd present AND hooks.json
43
+ // SessionStart wires inject-using-gdd.sh)
44
+ // - "skill-discipline: missing using-gdd" (skills/using-gdd/SKILL.md absent)
45
+ // - "skill-discipline: hook not wired" (skill present but no SessionStart
46
+ // inject-using-gdd entry)
47
+ // status: 'ok' when ready, 'warn' otherwise. PURE read-only (rootDir-relative
48
+ // file + JSON inspection only) — NEVER throws, NEVER networks.
37
49
 
38
50
  const fs = require('node:fs');
39
51
  const path = require('node:path');
@@ -174,9 +186,75 @@ async function getHealthChecks(rootDir) {
174
186
  checks.push({ name: 'figma_extract', status, detail });
175
187
  }
176
188
 
189
+ // 7. skill_discipline — using-gdd bootstrap + SessionStart inject (Plan 32-07).
190
+ // Reports exactly one of three states. PURE read-only: file existence +
191
+ // hooks.json JSON inspection only. NEVER throws, NEVER networks (every read
192
+ // is wrapped defensively like the figma_extract check above).
193
+ {
194
+ const skillPresent = fileExists(
195
+ path.join(rootDir, 'skills', 'using-gdd', 'SKILL.md')
196
+ );
197
+ const hookWired = skillPresent && sessionStartWiresInject(rootDir);
198
+
199
+ let detail;
200
+ let status;
201
+ if (!skillPresent) {
202
+ detail = 'skill-discipline: missing using-gdd';
203
+ status = 'warn';
204
+ } else if (!hookWired) {
205
+ detail = 'skill-discipline: hook not wired';
206
+ status = 'warn';
207
+ } else {
208
+ detail = 'skill-discipline: ready';
209
+ status = 'ok';
210
+ }
211
+ checks.push({ name: 'skill_discipline', status, detail });
212
+ }
213
+
177
214
  return { checks };
178
215
  }
179
216
 
217
+ /**
218
+ * Does hooks/hooks.json wire the inject-using-gdd SessionStart entry?
219
+ * PURE read-only JSON inspection. Defensive: a missing/garbage hooks.json or an
220
+ * unexpected shape returns false (→ "hook not wired") rather than throwing — the
221
+ * health probe must never crash on this check. NEVER networks.
222
+ *
223
+ * @param {string} rootDir project root passed to getHealthChecks
224
+ * @returns {boolean} true iff a SessionStart hook command references inject-using-gdd
225
+ */
226
+ function sessionStartWiresInject(rootDir) {
227
+ try {
228
+ const p = path.join(rootDir, 'hooks', 'hooks.json');
229
+ let hooks;
230
+ try {
231
+ hooks = JSON.parse(fs.readFileSync(p, 'utf8'));
232
+ } catch {
233
+ return false; // missing/garbage hooks.json → not wired
234
+ }
235
+ const sessionStart =
236
+ hooks && hooks.hooks && Array.isArray(hooks.hooks.SessionStart)
237
+ ? hooks.hooks.SessionStart
238
+ : [];
239
+ for (const entry of sessionStart) {
240
+ const inner = entry && Array.isArray(entry.hooks) ? entry.hooks : [];
241
+ for (const h of inner) {
242
+ if (
243
+ h &&
244
+ typeof h.command === 'string' &&
245
+ /inject-using-gdd/.test(h.command)
246
+ ) {
247
+ return true;
248
+ }
249
+ }
250
+ }
251
+ return false;
252
+ } catch {
253
+ // Absolute safety net — never crash the health probe on this check.
254
+ return false;
255
+ }
256
+ }
257
+
180
258
  /**
181
259
  * Free-tier signal (LOCAL only — never a network call). The raw-pull stage
182
260
  * (scripts/lib/figma-extract/pull.cjs) writes a _meta.json per file key under
@@ -251,8 +251,50 @@ var require_health_mirror = __commonJS({
251
251
  }
252
252
  checks.push({ name: "figma_extract", status, detail });
253
253
  }
254
+ {
255
+ const skillPresent = fileExists(
256
+ path.join(rootDir, "skills", "using-gdd", "SKILL.md")
257
+ );
258
+ const hookWired = skillPresent && sessionStartWiresInject(rootDir);
259
+ let detail;
260
+ let status;
261
+ if (!skillPresent) {
262
+ detail = "skill-discipline: missing using-gdd";
263
+ status = "warn";
264
+ } else if (!hookWired) {
265
+ detail = "skill-discipline: hook not wired";
266
+ status = "warn";
267
+ } else {
268
+ detail = "skill-discipline: ready";
269
+ status = "ok";
270
+ }
271
+ checks.push({ name: "skill_discipline", status, detail });
272
+ }
254
273
  return { checks };
255
274
  }
275
+ function sessionStartWiresInject(rootDir) {
276
+ try {
277
+ const p = path.join(rootDir, "hooks", "hooks.json");
278
+ let hooks;
279
+ try {
280
+ hooks = JSON.parse(fs.readFileSync(p, "utf8"));
281
+ } catch {
282
+ return false;
283
+ }
284
+ const sessionStart = hooks && hooks.hooks && Array.isArray(hooks.hooks.SessionStart) ? hooks.hooks.SessionStart : [];
285
+ for (const entry of sessionStart) {
286
+ const inner = entry && Array.isArray(entry.hooks) ? entry.hooks : [];
287
+ for (const h of inner) {
288
+ if (h && typeof h.command === "string" && /inject-using-gdd/.test(h.command)) {
289
+ return true;
290
+ }
291
+ }
292
+ }
293
+ return false;
294
+ } catch {
295
+ return false;
296
+ }
297
+ }
256
298
  function figmaVariablesBlockedLocally(rootDir) {
257
299
  try {
258
300
  const rawRoot = path.join(rootDir, ".figma-extract-cache", "raw");
@@ -63,4 +63,17 @@ After the consolidated audit summary has been printed (and any reflection-propos
63
63
 
64
64
  Written by `hooks/update-check.sh`; suppressed mid-pipeline and when the latest release is dismissed.
65
65
 
66
+ ## Rationalizations — Thought to Reality
67
+
68
+ The excuses an agent reaches for to skip or thin out an audit, and the drift each one misses:
69
+
70
+ | Thought | Reality |
71
+ |---------|---------|
72
+ | "The audit passed last cycle, I can skip it this cycle." | Per-cycle audit catches drift the prior pass couldn't see; a skipped review is exactly where regressions accumulate unnoticed. |
73
+ | "`--quick` is fine, integration isn't the concern here." | Dropping the integration-checker hides orphaned decisions — wiring breaks even when the 6-pillar score looks healthy. |
74
+ | "I can eyeball the scores instead of spawning the auditor." | The auditor's rubric scores six pillars consistently; an eyeballed review drifts toward whatever the agent already believes. |
75
+ | "Reflection proposals are optional polish, skip the reflector." | The reflector turns this cycle's learnings into next-cycle improvements; skipping it lets the same mistakes repeat. |
76
+ | "I'll modify the source while I'm in here fixing findings." | Audit is read-only by contract; editing source mid-audit invalidates the very scores you're producing. |
77
+ | "Retroactive mode is overkill for a finished cycle." | Retroactive verification is the only check on tasks that shipped without per-task verify — skipping it leaves a completed cycle unaudited. |
78
+
66
79
  ## AUDIT COMPLETE
@@ -92,4 +92,29 @@ Next: @get-design-done explore
92
92
  ━━━━━━━━━━━━━━━━━━━━━━━
93
93
  ```
94
94
 
95
+ ## Spec self-review (before transition)
96
+
97
+ Run this final spec-quality pass over `.design/BRIEF.md` before the brief→explore transition:
98
+ - Placeholder scan: no TBD / TODO / `<placeholder>` / lorem left in the artifact.
99
+ - Internal consistency: sections don't contradict each other.
100
+ - Scope check: nothing in the artifact exceeds (or silently drops) the agreed scope.
101
+ - Ambiguity check: every requirement/decision is specific enough to act on without a follow-up question.
102
+
103
+ <HARD-GATE>
104
+ Do NOT transition to explore (or invoke `/gdd:explore`) until the brief artifact (default `.design/BRIEF.md`) is committed AND the user has approved it. If this project uses a custom `.design` location, read the artifact path from `.design/STATE.md` rather than assuming the default.
105
+ </HARD-GATE>
106
+
107
+ ## Rationalizations — Thought to Reality
108
+
109
+ The excuses an agent invents to skip or shortcut the brief, and what each one actually costs the cycle:
110
+
111
+ | Thought | Reality |
112
+ |---------|---------|
113
+ | "This brief is too simple to need a problem statement." | Skip the brief = guess at requirements, then redesign mid-design when the real problem surfaces. |
114
+ | "The user told me what to build, I can skip the interview." | Unasked constraints (a11y, brand, stack) become rework — the five questions exist because each one has blown a past cycle. |
115
+ | "I'll capture success metrics later in verify." | Verify has nothing to check against; an un-metricked brief produces an un-verifiable cycle. |
116
+ | "Scope is obvious, I don't need an in/out line." | Undeclared scope is scope creep waiting to happen — the explore scan widens to fill the vacuum. |
117
+ | "I can answer all five questions for the user from context." | AskUserQuestion one-at-a-time exists because batched/assumed answers smuggle in wrong premises that compound downstream. |
118
+ | "STATE.md bootstrap can wait." | Every later MCP mutation requires STATE.md to exist; skipping the bootstrap hard-blocks explore on entry. |
119
+
95
120
  ## BRIEF COMPLETE
@@ -78,4 +78,21 @@ Print the `=== Design stage complete ===` summary (tasks complete/total, deviati
78
78
 
79
79
  After all tasks finish, if STATE.md `<connections>` has `figma: available`, offer the user the figma-write opt-in prompt (modes: annotate / tokenize / mappings, with optional `--dry-run`). Spawn `design-figma-writer` with the selected mode on "yes"; skip silently on "no". NEVER auto-run without confirmation. Full prompt + dispatch logic: `./design-procedure.md` §Figma Write Dispatch.
80
80
 
81
+ <HARD-GATE>
82
+ Do NOT transition to verify (or invoke `/gdd:verify`) until `.design/DESIGN-SUMMARY.md` is committed. If this project uses a custom `.design` location, read the artifact path from `.design/STATE.md` rather than assuming the default.
83
+ </HARD-GATE>
84
+
85
+ ## Rationalizations — Thought to Reality
86
+
87
+ The excuses an agent uses to cut corners during design implementation, and the cost of each:
88
+
89
+ | Thought | Reality |
90
+ |---------|---------|
91
+ | "I can skip planning for this small task and just implement it." | Plan-skipped tasks blow scope per cycle telemetry; the gate is for the typical case, not the exception. |
92
+ | "These two tasks touch nearby files but I'll run them in parallel anyway." | Overlapping `Touches:` in a parallel batch produce merge conflicts that silently drop one task's work — split into sequential sub-waves. |
93
+ | "Hardcoding this value is faster than wiring the token." | A hardcoded value is a stub the verifier catches as drift from the design tokens; you pay for it twice. |
94
+ | "I'll emit the `.stories.tsx` stub later when Storybook is back up." | The CSF stub must land with the component or the next cycle's visual-regression scope misses it entirely. |
95
+ | "This deviation is minor, I won't record a blocker." | An unrecorded deviation can't be resolved by a follow-up task, so it leaks into verify as an unexplained gap. |
96
+ | "Auto-mode means I can ignore the wave checkpoints." | Auto-mode skips prompts, not the wave structure; ignoring wave order still corrupts dependent-task ordering. |
97
+
81
98
  ## DESIGN COMPLETE
@@ -80,4 +80,17 @@ Cycle: <name or "default">
80
80
  - Do not run the interview yourself — always spawn the agent.
81
81
  - Do not touch files outside `.design/`.
82
82
 
83
+ ## Rationalizations — Thought to Reality
84
+
85
+ The shortcuts an agent takes during a discuss session, and what each one costs the decision record:
86
+
87
+ | Thought | Reality |
88
+ |---------|---------|
89
+ | "I'll ask all eight questions at once to save time." | Batched questions overwhelm the user; one-at-a-time keeps each decision clean and prevents coupled answers. |
90
+ | "I can run the interview inline instead of spawning the discussant." | The skill's contract is to always spawn the agent — running it yourself skips the discussant's mode handling and D-XX numbering. |
91
+ | "This answer is good enough, I'll record it as a decision without follow-up." | A vague answer ("modern", "clean") recorded as a D-XX locks in an undecided premise; reject and re-ask once. |
92
+ | "I'll batch all the new D-XX entries into STATE.md at the end." | Decisions written atomically per answer survive an interrupted session; batching loses everything if the session drops. |
93
+ | "The glossary term can wait until I write the summary." | CONTEXT.md is written immediately per term — a deferred glossary entry is a naming inconsistency the next cycle inherits. |
94
+ | "Every decision this session is worth an ADR." | ADRs require all three criteria (hard-to-reverse, surprising, real-tradeoff); auto-promoting routine choices buries the genuinely load-bearing ones. |
95
+
83
96
  ## DISCUSS COMMAND COMPLETE
@@ -85,4 +85,21 @@ Full interview protocol + JSON line schema: `./explore-procedure.md` §Step 3.
85
85
 
86
86
  Print: "=== Explore complete ===\nSaved: .design/DESIGN.md, .design/DESIGN-DEBT.md, .design/DESIGN-CONTEXT.md\nNext: @get-design-done plan".
87
87
 
88
+ <HARD-GATE>
89
+ Do NOT transition to plan (or invoke `/gdd:plan`) until BOTH `.design/DESIGN.md` AND `.design/DESIGN-CONTEXT.md` are committed AND the user has approved them. If this project uses a custom `.design` location, read the artifact paths from `.design/STATE.md` rather than assuming the default.
90
+ </HARD-GATE>
91
+
92
+ ## Rationalizations — Thought to Reality
93
+
94
+ The shortcut excuses an agent reaches for during explore, and the drift each one introduces:
95
+
96
+ | Thought | Reality |
97
+ |---------|---------|
98
+ | "I already know this codebase, I can skip the inventory scan." | An unscanned codebase hides the tokens/components you'll duplicate — the grep pass exists to stop you reinventing what's there. |
99
+ | "The six connection probes are noise, I'll assume Figma is off." | A skipped probe means a wrong connection assumption silently breaks the design stage's tool dispatch. |
100
+ | "`--skip-interview` is fine, the brief covered it." | The interview locks the gray areas the brief left fuzzy; skipping it ships undecided D-XX into planning. |
101
+ | "I'll batch all the interview questions to save round-trips." | Batched questions overwhelm the user and smuggle in coupled assumptions — one-at-a-time keeps each decision clean. |
102
+ | "DESIGN-DEBT.md is optional, the scan was clean enough." | Unrecorded debt resurfaces as an unexplained constraint three stages later with no provenance. |
103
+ | "Prior sketches and project conventions don't apply this cycle." | Ignored conventions get overridden by defaults, producing inconsistency the audit will flag against the rest of the system. |
104
+
88
105
  ## EXPLORE COMPLETE
@@ -63,6 +63,12 @@ After the health table, the `gdd_health` MCP surface (`scripts/lib/health-mirror
63
63
 
64
64
  Token PRESENCE only is detected (D-10) — the token value is never read, logged, or shown. The Free-tier signal is read from the local raw-pull cache only; no network call is made.
65
65
 
66
+ ## Skill-discipline bootstrap (skill_discipline)
67
+
68
+ The `gdd_health` MCP surface also reports a `skill_discipline` check (Phase 32) confirming the using-gdd SessionStart bootstrap is live — detail is one of three exact strings:
69
+ - `skill-discipline: ready` — `skills/using-gdd/SKILL.md` exists AND `hooks/hooks.json` SessionStart wires `inject-using-gdd.sh` (status `ok`).
70
+ - `skill-discipline: missing using-gdd` (skill absent) or `skill-discipline: hook not wired` (skill present, no SessionStart inject) — both `warn`.
71
+
66
72
  ## Check MCP registration (gdd-mcp)
67
73
 
68
74
  After the health table, inspect whether `gdd-mcp` (Phase 27.7+) is registered with any installed harness and render a one-line status row. Dismissable via `.design/config.json#mcp_nudge=false`. Non-blocking: failure paths render `MCP server: unknown` rather than crash. Full detection procedure (dismissal check, detection via `scripts/lib/install/mcp-register.cjs`, row rendering for claude/codex/both/neither, fallback) lives in `./health-mcp-detection.md`.
@@ -77,4 +77,29 @@ The next stage (design) calls `mcp__gdd_state__transition_stage` on entry — th
77
77
 
78
78
  Print: plan tasks (N waves, M total tasks), files written (`.design/DESIGN-PLAN.md`, plus `.design/DESIGN-RESEARCH.md` if research ran), next step `/get-design-done:design`.
79
79
 
80
+ ## Spec self-review (before transition)
81
+
82
+ Run this final spec-quality pass over `.design/DESIGN-PLAN.md` before the plan→design transition:
83
+ - Placeholder scan: no TBD / TODO / `<placeholder>` / lorem left in the artifact.
84
+ - Internal consistency: sections don't contradict each other.
85
+ - Scope check: nothing in the artifact exceeds (or silently drops) the agreed scope.
86
+ - Ambiguity check: every requirement/decision is specific enough to act on without a follow-up question.
87
+
88
+ <HARD-GATE>
89
+ Do NOT transition to design (or invoke `/gdd:design`) until `.design/DESIGN-PLAN.md` is committed AND the user has approved it. If this project uses a custom `.design` location, read the artifact path from `.design/STATE.md` rather than assuming the default.
90
+ </HARD-GATE>
91
+
92
+ ## Rationalizations — Thought to Reality
93
+
94
+ The reasons an agent gives to skip planning or rush DESIGN-PLAN.md, and what each one costs:
95
+
96
+ | Thought | Reality |
97
+ |---------|---------|
98
+ | "This change is small, I can design straight from DESIGN-CONTEXT.md." | Plan-skipped tasks blow scope per cycle telemetry; the plan gate is for the typical case, not the exception you think you're in. |
99
+ | "Pattern mapping is brownfield ceremony, I'll skip it." | Step 1.5 is mandatory because an unmapped brownfield is where the executor silently re-implements an existing pattern. |
100
+ | "The plan-checker will just rubber-stamp it, skip the spawn." | The checker's 5 dimensions (coverage, wave order, must-have derivation) catch the gaps you can't see in your own plan. |
101
+ | "I'll let the planner infer wave ordering at design time." | Unordered waves serialize work that could parallelize — or worse, run dependent tasks concurrently and corrupt the tree. |
102
+ | "Research is overkill for this scope." | The complexity heuristic exists precisely because agents under-estimate scope; skipping research on a 3+-scope domain guarantees a mid-design surprise. |
103
+ | "I can record decisions in DESIGN-PLAN.md prose instead of D-XX." | Prose decisions never reach STATE.md, so verify's integration-checker can't trace them and flags them orphaned. |
104
+
80
105
  ## PLAN COMPLETE
@@ -79,6 +79,10 @@ If `.design/budget.json` is missing, assume defaults from `reference/config-sche
79
79
 
80
80
  When the router cannot resolve `intent-string` to a known agent (no `description` match, no `default-tier` rule, no path-selection fallback), emit ONE `capability_gap` event with `source: "router"` before returning the conservative-fallback JSON. Feeds Phase 29 Stage-0 telemetry — see `./capability-gap-emitter.md` for the synchronous Node snippet, semantic notes (suggested_kind = `"agent"`, MCP-probe exclusion per D-08, back-compat invariant on router output), and the opaque-extras payload routing through `appendChainEvent`.
81
81
 
82
+ ## Emitting router_pick on a resolved pick
83
+
84
+ When the router DID resolve a pick — it has the `path`/`complexity_class`/`resolved_models` decision and is about to return the decision JSON — emit ONE `router_pick` event (`source: "router"`) recording which skill/agent was auto-picked, as the last step before returning. Side-effect only; the output JSON contract is UNCHANGED. Feeds the D-02 under-reached-skill instrument (Phase 33 baselines per-skill pick rates) — see `./router-pick-emitter.md` for the synchronous Node snippet, the 7-field no-PII payload (context_hash only — never the raw prompt), and the opaque-extras routing through `appendChainEvent`.
85
+
82
86
  ## Non-Goals
83
87
 
84
88
  The router does not: (a) make a model call, (b) write files, (c) enforce budget caps (that's the hook's job), (d) learn from history (Phase 11 reflector territory per D-07).
@@ -0,0 +1,78 @@
1
+ # gdd-router — router_pick emitter (Phase 32-08 / D-02)
2
+
3
+ Co-located reference for `skills/router/SKILL.md` — split out per the Phase 28.5
4
+ contract (router SKILL ≤100 lines) and the Phase 28.6 co-location pattern (same
5
+ convention as the sibling `./capability-gap-emitter.md`).
6
+
7
+ ## When to emit
8
+
9
+ When the router resolves an intent to a concrete pick — i.e. it has selected the
10
+ `path` / `complexity_class` / `resolved_models` decision and is about to return
11
+ its decision JSON — emit ONE `router_pick` event recording WHICH skill/agent it
12
+ auto-picked. Emit exactly once per resolved pick, as the LAST step before
13
+ returning the decision JSON to the caller.
14
+
15
+ This is the D-02 router_pick instrument: GDD routes by description-match but has
16
+ no record of what the router actually reaches for, so there is no data on
17
+ under-reached skills. Phase 33 reads these events from the chain file
18
+ (`.design/gep/events.jsonl`) to baseline per-skill auto-pick rates (the
19
+ "pick-rate regression" expansion in the ROADMAP).
20
+
21
+ `router_pick` is NOT `capability_gap`: emit `router_pick` when the router DID
22
+ resolve a pick; emit `capability_gap` (see `./capability-gap-emitter.md`) only
23
+ when it could not resolve the intent at all. They are disjoint surfaces.
24
+
25
+ ## Synchronous emitter snippet
26
+
27
+ Builds the 7-field `RouterPickPayload` and writes it via `appendChainEvent`.
28
+ The intent is hashed — the raw prompt is NEVER stored (no PII). `picked_skill`,
29
+ `rank`, and `alternatives` come from the router's resolved decision:
30
+
31
+ ```bash
32
+ node -e '
33
+ const { appendChainEvent } = require("./scripts/lib/event-chain.cjs");
34
+ const { createHash, randomUUID } = require("node:crypto");
35
+ const intent = process.env.GDD_INTENT || "";
36
+ const payload = {
37
+ event_id: randomUUID(),
38
+ source: "router",
39
+ picked_skill: process.env.GDD_PICKED_SKILL || "",
40
+ context_hash: createHash("sha256").update(intent).digest("hex"),
41
+ rank: Number(process.env.GDD_PICK_RANK || 0),
42
+ alternatives: (process.env.GDD_ALTERNATIVES || "").split(",").filter(Boolean),
43
+ ts: new Date().toISOString(),
44
+ };
45
+ appendChainEvent({
46
+ agent: "router",
47
+ outcome: "router_pick",
48
+ payload,
49
+ type: "router_pick",
50
+ timestamp: new Date().toISOString(),
51
+ sessionId: process.env.GDD_SESSION_ID || "router-cli",
52
+ });
53
+ '
54
+ ```
55
+
56
+ `GDD_PICKED_SKILL` is the resolved pick; `GDD_PICK_RANK` is its rank among
57
+ candidates (0 = top pick); `GDD_ALTERNATIVES` is a comma-separated list of the
58
+ OTHER candidate skill/agent names the router considered (names only — no scores,
59
+ no prompt text). `GDD_INTENT` is hashed in-process and is never written to disk.
60
+
61
+ ## Notes
62
+
63
+ - **No PII**: only `context_hash` (sha256 of the intent) is stored — never the
64
+ raw prompt or intent string. The `RouterPickPayload` is
65
+ `additionalProperties: false`, so a stray `raw_prompt` field would be rejected
66
+ by `events.schema.json` validation. This mirrors `capability_gap`'s hash
67
+ discipline.
68
+ - **Router output JSON contract is UNCHANGED** — `router_pick` is a SIDE EFFECT,
69
+ not a new output field. Back-compat is preserved exactly as the existing
70
+ `## Output schema versioning` table in `SKILL.md` guarantees; the emitter runs
71
+ AFTER the decision is computed and does not alter the returned blob.
72
+ - The 7-field payload flows through `appendChainEvent`'s opaque-extras pattern
73
+ verbatim; the chain row carries `type`, `timestamp`, `sessionId`, `payload` as
74
+ opaque extras and is projected back to the events-schema envelope by Phase 33
75
+ aggregation (same projection the capability_gap aggregation uses).
76
+ - Validated against the additive `RouterPickPayload` branch (allOf[2]) in
77
+ `reference/schemas/events.schema.json` — see
78
+ `test/suite/router-pick-event.test.cjs`.
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: using-gdd
3
+ description: "Use when starting any GDD session — establishes how to find and apply GDD skills."
4
+ disable-model-invocation: true
5
+ ---
6
+ <SUBAGENT-STOP>
7
+
8
+ # Using GDD
9
+
10
+ This is the bootstrap discipline contract for every Get Design Done session. Read it
11
+ first; it tells you how to find and apply the right GDD skill before you act.
12
+
13
+ ## The 1% rule
14
+
15
+ **If you think there is even a 1% chance a skill might apply, you ABSOLUTELY MUST invoke the skill.**
16
+
17
+ In GDD, almost every request maps to a pipeline stage — brief, explore, plan, design,
18
+ verify — or to a cross-cutting skill (discuss, audit, style, darkmode). When in doubt,
19
+ search for and read the skill's body. The cost of reading a skill is trivial; the cost of
20
+ free-handing a stage is rework, scope creep, and a broken pipeline state.
21
+
22
+ ## Red flags — Thought → Reality
23
+
24
+ When you catch yourself thinking any of the following, STOP and check for a skill.
25
+
26
+ | Thought | Reality |
27
+ | --- | --- |
28
+ | This is just a simple design question. | Questions are tasks. Check for a skill. |
29
+ | I'll just tweak the CSS directly. | Token changes go through the pipeline — check /gdd:design. |
30
+ | I already know the codebase, skip explore. | Explore probes connections you haven't re-checked this cycle. |
31
+ | This change is too small to plan. | Plan-skipped tasks blow scope per cycle telemetry. Run /gdd:plan. |
32
+ | I can write the brief later. | No brief means no shared problem statement — /gdd:brief comes first. |
33
+ | The user clearly wants X, I'll skip discuss. | Ambiguity hides here. /gdd:discuss surfaces the real constraint. |
34
+ | I'll verify by eyeballing it. | Verification is a stage with criteria — run /gdd:verify, don't guess. |
35
+ | It's obviously a dark-mode tweak. | Color-scheme work has its own skill — check /gdd:darkmode. |
36
+ | Let me just compare these two designs quickly. | Comparison is an audit task — /gdd:compare has the rubric. |
37
+ | This is a one-off, no skill needed. | "One-off" is the most common rationalization in the telemetry. Check anyway. |
38
+ | I'll refactor the style tokens by hand. | /gdd:style owns token edits so the pipeline stays consistent. |
39
+ | The audit can wait until after I ship. | An un-audited cycle is an unverified cycle — /gdd:audit before close. |
40
+
41
+ ## Skill priority order
42
+
43
+ When more than one skill could apply, resolve in this order:
44
+
45
+ 1. **Process** — brief / explore / discuss. Establish the problem and context first.
46
+ 2. **Implementation** — design / style / darkmode. Only after process is settled.
47
+ 3. **Audit** — verify / compare / audit. Close the loop before declaring done.
48
+
49
+ Never run an Implementation skill before the Process skills that gate it have produced
50
+ their artifact. Never declare a cycle complete without an Audit skill.
51
+
52
+ ## Instruction priority
53
+
54
+ When instructions conflict, obey this precedence (highest first):
55
+
56
+ 1. **The user's CLAUDE.md** — project- and user-level directives always win.
57
+ 2. **GDD skills** — the skill body is the source of truth for how a stage runs.
58
+ 3. **Defaults** — your own general training and habits come last.
59
+
60
+ If a GDD skill contradicts the user's CLAUDE.md, the CLAUDE.md wins and you flag the
61
+ conflict. If your instinct contradicts a GDD skill, the skill wins.
62
+
63
+ ## GDD pipeline flow
64
+
65
+ The core flow is **Brief → Explore → Plan → Design → Verify**, with branch points:
66
+
67
+ - **Brief** captures the problem (`/gdd:brief`). Branch: a rough idea can sketch or spike
68
+ off the brief before exploration; a changed problem loops back via `--re-brief`.
69
+ - **Explore** scans the codebase and connections (`/gdd:explore`) — even on a familiar
70
+ repo, because connections drift each cycle.
71
+ - **Plan** decomposes work into tasks (`/gdd:plan`). Skipping it is the top cause of scope
72
+ blow-up; small tasks still get a plan.
73
+ - **Design** implements (`/gdd:design`, with `/gdd:style` and `/gdd:darkmode` as
74
+ implementation peers). Implementation never runs ahead of an approved plan.
75
+ - **Verify** checks against criteria (`/gdd:verify`), then `/gdd:audit` / `/gdd:compare`
76
+ close the loop. On pass the cycle completes; on fail it loops back to the failing stage.
77
+
78
+ `/gdd:discuss` runs alongside any stage to resolve ambiguity before it propagates.
@@ -93,4 +93,21 @@ Full prompts + branching: `./verify-procedure.md` §Step 3.
93
93
 
94
94
  Print the `=== Verify complete ===` summary (status, gap counts, agent paths, next-step suggestion) from `./verify-procedure.md` §After Completion.
95
95
 
96
+ <HARD-GATE>
97
+ Do NOT mark the cycle complete until the user has reviewed `.design/DESIGN-VERIFICATION.md`. If this project uses a custom `.design` location, read the artifact path from `.design/STATE.md` rather than assuming the default.
98
+ </HARD-GATE>
99
+
100
+ ## Rationalizations — Thought to Reality
101
+
102
+ The reasons an agent gives to skip or weaken verification, and what each one lets through:
103
+
104
+ | Thought | Reality |
105
+ |---------|---------|
106
+ | "The implementation looks right, I can skip the verifier spawn." | Skipping verification ships unchecked must-haves; the 5-phase verifier exists to catch what "looks right" misses. |
107
+ | "The integration-checker is redundant with the auditor." | The auditor scores quality; the integration-checker proves each D-XX is actually wired — an orphaned decision passes the audit but fails the product. |
108
+ | "These gaps are minor, I'll accept-as-is without a blocker." | Accept-as-is without recording the unresolved gaps erases the trail; the next cycle re-discovers them from scratch. |
109
+ | "The quality gate timed out, I'll treat that as a pass." | Timeout is a signal, not a pass — masking it lets a genuinely failing gate slip through to ship. |
110
+ | "I'll loop the fixer a fourth time to clear the last gap." | The 3-iteration cap exists because a gap surviving three fixes is a design problem, not a code problem — save and escalate. |
111
+ | "Post-handoff bundles don't need the faithfulness check." | Skipping the handoff-faithfulness section means a divergence from the source design ships unflagged. |
112
+
96
113
  ## VERIFY COMPLETE