@hegemonart/get-design-done 1.37.2 → 1.38.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +45 -0
- package/README.md +8 -0
- package/SKILL.md +1 -0
- package/agents/design-verifier.md +1 -1
- package/agents/experiment-result-ingester.md +61 -0
- package/agents/rollout-coordinator.md +71 -0
- package/agents/user-research-synthesizer.md +65 -0
- package/connections/connections.md +7 -1
- package/connections/growthbook.md +110 -0
- package/connections/hotjar.md +110 -0
- package/connections/launchdarkly.md +83 -0
- package/connections/maze.md +130 -0
- package/connections/statsig.md +83 -0
- package/connections/usertesting.md +99 -0
- package/package.json +1 -1
- package/reference/design-variants.md +56 -0
- package/reference/registry.json +14 -0
- package/reference/rollout-coordination.md +63 -0
- package/reference/schemas/events.schema.json +1 -1
- package/scripts/lib/ds-arms/design-arms-store.cjs +119 -0
- package/scripts/lib/rollout/rollout-status.cjs +60 -0
- package/skills/brief/SKILL.md +8 -0
- package/skills/connections/SKILL.md +4 -4
- package/skills/connections/connections-onboarding.md +58 -4
- package/skills/design/SKILL.md +2 -1
- package/skills/rollout-status/SKILL.md +35 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* scripts/lib/ds-arms/design-arms-store.cjs — Phase 38 `design_arms` posterior class.
|
|
4
|
+
*
|
|
5
|
+
* A NEW arm class, DISTINCT from the routing bandit's `routing_arms`
|
|
6
|
+
* (scripts/lib/bandit-router.cjs) — design_arms learn "which design pattern wins with USERS"
|
|
7
|
+
* from external A/B + user-research outcomes, not internal lint/test/visual signals (D-01).
|
|
8
|
+
* Isolated store: never touches the mature routing bandit. Keyed by
|
|
9
|
+
* (component_type, variant_pattern_hash) with a conservative Beta(2, 8) prior (posterior mean
|
|
10
|
+
* 0.2 — Phase 29 fairness-gate pattern: a pattern must EARN trust from real outcomes).
|
|
11
|
+
*
|
|
12
|
+
* No new dependency: an inline FNV-1a hash for the pattern key (no `crypto`, no egress). The
|
|
13
|
+
* posterior math is pure; persistence is an atomic write to `.design/telemetry/design-arms.json`
|
|
14
|
+
* (override `armsPath`/`baseDir` for hermetic tests).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const fs = require('node:fs');
|
|
18
|
+
const path = require('node:path');
|
|
19
|
+
|
|
20
|
+
const SCHEMA_VERSION = '38.0';
|
|
21
|
+
const DEFAULT_ARMS_PATH = '.design/telemetry/design-arms.json';
|
|
22
|
+
// Conservative prior — Beta(2, 8), posterior mean 0.2. A design pattern is advisory until real
|
|
23
|
+
// user-outcome data shifts it (D-03 — advisory, never directive).
|
|
24
|
+
const DESIGN_ARM_PRIOR = Object.freeze({ alpha: 2, beta: 8 });
|
|
25
|
+
|
|
26
|
+
/** Inline FNV-1a (32-bit) hash → 8-char hex. Deterministic, dependency-free. */
|
|
27
|
+
function fnv1a(str) {
|
|
28
|
+
let h = 0x811c9dc5;
|
|
29
|
+
for (let i = 0; i < str.length; i++) {
|
|
30
|
+
h ^= str.charCodeAt(i);
|
|
31
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
32
|
+
}
|
|
33
|
+
return h.toString(16).padStart(8, '0');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** variantKey(componentType, pattern) — a stable key for a design-arm. `pattern` may be a
|
|
37
|
+
* string ("primary-CTA-bold") or an object (canonicalized by sorted JSON). */
|
|
38
|
+
function variantKey(componentType, pattern) {
|
|
39
|
+
const p = typeof pattern === 'string' ? pattern : JSON.stringify(pattern, Object.keys(pattern || {}).sort());
|
|
40
|
+
return fnv1a(`${componentType}::${p}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function resolvePath(opts = {}) {
|
|
44
|
+
const p = opts.armsPath || DEFAULT_ARMS_PATH;
|
|
45
|
+
return path.isAbsolute(p) ? p : path.resolve(opts.baseDir || process.cwd(), p);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function load(opts = {}) {
|
|
49
|
+
const p = resolvePath(opts);
|
|
50
|
+
if (!fs.existsSync(p)) return { schema_version: SCHEMA_VERSION, generated_at: new Date().toISOString(), arms: [] };
|
|
51
|
+
try {
|
|
52
|
+
const data = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
53
|
+
if (!Array.isArray(data.arms)) data.arms = [];
|
|
54
|
+
return data;
|
|
55
|
+
} catch (e) {
|
|
56
|
+
return { schema_version: SCHEMA_VERSION, generated_at: new Date().toISOString(), arms: [] };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function save(store, opts = {}) {
|
|
61
|
+
const p = resolvePath(opts);
|
|
62
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
63
|
+
store.schema_version = SCHEMA_VERSION;
|
|
64
|
+
store.generated_at = new Date().toISOString();
|
|
65
|
+
const tmp = p + '.tmp';
|
|
66
|
+
fs.writeFileSync(tmp, JSON.stringify(store, null, 2));
|
|
67
|
+
fs.renameSync(tmp, p);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const meanOf = (alpha, beta) => alpha / (alpha + beta);
|
|
71
|
+
|
|
72
|
+
/** pull(componentType, hash, opts) — the arm's posterior, or the conservative prior if unseen. */
|
|
73
|
+
function pull(componentType, hash, opts = {}) {
|
|
74
|
+
const store = opts._store || load(opts);
|
|
75
|
+
const arm = store.arms.find((a) => a.component_type === componentType && a.variant_pattern_hash === hash);
|
|
76
|
+
if (!arm) {
|
|
77
|
+
return { component_type: componentType, variant_pattern_hash: hash, alpha: DESIGN_ARM_PRIOR.alpha, beta: DESIGN_ARM_PRIOR.beta, count: 0, mean: meanOf(DESIGN_ARM_PRIOR.alpha, DESIGN_ARM_PRIOR.beta), seen: false };
|
|
78
|
+
}
|
|
79
|
+
return { ...arm, mean: meanOf(arm.alpha, arm.beta), seen: true };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* observe(componentType, hash, outcome, opts) — fold an external outcome into the arm.
|
|
84
|
+
* outcome: { won:boolean, weight?:number=1, source?:'ab'|'research'|'dev_time', pattern?, label? }.
|
|
85
|
+
* won → alpha += weight; lost → beta += weight. Persists (unless opts._store is supplied).
|
|
86
|
+
*/
|
|
87
|
+
function observe(componentType, hash, outcome = {}, opts = {}) {
|
|
88
|
+
const store = opts._store || load(opts);
|
|
89
|
+
const weight = typeof outcome.weight === 'number' && outcome.weight > 0 ? outcome.weight : 1;
|
|
90
|
+
let arm = store.arms.find((a) => a.component_type === componentType && a.variant_pattern_hash === hash);
|
|
91
|
+
if (!arm) {
|
|
92
|
+
arm = {
|
|
93
|
+
component_type: componentType,
|
|
94
|
+
variant_pattern_hash: hash,
|
|
95
|
+
label: outcome.label || null,
|
|
96
|
+
alpha: DESIGN_ARM_PRIOR.alpha,
|
|
97
|
+
beta: DESIGN_ARM_PRIOR.beta,
|
|
98
|
+
count: 0,
|
|
99
|
+
prior_class: 'design_arm',
|
|
100
|
+
last_source: null,
|
|
101
|
+
last_observed: null,
|
|
102
|
+
};
|
|
103
|
+
store.arms.push(arm);
|
|
104
|
+
}
|
|
105
|
+
if (outcome.won) arm.alpha += weight; else arm.beta += weight;
|
|
106
|
+
arm.count += 1;
|
|
107
|
+
arm.last_source = outcome.source || 'ab';
|
|
108
|
+
arm.last_observed = new Date().toISOString();
|
|
109
|
+
if (!opts._store) save(store, opts);
|
|
110
|
+
return { ...arm, mean: meanOf(arm.alpha, arm.beta) };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** all(opts) — every arm with its posterior mean, for design-stage ranking (advisory). */
|
|
114
|
+
function all(opts = {}) {
|
|
115
|
+
const store = opts._store || load(opts);
|
|
116
|
+
return store.arms.map((a) => ({ ...a, mean: meanOf(a.alpha, a.beta) }));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = { variantKey, pull, observe, all, load, save, fnv1a, DESIGN_ARM_PRIOR, SCHEMA_VERSION, DEFAULT_ARMS_PATH };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* scripts/lib/rollout/rollout-status.cjs — Phase 38.5 rollout-state classifier.
|
|
4
|
+
*
|
|
5
|
+
* Pure + dep-free (D-01): zero `require`. Given a NORMALIZED feature-flag state (the
|
|
6
|
+
* rollout-coordinator normalizes LaunchDarkly / Statsig / GrowthBook payloads to this shape),
|
|
7
|
+
* classify the per-cycle rollout state, the deployed percentage, whether a rollout is stuck,
|
|
8
|
+
* and the deployed-weight a `verify_outcome` observation carries into the `design_arms` posterior.
|
|
9
|
+
* Deterministic — same input → same output (hermetic tests, D-07).
|
|
10
|
+
*
|
|
11
|
+
* Normalized flag state:
|
|
12
|
+
* { stagingEnabled: boolean, prodEnabled: boolean, prodPercent: number (0..100) }
|
|
13
|
+
*
|
|
14
|
+
* Rollout states: 'unrolled' | 'staging-only' | 'canary-N%' | 'prod-100%'
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const STUCK_DEFAULT_DAYS = 14; // D-04
|
|
18
|
+
|
|
19
|
+
function clampPct(n) {
|
|
20
|
+
if (typeof n !== 'number' || !isFinite(n)) return 0;
|
|
21
|
+
return Math.max(0, Math.min(100, n));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** classifyRollout(flagState) → the rollout-state string. */
|
|
25
|
+
function classifyRollout(flagState = {}) {
|
|
26
|
+
const stagingEnabled = !!flagState.stagingEnabled;
|
|
27
|
+
const prodEnabled = !!flagState.prodEnabled;
|
|
28
|
+
const pct = clampPct(flagState.prodPercent);
|
|
29
|
+
if (!prodEnabled || pct === 0) {
|
|
30
|
+
return stagingEnabled || prodEnabled ? 'staging-only' : 'unrolled';
|
|
31
|
+
}
|
|
32
|
+
if (pct >= 100) return 'prod-100%';
|
|
33
|
+
return `canary-${pct}%`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** deployedPct(flagState) → the live production rollout percentage (0 when not in prod). */
|
|
37
|
+
function deployedPct(flagState = {}) {
|
|
38
|
+
return flagState.prodEnabled ? clampPct(flagState.prodPercent) : 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* isStuck(state, daysSinceChange, threshold=14) — a PARTIAL rollout (staging-only / canary-N%)
|
|
43
|
+
* that has not advanced for >= threshold days. A finished (prod-100%) or never-started (unrolled)
|
|
44
|
+
* rollout is never "stuck".
|
|
45
|
+
*/
|
|
46
|
+
function isStuck(state, daysSinceChange, threshold = STUCK_DEFAULT_DAYS) {
|
|
47
|
+
if (state === 'prod-100%' || state === 'unrolled') return false;
|
|
48
|
+
const partial = state === 'staging-only' || /^canary-\d+%$/.test(state);
|
|
49
|
+
return partial && typeof daysSinceChange === 'number' && daysSinceChange >= threshold;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* deployedWeight(pct) — the weight a verify_outcome observation carries into design_arms.
|
|
54
|
+
* Linear (D-03): a 10%-rolled variant counts 0.1; 100% counts 1.0. Range [0, 1].
|
|
55
|
+
*/
|
|
56
|
+
function deployedWeight(pct) {
|
|
57
|
+
return clampPct(pct) / 100;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = { classifyRollout, deployedPct, isStuck, deployedWeight, clampPct, STUCK_DEFAULT_DAYS };
|
package/skills/brief/SKILL.md
CHANGED
|
@@ -54,8 +54,16 @@ Write the brief with these sections, preserving any pre-existing answers:
|
|
|
54
54
|
|
|
55
55
|
## Scope
|
|
56
56
|
<answer>
|
|
57
|
+
|
|
58
|
+
<prior-research>
|
|
59
|
+
<!-- Phase 38: populated by agents/user-research-synthesizer.md from UserTesting/Maze/Hotjar
|
|
60
|
+
(pseudonymized) — ranked findings {finding · frequency · severity}. Empty on a fresh brief;
|
|
61
|
+
the verify stage cross-checks each finding (addressed or explicitly deferred). -->
|
|
62
|
+
</prior-research>
|
|
57
63
|
```
|
|
58
64
|
|
|
65
|
+
Leave the `<prior-research>` block empty on a greenfield brief — it is filled by `/gdd:research-sync` (the `user-research-synthesizer`) when a research source is connected, and re-checked at verify. See `reference/design-variants.md` for the outcome loop.
|
|
66
|
+
|
|
59
67
|
## Step 4 — Bootstrap STATE.md (if missing)
|
|
60
68
|
|
|
61
69
|
<!-- BOOTSTRAP EXCEPTION: STATE.md does not exist yet — MCP tools require it to exist. Direct Write is intentional. All subsequent mutations use MCP. -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gdd-connections
|
|
3
|
-
description: "Interactive onboarding wizard for the
|
|
3
|
+
description: "Interactive onboarding wizard for the 33 external integrations the pipeline supports — probes all (`figma`, `refero`, `preview`, `storybook`, `chromatic`, `graphify`, `pinterest`, `claude-design`, `paper-design`, `pencil-dev`, `21st-dev`, `magic-patterns`, `lazyweb`, `mobbin`, `slack`, `discord`, `linear`, `jira`, `notion`, `lottie`, `rive`, `framer`, `penpot`, `webflow`, `v0-dev`, `plasmic`, `builder-io`, `launchdarkly`, `statsig`, `growthbook`, `usertesting`, `maze`, `hotjar`), recommends based on project type, walks the user through setup (auto-run MCP install or copy-command fallback), writes results to `STATE.md <connections>`. Use after `/gdd:new-project` or whenever the user wants to add, inspect, or skip a connection. Re-runnable anytime."
|
|
4
4
|
argument-hint: "[list | <connection-name> | --auto]"
|
|
5
5
|
user-invocable: true
|
|
6
6
|
tools: Read, Write, Bash, Glob, Grep, AskUserQuestion, ToolSearch
|
|
@@ -8,11 +8,11 @@ tools: Read, Write, Bash, Glob, Grep, AskUserQuestion, ToolSearch
|
|
|
8
8
|
|
|
9
9
|
# /gdd:connections
|
|
10
10
|
|
|
11
|
-
Interactive onboarding for the
|
|
11
|
+
Interactive onboarding for the 33 external integrations the pipeline supports. Replaces "probe silently at scan entry and hope the user noticed" with an explicit "here is what can plug in, here is how."
|
|
12
12
|
|
|
13
13
|
Canonical per-connection specs live in `../../connections/<name>.md` (one file per integration). The capability matrix + probe-pattern spec live in `../../connections/connections.md`. This skill is the **user-facing front end** for those specs.
|
|
14
14
|
|
|
15
|
-
For the
|
|
15
|
+
For the 33 probe scripts (MCP + HTTP + CLI + file probes), bucket categorization, per-connection setup screen, auto-run eligibility matrix, value-prop one-liners, and STATE.md / config.json write contracts, see `./connections-onboarding.md`. For the cross-skill probe pattern + connection-handshake summary, see `../../reference/shared-preamble.md#connection-handshake-summary`. For the cross-skill output discipline, see `../../reference/shared-preamble.md#output-contract-reminders`.
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
@@ -38,7 +38,7 @@ For the 27 probe scripts (MCP + HTTP + CLI + file probes), bucket categorization
|
|
|
38
38
|
|
|
39
39
|
## Workflow
|
|
40
40
|
|
|
41
|
-
1. **Probe all
|
|
41
|
+
1. **Probe all 33 connections** — run every probe script per `./connections-onboarding.md#step-1--probe-all-33-connections`. MCP probes use `ToolSearch` first; HTTP / CLI / file probes follow non-MCP patterns. Merge results into `STATE.md <connections>` with the three-value schema (`available | unavailable | not_configured`) — never add new values.
|
|
42
42
|
2. **Categorize + build summary** — bucket each probe result (available / recommended / optional / skipped / unavailable) using project-hint detection. Detail + recommendation mapping: `./connections-onboarding.md#step-2--bucket-categorization`.
|
|
43
43
|
3. **Print summary table** — show buckets + value-prop one-liners (verbatim from `./connections-onboarding.md#step-3--summary-table`).
|
|
44
44
|
4. **Route by mode** — `list` / `--auto` exits after summary; `<name>` jumps straight to Step 5; default mode opens an AskUserQuestion (configure recommended / pick one by one / configure all optional / re-check specific / exit). Routing detail: `./connections-onboarding.md#step-4--route-by-mode`.
|
|
@@ -9,7 +9,7 @@ last_updated: 2026-05-18
|
|
|
9
9
|
|
|
10
10
|
Source: extracted from `skills/connections/SKILL.md` (Phase 28.5 rework — D-10 extract-then-link).
|
|
11
11
|
The skill's load-bearing routing + invocation-mode dispatch stays in `../skills/connections/SKILL.md`;
|
|
12
|
-
this file holds the
|
|
12
|
+
this file holds the 33 probe scripts, bucket categorization, per-connection setup screen,
|
|
13
13
|
auto-run eligibility matrix, value-prop one-liners, and STATE.md / config.json write contracts.
|
|
14
14
|
|
|
15
15
|
# Connections Onboarding Procedure
|
|
@@ -27,7 +27,7 @@ this file does NOT duplicate them; it points at them by name.
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
-
## Step 1 — Probe all
|
|
30
|
+
## Step 1 — Probe all 33 connections
|
|
31
31
|
|
|
32
32
|
Run every probe below in order. MCP probes call `ToolSearch` first (deferred tools fail silently without it). Write every result to `STATE.md <connections>` when done.
|
|
33
33
|
|
|
@@ -238,7 +238,49 @@ ToolSearch({ query: "builder", max_results: 5 })
|
|
|
238
238
|
→ Non-empty → builder-io: available
|
|
239
239
|
```
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
**launchdarkly:** (Outcome — experiment-source; read-only A/B)
|
|
242
|
+
```
|
|
243
|
+
ToolSearch({ query: "launchdarkly", max_results: 5 }) (else check the platform API-key env)
|
|
244
|
+
→ Empty / GDD_DISABLE_LAUNCHDARKLY=1 → launchdarkly: not_configured
|
|
245
|
+
→ Non-empty / key set → launchdarkly: available
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**statsig:** (Outcome — experiment-source; read-only)
|
|
249
|
+
```
|
|
250
|
+
ToolSearch({ query: "statsig", max_results: 5 }) (else check the platform API-key env)
|
|
251
|
+
→ Empty / GDD_DISABLE_STATSIG=1 → statsig: not_configured
|
|
252
|
+
→ Non-empty / key set → statsig: available
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**growthbook:** (Outcome — experiment-source; self-host/cloud)
|
|
256
|
+
```
|
|
257
|
+
ToolSearch({ query: "growthbook", max_results: 5 }) (else check the platform API-key env)
|
|
258
|
+
→ Empty / GDD_DISABLE_GROWTHBOOK=1 → growthbook: not_configured
|
|
259
|
+
→ Non-empty / key set → growthbook: available
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**usertesting:** (Outcome — user-research; pseudonymize-first)
|
|
263
|
+
```
|
|
264
|
+
ToolSearch({ query: "usertesting", max_results: 5 }) (else check the platform API-key env)
|
|
265
|
+
→ Empty / GDD_DISABLE_USERTESTING=1 → usertesting: not_configured
|
|
266
|
+
→ Non-empty / key set → usertesting: available
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**maze:** (Outcome — user-research; pseudonymize-first)
|
|
270
|
+
```
|
|
271
|
+
ToolSearch({ query: "maze", max_results: 5 }) (else check the platform API-key env)
|
|
272
|
+
→ Empty / GDD_DISABLE_MAZE=1 → maze: not_configured
|
|
273
|
+
→ Non-empty / key set → maze: available
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**hotjar:** (Outcome — user-research; indexed insights only)
|
|
277
|
+
```
|
|
278
|
+
ToolSearch({ query: "hotjar", max_results: 5 }) (else check the platform API-key env)
|
|
279
|
+
→ Empty / GDD_DISABLE_HOTJAR=1 → hotjar: not_configured
|
|
280
|
+
→ Non-empty / key set → hotjar: available
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
After all 33 probes complete, merge results into `STATE.md <connections>`. Preserve the three-value schema verbatim (`available | unavailable | not_configured`). Do not add new values.
|
|
242
284
|
|
|
243
285
|
---
|
|
244
286
|
|
|
@@ -334,6 +376,12 @@ One-line value props (use verbatim):
|
|
|
334
376
|
| v0-dev | generator — Vercel v0 prompt→component (MCP-first → REST + V0_API_KEY) |
|
|
335
377
|
| plasmic | generator + canvas — emit code + read the Plasmic canvas |
|
|
336
378
|
| builder-io | generator — Builder.io Visual Copilot (pull-only this phase) |
|
|
379
|
+
| launchdarkly | outcome — read A/B results → design_arms posterior (experiment-source) |
|
|
380
|
+
| statsig | outcome — read experiment/pulse results → design_arms (experiment-source) |
|
|
381
|
+
| growthbook | outcome — read experiment results → design_arms (experiment-source; OSS) |
|
|
382
|
+
| usertesting | outcome — read test reports → brief findings (user-research; pseudonymized) |
|
|
383
|
+
| maze | outcome — read usability metrics → brief findings (user-research; pseudonymized) |
|
|
384
|
+
| hotjar | outcome — read indexed insights → brief findings (user-research; pseudonymized) |
|
|
337
385
|
|
|
338
386
|
---
|
|
339
387
|
|
|
@@ -361,7 +409,7 @@ options:
|
|
|
361
409
|
- "Exit" → emit ## CONNECTIONS COMPLETE, exit
|
|
362
410
|
```
|
|
363
411
|
|
|
364
|
-
If recommended bucket is empty, swap that option for "Show all
|
|
412
|
+
If recommended bucket is empty, swap that option for "Show all 33 and pick."
|
|
365
413
|
|
|
366
414
|
---
|
|
367
415
|
|
|
@@ -433,6 +481,12 @@ options:
|
|
|
433
481
|
| v0-dev | `claude mcp add v0 ...` (or V0_API_KEY) | ✓ yes | Reversible; MCP-first → REST fallback |
|
|
434
482
|
| plasmic | `claude mcp add plasmic ...` (or token) | ✓ yes | Reversible; dual canvas+generator |
|
|
435
483
|
| builder-io | `claude mcp add builder ...` (or BUILDER_API_KEY) | ✓ yes | Reversible; pull-only this phase |
|
|
484
|
+
| launchdarkly | (set `LAUNCHDARKLY_API_KEY` / add the LaunchDarkly MCP) | ✓ yes | Reversible; read-only experiment-source |
|
|
485
|
+
| statsig | (set `STATSIG_API_KEY` / add the Statsig MCP) | ✓ yes | Reversible; read-only experiment-source |
|
|
486
|
+
| growthbook | (set `GROWTHBOOK_API_KEY` [+ host] / add the MCP) | ✓ yes | Reversible; self-host or cloud |
|
|
487
|
+
| usertesting | (set `USERTESTING_API_KEY` / add the MCP) | ✓ yes | Reversible; read-only; pseudonymize-first |
|
|
488
|
+
| maze | (set `MAZE_API_KEY` / add the MCP) | ✓ yes | Reversible; read-only; pseudonymize-first |
|
|
489
|
+
| hotjar | (set `HOTJAR_API_KEY` / add the MCP) | ✓ yes | Reversible; indexed insights only; pseudonymize-first |
|
|
436
490
|
|
|
437
491
|
For non-auto-run connections, hide the "Run install command now" option entirely in 5.3.
|
|
438
492
|
|
package/skills/design/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: design
|
|
3
3
|
description: "Stage 4 of 5 orchestrator that reads DESIGN-PLAN.md, partitions tasks by wave + parallel-safe flag, and spawns design-executor agents with the appropriate isolation (worktree for parallel batches, in-place for sequential tail). Use when DESIGN-PLAN.md is approved and ready for implementation."
|
|
4
|
-
argument-hint: "[--auto] [--parallel]"
|
|
4
|
+
argument-hint: "[--auto] [--parallel] [--variants N]"
|
|
5
5
|
user-invocable: true
|
|
6
6
|
tools: Read, Write, Bash, Grep, Glob, Task, AskUserQuestion, mcp__gdd_state__get, mcp__gdd_state__transition_stage, mcp__gdd_state__update_progress, mcp__gdd_state__set_status, mcp__gdd_state__add_blocker, mcp__gdd_state__resolve_blocker, mcp__gdd_state__checkpoint
|
|
7
7
|
---
|
|
@@ -28,6 +28,7 @@ Detail: `./design-procedure.md` §Stage entry.
|
|
|
28
28
|
|
|
29
29
|
- `--auto` -> `auto_mode=true` (no mid-stage prompts; architectural deviations stop the individual task but continue the rest).
|
|
30
30
|
- `--parallel` -> `parallel_mode=true` (use worktree isolation for `Parallel: true` tasks).
|
|
31
|
+
- `--variants N` -> `variants_mode` (default N=2): for tasks that build a user-facing surface, the executor emits **N competing, hypothesis-tagged variants** (`<variant id component pattern hypothesis>`) instead of one. Before generating, consult the `design_arms` posterior (`scripts/lib/ds-arms/design-arms-store.cjs`) to bias toward patterns that have won prior A/B / user-research outcomes — **advisory, never directive** (the user's explicit choice always wins). The tagged variants flow to A/B (LaunchDarkly/Statsig/GrowthBook) for outcome ingestion. Full schema + the outcome loop: `../../reference/design-variants.md`.
|
|
31
32
|
- **Directionally-open check** (skipped if `auto_mode`): scan DESIGN-PLAN.md for tasks whose criteria read "explore N directions" / "pick a visual approach" and suggest `/gdd:sketch` first.
|
|
32
33
|
- **Project-local conventions**: include any `./.claude/skills/design-*-conventions.md` and `~/.claude/gdd/global-skills/*.md` in every executor's `<required_reading>` — global conventions inform but do not override project-local D-XX decisions.
|
|
33
34
|
- **`.stories.tsx` stub**: after each new component file is created by the executor, emit a CSF stub alongside if `.storybook/` exists or `"storybook"` is in `package.json`, even with the dev server offline. Detail: `./design-procedure.md` §.stories.tsx Stub.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gdd-rollout-status
|
|
3
|
+
description: "Shows where a finished design cycle actually is in production rollout — unrolled / staging-only / canary-N% / prod-100% — by reading the feature-flag service (LaunchDarkly/Statsig/GrowthBook) via the rollout-coordinator. Surfaces STUCK rollouts (a canary that hasn't advanced for N days) and the design_arms outcome weighting. Read-only — GDD never advances or rolls back; it reports and notifies. Use after /gdd:ship to track the post-merge journey."
|
|
4
|
+
argument-hint: "[<cycle>] [--all] [--stuck]"
|
|
5
|
+
user-invocable: true
|
|
6
|
+
tools: Read, Bash, Grep, Glob, ToolSearch, Task
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# /gdd:rollout-status
|
|
10
|
+
|
|
11
|
+
Closes the visibility gap after `/gdd:ship`: a PR merges, but staging → canary → 100% rollout happens outside GDD. This skill reports where each cycle's design actually is in production, by delegating to `agents/rollout-coordinator.md` (which reads the feature-flag service via the Phase 38 connections). **Read-only** — it reports + notifies; it never advances or rolls back a rollout. Contract + the `<rollout_status>` schema: `../../reference/rollout-coordination.md`.
|
|
12
|
+
|
|
13
|
+
## Invocation
|
|
14
|
+
|
|
15
|
+
| Command | Behavior |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `/gdd:rollout-status` | The current cycle's rollout state (from `.design/STATE.md <rollout_status>`, refreshed via the coordinator). |
|
|
18
|
+
| `/gdd:rollout-status <cycle>` | A specific cycle's rollout state. |
|
|
19
|
+
| `/gdd:rollout-status --all` | Every cycle with a `<rollout_status>` block — a rollout dashboard. |
|
|
20
|
+
| `/gdd:rollout-status --stuck` | Only the **stuck** rollouts (partial rollouts that haven't advanced for ≥ the threshold). |
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
1. **Probe the flag service.** Check a flag connection is `available` (`connections/launchdarkly.md` / `statsig.md` / `growthbook.md`). None → print `rollout-status: no flag service configured — connect one via /gdd:connections.` and exit.
|
|
25
|
+
2. **Delegate to `rollout-coordinator`** (via `Task`): it reads the service, classifies via `scripts/lib/rollout/rollout-status.cjs`, refreshes the `<rollout_status>` block, and reports state + deployed % + stuck.
|
|
26
|
+
3. **Render.** Show each cycle: `state` · `deployed_pct` · `last_changed` · `stuck?`. For `--stuck`, list only stuck cycles with the days-since-change and an advance-or-rollback suggestion.
|
|
27
|
+
4. **Do not act.** Never run a flag-service mutation, advance a canary, or roll back — GDD reports; the human + the flag service decide.
|
|
28
|
+
|
|
29
|
+
## Output
|
|
30
|
+
|
|
31
|
+
End with:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
## ROLLOUT-STATUS COMPLETE
|
|
35
|
+
```
|