@hegemonart/get-design-done 1.20.0 → 1.22.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.
Files changed (69) hide show
  1. package/.claude-plugin/marketplace.json +9 -12
  2. package/.claude-plugin/plugin.json +8 -31
  3. package/CHANGELOG.md +200 -0
  4. package/README.md +48 -7
  5. package/bin/gdd-sdk +55 -0
  6. package/hooks/_hook-emit.js +81 -0
  7. package/hooks/gdd-bash-guard.js +8 -0
  8. package/hooks/gdd-decision-injector.js +2 -0
  9. package/hooks/gdd-protected-paths.js +8 -0
  10. package/hooks/gdd-trajectory-capture.js +64 -0
  11. package/hooks/hooks.json +9 -0
  12. package/package.json +19 -47
  13. package/reference/codex-tools.md +53 -0
  14. package/reference/gemini-tools.md +53 -0
  15. package/reference/registry.json +14 -0
  16. package/scripts/cli/gdd-events.mjs +283 -0
  17. package/scripts/e2e/run-headless.ts +514 -0
  18. package/scripts/lib/cli/commands/audit.ts +382 -0
  19. package/scripts/lib/cli/commands/init.ts +217 -0
  20. package/scripts/lib/cli/commands/query.ts +329 -0
  21. package/scripts/lib/cli/commands/run.ts +656 -0
  22. package/scripts/lib/cli/commands/stage.ts +468 -0
  23. package/scripts/lib/cli/index.ts +167 -0
  24. package/scripts/lib/cli/parse-args.ts +336 -0
  25. package/scripts/lib/connection-probe/index.cjs +263 -0
  26. package/scripts/lib/context-engine/index.ts +116 -0
  27. package/scripts/lib/context-engine/manifest.ts +69 -0
  28. package/scripts/lib/context-engine/truncate.ts +282 -0
  29. package/scripts/lib/context-engine/types.ts +59 -0
  30. package/scripts/lib/discuss-parallel-runner/aggregator.ts +448 -0
  31. package/scripts/lib/discuss-parallel-runner/discussants.ts +430 -0
  32. package/scripts/lib/discuss-parallel-runner/index.ts +223 -0
  33. package/scripts/lib/discuss-parallel-runner/types.ts +184 -0
  34. package/scripts/lib/event-chain.cjs +177 -0
  35. package/scripts/lib/event-stream/index.ts +31 -1
  36. package/scripts/lib/event-stream/reader.ts +139 -0
  37. package/scripts/lib/event-stream/types.ts +155 -1
  38. package/scripts/lib/event-stream/writer.ts +65 -8
  39. package/scripts/lib/explore-parallel-runner/index.ts +294 -0
  40. package/scripts/lib/explore-parallel-runner/mappers.ts +290 -0
  41. package/scripts/lib/explore-parallel-runner/synthesizer.ts +295 -0
  42. package/scripts/lib/explore-parallel-runner/types.ts +139 -0
  43. package/scripts/lib/harness/detect.ts +90 -0
  44. package/scripts/lib/harness/index.ts +64 -0
  45. package/scripts/lib/harness/tool-map.ts +142 -0
  46. package/scripts/lib/init-runner/index.ts +396 -0
  47. package/scripts/lib/init-runner/researchers.ts +245 -0
  48. package/scripts/lib/init-runner/scaffold.ts +224 -0
  49. package/scripts/lib/init-runner/synthesizer.ts +224 -0
  50. package/scripts/lib/init-runner/types.ts +143 -0
  51. package/scripts/lib/logger/index.ts +251 -0
  52. package/scripts/lib/logger/sinks.ts +269 -0
  53. package/scripts/lib/logger/types.ts +110 -0
  54. package/scripts/lib/pipeline-runner/human-gate.ts +134 -0
  55. package/scripts/lib/pipeline-runner/index.ts +527 -0
  56. package/scripts/lib/pipeline-runner/stage-handlers.ts +339 -0
  57. package/scripts/lib/pipeline-runner/state-machine.ts +144 -0
  58. package/scripts/lib/pipeline-runner/types.ts +183 -0
  59. package/scripts/lib/redact.cjs +122 -0
  60. package/scripts/lib/session-runner/errors.ts +406 -0
  61. package/scripts/lib/session-runner/index.ts +715 -0
  62. package/scripts/lib/session-runner/transcript.ts +189 -0
  63. package/scripts/lib/session-runner/types.ts +144 -0
  64. package/scripts/lib/tool-scoping/index.ts +219 -0
  65. package/scripts/lib/tool-scoping/parse-agent-tools.ts +207 -0
  66. package/scripts/lib/tool-scoping/stage-scopes.ts +139 -0
  67. package/scripts/lib/tool-scoping/types.ts +77 -0
  68. package/scripts/lib/trajectory/index.cjs +126 -0
  69. package/scripts/lib/transports/ws.cjs +179 -0
@@ -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.20.0"
8
+ "version": "1.22.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.20.0",
15
+ "version": "1.22.0",
16
16
  "author": {
17
17
  "name": "hegemonart"
18
18
  },
@@ -62,16 +62,13 @@
62
62
  "cost-optimization",
63
63
  "cache-aware",
64
64
  "budget",
65
- "component-specs",
66
- "design-system-benchmarks",
67
- "component-conformance",
68
- "convergence-detector",
69
- "i18n",
70
- "user-research",
71
- "information-architecture",
72
- "form-patterns",
73
- "data-viz",
74
- "platforms"
65
+ "headless",
66
+ "cli",
67
+ "codex",
68
+ "gemini",
69
+ "mcp",
70
+ "parallel-agents",
71
+ "agent-sdk"
75
72
  ]
76
73
  }
77
74
  ]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "get-design-done",
3
3
  "short_name": "gdd",
4
- "version": "1.20.0",
4
+ "version": "1.22.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.",
6
6
  "author": {
7
7
  "name": "hegemonart",
@@ -53,36 +53,13 @@
53
53
  "cost-optimization",
54
54
  "cache-aware",
55
55
  "budget",
56
- "iconography",
57
- "brand-voice",
58
- "performance-budget",
59
- "framer-motion",
60
- "motion-design",
61
- "micro-polish",
62
- "surfaces",
63
- "make-interfaces-feel-better",
64
- "palette-catalog",
65
- "style-vocabulary",
66
- "industry-palettes",
67
- "ui-style-vocabulary",
68
- "variable-fonts",
69
- "container-queries",
70
- "view-transitions",
71
- "motion-vocabulary",
72
- "motion-easings",
73
- "transition-taxonomy",
74
- "gesture-mechanics",
75
- "clip-path-animation",
76
- "component-specs",
77
- "design-system-benchmarks",
78
- "component-conformance",
79
- "convergence-detector",
80
- "i18n",
81
- "user-research",
82
- "information-architecture",
83
- "form-patterns",
84
- "data-viz",
85
- "platforms"
56
+ "headless",
57
+ "cli",
58
+ "codex",
59
+ "gemini",
60
+ "mcp",
61
+ "parallel-agents",
62
+ "agent-sdk"
86
63
  ],
87
64
  "skills": [
88
65
  "./skills/"
package/CHANGELOG.md CHANGED
@@ -4,6 +4,206 @@ All notable changes to get-design-done are documented here. Versions follow [sem
4
4
 
5
5
  ---
6
6
 
7
+ ## [1.22.0] — 2026-04-25
8
+
9
+ Phase 22 GDD SDK Observability milestone — the single-typed `BaseEvent` envelope from Phase 20 grows into a queryable, redacted, transport-able observability layer with tail/grep/WebSocket consumers and a causal event chain. 10 plans (22-01 through 22-10), additive — every Phase 20 + Phase 21 consumer keeps working unchanged.
10
+
11
+ ### Added
12
+
13
+ - **Expanded event-type registry** — 17 new pre-registered subtypes alongside
14
+ the 6 from Phase 20: `wave.started`, `wave.completed`, `blocker.added`,
15
+ `decision.added`, `must_have.added`, `parallelism.verdict`, `cost.update`,
16
+ `rate_limit`, `api.retry`, `compact.boundary`, `mcp.probe`,
17
+ `reflection.proposed`, `connection.status_change`, `tool_call.started`,
18
+ `tool_call.completed`, `agent.spawn`, `agent.outcome`. The envelope
19
+ remains open (`type: string`); the `KnownEvent` union is an additive
20
+ overlay for typed `switch` consumers. Runtime `KNOWN_EVENT_TYPES` list
21
+ exported for the CLI's `list-types` subcommand. (Plan 22-01)
22
+
23
+ - **Secret scrubber** — `scripts/lib/redact.cjs` deep-walks every event
24
+ payload and replaces secret-shaped strings with `[REDACTED:<type>]`
25
+ placeholders. Patterns: `sk-ant-…` (anthropic), `sk_live_…` (stripe),
26
+ `xox[baprs]-…` (slack), `ghp_…` (github_pat), `AKIA…` (aws), generic
27
+ `sk-…`, `eyJ…` JWTs, and full `-----BEGIN/END-----` PEM blocks.
28
+ Wired into `EventWriter.serialize()` so every event hitting disk and
29
+ every bus subscriber sees the scrubbed form — single rule everywhere,
30
+ no escape hatch. (Plan 22-02)
31
+
32
+ - **Per-tool-call trajectory stream** — `.design/telemetry/trajectories/<cycle>.jsonl`
33
+ receives one line per agent tool-use:
34
+ `{ts, agent, tool, args_hash, result_hash, latency_ms, status}`.
35
+ Args + result are sha256-prefix-hashed (16 chars) — line size stays
36
+ bounded; prompt content stays de-identified. Captured by the new
37
+ PostToolUse:Agent hook `hooks/gdd-trajectory-capture.js`. (Plan 22-03)
38
+
39
+ - **Append-only event chain** — `.design/gep/events.jsonl` (gep =
40
+ "GDD Event Provenance"). One line per causal hop: `{event_id,
41
+ parent_event_id, ts, agent, decision_refs, outcome, rollback_reason?}`.
42
+ `appendChainEvent()` auto-generates UUIDs; `walkParents()` traces a
43
+ row up to its root for `/gdd:audit --retroactive`. Cycle-safe; skips
44
+ invalid lines; lives separately from the firehose so audits don't
45
+ scan unrelated rows. (Plan 22-04)
46
+
47
+ - **Typed event reader + aggregator** — `readEvents({path, type,
48
+ predicate, since, until})` returns an async streaming iterator over
49
+ `events.jsonl` (readline + createReadStream — no full-file load,
50
+ GB-scale logs OK). `aggregate()` rolls events up by type, stage,
51
+ cycle, agent + totals (count, error_count, truncated_count). Exposed
52
+ from the public event-stream API. (Plan 22-05)
53
+
54
+ - **CLI transport** — `gdd-events` bin entry, subcommands:
55
+ `tail [--follow]` (250ms-poll follow mode, no native inotify dep);
56
+ `grep <terms…>` with hand-rolled filter language
57
+ (`type=foo`, `payload.x.y=bar`, `!type=baz`, multiple = AND);
58
+ `cat` pretty-print with timestamp+type prefix; `list-types` runtime
59
+ registry dump; `serve` for the WebSocket transport. (Plan 22-06)
60
+
61
+ - **WebSocket transport** — `scripts/lib/transports/ws.cjs` exposes
62
+ `startServer({port, token, tailFrom?, subscribe?})`. Loaded via
63
+ `probeOptional('ws')` — clear install hint when absent. Auth:
64
+ `Authorization: Bearer <token>` on the upgrade; mismatched →
65
+ HTTP 401 close. Tail replay sends `tailFrom`'s contents to new
66
+ clients before subscribing them to the live bus. Fire-and-forget
67
+ delivery; closed sockets dropped silently. `ws@8` declared as
68
+ optional dep. (Plan 22-07)
69
+
70
+ - **Connection probe primitive** — `scripts/lib/connection-probe/`
71
+ exposes `probe({name, cmd, timeout, retries, fallback})` →
72
+ `{status: 'ok'|'degraded'|'down', latency_ms, attempts,
73
+ fallback_used, error?}`. Backoff between retries via
74
+ `jittered-backoff.cjs`. State persisted at
75
+ `.design/telemetry/connection-state.json` (atomic .tmp+rename).
76
+ Status transitions emit `connection.status_change` events through a
77
+ caller-supplied `emit` callback — transitions only, not every probe.
78
+ Replaces ad-hoc bash probe snippets in `connections/`. (Plan 22-08)
79
+
80
+ - **Hook → event-stream wire-in** — new `hooks/_hook-emit.js` shared
81
+ helper wraps `appendEvent()` in try/catch (hooks must NEVER throw on
82
+ telemetry failure). Wired hooks emit `hook.fired` events on every
83
+ decision: `gdd-bash-guard` (allow/block + severity + pattern),
84
+ `gdd-protected-paths` (allow/block + matched glob),
85
+ `gdd-decision-injector` (inject/no-hits + backend label).
86
+ Trajectory-capture (Plan 22-03) already emits via its own path.
87
+ Additive — zero behavior change to existing hook contracts. (Plan 22-09)
88
+
89
+ ### Changed
90
+
91
+ - `EventWriter.serialize()` now runs `redact()` on the event before
92
+ JSON-stringifying. Persisted form is the canonical scrubbed form.
93
+ All 27 Phase 20 event-stream tests still pass. (Plan 22-02 wire-in)
94
+
95
+ - `hooks.json` registers a new `PostToolUse:Agent` matcher pointing at
96
+ `gdd-trajectory-capture.js`. The existing `PreToolUse:Agent`
97
+ budget-enforcer is unaffected. (Plan 22-03 registration)
98
+
99
+ ### Tests
100
+
101
+ - `tests/event-types-registry.test.ts` — registry expansion (4 tests)
102
+ - `tests/redact.test.cjs` — secret scrubber (12 tests)
103
+ - `tests/event-stream-redact-integration.test.ts` — write-time wire-in (2 tests)
104
+ - `tests/trajectory-capture.test.cjs` — module + hook subprocess (7 tests)
105
+ - `tests/event-chain.test.cjs` — chain + walk + cycle defense (10 tests)
106
+ - `tests/event-reader.test.ts` — reader + aggregator (8 tests)
107
+ - `tests/cli-events.test.cjs` — CLI subcommands + filter language (10 tests)
108
+ - `tests/ws-transport.test.cjs` — WebSocket auth + replay + live (5 + 1 skip)
109
+ - `tests/connection-probe-primitive.test.cjs` — retry + fallback + emit (9 tests)
110
+ - `tests/hook-emit-wire.test.cjs` — bash-guard + protected-paths emission (4 tests)
111
+ - `tests/phase-22-baseline.test.cjs` — Phase 22 regression baseline (12 tests)
112
+
113
+ Total: 84 new tests. All Phase 20/21 tests still green.
114
+
115
+ ### Deferred
116
+
117
+ - Grafana / Prometheus exporter (out of scope; code-primitive
118
+ observability shipped first).
119
+ - Event-stream compaction / retention (`events.jsonl` grows unbounded;
120
+ Phase 22.x if needed).
121
+ - Replay-on-subscribe semantics (bus stays live-only; transports that
122
+ want replay read `events.jsonl` directly, then subscribe live).
123
+ - Wire-in for `gdd-mcp-circuit-breaker.js`, `budget-enforcer.ts`,
124
+ `context-exhaustion.ts`, `gdd-read-injection-scanner.ts` — flow is
125
+ more intricate; follow-up phase.
126
+
127
+ ---
128
+
129
+ ## [1.21.0] — 2026-04-24
130
+
131
+ Phase 21 GDD SDK Headless milestone — the plugin now runs unchanged on Claude Code, OpenAI Codex CLI, and Gemini CLI, and ships a full `gdd-sdk` CLI that executes the design pipeline without a harness. 12 plans (21-01 through 21-12), 50+ commits, 936 tests.
132
+
133
+ ### Added
134
+
135
+ - **Headless SDK** — new `bin/gdd-sdk` CLI that runs the full design pipeline
136
+ without Claude Code. Subcommands: `run`, `stage <name>`, `query <op>`,
137
+ `audit`, `init`. Publishes as `gdd-sdk` in `package.json` `bin`. See
138
+ `docs/HEADLESS.md` (Phase 23 deliverable) for CI integration guidance.
139
+ - **Session runner** (`scripts/lib/session-runner/`) — typed wrapper around
140
+ `@anthropic-ai/claude-agent-sdk` with USD/token budget caps, turn caps,
141
+ transcript capture, structured error mapping via `gdd-errors` taxonomy.
142
+ Emits `session.started`, `session.completed`, `session.budget_exceeded`
143
+ events on the shared event stream.
144
+ - **Context engine** (`scripts/lib/context-engine/`) — per-stage file
145
+ manifest + markdown-aware truncation that preserves frontmatter, every
146
+ heading, and the first paragraph of each section for files larger than
147
+ 8 KiB. Keeps session prompts within budget without dropping load-bearing
148
+ context.
149
+ - **Tool scoping** (`scripts/lib/tool-scoping/`) — per-stage allowed-tools
150
+ enforcement at session creation. Verify is read-only; Explore adds web;
151
+ Design permits shell mutations. Per-agent frontmatter overrides via
152
+ `parseAgentTools()` for agent-level deviations.
153
+ - **Structured logger** (`scripts/lib/logger/`) — leveled (debug/info/warn/
154
+ error) with JSONL output in headless mode, ANSI-colored stderr in
155
+ interactive mode. `warn`/`error` also emit `ErrorEvent` on the event
156
+ stream for CI consumers.
157
+ - **Pipeline runner** (`scripts/lib/pipeline-runner/`) — brief → explore →
158
+ plan → design → verify state machine with retry-once, halt logic,
159
+ human-gate callbacks, config-driven step skipping. Emits
160
+ `pipeline.started`, `pipeline.completed`, `pipeline.halted`.
161
+ - **Explore parallel runner** (`scripts/lib/explore-parallel-runner/`) —
162
+ 4 mappers (token, component-taxonomy, a11y, visual-hierarchy) concurrent
163
+ with streaming synthesizer. Honors `parallelism_safe` agent frontmatter
164
+ for opt-in isolation.
165
+ - **Discuss parallel runner** (`scripts/lib/discuss-parallel-runner/`) —
166
+ N discussant variants (user-journey, technical-constraint, brand-fit,
167
+ accessibility) concurrent, aggregator dedupes and clusters questions.
168
+ - **`gdd-sdk init`** (`scripts/lib/init-runner/`) — new-project bootstrap
169
+ spawning 4 parallel researchers (design-system-audit, brand-context,
170
+ accessibility-baseline, competitive-references) + synthesizer producing
171
+ `.design/DESIGN-CONTEXT.md` draft.
172
+ - **Cross-harness portability** (`scripts/lib/harness/`) — the plugin now
173
+ runs unchanged on Claude Code, OpenAI Codex CLI, and Gemini CLI. Ships
174
+ `reference/codex-tools.md`, `reference/gemini-tools.md`, `AGENTS.md`
175
+ (Codex), `GEMINI.md` (Gemini). The `gdd-state` MCP server works on all
176
+ three harnesses; harness detection is runtime-driven.
177
+ - **E2E headless integration test** — `tests/e2e-headless.test.ts` with a
178
+ dry-run variant (always runs) and a live variant (gated on
179
+ `ANTHROPIC_API_KEY`). CI workflow gains an `e2e-headless` job.
180
+ - **Phase 21 regression baseline** at `test-fixture/baselines/phase-21/` —
181
+ directory list, module list, agent list, connections list, CLI
182
+ subcommand list, event-type list. Enforced by
183
+ `tests/phase-21-baseline.test.cjs`.
184
+
185
+ ### Changed
186
+
187
+ - `@anthropic-ai/claude-agent-sdk` added as a runtime dependency (was
188
+ previously only referenced in docs).
189
+ - `package.json` `bin` now exports `gdd-sdk` in addition to
190
+ `get-design-done` and `gdd-state-mcp`.
191
+ - `package.json` `files` adds `bin/` to the publish include list so the
192
+ `gdd-sdk` trampoline ships with the npm package.
193
+ - `package.json` `keywords` expanded with headless / CLI / cross-harness
194
+ tokens (`headless`, `cli`, `codex`, `gemini`, `mcp`, `parallel-agents`,
195
+ `agent-sdk`) for npm search surface.
196
+
197
+ ### Infrastructure
198
+
199
+ - New regression baseline at `test-fixture/baselines/phase-21/`.
200
+ - CI workflow gains an `e2e-headless` job (dry-run on every PR; live on
201
+ main-branch push with `ANTHROPIC_API_KEY` secret).
202
+ - `tests/semver-compare.test.cjs` `OFF_CADENCE_VERSIONS` now includes
203
+ `1.21.0` as the second off-cadence minor bump after `1.20.0`.
204
+
205
+ ---
206
+
7
207
  ## [1.20.0] — 2026-04-24
8
208
 
9
209
  Phase 20 SDK foundation milestone — the shift from "design pipeline" to "typed SDK + MCP server + resilience primitives + event stream". 16 plans (20-00 through 20-15), 50+ commits, 645+ tests.
package/README.md CHANGED
@@ -29,7 +29,7 @@ npx @hegemonart/get-design-done@latest
29
29
 
30
30
  <br>
31
31
 
32
- [Why I Built This](#why-i-built-this) · [How It Works](#how-it-works) · [Canvas Tools](#ai-native-canvas-tools) · [Component Generators](#component-generators) · [Commands](#commands) · [Connections](#connections) · [Why It Works](#why-it-works)
32
+ [Why I Built This](#why-i-built-this) · [How It Works](#how-it-works) · [Headless SDK](#headless-sdk) · [Canvas Tools](#ai-native-canvas-tools) · [Component Generators](#component-generators) · [Commands](#commands) · [Connections](#connections) · [Why It Works](#why-it-works)
33
33
 
34
34
  </div>
35
35
 
@@ -104,17 +104,27 @@ Built-in quality gates catch real problems: Handoff Faithfulness scoring on Clau
104
104
  - **Component generators** — 21st.dev Magic MCP adds a prior-art gate before any greenfield build; Magic Patterns generates DS-aware components with a `preview_url` for visual verification. Both feed into a shared `design-component-generator` agent.
105
105
  - **Twelve tool connections** — Four new connections (paper.design, pencil.dev, 21st.dev, Magic Patterns) join the original eight. All are optional; the pipeline degrades gracefully to fallbacks when any connection is unavailable.
106
106
 
107
- ## What's New in v1.20.0
107
+ ## What's New in v1.21.0
108
108
 
109
- **Resilience primitives** (headline upgrade) — the pipeline now survives Anthropic API rate limits, 429 responses, and context-overflow errors without manual restart. New modules: jittered backoff, rate-guard, error-classifier, iteration-budget. See [`reference/error-recovery.md`](reference/error-recovery.md) for the recovery protocol. Connection probes and long-running loops use these primitives instead of fixed sleeps.
109
+ **Headless SDK** (headline upgrade) — the plugin now ships a `gdd-sdk` CLI that runs the full design pipeline without Claude Code. Five subcommands (`run`, `stage`, `query`, `audit`, `init`) work on any CI runner with Node 22+ and an `ANTHROPIC_API_KEY`. See the [Headless SDK](#headless-sdk) section below for examples.
110
110
 
111
- **Typed state core** — `.design/STATE.md` mutations are now lockfile-safe. Parallel executors can concurrently update `task_progress` and `<blockers>` on the same file with zero corruption validated by a 4-way race-condition test (2000 concurrent ops, <60s). The legacy `ReadregexWrite` pattern is deprecated in favor of the typed API.
111
+ **Parallel researchers** — four new runners execute concurrent specialized agents with a streaming synthesizer: `explore-parallel-runner` (4 mappers: token, component-taxonomy, a11y, visual-hierarchy), `discuss-parallel-runner` (N discussants: user-journey, technical-constraint, brand-fit, accessibility), and `init-runner` (4 researchers for `gdd-sdk init` bootstrap). A `pipeline-runner` state machine orchestrates brief exploreplan design verify with retry-once, halt logic, and human-gate callbacks.
112
112
 
113
- **`gdd-state` MCP server** — 11 typed tools (`gdd_state__get`, `__update_progress`, `__transition_stage`, `__add_blocker`, `__resolve_blocker`, `__add_decision`, `__add_must_have`, `__set_status`, `__checkpoint`, `__probe_connections`, `__frontmatter_update`) replace ad-hoc STATE.md edits. Every mutation emits a typed event to `.design/telemetry/events.jsonl`, giving downstream consumers a structured audit trail next to the existing `costs.jsonl` cost stream.
113
+ **Cross-harness portability** — the plugin runs unchanged on Claude Code, OpenAI Codex CLI, and Gemini CLI. Codex auto-loads [`AGENTS.md`](AGENTS.md); Gemini auto-loads [`GEMINI.md`](GEMINI.md). Tool-name translations live in [`reference/codex-tools.md`](reference/codex-tools.md) and [`reference/gemini-tools.md`](reference/gemini-tools.md). The `gdd-state` MCP server works on all three harnesses.
114
114
 
115
- **TypeScript foundation** — `tsc --noEmit` typechecks the whole SDK; JSON schemas codegen to `reference/schemas/generated.d.ts`; hooks + Tier-1 scripts migrated to `.ts` and executed directly via Node 22 `--experimental-strip-types` (no bundler step).
115
+ **Session primitives** — `session-runner` (typed wrapper around `@anthropic-ai/claude-agent-sdk` with USD/token budget caps, turn caps, transcript capture), `context-engine` (per-stage file manifest + markdown-aware truncation preserving frontmatter, headings, and first paragraph of each section), `tool-scoping` (per-stage allowed-tools enforcement with per-agent frontmatter overrides), and a structured `logger` (leveled, JSONL in headless mode, ANSI-colored in interactive mode).
116
116
 
117
- **Prompt sanitizer** — strips interactive-only constructs (AskUserQuestion, STOP, `/gdd:` slash commands) from skill bodies. Preparatory work for headless-runner support.
117
+ **E2E headless integration test** — `tests/e2e-headless.test.ts` with a dry-run variant (always runs) and a live variant gated on `ANTHROPIC_API_KEY`. CI gains an `e2e-headless` job.
118
+
119
+ ### Previously in v1.20.0
120
+
121
+ **Resilience primitives** — the pipeline survives Anthropic API rate limits, 429 responses, and context-overflow errors without manual restart. Modules: jittered backoff, rate-guard, error-classifier, iteration-budget. See [`reference/error-recovery.md`](reference/error-recovery.md).
122
+
123
+ **Typed state core** — `.design/STATE.md` mutations are lockfile-safe. Parallel executors concurrently update `task_progress` and `<blockers>` on the same file with zero corruption (validated by 4-way race-condition test, 2000 concurrent ops, <60s).
124
+
125
+ **`gdd-state` MCP server** — 11 typed tools (`gdd_state__get`, `__update_progress`, `__transition_stage`, `__add_blocker`, `__resolve_blocker`, `__add_decision`, `__add_must_have`, `__set_status`, `__checkpoint`, `__probe_connections`, `__frontmatter_update`) replace ad-hoc STATE.md edits. Every mutation emits a typed event to `.design/telemetry/events.jsonl`.
126
+
127
+ **TypeScript foundation** — `tsc --noEmit` typechecks the whole SDK; JSON schemas codegen to `reference/schemas/generated.d.ts`; hooks + Tier-1 scripts migrated to `.ts` and executed directly via Node 22 `--experimental-strip-types`.
118
128
 
119
129
  ---
120
130
 
@@ -490,6 +500,37 @@ The watcher writes `.design/authority-report.md` — new entries classified into
490
500
 
491
501
  ---
492
502
 
503
+ ## Headless SDK
504
+
505
+ Run the full GDD pipeline without Claude Code:
506
+
507
+ ```bash
508
+ npx gdd-sdk init # bootstrap a new project
509
+ npx gdd-sdk run # full pipeline (brief → verify)
510
+ npx gdd-sdk stage explore --parallel # single stage with parallel mappers
511
+ npx gdd-sdk query position # typed STATE.md read
512
+ npx gdd-sdk audit --baseline <dir> # regression check
513
+ ```
514
+
515
+ Requires Node 22+ and an `ANTHROPIC_API_KEY`. Works on any CI runner.
516
+
517
+ Internally the SDK stitches together the Phase-21 runner modules:
518
+ `session-runner` (budget + turn cap + transcript), `context-engine` (per-stage
519
+ file manifest + markdown truncation), `tool-scoping` (per-stage allowed-tools),
520
+ `pipeline-runner` (brief → verify state machine with retry-once + human-gate
521
+ callbacks), and `explore-parallel` / `discuss-parallel` / `init` for the
522
+ concurrent researcher stages.
523
+
524
+ ### Cross-harness
525
+
526
+ The plugin runs unchanged on Claude Code, OpenAI Codex CLI, and Gemini CLI.
527
+ See [`reference/codex-tools.md`](reference/codex-tools.md) and
528
+ [`reference/gemini-tools.md`](reference/gemini-tools.md) for the tool
529
+ translations; Codex auto-loads [`AGENTS.md`](AGENTS.md) and Gemini auto-loads
530
+ [`GEMINI.md`](GEMINI.md). The `gdd-state` MCP server works on all three.
531
+
532
+ ---
533
+
493
534
  ## AI-Native Canvas Tools
494
535
 
495
536
  get-design-done integrates with canvas tools that treat the design canvas as both source AND destination — enabling a full canvas→code→verify→canvas round-trip.
package/bin/gdd-sdk ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ // bin/gdd-sdk — Plan 21-09 Task 7 (SDK-21).
3
+ //
4
+ // CJS trampoline: spawns `node --experimental-strip-types` against the
5
+ // real TS entry point in `scripts/lib/cli/index.ts` and forwards argv +
6
+ // exit code. Windows-compatible (npm's generated .cmd shim on Windows
7
+ // has no way to inject the --experimental-strip-types flag otherwise).
8
+ //
9
+ // Why a trampoline:
10
+ // POSIX shebangs can use `#!/usr/bin/env -S node --experimental-strip-types`,
11
+ // but Windows cmd.exe does not honor shebangs. npm's auto-generated
12
+ // .cmd shim invokes plain `node bin/gdd-sdk` without passing the
13
+ // experimental flag. The trampoline re-launches node with the flag
14
+ // explicitly so both platforms end up at the same TS entry.
15
+
16
+ 'use strict';
17
+
18
+ const { spawn } = require('node:child_process');
19
+ const path = require('node:path');
20
+
21
+ const entry = path.resolve(
22
+ __dirname,
23
+ '..',
24
+ 'scripts',
25
+ 'lib',
26
+ 'cli',
27
+ 'index.ts',
28
+ );
29
+
30
+ const child = spawn(
31
+ process.execPath,
32
+ ['--experimental-strip-types', entry, ...process.argv.slice(2)],
33
+ { stdio: 'inherit', shell: false },
34
+ );
35
+
36
+ child.on('exit', (code, signal) => {
37
+ if (signal) {
38
+ // Re-raise the signal to ourselves so the parent shell sees the same
39
+ // termination mode (e.g., Ctrl+C propagates as SIGINT exit).
40
+ try {
41
+ process.kill(process.pid, signal);
42
+ } catch {
43
+ process.exit(1);
44
+ }
45
+ return;
46
+ }
47
+ process.exit(typeof code === 'number' ? code : 0);
48
+ });
49
+
50
+ child.on('error', (err) => {
51
+ // Failure to spawn node itself — extremely rare; surface to stderr.
52
+ // eslint-disable-next-line no-console
53
+ console.error('gdd-sdk: failed to launch TypeScript entry:', err.message);
54
+ process.exit(3);
55
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * hooks/_hook-emit.js — shared `hook.fired` emitter for Phase 22 wire-in
3
+ * (Plan 22-09).
4
+ *
5
+ * Hooks must NEVER throw on telemetry failure — a broken event stream
6
+ * cannot block a tool call. This helper wraps appendEvent in try/catch
7
+ * and silently swallows.
8
+ *
9
+ * Why a wrapper instead of importing directly:
10
+ * * Centralizes the try/catch so each hook stays terse.
11
+ * * Loads the .ts event-stream lazily — hooks invoked via plain `node`
12
+ * (no --experimental-strip-types) just no-op on telemetry instead
13
+ * of crashing. The hooks.json registrations vary on whether they
14
+ * pass --experimental-strip-types, and we don't want to forbid
15
+ * plain-node invocation paths.
16
+ * * Single place to add structured event sinks later (e.g. mirror to
17
+ * CLI transport) without touching every hook file.
18
+ *
19
+ * Usage:
20
+ * const { emitHookFired } = require('./_hook-emit.js');
21
+ * // …decision computed…
22
+ * emitHookFired('budget-enforcer', 'allow');
23
+ */
24
+
25
+ 'use strict';
26
+
27
+ let cachedAppendEvent = null;
28
+ let resolutionAttempted = false;
29
+
30
+ /**
31
+ * Lazy-resolve `appendEvent` — only loads the event-stream module the
32
+ * first time a hook fires. Falls back to a no-op if the module is not
33
+ * loadable in the current runtime (e.g. plain `node` without
34
+ * --experimental-strip-types).
35
+ *
36
+ * @returns {(ev: unknown) => void}
37
+ */
38
+ function getAppendEvent() {
39
+ if (cachedAppendEvent !== null || resolutionAttempted) {
40
+ return cachedAppendEvent || (() => {});
41
+ }
42
+ resolutionAttempted = true;
43
+ try {
44
+ // event-stream/index.ts requires --experimental-strip-types. Try
45
+ // require()'ing — if Node refuses to parse `.ts`, we silently fall
46
+ // back to no-op.
47
+ // eslint-disable-next-line node/no-missing-require, global-require
48
+ cachedAppendEvent = require('../scripts/lib/event-stream/index.ts').appendEvent;
49
+ return cachedAppendEvent;
50
+ } catch {
51
+ cachedAppendEvent = null;
52
+ return () => {};
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Emit a `hook.fired` event. Silent on every failure mode.
58
+ *
59
+ * @param {string} hookName
60
+ * @param {string} decision
61
+ * @param {Record<string, unknown>} [extras] — opaque additional payload fields
62
+ */
63
+ function emitHookFired(hookName, decision, extras) {
64
+ try {
65
+ const appendEvent = getAppendEvent();
66
+ const payload = { hook: hookName, decision };
67
+ if (extras && typeof extras === 'object') {
68
+ Object.assign(payload, extras);
69
+ }
70
+ appendEvent({
71
+ type: 'hook.fired',
72
+ timestamp: new Date().toISOString(),
73
+ sessionId: process.env.GDD_SESSION_ID || 'hook',
74
+ payload,
75
+ });
76
+ } catch {
77
+ /* hooks must never throw on telemetry */
78
+ }
79
+ }
80
+
81
+ module.exports = { emitHookFired };
@@ -15,6 +15,7 @@
15
15
 
16
16
  const path = require('path');
17
17
  const { match } = require(path.join(__dirname, '..', 'scripts', 'lib', 'dangerous-patterns.cjs'));
18
+ const { emitHookFired } = require('./_hook-emit.js'); // Plan 22-09 wire-in
18
19
 
19
20
  async function main() {
20
21
  let buf = '';
@@ -22,11 +23,13 @@ async function main() {
22
23
 
23
24
  let payload;
24
25
  try { payload = JSON.parse(buf || '{}'); } catch {
26
+ emitHookFired('gdd-bash-guard', 'allow', { reason: 'parse-error' });
25
27
  process.stdout.write(JSON.stringify({ continue: true }));
26
28
  return;
27
29
  }
28
30
 
29
31
  if (payload?.tool_name && payload.tool_name !== 'Bash') {
32
+ emitHookFired('gdd-bash-guard', 'allow', { reason: 'non-bash-tool' });
30
33
  process.stdout.write(JSON.stringify({ continue: true }));
31
34
  return;
32
35
  }
@@ -34,6 +37,10 @@ async function main() {
34
37
  const command = payload?.tool_input?.command ?? '';
35
38
  const r = match(command);
36
39
  if (r.matched) {
40
+ emitHookFired('gdd-bash-guard', 'block', {
41
+ severity: r.severity,
42
+ pattern: r.pattern,
43
+ });
37
44
  process.stdout.write(JSON.stringify({
38
45
  continue: false,
39
46
  stopReason: `gdd-bash-guard: dangerous command blocked (${r.severity}): ${r.description} [${r.pattern}]`,
@@ -41,6 +48,7 @@ async function main() {
41
48
  return;
42
49
  }
43
50
 
51
+ emitHookFired('gdd-bash-guard', 'allow', { reason: 'no-match' });
44
52
  process.stdout.write(JSON.stringify({ continue: true }));
45
53
  }
46
54
 
@@ -203,10 +203,12 @@ async function main() {
203
203
  const backendLabel = BACKEND || (useRgGlobal ? 'ripgrep' : 'node-grep');
204
204
  const block = buildRecallBlock(hits, basename, backendLabel);
205
205
  if (!block) {
206
+ try { require('./_hook-emit.js').emitHookFired('gdd-decision-injector', 'no-hits', { backend: backendLabel }); } catch { /* swallow */ }
206
207
  process.stdout.write(JSON.stringify({ continue: true }));
207
208
  return;
208
209
  }
209
210
 
211
+ try { require('./_hook-emit.js').emitHookFired('gdd-decision-injector', 'inject', { backend: backendLabel, hit_count: hits.length }); } catch { /* swallow */ }
210
212
  process.stdout.write(JSON.stringify({
211
213
  continue: true,
212
214
  hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: block },
@@ -98,6 +98,11 @@ async function main() {
98
98
  : cand.replace(/\\/g, '/');
99
99
  const r = matches(rel, protectedPaths);
100
100
  if (r.matched) {
101
+ try {
102
+ require('./_hook-emit.js').emitHookFired('gdd-protected-paths', 'block', {
103
+ path: rel, pattern: r.pattern,
104
+ });
105
+ } catch { /* swallow */ }
101
106
  process.stdout.write(JSON.stringify({
102
107
  continue: false,
103
108
  stopReason: `gdd-protected-paths: '${rel}' is a protected path (matched '${r.pattern}'). To override, lift the path from the default glob list or explicitly edit via an approved workflow (e.g., /gdd:update, plan execution).`,
@@ -106,6 +111,9 @@ async function main() {
106
111
  }
107
112
  }
108
113
 
114
+ try {
115
+ require('./_hook-emit.js').emitHookFired('gdd-protected-paths', 'allow');
116
+ } catch { /* swallow */ }
109
117
  process.stdout.write(JSON.stringify({ continue: true }));
110
118
  }
111
119