@hegemonart/get-design-done 1.0.7
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/.claude-plugin/marketplace.json +63 -0
- package/.claude-plugin/plugin.json +54 -0
- package/CHANGELOG.md +221 -0
- package/LICENSE +21 -0
- package/README.md +724 -0
- package/SKILL.md +232 -0
- package/agents/README.md +226 -0
- package/agents/a11y-mapper.md +118 -0
- package/agents/component-taxonomy-mapper.md +88 -0
- package/agents/design-advisor.md +139 -0
- package/agents/design-assumptions-analyzer.md +171 -0
- package/agents/design-auditor.md +383 -0
- package/agents/design-context-builder.md +544 -0
- package/agents/design-context-checker-gate.md +90 -0
- package/agents/design-context-checker.md +260 -0
- package/agents/design-discussant.md +98 -0
- package/agents/design-doc-writer.md +229 -0
- package/agents/design-executor.md +452 -0
- package/agents/design-figma-writer.md +302 -0
- package/agents/design-fixer.md +180 -0
- package/agents/design-integration-checker-gate.md +93 -0
- package/agents/design-integration-checker.md +326 -0
- package/agents/design-pattern-mapper.md +206 -0
- package/agents/design-phase-researcher.md +229 -0
- package/agents/design-plan-checker.md +164 -0
- package/agents/design-planner.md +352 -0
- package/agents/design-reflector.md +175 -0
- package/agents/design-research-synthesizer.md +127 -0
- package/agents/design-verifier-gate.md +97 -0
- package/agents/design-verifier.md +605 -0
- package/agents/gdd-graphify-sync.md +100 -0
- package/agents/gdd-intel-updater.md +88 -0
- package/agents/gdd-learnings-extractor.md +85 -0
- package/agents/motion-mapper.md +103 -0
- package/agents/token-mapper.md +103 -0
- package/agents/visual-hierarchy-mapper.md +95 -0
- package/connections/chromatic.md +247 -0
- package/connections/claude-design.md +190 -0
- package/connections/connections.md +218 -0
- package/connections/figma-writer.md +139 -0
- package/connections/figma.md +146 -0
- package/connections/graphify.md +197 -0
- package/connections/pinterest.md +153 -0
- package/connections/preview.md +173 -0
- package/connections/refero.md +189 -0
- package/connections/storybook.md +280 -0
- package/hooks/budget-enforcer.js +318 -0
- package/hooks/context-exhaustion.js +127 -0
- package/hooks/gdd-read-injection-scanner.js +44 -0
- package/hooks/hooks.json +44 -0
- package/package.json +60 -0
- package/reference/BRANCH-PROTECTION.md +65 -0
- package/reference/DEPRECATIONS.md +41 -0
- package/reference/STATE-TEMPLATE.md +200 -0
- package/reference/accessibility.md +190 -0
- package/reference/anti-patterns.md +336 -0
- package/reference/audit-scoring.md +205 -0
- package/reference/checklists.md +137 -0
- package/reference/config-schema.md +319 -0
- package/reference/debugger-philosophy.md +32 -0
- package/reference/heuristics.md +201 -0
- package/reference/intel-schema.md +266 -0
- package/reference/model-prices.md +37 -0
- package/reference/model-tiers.md +118 -0
- package/reference/motion.md +285 -0
- package/reference/parallelism-rules.md +108 -0
- package/reference/priority-matrix.md +31 -0
- package/reference/project-skills-guide.md +42 -0
- package/reference/review-format.md +107 -0
- package/reference/schemas/config.schema.json +41 -0
- package/reference/schemas/hooks.schema.json +55 -0
- package/reference/schemas/intel.schema.json +191 -0
- package/reference/schemas/marketplace.schema.json +72 -0
- package/reference/schemas/plugin.schema.json +59 -0
- package/reference/shared-preamble.md +82 -0
- package/reference/typography.md +229 -0
- package/scripts/aggregate-agent-metrics.js +144 -0
- package/scripts/apply-branch-protection.sh +75 -0
- package/scripts/bootstrap-manifest.txt +3 -0
- package/scripts/bootstrap.sh +80 -0
- package/scripts/build-intel.cjs +458 -0
- package/scripts/detect-stale-refs.cjs +101 -0
- package/scripts/extract-changelog-section.cjs +57 -0
- package/scripts/release-smoke-test.cjs +169 -0
- package/scripts/rollback-release.sh +42 -0
- package/scripts/run-injection-scanner-ci.cjs +92 -0
- package/scripts/validate-frontmatter.cjs +68 -0
- package/scripts/validate-schemas.cjs +225 -0
- package/scripts/verify-version-sync.cjs +30 -0
- package/skills/add-backlog/SKILL.md +47 -0
- package/skills/analyze-dependencies/SKILL.md +184 -0
- package/skills/apply-reflections/SKILL.md +112 -0
- package/skills/audit/SKILL.md +54 -0
- package/skills/brief/SKILL.md +75 -0
- package/skills/cache-manager/SKILL.md +120 -0
- package/skills/compare/SKILL.md +322 -0
- package/skills/complete-cycle/SKILL.md +33 -0
- package/skills/darkmode/SKILL.md +331 -0
- package/skills/debug/SKILL.md +38 -0
- package/skills/design/SKILL.md +281 -0
- package/skills/discover/SKILL.md +172 -0
- package/skills/discuss/SKILL.md +67 -0
- package/skills/do/SKILL.md +45 -0
- package/skills/explore/SKILL.md +109 -0
- package/skills/extract-learnings/SKILL.md +98 -0
- package/skills/fast/SKILL.md +44 -0
- package/skills/figma-write/SKILL.md +40 -0
- package/skills/graphify/SKILL.md +48 -0
- package/skills/health/SKILL.md +48 -0
- package/skills/help/SKILL.md +76 -0
- package/skills/list-assumptions/SKILL.md +60 -0
- package/skills/map/SKILL.md +112 -0
- package/skills/new-cycle/SKILL.md +35 -0
- package/skills/new-project/SKILL.md +53 -0
- package/skills/next/SKILL.md +42 -0
- package/skills/note/SKILL.md +47 -0
- package/skills/optimize/SKILL.md +120 -0
- package/skills/pause/SKILL.md +41 -0
- package/skills/plan/SKILL.md +251 -0
- package/skills/plant-seed/SKILL.md +47 -0
- package/skills/pr-branch/SKILL.md +31 -0
- package/skills/progress/SKILL.md +60 -0
- package/skills/quick/SKILL.md +43 -0
- package/skills/reapply-patches/SKILL.md +31 -0
- package/skills/reflect/SKILL.md +73 -0
- package/skills/resume/SKILL.md +37 -0
- package/skills/review-backlog/SKILL.md +45 -0
- package/skills/router/SKILL.md +67 -0
- package/skills/scan/SKILL.md +721 -0
- package/skills/settings/SKILL.md +78 -0
- package/skills/ship/SKILL.md +31 -0
- package/skills/sketch/SKILL.md +78 -0
- package/skills/sketch-wrap-up/SKILL.md +88 -0
- package/skills/skill-manifest/SKILL.md +79 -0
- package/skills/spike/SKILL.md +67 -0
- package/skills/spike-wrap-up/SKILL.md +81 -0
- package/skills/stats/SKILL.md +50 -0
- package/skills/style/SKILL.md +193 -0
- package/skills/synthesize/SKILL.md +93 -0
- package/skills/todo/SKILL.md +54 -0
- package/skills/undo/SKILL.md +30 -0
- package/skills/update/SKILL.md +36 -0
- package/skills/verify/SKILL.md +452 -0
- package/skills/warm-cache/SKILL.md +113 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# Motion & Animation Framework
|
|
2
|
+
|
|
3
|
+
Based on Emil Kowalski's design engineering philosophy. Apply these rules in order — do not skip to "how should this animate" before answering "should this animate."
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Decision Framework (Run In Order)
|
|
8
|
+
|
|
9
|
+
### Question 1: Should This Animate At All?
|
|
10
|
+
|
|
11
|
+
| Action frequency | Decision |
|
|
12
|
+
|---|---|
|
|
13
|
+
| 100+/day — keyboard shortcuts, command palette, list navigation | **No animation. Ever.** |
|
|
14
|
+
| Tens/day — hover states, toggles, tab switching | Remove or keep to <80ms. No delay. |
|
|
15
|
+
| Occasional — modals opening, drawers, toasts | Standard animation (150–300ms) |
|
|
16
|
+
| Rare — onboarding, celebrations, first-time flows | Can add personality and delight |
|
|
17
|
+
| Once — loading splash, page transitions | Full animation budget |
|
|
18
|
+
|
|
19
|
+
**Critical rule**: Never animate keyboard-initiated actions. They repeat hundreds of times daily. Every ms of animation is felt.
|
|
20
|
+
|
|
21
|
+
### Question 2: What Is The Purpose?
|
|
22
|
+
|
|
23
|
+
Valid animation purposes only. If it doesn't serve one of these, remove it.
|
|
24
|
+
|
|
25
|
+
| Purpose | Example |
|
|
26
|
+
|---|---|
|
|
27
|
+
| **Spatial consistency** | Toast enters/exits same edge each time |
|
|
28
|
+
| **State indication** | Button morphs to show loading → success |
|
|
29
|
+
| **Cause-effect explanation** | Item deletion — item flies to trash |
|
|
30
|
+
| **Feedback** | Button scales 0.97 on press |
|
|
31
|
+
| **Prevent jarring changes** | Content appearing/disappearing needs transition |
|
|
32
|
+
|
|
33
|
+
Invalid purposes: "It looks cool", "It feels modern", "Other apps do it."
|
|
34
|
+
|
|
35
|
+
### Question 3: What Easing?
|
|
36
|
+
|
|
37
|
+
| Element state | Easing | Rationale |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| **Entering** | `ease-out` (fast start, slow end) | Feels responsive — starts immediately |
|
|
40
|
+
| **Exiting** | `ease-in` (slow start, fast end) | Gets out of the way — doesn't linger |
|
|
41
|
+
| **State transition** (same element) | `ease-in-out` | Natural — neither abrupt start nor end |
|
|
42
|
+
| **Interactive/draggable** | Spring physics | Follows finger/cursor naturally |
|
|
43
|
+
| **Bounce/elastic** | **Never** | Feels toy-like and dated |
|
|
44
|
+
|
|
45
|
+
CSS:
|
|
46
|
+
```css
|
|
47
|
+
/* Enter */
|
|
48
|
+
transition: transform 200ms cubic-bezier(0, 0, 0.2, 1); /* ease-out */
|
|
49
|
+
|
|
50
|
+
/* Exit */
|
|
51
|
+
transition: transform 150ms cubic-bezier(0.4, 0, 1, 1); /* ease-in */
|
|
52
|
+
|
|
53
|
+
/* Transition */
|
|
54
|
+
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1); /* ease-in-out */
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Question 4: What Duration?
|
|
58
|
+
|
|
59
|
+
| Animation type | Duration | Notes |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Micro-interactions | 80–150ms | Hover, press, toggle |
|
|
62
|
+
| Component enter/exit | 150–250ms | Modals, drawers, dropdowns |
|
|
63
|
+
| Page transitions | 200–350ms | Route changes |
|
|
64
|
+
| Complex/orchestrated | ≤400ms | Multi-step, staggered reveals |
|
|
65
|
+
| **Never exceed** | 400ms | Anything longer feels broken |
|
|
66
|
+
|
|
67
|
+
**Exit faster than enter**: Exit animations should run at **60–70%** of the enter duration. Exiting elements should get out of the way fast.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Enter: 250ms
|
|
71
|
+
Exit: 150ms (60% of 250)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Question 5: Only Animate `transform` and `opacity`
|
|
75
|
+
|
|
76
|
+
**Only these properties animate on the GPU:**
|
|
77
|
+
```css
|
|
78
|
+
/* SAFE */
|
|
79
|
+
transform: translateX(), translateY(), scale(), rotate()
|
|
80
|
+
opacity: 0 → 1
|
|
81
|
+
|
|
82
|
+
/* DANGEROUS — triggers layout/paint */
|
|
83
|
+
width, height, top, left, margin, padding, font-size
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Exception: `filter` (blur) is GPU-accelerated in modern browsers but battery-expensive on mobile.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Stagger Rules
|
|
91
|
+
|
|
92
|
+
When animating a list of items entering:
|
|
93
|
+
- Stagger delay: **30–50ms** per item
|
|
94
|
+
- Maximum stagger depth: **6–8 items** (items beyond that appear simultaneously)
|
|
95
|
+
- Direction: top-to-bottom OR left-to-right — never random
|
|
96
|
+
|
|
97
|
+
```css
|
|
98
|
+
.item:nth-child(1) { animation-delay: 0ms; }
|
|
99
|
+
.item:nth-child(2) { animation-delay: 40ms; }
|
|
100
|
+
.item:nth-child(3) { animation-delay: 80ms; }
|
|
101
|
+
/* etc. — cap at ~6 staggered items */
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Press Feedback
|
|
107
|
+
|
|
108
|
+
Every clickable element must give visual feedback within **100ms** of interaction.
|
|
109
|
+
|
|
110
|
+
```css
|
|
111
|
+
button:active {
|
|
112
|
+
transform: scale(0.97); /* NOT 0.90 — too dramatic */
|
|
113
|
+
transition: transform 80ms ease-out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* On release */
|
|
117
|
+
button:not(:active) {
|
|
118
|
+
transform: scale(1);
|
|
119
|
+
transition: transform 150ms ease-out;
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Scale range: **0.95–0.98** for buttons. **0.97** is the safest default.
|
|
124
|
+
Never scale below 0.90 — it looks broken.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## `prefers-reduced-motion`
|
|
129
|
+
|
|
130
|
+
Always respect this. It's not optional.
|
|
131
|
+
|
|
132
|
+
```css
|
|
133
|
+
@media (prefers-reduced-motion: reduce) {
|
|
134
|
+
*,
|
|
135
|
+
*::before,
|
|
136
|
+
*::after {
|
|
137
|
+
animation-duration: 0.01ms !important;
|
|
138
|
+
animation-iteration-count: 1 !important;
|
|
139
|
+
transition-duration: 0.01ms !important;
|
|
140
|
+
scroll-behavior: auto !important;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Or in JavaScript:
|
|
146
|
+
```js
|
|
147
|
+
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
148
|
+
if (!prefersReduced) {
|
|
149
|
+
// Run animation
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## What Never To Animate
|
|
156
|
+
|
|
157
|
+
- Keyboard shortcuts and commands (too frequent)
|
|
158
|
+
- Tab switching within a page
|
|
159
|
+
- Filter/sort toggles on data tables
|
|
160
|
+
- Expanding/collapsing sidebar navigation items during heavy use
|
|
161
|
+
- Any interaction the user will perform 50+ times in a session
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## The Invisible Detail Rule
|
|
166
|
+
|
|
167
|
+
The best animations are ones users cannot describe but notice when absent. Signs of this:
|
|
168
|
+
- The interaction feels "snappy" or "responsive" without thinking about why
|
|
169
|
+
- Removing the animation makes the UI feel broken
|
|
170
|
+
- Users say "it feels premium" but can't point to any specific feature
|
|
171
|
+
|
|
172
|
+
This is the goal. Not "look at this animation" — "why does this feel so good to use?"
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Quick Animation Audit Checklist
|
|
177
|
+
|
|
178
|
+
- [ ] No animation on keyboard-triggered actions
|
|
179
|
+
- [ ] All durations ≤ 400ms
|
|
180
|
+
- [ ] Exit < enter duration
|
|
181
|
+
- [ ] Only `transform` and `opacity` for performance
|
|
182
|
+
- [ ] `prefers-reduced-motion` implemented
|
|
183
|
+
- [ ] Stagger ≤ 50ms per item, capped at 6–8 items
|
|
184
|
+
- [ ] Press feedback on all interactive elements
|
|
185
|
+
- [ ] No bounce/elastic easing anywhere
|
|
186
|
+
- [ ] All animations have a defined purpose
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Spring Physics
|
|
191
|
+
|
|
192
|
+
Spring-based animation replaces duration-based tweening with physics parameters
|
|
193
|
+
(stiffness, damping, mass). Output feels more organic and adapts to interruption.
|
|
194
|
+
|
|
195
|
+
### React Spring
|
|
196
|
+
|
|
197
|
+
```jsx
|
|
198
|
+
import { useSpring, animated } from '@react-spring/web';
|
|
199
|
+
|
|
200
|
+
const styles = useSpring({
|
|
201
|
+
from: { opacity: 0, transform: 'translateY(20px)' },
|
|
202
|
+
to: { opacity: 1, transform: 'translateY(0px)' },
|
|
203
|
+
config: { tension: 170, friction: 26 } // default preset
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
React Spring presets:
|
|
208
|
+
|
|
209
|
+
| Preset | tension | friction | Character |
|
|
210
|
+
|--------|---------|----------|-----------|
|
|
211
|
+
| default | 170 | 26 | balanced |
|
|
212
|
+
| gentle | 120 | 14 | smooth, leisurely |
|
|
213
|
+
| wobbly | 180 | 12 | playful bounce |
|
|
214
|
+
| stiff | 210 | 20 | snappy |
|
|
215
|
+
| slow | 280 | 60 | slow and deliberate |
|
|
216
|
+
| molasses | 280 | 120 | very slow, no bounce |
|
|
217
|
+
|
|
218
|
+
### Framer Motion
|
|
219
|
+
|
|
220
|
+
```jsx
|
|
221
|
+
<motion.div
|
|
222
|
+
animate={{ x: 100 }}
|
|
223
|
+
transition={{ type: "spring", stiffness: 100, damping: 15, mass: 1 }}
|
|
224
|
+
/>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Parameter guidance:
|
|
228
|
+
|
|
229
|
+
| Param | Range | Effect |
|
|
230
|
+
|-------|-------|--------|
|
|
231
|
+
| stiffness | 50–300 | higher = snappier arrival |
|
|
232
|
+
| damping | 10–40 | higher = less oscillation |
|
|
233
|
+
| mass | 0.5–2 | higher = more inertia, slower response |
|
|
234
|
+
|
|
235
|
+
Rule of thumb: for UI micro-interactions use stiffness 150–250, damping 20–30, mass 1.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Scroll-Triggered Animations
|
|
240
|
+
|
|
241
|
+
Use IntersectionObserver for scroll-reveal effects — it replaces scroll-event
|
|
242
|
+
listeners with a throttled browser-native API.
|
|
243
|
+
|
|
244
|
+
### Basic pattern
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
const observer = new IntersectionObserver((entries) => {
|
|
248
|
+
entries.forEach(entry => {
|
|
249
|
+
if (entry.isIntersecting) {
|
|
250
|
+
entry.target.classList.add('in-view');
|
|
251
|
+
// Optional: disconnect after first trigger
|
|
252
|
+
// observer.unobserve(entry.target);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}, {
|
|
256
|
+
threshold: 0.1,
|
|
257
|
+
rootMargin: '0px 0px -100px 0px' // trigger 100px before entering viewport bottom
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Threshold guidance
|
|
264
|
+
|
|
265
|
+
| threshold | Meaning |
|
|
266
|
+
|-----------|---------|
|
|
267
|
+
| 0.0 | element enters viewport edge |
|
|
268
|
+
| 0.1–0.25 | element partially visible (most common for reveals) |
|
|
269
|
+
| 0.5 | element half-visible |
|
|
270
|
+
| 1.0 | element fully visible |
|
|
271
|
+
|
|
272
|
+
### Once vs repeat
|
|
273
|
+
|
|
274
|
+
- **Once** — call `observer.unobserve(entry.target)` after first intersection.
|
|
275
|
+
Use for: hero reveals, one-shot entrance animations, stat counters.
|
|
276
|
+
- **Repeat** — leave observer active. Use for: progress indicators, parallax effects,
|
|
277
|
+
sticky nav state changes.
|
|
278
|
+
|
|
279
|
+
### Performance rules
|
|
280
|
+
|
|
281
|
+
1. Animate only `transform` and `opacity` (GPU-accelerated). Avoid `top`, `left`, `width`, `height`.
|
|
282
|
+
2. No debounce/throttle needed — IntersectionObserver is already throttled by the browser.
|
|
283
|
+
3. For many elements, share a single observer instance and call `observe()` once per element.
|
|
284
|
+
4. Prefer CSS transitions triggered by a class toggle over requestAnimationFrame loops.
|
|
285
|
+
5. Use `will-change: transform, opacity` sparingly (only on elements that animate repeatedly).
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Parallelism Rules for get-design-done
|
|
2
|
+
|
|
3
|
+
The decision engine reads these rules at every stage spawn point and writes its verdict to STATE.md `<parallelism_decision>`. Parallelism is computed, not hardcoded.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Hard Rules — Always Serial (override everything)
|
|
8
|
+
|
|
9
|
+
1. **Sequential dependency** — Agent B requires output from Agent A → serial.
|
|
10
|
+
2. **Shared write conflict** — Two agents write to the same file path (intersecting `writes:` fields) → serial.
|
|
11
|
+
3. **Interactive agent** — Agent requires `AskUserQuestion` during execution → serial. Interactive agents cannot be parallelized.
|
|
12
|
+
4. **Single task** — Only 1 candidate in the wave → serial (nothing to parallelize).
|
|
13
|
+
5. **Overlapping Touches** — Two tasks have overlapping `Touches:` fields (same file paths) → serial.
|
|
14
|
+
6. **Schema migrations** — Any agent altering database schema (migrations, `ALTER TABLE`, index changes) → serial within its wave.
|
|
15
|
+
7. **Rate-limited external API** — Agents calling an external API with shared rate limits (same auth token, same quota) → serial.
|
|
16
|
+
|
|
17
|
+
## Soft Rules — Prefer Serial (yield to config overrides)
|
|
18
|
+
|
|
19
|
+
8. **Below savings threshold** — `sum(typical-duration-seconds) - max(typical-duration-seconds) < config.min_estimated_savings_seconds` (default 30s) → prefer serial.
|
|
20
|
+
9. **All candidates fast** — Every candidate has `typical-duration-seconds < 10` → parallel overhead may exceed savings → prefer serial.
|
|
21
|
+
10. **Beyond max_parallel_agents cap** — N candidates > `config.max_parallel_agents` → split into sequential waves of `max_parallel_agents` each.
|
|
22
|
+
11. **Worktree isolation unavailable** — `worktree_isolation: true` in config but git worktrees not available → fall back to serial.
|
|
23
|
+
12. **Below min_tasks_to_parallelize** — Fewer than `config.min_tasks_to_parallelize` (default 2) eligible → serial.
|
|
24
|
+
13. **Large context** — Any candidate's `<required_reading>` total is >100K tokens — risk of context bloat in concurrent dispatch → prefer serial.
|
|
25
|
+
14. **Token-costly agents** — Agents tagged `model: opus` with `typical-duration-seconds > 120s` — prefer serial to avoid bursty spend unless explicitly opted in.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Decision Algorithm
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
FOR each spawn point in a stage orchestrator:
|
|
33
|
+
candidates = tasks_in_current_wave
|
|
34
|
+
|
|
35
|
+
# Hard checks (short-circuit to serial)
|
|
36
|
+
IF len(candidates) < 2 → serial (rule 4)
|
|
37
|
+
IF any candidate is interactive → serial (rule 3)
|
|
38
|
+
FOR each pair (A, B) in candidates:
|
|
39
|
+
IF A.writes ∩ B.writes ≠ ∅ → serial (rule 2)
|
|
40
|
+
IF A.Touches ∩ B.Touches ≠ ∅ AND config.require_disjoint_touches
|
|
41
|
+
→ serial (rule 5)
|
|
42
|
+
IF A.depends_on(B) OR B.depends_on(A) → serial (rule 1)
|
|
43
|
+
IF any candidate mutates schema → serial (rule 6)
|
|
44
|
+
IF rate_limit_sharing(candidates) → serial (rule 7)
|
|
45
|
+
|
|
46
|
+
# Soft checks (config-adjustable)
|
|
47
|
+
IF len(candidates) < config.min_tasks_to_parallelize → serial (rule 12)
|
|
48
|
+
est_savings = sum(typical-duration-seconds) - max(typical-duration-seconds)
|
|
49
|
+
IF est_savings < config.min_estimated_savings_seconds → serial (rule 8)
|
|
50
|
+
IF all(c.typical-duration-seconds < 10 for c in candidates) → serial (rule 9)
|
|
51
|
+
IF worktree_required_but_unavailable() → serial (rule 11)
|
|
52
|
+
IF context_pressure(candidates) > 100K → serial (rule 13)
|
|
53
|
+
|
|
54
|
+
# Cap
|
|
55
|
+
IF len(candidates) > config.max_parallel_agents:
|
|
56
|
+
return split_into_waves(candidates, config.max_parallel_agents)
|
|
57
|
+
|
|
58
|
+
→ verdict: parallel
|
|
59
|
+
|
|
60
|
+
WRITE verdict to STATE.md <parallelism_decision>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## State Output Format
|
|
66
|
+
|
|
67
|
+
```xml
|
|
68
|
+
<parallelism_decision>
|
|
69
|
+
stage: explore
|
|
70
|
+
verdict: parallel
|
|
71
|
+
reason: "5 mappers, all parallel-safe: auto, Touches disjoint, savings est. 165s"
|
|
72
|
+
agents: ["token-mapper", "component-taxonomy-mapper", "visual-hierarchy-mapper", "a11y-mapper", "motion-mapper"]
|
|
73
|
+
ruled_out: []
|
|
74
|
+
timestamp: 2026-04-18T05:00:00Z
|
|
75
|
+
</parallelism_decision>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Serial verdict example
|
|
79
|
+
|
|
80
|
+
```xml
|
|
81
|
+
<parallelism_decision>
|
|
82
|
+
stage: plan
|
|
83
|
+
verdict: serial
|
|
84
|
+
reason: "sequential dependency — design-planner consumes design-phase-researcher output (rule 1)"
|
|
85
|
+
agents: ["design-phase-researcher", "design-pattern-mapper", "design-planner", "design-plan-checker"]
|
|
86
|
+
ruled_out: ["parallel: rule 1"]
|
|
87
|
+
timestamp: 2026-04-18T05:10:00Z
|
|
88
|
+
</parallelism_decision>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Parallel verdict example
|
|
92
|
+
|
|
93
|
+
```xml
|
|
94
|
+
<parallelism_decision>
|
|
95
|
+
stage: verify
|
|
96
|
+
verdict: parallel
|
|
97
|
+
reason: "design-auditor + design-integration-checker — disjoint writes, both parallel-safe: auto, savings est 60s"
|
|
98
|
+
agents: ["design-auditor", "design-integration-checker"]
|
|
99
|
+
ruled_out: []
|
|
100
|
+
timestamp: 2026-04-18T05:20:00Z
|
|
101
|
+
</parallelism_decision>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Why this is a first-class primitive
|
|
107
|
+
|
|
108
|
+
"Why didn't it parallelize?" becomes a one-file STATE.md read — not a guess. Every stage orchestrator computes and writes a verdict before any multi-agent spawn. Operators can audit the decision without rerunning.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Priority Matrix — 10 Categories, CRITICAL → LOW
|
|
2
|
+
|
|
3
|
+
Adapted from `ui-ux-pro-max`. Use this to rank findings when auditing, critiquing, or deciding fix order.
|
|
4
|
+
|
|
5
|
+
| # | Category | Severity | Must-have checks | Anti-patterns (avoid) |
|
|
6
|
+
|---|---|---|---|---|
|
|
7
|
+
| 1 | **Accessibility** | CRITICAL | Contrast 4.5:1 body / 3:1 UI / 7:1 AAA; alt text; keyboard nav; aria-labels; visible focus rings; `prefers-reduced-motion`; no color-only meaning; sequential heading hierarchy | Removed focus rings; icon-only buttons without labels; placeholder as label; red/green only as meaning |
|
|
8
|
+
| 2 | **Touch & Interaction** | CRITICAL | Min 44×44pt iOS / 48×48dp Android; 8px+ spacing between targets; loading feedback on async; error near field; visible press feedback | Hover-only interactions; instant (0ms) state changes; gesture-only critical actions; custom back overriding swipe |
|
|
9
|
+
| 3 | **Performance** | HIGH | WebP/AVIF + `srcset`; lazy loading below fold; reserve space (CLS < 0.1); animate transform/opacity only; `touch-action: manipulation` | Layout thrashing; animating width/height; no reduced-motion respect; heavy blur > 20px in Safari |
|
|
10
|
+
| 4 | **Style Selection** | HIGH | Committed aesthetic direction; consistency across surfaces; SVG icons only; max 2 font families; palette has dominant + accent (not rainbow) | Mixing flat + skeuomorphic; emoji as icons; 3+ font families; every element equally weighted |
|
|
11
|
+
| 5 | **Layout & Responsive** | HIGH | Mobile-first min-width queries; viewport meta; safe-area insets; no horizontal scroll; container queries for components; 3 breakpoints usually enough | Fixed px widths; desktop-first max-width; disable-zoom viewport; ignoring notch / Dynamic Island |
|
|
12
|
+
| 6 | **Typography & Color** | MEDIUM | Base 16px; line-height 1.5 (1.55 for light-on-dark); 65–75ch measure; OKLCH with tinted neutrals; semantic tokens, no raw hex; 5-step scale with 1.25+ ratio | Body < 12px; gray-on-gray; raw hex in components; Inter+purple+gradient default; pure gray neutrals; 8 sizes × 1.1 ratio |
|
|
13
|
+
| 7 | **Animation** | MEDIUM | Duration 100–300ms UI, 300–500ms layout; ease-out for entry, ease-in for exit, exits ~75% of enter; purposeful; `prefers-reduced-motion` | Decorative-only animation; `transition: all`; `ease-in` on UI; `scale(0)` entry; bounce/elastic curves; animating keyboard-initiated actions |
|
|
14
|
+
| 8 | **Forms & Feedback** | MEDIUM | Visible labels above fields; errors below with `aria-describedby`; helper text; validate on blur; progressive disclosure; single column | Placeholder-only label; errors only at top of form; overwhelming all fields upfront; validating every keystroke |
|
|
15
|
+
| 9 | **Navigation Patterns** | HIGH | Predictable back; bottom nav ≤5 items; deep linking; breadcrumbs for deep IA; command palette ⌘K on web/desktop | Overloaded nav; broken back behavior; no deep links; hamburger as primary on desktop; FAB on iOS |
|
|
16
|
+
| 10 | **Charts & Data** | LOW–MED | Legends; tooltips; accessible color palette; right-align numbers; tabular-nums; include axis labels | Color-only meaning; 3D effects; pie charts with > 5 slices; sparkline-as-decoration; missing units |
|
|
17
|
+
|
|
18
|
+
## Severity definitions (P0–P3)
|
|
19
|
+
|
|
20
|
+
- **P0 (block ship)**: Any CRITICAL failure, any legal/compliance issue, broken primary flow
|
|
21
|
+
- **P1 (fix this sprint)**: HIGH severity, broken secondary flow, significant UX confusion
|
|
22
|
+
- **P2 (backlog)**: MEDIUM, polish, non-blocking inconsistencies
|
|
23
|
+
- **P3 (nice-to-have)**: LOW, micro-improvements, aesthetic refinements
|
|
24
|
+
|
|
25
|
+
## How to use this table in audits
|
|
26
|
+
|
|
27
|
+
1. Run the discover stage audit or a manual grep pass using `reference/anti-patterns.md` patterns.
|
|
28
|
+
2. For each finding, assign a category (1–10) from above.
|
|
29
|
+
3. Sort by severity descending.
|
|
30
|
+
4. Fix P0s before shipping — never ship with one open.
|
|
31
|
+
5. Map each P0/P1 to a task type in the Design stage: color findings → `color` task, typography → `typography` task, accessibility → `accessibility` task.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Project-Local Skills Guide
|
|
2
|
+
|
|
3
|
+
Project-local skills live at `./.claude/skills/` within the user's project (not the plugin install). They are auto-loaded by gdd pipeline stages (explore, plan, design) as additional design context.
|
|
4
|
+
|
|
5
|
+
## Auto-loaded patterns
|
|
6
|
+
|
|
7
|
+
Files matching `./.claude/skills/design-*-conventions.md` are read by:
|
|
8
|
+
- `explore` — included in DESIGN-CONTEXT.md synthesis under a `<project_conventions>` section
|
|
9
|
+
- `plan` — passed to design-planner as `<required_reading>`
|
|
10
|
+
- `design` — passed to the executor as `<required_reading>`
|
|
11
|
+
|
|
12
|
+
## File format
|
|
13
|
+
|
|
14
|
+
```markdown
|
|
15
|
+
# Design <Area> Conventions (Project-Local)
|
|
16
|
+
|
|
17
|
+
Auto-loaded in gdd sessions.
|
|
18
|
+
|
|
19
|
+
## Decision from sketch: <slug> (YYYY-MM-DD)
|
|
20
|
+
**Winner**: variant-2
|
|
21
|
+
**Rationale**: ...
|
|
22
|
+
**Token implications**: ...
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Typical areas
|
|
26
|
+
|
|
27
|
+
- `design-typography-conventions.md`
|
|
28
|
+
- `design-color-conventions.md`
|
|
29
|
+
- `design-layout-conventions.md`
|
|
30
|
+
- `design-motion-conventions.md`
|
|
31
|
+
- `design-component-conventions.md`
|
|
32
|
+
- `design-interaction-conventions.md`
|
|
33
|
+
|
|
34
|
+
## Writers
|
|
35
|
+
|
|
36
|
+
- `/gdd:sketch-wrap-up` appends winner rationale to the appropriate file
|
|
37
|
+
- User edits directly
|
|
38
|
+
- `/gdd:spike-wrap-up` may append to the relevant file when adopted
|
|
39
|
+
|
|
40
|
+
## Why this layer?
|
|
41
|
+
|
|
42
|
+
Design decisions accumulate across cycles. Without a project-local layer, `explore` would re-discover the same conventions each cycle and `plan` would lack continuity. This directory persists decisions and feeds them back into the pipeline automatically.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Review Format — The Before/After Table
|
|
2
|
+
|
|
3
|
+
Adopted from `emil-design-eng` and enforced across `get-design-done`. **Every design review uses this format.** No exceptions.
|
|
4
|
+
|
|
5
|
+
## The format
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
| Before | After | Why |
|
|
9
|
+
| --- | --- | --- |
|
|
10
|
+
| `transition: all 300ms` | `transition: transform 200ms ease-out` | Specify exact properties; avoid `all` (repaint cost + unpredictable) |
|
|
11
|
+
| `transform: scale(0)` | `transform: scale(0.95); opacity: 0` | Nothing in the real world appears from nothing |
|
|
12
|
+
| `ease-in` on dropdown | `ease-out` with custom curve | `ease-in` feels sluggish; ease-out gives instant feedback |
|
|
13
|
+
| No `:active` on button | `transform: scale(0.97)` on `:active` | Buttons must feel responsive to press |
|
|
14
|
+
| `transform-origin: center` on popover | `transform-origin: var(--radix-popover-content-transform-origin)` | Popovers scale from their trigger (modals stay centered) |
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**That's the whole format.** Three columns, one row per issue.
|
|
18
|
+
|
|
19
|
+
## Why this format and not prose
|
|
20
|
+
|
|
21
|
+
- **Scannable.** Reviewer can see the whole list at a glance.
|
|
22
|
+
- **Actionable.** Each row is a specific, applyable change.
|
|
23
|
+
- **Non-redundant.** No repeating "Before:" / "After:" labels every time.
|
|
24
|
+
- **The "Why" column is required.** It forces reasoning instead of taste-asserting. Future you also forgets why; the column documents the decision.
|
|
25
|
+
|
|
26
|
+
## Wrong format — never produce this
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Before: transition: all 300ms
|
|
30
|
+
After: transition: transform 200ms ease-out
|
|
31
|
+
|
|
32
|
+
Before: scale(0)
|
|
33
|
+
After: scale(0.95)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This form is verbose, hard to scan, and separates the reasoning from the change. Don't do it.
|
|
37
|
+
|
|
38
|
+
Also wrong:
|
|
39
|
+
- Bullet lists of "change X to Y" without the Why column
|
|
40
|
+
- Narrative paragraphs explaining multiple changes at once
|
|
41
|
+
- Code blocks with full file rewrites instead of focused diffs
|
|
42
|
+
|
|
43
|
+
## When to use this format
|
|
44
|
+
|
|
45
|
+
- **Any review of existing code or design.** `impeccable-audit`, `impeccable-critique`, `design:design-critique`, `design:accessibility-review` — all produce outputs that can be rendered as this table.
|
|
46
|
+
- **Responding to "review this" / "what do you think of this."**
|
|
47
|
+
- **After `Skill(impeccable-polish)` runs** — present the diff as a table.
|
|
48
|
+
- **Documenting design-system migrations** (old token → new token, with why).
|
|
49
|
+
|
|
50
|
+
## When NOT to use this format
|
|
51
|
+
|
|
52
|
+
- **Greenfield design.** No "Before" exists — that's a design proposal, not a review.
|
|
53
|
+
- **Strategic direction critiques.** ("Should we commit to dark mode?") — that's a decision, not a diff.
|
|
54
|
+
- **Presentation to stakeholders.** Use `anthropic-skills:design-storytelling`'s narrative spine instead.
|
|
55
|
+
|
|
56
|
+
## Variations by domain
|
|
57
|
+
|
|
58
|
+
### Typography review
|
|
59
|
+
```
|
|
60
|
+
| Before | After | Why |
|
|
61
|
+
| 3 font families (Inter + Playfair + JetBrains) | 2 (ABC Favorit + JetBrains) | More than 2 families dilutes hierarchy |
|
|
62
|
+
| 8 font sizes at 1.1 ratio | 5 sizes at 1.25 ratio | Fewer sizes, more contrast = clearer hierarchy |
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Color review
|
|
66
|
+
```
|
|
67
|
+
| Before | After | Why |
|
|
68
|
+
| `#888` secondary text on white | oklch(52% 0.01 [hue]) | #888 fails 4.5:1; oklch value passes |
|
|
69
|
+
| Pure black dark-mode bg | oklch(14% 0.01 [brand-hue]) | Pure black is harsh; tinted darkens feels premium |
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Motion review
|
|
73
|
+
```
|
|
74
|
+
| Before | After | Why |
|
|
75
|
+
| Same 300ms for open + close | 300ms open / 225ms close | Exits should be ~75% of enter duration |
|
|
76
|
+
| Sheet animates height | Sheet animates transform: translateY | height animation is main-thread; transform is GPU |
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### UX copy review
|
|
80
|
+
```
|
|
81
|
+
| Before | After | Why |
|
|
82
|
+
| "OK" button | "Save changes" | Verbs describe the outcome; generic OK is lazy |
|
|
83
|
+
| "Error: invalid email" | "Enter a valid email like name@example.com" | Tell user how to fix, not just what's wrong |
|
|
84
|
+
| Empty state: "No items" | "No messages yet. Try [connecting your inbox]." | Empty state = onboarding opportunity |
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Scoring version (when comparing multiple artifacts)
|
|
88
|
+
|
|
89
|
+
When comparing two variations (A vs B) instead of reviewing one, switch to a scored table:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
| Dimension | Variant A | Variant B | Winner | Why |
|
|
93
|
+
| Visual hierarchy | 6/10 | 8/10 | B | B's size contrast more decisive |
|
|
94
|
+
| Touch targets | 7/10 | 5/10 | A | B has 32px buttons fail 44pt |
|
|
95
|
+
| Brand fit | 9/10 | 5/10 | A | A commits to editorial tone; B hedges |
|
|
96
|
+
| Accessibility | 7/10 | 7/10 | tie | Both miss focus rings |
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use the 10 priority-matrix categories (see `priority-matrix.md`) as the dimensions by default.
|
|
100
|
+
|
|
101
|
+
## Output header
|
|
102
|
+
|
|
103
|
+
Always precede the table with one sentence stating the scope:
|
|
104
|
+
|
|
105
|
+
> Reviewed: Settings page modal, `components/Settings.tsx`. 7 changes proposed — 2 P0 accessibility, 3 P1 motion, 2 P2 polish.
|
|
106
|
+
|
|
107
|
+
Then the table. Then nothing. The reader decides whether to apply.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://get-design-done.example/schemas/config.schema.json",
|
|
4
|
+
"title": ".design/config.json",
|
|
5
|
+
"description": "Shape of .design/config.json — model profile and parallelism settings per reference/config-schema.md.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": true,
|
|
8
|
+
"properties": {
|
|
9
|
+
"model_profile": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"enum": ["quality", "balanced", "budget"]
|
|
12
|
+
},
|
|
13
|
+
"parallelism": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"additionalProperties": true,
|
|
16
|
+
"properties": {
|
|
17
|
+
"enabled": { "type": "boolean" },
|
|
18
|
+
"max_parallel_agents": { "type": "integer", "minimum": 1 },
|
|
19
|
+
"min_tasks_to_parallelize": { "type": "integer", "minimum": 1 },
|
|
20
|
+
"min_estimated_savings_seconds": { "type": "integer", "minimum": 0 },
|
|
21
|
+
"require_disjoint_touches": { "type": "boolean" },
|
|
22
|
+
"worktree_isolation": { "type": "boolean" },
|
|
23
|
+
"per_stage_override": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"additionalProperties": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": true,
|
|
28
|
+
"properties": {
|
|
29
|
+
"enabled": { "type": "boolean" },
|
|
30
|
+
"max_parallel_agents": { "type": "integer", "minimum": 1 },
|
|
31
|
+
"min_tasks_to_parallelize": { "type": "integer", "minimum": 1 },
|
|
32
|
+
"min_estimated_savings_seconds": { "type": "integer", "minimum": 0 },
|
|
33
|
+
"require_disjoint_touches": { "type": "boolean" },
|
|
34
|
+
"worktree_isolation": { "type": "boolean" }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://get-design-done.example/schemas/hooks.schema.json",
|
|
4
|
+
"title": "Claude hooks.json",
|
|
5
|
+
"description": "Shape of hooks/hooks.json — event-triggered commands registered by the plugin.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": true,
|
|
8
|
+
"required": ["hooks"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"hooks": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"additionalProperties": true,
|
|
13
|
+
"properties": {
|
|
14
|
+
"SessionStart": {
|
|
15
|
+
"type": "array",
|
|
16
|
+
"items": { "$ref": "#/definitions/hookGroup" }
|
|
17
|
+
},
|
|
18
|
+
"SessionEnd": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"items": { "$ref": "#/definitions/hookGroup" }
|
|
21
|
+
},
|
|
22
|
+
"PreToolUse": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": { "$ref": "#/definitions/hookGroup" }
|
|
25
|
+
},
|
|
26
|
+
"PostToolUse": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"items": { "$ref": "#/definitions/hookGroup" }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"definitions": {
|
|
34
|
+
"hookGroup": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"additionalProperties": true,
|
|
37
|
+
"required": ["hooks"],
|
|
38
|
+
"properties": {
|
|
39
|
+
"matcher": { "type": "string" },
|
|
40
|
+
"hooks": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"items": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"additionalProperties": true,
|
|
45
|
+
"required": ["type", "command"],
|
|
46
|
+
"properties": {
|
|
47
|
+
"type": { "type": "string", "enum": ["command"] },
|
|
48
|
+
"command": { "type": "string", "minLength": 1 }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|