@hegemonart/get-design-done 1.31.0 → 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.
Files changed (180) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +75 -0
  4. package/NOTICE +262 -0
  5. package/README.md +13 -1
  6. package/SKILL.md +4 -0
  7. package/agents/design-authority-watcher.md +1 -1
  8. package/agents/perf-analyzer.md +2 -2
  9. package/bin/gdd-mcp +78 -0
  10. package/bin/gdd-sdk +34 -24
  11. package/bin/gdd-state-mcp +78 -0
  12. package/{README.de.md → docs/i18n/README.de.md} +1 -1
  13. package/{README.fr.md → docs/i18n/README.fr.md} +1 -1
  14. package/{README.it.md → docs/i18n/README.it.md} +1 -1
  15. package/{README.ja.md → docs/i18n/README.ja.md} +1 -1
  16. package/{README.ko.md → docs/i18n/README.ko.md} +1 -1
  17. package/{README.zh-CN.md → docs/i18n/README.zh-CN.md} +1 -1
  18. package/hooks/_hook-emit.js +1 -1
  19. package/hooks/budget-enforcer.ts +5 -5
  20. package/hooks/context-exhaustion.ts +2 -2
  21. package/hooks/gdd-precompact-snapshot.js +3 -3
  22. package/hooks/gdd-read-injection-scanner.ts +2 -2
  23. package/hooks/gdd-sessionstart-recap.js +1 -1
  24. package/hooks/gdd-turn-closeout.js +1 -1
  25. package/hooks/hooks.json +9 -0
  26. package/hooks/inject-using-gdd.sh +72 -0
  27. package/hooks/run-hook.cmd +35 -0
  28. package/package.json +20 -9
  29. package/recipes/.gitkeep +0 -0
  30. package/reference/schemas/events.schema.json +63 -1
  31. package/reference/schemas/recipe.schema.json +33 -0
  32. package/scripts/cli/gdd-events.mjs +5 -5
  33. package/scripts/lib/cache/gdd-cache-manager.cjs +1 -1
  34. package/scripts/lib/cli/index.ts +22 -160
  35. package/scripts/lib/connection-probe/index.cjs +1 -1
  36. package/scripts/lib/discuss-parallel-runner/aggregator.ts +1 -1
  37. package/scripts/lib/discuss-parallel-runner/index.ts +1 -1
  38. package/scripts/lib/error-classifier.cjs +24 -227
  39. package/scripts/lib/event-stream/index.ts +25 -193
  40. package/scripts/lib/gdd-errors/index.ts +24 -213
  41. package/scripts/lib/gdd-state/index.ts +23 -161
  42. package/scripts/lib/health-mirror/index.cjs +79 -1
  43. package/scripts/lib/iteration-budget.cjs +23 -199
  44. package/scripts/lib/jittered-backoff.cjs +24 -107
  45. package/scripts/lib/lockfile.cjs +23 -195
  46. package/scripts/lib/logger/index.ts +1 -1
  47. package/scripts/lib/parallelism-engine/concurrency-tuner.cjs +1 -1
  48. package/scripts/lib/perf-analyzer/index.cjs +1 -1
  49. package/scripts/lib/pipeline-runner/index.ts +4 -4
  50. package/scripts/lib/pipeline-runner/state-machine.ts +1 -1
  51. package/scripts/lib/prompt-dedup/index.cjs +1 -1
  52. package/scripts/lib/rate-guard.cjs +2 -2
  53. package/scripts/lib/recipe-loader.cjs +142 -0
  54. package/scripts/lib/session-runner/errors.ts +3 -3
  55. package/scripts/lib/session-runner/index.ts +3 -3
  56. package/scripts/lib/session-runner/transcript.ts +1 -1
  57. package/scripts/lib/tool-scoping/index.ts +1 -1
  58. package/scripts/mcp-servers/gdd-mcp/server.ts +29 -311
  59. package/scripts/mcp-servers/gdd-state/server.ts +28 -282
  60. package/sdk/README.md +45 -0
  61. package/{scripts/lib → sdk}/cli/commands/audit.ts +3 -3
  62. package/{scripts/lib → sdk}/cli/commands/init.ts +3 -3
  63. package/{scripts/lib → sdk}/cli/commands/query.ts +4 -4
  64. package/{scripts/lib → sdk}/cli/commands/run.ts +5 -5
  65. package/{scripts/lib → sdk}/cli/commands/stage.ts +5 -5
  66. package/sdk/cli/index.js +8091 -0
  67. package/sdk/cli/index.ts +172 -0
  68. package/{scripts/lib → sdk}/cli/parse-args.ts +2 -2
  69. package/{scripts/lib/gdd-errors → sdk/errors}/classification.ts +1 -1
  70. package/sdk/errors/index.ts +218 -0
  71. package/{scripts/lib → sdk}/event-stream/emitter.ts +1 -1
  72. package/sdk/event-stream/index.ts +197 -0
  73. package/{scripts/lib → sdk}/event-stream/reader.ts +1 -1
  74. package/{scripts/lib → sdk}/event-stream/types.ts +2 -2
  75. package/{scripts/lib → sdk}/event-stream/writer.ts +1 -1
  76. package/sdk/index.ts +19 -0
  77. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/README.md +3 -3
  78. package/sdk/mcp/gdd-mcp/server.js +1966 -0
  79. package/sdk/mcp/gdd-mcp/server.ts +325 -0
  80. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_cycle_recap.ts +3 -3
  81. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_decisions_list.ts +2 -2
  82. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_events_tail.ts +3 -3
  83. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_health.ts +2 -2
  84. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_intel_get.ts +2 -2
  85. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_learnings_digest.ts +2 -2
  86. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_phase_current.ts +2 -2
  87. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_phases_list.ts +2 -2
  88. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_plans_list.ts +2 -2
  89. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_reflections_latest.ts +2 -2
  90. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_status.ts +3 -3
  91. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_telemetry_query.ts +3 -3
  92. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/index.ts +2 -2
  93. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/shared.ts +3 -3
  94. package/sdk/mcp/gdd-state/server.js +2790 -0
  95. package/sdk/mcp/gdd-state/server.ts +294 -0
  96. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_blocker.ts +3 -3
  97. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_decision.ts +3 -3
  98. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_must_have.ts +3 -3
  99. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/checkpoint.ts +2 -2
  100. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/frontmatter_update.ts +2 -2
  101. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/get.ts +3 -3
  102. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/index.ts +1 -1
  103. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/probe_connections.ts +3 -3
  104. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/resolve_blocker.ts +3 -3
  105. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/set_status.ts +2 -2
  106. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/shared.ts +8 -8
  107. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/transition_stage.ts +4 -4
  108. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/update_progress.ts +2 -2
  109. package/sdk/primitives/error-classifier.cjs +232 -0
  110. package/sdk/primitives/iteration-budget.cjs +205 -0
  111. package/sdk/primitives/jittered-backoff.cjs +112 -0
  112. package/sdk/primitives/lockfile.cjs +201 -0
  113. package/{scripts/lib/gdd-state → sdk/state}/gates.ts +1 -1
  114. package/sdk/state/index.ts +167 -0
  115. package/{scripts/lib/gdd-state → sdk/state}/lockfile.ts +1 -1
  116. package/{scripts/lib/gdd-state → sdk/state}/mutator.ts +1 -1
  117. package/{scripts/lib/gdd-state → sdk/state}/parser.ts +1 -1
  118. package/{scripts/lib/gdd-state → sdk/state}/types.ts +4 -4
  119. package/skills/audit/SKILL.md +13 -0
  120. package/skills/brief/SKILL.md +25 -0
  121. package/skills/design/SKILL.md +17 -0
  122. package/skills/discuss/SKILL.md +13 -0
  123. package/skills/explore/SKILL.md +17 -0
  124. package/skills/health/SKILL.md +6 -0
  125. package/skills/plan/SKILL.md +25 -0
  126. package/skills/quality-gate/SKILL.md +2 -2
  127. package/skills/router/SKILL.md +4 -0
  128. package/skills/router/router-pick-emitter.md +78 -0
  129. package/skills/using-gdd/SKILL.md +78 -0
  130. package/skills/verify/SKILL.md +17 -0
  131. package/scripts/aggregate-agent-metrics.ts +0 -282
  132. package/scripts/bootstrap-manifest.txt +0 -3
  133. package/scripts/bootstrap.sh +0 -80
  134. package/scripts/build-distribution-bundles.cjs +0 -549
  135. package/scripts/build-intel.cjs +0 -486
  136. package/scripts/codegen-schema-types.ts +0 -149
  137. package/scripts/detect-stale-refs.cjs +0 -107
  138. package/scripts/e2e/run-headless.ts +0 -514
  139. package/scripts/extract-changelog-section.cjs +0 -58
  140. package/scripts/gsd-cleanup-incubator.cjs +0 -367
  141. package/scripts/injection-patterns.cjs +0 -58
  142. package/scripts/lint-agentskills-spec.cjs +0 -457
  143. package/scripts/release-smoke-test.cjs +0 -200
  144. package/scripts/rollback-release.sh +0 -42
  145. package/scripts/run-injection-scanner-ci.cjs +0 -83
  146. package/scripts/tests/test-authority-rejected-kinds.sh +0 -58
  147. package/scripts/tests/test-authority-watcher-diff.sh +0 -113
  148. package/scripts/tests/test-motion-provenance.sh +0 -64
  149. package/scripts/validate-frontmatter.ts +0 -409
  150. package/scripts/validate-incubator-scope.cjs +0 -133
  151. package/scripts/validate-schemas.ts +0 -401
  152. package/scripts/validate-skill-length.cjs +0 -283
  153. package/scripts/verify-version-sync.cjs +0 -30
  154. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_cycle_recap.schema.json +0 -0
  155. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_decisions_list.schema.json +0 -0
  156. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_events_tail.schema.json +0 -0
  157. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_health.schema.json +0 -0
  158. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_intel_get.schema.json +0 -0
  159. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_learnings_digest.schema.json +0 -0
  160. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_phase_current.schema.json +0 -0
  161. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_phases_list.schema.json +0 -0
  162. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_plans_list.schema.json +0 -0
  163. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_reflections_latest.schema.json +0 -0
  164. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_status.schema.json +0 -0
  165. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_telemetry_query.schema.json +0 -0
  166. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_blocker.schema.json +0 -0
  167. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_decision.schema.json +0 -0
  168. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_must_have.schema.json +0 -0
  169. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/checkpoint.schema.json +0 -0
  170. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/frontmatter_update.schema.json +0 -0
  171. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/get.schema.json +0 -0
  172. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/probe_connections.schema.json +0 -0
  173. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/resolve_blocker.schema.json +0 -0
  174. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/set_status.schema.json +0 -0
  175. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/transition_stage.schema.json +0 -0
  176. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/update_progress.schema.json +0 -0
  177. /package/{scripts/lib → sdk/primitives}/error-classifier.d.cts +0 -0
  178. /package/{scripts/lib → sdk/primitives}/iteration-budget.d.cts +0 -0
  179. /package/{scripts/lib → sdk/primitives}/jittered-backoff.d.cts +0 -0
  180. /package/{scripts/lib → sdk/primitives}/lockfile.d.cts +0 -0
@@ -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
@@ -1,282 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * aggregate-agent-metrics.ts — Incremental per-agent aggregator.
4
- *
5
- * Reads: .design/telemetry/costs.jsonl (append-only ledger from
6
- * hooks/budget-enforcer.js)
7
- * agents/{agent}.md (frontmatter source for default-tier, parallel-safe,
8
- * reads-only, typical-duration-seconds)
9
- * Writes: .design/agent-metrics.json (atomic overwrite via tmp-file + rename)
10
- * .design/telemetry/phase-totals.json (same, WR-02)
11
- *
12
- * Invoked:
13
- * 1. Detached child of hooks/budget-enforcer.js after every telemetry write.
14
- * 2. Directly by /gdd:optimize skill as an explicit refresh step.
15
- * 3. Manually: `node --experimental-strip-types scripts/aggregate-agent-metrics.ts`
16
- * 4. With `--help` to print usage (used by the Plan 20-00 smoke check).
17
- *
18
- * OPT-09 contract: fields must match Phase 11 reflector's expectations.
19
- *
20
- * Converted from scripts/aggregate-agent-metrics.js in Plan 20-00 (Tier-1).
21
- * Behavior preserved verbatim.
22
- */
23
-
24
- import {
25
- existsSync,
26
- mkdirSync,
27
- readFileSync,
28
- writeFileSync,
29
- renameSync,
30
- } from 'node:fs';
31
- import { join, dirname, basename } from 'node:path';
32
-
33
- // Generated-type import (unused at runtime, erased by strip-types) to satisfy
34
- // Plan 20-00's requirement that every Tier-1 TS file participates in the
35
- // codegen graph. We pick AuthoritySnapshotSchema as a stable anchor and
36
- // re-export for downstream callers.
37
- import type { AuthoritySnapshotSchema } from '../reference/schemas/generated.js';
38
- export type { AuthoritySnapshotSchema };
39
-
40
- const CWD: string = process.cwd();
41
- const TELEMETRY_PATH: string = join(CWD, '.design', 'telemetry', 'costs.jsonl');
42
- const METRICS_PATH: string = join(CWD, '.design', 'agent-metrics.json');
43
- const PHASE_TOTALS_PATH: string = join(CWD, '.design', 'telemetry', 'phase-totals.json');
44
- const AGENTS_DIR: string = join(CWD, 'agents');
45
-
46
- /**
47
- * Subset of the agent-markdown frontmatter we care about. `null` means the
48
- * field is absent or unparseable (aggregator is tolerant — degraded mode
49
- * preferred over hard-fail per OPT-09).
50
- */
51
- interface AgentFrontmatter {
52
- default_tier: string | null;
53
- parallel_safe: boolean | null;
54
- reads_only: boolean | null;
55
- typical_duration_seconds: number | null;
56
- }
57
-
58
- /** ---- frontmatter reader (no YAML dep) ---- */
59
- function readAgentFrontmatter(agentName: string): Partial<AgentFrontmatter> {
60
- const p: string = join(AGENTS_DIR, `${agentName}.md`);
61
- if (!existsSync(p)) return {};
62
- try {
63
- const content: string = readFileSync(p, 'utf8');
64
- const fm = content.match(/^---\s*\n([\s\S]*?)\n---/);
65
- if (!fm) return {};
66
- const body: string = fm[1] ?? '';
67
- const get = (key: string): string | null => {
68
- const m = body.match(new RegExp(`^${key}:\\s*"?([^"\\n]+)"?`, 'm'));
69
- return m && m[1] !== undefined ? m[1].trim() : null;
70
- };
71
- const defaultTier: string | null = get('default-tier');
72
- const parallelSafe: string | null = get('parallel-safe');
73
- const readsOnly: string | null = get('reads-only');
74
- const typicalDuration: string | null = get('typical-duration-seconds');
75
- return {
76
- default_tier: defaultTier ?? null,
77
- parallel_safe: parallelSafe === null ? null : /^(true|yes)$/i.test(parallelSafe),
78
- reads_only: readsOnly === null ? null : /^(true|yes)$/i.test(readsOnly),
79
- typical_duration_seconds:
80
- typicalDuration === null ? null : Number(typicalDuration) || null,
81
- };
82
- } catch {
83
- return {};
84
- }
85
- }
86
-
87
- /**
88
- * Shape of a single row in .design/telemetry/costs.jsonl. Mirrors the OPT-09
89
- * schema: nine mandatory fields + four optional diagnostic fields. Unknown
90
- * keys are tolerated (Phase 11 reflector ignores them).
91
- */
92
- export interface CostRow {
93
- ts?: string;
94
- agent?: string;
95
- tier?: string;
96
- tokens_in?: number | string;
97
- tokens_out?: number | string;
98
- cache_hit?: boolean;
99
- est_cost_usd?: number | string;
100
- cycle?: string;
101
- phase?: string;
102
- // Optional / diagnostic
103
- tier_downgraded?: boolean;
104
- enforcement_mode?: string;
105
- lazy_skipped?: boolean;
106
- block_reason?: string;
107
- }
108
-
109
- /** ---- telemetry reader ---- */
110
- function readTelemetryRows(): CostRow[] {
111
- if (!existsSync(TELEMETRY_PATH)) return [];
112
- const raw: string = readFileSync(TELEMETRY_PATH, 'utf8');
113
- const out: CostRow[] = [];
114
- for (const line of raw.split(/\r?\n/)) {
115
- if (!line.trim()) continue;
116
- try {
117
- out.push(JSON.parse(line) as CostRow);
118
- } catch {
119
- // tolerant: skip malformed lines (partial write, truncation)
120
- }
121
- }
122
- return out;
123
- }
124
-
125
- /** Per-agent roll-up accumulator. */
126
- interface AgentAccumulator {
127
- total_spawns: number;
128
- total_cost_usd: number;
129
- total_tokens_in: number;
130
- total_tokens_out: number;
131
- cache_hits: number;
132
- lazy_skips: number;
133
- }
134
-
135
- /** Final per-agent shape written to .design/agent-metrics.json. */
136
- export interface AgentMetrics {
137
- typical_duration_seconds: number | null | undefined;
138
- default_tier: string | null | undefined;
139
- parallel_safe: boolean | null | undefined;
140
- reads_only: boolean | null | undefined;
141
- total_spawns: number;
142
- total_cost_usd: number;
143
- total_tokens_in: number;
144
- total_tokens_out: number;
145
- cache_hit_rate: number;
146
- lazy_skip_rate: number;
147
- }
148
-
149
- /** ---- aggregator ---- */
150
- function aggregate(rows: readonly CostRow[]): Record<string, AgentMetrics> {
151
- const byAgent = new Map<string, AgentAccumulator>();
152
- for (const r of rows) {
153
- // Blocked rows represent a spawn that was denied at the hook — the agent
154
- // never actually ran, so it must not contribute to spawn counts, cost, or
155
- // token totals. Skip them here (mirror of the filter in aggregateByPhase).
156
- if (r.block_reason) continue;
157
- const agent: string = r.agent ?? 'unknown';
158
- let a = byAgent.get(agent);
159
- if (!a) {
160
- a = {
161
- total_spawns: 0,
162
- total_cost_usd: 0,
163
- total_tokens_in: 0,
164
- total_tokens_out: 0,
165
- cache_hits: 0,
166
- lazy_skips: 0,
167
- };
168
- byAgent.set(agent, a);
169
- }
170
- a.total_spawns += 1;
171
- a.total_cost_usd += Number(r.est_cost_usd ?? 0);
172
- a.total_tokens_in += Number(r.tokens_in ?? 0);
173
- a.total_tokens_out += Number(r.tokens_out ?? 0);
174
- if (r.cache_hit === true) a.cache_hits += 1;
175
- if (r.lazy_skipped === true) a.lazy_skips += 1;
176
- }
177
-
178
- const out: Record<string, AgentMetrics> = {};
179
- for (const [agent, a] of byAgent.entries()) {
180
- const fm = readAgentFrontmatter(agent);
181
- const spawns: number = a.total_spawns || 1; // guard div-by-zero
182
- out[agent] = {
183
- typical_duration_seconds: fm.typical_duration_seconds,
184
- default_tier: fm.default_tier,
185
- parallel_safe: fm.parallel_safe,
186
- reads_only: fm.reads_only,
187
- total_spawns: a.total_spawns,
188
- total_cost_usd: Number(a.total_cost_usd.toFixed(6)),
189
- total_tokens_in: a.total_tokens_in,
190
- total_tokens_out: a.total_tokens_out,
191
- cache_hit_rate: Number((a.cache_hits / spawns).toFixed(4)),
192
- lazy_skip_rate: Number((a.lazy_skips / spawns).toFixed(4)),
193
- };
194
- }
195
- return out;
196
- }
197
-
198
- /** ---- atomic write ---- */
199
- function writeAtomic(filePath: string, content: string): void {
200
- const dir: string = dirname(filePath);
201
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
202
- const tmp: string = join(
203
- dir,
204
- `.${basename(filePath)}.${process.pid}.${Date.now()}.tmp`,
205
- );
206
- writeFileSync(tmp, content, 'utf8');
207
- renameSync(tmp, filePath);
208
- }
209
-
210
- /** ---- phase totals aggregator (WR-02: avoids full JSONL replay in budget enforcer) ---- */
211
- function aggregateByPhase(rows: readonly CostRow[]): Record<string, number> {
212
- const byPhase: Record<string, number> = {};
213
- for (const r of rows) {
214
- // Blocked rows represent spawns that were denied by the hook — the agent
215
- // never ran, so their est_cost_usd must not inflate cumulative phase spend.
216
- // Counting them would make future hard-block and soft-threshold checks
217
- // stricter than intended on every repeat cap hit.
218
- if (r.block_reason) continue;
219
- const phase: string = r.phase ?? 'unknown';
220
- byPhase[phase] = (byPhase[phase] ?? 0) + Number(r.est_cost_usd ?? 0);
221
- }
222
- // Round to 6dp to match per-agent precision
223
- for (const k of Object.keys(byPhase)) {
224
- const v: number = byPhase[k] ?? 0;
225
- byPhase[k] = Number(v.toFixed(6));
226
- }
227
- return byPhase;
228
- }
229
-
230
- /** ---- usage / --help ---- */
231
- function printHelp(): void {
232
- console.log(
233
- `aggregate-agent-metrics.ts — Aggregate per-agent telemetry from .design/telemetry/costs.jsonl.\n` +
234
- `\n` +
235
- `Usage:\n` +
236
- ` node --experimental-strip-types scripts/aggregate-agent-metrics.ts\n` +
237
- ` node --experimental-strip-types scripts/aggregate-agent-metrics.ts --help\n` +
238
- `\n` +
239
- `Reads: .design/telemetry/costs.jsonl\n` +
240
- ` agents/<agent>.md (frontmatter)\n` +
241
- `Writes: .design/agent-metrics.json\n` +
242
- ` .design/telemetry/phase-totals.json\n` +
243
- `\n` +
244
- `Invoked:\n` +
245
- ` - Detached child of hooks/budget-enforcer.js after every telemetry row.\n` +
246
- ` - Directly by /gdd:optimize as an explicit refresh step.\n` +
247
- ` - Manually, on demand.\n`,
248
- );
249
- }
250
-
251
- /** ---- main ---- */
252
- function main(): void {
253
- if (process.argv.includes('--help') || process.argv.includes('-h')) {
254
- printHelp();
255
- process.exit(0);
256
- }
257
-
258
- const rows: CostRow[] = readTelemetryRows();
259
- const agents = aggregate(rows);
260
- const payload = {
261
- generated_at: new Date().toISOString(),
262
- agents,
263
- };
264
- writeAtomic(METRICS_PATH, JSON.stringify(payload, null, 2) + '\n');
265
- // Write lightweight phase-totals.json so budget-enforcer can read phase
266
- // spend in O(1) without replaying the full JSONL on every agent spawn
267
- // (WR-02).
268
- const phaseTotals = {
269
- generated_at: new Date().toISOString(),
270
- totals: aggregateByPhase(rows),
271
- };
272
- writeAtomic(PHASE_TOTALS_PATH, JSON.stringify(phaseTotals, null, 2) + '\n');
273
- }
274
-
275
- try {
276
- main();
277
- } catch (err) {
278
- // Fail open: aggregator must never block the hook or /gdd:optimize flow.
279
- const msg: string = err instanceof Error ? err.message : String(err);
280
- process.stderr.write(`aggregate-agent-metrics: ${msg}\n`);
281
- process.exit(0);
282
- }
@@ -1,3 +0,0 @@
1
- get-design-done-bootstrap
2
- v1
3
- awesome-design-md@VoltAgent
@@ -1,80 +0,0 @@
1
- #!/usr/bin/env bash
2
- # get-design-done bootstrap
3
- # Auto-provisions companion resources that get-design-done references but which
4
- # are not Claude Code plugins (so they cannot be listed in `dependencies`).
5
- #
6
- # Runs on SessionStart. Idempotent: uses a marker in ${CLAUDE_PLUGIN_DATA} so it
7
- # only performs network work on first install or when the bundled manifest changes.
8
- #
9
- # Resources provisioned:
10
- # - ~/.claude/libs/awesome-design-md (VoltAgent/awesome-design-md)
11
- #
12
- # Resources NOT provisioned (install separately, see README):
13
- # - emil-design-eng skill — no canonical upstream
14
- # - refero MCP — optional, add to your Claude config if you have access
15
-
16
- set -u
17
-
18
- PLUGIN_DATA="${CLAUDE_PLUGIN_DATA:-$HOME/.claude/plugins/data/get-design-done}"
19
- PLUGIN_DATA="${PLUGIN_DATA//\\//}" # Normalize Windows backslashes to forward slashes
20
- PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
21
- PLUGIN_ROOT="${PLUGIN_ROOT//\\//}" # Normalize Windows backslashes to forward slashes
22
- MANIFEST="${PLUGIN_ROOT}/scripts/bootstrap-manifest.txt"
23
- MARKER="${PLUGIN_DATA}/bootstrap-manifest.txt"
24
-
25
- mkdir -p "${PLUGIN_DATA}" "${HOME}/.claude/libs" "${HOME}/.claude/skills"
26
-
27
- # Skip if bundled manifest matches the last-run marker (no-op on every other session).
28
- if [[ -f "${MANIFEST}" && -f "${MARKER}" ]] && diff -q "${MANIFEST}" "${MARKER}" >/dev/null 2>&1; then
29
- exit 0
30
- fi
31
-
32
- log() { printf '[get-design-done bootstrap] %s\n' "$*" >&2; }
33
-
34
- clone_or_update() {
35
- local repo_url="$1"
36
- local target="$2"
37
- if [[ -d "${target}/.git" ]]; then
38
- log "updating ${target}"
39
- git -C "${target}" pull --quiet --ff-only 2>/dev/null || log "pull failed for ${target} (continuing)"
40
- elif [[ -d "${target}" ]]; then
41
- log "${target} exists and is not a git checkout — skipping"
42
- else
43
- log "cloning ${repo_url} -> ${target}"
44
- git clone --quiet --depth 1 "${repo_url}" "${target}" || log "clone failed for ${repo_url}"
45
- fi
46
- }
47
-
48
- # Required library: awesome-design-md
49
- clone_or_update "https://github.com/VoltAgent/awesome-design-md.git" "${HOME}/.claude/libs/awesome-design-md"
50
-
51
- # Soft notice for companion skills we cannot auto-install.
52
- if [[ ! -d "${HOME}/.claude/skills/emil-design-eng" ]]; then
53
- log "optional: emil-design-eng skill not found in ~/.claude/skills. See get-design-done README for install options."
54
- fi
55
-
56
- # Phase 10.1: ensure .design/budget.json exists with defaults (D-12)
57
- DESIGN_DIR="$(pwd)/.design"
58
- mkdir -p "${DESIGN_DIR}"
59
- if [ ! -f "${DESIGN_DIR}/budget.json" ]; then
60
- cat > "${DESIGN_DIR}/budget.json" <<'BUDGET_EOF'
61
- {
62
- "per_task_cap_usd": 2.00,
63
- "per_phase_cap_usd": 20.00,
64
- "tier_overrides": {},
65
- "auto_downgrade_on_cap": true,
66
- "cache_ttl_seconds": 3600,
67
- "enforcement_mode": "enforce"
68
- }
69
- BUDGET_EOF
70
- fi
71
-
72
- # Phase 10.1: ensure .design/telemetry/ directory is writable
73
- mkdir -p "${DESIGN_DIR}/telemetry"
74
-
75
- # Record success so we don't re-run until the bundled manifest changes.
76
- if [[ -f "${MANIFEST}" ]]; then
77
- cp "${MANIFEST}" "${MARKER}"
78
- fi
79
-
80
- exit 0