@tekyzinc/gsd-t 2.70.10 → 2.70.12
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 +21 -0
- package/commands/gsd-t-design-audit.md +56 -1
- package/commands/gsd-t-design-decompose.md +19 -0
- package/commands/gsd-t-execute.md +65 -1
- package/commands/gsd-t-quick.md +14 -2
- package/package.json +1 -1
- package/templates/stacks/design-to-code.md +63 -8
- package/templates/widget-contract.md +38 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to GSD-T are documented here. Updated with each release.
|
|
4
4
|
|
|
5
|
+
## [2.70.12] - 2026-04-06
|
|
6
|
+
|
|
7
|
+
### Added (design pipeline — element count reconciliation)
|
|
8
|
+
- **Element Count Reconciliation** — new mandatory verification step that runs BEFORE any property or visual comparison. Counts widgets and elements from the Figma decomposition (stored in INDEX.md), counts the built page's widgets and elements via Playwright, and compares. Any mismatch (missing or extra widgets/elements) is a CRITICAL deviation. Added to: `gsd-t-execute` (Step 0 inside Design Verification Agent), `gsd-t-quick` (Step 0), `gsd-t-design-audit` (Step 1.5).
|
|
9
|
+
- **Figma Element Counts table in INDEX.md** — `gsd-t-design-decompose` now writes element/widget/page counts and a per-page element manifest to INDEX.md as the verification anchor. The verification agent reads these counts as ground truth.
|
|
10
|
+
- **5-layer verification model** — design-to-code.md now documents Targets 0-4 in execution order: count reconciliation → contract comparison → Figma comparison → SVG overlay → DOM box model inspection.
|
|
11
|
+
|
|
12
|
+
### Why
|
|
13
|
+
A missing widget is the most catastrophic deviation but the easiest to miss in a 30+ row comparison table. The agent compares what exists but doesn't notice what's absent. An explicit count gate catches "Figma has 10 widgets, built page has 9 — WHERE IS THE 10TH?" before any property-level work begins.
|
|
14
|
+
|
|
15
|
+
## [2.70.11] - 2026-04-06
|
|
16
|
+
|
|
17
|
+
### Added (design pipeline — DOM box model inspection + layout arithmetic)
|
|
18
|
+
- **DOM Box Model Inspection** — new mandatory verification step for fixed-height containers. Uses Playwright to evaluate `offsetHeight` vs `scrollHeight` for each child element. Flags elements where `offsetHeight > scrollHeight * 1.5` as INFLATED (symptom: `flex: 1` on a content element inflating its box beyond content size). Added to: `gsd-t-execute` (Step 5.5 inside Design Verification Agent), `gsd-t-quick` (step 8 inside Design Verification Agent), `gsd-t-design-audit` (Step 3.75).
|
|
19
|
+
- **Internal Layout Arithmetic** — widget contract template now requires computed height budgets for fixed-height cards: `card_height - padding - header = body_available`, then `child1 + gap1 + child2 + ... = total_content ≤ body_available`. Forces the agent to write the math before coding — prevents `gap: 12px` when only `gap: 8px` fits.
|
|
20
|
+
- **Flex Centering Anti-Pattern Rule** — `design-to-code.md` Section 8 now explicitly prohibits `flex: 1` on content elements (KPI, labels, text) for centering. Rule: `flex: 1` belongs on containers, `justify-content: center` on the parent. Children keep natural size.
|
|
21
|
+
- **4 new verification checklist items** in `design-to-code.md` and `widget-contract.md`: box model inspection, layout arithmetic, no content flex:1, inflated element detection.
|
|
22
|
+
|
|
23
|
+
### Why
|
|
24
|
+
BDS horizontal stacked bar cards required 5 user-prompted fix iterations to get spacing right. Root cause: agent used `flex: 1` on `.kpi` to center it vertically, which inflated the element to 144px (content was 40px), displacing the chart section. The property comparison table and SVG overlay both missed this because the *positions* were close enough — the problem was *how space was distributed*, not where elements landed. DOM box model inspection catches the cause (inflated element) not just the symptom (displaced sibling).
|
|
25
|
+
|
|
5
26
|
## [2.70.10] - 2026-04-06
|
|
6
27
|
|
|
7
28
|
### Added (design pipeline — 2 new capabilities)
|
|
@@ -62,6 +62,35 @@ Widget: "Member Segmentation: State"
|
|
|
62
62
|
CLASSIFICATION: chart-bar-stacked-vertical (two instances side-by-side)
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
## Step 1.5: Element Count Reconciliation (MANDATORY)
|
|
66
|
+
|
|
67
|
+
Before any property comparison, verify the built page has the correct number of elements:
|
|
68
|
+
|
|
69
|
+
1. **Count from Figma** (from Step 1):
|
|
70
|
+
- Total widgets/cards identified
|
|
71
|
+
- Total elements within widgets (charts, legends, stat cards, controls, tables)
|
|
72
|
+
- Record: `Figma: {N} widgets, {M} total elements`
|
|
73
|
+
|
|
74
|
+
2. **Count from built page** (open in browser via Playwright):
|
|
75
|
+
- Count top-level visual groups (cards/widgets)
|
|
76
|
+
- Count elements within each group
|
|
77
|
+
- Record: `Built: {N} widgets, {M} total elements`
|
|
78
|
+
|
|
79
|
+
3. **Compare**:
|
|
80
|
+
- Widget count match? If NO → ❌ CRITICAL: identify MISSING or EXTRA widgets by name
|
|
81
|
+
- Element count match per widget? If NO → ❌ CRITICAL: identify MISSING or EXTRA elements
|
|
82
|
+
|
|
83
|
+
```markdown
|
|
84
|
+
### Element Count Reconciliation
|
|
85
|
+
|
|
86
|
+
| Level | Figma | Built | Verdict |
|
|
87
|
+
|--------------------|-------|-------|---------|
|
|
88
|
+
| Widgets (page) | 10 | 9 | ❌ MISSING: video-playlist-widget |
|
|
89
|
+
| Elements (total) | 27 | 24 | ❌ MISSING: 3 elements in video-playlist-widget |
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
A missing widget is the most catastrophic deviation — it means an entire section of the design was silently dropped. Catch it here before spending effort on property-level comparison of widgets that DO exist.
|
|
93
|
+
|
|
65
94
|
## Step 2: Capture the Built Screen
|
|
66
95
|
|
|
67
96
|
Open the built app at the target URL/route. For each widget identified in Step 1:
|
|
@@ -197,9 +226,35 @@ After the per-widget property comparison, run a mechanical SVG-based diff to cat
|
|
|
197
226
|
|
|
198
227
|
This step catches spacing rhythm, alignment drift, and proportion issues that pass the per-widget property check but are visually wrong in aggregate.
|
|
199
228
|
|
|
229
|
+
## Step 3.75: DOM Box Model Inspection (MANDATORY for fixed-height containers)
|
|
230
|
+
|
|
231
|
+
For each card/widget with a fixed height, inspect the internal space distribution:
|
|
232
|
+
|
|
233
|
+
1. **Evaluate in browser** (via Playwright) for each card body child:
|
|
234
|
+
- `offsetHeight` (layout box size), `scrollHeight` (content size), `flex-grow` (computed)
|
|
235
|
+
|
|
236
|
+
2. **Flag inflated elements**: any element where `offsetHeight > scrollHeight * 1.5`
|
|
237
|
+
- This means `flex: 1` or `flex-grow: 1` is inflating the element's box beyond its content
|
|
238
|
+
- Severity: HIGH — "`.kpi` offsetHeight=144px but content only needs 40px — inflated by flex growth"
|
|
239
|
+
|
|
240
|
+
3. **Verify layout arithmetic**: sum all child `offsetHeight` values + computed gaps. Compare against card body `offsetHeight`:
|
|
241
|
+
- Sum > body → content overflows (❌ DEVIATION)
|
|
242
|
+
- Sum < body by >20px with no centering strategy → space is unaccounted (❌ DEVIATION)
|
|
243
|
+
|
|
244
|
+
4. **Produce box model table** per widget:
|
|
245
|
+
|
|
246
|
+
```markdown
|
|
247
|
+
### Box Model: {widget-name}
|
|
248
|
+
|
|
249
|
+
| # | Element | offsetHeight | scrollHeight | flex-grow | Verdict |
|
|
250
|
+
|---|---------|-------------|-------------|-----------|---------|
|
|
251
|
+
| 1 | .kpi | 144px | 40px | 1 | ❌ INFLATED |
|
|
252
|
+
| 2 | .chart | 74px | 74px | 0 | ✅ MATCH |
|
|
253
|
+
```
|
|
254
|
+
|
|
200
255
|
## Step 4: Summary Report
|
|
201
256
|
|
|
202
|
-
After all widgets are audited (property tables + SVG structural diff), produce a summary:
|
|
257
|
+
After all widgets are audited (property tables + SVG structural diff + box model), produce a summary:
|
|
203
258
|
|
|
204
259
|
```markdown
|
|
205
260
|
## Design Audit Summary
|
|
@@ -280,6 +280,25 @@ Write `INDEX.md` as a navigation map:
|
|
|
280
280
|
element contract > widget contract > page contract
|
|
281
281
|
|
|
282
282
|
Widgets and pages reference elements by name. They CANNOT override element visual spec. To customize, create a new element variant.
|
|
283
|
+
|
|
284
|
+
## Figma Element Counts (MANDATORY — verification anchor)
|
|
285
|
+
|
|
286
|
+
These counts are captured from the Figma decomposition and serve as the
|
|
287
|
+
ground truth during verification. Any mismatch between these counts and
|
|
288
|
+
the built output is a CRITICAL deviation.
|
|
289
|
+
|
|
290
|
+
| Level | Count | Source |
|
|
291
|
+
|----------|-------|---------------------------------|
|
|
292
|
+
| Elements | {N} | Inventory table (Step 1d) |
|
|
293
|
+
| Widgets | {N} | Widget inventory (Step 3) |
|
|
294
|
+
| Pages | {N} | Page inventory (Step 4) |
|
|
295
|
+
| Total | {N} | Sum of all contracts |
|
|
296
|
+
|
|
297
|
+
Per-page element manifest (for verification agent):
|
|
298
|
+
| Page | Widgets | Elements (including widget-internal) |
|
|
299
|
+
|--------------------|---------|--------------------------------------|
|
|
300
|
+
| {dashboard} | {N} | {N} — {list: stat-card ×4, chart-donut ×1, ...} |
|
|
301
|
+
| {analytics} | {N} | {N} — {list} |
|
|
283
302
|
```
|
|
284
303
|
|
|
285
304
|
## Step 6.5: Contract-vs-Figma Verification Gate (MANDATORY)
|
|
@@ -632,7 +632,28 @@ each one matches — not assume it does. 'Looks close' is not a verdict.
|
|
|
632
632
|
'Appears to match' is not a verdict. The only valid verdicts are MATCH
|
|
633
633
|
(with proof) or DEVIATION (with specifics).
|
|
634
634
|
|
|
635
|
-
## Step 0:
|
|
635
|
+
## Step 0: Element Count Reconciliation (MANDATORY — run BEFORE anything else)
|
|
636
|
+
|
|
637
|
+
Before any visual or property comparison, verify the built page has the
|
|
638
|
+
correct NUMBER of elements. A missing widget is the easiest deviation to
|
|
639
|
+
miss in a 30+ row comparison table — and the most catastrophic.
|
|
640
|
+
|
|
641
|
+
1. Read INDEX.md (hierarchical) or design-contract.md (flat) to get the
|
|
642
|
+
Figma element counts:
|
|
643
|
+
- Per-page: how many widgets on this page? How many total elements
|
|
644
|
+
(including widget-internal charts, legends, cards, controls)?
|
|
645
|
+
2. Count the built page's distinct visual elements via Playwright:
|
|
646
|
+
- Widgets/cards (top-level visual groups)
|
|
647
|
+
- Charts, tables, stat cards, legends, controls within each widget
|
|
648
|
+
3. Compare:
|
|
649
|
+
- Figma widget count vs built widget count → mismatch = ❌ CRITICAL
|
|
650
|
+
- Figma element count vs built element count → mismatch = ❌ CRITICAL
|
|
651
|
+
4. If counts match → proceed to Step 0.5
|
|
652
|
+
If counts DON'T match → identify WHICH elements are missing or extra:
|
|
653
|
+
'Figma has {N} widgets, built page has {M}. MISSING: {list}. EXTRA: {list}'
|
|
654
|
+
Log as CRITICAL deviation — do NOT skip, continue with remaining steps.
|
|
655
|
+
|
|
656
|
+
## Step 0.5: Data-Labels Cross-Check (MANDATORY)
|
|
636
657
|
|
|
637
658
|
Before any visual comparison, verify the built UI is rendering the CORRECT
|
|
638
659
|
DATA from the design. This is the most common failure mode: agents use
|
|
@@ -785,6 +806,49 @@ aggregate visual drift that individual property checks miss.
|
|
|
785
806
|
This step catches spacing rhythm, alignment drift, and proportion issues
|
|
786
807
|
that pass the property-level check but are visually wrong in aggregate.
|
|
787
808
|
|
|
809
|
+
## Step 5.5: DOM Box Model Inspection (MANDATORY for fixed-height containers)
|
|
810
|
+
|
|
811
|
+
The property table catches wrong values. The SVG overlay catches wrong positions.
|
|
812
|
+
This step catches wrong SPACE DISTRIBUTION — elements whose box model is inflated
|
|
813
|
+
by flex growth, pushing siblings out of position even when the visual appears close.
|
|
814
|
+
|
|
815
|
+
For each card/widget with a fixed height (container_height is not 'auto'):
|
|
816
|
+
|
|
817
|
+
1. Use Playwright to evaluate in the browser:
|
|
818
|
+
```javascript
|
|
819
|
+
// For each child element of the card body:
|
|
820
|
+
const children = await page.$$eval('.card-body > *', els =>
|
|
821
|
+
els.map(el => ({
|
|
822
|
+
selector: el.className,
|
|
823
|
+
offsetHeight: el.offsetHeight,
|
|
824
|
+
scrollHeight: el.scrollHeight,
|
|
825
|
+
computedFlex: getComputedStyle(el).flex,
|
|
826
|
+
computedFlexGrow: getComputedStyle(el).flexGrow,
|
|
827
|
+
}))
|
|
828
|
+
);
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
2. Flag any element where `offsetHeight > scrollHeight * 1.5`:
|
|
832
|
+
This means the element's layout box is ≥50% larger than its content.
|
|
833
|
+
Symptom: element is using `flex: 1` or `flex-grow: 1` and inflating.
|
|
834
|
+
❌ DEVIATION (severity HIGH): '{selector} offsetHeight={X}px but
|
|
835
|
+
content only needs {scrollHeight}px — inflated by flex growth.
|
|
836
|
+
Fix: remove flex:1 from this element, apply justify-content:center
|
|
837
|
+
on its parent container instead.'
|
|
838
|
+
|
|
839
|
+
3. Verify layout arithmetic:
|
|
840
|
+
- Read the widget contract's Internal Layout Arithmetic section
|
|
841
|
+
- Sum all child offsetHeights + computed gaps
|
|
842
|
+
- Compare against the card body's offsetHeight
|
|
843
|
+
- If sum > body height → ❌ DEVIATION: content overflows
|
|
844
|
+
- If sum < body height by >20px with no centering strategy → ❌ DEVIATION
|
|
845
|
+
|
|
846
|
+
4. Produce box model table:
|
|
847
|
+
| # | Element | offsetHeight | scrollHeight | flex-grow | Verdict |
|
|
848
|
+
|---|---------|-------------|-------------|-----------|---------|
|
|
849
|
+
| 1 | .kpi | 144px | 40px | 1 | ❌ INFLATED |
|
|
850
|
+
| 2 | .chart | 74px | 74px | 0 | ✅ MATCH |
|
|
851
|
+
|
|
788
852
|
## Step 6: Report Deviations
|
|
789
853
|
|
|
790
854
|
For each ❌ DEVIATION, write a specific finding:
|
package/commands/gsd-t-quick.md
CHANGED
|
@@ -259,7 +259,12 @@ comparison table. You write ZERO feature code.
|
|
|
259
259
|
|
|
260
260
|
FAIL-BY-DEFAULT: Every visual element starts as UNVERIFIED. Prove each matches.
|
|
261
261
|
|
|
262
|
-
STEP 0 (MANDATORY FIRST):
|
|
262
|
+
STEP 0 (MANDATORY FIRST): Element count reconciliation.
|
|
263
|
+
Read INDEX.md or design-contract.md for Figma element counts (widgets per page,
|
|
264
|
+
total elements per page). Count the built page's widgets and elements via Playwright.
|
|
265
|
+
If counts don't match → CRITICAL DEVIATION: identify which are MISSING or EXTRA.
|
|
266
|
+
|
|
267
|
+
STEP 0.5: Data-labels cross-check.
|
|
263
268
|
For each element contract (or design-contract.md section), read the Test Fixture.
|
|
264
269
|
Verify EVERY label, value, percentage from the fixture appears verbatim in the
|
|
265
270
|
rendered UI. If any is missing → CRITICAL DEVIATION (wrong data). Wrong data
|
|
@@ -288,7 +293,14 @@ cannot be redeemed by visual polish.
|
|
|
288
293
|
| # | SVG Element | SVG Position | Built Position | Δ px | Verdict |
|
|
289
294
|
g. Flag unmapped SVG elements as MISSING, unmapped DOM elements as EXTRA
|
|
290
295
|
This catches aggregate visual drift that property-level checks miss.
|
|
291
|
-
8.
|
|
296
|
+
8. DOM Box Model Inspection (for fixed-height containers):
|
|
297
|
+
a. For each card body child, evaluate: offsetHeight, scrollHeight, flex-grow
|
|
298
|
+
b. Flag elements where offsetHeight > scrollHeight * 1.5 as INFLATED
|
|
299
|
+
(element using flex:1 when it shouldn't — box larger than content)
|
|
300
|
+
c. Verify layout arithmetic: sum of child heights + gaps = body height
|
|
301
|
+
d. Produce box model table:
|
|
302
|
+
| Element | offsetHeight | scrollHeight | flex-grow | Verdict |
|
|
303
|
+
9. Write results (property table + SVG diff + box model) to .gsd-t/contracts/design-contract.md
|
|
292
304
|
under '## Verification Status'
|
|
293
305
|
9. Any ❌ → append to .gsd-t/qa-issues.md with [VISUAL] tag
|
|
294
306
|
10. Report: DESIGN VERIFIED | DESIGN DEVIATIONS FOUND ({count})"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekyzinc/gsd-t",
|
|
3
|
-
"version": "2.70.
|
|
3
|
+
"version": "2.70.12",
|
|
4
4
|
"description": "GSD-T: Contract-Driven Development for Claude Code — 54 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",
|
|
@@ -281,6 +281,47 @@ MANDATORY:
|
|
|
281
281
|
|
|
282
282
|
**GOOD** — Extracting gap as exactly `24px` from the design, then: `display: flex; gap: 1.5rem; /* 24px — design contract: section-gap */`
|
|
283
283
|
|
|
284
|
+
### Flex Centering Anti-Pattern (MANDATORY)
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
NEVER use flex: 1 on a content element to center its text/content.
|
|
288
|
+
flex: 1 makes the ELEMENT GROW to fill available space — the content
|
|
289
|
+
centers within an oversized box, but the box itself displaces siblings.
|
|
290
|
+
|
|
291
|
+
WRONG — content element grows, inflated box shifts layout:
|
|
292
|
+
.kpi { flex: 1; display: flex; justify-content: center; }
|
|
293
|
+
|
|
294
|
+
RIGHT — parent grows, children keep natural size:
|
|
295
|
+
.body { flex: 1; display: flex; flex-direction: column;
|
|
296
|
+
justify-content: center; }
|
|
297
|
+
.kpi { /* no flex: 1 — natural height only */ }
|
|
298
|
+
|
|
299
|
+
RULE: flex: 1 belongs on CONTAINERS, not on CONTENT elements.
|
|
300
|
+
To center content vertically, apply justify-content: center
|
|
301
|
+
on the parent — never flex: 1 on the child.
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Fixed-Height Container Arithmetic (MANDATORY)
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
When a card or container has a fixed height, BEFORE writing any CSS:
|
|
308
|
+
1. Compute the total available body height:
|
|
309
|
+
body_available = card_height - padding_top - padding_bottom
|
|
310
|
+
- header_height - header_to_body_gap
|
|
311
|
+
2. List every child element's height (from the design contract)
|
|
312
|
+
3. List every gap between children
|
|
313
|
+
4. SUM them: total_content = child1 + gap1 + child2 + gap2 + ...
|
|
314
|
+
5. Compare: total_content MUST ≤ body_available
|
|
315
|
+
6. If total_content < body_available:
|
|
316
|
+
Document the centering strategy (justify-content: center on parent)
|
|
317
|
+
7. If total_content > body_available:
|
|
318
|
+
The design extraction is wrong — go back to Figma
|
|
319
|
+
|
|
320
|
+
This arithmetic goes in the widget contract's Internal Layout
|
|
321
|
+
Arithmetic section. The implementation MUST match the arithmetic.
|
|
322
|
+
If gap: 12px makes the math exceed body_available, use gap: 8px.
|
|
323
|
+
```
|
|
324
|
+
|
|
284
325
|
---
|
|
285
326
|
|
|
286
327
|
## 9. Responsive Breakpoint Strategy
|
|
@@ -519,7 +560,12 @@ MANDATORY:
|
|
|
519
560
|
The verification agent compares the built frontend against **TWO sources** — not just one:
|
|
520
561
|
|
|
521
562
|
```
|
|
522
|
-
VERIFICATION TARGETS:
|
|
563
|
+
VERIFICATION TARGETS (run in this order):
|
|
564
|
+
├── TARGET 0: ELEMENT COUNT RECONCILIATION (run FIRST)
|
|
565
|
+
│ Does the built page have the same NUMBER of widgets and elements
|
|
566
|
+
│ as the Figma design? A missing widget is the most catastrophic
|
|
567
|
+
│ deviation — catch it before spending effort on property comparison.
|
|
568
|
+
│
|
|
523
569
|
├── TARGET 1: Built screen vs DESIGN CONTRACTS
|
|
524
570
|
│ Does the code match the contract's claimed values?
|
|
525
571
|
│ (This is what the 13-task validation proved works — airtight.)
|
|
@@ -529,15 +575,19 @@ VERIFICATION TARGETS:
|
|
|
529
575
|
│ This catches: contracts that were wrong to begin with,
|
|
530
576
|
│ chart type misclassification, hallucinated data, missing elements.
|
|
531
577
|
│
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
578
|
+
├── TARGET 3: SVG STRUCTURAL OVERLAY (MANDATORY)
|
|
579
|
+
│ Export Figma frame as SVG → parse element positions/dimensions/colors
|
|
580
|
+
│ → compare geometrically against built DOM bounding boxes.
|
|
581
|
+
│ This catches: aggregate spacing drift, alignment issues, proportion
|
|
582
|
+
│ errors that pass property-level checks but look wrong visually.
|
|
583
|
+
│
|
|
584
|
+
└── TARGET 4: DOM BOX MODEL INSPECTION (fixed-height containers)
|
|
585
|
+
Evaluate offsetHeight vs scrollHeight per child element.
|
|
586
|
+
This catches: inflated flex boxes, wrong space distribution,
|
|
587
|
+
elements growing beyond their content size.
|
|
538
588
|
```
|
|
539
589
|
|
|
540
|
-
**
|
|
590
|
+
**Each target catches a different failure class.** Target 0: missing elements. Target 1: wrong values. Target 2: wrong contracts. Target 3: wrong placement. Target 4: wrong space distribution. All five are needed — no single layer catches everything.
|
|
541
591
|
|
|
542
592
|
### Verification agent workflow
|
|
543
593
|
|
|
@@ -611,6 +661,8 @@ Before marking any design implementation task as complete:
|
|
|
611
661
|
- [ ] Design system / component library identified (or confirmed none) and documented in design contract
|
|
612
662
|
- [ ] Library components mapped to design elements — custom build only where no library match exists
|
|
613
663
|
- [ ] Design source identified and documented in design contract
|
|
664
|
+
- [ ] Element counts recorded in INDEX.md (widgets per page, elements per page)
|
|
665
|
+
- [ ] Built page element count matches Figma element count (no missing/extra widgets)
|
|
614
666
|
- [ ] Stack capability evaluated — all design requirements achievable (or alternatives approved)
|
|
615
667
|
- [ ] All design tokens extracted (colors, typography, spacing, borders, shadows)
|
|
616
668
|
- [ ] Tokens written to `.gsd-t/contracts/design-contract.md`
|
|
@@ -628,4 +680,7 @@ Before marking any design implementation task as complete:
|
|
|
628
680
|
- [ ] Accessibility: focus indicators, alt text, ARIA where needed, 44px touch targets
|
|
629
681
|
- [ ] No magic numbers — every value is documented or uses a design token
|
|
630
682
|
- [ ] SVG structural overlay comparison completed — geometry diff ≤2px per element
|
|
683
|
+
- [ ] DOM box model inspection passed — no inflated elements (offsetHeight >> scrollHeight)
|
|
684
|
+
- [ ] Layout arithmetic verified — child heights + gaps = body available height (fixed-height cards)
|
|
685
|
+
- [ ] No content element uses `flex: 1` for centering — only parent containers
|
|
631
686
|
- [ ] Verification results logged in design contract Verification Status table
|
|
@@ -95,6 +95,41 @@ This section specifies how elements are sized, spaced, and aligned WITHIN the ca
|
|
|
95
95
|
- `body_layout` + `body_justify` + `body_align` together define whether the chart is centered in its card, left-aligned, or stretched. Get this wrong and every widget "looks off."
|
|
96
96
|
- These values are WIDGET-OWNED — they describe how the widget positions its elements, not the elements' internal specs (which live in element contracts).
|
|
97
97
|
|
|
98
|
+
### Internal Layout Arithmetic (MANDATORY for fixed-height cards)
|
|
99
|
+
|
|
100
|
+
When `container_height` is fixed (not `auto`), you MUST compute and document the internal height budget. The math must add up exactly — no approximation.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
card_height: {e.g., 334px}
|
|
104
|
+
card_padding_top: {e.g., 16px}
|
|
105
|
+
card_padding_bottom: {e.g., 16px}
|
|
106
|
+
header_height: {title + subtitle + gap} = {e.g., 48px}
|
|
107
|
+
header_to_body_gap: {e.g., 16px}
|
|
108
|
+
─────────────────────────────────────────────────
|
|
109
|
+
body_available: {card_height - padding_top - padding_bottom
|
|
110
|
+
- header_height - header_to_body_gap}
|
|
111
|
+
= {e.g., 334 - 16 - 16 - 48 - 16 = 238px}
|
|
112
|
+
|
|
113
|
+
body_breakdown:
|
|
114
|
+
kpi_height: {natural content height, e.g., 40px — NOT flex:1}
|
|
115
|
+
kpi_to_chart_gap: {e.g., 16px}
|
|
116
|
+
chart_section: {bar + gap + labels + gap + legend}
|
|
117
|
+
= {e.g., 30 + 8 + 12 + 8 + 16 = 74px}
|
|
118
|
+
────────────────────
|
|
119
|
+
total_body_content: {40 + 16 + 74 = 130px}
|
|
120
|
+
remaining_space: {238 - 130 = 108px}
|
|
121
|
+
|
|
122
|
+
centering_strategy: {e.g., body uses flex-column + justify-content: center
|
|
123
|
+
to vertically center the content group (KPI + chart)
|
|
124
|
+
in the 238px body area. KPI keeps natural height.}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Rules:**
|
|
128
|
+
- Every row must be an exact pixel value extracted from the Figma design
|
|
129
|
+
- The sum of all body content MUST equal `body_available` OR explicitly document how remaining space is distributed (centering, padding, etc.)
|
|
130
|
+
- **NEVER use `flex: 1` on a content element (KPI, label, text) to center it.** `flex: 1` makes the element grow to fill available space, inflating its box model. Use `flex: 1` + `justify-content: center` on the PARENT container instead. The parent grows; children keep natural size.
|
|
131
|
+
- If the math doesn't add up, the design extraction is incomplete — go back to Figma
|
|
132
|
+
|
|
98
133
|
## Data Binding
|
|
99
134
|
|
|
100
135
|
**Widget input shape:**
|
|
@@ -189,6 +224,9 @@ Widget-level verification runs AFTER all referenced elements pass their own veri
|
|
|
189
224
|
- [ ] Element sizing matches design (chart_width, chart_height, legend_width)
|
|
190
225
|
- [ ] Legend alignment matches design (footer_legend_justify: center vs left)
|
|
191
226
|
- [ ] Card container values match design (padding, border, radius, shadow)
|
|
227
|
+
- [ ] Layout arithmetic adds up: sum of child heights + gaps = body_available (fixed-height cards only)
|
|
228
|
+
- [ ] No content element uses `flex: 1` for centering — only parent containers may use `flex: 1`
|
|
229
|
+
- [ ] DOM box model check: no element's offsetHeight >> its content height (inflated box = wrong flex)
|
|
192
230
|
- [ ] Responsive breakpoints adapt as specified
|
|
193
231
|
- [ ] Data binding produces correct element inputs (spot-check with sample data)
|
|
194
232
|
- [ ] Inter-element interactions fire (hover sync, click propagation)
|