@hegemonart/get-design-done 1.47.0 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: copy-quality
3
+ type: heuristic
4
+ version: 1.0.0
5
+ phase: 48
6
+ tags: [copy, microcopy, ux-writing, ctas, errors, empty-states, aria, alt-text, i18n, voice, pillar-1]
7
+ last_updated: 2026-06-03
8
+ ---
9
+
10
+ # Copy Quality - Microcopy Rubric
11
+
12
+ This file is the rubric the Copy pillar (Pillar 1 of `agents/design-auditor.md`) scores against, and the detailed reference that `agents/copy-auditor.md` applies. The design-auditor's Pillar 1 carries the 1-4 score and a one-line finding; this file holds the per-category criteria, the failure patterns, and the i18n lens that produce that score.
13
+
14
+ Voice and tone are owned by [`brand-voice.md`](./brand-voice.md): the five axes (formal/casual, serious/playful, expert/approachable, reverent/irreverent, authoritative/collaborative), the 12 archetypes, and the tone-by-context table. This file does not restate those. It checks whether the implemented strings honor the voice the product declared, and whether each microcopy surface does its specific job.
15
+
16
+ Cultural and locale meaning is owned by [`rtl-cjk-cultural.md`](./rtl-cjk-cultural.md); engineering primitives for localized strings are owned by [`i18n.md`](./i18n.md). This file consumes the i18n text-expansion table as a copy-length lens (see Internationalization Lens below).
17
+
18
+ ## Why Copy Is a Pillar
19
+
20
+ Generic or default copy is the most common quiet failure in shipped UI. A "Submit" button, a "No data" empty state, and a raw stack-trace error each pass a functional test and each fail the user. Specific, purposeful language is a craft signal: it shows the team pictured a real person reading the screen. The Copy pillar measures that gap between functional text and intentional text.
21
+
22
+ ## Category Rubrics
23
+
24
+ Each category below lists what good looks like and the failure patterns to grep for. A category is "weak" when the failure patterns dominate; "absent" when the surface exists with no considered copy at all.
25
+
26
+ ### Button and CTA labels
27
+
28
+ Good labels are verb-first and name the object: "Export CSV", "Add member", "Send invite", "Delete project". The user reads the label and knows the outcome before clicking. Primary actions carry the specific verb; secondary actions ("Cancel", "Back") may stay plain because they are reversible and conventional.
29
+
30
+ Failure patterns: bare "Submit", "OK", "Go", "Click here", "Button", or a noun with no verb ("Form", "Settings" on an action). A primary action labeled "Save" with no object on a screen that saves several distinct things is weak, not broken.
31
+
32
+ ```bash
33
+ grep -rEn ">(Submit|Click Here|OK|Go|Button|Done)<" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
34
+ ```
35
+
36
+ ### Error messages
37
+
38
+ Good error copy names the cause and the recovery, and never blames the user. State what happened, then what to do: "We could not save your changes. Check your connection and try again." For validation, point at the field and the fix: "Enter a date in the future." The tone matches the stakes (see the tone-by-context table in `brand-voice.md`); data-loss and payment failures are calm and serious, never playful.
39
+
40
+ Failure patterns: raw codes or stack traces shown to users ("Error 500", "undefined is not a function"), blame language ("You entered an invalid value", "Your input was wrong"), and dead ends that state the failure with no next step.
41
+
42
+ ```bash
43
+ grep -rEn "went wrong|Error [0-9]|invalid input|you entered|try again" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
44
+ ```
45
+
46
+ ### Empty states
47
+
48
+ Good empty states orient and offer the first action. They explain why the screen is empty and give one clear thing to do: "No projects yet. Create your first project to get started." A first-run empty state is an onboarding moment, not an error.
49
+
50
+ Failure patterns: "No data", "Nothing here", a bare zero, or an empty container with no copy. An empty state that explains the emptiness but offers no action is weak.
51
+
52
+ ```bash
53
+ grep -rEn "No data|No results|Nothing here|No items|empty" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
54
+ ```
55
+
56
+ ### Loading and skeleton copy
57
+
58
+ Good loading copy reassures and signals progress without nagging: "Getting your data...", "Almost there." Skeleton screens are preferred to spinner-plus-text for content that has a known shape; when text is shown, it is brief and specific to what is loading. Long operations name the step ("Uploading 3 of 12 files").
59
+
60
+ Failure patterns: "Loading..." with no context on a multi-second operation, a spinner with no label on a process that can fail, or jokey loading copy on a high-stakes action.
61
+
62
+ ```bash
63
+ grep -rEn "Loading|Please wait|spinner|Skeleton" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
64
+ ```
65
+
66
+ ### ARIA text quality
67
+
68
+ ARIA strings are copy the screen-reader user hears. They must describe purpose, not implementation. `aria-label="Close dialog"` is good; `aria-label="button"` or `aria-label="icon"` is noise. Live-region announcements (`aria-live`, `role="status"`, `role="alert"`) carry the same cause-plus-recovery standard as visible errors. Labels must not duplicate adjacent visible text in a way that makes the reader say it twice.
69
+
70
+ Failure patterns: `aria-label` set to the element type, `aria-label` that restates a visible label verbatim, missing `aria-label` on icon-only controls, and silent live regions on async state changes.
71
+
72
+ ```bash
73
+ grep -rEn "aria-label=\"(button|icon|link|image|click)\"" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
74
+ ```
75
+
76
+ ### Alt-text quality
77
+
78
+ Good alt text conveys the function or meaning of an image in context. A logo links home: `alt="Acme home"`, not `alt="logo"`. A decorative image takes empty alt (`alt=""`) so the reader skips it. An informative chart names its takeaway, not its file. Alt text never starts with "image of" or "picture of"; the reader already knows it is an image.
79
+
80
+ Failure patterns: `alt="image"`, `alt="photo"`, filename alt (`alt="IMG_2043.jpg"`), missing alt on informative images, and non-empty alt on purely decorative images.
81
+
82
+ ```bash
83
+ grep -rEn "alt=\"(image|photo|picture|img|logo)\"|alt=\"[^\"]*\\.(png|jpg|jpeg|svg|webp)\"" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
84
+ ```
85
+
86
+ ### Form labels, helper, and validation copy
87
+
88
+ Every input has a persistent visible label (placeholders are not labels). Helper text sets expectations before the user types ("Use 8 or more characters"). Validation copy is specific and arrives at the right time: inline after blur for format rules, on submit for cross-field rules. Required and optional states are stated in words, not color alone.
89
+
90
+ Failure patterns: placeholder-as-label, helper text that only appears as an error after failure, generic "This field is required" with no field name when several are blank, and validation copy that says what is wrong but not how to fix it.
91
+
92
+ ```bash
93
+ grep -rEn "placeholder=|required|This field|is invalid" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
94
+ ```
95
+
96
+ ### Voice and tone alignment
97
+
98
+ Read the declared voice from `.design/DESIGN-CONTEXT.md` (axis positions and archetype, if recorded) and check the implemented strings against it. A Caregiver health app with a curt, blaming error message is off-voice even if the error is technically clear. A formal finance app with "Oops!" on a failed transfer is off-voice. Use the tone-by-context table in `brand-voice.md` as the per-surface contract: error, empty state, success, onboarding, loading, destructive confirmation each have a recommended register.
99
+
100
+ Failure patterns: one tone for marketing copy and a flatly different tone for in-product copy, playful language on high-stakes actions, and copy that contradicts the declared archetype.
101
+
102
+ ## Internationalization Lens
103
+
104
+ Apply this lens to copy-heavy components (anything where text drives width: buttons, nav, tabs, chips, table headers, banners). It folds the [`i18n.md`](./i18n.md) text-expansion table into the copy score.
105
+
106
+ Two probes:
107
+
108
+ 1. **Hardcoded user-facing strings.** Strings rendered to users should flow through the project's i18n layer, not sit as literals in JSX. A literal English string in a component is a copy defect for any product that ships, or plans to ship, more than one locale.
109
+
110
+ ```bash
111
+ grep -rEn ">[A-Z][a-z]+ [a-z]+.*<|aria-label=\"[A-Z][a-z]+ " src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
112
+ ```
113
+
114
+ 2. **Expansion-overflow at +40%.** German expands English by about +30%, Russian by about +40% (see the expansion table in `i18n.md`). A fixed-width control sized to English is the worst case. The lens: for each copy-bearing component with a width constraint, ask whether the label survives a +40% expansion without clipping or truncating mid-word. Containers sized to `EN base x 1.4` clear the worst row of that table. Flag fixed pixel widths on text controls and single-line labels with no wrap or ellipsis strategy.
115
+
116
+ ```bash
117
+ grep -rEn "w-\[[0-9]+px\]|width:\s*[0-9]+px|truncate|whitespace-nowrap" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
118
+ ```
119
+
120
+ A copy-heavy component that hardcodes strings, or that clips at +40%, drops the Copy pillar by one point and appears in the findings with the `i18n_readiness` lens tag (see `audit-scoring.md` Lens-Tags).
121
+
122
+ ## Scoring Guide (Copy Pillar, 1-4)
123
+
124
+ This scale matches the 1-4 definitions in `agents/design-auditor.md`. The Copy pillar score is a single 1-4 value; the categories above supply the evidence.
125
+
126
+ | Score | Label | Criteria |
127
+ |-------|-------|----------|
128
+ | 4 | Exemplary | CTAs are verb-object specific; error messages name cause and recovery without blame; empty states orient and offer a first action; ARIA and alt text describe purpose; form copy guides before and during input; voice matches the declared axes and archetype; copy-heavy components survive a +40% expansion and route strings through i18n. |
129
+ | 3 | Solid | Most copy is intentional; one or two generic labels remain (a plain "Save" on a single-purpose form); error and empty states are present and human but plain; minor voice drift only. |
130
+ | 2 | Present but weak | Mix of intentional and generic copy; some empty states missing; errors show raw codes or blame; ARIA or alt text restates element type; hardcoded strings or +40% overflow risk in copy-heavy components. |
131
+ | 1 | Absent or broken | Majority generic ("Submit", "OK", "Cancel"); empty states absent or "No data"; errors are developer-facing; ARIA labels are noise; alt text is "image" or filenames; no voice considered. |
132
+
133
+ ## How findings feed the audit
134
+
135
+ `agents/copy-auditor.md` runs these probes, scores the pillar, and writes `.design/COPY-AUDIT.md` as a supplement. `agents/design-auditor.md` folds that score and the top finding into Pillar 1 of `.design/DESIGN-AUDIT.md`. Neither file changes the separate 7-category 0-10 system in `audit-scoring.md`; the Copy pillar is a qualitative 1-4 signal, not a weighted metric.
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: debt-categories
3
+ type: reference
4
+ version: 1.0.0
5
+ phase: 48
6
+ tags: [debt, taxonomy, audit, crawler, priority-scoring, retroactive]
7
+ last_updated: 2026-06-03
8
+ ---
9
+
10
+ # Debt Categories
11
+
12
+ The taxonomy `agents/design-debt-crawler.md` uses to classify and rank design debt
13
+ found across an entire codebase. Each class has a definition, the detection signal
14
+ that surfaces it, and the typical fix shape. The priority model at the end converts
15
+ every finding into one comparable score so the catalog reads top to bottom by impact.
16
+
17
+ This taxonomy is detection-oriented, not a style guide. The reason behind each rule
18
+ lives in `reference/anti-patterns.md` (the BAN-NN and SLOP-NN catalog) and the domain
19
+ references `reference/color.md`, `reference/typography.md`, and `reference/spatial.md`.
20
+ This file is the catalog of what to look for and how to weigh it.
21
+
22
+ ---
23
+
24
+ ## Debt Classes
25
+
26
+ ### color-literal
27
+
28
+ **Definition:** A raw color value written directly in source instead of a token
29
+ reference. Includes `#rgb` / `#rrggbb` / `#rrggbbaa` hex, `rgb()` / `rgba()`, and
30
+ `hsl()` / `hsla()` function literals that flow to a rendered surface.
31
+ **Detection signal:** Grep for `#[0-9a-fA-F]{3,8}`, `rgb\(`, `rgba\(`, `hsl\(`,
32
+ `hsla\(` in source files. Exclude token-definition files (the palette source itself)
33
+ and comments. A literal inside a `var(--token: #hex)` definition is the token, not debt.
34
+ **Fix shape:** Replace the literal with the matching semantic token. If no token
35
+ exists for that role, the fix is to define one first.
36
+
37
+ ### untokenized-component
38
+
39
+ **Definition:** A component file that renders visual surface (color, spacing, type
40
+ size) using inline values or arbitrary utility classes rather than referencing the
41
+ design system's tokens or scale.
42
+ **Detection signal:** A component file (`.tsx` / `.jsx` / `.vue` / `.svelte`) that
43
+ contains color-literal or arbitrary-bracket utility hits (`\[[0-9]+px\]`,
44
+ `\[#[0-9a-f]+\]`) and zero `var(--` references or scale-class references. The ratio
45
+ of literal uses to token uses inside one file is the strength signal.
46
+ **Fix shape:** Route the component's visual values through tokens and the spacing
47
+ or type scale; remove the arbitrary brackets.
48
+
49
+ ### anti-pattern
50
+
51
+ **Definition:** A confirmed instance of a banned construct (BAN-NN) or an AI-slop
52
+ tell (SLOP-NN) from `reference/anti-patterns.md`.
53
+ **Detection signal:** Run `gdd-detect <path> --json`. Each finding carries its
54
+ `ruleId`, `file`, `line`, and a link back to the matching paragraph. The detector
55
+ covers the statically matchable BAN rules; the two subjective rules it cannot match
56
+ (BAN-04 keyboard-action animation, BAN-10 nested equal radius) are noted as a
57
+ manual-review item, not auto-counted.
58
+ **Fix shape:** Apply the rule's documented rewrite. Hard bans take precedence over
59
+ SLOP tells when both touch the same element.
60
+
61
+ ### contrast
62
+
63
+ **Definition:** A foreground and background pairing that falls below the WCAG 2.1 AA
64
+ contrast floor (4.5:1 for body text, 3:1 for large text and non-text indicators).
65
+ **Detection signal:** Resolve text-color and background-color pairs that share an
66
+ element or selector, compute the ratio, and flag pairs under the threshold. Pairs
67
+ built from unresolvable runtime values are a manual-review item.
68
+ **Fix shape:** Adjust the token or the role assignment so the pair clears AA. Never
69
+ rely on color alone to carry meaning; pair it with text or an icon.
70
+
71
+ ### density-spacing
72
+
73
+ **Definition:** Spacing values that sit off the project's modular scale (for example
74
+ the 4 / 8 / 12 / 16 / 24 / 32 series), or inconsistent density between sibling
75
+ components that should share rhythm.
76
+
77
+ **Detection signal:** Collect every padding, margin, and gap value, then flag values
78
+ that are not on the declared scale and clusters where neighboring components use
79
+ different step counts for the same structural role.
80
+
81
+ **Fix shape:** Snap off-grid values to the nearest scale step; align sibling density.
82
+
83
+ ### typography-drift
84
+
85
+ **Definition:** Font sizes, weights, or families that drift from a systematic type
86
+ scale: arbitrary pixel sizes, more than the agreed family count, or weight choices
87
+ that break the heading-to-body hierarchy.
88
+
89
+ **Detection signal:** Tally the distinct font-size and font-weight values and the
90
+ family count. A long tail of one-off sizes, more than two families, or `font-weight`
91
+ under 400 on small text are the drift markers.
92
+
93
+ **Fix shape:** Map each one-off value onto the nearest scale step; cap families at two.
94
+
95
+ ### a11y-text
96
+
97
+ **Definition:** Text-content accessibility debt: missing `alt` on meaningful images,
98
+ icon-only controls without an accessible name, placeholder used as the only label,
99
+ and generic or developer-facing copy in empty and error states.
100
+
101
+ **Detection signal:** Grep for `<img` without `alt`, interactive elements without
102
+ `aria-label` or visible text, inputs with `placeholder` and no `<label>`, and
103
+ empty-state strings such as "No data" or raw error codes.
104
+
105
+ **Fix shape:** Add the accessible name or label; rewrite generic copy to be specific
106
+ and actionable. Copy-quality detail lives in `reference/copy-quality.md`.
107
+
108
+ ---
109
+
110
+ ## Priority Scoring Model
111
+
112
+ Every finding gets one priority score so the catalog ranks by impact, not by the
113
+ order files were walked. Three ordinal factors combine, each on a 1 to 3 scale.
114
+
115
+ **Visible-delta** (how much a user notices the fix):
116
+
117
+ | Value | Meaning |
118
+ |-------|---------|
119
+ | 3 | Changes a primary surface a user sees on first load |
120
+ | 2 | Changes a secondary or interior surface |
121
+ | 1 | Invisible at rest; shows only in an edge state or to assistive tech |
122
+
123
+ **Effort** (how cheap the fix is; cheaper scores higher so quick wins float up):
124
+
125
+ | Value | Meaning |
126
+ |-------|---------|
127
+ | 3 | Mechanical one-line swap (literal to token) |
128
+ | 2 | Localized edit across a single component |
129
+ | 1 | Needs a new token, scale decision, or cross-file refactor |
130
+
131
+ **Prevalence** (how many instances share this root cause):
132
+
133
+ | Value | Meaning |
134
+ |-------|---------|
135
+ | 3 | Ten or more instances of the same finding |
136
+ | 2 | Three to nine instances |
137
+ | 1 | One or two instances |
138
+
139
+ **Combine** by multiplying the three factors:
140
+
141
+ ```
142
+ priority = visible-delta × effort × prevalence
143
+ ```
144
+
145
+ The product ranges from 1 (low) to 27 (high). Sort the catalog by `priority`
146
+ descending so the highest-impact, lowest-cost, most-widespread debt sits at the top.
147
+ On ties, break by visible-delta first, then prevalence. Record the three factors next
148
+ to the score in each catalog row so the ranking is auditable, not opaque.
@@ -1100,6 +1100,27 @@
1100
1100
  "type": "domain-index",
1101
1101
  "phase": 45,
1102
1102
  "description": "Phase 45 domain-index: UX-writing + voice - brand-voice, style-vocabulary, anti-patterns."
1103
+ },
1104
+ {
1105
+ "name": "copy-quality",
1106
+ "path": "reference/copy-quality.md",
1107
+ "type": "heuristic",
1108
+ "phase": 48,
1109
+ "description": "Phase 48 copy-quality pillar rubric: microcopy (button/CTA labels, error messages, empty states, ARIA/alt text, loading copy), voice alignment, i18n overflow lens."
1110
+ },
1111
+ {
1112
+ "name": "debt-categories",
1113
+ "path": "reference/debt-categories.md",
1114
+ "type": "taxonomy",
1115
+ "phase": 48,
1116
+ "description": "Phase 48 design-debt taxonomy: debt classes (color-literal, untokenized-component, anti-pattern, contrast, density-spacing, typography-drift, a11y-text) + visible-delta x effort x prevalence priority scoring."
1117
+ },
1118
+ {
1119
+ "name": "brief-quality-rubric",
1120
+ "path": "reference/brief-quality-rubric.md",
1121
+ "type": "output-contract",
1122
+ "phase": 48,
1123
+ "description": "Phase 48 brief-quality rubric: 5 anti-patterns (vague verbs, missing audience, immeasurable success criteria, scope creep, missing anti-goals) the brief-auditor surfaces."
1103
1124
  }
1104
1125
  ]
1105
1126
  }
@@ -108,6 +108,23 @@ Run this final spec-quality pass over `.design/BRIEF.md` before the brief→expl
108
108
  - Scope check: nothing in the artifact exceeds (or silently drops) the agreed scope.
109
109
  - Ambiguity check: every requirement/decision is specific enough to act on without a follow-up question.
110
110
 
111
+ ## Optional brief audit (non-blocking)
112
+
113
+ Before the gate, you MAY spawn `agents/brief-auditor.md` via `Task` to grade the brief against the five
114
+ brief anti-patterns (vague verbs, missing audience, immeasurable success criteria, scope creep, missing
115
+ anti-goals). The auditor reads `.design/BRIEF.md` plus `reference/brief-quality-rubric.md` and writes
116
+ advisory findings to `.design/BRIEF-AUDIT.md`. This step is advisory and MUST NOT block the brief to
117
+ explore transition.
118
+
119
+ If the auditor reports one or more fired anti-patterns, surface a single-line pointer to the user:
120
+
121
+ ```
122
+ Brief audit flagged N issue(s) - run /gdd:discuss brief to refine, or proceed to explore.
123
+ ```
124
+
125
+ The user decides. Proceeding to explore with a flagged brief is allowed; the pointer is a nudge, not a gate.
126
+ If the auditor reports no fired anti-patterns, or you skip the audit, continue to the gate unchanged.
127
+
111
128
  <HARD-GATE>
112
129
  Do NOT transition to explore (or invoke `/gdd:explore`) until the brief artifact (default `.design/BRIEF.md`) is committed AND the user has approved it. If this project uses a custom `.design` location, read the artifact path from `.design/STATE.md` rather than assuming the default.
113
130
  </HARD-GATE>
@@ -39,7 +39,7 @@ Read once at start from `.design/config.json` (all optional; defaults in parens)
39
39
  Stop at the first tier that produces ≥ 1 command:
40
40
 
41
41
  1. **Authoritative config.** If `.design/config.json` has `quality_gate.commands` non-empty, use verbatim.
42
- 2. **Auto-detect from `package.json#scripts`** - match against allowlist: `lint`, `typecheck`, `tsc` (only if `typecheck` absent), `test`, `chromatic`, `test:visual`, `lint:design` (Phase 41 - the `gdd-detect` deterministic anti-pattern gate, alongside `axe`/`pa11y`/`lighthouse`). Exclude by name: `test:e2e`, `test:integration` (if separate `test`), anything starting `dev:`, `build:`, `start:`. Run via `npm run <name>` unless `quality_gate.package_manager` overrides.
42
+ 2. **Auto-detect from `package.json#scripts`** - match against allowlist: `lint`, `typecheck`, `tsc` (only if `typecheck` absent), `test`, `chromatic`, `test:visual`, `lint:design` (Phase 41 - the `gdd-detect` deterministic anti-pattern gate), and the accessibility scripts `axe`, `pa11y`, `lighthouse`, `eslint-plugin-jsx-a11y` (or a script named `jsx-a11y`) which classify into the `a11y` bucket. Exclude by name: `test:e2e`, `test:integration` (if separate `test`), anything starting `dev:`, `build:`, `start:`. Run via `npm run <name>` unless `quality_gate.package_manager` overrides.
43
43
  3. **Skip with notice.** Emit `quality_gate_skipped` (Step 6) and write a `<run/>` with `status="skipped"`. Verify treats skipped as non-blocking.
44
44
 
45
45
  ## Step 2 - Parallel run
@@ -48,7 +48,7 @@ Emit `quality_gate_started`. Spawn each command in a separate `Bash`; collect `{
48
48
 
49
49
  ## Step 3 - Classification
50
50
 
51
- Spawn `quality-gate-runner` agent via `Task` with payload `{outputs: [{command, exit_code, stderr}, ...]}`. Agent returns `{status: "pass"|"fail", classified_failures: {lint, type, test, visual}}`. `pass` → Step 5. `fail` → Step 4.
51
+ Spawn `quality-gate-runner` agent via `Task` with payload `{outputs: [{command, exit_code, stderr}, ...]}`. Agent returns `{status: "pass"|"fail", classified_failures: {lint, type, test, visual, a11y}}`. The `a11y` bucket groups accessibility failures from axe / pa11y / lighthouse / jsx-a11y. `pass` → Step 5. `fail` → Step 4.
52
52
 
53
53
  ## Step 4 - Fix loop (D-08)
54
54