@hegemonart/get-design-done 1.50.1 → 1.52.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 (52) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +93 -0
  4. package/README.md +4 -0
  5. package/SKILL.md +4 -1
  6. package/agents/a11y-mapper.md +30 -1
  7. package/agents/component-taxonomy-mapper.md +30 -1
  8. package/agents/design-debt-crawler.md +60 -60
  9. package/agents/design-reflector.md +33 -0
  10. package/agents/design-research-synthesizer.md +27 -1
  11. package/agents/motion-mapper.md +35 -13
  12. package/agents/token-mapper.md +30 -1
  13. package/agents/visual-hierarchy-mapper.md +30 -1
  14. package/dist/claude-code/.claude/skills/apply-reflections/SKILL.md +17 -0
  15. package/dist/claude-code/.claude/skills/context/SKILL.md +137 -0
  16. package/dist/claude-code/.claude/skills/extract-learnings/SKILL.md +16 -0
  17. package/dist/claude-code/.claude/skills/instinct/SKILL.md +111 -0
  18. package/dist/claude-code/.claude/skills/migrate-context/SKILL.md +123 -0
  19. package/dist/claude-code/.claude/skills/progress/SKILL.md +4 -0
  20. package/hooks/gdd-decision-injector.js +115 -6
  21. package/package.json +3 -2
  22. package/reference/design-context-schema.md +159 -0
  23. package/reference/design-context-tag-vocab.md +82 -0
  24. package/reference/instinct-format.md +120 -0
  25. package/reference/registry.json +21 -0
  26. package/reference/schemas/design-context.schema.json +130 -0
  27. package/reference/schemas/events.schema.json +1 -1
  28. package/reference/schemas/instinct.schema.json +91 -0
  29. package/reference/schemas/mcp-gdd-tools.schema.json +34 -1
  30. package/reference/skill-graph.md +4 -1
  31. package/scripts/lib/design-context/extract-a11y.mjs +188 -0
  32. package/scripts/lib/design-context/extract-components.mjs +243 -0
  33. package/scripts/lib/design-context/extract-motion.mjs +248 -0
  34. package/scripts/lib/design-context/extract-tokens.mjs +234 -0
  35. package/scripts/lib/design-context/extract-visual-hierarchy.mjs +178 -0
  36. package/scripts/lib/design-context/integration-map.mjs +251 -0
  37. package/scripts/lib/design-context/merge-fragments.mjs +227 -0
  38. package/scripts/lib/design-context-query.cjs +0 -0
  39. package/scripts/lib/instinct-store.cjs +677 -0
  40. package/scripts/lib/manifest/skills.json +24 -0
  41. package/scripts/lib/mcp-tools-lint/index.cjs +3 -1
  42. package/sdk/mcp/gdd-mcp/schemas/gdd_context_query.schema.json +60 -0
  43. package/sdk/mcp/gdd-mcp/server.js +474 -158
  44. package/sdk/mcp/gdd-mcp/server.ts +9 -5
  45. package/sdk/mcp/gdd-mcp/tools/gdd_context_query.ts +35 -0
  46. package/sdk/mcp/gdd-mcp/tools/index.ts +18 -13
  47. package/skills/apply-reflections/SKILL.md +17 -0
  48. package/skills/context/SKILL.md +137 -0
  49. package/skills/extract-learnings/SKILL.md +16 -0
  50. package/skills/instinct/SKILL.md +111 -0
  51. package/skills/migrate-context/SKILL.md +123 -0
  52. package/skills/progress/SKILL.md +4 -0
@@ -14,7 +14,8 @@
14
14
  // Zod shapes, and our per-tool schemas are Draft-07 JSON.)
15
15
  // 2. Register `tools/list` — returns the registered tools with their
16
16
  // input JSON Schemas loaded from disk. Scaffold ships with 0
17
- // tools; Plan 27.7-02 populates `TOOL_MODULES` with 12 entries.
17
+ // tools; Plan 27.7-02 populated `TOOL_MODULES` with 12 entries;
18
+ // Phase 52 raised it to 13 (gdd_context_query, D5).
18
19
  // 3. Register `tools/call` — dispatches by name to the matching
19
20
  // handler. Each handler returns a typed ToolResponse; the server
20
21
  // wraps it into the MCP CallToolResult shape. Unknown tool names
@@ -89,8 +90,8 @@ function here(): string {
89
90
  * restart, which matches every other part of the pipeline.
90
91
  *
91
92
  * Scaffold ships with 0 tools — loadTools() returns []. Plan 27.7-02
92
- * adds 12 tool modules, each with its own `schemaPath` pointing into
93
- * `sdk/mcp/gdd-mcp/schemas/`. */
93
+ * added 12 tool modules; Phase 52 raised it to 13. Each has its own
94
+ * `schemaPath` pointing into `sdk/mcp/gdd-mcp/schemas/`. */
94
95
  interface LoadedTool extends ToolModule {
95
96
  inputSchema: Record<string, unknown>;
96
97
  }
@@ -124,12 +125,14 @@ function loadTools(): LoadedTool[] {
124
125
  * Tool descriptions — short, scannable, lifted from the plan. Skill
125
126
  * prose uses these verbatim when suggesting a tool to the model.
126
127
  *
127
- * Plan 27.7-02 populates 12 entries one per tool name in the canonical
128
- * 12-tool list.
128
+ * Plan 27.7-02 populated 12 entries; Phase 52 added a 13th
129
+ * (gdd_context_query) — one per tool name in the canonical 13-tool list.
129
130
  */
130
131
  export const TOOL_DESCRIPTIONS: Record<string, string> = {
131
132
  gdd_status:
132
133
  'gdd_status: current cycle phase, branch, last-3 decisions, last-3 completed plans, blocker count.',
134
+ gdd_context_query:
135
+ 'gdd_context_query: read-only query over the DesignContext graph (.design/context-graph.json) — op one of nodes/edges/path/consumers-of/unreachable/cycles/coverage; structured no-graph result when absent.',
133
136
  gdd_phase_current:
134
137
  'gdd_phase_current: STATE.md <position> block (phase, stage, task_progress, status).',
135
138
  gdd_phases_list:
@@ -159,6 +162,7 @@ export const TOOL_DESCRIPTIONS: Record<string, string> = {
159
162
  * modify disk. v1 is read-only (D-04) so every entry is `true`. */
160
163
  export const TOOL_READONLY: Record<string, boolean> = {
161
164
  gdd_status: true,
165
+ gdd_context_query: true,
162
166
  gdd_phase_current: true,
163
167
  gdd_phases_list: true,
164
168
  gdd_plans_list: true,
@@ -0,0 +1,35 @@
1
+ // sdk/mcp/gdd-mcp/tools/gdd_context_query.ts
2
+ //
3
+ // Phase 52 (DesignContext graph keystone). Read-only query surface over the
4
+ // typed DesignContext graph at `.design/context-graph.json`. Thin tool: the
5
+ // fs read + every query lives in scripts/lib/design-context-query.cjs (sibling
6
+ // A); this file only dispatches `op`. Graceful: a missing/unreadable graph
7
+ // returns a structured `{ graph_present: false }` result rather than throwing
8
+ // (the same missing-data discipline the other read tools follow).
9
+
10
+ import {
11
+ load, nodes, edges, path as findPath, consumersOf, unreachable, cycles, coverage,
12
+ } from '../../../../scripts/lib/design-context-query.cjs';
13
+ import { errorResponse, okResponse, resolveProjectRoot, type ToolResponse } from './shared.ts';
14
+
15
+ export const name = 'gdd_context_query';
16
+ export const schemaPath = '../schemas/gdd_context_query.schema.json';
17
+
18
+ interface CtxInput { op?: string; type?: string; tag?: string; from?: string; to?: string; id?: string; }
19
+
20
+ export async function handle(input: unknown): Promise<ToolResponse> {
21
+ try {
22
+ const t = (input ?? {}) as CtxInput;
23
+ let graph: unknown = null;
24
+ const ops: Record<string, () => unknown> = {
25
+ nodes: () => nodes(graph, { type: t.type, tag: t.tag }), edges: () => edges(graph, { type: t.type }),
26
+ path: () => findPath(graph, t.from, t.to), 'consumers-of': () => consumersOf(graph, t.id),
27
+ unreachable: () => unreachable(graph), cycles: () => cycles(graph), coverage: () => coverage(graph),
28
+ };
29
+ const fn = t.op ? ops[t.op] : undefined;
30
+ if (!fn) return errorResponse(new Error('op is required — one of: ' + Object.keys(ops).join(', ')));
31
+ try { graph = load(resolveProjectRoot() + '/.design/context-graph.json'); } catch { graph = null; }
32
+ if (!graph) return okResponse({ op: t.op, graph_present: false, result: null });
33
+ return okResponse({ op: t.op, graph_present: true, result: fn() });
34
+ } catch (err) { return errorResponse(err); }
35
+ }
@@ -1,8 +1,9 @@
1
1
  // sdk/mcp/gdd-mcp/tools/index.ts
2
2
  //
3
- // Tool registry for `gdd-mcp`. Plan 27.7-02 populates with 12 read-only
4
- // tools. The 12-tool cap is D-03 (hard); enforced at module load by a
5
- // runtime check + by tests in Plan 27.7-03.
3
+ // Tool registry for `gdd-mcp`. Plan 27.7-02 populated this with 12 read-only
4
+ // tools. Phase 52 (DesignContext keystone, D5) adds a 13th read-only tool
5
+ // (`gdd_context_query`) and bumps the cap 12 -> 13. The cap is D-03 (hard);
6
+ // enforced at module load by a runtime check + by tests in Plan 27.7-03.
6
7
  //
7
8
  // Convention (mirrors Phase 20 `gdd-state`):
8
9
  // - Each tool exports `name`, `schemaPath`, and `handle` from its own
@@ -15,6 +16,7 @@
15
16
 
16
17
  import type { ToolResponse } from './shared.ts';
17
18
 
19
+ import * as gdd_context_query from './gdd_context_query.ts';
18
20
  import * as gdd_cycle_recap from './gdd_cycle_recap.ts';
19
21
  import * as gdd_decisions_list from './gdd_decisions_list.ts';
20
22
  import * as gdd_events_tail from './gdd_events_tail.ts';
@@ -39,12 +41,14 @@ export interface ToolModule {
39
41
  }
40
42
 
41
43
  /**
42
- * Canonical tool registry. 12 tools (D-03 hard cap). Order is
44
+ * Canonical tool registry. 13 tools (D-03 cap, raised 12 -> 13 in Phase 52
45
+ * for the read-only `gdd_context_query` DesignContext surface, D5). Order is
43
46
  * alphabetical (after `gdd_status` which leads as the canonical entry).
44
47
  * All tools are advertised equivalently in `tools/list`.
45
48
  */
46
49
  export const TOOL_MODULES: readonly ToolModule[] = [
47
50
  gdd_status,
51
+ gdd_context_query,
48
52
  gdd_cycle_recap,
49
53
  gdd_decisions_list,
50
54
  gdd_events_tail,
@@ -58,18 +62,19 @@ export const TOOL_MODULES: readonly ToolModule[] = [
58
62
  gdd_telemetry_query,
59
63
  ] as const;
60
64
 
61
- /** Canonical count. The plan caps this at 12 — if you add a tool past
62
- * that bound, update the plan, the combined schema, and the lint
65
+ /** Canonical count. The cap is 13 (raised from 12 in Phase 52) — if you add a
66
+ * tool past that bound, update the plan, the combined schema, and the lint
63
67
  * test (Plan 27.7-03). */
64
68
  export const TOOL_COUNT: number = TOOL_MODULES.length;
65
69
 
66
- // Module-load runtime assertion of the 12-tool cap (D-03). A compile-time
67
- // type guard is fragile against `readonly ToolModule[]` (the length type
68
- // widens to `number`); the runtime check is cheap, deterministic, and
69
- // fails fast on server boot if the registry ever drifts past the cap.
70
- if (TOOL_COUNT > 12) {
70
+ // Module-load runtime assertion of the 13-tool cap (D-03, raised from 12 in
71
+ // Phase 52). A compile-time type guard is fragile against `readonly
72
+ // ToolModule[]` (the length type widens to `number`); the runtime check is
73
+ // cheap, deterministic, and fails fast on server boot if the registry ever
74
+ // drifts past the cap.
75
+ if (TOOL_COUNT > 13) {
71
76
  throw new Error(
72
- `gdd-mcp: TOOL_COUNT=${TOOL_COUNT} exceeds the 12-tool cap (D-03). ` +
73
- 'Add tool past 12 requires re-scoping in a new plan.',
77
+ `gdd-mcp: TOOL_COUNT=${TOOL_COUNT} exceeds the 13-tool cap (D-03, raised ` +
78
+ 'from 12 in Phase 52). Adding a tool past 13 requires re-scoping in a new plan.',
74
79
  );
75
80
  }
@@ -84,6 +84,23 @@ Incubator drafts authored by `scripts/lib/incubator-author.cjs` (Phase 29-04) ap
84
84
 
85
85
  KFM-catalogue proposals authored by `scripts/lib/reflector-kfm-proposer.cjs` (Phase 30.5-03 D-05) appear as a 6th proposal class. Drafts at `.design/reflections/incubator/kfm-<slug>/CATALOGUE-ENTRY.md`; pre-filled 11-field schema with `TODO:` placeholders for `pattern` + `fix`. Two upstream signals share the surface (D-06): `capability_gap` clusters (≥3, no existing match) + `kfm-candidate` events (whitelist-matched articles, 1-shot). User chooses **accept** | **reject** | **defer** | **edit**. `applyAccept` appends to `reference/known-failure-modes.md` + `reference/registry.json` (`origin: incubator-kfm`); `applyReject` removes the incubator subdir; `applyDefer` stamps `deferred_until`; `applyEdit` returns the draft path for `$EDITOR`. Full procedure: `./apply-reflections-procedure.md` §[KFM-CANDIDATE].
86
86
 
87
+ ## [INSTINCT]
88
+
89
+ Atomic instinct units emitted by `design-reflector` (and surfaced from `/gdd:extract-learnings`) appear as a distinct proposal class, alongside `[INCUBATOR]` and `[KFM-CANDIDATE]`. Each unit is a fenced `yaml` block under the reflector's `## Atomic instincts` section, shaped per `reference/instinct-format.md` (`id`, `trigger`, `confidence`, `domain`, `scope`, `project_id`, `source`, `cycles_seen`, `first_seen`, `last_seen`, plus a short body). A unit is a proposal, never a stored fact - nothing lands until the user accepts it.
90
+
91
+ Mirror the `[INCUBATOR]` flow:
92
+
93
+ 1. Discover the units: parse every `yaml` block under `## Atomic instincts` in the reflections file. Skip malformed blocks (warn on stderr, keep going).
94
+ 2. For each unit: show the parsed `trigger`, `domain`, `confidence`, and body so the user sees what would be stored.
95
+ 3. Prompt: `(a) accept (r) reject (d) defer (e) edit (q) quit`.
96
+
97
+ **Per-action behavior:**
98
+
99
+ 1. **accept** - call `scripts/lib/instinct-store.cjs` `add(unit, { scope, baseDir })` with the unit at its emitted `confidence`. The store owns de-duplication and `cycles_seen` bookkeeping. On success print `Stored instinct <id> (<domain>, confidence <n>).` and append `**Applied**: <date>` to the proposal block.
100
+ 2. **reject** - do not store the unit. Append `**Reviewed: rejected**` to the reflections file.
101
+ 3. **defer** - no-op; the unit re-surfaces next run. Append `**Reviewed: deferred**`.
102
+ 4. **edit** - let the user adjust `trigger`, `confidence`, or `domain`, then accept the edited unit through the same `add(...)` call. Default `scope: 'project'` (write `global` only when the unit's frontmatter says so); never edit `.design/instincts/instincts.json` directly, and promote to global via the separate gated `/gdd:instinct promote`.
103
+
87
104
  ## Do Not
88
105
 
89
106
  - Do not apply any proposal without the user explicitly choosing `a` or `e`.
@@ -0,0 +1,137 @@
1
+ ---
2
+ name: gdd-context
3
+ description: "Queries the typed DesignContext graph at .design/context-graph.json - the design-semantic map of tokens, components, variants, states, motion, a11y patterns, screens, layers, and design patterns plus the edges between them. Lists and filters nodes and edges, traces a path between two nodes, finds the consumers of a node, and reports unreachable nodes, dependency cycles, and coverage. Use when the user wants to inspect the design graph, find what depends on a token or component, trace how one node reaches another, or check graph health. Activates for requests involving the design context graph, design dependencies, token consumers, component composition, unreachable design nodes, design cycles, or design coverage."
4
+ argument-hint: "[nodes --type X | edges --type Z | path <a> <b> | consumers-of <id> | unreachable | cycles | coverage]"
5
+ tools: Read, Bash
6
+ user-invocable: true
7
+ ---
8
+
9
+ # /gdd:context
10
+
11
+ **Role:** Read-only front end for the typed DesignContext graph. The graph is a design-semantic map: nodes are tokens, components, variants, states, motion fragments, a11y patterns, screens, layers, and design patterns; edges connect them (uses-token, composes, extends, transitions-to, depends-on, mirrors, conflicts-with, referenced-by, tested-by, documented-by, consumes-context, provides-context). This skill queries that graph. It never writes to it. The graph is authored by the mapper agents plus the design-research-synthesizer; this skill only reads.
12
+
13
+ The query engine ships at `scripts/lib/design-context-query.cjs` (authored elsewhere; this skill only calls it). It is pure and dep-free, exposing `load`, `nodes`, `edges`, `path`, `consumersOf`, `unreachable`, `cycles`, and `coverage`. The merged graph lives at `.design/context-graph.json` with the shape `{ schema_version, generated_at, nodes[], edges[] }`.
14
+
15
+ If `.design/context-graph.json` is absent, print: `No DesignContext graph yet. Run the design research pipeline (mappers plus /gdd:synthesize) to generate .design/context-graph.json.` Then STOP. Do not invent a graph.
16
+
17
+ The engine exposes a module API rather than a CLI, so drive it from a short `node -e` script, the same way other skills call a `scripts/lib` helper:
18
+
19
+ ```bash
20
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
21
+ const g=q.load('.design/context-graph.json'); \
22
+ console.log(JSON.stringify(q.nodes(g, { type: process.env.NODE_TYPE || undefined, tag: process.env.TAG || undefined })));"
23
+ ```
24
+
25
+ ## Invocation Modes
26
+
27
+ | Command | Behavior |
28
+ |---|---|
29
+ | `/gdd:context nodes` | List graph nodes, optionally filtered by `--type` and `--tag` (default mode). |
30
+ | `/gdd:context edges` | List graph edges, optionally filtered by `--type`. |
31
+ | `/gdd:context path <a> <b>` | Trace a path from node `<a>` to node `<b>`. |
32
+ | `/gdd:context consumers-of <id>` | List the nodes that consume node `<id>`. |
33
+ | `/gdd:context unreachable` | List nodes no edge reaches. |
34
+ | `/gdd:context cycles` | List dependency cycles in the graph. |
35
+ | `/gdd:context coverage` | Report graph coverage (typed and tagged ratios). |
36
+
37
+ Output discipline: emit JSON when a tool or another skill is the caller; render a compact table when a person is at the terminal.
38
+
39
+ ## nodes
40
+
41
+ List nodes. `--type <t>` filters by node type (token, component, variant, state, motion-fragment, a11y-pattern, screen, layer, pattern, anti-pattern). `--tag <tag>` filters by a controlled tag. Call `nodes(graph, { type, tag })`:
42
+
43
+ ```bash
44
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
45
+ const g=q.load('.design/context-graph.json'); \
46
+ console.log(JSON.stringify(q.nodes(g, { type: process.env.NODE_TYPE || undefined, tag: process.env.TAG || undefined })));"
47
+ ```
48
+
49
+ Render one row per node. Keep it scannable:
50
+
51
+ ```
52
+ ID TYPE COMPLEXITY NAME
53
+ token:color/brand token simple Brand primary
54
+ component:Button component moderate Button
55
+ ```
56
+
57
+ If no nodes match, say so plainly and suggest a broader filter.
58
+
59
+ ## edges
60
+
61
+ List edges. `--type <t>` filters by edge type (uses-token, composes, extends, transitions-to, depends-on, mirrors, conflicts-with, referenced-by, tested-by, documented-by, consumes-context, provides-context). Call `edges(graph, { type })`:
62
+
63
+ ```bash
64
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
65
+ const g=q.load('.design/context-graph.json'); \
66
+ console.log(JSON.stringify(q.edges(g, { type: process.env.EDGE_TYPE || undefined })));"
67
+ ```
68
+
69
+ Render `source -> target (type, weight)` per row. If none match, report it and suggest dropping the filter.
70
+
71
+ ## path
72
+
73
+ Trace a path between two node ids. Call `path(graph, from, to)`:
74
+
75
+ ```bash
76
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
77
+ const g=q.load('.design/context-graph.json'); \
78
+ console.log(JSON.stringify(q.path(g, process.env.FROM, process.env.TO)));"
79
+ ```
80
+
81
+ Print the ordered node ids joined by arrows. If no path exists, print `No path from <a> to <b>.` Do not fabricate intermediate nodes.
82
+
83
+ ## consumers-of
84
+
85
+ List the nodes that consume a given node (the inbound side). Call `consumersOf(graph, id)`:
86
+
87
+ ```bash
88
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
89
+ const g=q.load('.design/context-graph.json'); \
90
+ console.log(JSON.stringify(q.consumersOf(g, process.env.ID)));"
91
+ ```
92
+
93
+ Render the consumer ids one per row. If the id is unknown, print `No node <id> in the graph.` and suggest `/gdd:context nodes`.
94
+
95
+ ## unreachable
96
+
97
+ List nodes that no edge reaches (orphans). Call `unreachable(graph)`:
98
+
99
+ ```bash
100
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
101
+ const g=q.load('.design/context-graph.json'); \
102
+ console.log(JSON.stringify(q.unreachable(g)));"
103
+ ```
104
+
105
+ If the list is empty, print `Every node is reachable.`
106
+
107
+ ## cycles
108
+
109
+ List dependency cycles. Call `cycles(graph)`:
110
+
111
+ ```bash
112
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
113
+ const g=q.load('.design/context-graph.json'); \
114
+ console.log(JSON.stringify(q.cycles(g)));"
115
+ ```
116
+
117
+ Print each cycle as its ordered node ids. If there are none, print `No cycles detected.`
118
+
119
+ ## coverage
120
+
121
+ Report graph coverage. Call `coverage(graph)`:
122
+
123
+ ```bash
124
+ node -e "const q=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/design-context-query.cjs'); \
125
+ const g=q.load('.design/context-graph.json'); \
126
+ console.log(JSON.stringify(q.coverage(g)));"
127
+ ```
128
+
129
+ Surface the returned ratios (for example typed and tagged coverage and node and edge counts) as a short summary.
130
+
131
+ ## Do Not
132
+
133
+ - Do not edit `.design/context-graph.json` or the fragments under `.design/fragments/`. All writes go through the mapper agents and the synthesizer.
134
+ - Do not invent nodes, edges, or paths. If a query returns nothing, report it plainly.
135
+ - Do not modify `scripts/lib/design-context-query.cjs` or the DesignContext schema.
136
+
137
+ ## CONTEXT COMPLETE
@@ -53,6 +53,22 @@ Layout of `.design/learnings/LEARNINGS.md`:
53
53
  ---
54
54
  ```
55
55
 
56
+ ### Step 3b - Dual-emit atomic instinct units (Phase 51)
57
+
58
+ Alongside the prose `LEARNINGS.md`, emit atomic instinct units for every learning the extractor tags as an `instinct-candidate`. A learning is an `instinct-candidate` when it states a single trigger plus a one-line response - the same shape the reflector emits. Broader narrative learnings stay prose-only.
59
+
60
+ For each `instinct-candidate`, build a unit per `reference/instinct-format.md` (frontmatter: `id`, `trigger`, `confidence` from 0.3 to 0.9, `domain`, `scope`, `project_id`, `source`, `cycles_seen`, `first_seen`, `last_seen`, plus a short body). Set `source: extract-learnings`. Carry the learning's confidence (high / medium / low) into the numeric field (roughly 0.8 / 0.55 / 0.35), capped at 0.9.
61
+
62
+ Write each unit through the store engine `scripts/lib/instinct-store.cjs` rather than by hand:
63
+
64
+ ```bash
65
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/lib/instinct-store.cjs" add --scope project
66
+ ```
67
+
68
+ If the engine exposes a module API only, drive `add(unit, { scope: 'project', baseDir })` from a short `node -e` script. The engine owns de-duplication and `cycles_seen` bookkeeping; do not pre-merge.
69
+
70
+ The prose `LEARNINGS.md` is **retained read-only for one minor version** so existing readers keep working while tooling migrates to the units. Keep writing it; do not drop the prose path in this version.
71
+
56
72
  ### Step 4 - Reference file proposal (optional)
57
73
 
58
74
  After writing LEARNINGS.md, check each learning entry with `Proposed reference update: yes`.
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: gdd-instinct
3
+ description: "Inspects and manages atomic instinct learning units - small, scoped, confidence-weighted patterns the pipeline accumulates across cycles. Lists the project and global instinct stores, searches them by keyword, and promotes a vetted project instinct to the global store once it has cleared the cross-project gate. Use when the user wants to see what instincts exist, find an instinct by topic, or promote one to global scope. Activates for requests involving instincts, learned patterns, instinct promotion, instinct search, or the instinct store."
4
+ argument-hint: "[list | query <keyword> | promote <id>] [--scope project|global] [--domain <d>]"
5
+ tools: Read, Bash
6
+ user-invocable: true
7
+ ---
8
+
9
+ # /gdd:instinct
10
+
11
+ **Role:** Front end for the atomic instinct store. An instinct is a single learned pattern with a trigger, a confidence between 0.3 and 0.9, a domain, and a scope. This skill lists, searches, and promotes instincts. It never edits stored units by hand and never invents new ones - the reflector and `/gdd:extract-learnings` author them.
12
+
13
+ The store engine ships at `scripts/lib/instinct-store.cjs` (authored elsewhere - this skill only calls it). Unit shape (YAML frontmatter plus a short body) is specified in `reference/instinct-format.md`. The project store lives at `.design/instincts/instincts.json`; the global store at `~/.claude/gdd/global-instincts.json`.
14
+
15
+ Invoke the engine with `node`, the same way other skills call a `scripts/lib` helper:
16
+
17
+ ```bash
18
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/lib/instinct-store.cjs" <subcommand> [args]
19
+ ```
20
+
21
+ If the engine exposes only a module API rather than a CLI, drive it from a short `node -e` script:
22
+
23
+ ```bash
24
+ node -e "const s=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/instinct-store.cjs'); console.log(JSON.stringify(s.list({scope:process.env.SCOPE})))"
25
+ ```
26
+
27
+ ## Invocation Modes
28
+
29
+ | Command | Behavior |
30
+ |---|---|
31
+ | `/gdd:instinct list` | Compact table of stored instincts (default mode). |
32
+ | `/gdd:instinct query "<keyword>"` | Search instincts by keyword; show the top matches. |
33
+ | `/gdd:instinct promote <id>` | Promote one project instinct to the global store (gated). |
34
+
35
+ Flags apply across modes:
36
+
37
+ - `--scope project|global` selects which store to read. Default is `project`.
38
+ - `--domain <d>` filters to one domain (the domain enum is defined in `reference/instinct-format.md`).
39
+
40
+ ## list
41
+
42
+ Read the requested store and print a compact table. Call `instinct-store.list({ scope, domain, baseDir })`:
43
+
44
+ ```bash
45
+ node -e "const s=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/instinct-store.cjs'); \
46
+ const rows=s.list({ scope: process.env.SCOPE || 'project', domain: process.env.DOMAIN || undefined }); \
47
+ console.log(JSON.stringify(rows));"
48
+ ```
49
+
50
+ Render one row per instinct. Keep it scannable:
51
+
52
+ ```
53
+ ID DOMAIN CONF CYCLES TRIGGER
54
+ in-7f3a tokens 0.72 3 palette has no neutral ramp
55
+ in-91bc layout 0.55 2 cards overflow on the 320px breakpoint
56
+ ```
57
+
58
+ - `CONF` is the stored confidence (0.3 to 0.9).
59
+ - `CYCLES` is `cycles_seen`.
60
+ - Truncate `TRIGGER` to keep each line on one row.
61
+
62
+ If the store is empty, print: `No instincts in the <scope> store yet. Run /gdd:reflect or /gdd:extract-learnings to accumulate some.`
63
+
64
+ ## query
65
+
66
+ Search by keyword and show the closest matches. Call `instinct-store.query(keyword, { scope, baseDir, limit })`. The engine uses an FTS5 index when one is present and falls back to a plain scan otherwise; either path returns the same row shape.
67
+
68
+ ```bash
69
+ node -e "const s=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/instinct-store.cjs'); \
70
+ const hits=s.query(process.env.KW, { scope: process.env.SCOPE || 'project', limit: 10 }); \
71
+ console.log(JSON.stringify(hits));"
72
+ ```
73
+
74
+ Print the top matches in the same table shape as `list`, ordered by the engine's relevance ranking. If there are no matches, say so plainly and suggest a broader keyword. Quote multi-word keywords so the shell passes one argument.
75
+
76
+ ## promote
77
+
78
+ Promote a single project instinct into the global store so it applies across every project. Promotion is **gated**: `instinct-store.promote(id, { baseDir })` only succeeds when the instinct has been seen across at least K cycles (K=2) spanning at least M distinct project ids (M=2). The engine enforces the gate; this skill surfaces the outcome and asks the user to confirm before the write.
79
+
80
+ Confirm first. Prefer `@clack/prompts`, and fall back to `AskUserQuestion` when it is absent (mirror the probe in `/gdd:new-skill`):
81
+
82
+ ```bash
83
+ node -e "try { require.resolve('@clack/prompts'); console.log('clack'); } catch { console.log('fallback'); }"
84
+ ```
85
+
86
+ - `clack`: drive `clack.confirm({ message: 'Promote <id> to the global store?' })` from a short Node script.
87
+ - `fallback`: ask the same yes or no question with `AskUserQuestion`.
88
+
89
+ On a confirmed yes, run the promotion:
90
+
91
+ ```bash
92
+ node -e "const s=require('${CLAUDE_PLUGIN_ROOT}/scripts/lib/instinct-store.cjs'); \
93
+ console.log(JSON.stringify(s.promote(process.env.ID, {})));"
94
+ ```
95
+
96
+ Branch on the engine result:
97
+
98
+ - Promotion succeeded: print `Promoted <id> to the global store.` and show the new global row.
99
+ - Gate not met: the engine reports how far the instinct is from the K=2 / M=2 bar. Print that plainly, for example `<id> needs 2 cycles across 2 projects; seen 1 cycle in 1 project so far. Not promoted.` Do not retry and do not force the write.
100
+ - Unknown id: print `No instinct <id> in the project store.` and suggest `/gdd:instinct list`.
101
+
102
+ If the user answers no at the confirm step, print `Promotion cancelled.` and exit without writing.
103
+
104
+ ## Do Not
105
+
106
+ - Do not edit `.design/instincts/instincts.json` or the global store by hand. All writes go through `scripts/lib/instinct-store.cjs`.
107
+ - Do not author new instincts here. The reflector and `/gdd:extract-learnings` emit units; this skill reads and promotes them.
108
+ - Do not bypass the promotion gate. If the K=2 / M=2 bar is not met, report it and stop.
109
+ - Do not modify `reference/instinct-format.md` or the store engine.
110
+
111
+ ## INSTINCT COMPLETE
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: gdd-migrate-context
3
+ description: "Migrates a pre-Phase-52 project from the flat .design/map/*.md mapper notes to the typed DesignContext graph at .design/context-graph.json. Reads the old map notes, runs the deterministic extract-*.mjs passes to build mapper fragments, merges them with merge-fragments.mjs, validates the result with validate-design-context.cjs, and flags every low-confidence transform for human review before anything is trusted. Read-first and reversible; --dry-run previews the plan without writing. Use when upgrading a project to the DesignContext graph and .design/map/*.md still holds the only structured design notes. Activates for requests involving migrating design maps, building the context graph from old notes, or DesignContext graph migration."
4
+ argument-hint: "[--dry-run]"
5
+ tools: Read, Write, Bash
6
+ user-invocable: true
7
+ ---
8
+
9
+ # /gdd:migrate-context
10
+
11
+ Closes the pre-graph gap: before Phase 52 a project recorded its structured design knowledge as flat
12
+ `.design/map/*.md` mapper notes (token map, component taxonomy, motion map, a11y map, visual-hierarchy
13
+ map). Phase 52 introduced the typed DesignContext graph at `.design/context-graph.json`. This skill
14
+ carries a project across that boundary: it reads the old map notes, rebuilds the graph deterministically
15
+ from source, validates it, and surfaces anything it could not transform with confidence so a human can
16
+ confirm it. It never trusts a low-confidence guess silently.
17
+
18
+ Contracts: `../../reference/design-context-schema.md` (the Node / Edge / Fragment / Graph shapes) and
19
+ `../../reference/design-context-tag-vocab.md` (the controlled `tags[]` vocabulary).
20
+
21
+ ## Invocation
22
+
23
+ | Command | Behavior |
24
+ |---|---|
25
+ | `/gdd:migrate-context` | Run the full migration: read old maps, extract fragments, merge, validate, then report the low-confidence items for review. |
26
+ | `/gdd:migrate-context --dry-run` | Preview only. Print the migration plan and what each step would write, change nothing on disk. |
27
+
28
+ ## Step 1 - Detect the pre-52 state
29
+
30
+ Read the project layout before touching anything.
31
+
32
+ 1. List `.design/map/*.md`. These are the pre-52 mapper notes (for example `token-map.md`,
33
+ `component-taxonomy.md`, `motion-map.md`, `a11y-map.md`, `visual-hierarchy.md`). If the directory is
34
+ absent or empty, there is nothing to migrate: print `No .design/map/*.md notes found; nothing to
35
+ migrate.` and stop.
36
+ 2. Check whether `.design/context-graph.json` already exists. If it does, this is a re-run: keep the
37
+ existing graph as a backup reference and report that the migration will rebuild it. Do not delete it.
38
+ 3. In `--dry-run`, print the file list and the planned outputs (`.design/fragments/<mapper>.json` per
39
+ mapper, then `.design/context-graph.json`) and stop before Step 2.
40
+
41
+ ## Step 2 - Rebuild fragments deterministically
42
+
43
+ The graph topology comes from the source tree, not from prose. Run each deterministic extractor over the
44
+ configured source roots (default `src/`; read `source_roots` from `.design/STATE.md` if present). Each
45
+ extractor is pure, dependency-free, and prints a schema-valid Fragment to stdout.
46
+
47
+ ```bash
48
+ mkdir -p .design/fragments
49
+ for mapper in tokens components motion a11y visual-hierarchy; do
50
+ node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/lib/design-context/extract-${mapper}.mjs" src/ \
51
+ > ".design/fragments/extract-${mapper}.json"
52
+ done
53
+ ```
54
+
55
+ The extractors fill `id / type / name / subtype / tags / complexity` and every edge they can prove; they
56
+ leave each node `summary` empty for the summary pass. Use the old `.design/map/*.md` notes as the source
57
+ of the human-authored `summary` text and any tags the extractor could not infer: for each node whose name
58
+ matches a map entry, copy that note's one-line description into the node `summary` and add any vocabulary
59
+ tags it implies. This is the only place prose feeds the graph.
60
+
61
+ ## Step 3 - Merge into the canonical graph
62
+
63
+ Merge the fragments into the single graph. The merger dedupes nodes by `id`, unions tags, prefers a
64
+ non-stub summary over the empty stub, and keeps an edge only when both endpoints resolve to a node in some
65
+ fragment. Dropped dangling edges are reported on stderr as `could-not-fix:` lines.
66
+
67
+ ```bash
68
+ node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/lib/design-context/merge-fragments.mjs" \
69
+ .design/fragments --out .design/context-graph.json
70
+ ```
71
+
72
+ Capture the stderr `could-not-fix:` lines. Each one is a transform the merge could not complete (a map
73
+ note referenced an entity the extractor never found in source). These are low-confidence items for Step 5,
74
+ not silent drops.
75
+
76
+ ## Step 4 - Validate
77
+
78
+ Validate the merged graph. The validator checks structure, referential integrity (no dangling edges),
79
+ unique ids, non-stub summaries (soft warning), and the controlled tag vocabulary (soft warning).
80
+
81
+ ```bash
82
+ node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/validate-design-context.cjs" .design/context-graph.json
83
+ ```
84
+
85
+ Exit `0` is clean, `1` is warnings only (stub summaries or unknown tags to tidy later), `2` is a hard
86
+ error (a dangling edge or duplicate id) that must be fixed before the graph is trusted. On exit `2`, do
87
+ not present the graph as migrated: report the errors and stop so a human can resolve them.
88
+
89
+ ## Step 5 - Flag low-confidence transforms
90
+
91
+ Collect everything that needs human eyes and present it as one review list rather than applying it:
92
+
93
+ - every `could-not-fix:` line from the merge (an unresolved or dropped edge);
94
+ - every node still carrying an empty `summary` after Step 2 (a map note had no matching entity, or no
95
+ note existed);
96
+ - every validator `WARN` (stub summary, tag outside the controlled vocabulary).
97
+
98
+ Print the list with a clear heading and ask the user to confirm or correct each item. Do not auto-resolve
99
+ a low-confidence transform: a wrong edge or a mislabeled node poisons every later graph query.
100
+
101
+ ## Step 6 - Deprecate the old map notes
102
+
103
+ The flat `.design/map/*.md` notes stay readable for one minor version so nothing breaks mid-upgrade. Add a
104
+ one-line deprecation banner to the top of each migrated map note (do not delete the file):
105
+
106
+ ```text
107
+ > Deprecated: superseded by the DesignContext graph (.design/context-graph.json) as of Phase 52.
108
+ > Read-only for one minor version; regenerate the graph with /gdd:migrate-context.
109
+ ```
110
+
111
+ In `--dry-run`, describe this banner instead of writing it. Announce that the next minor version may remove
112
+ the `.design/map/*.md` notes, and that the graph is now the source of truth.
113
+
114
+ ## Do Not
115
+
116
+ - Do not trust a low-confidence transform silently. Every `could-not-fix:` line and every stub goes on the
117
+ Step 5 review list.
118
+ - Do not delete `.design/map/*.md`. Add the deprecation banner and keep the notes for one minor version.
119
+ - Do not hand-edit `.design/context-graph.json` to force validation green. Fix the fragment or the source,
120
+ then re-merge.
121
+ - Do not edit the extractors, the merger, or the validator. This skill only calls them.
122
+
123
+ ## MIGRATE-CONTEXT COMPLETE
@@ -86,6 +86,10 @@ After the pipeline state (and forensic audit if run), surface a one-line composi
86
86
 
87
87
  Run `scripts/validate-composition-graph.cjs` for the authoritative cycle and dangling-edge counts when that validator is present; until then report `0` and note the graph is not yet wired. This is a readiness hint, not a gate.
88
88
 
89
+ ## Step 3.6 - DesignContext graph coverage
90
+
91
+ When `.design/context-graph.json` exists, surface one line for the typed DesignContext graph using the `coverage` helper in `scripts/lib/design-context-query.cjs` (`node scripts/lib/design-context-query.cjs coverage`), then point at the Atomic-Design map: `DesignContext graph: <pct>% node-type coverage | map: .design/INTEGRATION-MAP.md`. Skip this line entirely when the graph is absent (a pre-Phase-52 project); offer `/gdd:migrate-context` as the next step instead. Readiness hint, not a gate.
92
+
89
93
  ## Step 4 - Update notice (safe-window surface)
90
94
 
91
95
  After printing the pipeline state, emit the plugin-update banner if one is present. This file is written by `hooks/update-check.sh` subject to the state-machine guard (mid-pipeline stages suppress it) and per-version dismissal.