@hegemonart/get-design-done 1.30.6 → 1.31.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.
@@ -8,12 +8,13 @@
8
8
  // Surface:
9
9
  // async getHealthChecks(rootDir) → { checks: HealthCheck[] }
10
10
  //
11
- // The 5 checks (in stable order) are:
11
+ // The 6 checks (in stable order) are:
12
12
  // 1. claude_md — CLAUDE.md presence
13
13
  // 2. planning_dir — .planning/ presence
14
14
  // 3. design_dir — .design/ presence
15
15
  // 4. package_json — package.json present AND parseable
16
16
  // 5. issue_reporter — kill-switch state (Plan 30-06 / D-08)
17
+ // 6. figma_extract — extract readiness + Free-tier signal (Plan 31-09)
17
18
  //
18
19
  // Check 5 was added in Plan 30-06 — surfaces the report-issue kill-switch
19
20
  // (env or config disable) so users can verify why the command is
@@ -22,6 +23,17 @@
22
23
  // - "issue reporter: disabled by env (GDD_DISABLE_ISSUE_REPORTER=1)"
23
24
  // - "issue reporter: disabled by config (.design/config.json: issue_reporter=false)"
24
25
  // When both env and config trigger, env wins (matches D-08 display contract).
26
+ //
27
+ // Check 6 was added in Plan 31-09 — surfaces figma-extract readiness so a user
28
+ // running /gdd:health immediately knows whether figma-extract is usable. The
29
+ // detail line is one of three exact strings:
30
+ // - "figma extract: ready (token set)"
31
+ // - "figma extract: token missing"
32
+ // - "figma extract: plugin sync needed for variables (Free tier detected)"
33
+ // D-10: only FIGMA_TOKEN *presence* is used — the token VALUE is never read,
34
+ // logged, or placed in the detail. The Free-tier state is derived from a LOCAL
35
+ // signal only (a prior pull's _meta.json recording a 403/skip on the Variables
36
+ // endpoint) — never a live network call (health-mirror is pure read-only).
25
37
 
26
38
  const fs = require('node:fs');
27
39
  const path = require('node:path');
@@ -135,7 +147,82 @@ async function getHealthChecks(rootDir) {
135
147
  });
136
148
  }
137
149
 
150
+ // 6. figma_extract — extract readiness + Free-tier plugin-sync signal (Plan 31-09)
151
+ // Reports exactly one of three states. PURE read-only: presence-only token
152
+ // check (D-10 — value never read/logged/printed) + a LOCAL Free-tier marker
153
+ // (a prior pull's _meta.json recording a 403/skip on the Variables endpoint —
154
+ // see scripts/lib/figma-extract/pull.cjs). NEVER throws, NEVER networks.
155
+ {
156
+ // D-10: presence only. The token VALUE is never bound to a variable that
157
+ // could be interpolated into detail/logs — only the boolean is kept.
158
+ const tokenSet = !!(process.env.FIGMA_TOKEN || process.env.FIGMA_PERSONAL_ACCESS_TOKEN);
159
+
160
+ let detail;
161
+ let status;
162
+ if (!tokenSet) {
163
+ detail = 'figma extract: token missing';
164
+ status = 'warn';
165
+ } else if (figmaVariablesBlockedLocally(rootDir)) {
166
+ // Token present but a prior pull recorded a 403/skip on the Variables REST
167
+ // path → Free/non-Enterprise tier. Actionable (plugin sync), not a hard fail.
168
+ detail = 'figma extract: plugin sync needed for variables (Free tier detected)';
169
+ status = 'warn';
170
+ } else {
171
+ detail = 'figma extract: ready (token set)';
172
+ status = 'ok';
173
+ }
174
+ checks.push({ name: 'figma_extract', status, detail });
175
+ }
176
+
138
177
  return { checks };
139
178
  }
140
179
 
180
+ /**
181
+ * Free-tier signal (LOCAL only — never a network call). The raw-pull stage
182
+ * (scripts/lib/figma-extract/pull.cjs) writes a _meta.json per file key under
183
+ * the gitignored cache dir; on a Variables 403 it records a totals[] entry
184
+ * `{ name: 'variables', skipped: true, reason: 'HTTP 403' }`. We scan the
185
+ * default cache root for any such marker. Defensive: malformed/absent markers
186
+ * default to NOT-free (→ 'ready') so the health probe never false-alarms and
187
+ * NEVER throws. NEVER reads the token; NEVER makes a request.
188
+ *
189
+ * @param {string} rootDir project root passed to getHealthChecks
190
+ * @returns {boolean} true iff a prior pull recorded a Variables 403/skip
191
+ */
192
+ function figmaVariablesBlockedLocally(rootDir) {
193
+ try {
194
+ const rawRoot = path.join(rootDir, '.figma-extract-cache', 'raw');
195
+ let entries;
196
+ try {
197
+ entries = fs.readdirSync(rawRoot, { withFileTypes: true });
198
+ } catch {
199
+ return false; // no cache yet → default to ready
200
+ }
201
+ for (const ent of entries) {
202
+ if (!ent.isDirectory()) continue;
203
+ const metaPath = path.join(rawRoot, ent.name, '_meta.json');
204
+ let meta;
205
+ try {
206
+ meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
207
+ } catch {
208
+ continue; // missing/garbage marker → ignore this dir, keep scanning
209
+ }
210
+ const totals = meta && Array.isArray(meta.totals) ? meta.totals : [];
211
+ const blocked = totals.some(
212
+ (t) =>
213
+ t &&
214
+ t.name === 'variables' &&
215
+ t.skipped === true &&
216
+ typeof t.reason === 'string' &&
217
+ /403/.test(t.reason)
218
+ );
219
+ if (blocked) return true;
220
+ }
221
+ return false;
222
+ } catch {
223
+ // Absolute safety net — the health probe must never crash on this check.
224
+ return false;
225
+ }
226
+ }
227
+
141
228
  module.exports = { getHealthChecks };
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: gdd-figma-extract
3
+ description: Off-context Figma design-system extraction into a compact local digest (DESIGN.md + tokens.json + components.json). Pulls the file via the Figma REST API and digests it without the raw JSON ever entering the model context.
4
+ ---
5
+
6
+ # gdd-figma-extract
7
+
8
+ Pull a whole Figma design system into a compact, queryable local digest — **without** the raw JSON ever entering Claude context. The heavy lifting runs in tested `.cjs` tools; the model reads only the digest outputs.
9
+
10
+ ## Usage
11
+
12
+ ```
13
+ /gdd:figma-extract <file-key-or-url> # full design-system digest
14
+ /gdd:figma-extract <file-key-or-url> --component Button # ~500-token single-component slice
15
+ ```
16
+
17
+ `<file-key-or-url>` is a Figma file URL (`https://www.figma.com/file/<key>/…` or `/design/<key>/…`) or a bare file key.
18
+
19
+ ## Behavior
20
+
21
+ 1. **Preflight (D-10).** Confirm `FIGMA_TOKEN` is set in the environment:
22
+ ```
23
+ node -e "process.exit(process.env.FIGMA_TOKEN||process.env.FIGMA_PERSONAL_ACCESS_TOKEN?0:1)"
24
+ ```
25
+ If unset, tell the user to `export FIGMA_TOKEN=figd_…` (from https://www.figma.com/developers/api#access-tokens). The token comes from the environment **only** — never ask the user to paste it into a file or the chat, and never echo it back.
26
+
27
+ 2. **Stage 1 — pull.** Pull the file's REST endpoints into the gitignored raw cache (D-09):
28
+ ```
29
+ node scripts/lib/figma-extract/pull.cjs "<file-key-or-url>"
30
+ ```
31
+ This caches to `.figma-extract-cache/raw/<file-key>/` and skips re-pulling when Figma's `version` is unchanged (D-11). Add `--force` to bypass the cache, `--out <dir>` to relocate the cache. The tool prints a JSON summary (endpoints, bytes, cached) on stdout — the raw bodies stay on disk.
32
+
33
+ 3. **Stage 2 — plugin sync (OPTIONAL, Path C).** Only when the design tokens live in Figma Variables that the REST API cannot return (non-Enterprise plans → the pull summary shows `variables` skipped) and the user wants token coverage:
34
+ ```
35
+ node scripts/lib/figma-extract/receiver.cjs --out .figma-extract-cache/raw/<file-key>
36
+ ```
37
+ This binds `127.0.0.1:5179` (D-06). Tell the user to run the dev-installed **"GDD Sync"** plugin in Figma and click **"Export to GDD"** — see `figma-plugin/README.md` for the one-time dev-install. The receiver writes `variables.json` into the cache and exits on receipt or timeout. Skip this stage entirely for design systems whose tokens already come through the REST pull.
38
+
39
+ 4. **Stage 3 — digest.** Transform the cache into the compact digest:
40
+ ```
41
+ node scripts/lib/figma-extract/digest.cjs --raw .figma-extract-cache/raw/<file-key> --out .figma-extract-cache/digest
42
+ ```
43
+ This writes `DESIGN.md`, `tokens.json`, and `components.json`. Add `--prefer-styles` to invert the token priority to styles-first (D-04). Add `--component <name>` (D-08) to emit a single-component slice instead of the full digest.
44
+
45
+ 5. **Read the digest.** Open **only** `.figma-extract-cache/digest/DESIGN.md` (plus `tokens.json` / `components.json` when you need structured data). For a single component, pass `--component <name>` in Stage 3 and read the ~500-token slice instead of the full ~16K-token spec.
46
+
47
+ ## Required Reading
48
+
49
+ - `.figma-extract-cache/digest/DESIGN.md` — the compact human/LLM-readable spec
50
+ - `.figma-extract-cache/digest/tokens.json` — resolved design tokens (when structured token data is needed)
51
+ - `.figma-extract-cache/digest/components.json` — components with variants/props/defaults (when structured component data is needed)
52
+
53
+ ## Notes
54
+
55
+ - Two-stage pipeline (D-01): re-run Stage 3 against an existing cache without re-pulling. The digest does zero network calls.
56
+ - The spike proved **0 Claude tokens** during extraction (898× compression, 223 MB → 254 KB). That property holds only because this skill never surfaces the raw cache.
57
+ - Figma MCP remains the right tool for spot questions on a single live component; this skill is the cheaper path for whole-design-system workflows.
58
+
59
+ ## Do Not
60
+
61
+ - **Do NOT read or `cat` the `raw/*.json` cache** (e.g. `.figma-extract-cache/raw/<file-key>/file.json`). It is tool-internal and often 100+ MB; loading it into context defeats the off-context guarantee (D-12). Read only the digest outputs above.
62
+ - **Do not persist, log, echo, or print `FIGMA_TOKEN`** (D-10). It belongs in the environment only — never write it to a file, a commit, or chat output.
63
+
64
+ ## FIGMA-EXTRACT COMPLETE
@@ -53,6 +53,16 @@ Health: 5 / 6 checks passing.
53
53
  ━━━━━━━━━━━━━━━━━━━━━
54
54
  ```
55
55
 
56
+ ## Figma-extract readiness (figma_extract)
57
+
58
+ After the health table, the `gdd_health` MCP surface (`scripts/lib/health-mirror/index.cjs`) reports a `figma_extract` check so a user knows whether figma-extract is usable. The detail is one of three exact strings:
59
+
60
+ - `figma extract: ready (token set)` — `FIGMA_TOKEN` (or `FIGMA_PERSONAL_ACCESS_TOKEN`) is present (status `ok`).
61
+ - `figma extract: token missing` — no token env is set (status `warn`).
62
+ - `figma extract: plugin sync needed for variables (Free tier detected)` — token present but a prior pull recorded a 403/skip on the Variables REST path, so run the plugin-sync step (status `warn`).
63
+
64
+ Token PRESENCE only is detected (D-10) — the token value is never read, logged, or shown. The Free-tier signal is read from the local raw-pull cache only; no network call is made.
65
+
56
66
  ## Check MCP registration (gdd-mcp)
57
67
 
58
68
  After the health table, inspect whether `gdd-mcp` (Phase 27.7+) is registered with any installed harness and render a one-line status row. Dismissable via `.design/config.json#mcp_nudge=false`. Non-blocking: failure paths render `MCP server: unknown` rather than crash. Full detection procedure (dismissal check, detection via `scripts/lib/install/mcp-register.cjs`, row rendering for claude/codex/both/neither, fallback) lives in `./health-mcp-detection.md`.