@tekyzinc/gsd-t 2.57.10 → 2.58.10

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/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to GSD-T are documented here. Updated with each release.
4
4
 
5
+ ## [2.58.10] - 2026-04-05
6
+
7
+ ### Added
8
+ - **Hierarchical design contracts** — `element` → `widget` → `page` contract hierarchy for design-to-code projects. Element contracts are the single source of truth for visual spec (one contract per visual variant, e.g., `chart-bar-stacked-horizontal` and `chart-bar-stacked-vertical` are separate). Widgets compose elements with layout + data binding. Pages compose widgets with routing + grid layout.
9
+ - **Precedence rule**: element > widget > page. Widgets and pages SELECT and POSITION elements but cannot override element visual spec. Structural drift becomes impossible.
10
+ - **New templates**: `templates/element-contract.md`, `templates/widget-contract.md`, `templates/page-contract.md`
11
+ - **New command**: `/user:gsd-t-design-decompose` — surveys a design (Figma/image/prototype), classifies elements (reuse count ≥2 or non-trivial spec → promoted to element contract), identifies widgets and pages, writes the full contract hierarchy under `.gsd-t/contracts/design/{elements,widgets,pages}/` plus an `INDEX.md` navigation map.
12
+
13
+ ### Changed
14
+ - `design-to-code.md` stack rule adds Section 0 explaining flat vs. hierarchical contract modes and detection at execute-time (presence of `.gsd-t/contracts/design/` triggers hierarchical verification: elements first, then widgets, then pages)
15
+ - Command count: 48 GSD-T + 5 utility = 53 total
16
+
5
17
  ## [2.57.10] - 2026-04-04
6
18
 
7
19
  ### Added
package/README.md CHANGED
@@ -30,7 +30,7 @@ A methodology for reliable, parallelizable development using Claude Code with op
30
30
  npx @tekyzinc/gsd-t install
31
31
  ```
32
32
 
33
- This installs 47 GSD-T commands + 5 utility commands (52 total) to `~/.claude/commands/` and the global CLAUDE.md to `~/.claude/CLAUDE.md`. Works on Windows, Mac, and Linux.
33
+ This installs 48 GSD-T commands + 5 utility commands (53 total) to `~/.claude/commands/` and the global CLAUDE.md to `~/.claude/CLAUDE.md`. Works on Windows, Mac, and Linux.
34
34
 
35
35
  ### Start Using It
36
36
 
@@ -149,6 +149,7 @@ This will replace changed command files, back up your CLAUDE.md if customized, a
149
149
  | `/user:gsd-t-gap-analysis` | Requirements gap analysis — spec vs. existing code | Manual |
150
150
  | `/user:gsd-t-promote-debt` | Convert techdebt items to milestones | Manual |
151
151
  | `/user:gsd-t-populate` | Auto-populate docs from existing codebase | Manual |
152
+ | `/user:gsd-t-design-decompose` | Decompose design into element/widget/page contracts | Manual |
152
153
 
153
154
  ### Milestone Workflow
154
155
 
@@ -338,7 +339,7 @@ get-stuff-done-teams/
338
339
  ├── LICENSE
339
340
  ├── bin/
340
341
  │ └── gsd-t.js # CLI installer
341
- ├── commands/ # 51 slash commands
342
+ ├── commands/ # 53 slash commands
342
343
  │ ├── gsd-t-*.md # 45 GSD-T workflow commands
343
344
  │ ├── gsd.md # GSD-T smart router
344
345
  │ ├── branch.md # Git branch helper
@@ -0,0 +1,241 @@
1
+ # GSD-T: Design Decompose — Hierarchical Contract Extraction
2
+
3
+ You are the lead agent for decomposing a design (Figma file, image, screenshot, or prototype URL) into a hierarchy of element / widget / page contracts.
4
+
5
+ **Output**: A tree of contracts — elements at the bottom (atomic, reusable, variant-per-contract), widgets in the middle (element composition + data binding), pages at the top (widget assembly + layout + routing).
6
+
7
+ **Why hierarchical contracts:** A flat `design-contract.md` makes verification expensive and lets drift accumulate (two donut charts on two pages diverge over time). Hierarchical contracts verify elements in isolation once, then compose — drift is impossible because elements are the single source of truth for visual spec.
8
+
9
+ **When to use this command:**
10
+ - Starting a design-to-code project with multiple pages sharing components
11
+ - Retrofitting an existing flat `design-contract.md` into reusable parts
12
+ - Adding a new page that reuses existing elements/widgets
13
+
14
+ If the project is small (single page, ≤10 elements, nothing reusable), use the flat `design-contract.md` template instead and skip this command.
15
+
16
+ ---
17
+
18
+ ## Step 0: Detect Inputs
19
+
20
+ Run these checks, log results to user inline:
21
+
22
+ 1. **Figma MCP available?**
23
+ - If yes → log "Figma MCP detected — will extract exact tokens per element"
24
+ - If no → log "Figma MCP unavailable — using visual analysis (reduced precision)"
25
+ 2. **Existing flat contract?**
26
+ - If `.gsd-t/contracts/design-contract.md` exists → this is a retrofit; read it and use it as input alongside the design source
27
+ - If not → this is a fresh decomposition from the design source directly
28
+ 3. **Design source provided?**
29
+ - Required: Figma URL, image path, or prototype URL in `$ARGUMENTS`
30
+ - If missing → ask user: "Provide the design source (Figma URL, image path, or prototype URL)"
31
+
32
+ ## Step 1: Survey the Design
33
+
34
+ Enumerate every visual element on every page/screen in the design. Use Figma MCP `get_metadata` or `get_design_context` if available; otherwise use visual analysis on the image.
35
+
36
+ Produce an initial flat inventory table:
37
+
38
+ | # | Element on Design | Appears On Pages | Visual Variant |
39
+ |---|------------------------------------|------------------------|--------------------------------------|
40
+ | 1 | Donut chart with center label | Overview, Analytics | chart-donut |
41
+ | 2 | Horizontal stacked bar chart | Analytics | chart-bar-stacked-horizontal |
42
+ | 3 | Vertical legend on right | Overview | legend-vertical-right |
43
+ | 4 | KPI tile with delta indicator | Overview (×4) | stat-card-with-delta |
44
+ | ...
45
+
46
+ **Rule**: distinct visual variants = distinct rows. A horizontal stacked bar and a vertical stacked bar are TWO rows, not one.
47
+
48
+ ## Step 2: Classify Each Element
49
+
50
+ For each row in the inventory, assign:
51
+
52
+ - **Category** — chart / legend / axis / card / table / control / layout / typography / icon / other
53
+ - **Reuse count** — how many times does it appear across the entire design?
54
+ - **Owner layer** — element / widget-internal / page-internal
55
+
56
+ **Promotion rule**: an item becomes an **element contract** if:
57
+ - It appears ≥2 times across the design, OR
58
+ - It has non-trivial visual spec (≥5 distinct spec properties), OR
59
+ - It has states or interactions beyond "static display"
60
+
61
+ Otherwise, it stays internal to its widget or page (no contract needed).
62
+
63
+ ## Step 3: Identify Widgets
64
+
65
+ A **widget** is a reusable composition of elements + data binding that appears as a visual group in the design. Examples: "Revenue Breakdown" (donut + legend + title + filter), "Stat Strip" (4× stat-card-with-delta).
66
+
67
+ For each visual group in the design, determine:
68
+ - Does it appear on ≥2 pages, OR is it clearly a reusable unit conceptually?
69
+ - Yes → widget contract
70
+ - No → page-internal composition (no widget contract needed)
71
+
72
+ Produce a widget inventory:
73
+
74
+ | # | Widget Name | Appears On Pages | Elements Used |
75
+ |---|---------------------------|------------------------|-------------------------------------------------|
76
+ | 1 | revenue-breakdown-widget | Overview, Analytics | chart-donut, legend-vertical-right, heading-h3, select-dropdown |
77
+ | 2 | stat-strip-widget | Overview | stat-card-with-delta (×4) |
78
+ | ...
79
+
80
+ ## Step 4: Identify Pages
81
+
82
+ Each page/screen in the design becomes a page contract. Document:
83
+ - Widgets used and grid position
84
+ - Global layout (header, sidebar, main)
85
+ - Route + auth guards
86
+
87
+ ## Step 5: Confirm Decomposition With User
88
+
89
+ Present the full hierarchy summary:
90
+
91
+ ```
92
+ DECOMPOSITION SUMMARY
93
+ ─────────────────────
94
+ Elements: 14 contracts
95
+ Charts: 4 (chart-donut, chart-bar-stacked-horizontal, chart-line, chart-sparkline)
96
+ Legends: 2 (legend-vertical-right, legend-horizontal-bottom)
97
+ Cards: 2 (stat-card, stat-card-with-delta)
98
+ Tables: 1 (table-dense)
99
+ Controls: 5 (button-primary, select-dropdown, input-search, tabs-underline, toggle)
100
+
101
+ Widgets: 6 contracts
102
+ stat-strip-widget, revenue-breakdown-widget, user-growth-widget,
103
+ recent-activity-table-widget, page-header-widget, nav-sidebar-widget
104
+
105
+ Pages: 3 contracts
106
+ dashboard-overview, analytics-detail, settings
107
+
108
+ Total: 23 contracts (vs. flat: ~57 elements in single file)
109
+
110
+ Cost estimate:
111
+ - Decomposition effort: ~{N} hours to write all contracts
112
+ - Verification: elements verified once, reused everywhere → no drift
113
+ - Implementation: widgets become assembly, not reinvention
114
+ ```
115
+
116
+ Ask user: "Proceed with this decomposition? [y/n/edit]"
117
+ - **y** → Step 6
118
+ - **n** → abort
119
+ - **edit** → accept user revisions to the hierarchy, re-present
120
+
121
+ ## Step 6: Write Contracts
122
+
123
+ Create the directory structure:
124
+
125
+ ```
126
+ .gsd-t/contracts/design/
127
+ ├── elements/
128
+ │ ├── chart-donut.contract.md
129
+ │ ├── chart-bar-stacked-horizontal.contract.md
130
+ │ ├── legend-vertical-right.contract.md
131
+ │ └── ... (one file per element)
132
+ ├── widgets/
133
+ │ ├── revenue-breakdown-widget.contract.md
134
+ │ └── ... (one file per widget)
135
+ ├── pages/
136
+ │ ├── dashboard-overview.contract.md
137
+ │ └── ... (one file per page)
138
+ └── INDEX.md (hierarchy map + cross-references)
139
+ ```
140
+
141
+ For each element contract:
142
+ 1. Copy `templates/element-contract.md` as scaffold
143
+ 2. Fill in visual spec from Figma MCP (exact values) or visual analysis (estimated values)
144
+ 3. Fill in states, interactions, data binding, accessibility, verification checklist
145
+ 4. If Figma MCP available → use `get_design_context` per element node to extract tokens
146
+
147
+ For each widget contract:
148
+ 1. Copy `templates/widget-contract.md` as scaffold
149
+ 2. Reference elements by name in the "Elements Used" table
150
+ 3. Define layout, data binding, responsive behavior, widget-level verification
151
+
152
+ For each page contract:
153
+ 1. Copy `templates/page-contract.md` as scaffold
154
+ 2. Reference widgets in grid positions
155
+ 3. Define route, data loading, global states, performance budget
156
+
157
+ Write `INDEX.md` as a navigation map:
158
+
159
+ ```markdown
160
+ # Design Contracts: {Project Name}
161
+
162
+ ## Elements (14)
163
+ - [chart-donut](elements/chart-donut.contract.md) — used by revenue-breakdown-widget
164
+ - [chart-bar-stacked-horizontal](elements/chart-bar-stacked-horizontal.contract.md) — used by analytics-trend-widget
165
+ - ...
166
+
167
+ ## Widgets (6)
168
+ - [revenue-breakdown-widget](widgets/revenue-breakdown-widget.contract.md) — uses chart-donut, legend-vertical-right
169
+ - ...
170
+
171
+ ## Pages (3)
172
+ - [dashboard-overview](pages/dashboard-overview.contract.md) — uses stat-strip-widget, revenue-breakdown-widget, user-growth-widget, recent-activity-table-widget
173
+ - ...
174
+
175
+ ## Precedence
176
+ element contract > widget contract > page contract
177
+
178
+ Widgets and pages reference elements by name. They CANNOT override element visual spec. To customize, create a new element variant.
179
+ ```
180
+
181
+ ## Step 7: Wire Into Partition
182
+
183
+ If `.gsd-t/domains/` exists (project is already partitioned), append to relevant domain's `scope.md`:
184
+
185
+ ```markdown
186
+ ## Design Contracts
187
+ This domain owns the following design contracts:
188
+ - Elements: chart-donut, legend-vertical-right
189
+ - Widgets: revenue-breakdown-widget
190
+ - Pages: (none — pages owned by page-assembly domain)
191
+ ```
192
+
193
+ If `.gsd-t/domains/` does NOT exist yet, suggest the user run `/user:gsd-t-partition` next, with a note that design contracts should be partitioned into domains:
194
+ - **design-system domain** owns element contracts
195
+ - **widgets domain** owns widget contracts
196
+ - **pages domain** owns page assembly + routing
197
+
198
+ ## Step 8: Update progress.md Decision Log
199
+
200
+ Append:
201
+ ```
202
+ - {YYYY-MM-DD HH:MM}: gsd-t-design-decompose — created {N} element / {N} widget / {N} page contracts under .gsd-t/contracts/design/. Hierarchy: elements are single source of truth for visual spec; widgets compose elements; pages compose widgets.
203
+ ```
204
+
205
+ ## Step 9: Next Up Hint
206
+
207
+ Display:
208
+
209
+ ```
210
+ ───────────────────────────────────────────────────────────────
211
+
212
+ ## ▶ Next Up
213
+
214
+ **Partition** — decompose project into domains owning the design contracts
215
+
216
+ `/user:gsd-t-partition`
217
+
218
+ **Also available:**
219
+ - `/user:gsd-t-execute` — build element contracts first (they're independently testable)
220
+ - `/user:gsd-t-plan` — plan tasks around the contract hierarchy
221
+
222
+ ───────────────────────────────────────────────────────────────
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Document Ripple
228
+
229
+ After writing contracts, update:
230
+ - `.gsd-t/progress.md` — Decision Log entry (Step 8)
231
+ - `docs/architecture.md` — add "Design Contract Hierarchy" section if not present
232
+ - If existing flat `.gsd-t/contracts/design-contract.md` was retrofitted → mark it with a DEPRECATED header pointing to `design/INDEX.md`
233
+
234
+ ## Pre-Commit Gate
235
+
236
+ - [ ] All contracts written from templates (element/widget/page)
237
+ - [ ] `INDEX.md` created with full hierarchy + precedence note
238
+ - [ ] Decision Log updated in progress.md
239
+ - [ ] architecture.md updated if this is a new concept for the project
240
+
241
+ $ARGUMENTS
@@ -60,6 +60,7 @@ UTILITIES Manual
60
60
  audit Harness self-audit — analyze cost/benefit of enforcement components
61
61
  promote-debt Convert techdebt items to milestones
62
62
  populate Auto-populate docs from existing codebase
63
+ design-decompose Decompose design into element/widget/page contracts
63
64
  log Sync progress Decision Log with recent git activity
64
65
  version-update Update GSD-T package to latest version
65
66
  version-update-all Update GSD-T package + all registered projects
@@ -382,6 +383,13 @@ Use these when user asks for help on a specific command:
382
383
  - **Updates**: `docs/requirements.md`, `docs/architecture.md`, `docs/workflows.md`, `docs/infrastructure.md`, `.gsd-t/progress.md`
383
384
  - **Use when**: You have an existing codebase and want to fill docs with real findings instead of placeholders
384
385
 
386
+ ### design-decompose
387
+ - **Summary**: Decompose a design (Figma/image/prototype) into a hierarchy of element → widget → page contracts
388
+ - **Auto-invoked**: No
389
+ - **Creates**: `.gsd-t/contracts/design/elements/*.contract.md`, `.gsd-t/contracts/design/widgets/*.contract.md`, `.gsd-t/contracts/design/pages/*.contract.md`, `.gsd-t/contracts/design/INDEX.md`
390
+ - **Use when**: Starting a design-to-code project with multiple pages/reusable components, or retrofitting a flat design-contract.md
391
+ - **Precedence rule**: element > widget > page. Widgets and pages cannot override element visual spec.
392
+
385
393
  ### log
386
394
  - **Summary**: Sync progress.md Decision Log with recent git activity
387
395
  - **Auto-invoked**: No
package/commands/gsd.md CHANGED
@@ -65,7 +65,8 @@ When the request involves UI implementation from a design (Figma, screenshots, m
65
65
  - **If a milestone exists but no domains** → route to `partition` (creates design contract in Step 3.6)
66
66
  - **If domains exist but no tasks** → route to `plan`
67
67
  - **If tasks exist** → route to `execute` (design-to-code stack rule will inject)
68
- - The design-to-code stack rule activates automatically when `.gsd-t/contracts/design-contract.md` exists or Figma MCP is configured — but the **partition step must run first** to create the design contract
68
+ - The design-to-code stack rule activates automatically when `.gsd-t/contracts/design-contract.md` OR `.gsd-t/contracts/design/` exists, or Figma MCP is configured — but the **partition step must run first** to create the design contract
69
+ - **For projects with multiple pages or reusable components** (charts, widgets, design system): route to `design-decompose` BEFORE partition to create the hierarchical contract tree (elements → widgets → pages). Single-page/one-off designs can use flat `design-contract.md` created during partition instead.
69
70
 
70
71
  ## Step 3: Confirm and Execute
71
72
 
@@ -90,6 +90,7 @@ GSD-T reads all state files and tells you exactly where you left off.
90
90
  | `/user:gsd-t-gap-analysis` | Requirements gap analysis — spec vs. existing code | Manual |
91
91
  | `/user:gsd-t-promote-debt` | Convert techdebt items to milestones | Manual |
92
92
  | `/user:gsd-t-populate` | Auto-populate docs from existing codebase | Manual |
93
+ | `/user:gsd-t-design-decompose` | Decompose design into element/widget/page contracts | Manual |
93
94
 
94
95
  ### Milestone Workflow
95
96
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "2.57.10",
3
+ "version": "2.58.10",
4
4
  "description": "GSD-T: Contract-Driven Development for Claude Code — 51 slash commands with headless CI/CD mode, graph-powered code analysis, real-time agent dashboard, execution intelligence, task telemetry, doc-ripple enforcement, backlog management, impact analysis, test sync, milestone archival, and PRD generation",
5
5
  "author": "Tekyz, Inc.",
6
6
  "license": "MIT",
@@ -63,6 +63,7 @@ PROJECT or FEATURE or SCAN
63
63
  | `/user:gsd-t-health` | Validate .gsd-t/ structure, optionally repair |
64
64
  | `/user:gsd-t-pause` | Save exact position for reliable resume |
65
65
  | `/user:gsd-t-populate` | Auto-populate docs from existing codebase |
66
+ | `/user:gsd-t-design-decompose` | Decompose design into element/widget/page contracts |
66
67
  | `/user:gsd-t-log` | Sync progress Decision Log with recent git activity |
67
68
  | `/user:gsd-t-resume` | Restore context, continue |
68
69
  | `/user:gsd-t-version-update` | Update GSD-T to latest version |
@@ -639,7 +640,7 @@ GSD-T auto-detects project tech stack at subagent spawn time and injects mandato
639
640
 
640
641
  **Stack-specific rules**: Injected only when the matching stack is detected (e.g., `react.md` when `"react"` is in `package.json`).
641
642
 
642
- **Design-to-code**: Activated when `.gsd-t/contracts/design-contract.md`, `design-tokens.json`, `design-tokens/`, `.figmarc`, or `figma.config.json` exists, OR when Figma MCP is configured in `~/.claude/settings.json`. Auto-bootstrapped during partition when Figma URLs or design references are detected in requirements. Enforces pixel-perfect frontend implementation from designs with: Figma MCP auto-detection, design token extraction protocol, stack capability evaluation (recommends alternatives if stack can't achieve the design), component decomposition, responsive breakpoint strategy, and a mandatory visual verification loop — every implemented screen must be rendered in a real browser, screenshotted at mobile/tablet/desktop breakpoints, and compared pixel-by-pixel against the Figma design. Visual deviations block task completion.
643
+ **Design-to-code**: Activated when `.gsd-t/contracts/design-contract.md` (flat), `.gsd-t/contracts/design/` (hierarchical element/widget/page contracts — bootstrap via `/user:gsd-t-design-decompose`), `design-tokens.json`, `design-tokens/`, `.figmarc`, or `figma.config.json` exists, OR when Figma MCP is configured in `~/.claude/settings.json`. Auto-bootstrapped during partition when Figma URLs or design references are detected in requirements. Enforces pixel-perfect frontend implementation from designs with: Figma MCP auto-detection, design token extraction protocol, stack capability evaluation (recommends alternatives if stack can't achieve the design), component decomposition, responsive breakpoint strategy, and a mandatory visual verification loop — every implemented screen must be rendered in a real browser, screenshotted at mobile/tablet/desktop breakpoints, and compared pixel-by-pixel against the Figma design. Visual deviations block task completion.
643
644
 
644
645
  **Enforcement**: Stack rule violations have the same weight as contract violations — they are task failures, not warnings.
645
646
 
@@ -0,0 +1,125 @@
1
+ # Element Contract: {element-name}
2
+
3
+ Atomic visual unit. One contract per visual variant (e.g., `chart-bar-stacked-horizontal` and `chart-bar-stacked-vertical` are separate contracts). Widgets and pages reference element contracts by name; they CANNOT override the visual spec.
4
+
5
+ ## Metadata
6
+
7
+ | Field | Value |
8
+ |----------------|-----------------------------------------------------------|
9
+ | element | {e.g., chart-bar-stacked-horizontal} |
10
+ | category | {chart / legend / axis / card / table / control / layout} |
11
+ | variant_of | {base element name, or `null` if base} |
12
+ | version | {1.0} |
13
+ | extends | {[axis-x-numeric, axis-y-categorical] — or []} |
14
+ | design_source | {Figma node URL or design file path + node id} |
15
+ | extracted_via | {Figma MCP / Visual Analysis / Design Tokens} |
16
+ | extracted_date | {YYYY-MM-DD} |
17
+
18
+ ## Purpose
19
+
20
+ {One sentence — what this element is and when to use it. E.g., "Horizontal stacked bar chart for displaying part-to-whole comparisons across categories, with segment labels inside when segment width ≥40px."}
21
+
22
+ ## Visual Spec
23
+
24
+ | Property | Value |
25
+ |---------------|-------------------------------------------------------|
26
+ | {dimension_1} | {exact value, referencing design tokens if available} |
27
+ | {dimension_2} | {exact value} |
28
+
29
+ *List every measurable visual property: dimensions, spacing, radii, borders, shadows, opacity. Reference design tokens rather than raw values where possible (`tokens.spacing.4` instead of `16px`).*
30
+
31
+ ## Labels / Text (if applicable)
32
+
33
+ | Property | Value |
34
+ |---------------|--------------------------------------------------------------------|
35
+ | font_family | {tokens.font.family.sans} |
36
+ | font_size | {tokens.font.size.sm} |
37
+ | font_weight | {tokens.font.weight.medium} |
38
+ | color | {tokens.color.text.primary} |
39
+ | position | {inside-segment-centered / above-bar / below-bar / left / right} |
40
+ | visibility | {always / conditional: {rule, e.g., `hide if segment width <40px`}} |
41
+ | alignment | {left / center / right / start / end} |
42
+ | truncation | {none / ellipsis / tooltip-on-truncate} |
43
+
44
+ ## Colors
45
+
46
+ | Usage | Token |
47
+ |-------------|--------------------------------------|
48
+ | {fill} | {tokens.color.chart.sequence[0..n]} |
49
+ | {stroke} | {tokens.color.chart.border} |
50
+ | {text} | {tokens.color.text.onPrimary} |
51
+ | {hover} | {tokens.color.chart.hover.overlay} |
52
+
53
+ ## States
54
+
55
+ | State | Visual Change |
56
+ |-------------|--------------------------------------------------------------------|
57
+ | default | {base appearance} |
58
+ | hover | {e.g., segment opacity 1.0, siblings 0.6, cursor: pointer} |
59
+ | active | {e.g., border 2px tokens.color.accent} |
60
+ | disabled | {e.g., opacity 0.4, cursor: not-allowed} |
61
+ | focus | {e.g., outline 2px tokens.color.focus, offset 2px} |
62
+ | loading | {e.g., skeleton shimmer} |
63
+ | empty | {e.g., placeholder icon + "No data" text} |
64
+
65
+ ## Interactions
66
+
67
+ | Event | Behavior |
68
+ |-------------|--------------------------------------------------------------------|
69
+ | hover | {e.g., show tooltip with {category, series, value, percent}} |
70
+ | click | {e.g., emit `onSegmentClick({category, series, value})`} |
71
+ | keyboard | {e.g., Tab focuses, Enter activates, Arrow keys navigate segments} |
72
+
73
+ ## Data Binding
74
+
75
+ **Input shape:**
76
+ ```typescript
77
+ {
78
+ // Define the minimum data contract required to render this element
79
+ categories: string[];
80
+ series: { name: string; values: number[]; color?: string }[];
81
+ }
82
+ ```
83
+
84
+ **Invariants:**
85
+ - {e.g., All series arrays MUST have length === categories.length}
86
+ - {e.g., Values MUST be non-negative for stacked variants}
87
+
88
+ ## Responsive Behavior
89
+
90
+ | Breakpoint | Adaptation |
91
+ |------------|---------------------------------------------------------------|
92
+ | mobile | {e.g., labels hidden, tap for tooltip} |
93
+ | tablet | {e.g., reduced label font-size to tokens.font.size.xs} |
94
+ | desktop | {full labels as specified} |
95
+
96
+ ## Accessibility
97
+
98
+ - **Role**: {e.g., `img` with descriptive aria-label, or `figure` with `<figcaption>`}
99
+ - **Keyboard**: {e.g., focusable, arrow-key navigation between segments}
100
+ - **Screen reader**: {e.g., announces category, series, value on focus}
101
+ - **Contrast**: {label text contrast ratio ≥4.5:1 against segment fill}
102
+
103
+ ## Implementation Notes
104
+
105
+ - **Library**: {e.g., Plotly.js / Recharts / D3 / native SVG}
106
+ - **Component path**: {src/components/charts/BarStackedHorizontal.vue}
107
+ - **Dependencies**: {list of required packages}
108
+
109
+ ## Verification Checklist
110
+
111
+ Design Verification Agent uses this list. Every item must resolve to ✅ MATCH or ❌ DEVIATION (with specific values) — never "looks close" or "appears to match".
112
+
113
+ - [ ] {Visual spec property 1 matches design}
114
+ - [ ] {Visual spec property 2 matches design}
115
+ - [ ] Label position/font/color match design
116
+ - [ ] Color sequence matches design tokens
117
+ - [ ] Hover state changes as specified
118
+ - [ ] Focus state visible and correct
119
+ - [ ] Responsive adaptations fire at correct breakpoints
120
+ - [ ] Accessibility attributes present and correct
121
+
122
+ ## Examples
123
+
124
+ **Used by widgets:** {list widget contracts that reference this element}
125
+ **Used by pages:** {list page contracts that reference this element directly}
@@ -0,0 +1,143 @@
1
+ # Page Contract: {page-name}
2
+
3
+ Top-level assembly of widgets + global layout + routing + data loading. Pages POSITION widgets in a layout grid; they cannot redefine widget internals or element visual specs.
4
+
5
+ ## Metadata
6
+
7
+ | Field | Value |
8
+ |----------------|-------------------------------------------------|
9
+ | page | {e.g., dashboard-overview} |
10
+ | route | {e.g., /dashboard or /dashboard/overview} |
11
+ | version | {1.0} |
12
+ | design_source | {Figma page URL or image reference} |
13
+ | extracted_date | {YYYY-MM-DD} |
14
+
15
+ ## Purpose
16
+
17
+ {One sentence — what this page is for and who uses it. E.g., "Primary landing page after login. Displays KPIs, revenue trends, and recent activity for executives scanning performance at-a-glance."}
18
+
19
+ ## Widgets Used
20
+
21
+ | Position in Grid | Widget Contract | Notes |
22
+ |----------------------------------|---------------------------------|------------------------------|
23
+ | header | page-header-widget | {sticky} |
24
+ | sidebar | nav-sidebar-widget | {collapsible at <1024px} |
25
+ | grid[row=1, cols=1-4] | stat-strip-widget | {4 KPI tiles} |
26
+ | grid[row=2, col=1-2] | revenue-breakdown-widget | {spans 2 columns} |
27
+ | grid[row=2, col=3-4] | user-growth-widget | {spans 2 columns} |
28
+ | grid[row=3, col=1-4] | recent-activity-table-widget | {full width} |
29
+
30
+ ## Layout
31
+
32
+ ```
33
+ ┌──────────────────────────────────────────────────────┐
34
+ │ page-header-widget │
35
+ ├──────────┬───────────────────────────────────────────┤
36
+ │ │ stat-strip-widget │
37
+ │ nav- ├─────────────────────┬─────────────────────┤
38
+ │ sidebar │ revenue-breakdown │ user-growth │
39
+ │ -widget │ │ │
40
+ │ ├─────────────────────┴─────────────────────┤
41
+ │ │ recent-activity-table-widget │
42
+ └──────────┴───────────────────────────────────────────┘
43
+ ```
44
+
45
+ | Property | Value |
46
+ |---------------------|------------------------------------------------|
47
+ | layout_type | {grid / flex / fixed-sidebar+fluid-content} |
48
+ | grid_columns | {4} |
49
+ | grid_column_gap | {tokens.spacing.6} |
50
+ | grid_row_gap | {tokens.spacing.6} |
51
+ | page_padding | {tokens.spacing.8} |
52
+ | max_content_width | {1440px} |
53
+ | sidebar_width | {240px (expanded) / 64px (collapsed)} |
54
+ | header_height | {64px} |
55
+ | background | {tokens.color.bg.page} |
56
+
57
+ ## Data Loading
58
+
59
+ **Page-level data requirements:**
60
+ ```typescript
61
+ {
62
+ stats: Stat[];
63
+ revenue: RevenueData[];
64
+ userGrowth: GrowthData[];
65
+ activity: ActivityRow[];
66
+ }
67
+ ```
68
+
69
+ **Loading strategy:**
70
+ - {e.g., Single API call to `/api/dashboard/overview` on mount}
71
+ - {e.g., Parallel fetches per widget; widgets manage own loading states}
72
+ - {e.g., Server-side rendered with incremental hydration}
73
+
74
+ ## Routing & Navigation
75
+
76
+ - **Route**: {/dashboard/overview}
77
+ - **Guards**: {requires authentication, role: user|admin}
78
+ - **Breadcrumbs**: {Home > Dashboard > Overview}
79
+ - **Nav active state**: {highlights "Dashboard" in nav-sidebar}
80
+
81
+ ## Global States
82
+
83
+ | State | Page Behavior |
84
+ |------------------|---------------------------------------------------------|
85
+ | unauthenticated | Redirect to /login |
86
+ | page_loading | Skeleton grid with widget placeholders |
87
+ | page_error | Full-page error with retry button |
88
+ | partial_error | Individual widgets show own error states; page persists |
89
+
90
+ ## Responsive Behavior
91
+
92
+ | Breakpoint | Adaptation |
93
+ |------------|----------------------------------------------------------------|
94
+ | mobile | Sidebar becomes drawer; grid collapses to 1 column; stats stack vertically |
95
+ | tablet | Sidebar collapses to icon-only; grid becomes 2 columns |
96
+ | desktop | Full layout as specified |
97
+
98
+ ## Interactions
99
+
100
+ - {Sidebar toggle persists across sessions (localStorage)}
101
+ - {Widget filter changes do NOT affect other widgets unless explicitly wired}
102
+ - {Clicking KPI tile navigates to detail page}
103
+
104
+ ## Performance Budget
105
+
106
+ | Metric | Target |
107
+ |--------------------|-------------------------------------------------|
108
+ | First Contentful Paint | {<1.5s on 4G} |
109
+ | Time to Interactive | {<3.0s on 4G} |
110
+ | JS bundle size | {<200KB gzipped for this route} |
111
+
112
+ ## Accessibility
113
+
114
+ - **Landmarks**: `<header>`, `<nav>`, `<main>`, per-widget `<section role="region">`
115
+ - **Skip link**: "Skip to main content" at top, focuses `<main>` on activation
116
+ - **Keyboard order**: header → sidebar → widgets in visual reading order
117
+ - **Page title**: Set via `<title>` per route
118
+
119
+ ## Implementation Notes
120
+
121
+ - **Component path**: {src/pages/DashboardOverview.vue or src/routes/dashboard/overview.tsx}
122
+ - **Composes**: {list widget imports}
123
+ - **Router integration**: {vue-router / react-router / next.js app dir}
124
+ - **Data fetching**: {composable / hook / server component}
125
+
126
+ ## Verification Checklist
127
+
128
+ Page-level verification runs AFTER all widgets pass their own verification. Page verification only checks assembly — widget and element internals are out of scope.
129
+
130
+ - [ ] All widgets present in correct grid positions
131
+ - [ ] Layout dimensions (gaps, padding, max-width) match design
132
+ - [ ] Header / sidebar / main regions correctly landmarked
133
+ - [ ] Sidebar collapse/expand behavior works
134
+ - [ ] Responsive breakpoints rearrange layout as specified
135
+ - [ ] Data loading strategy produces correct widget inputs
136
+ - [ ] Route guards enforce authentication/roles
137
+ - [ ] Performance budget met (measure with Lighthouse)
138
+ - [ ] Keyboard navigation follows visual reading order
139
+ - [ ] Skip-link and page title present
140
+
141
+ ## Composes Elements (direct, not via widgets)
142
+
143
+ {List any element contracts referenced directly by the page (rare — usually everything goes through widgets). E.g., `button-primary` for a floating action button.}
@@ -6,6 +6,35 @@ These rules apply when implementing a visual design as frontend code. The design
6
6
 
7
7
  ---
8
8
 
9
+ ## 0. Contract Structure — Flat or Hierarchical
10
+
11
+ Two contract layouts are supported. Pick the one that fits the project scope:
12
+
13
+ **Flat** (single file: `.gsd-t/contracts/design-contract.md`)
14
+ - Use when: single page, ≤10 distinct elements, nothing reusable across pages
15
+ - Pros: fast to set up; fine for a landing page or one-off screen
16
+ - Cons: no reuse; visual spec repeats; drift between instances is easy
17
+
18
+ **Hierarchical** (directory: `.gsd-t/contracts/design/{elements,widgets,pages}/`)
19
+ - Use when: multiple pages, reusable components (charts, cards, legends), design system in play
20
+ - Pros: element contracts are the single source of truth for visual spec — widgets and pages SELECT and POSITION but cannot override. Drift is structurally impossible.
21
+ - Cons: more contracts to write upfront (elements: ~10-20, widgets: ~5-10, pages: N)
22
+ - Bootstrap via: `/user:gsd-t-design-decompose {Figma URL or image path}`
23
+ - Templates: `templates/element-contract.md`, `templates/widget-contract.md`, `templates/page-contract.md`
24
+
25
+ **Precedence rule (hierarchical only)**:
26
+ ```
27
+ element contract > widget contract > page contract
28
+ ```
29
+ A widget that uses `chart-donut` cannot change `chart-donut`'s bar-gap, colors, or label positioning. If customization is needed, create a new element variant (`chart-donut-compact.contract.md`) instead.
30
+
31
+ **Detection at execute-time**:
32
+ - If `.gsd-t/contracts/design/` exists → hierarchical mode, verify elements first, then widgets, then pages
33
+ - Else if `.gsd-t/contracts/design-contract.md` exists → flat mode
34
+ - Else → bootstrap flat contract during partition
35
+
36
+ ---
37
+
9
38
  ## 1. Design Source Setup
10
39
 
11
40
  ```
@@ -0,0 +1,121 @@
1
+ # Widget Contract: {widget-name}
2
+
3
+ Composition of elements + data binding + layout. Widgets SELECT and POSITION elements; they cannot redefine element visual specs. If a design needs a variant not covered by an existing element, create a new element contract — do not override from the widget.
4
+
5
+ ## Metadata
6
+
7
+ | Field | Value |
8
+ |----------------|-------------------------------------------------|
9
+ | widget | {e.g., revenue-breakdown-widget} |
10
+ | version | {1.0} |
11
+ | design_source | {Figma node URL or image reference} |
12
+ | extracted_date | {YYYY-MM-DD} |
13
+
14
+ ## Purpose
15
+
16
+ {One sentence — what this widget shows and why. E.g., "Displays revenue breakdown by product category with donut chart and accompanying legend-table, used on the dashboard Overview page and the Analytics detail page."}
17
+
18
+ ## Elements Used
19
+
20
+ | Slot | Element Contract | Rationale |
21
+ |------------------|-----------------------------------------|------------------------------------|
22
+ | {chart} | chart-donut | {part-to-whole comparison} |
23
+ | {legend} | legend-vertical-right | {6+ series, needs vertical space} |
24
+ | {title} | heading-h3 | {widget header} |
25
+ | {filter} | select-dropdown | {time-range selector} |
26
+
27
+ **Rule**: Each slot references an element contract by name. Widget CANNOT override element visual spec. To customize, create a new element variant.
28
+
29
+ ## Layout
30
+
31
+ ```
32
+ ┌──────────────────────────────────────────────┐
33
+ │ {title} [{filter}] │
34
+ ├──────────────────────────────────────────────┤
35
+ │ │ │
36
+ │ {chart} │ {legend} │
37
+ │ │ │
38
+ └──────────────────────────────────────────────┘
39
+ ```
40
+
41
+ | Property | Value |
42
+ |--------------------|-----------------------------------------------------|
43
+ | container_width | {100% of parent / fixed 480px} |
44
+ | container_height | {auto / fixed 320px} |
45
+ | padding | {tokens.spacing.6} |
46
+ | gap | {tokens.spacing.4} |
47
+ | background | {tokens.color.surface.card} |
48
+ | border | {1px solid tokens.color.border.subtle} |
49
+ | border_radius | {tokens.radius.lg} |
50
+ | shadow | {tokens.shadow.sm} |
51
+ | chart_area_ratio | {60% of widget width} |
52
+ | legend_area_ratio | {40% of widget width} |
53
+
54
+ ## Data Binding
55
+
56
+ **Widget input shape:**
57
+ ```typescript
58
+ {
59
+ title: string;
60
+ timeRange: '7d' | '30d' | '90d' | '1y';
61
+ data: { category: string; value: number; color?: string }[];
62
+ onFilterChange?: (range: string) => void;
63
+ }
64
+ ```
65
+
66
+ **Element data mapping:**
67
+ | Element | Receives |
68
+ |------------|------------------------------------------------------------------|
69
+ | chart | `{ categories: data.map(d=>d.category), series: [{name:'Revenue', values: data.map(d=>d.value)}]}` |
70
+ | legend | `data.map(d => ({label: d.category, value: d.value, color: d.color}))` |
71
+ | filter | `{ value: timeRange, options: ['7d','30d','90d','1y'], onChange: onFilterChange }` |
72
+
73
+ ## States
74
+
75
+ | State | Widget Behavior |
76
+ |-------------|-------------------------------------------------------------------|
77
+ | loading | Skeleton shimmer replaces chart and legend |
78
+ | empty | Chart shows empty state; legend hidden |
79
+ | error | Error banner replaces chart; filter stays enabled |
80
+
81
+ ## Responsive Behavior
82
+
83
+ | Breakpoint | Adaptation |
84
+ |------------|----------------------------------------------------------------|
85
+ | mobile | Legend drops below chart; chart becomes square |
86
+ | tablet | Legend shrinks to 35% width |
87
+ | desktop | Spec as defined above |
88
+
89
+ ## Interactions
90
+
91
+ - {Chart segment hover highlights corresponding legend row}
92
+ - {Legend row click toggles segment visibility}
93
+ - {Filter change triggers data refetch via `onFilterChange`}
94
+
95
+ ## Accessibility
96
+
97
+ - **Landmark role**: `region` with aria-labelledby pointing to title
98
+ - **Keyboard**: Tab order: filter → chart → legend rows
99
+ - **Announcements**: Data updates announced via `aria-live="polite"`
100
+
101
+ ## Implementation Notes
102
+
103
+ - **Component path**: {src/widgets/RevenueBreakdownWidget.vue}
104
+ - **Composes**: {list element components the widget imports}
105
+ - **State management**: {local state / zustand store / props only}
106
+
107
+ ## Verification Checklist
108
+
109
+ Widget-level verification runs AFTER all referenced elements pass their own verification. Widget verification only checks composition — element internals are out of scope.
110
+
111
+ - [ ] All referenced elements present and correctly slotted
112
+ - [ ] Layout dimensions (width, height, padding, gap) match design
113
+ - [ ] Responsive breakpoints adapt as specified
114
+ - [ ] Data binding produces correct element inputs (spot-check with sample data)
115
+ - [ ] Inter-element interactions fire (hover sync, click propagation)
116
+ - [ ] Loading/empty/error states render correctly
117
+ - [ ] Accessibility landmark and keyboard order correct
118
+
119
+ ## Used By
120
+
121
+ **Pages**: {list page contracts that reference this widget}