@hegemonart/get-design-done 1.30.5 → 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.
Files changed (43) hide show
  1. package/.claude-plugin/marketplace.json +6 -3
  2. package/.claude-plugin/plugin.json +5 -2
  3. package/CHANGELOG.md +129 -0
  4. package/README.md +22 -1
  5. package/SKILL.md +1 -0
  6. package/agents/design-integration-checker.md +1 -1
  7. package/agents/design-planner.md +1 -1
  8. package/agents/gdd-graph-refresh.md +90 -0
  9. package/bin/gdd-graph +261 -0
  10. package/connections/connections.md +10 -9
  11. package/connections/graphify.md +65 -54
  12. package/package.json +8 -3
  13. package/reference/capability-gap-stage-gate.md +7 -4
  14. package/reference/model-tiers.md +2 -2
  15. package/reference/start-interview.md +1 -1
  16. package/scripts/detect-stale-refs.cjs +6 -0
  17. package/scripts/lib/figma-extract/digest.cjs +430 -0
  18. package/scripts/lib/figma-extract/parse-url.cjs +87 -0
  19. package/scripts/lib/figma-extract/payload-schema.json +108 -0
  20. package/scripts/lib/figma-extract/pull.cjs +394 -0
  21. package/scripts/lib/figma-extract/receiver.cjs +273 -0
  22. package/scripts/lib/figma-extract/render-md.cjs +143 -0
  23. package/scripts/lib/figma-extract/styles-resolver.cjs +147 -0
  24. package/scripts/lib/figma-extract/walk.cjs +100 -0
  25. package/scripts/lib/graph/atomic-write.mjs +68 -0
  26. package/scripts/lib/graph/build.mjs +124 -0
  27. package/scripts/lib/graph/diff.mjs +90 -0
  28. package/scripts/lib/graph/index.mjs +14 -0
  29. package/scripts/lib/graph/query.mjs +155 -0
  30. package/scripts/lib/graph/schema.json +69 -0
  31. package/scripts/lib/graph/schema.mjs +47 -0
  32. package/scripts/lib/graph/status.mjs +88 -0
  33. package/scripts/lib/graph/token-estimate.mjs +27 -0
  34. package/scripts/lib/graph/upsert.mjs +210 -0
  35. package/scripts/lib/{gsd-health-mirror → health-mirror}/index.cjs +89 -2
  36. package/scripts/mcp-servers/gdd-mcp/tools/gdd_health.ts +3 -3
  37. package/skills/connections/connections-onboarding.md +6 -6
  38. package/skills/figma-extract/SKILL.md +64 -0
  39. package/skills/graphify/SKILL.md +11 -10
  40. package/skills/health/SKILL.md +10 -0
  41. package/skills/scan/scan-procedure.md +9 -8
  42. package/agents/gdd-graphify-sync.md +0 -110
  43. /package/scripts/lib/{gsd-health-mirror → health-mirror}/index.d.cts +0 -0
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
- // scripts/lib/gsd-health-mirror/index.cjs — Plan 27.7-02
2
+ // scripts/lib/health-mirror/index.cjs — Plan 27.7-02 (renamed in Phase 30.6-08 per D-10)
3
3
  //
4
4
  // Pure read-only mirror of skills/health/SKILL.md's check surface.
5
5
  // NO subprocess spawn — just inspects 4 well-known files/dirs and
@@ -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 };
@@ -1,9 +1,9 @@
1
1
  // scripts/mcp-servers/gdd-mcp/tools/gdd_health.ts
2
2
  //
3
- // Plan 27.7-02. Read-only mirror of skills/health/SKILL.md output via
4
- // scripts/lib/gsd-health-mirror/. No subprocess spawn — pure inspection.
3
+ // Plan 27.7-02 (lib renamed to health-mirror in Phase 30.6-08 per D-10).
4
+ // Read-only mirror of skills/health/SKILL.md output. No subprocess spawn — pure inspection.
5
5
 
6
- import { getHealthChecks } from '../../../lib/gsd-health-mirror/index.cjs';
6
+ import { getHealthChecks } from '../../../lib/health-mirror/index.cjs';
7
7
  import { errorResponse, okResponse, resolveProjectRoot, type ToolResponse } from './shared.ts';
8
8
 
9
9
  export const name = 'gdd_health';
@@ -106,13 +106,13 @@ Bash: command -v chromatic >/dev/null 2>&1 || npx --yes chromatic --version 2>/d
106
106
  Set → chromatic: available
107
107
  ```
108
108
 
109
- **graphify** (CLI + file):
109
+ **graphify** (native CLI + file):
110
110
  ```
111
- Bash: node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify status 2>/dev/null
112
- Error or enabled:false → graphify: not_configured
113
- enabled:true check graphify-out/graph.json exists
114
- Absent → graphify: unavailable
115
- Present → graphify: available
111
+ Bash: node -e "try{const c=JSON.parse(require('fs').readFileSync('.design/config.json','utf8'));process.stdout.write(String(c.graphify?.enabled===true))}catch{process.stdout.write('false')}"
112
+ → false → graphify: not_configured
113
+ → true Bash: node bin/gdd-graph status --format json
114
+ { configured: true, exists: false } → graphify: unavailable
115
+ { configured: true, exists: true } → graphify: available
116
116
  ```
117
117
 
118
118
  **pencil-dev** (file probe):
@@ -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
@@ -19,30 +19,31 @@ Thin command wrapper around the GSD graphify tools integration.
19
19
  ## Behavior
20
20
 
21
21
  1. Read `.design/STATE.md` to check `graphify` status in `<connections>`.
22
- 2. Check `graphify.enabled` in `.planning/config.json` via:
22
+ 2. Check `graphify.enabled` in `.design/config.json` via a direct file read (per D-09 — no `config-get` CLI subcommand):
23
23
  ```
24
- node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get graphify.enabled
24
+ node -e "try{const c=JSON.parse(require('fs').readFileSync('.design/config.json','utf8'));process.stdout.write(String(c.graphify?.enabled===true))}catch{process.stdout.write('false')}"
25
25
  ```
26
26
  3. If not enabled, print:
27
27
  ```
28
- "Graphify is not enabled. Enable with: node gsd-tools.cjs config-set graphify.enabled true"
28
+ "Graphify is not enabled. Edit `.design/config.json` to set `graphify.enabled: true`."
29
29
  "Then run /gdd:graphify build to generate the knowledge graph."
30
30
  ```
31
31
  STOP.
32
- 4. Execute the requested subcommand via GSD tools:
33
- - build: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify build`
34
- - query: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify query "<term>" --budget 2000`
35
- - status: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify status`
36
- - diff: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify diff`
32
+ 4. Execute the requested subcommand via the native CLI:
33
+ - build: `node bin/gdd-graph build`
34
+ - query: `node bin/gdd-graph query "<term>" --budget 2000`
35
+ - status: `node bin/gdd-graph status`
36
+ - diff: `node bin/gdd-graph diff`
37
37
  5. After `build` completes, update `.design/STATE.md` `<connections>`: `graphify: available`
38
38
 
39
39
  ## Required Reading
40
40
 
41
41
  - `.design/STATE.md` — for graphify status in `<connections>`
42
- - `.planning/config.json` — for `graphify.enabled` flag
42
+ - `.design/config.json` — for `graphify.enabled` flag
43
43
 
44
44
  ## Notes
45
45
 
46
- - Graphify is optional. If the binary is not installed (`pip install graphifyy`), the build subcommand will fail with an install prompt.
46
+ - Graphify is optional. The native CLI ships in this repo at `bin/gdd-graph` (no external install Node only).
47
+ - Graph is stored at `.design/graph/graph.json` (Ajv-validated against `scripts/lib/graph/schema.json`).
47
48
  - Graph covers source code (`src/`, `components/`). It does NOT index `.design/` artifacts by default.
48
49
  - Use `query` with node IDs from the graph schema: `component:<name>`, `token:color/<name>`, `decision:D-<nn>`, etc.
@@ -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`.
@@ -136,14 +136,15 @@ Write: chromatic: <status> to STATE.md <connections>
136
136
 
137
137
  ```
138
138
  Step G1 — Config check:
139
- Bash: node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify status
140
- -> Error or { enabled: false } -> graphify: not_configured
141
- -> { enabled: true } -> proceed to Step G2
142
-
143
- Step G2 — Graph file check:
144
- Bash: test -f graphify-out/graph.json
145
- -> Present -> graphify: available
146
- -> Absent -> graphify: unavailable
139
+ Bash: node -e "try{const c=JSON.parse(require('fs').readFileSync('.design/config.json','utf8'));process.stdout.write(String(c.graphify?.enabled===true))}catch{process.stdout.write('false')}"
140
+ -> false -> graphify: not_configured
141
+ -> true -> proceed to Step G2
142
+
143
+ Step G2 — Graph file check (status JSON):
144
+ Bash: node bin/gdd-graph status --format json
145
+ -> { configured: true, exists: true, ... } -> graphify: available
146
+ -> { configured: false, exists: false } or -> graphify: unavailable
147
+ { exists: false }
147
148
 
148
149
  Write: graphify: <status> to STATE.md <connections>
149
150
  ```
@@ -1,110 +0,0 @@
1
- ---
2
- name: gdd-graphify-sync
3
- description: "Feeds the Graphify knowledge graph from .design/intel/ slices. Converts intel store graph.json nodes and edges into Graphify-compatible format and upserts them. Run after gdd-intel-updater to keep the semantic graph current."
4
- tools: Bash, Read, Write
5
- color: green
6
- default-tier: haiku
7
- tier-rationale: "Sync operation is deterministic JSON → graph DB — cheap Haiku is enough"
8
- parallel-safe: false
9
- typical-duration-seconds: 20
10
- reads-only: false
11
- writes:
12
- - .design/intel/graph.json
13
- ---
14
-
15
- @reference/shared-preamble.md
16
-
17
- # gdd-graphify-sync
18
-
19
- **Role:** Bridge between the flat intel store and the Graphify semantic knowledge graph. Reads `graph.json` from the intel store and upserts nodes/edges into Graphify using the `gsd-tools.cjs graphify` CLI.
20
-
21
- ## When to invoke
22
-
23
- - After `gdd-intel-updater` completes (intel store updated)
24
- - After a phase plan that adds new skill/agent/reference files
25
- - When semantic graph queries return stale results
26
-
27
- ## Protocol
28
-
29
- ### Step 1 — Check intel store graph slice
30
-
31
- ```bash
32
- ls .design/intel/graph.json 2>/dev/null && echo "ready" || echo "missing"
33
- ```
34
-
35
- If missing: print "Intel store graph.json not found — run node scripts/build-intel.cjs --force first." and stop.
36
-
37
- ### Step 2 — Check Graphify availability
38
-
39
- ```bash
40
- node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify status 2>/dev/null | head -5
41
- ```
42
-
43
- If Graphify is unavailable or returns an error: print "Graphify unavailable — skipping sync. Intel store remains the primary lookup source." and stop gracefully (exit 0, do not fail).
44
-
45
- ### Step 3 — Read graph.json
46
-
47
- Read `.design/intel/graph.json`. Extract `nodes` and `edges` arrays.
48
-
49
- ### Step 4 — Upsert nodes
50
-
51
- For each node in `nodes`:
52
-
53
- ```bash
54
- node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify upsert-node \
55
- --id "<node.id>" \
56
- --type "<node.type>" \
57
- --label "<node.name>" \
58
- --source "gdd-intel-store"
59
- ```
60
-
61
- Batch in groups of 20 to avoid CLI argument limits. Report total nodes upserted.
62
-
63
- ### Step 5 — Upsert edges
64
-
65
- For each edge in `edges`:
66
-
67
- ```bash
68
- node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify upsert-edge \
69
- --from "<edge.from>" \
70
- --to "<edge.to>" \
71
- --kind "<edge.kind>" \
72
- --source "gdd-intel-store"
73
- ```
74
-
75
- Batch in groups of 20. Report total edges upserted.
76
-
77
- ### Step 6 — Verify sync
78
-
79
- ```bash
80
- node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify status
81
- ```
82
-
83
- Print the status response. Report node/edge counts in Graphify vs intel store.
84
-
85
- ### Step 7 — Summary
86
-
87
- ```
88
- ━━━ Graphify sync complete ━━━
89
- Nodes upserted: <N>
90
- Edges upserted: <M>
91
- Graphify status: <status line>
92
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
93
- ```
94
-
95
- ## Required reading (conditional)
96
-
97
- @.design/intel/graph.json (if present)
98
- @.design/intel/files.json (if present)
99
-
100
- ## GRAPHIFY-SYNC COMPLETE
101
-
102
- ## Record
103
-
104
- At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
105
-
106
- ```json
107
- {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
108
- ```
109
-
110
- Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.