@hegemonart/get-design-done 1.40.0 → 1.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +78 -0
  4. package/README.md +8 -0
  5. package/SKILL.md +1 -0
  6. package/agents/README.md +1 -0
  7. package/agents/design-auditor.md +5 -6
  8. package/bin/gdd-detect +20 -0
  9. package/package.json +4 -1
  10. package/reference/anti-patterns.md +26 -0
  11. package/reference/cli-localization.md +61 -0
  12. package/reference/config-schema.md +8 -0
  13. package/reference/registry.json +7 -0
  14. package/reference/schemas/config.schema.json +5 -0
  15. package/reference/schemas/generated.d.ts +4 -0
  16. package/scripts/lib/detect/cli.cjs +111 -0
  17. package/scripts/lib/detect/engine.cjs +83 -0
  18. package/scripts/lib/detect/rule-schema.json +31 -0
  19. package/scripts/lib/detect/rules/ban-01.cjs +33 -0
  20. package/scripts/lib/detect/rules/ban-02.cjs +33 -0
  21. package/scripts/lib/detect/rules/ban-03.cjs +33 -0
  22. package/scripts/lib/detect/rules/ban-05.cjs +33 -0
  23. package/scripts/lib/detect/rules/ban-06.cjs +33 -0
  24. package/scripts/lib/detect/rules/ban-07.cjs +33 -0
  25. package/scripts/lib/detect/rules/ban-08.cjs +33 -0
  26. package/scripts/lib/detect/rules/ban-09.cjs +33 -0
  27. package/scripts/lib/detect/rules/ban-11.cjs +33 -0
  28. package/scripts/lib/detect/rules/ban-12.cjs +33 -0
  29. package/scripts/lib/detect/rules/ban-13.cjs +33 -0
  30. package/scripts/lib/detect/rules/index.cjs +21 -0
  31. package/scripts/lib/i18n/index.cjs +95 -0
  32. package/scripts/lib/i18n/messages/de.json +7 -0
  33. package/scripts/lib/i18n/messages/en.json +27 -0
  34. package/scripts/lib/i18n/messages/fr.json +7 -0
  35. package/scripts/lib/i18n/messages/ja.json +7 -0
  36. package/scripts/lib/i18n/messages/ru.json +27 -0
  37. package/scripts/lib/i18n/messages/uk.json +7 -0
  38. package/scripts/lib/i18n/messages/zh.json +7 -0
  39. package/skills/locale/SKILL.md +51 -0
  40. package/skills/quality-gate/SKILL.md +1 -1
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Get Design Done — 5-stage agent-orchestrated design pipeline with 9 connections, handoff-first workflow, bidirectional Figma write-back, 22+ specialized agents, queryable knowledge layer (intel store, dependency analysis, learnings extraction), and a self-improvement loop (reflector, frontmatter + budget feedback, global-skills layer). v1.20.0 ships the SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream, and resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) for rate-limit + 429 + context-overflow recovery. Full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation (auto-tag + GitHub Release + release-time smoke test).",
8
- "version": "1.40.0"
8
+ "version": "1.41.0"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "get-design-done",
13
13
  "source": "./",
14
14
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), Claude Design handoff, bidirectional Figma write-back, and a queryable intel store (.design/intel/) for dependency and learnings queries. Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation. Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain.",
15
- "version": "1.40.0",
15
+ "version": "1.41.0",
16
16
  "author": {
17
17
  "name": "hegemonart"
18
18
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "get-design-done",
3
3
  "short_name": "gdd",
4
- "version": "1.40.0",
4
+ "version": "1.41.0",
5
5
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), handoff-first workflow via Claude Design bundles, bidirectional Figma write-back (annotations, Code Connect), queryable intel store (`.design/intel/`) for O(1) design surface lookups, and self-improvement loop (reflector agent, frontmatter + budget feedback, global-skills layer at `~/.claude/gdd/global-skills/`). Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings, reflect, apply-reflections. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows, lint + schema + frontmatter + stale-ref + shellcheck + gitleaks + injection-scan + blocking size-budget) and release automation (auto-tag + GitHub Release + release-time smoke test). Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain. v1.27.7 ships gdd-mcp (Phase 27.7): 12 read-only MCP tools for sub-3s priming. v1.28.0 (Phase 28): Foundational References Tier 2 — 5 new reference files (color-theory, composition, proportion-systems, i18n, contrast-advanced), 2 verifier i18n probes + 1 explore i18n-readiness probe, 12 additive cross-link insertions across 10 existing references, 2 orthogonal audit-scoring lens-tags (composition_alignment + i18n_readiness).",
6
6
  "author": {
7
7
  "name": "hegemonart",
package/CHANGELOG.md CHANGED
@@ -4,6 +4,84 @@ All notable changes to get-design-done are documented here. Versions follow [sem
4
4
 
5
5
  ---
6
6
 
7
+ ## [1.41.0] - 2026-06-02
8
+
9
+ ### Phase 41 — Deterministic Anti-Pattern CLI (`gdd-detect`)
10
+
11
+ GDD's BAN-NN anti-pattern catalogue was consumable only by spawning a Claude session through
12
+ `design-auditor` — no fast CI gate, no pre-commit hook, no zero-LLM regression check. 41 ships
13
+ **`gdd-detect`**: a **dep-free, offline** Node CLI that scans HTML/CSS/JSX for the 11 statically-
14
+ detectable BAN rules and emits JSON or human findings, each linked to its catalogue paragraph.
15
+ (Inspired by `pbakaus/impeccable`.) **No new runtime dependency, no new egress.**
16
+
17
+ ### Breaking changes
18
+
19
+ **None.** `gdd-detect` is purely additive — a new `bin` entry + a new `lint:design` script + new
20
+ `scripts/lib/detect/` modules. Nothing existing changes behavior; `design-auditor` swaps its inline
21
+ BAN greps for a `gdd-detect --json` call (same findings, deterministic). Upgrading from v1.40.5 is a no-op for existing workflows.
22
+
23
+ ### Added
24
+
25
+ - **`bin/gdd-detect`** (`gdd-detect <path> [--json] [--fast] [--rule BAN-NN] [--puppeteer]`) — exit
26
+ `0` clean / `2` findings / `1` invocation error. Recursive scan of HTML/CSS/JSX/TSX.
27
+ - **`scripts/lib/detect/`** — a pure, dep-free engine + `rule-schema.json` + 11 per-rule matchers
28
+ (`rules/ban-NN.cjs`) ported verbatim from the catalogue's own `**Grep**` patterns
29
+ (BAN-01/02/03/05/06/07/08/09/11/12/13). BAN-04 + BAN-10 are subjective (matcher-exempt).
30
+ - **`scripts/sync-rule-catalogue.cjs`** — bidirectional parity gate: every rule ↔ a `### BAN-NN:`
31
+ heading + a `bdId: BAN-NN` marker; no orphans; no un-ported detectable rule.
32
+ - **`scripts/hooks/pre-commit-detect.sh`** — opt-in pre-commit scaffold.
33
+ - **`lint:design`** npm script + `sync:rule-catalogue` npm script.
34
+
35
+ ### Changed
36
+
37
+ - **`reference/anti-patterns.md`** — `bdId: BAN-NN` markers under every BAN heading.
38
+ - **`agents/design-auditor.md`** — Pillar-7 inline BAN greps replaced by one `gdd-detect --json` call.
39
+ - **`skills/quality-gate/SKILL.md`** — `lint:design` added to the Phase-25 auto-detect linter allowlist.
40
+
41
+ ### Notes
42
+
43
+ - **Two execution paths**: regex-fast (the dep-free default) and DOM-aware (`jsdom`, a soft
44
+ `try-require` optional — **not** a `package.json` dependency); `--fast` forces regex; absent jsdom
45
+ falls back with a one-line warning. A `http(s)://` path needs `--puppeteer` (also soft-optional) and
46
+ prints a clear install message otherwise — never a stack trace. The CLI is **offline by default** (a
47
+ static network-isolation test fails the build on any network primitive in the detect tree).
48
+ - 6-manifest lockstep at **v1.41.0** + `OFF_CADENCE_VERSIONS.add('1.41.0')` (minor) + the 35 live-pinned
49
+ `manifests-version.txt` baselines forward-propagated 1.40.5 → 1.41.0.
50
+ - Inventory: tarball golden 731 → 747 (+16: `bin/gdd-detect` + `scripts/lib/detect/**`). No
51
+ skill/agent/registry deltas (`sync-rule-catalogue.cjs` + the pre-commit scaffold are maintainer-only).
52
+
53
+ ---
54
+
55
+ ## [1.40.5] - 2026-06-01
56
+
57
+ ### Phase 40.5 — GDD CLI Localization
58
+
59
+ GDD's README is multilingual, but the CLI talked English. 40.5 adds locale resolution + per-locale
60
+ message tables for the highest-traffic surface — `--help`, common error messages, and skill prompt
61
+ headers. English is always the final fallback, so a partial locale never breaks the CLI. **No new
62
+ runtime dependency, no new egress.**
63
+
64
+ ### Added
65
+
66
+ - **`scripts/lib/i18n/index.cjs`** — locale resolver: `resolveLocale` (`config.locale` > env `LANG`/`LC_ALL` > `en`), `fallbackChain` (`locale → base → en`), `translate` (chain walk; a missing key returns the key, never throws), `descriptionFor` (`description_i18n` || English). Pure functions + a thin `loadTable` reader.
67
+ - **`scripts/lib/i18n/messages/{en,ru,uk,de,fr,zh,ja}.json`** — flat message tables. `en` is the complete source (24 keys: `help.*`/`error.*`/`prompt.*`/`status.*`), `ru` a full translation, `uk`/`de`/`fr`/`zh`/`ja` placeholders (a `_meta` marker + a starter subset) that fall back to English.
68
+ - **`skills/locale/SKILL.md`** (`/gdd:locale [<code>]`) — inspect the resolved locale + per-locale coverage, or set `.design/config.json#locale`.
69
+ - **`reference/cli-localization.md`** — the resolver contract + the add-a-locale contribution path (translate the table, add a `NOTICE` translator credit, open a PR; warn-only completeness). Registered. Distinct from `reference/i18n.md` (which covers *user-design* i18n).
70
+
71
+ ### Changed
72
+
73
+ - **`reference/schemas/config.schema.json`** — + `locale` (enum en/ru/uk/de/fr/zh/ja); `generated.d.ts` regenerated.
74
+ - **`agents/README.md`** — document the opt-in `description_i18n` frontmatter field (falls back to the English `description`; backward-compatible — the 28.5 contract validates it only when present).
75
+
76
+ ### Notes
77
+
78
+ - **No new runtime dependency, no new egress.** Pure resolver + JSON tables + docs.
79
+ - The completeness gate is **warn-only** — only `en` + `ru` are full; the five placeholder locales rely on the English fallback and are never required to be 100%.
80
+ - 6-manifest lockstep at **v1.40.5** + `OFF_CADENCE_VERSIONS.add('1.40.5')` + the 34 live-pinned `manifests-version.txt` baselines forward-propagated 1.40.0 → 1.40.5.
81
+ - Inventory relock: registry-diff 159 → 160 (+`cli-localization`), skill-list 82 → 83 (+`locale`), skill-length-distribution relocked, tarball golden 721 → 731 (+10). No agent/event deltas. Root `SKILL.md` command table += `locale`.
82
+
83
+ ---
84
+
7
85
  ## [1.40.0] - 2026-06-01
8
86
 
9
87
  ### Phase 40 — Team Collaboration Mode
package/README.md CHANGED
@@ -194,6 +194,14 @@ GDD migrates *your* design systems (above) — now it migrates **itself**. When
194
194
 
195
195
  GDD's single-operator baseline now extends to **teams** — git-native + advisory, no server. Two developers working a cycle on parallel branches merge their `.design/STATE.md` **per section** ([`section-merge`](scripts/lib/collab/section-merge.cjs) unions decisions by `D-id`; a real conflict is only a same-id divergence, which [`conflict-resolver`](agents/conflict-resolver.md) reconciles with human confirmation — never auto-picking or dropping a decision). Decisions carry optional `[author= co-author=]` attribution, move through an async review queue (`proposed → reviewing → approved → locked`) with **hard locks** (the only escape is an audited [`/gdd:unlock-decision`](skills/unlock-decision/SKILL.md)), and [`/gdd:review-decisions`](skills/review-decisions/SKILL.md) surfaces what's pending. [`decision-journal-exporter`](agents/decision-journal-exporter.md) publishes a **pseudonymized, read-only** Notion/Confluence journal for stakeholders who don't run GDD. `gdd_cycle_mode` (designer/dev/full) partitions a cycle by role, a `permissions` model gates per-section writes, and `collab.multi_writer_enabled` switches the advisory lock to a team-mode backoff. The full contract: [`reference/multi-author-model.md`](reference/multi-author-model.md). **Everything is off by default** — a single-operator project is unaffected. **No new runtime dependency.**
196
196
 
197
+ ### CLI localization (v1.40.5)
198
+
199
+ GDD's README is multilingual — now its **CLI** is too. [`/gdd:locale <code>`](skills/locale/SKILL.md) sets the language of `--help`, common error messages, and skill prompt headers, resolved by [`scripts/lib/i18n`](scripts/lib/i18n/index.cjs) (precedence: `config.locale` > env `LANG` > `en`; fallback chain `locale → base → en`). Flat-JSON message tables ship for **en** (complete source), **ru** (full), and **uk/de/fr/zh/ja** placeholders — a missing key always falls back to English, so a partial locale never breaks the CLI. Skills + agents can carry an opt-in `description_i18n` map. Adding a locale is a PR: translate the table, add a `NOTICE` credit (the contribution path is in [`reference/cli-localization.md`](reference/cli-localization.md)). Completeness is **warn-only**. **No new runtime dependency.**
200
+
201
+ ### Deterministic anti-pattern CLI — `gdd-detect` (v1.41.0)
202
+
203
+ GDD's BAN-NN anti-pattern catalogue is now executable. [`gdd-detect`](bin/gdd-detect) is a **dep-free, offline** Node CLI that scans HTML/CSS/JSX for the 11 statically-detectable BAN rules ([`scripts/lib/detect/rules/`](scripts/lib/detect/)) — `transition: all`, `will-change: all`, gradient text, bounce easing, `scale(0)` entry, naked `outline: none`, pure-black dark mode, disabled zoom, tinted image outline — each finding linked to its [`reference/anti-patterns.md`](reference/anti-patterns.md) paragraph. `gdd-detect <path> [--json] [--fast] [--rule BAN-NN]` exits `0` clean / `2` findings / `1` error. The rule files are the canonical executable; the markdown stays canonical prose; [`sync-rule-catalogue`](scripts/sync-rule-catalogue.cjs) keeps them in parity. `npm run lint:design` is the CI gate; an opt-in pre-commit scaffold ships too. `design-auditor` and the Phase-25 quality-gate consume it; `jsdom`/`puppeteer` are soft-optional (regex-fast is the default). **No new runtime dependency.**
204
+
197
205
  ### Previous releases
198
206
 
199
207
  - **v1.26.0** — Headless Model Resolver (per-runtime tier→model map, `resolved_models` router field, per-runtime price tables, `reasoning-class` runtime-neutral alias).
package/SKILL.md CHANGED
@@ -107,6 +107,7 @@ Each stage produces artifacts in `.design/` inside the current project.
107
107
  | `migrate [--yes] [--dry-run]` | `get-design-done:gdd-migrate` | Phase 39.5 — migrate a project off GDD's own deprecated paths after an upgrade; reads `reference/DEPRECATIONS.md` via `deprecation-registry.cjs`, previews a diff, applies on confirm. Preview-first; never edits silently |
108
108
  | `review-decisions [<id>] [--pending]` | `get-design-done:gdd-review-decisions` | Phase 40 — surface the async decision-review queue (`proposed → reviewing → approved → locked`); `--pending` shows decisions still awaiting action. Read-only |
109
109
  | `unlock-decision <id> --approver <who> [--reason <text>] [--dry-run]` | `get-design-done:gdd-unlock-decision` | Phase 40 — reopen a LOCKED decision (the only escape hatch); requires an approver + writes an audit entry; previews before writing |
110
+ | `locale [<code>]` | `get-design-done:gdd-locale` | Phase 40.5 — inspect or set the GDD CLI locale (en/ru/uk/de/fr/zh/ja) for `--help`, errors, and skill prompt headers; missing keys fall back to English. No arg reports the resolved locale + coverage |
110
111
 
111
112
  ## Handoff Routing
112
113
 
package/agents/README.md CHANGED
@@ -39,6 +39,7 @@ Every agent file begins with a YAML frontmatter block. All fields except `model`
39
39
  |-------|------|-----------------|---------|
40
40
  | `name` | kebab-case string | unique within plugin | Identifier passed to the `Task` tool — must match the filename without `.md` |
41
41
  | `description` | string | free-form | One sentence: what the agent does + when it is spawned |
42
+ | `description_i18n` | object | `{ <locale>: "<description>" }` | **Phase 40.5, opt-in.** Localized descriptions keyed by locale (en/ru/uk/de/fr/zh/ja). `scripts/lib/i18n/index.cjs` `descriptionFor(frontmatter, locale)` resolves it via the fallback chain and falls back to the English `description` when a locale is absent. Backward-compatible — omit it and nothing changes. |
42
43
  | `tools` | comma-separated list | `Read`, `Write`, `Edit`, `Bash`, `Grep`, `Glob`, `Task`, `WebFetch`, `TodoWrite`, `mcp__*` | Claude tools the agent may use — list only what is needed |
43
44
  | `color` | enum | `yellow`, `green`, `blue`, `red` | Terminal display color for the agent's output |
44
45
  | `model` | enum (optional) | `inherit`, `sonnet`, `haiku` | Omit to use the project's configured profile default. Use `inherit` to bypass the profile and use the highest available model (quality-tier work) |
@@ -277,12 +277,11 @@ grep -rEn "confirm\b|Confirm\b|areYouSure|destructive|danger" src/ --include="*.
277
277
  Collect findings from the micro-polish sections of the mapper outputs (`.design/map/motion.md`, `.design/map/tokens.md`, `.design/map/visual-hierarchy.md`, `.design/map/a11y.md`). If those files are not yet available, run targeted grep passes:
278
278
 
279
279
  ```bash
280
- # transition:all violations
281
- grep -rEn "transition:\s*all|transition-property:\s*all" src/ --include="*.css" --include="*.scss" 2>/dev/null | head -10
282
- grep -rEn 'className="[^"]*\btransition\b[^-]' src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | head -10
283
-
284
- # will-change:all violations
285
- grep -rEn "will-change:\s*all" src/ --include="*.css" --include="*.scss" 2>/dev/null | head -5
280
+ # BAN-NN anti-patterns — Phase 41: run the deterministic detector instead of hand-grepping each
281
+ # rule. One pass, --json, every BAN rule (transition:all, will-change:all, gradient text, bounce
282
+ # easing, scale(0), naked outline:none, pure-black dark mode, disabled zoom, tinted image outline),
283
+ # each finding linked to its reference/anti-patterns.md paragraph. Offline + zero-LLM.
284
+ node "${CLAUDE_PLUGIN_ROOT:-.}/bin/gdd-detect" src/ --json 2>/dev/null || true
286
285
 
287
286
  # Missing AnimatePresence initial={false}
288
287
  grep -rEn "<AnimatePresence" src/ --include="*.tsx" --include="*.jsx" 2>/dev/null | grep -v "initial={false}" | head -10
package/bin/gdd-detect ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ // bin/gdd-detect — Phase 41 deterministic anti-pattern CLI.
3
+ //
4
+ // Thin CJS entry: the engine + CLI are plain dep-free CommonJS under scripts/lib/detect/, so unlike
5
+ // bin/gdd-sdk this needs no compiled/strip-types dual mode — it just requires the CLI and forwards
6
+ // argv + the exit code (0 clean · 2 findings · 1 invocation error).
7
+
8
+ 'use strict';
9
+
10
+ const path = require('node:path');
11
+
12
+ let cli;
13
+ try {
14
+ cli = require(path.resolve(__dirname, '..', 'scripts', 'lib', 'detect', 'cli.cjs'));
15
+ } catch (err) {
16
+ process.stderr.write('gdd-detect: failed to load the detector: ' + (err && err.message ? err.message : String(err)) + '\n');
17
+ process.exit(1);
18
+ }
19
+
20
+ process.exit(cli.main(process.argv.slice(2)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hegemonart/get-design-done",
3
- "version": "1.40.0",
3
+ "version": "1.41.0",
4
4
  "description": "A design-quality pipeline for AI coding agents: brief, plan, implement, and verify UI work against your design system.",
5
5
  "author": "Hegemon",
6
6
  "homepage": "https://github.com/hegemonart/get-design-done",
@@ -33,6 +33,7 @@
33
33
  "NOTICE"
34
34
  ],
35
35
  "bin": {
36
+ "gdd-detect": "./bin/gdd-detect",
36
37
  "gdd-events": "./scripts/cli/gdd-events.mjs",
37
38
  "gdd-graph": "./bin/gdd-graph",
38
39
  "gdd-mcp": "./bin/gdd-mcp",
@@ -57,6 +58,8 @@
57
58
  "lint:links": "npx --yes lychee --no-progress --accept 200,206,403,429 \"**/*.md\" || true",
58
59
  "lint:agentskills": "node scripts/lint-agentskills-spec.cjs",
59
60
  "lint:changelog": "node scripts/lint-changelog.cjs",
61
+ "lint:design": "node bin/gdd-detect test/fixtures/detect/negative --json",
62
+ "sync:rule-catalogue": "node scripts/sync-rule-catalogue.cjs --check",
60
63
  "validate:schemas": "node --experimental-strip-types scripts/validate-schemas.ts",
61
64
  "validate:frontmatter": "node --experimental-strip-types scripts/validate-frontmatter.ts agents/",
62
65
  "detect:stale-refs": "node scripts/detect-stale-refs.cjs",
@@ -18,6 +18,8 @@ Zero tolerance. Each violation = −3 points from Anti-Pattern score. Rewrite ra
18
18
 
19
19
  ### BAN-01: Side-Stripe Borders
20
20
 
21
+ bdId: BAN-01
22
+
21
23
  ```css
22
24
  /* BANNED — AI-generated card tell, regardless of color */
23
25
  border-left: 4px solid var(--color-primary);
@@ -32,6 +34,8 @@ border-right: 3px solid #6366f1;
32
34
 
33
35
  ### BAN-02: Gradient Text
34
36
 
37
+ bdId: BAN-02
38
+
35
39
  ```css
36
40
  /* BANNED */
37
41
  background: linear-gradient(to right, #6366f1, #8b5cf6);
@@ -48,6 +52,8 @@ background-clip: text;
48
52
 
49
53
  ### BAN-03: Bounce/Elastic Easing
50
54
 
55
+ bdId: BAN-03
56
+
51
57
  ```css
52
58
  /* BANNED */
53
59
  transition: all 300ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
@@ -63,6 +69,8 @@ animation-timing-function: spring(1, 80, 10, 0);
63
69
 
64
70
  ### BAN-04: Animating Keyboard Actions
65
71
 
72
+ bdId: BAN-04
73
+
66
74
  No animation on: command palette open/close, keyboard shortcuts, tab switching, filter/sort toggles, navigation item expand/collapse.
67
75
 
68
76
  **Why**: These repeat 100+ times per day. Every millisecond of animation accumulates into felt sluggishness.
@@ -71,6 +79,8 @@ No animation on: command palette open/close, keyboard shortcuts, tab switching,
71
79
 
72
80
  ### BAN-05: Pure Black Dark Mode
73
81
 
82
+ bdId: BAN-05
83
+
74
84
  ```css
75
85
  /* BANNED */
76
86
  background: #000000;
@@ -85,6 +95,8 @@ background: rgb(0, 0, 0);
85
95
 
86
96
  ### BAN-06: Disabling Zoom
87
97
 
98
+ bdId: BAN-06
99
+
88
100
  ```html
89
101
  <!-- BANNED -->
90
102
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
@@ -97,6 +109,8 @@ background: rgb(0, 0, 0);
97
109
 
98
110
  ### BAN-07: Naked `outline: none`
99
111
 
112
+ bdId: BAN-07
113
+
100
114
  ```css
101
115
  /* BANNED — unless a custom focus indicator replaces it */
102
116
  :focus { outline: none; }
@@ -111,6 +125,8 @@ button:focus { outline: 0; }
111
125
 
112
126
  ### BAN-08: `transition: all`
113
127
 
128
+ bdId: BAN-08
129
+
114
130
  ```css
115
131
  /* BANNED */
116
132
  transition: all 300ms ease;
@@ -124,6 +140,8 @@ transition: all 300ms ease;
124
140
 
125
141
  ### BAN-09: `scale(0)` Animation Entry
126
142
 
143
+ bdId: BAN-09
144
+
127
145
  ```css
128
146
  /* BANNED — nothing in the real world materializes from nothing */
129
147
  @keyframes enter { from { transform: scale(0); } }
@@ -339,6 +357,8 @@ If YES to any → rewrite that element before proceeding.
339
357
 
340
358
  ### BAN-10: Same Border-Radius on Nested Surfaces
341
359
 
360
+ bdId: BAN-10
361
+
342
362
  Applying the same `border-radius` to a container and an element inside it (when the element is separated by padding) makes the inner element appear to "float" — the radii should be concentric, not equal.
343
363
 
344
364
  **Grep (Tailwind):**
@@ -355,6 +375,8 @@ Source: jakubkrehel/make-interfaces-feel-better (MIT)
355
375
 
356
376
  ### BAN-11: Tinted Image Outline
357
377
 
378
+ bdId: BAN-11
379
+
358
380
  Using a colored outline on images (e.g., `outline-slate-200`, `outline-gray-300`, or a hex-value outline color) competes visually with the image content and creates color contamination.
359
381
 
360
382
  **Grep (Tailwind):**
@@ -376,6 +398,8 @@ Source: jakubkrehel/make-interfaces-feel-better (MIT)
376
398
 
377
399
  ### BAN-12: `transition: all`
378
400
 
401
+ bdId: BAN-12
402
+
379
403
  `transition: all` animates every animatable CSS property on the element, including layout-triggering properties (width, height, padding, margin). This causes layout recalculation on EVERY transition, creating jank and unexpected visual effects (e.g., a hover transition that also animates the element's size if any dimensions change).
380
404
 
381
405
  **Grep (CSS):**
@@ -393,6 +417,8 @@ Source: jakubkrehel/make-interfaces-feel-better (MIT)
393
417
 
394
418
  ### BAN-13: `will-change: all`
395
419
 
420
+ bdId: BAN-13
421
+
396
422
  `will-change: all` promotes every animatable property to its own GPU compositor layer, consuming GPU memory for each property. On complex components this can allocate hundreds of MB of texture memory per instance, causing performance degradation and potential crashes on mobile.
397
423
 
398
424
  **Grep:**
@@ -0,0 +1,61 @@
1
+ # CLI Localization — GDD's Own Surface
2
+
3
+ Phase 40.5 contract. `reference/i18n.md` covers internationalizing *user designs*; this file covers
4
+ **GDD's own CLI** — `--help`, the common error messages, and skill prompt headers. The goal is the
5
+ lowest-effort, highest-impact subset; full skill-body translation is deferred (per-locale demand).
6
+
7
+ ## Resolution
8
+
9
+ `scripts/lib/i18n/index.cjs` resolves the active locale with this precedence:
10
+
11
+ 1. **`.design/config.json#locale`** — an explicit per-project override (set via `/gdd:locale <code>`).
12
+ 2. **`process.env`** — `LC_ALL` / `LC_MESSAGES` / `LANG` / `LANGUAGE` (normalized: `ru_RU.UTF-8` → `ru`).
13
+ 3. **`en`** — the default.
14
+
15
+ A `C` / `POSIX` env locale resolves to `en`. The resolved code then drives a **fallback chain**
16
+ `locale → base → en` (e.g. `de-DE → de → en`), so a regional locale degrades to its base and finally
17
+ to English — the complete source table.
18
+
19
+ ## Message tables
20
+
21
+ Flat-JSON tables live at `scripts/lib/i18n/messages/<locale>.json` (chosen over ICU MessageFormat for
22
+ simplicity). Each is `{ "_meta": { locale, coverage, fallback }, "<key>": "<string>", ... }`. Keys are
23
+ namespaced: `help.*` (usage + section headers), `error.*` (the common CLI errors), `prompt.*` (skill
24
+ prompt headers), `status.*`.
25
+
26
+ - **`en.json`** — the **complete source of truth**; every key lives here.
27
+ - **`ru.json`** — a complete second-locale translation (covers every `en` key).
28
+ - **`uk.json` / `de.json` / `fr.json` / `zh.json` / `ja.json`** — **placeholders**: a `_meta` marker
29
+ (`coverage: "placeholder"`) plus a starter subset. Any missing key falls back to `en` per the chain.
30
+
31
+ `translate(tables, key, locale)` walks the chain and returns the first hit, or the key itself if no
32
+ table has it (a missing key is always visible, never a crash).
33
+
34
+ ## Frontmatter `description_i18n`
35
+
36
+ Skills and agents may carry an **opt-in** `description_i18n: { <locale>: "<description>" }` map.
37
+ `descriptionFor(frontmatter, locale)` returns the localized description via the fallback chain, or the
38
+ plain English `description` when the locale is absent. The field is fully backward-compatible — a
39
+ skill/agent without it is unaffected, and the Phase 28.5 contract only validates it (as an object of
40
+ locale→string) when present.
41
+
42
+ ## Completeness policy
43
+
44
+ The completeness gate is **warn-only**. Only `en` (source) and `ru` (full) are expected to be 100%; the
45
+ five placeholder locales are intentionally partial and rely on the English fallback. A locale is never
46
+ required to be complete to ship — partial is better than English-only, and fallback guarantees no key
47
+ is ever missing at runtime.
48
+
49
+ ## Adding or completing a locale (contribution path)
50
+
51
+ 1. Edit `scripts/lib/i18n/messages/<locale>.json` — add the keys you can translate (any `en` key is
52
+ fair game; you do not need 100%).
53
+ 2. Set `_meta.coverage` to `"complete"` once every `en` key is present, else leave `"placeholder"`.
54
+ 3. Add a translator-credit line to `NOTICE` under the attributions section (name/handle + locale).
55
+ 4. Open a PR. The warn-only gate reports coverage; it does not block on partial locales.
56
+
57
+ ## Boundaries
58
+
59
+ `--help` + common errors + skill prompt headers only — not full skill bodies (deferred per demand),
60
+ not RTL terminal rendering (a terminal concern), not voice/conversational localization. English is
61
+ always the final fallback, so the CLI is never broken by a partial translation.
@@ -395,3 +395,11 @@ single-operator projects are unaffected. Full contract: `reference/multi-author-
395
395
  team-mode policy (`scripts/lib/collab/lock-policy.cjs` — 30 s wait + 100 ms backoff);
396
396
  `sync_backend` selects the cross-machine `.design/` backend (`scripts/lib/collab/sync-backend.cjs`,
397
397
  default `git`; `s3`/`git-lfs` are opt-in declarations — a live client is not bundled this phase).
398
+
399
+ ## CLI localization (Phase 40.5)
400
+
401
+ - **`locale`** (`en`|`ru`|`uk`|`de`|`fr`|`zh`|`ja`) — overrides the language of GDD's own `--help`,
402
+ common error messages, and skill prompt headers. Set via `/gdd:locale <code>`. Precedence: this key >
403
+ env `LANG`/`LC_ALL` > `en`. Missing message keys fall back to English (`scripts/lib/i18n/index.cjs`,
404
+ chain `locale → base → en`); `en` + `ru` are complete, the other five are placeholders. Full
405
+ contract: `reference/cli-localization.md`.
@@ -1035,6 +1035,13 @@
1035
1035
  "type": "meta-rules",
1036
1036
  "phase": 40,
1037
1037
  "description": "Phase 40 team-collaboration contract: multi-writer STATE.md via a git-merge-driver with per-section semantic merge (scripts/lib/collab/section-merge.cjs — union by D-id, conflict only on same-id divergence); decision attribution line-suffix [author= co-author=] (attribution.cjs); the async review queue proposed->reviewing->approved->locked with hard locks + audited /gdd:unlock-decision (review-queue.cjs); the multi-writer advisory-lock policy (lock-policy.cjs, 30s/100ms backoff in team mode); sectional handoff gdd_cycle_mode designer|dev|full (cycle-mode.cjs); the permission model (permissions.cjs) + CI gate; decision-journal-exporter (pseudonymized, write-only Notion) + pr-commenter D-XX threading; opt-in cross-machine sync (sync-backend.cjs, defaults to git). Agents conflict-resolver + decision-journal-exporter; skills /gdd:review-decisions + /gdd:unlock-decision."
1038
+ },
1039
+ {
1040
+ "name": "cli-localization",
1041
+ "path": "reference/cli-localization.md",
1042
+ "type": "meta-rules",
1043
+ "phase": 40.5,
1044
+ "description": "Phase 40.5 CLI-localization contract: locale resolution (config.locale > env LANG > en) + fallback chain locale->base->en + flat-JSON message tables via scripts/lib/i18n/index.cjs; tables at scripts/lib/i18n/messages/{en,ru,uk,de,fr,zh,ja}.json (en source-complete, ru full, 5 placeholders with en fallback); the opt-in description_i18n frontmatter (descriptionFor falls back to English); /gdd:locale skill; warn-only completeness; the add-a-locale contribution path (translate table + NOTICE credit + PR). Distinct from reference/i18n.md (which covers USER-design i18n)."
1038
1045
  }
1039
1046
  ]
1040
1047
  }
@@ -41,6 +41,11 @@
41
41
  "type": "string",
42
42
  "description": "Latest plugin tag (e.g. \"v1.0.7.3\") whose update nudge the user has dismissed. Set by /gdd:check-update --dismiss and by hooks/update-check.sh on the --dismiss code path. When a newer tag ships, the nudge reappears."
43
43
  },
44
+ "locale": {
45
+ "type": "string",
46
+ "enum": ["en", "ru", "uk", "de", "fr", "zh", "ja"],
47
+ "description": "Phase 40.5 CLI locale override for GDD's own --help, error messages, and skill prompt headers. Set via /gdd:locale <code>. Precedence: this key > env LANG/LC_ALL > en. Missing message keys fall back to English per scripts/lib/i18n/index.cjs (locale -> base -> en). en + ru are complete; uk/de/fr/zh/ja are placeholders that fall back to English."
48
+ },
44
49
  "gdd_cycle_mode": {
45
50
  "type": "string",
46
51
  "enum": ["designer", "dev", "full"],
@@ -101,6 +101,10 @@ export interface DesignConfigJson {
101
101
  * Latest plugin tag (e.g. "v1.0.7.3") whose update nudge the user has dismissed. Set by /gdd:check-update --dismiss and by hooks/update-check.sh on the --dismiss code path. When a newer tag ships, the nudge reappears.
102
102
  */
103
103
  update_dismissed?: string;
104
+ /**
105
+ * Phase 40.5 CLI locale override for GDD's own --help, error messages, and skill prompt headers. Set via /gdd:locale <code>. Precedence: this key > env LANG/LC_ALL > en. Missing message keys fall back to English per scripts/lib/i18n/index.cjs (locale -> base -> en). en + ru are complete; uk/de/fr/zh/ja are placeholders that fall back to English.
106
+ */
107
+ locale?: 'en' | 'ru' | 'uk' | 'de' | 'fr' | 'zh' | 'ja';
104
108
  /**
105
109
  * Phase 40 sectional handoff. designer = Brief + Explore only; dev = Plan + Design + Verify; full = all stages (default). scripts/lib/collab/cycle-mode.cjs gates STATE writes by stage so a designer and a dev can hand a cycle back and forth without overwriting each other's sections.
106
110
  */
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+ // Phase 41 — gdd-detect CLI. Dep-free by default (regex-fast). The DOM-aware (jsdom) and URL
3
+ // (puppeteer) paths are SOFT optionals loaded via try-require — never a package.json dependency, so
4
+ // the SC#10 network-isolation scan stays clean and the plugin keeps its zero-runtime-dep guarantee.
5
+ //
6
+ // gdd-detect <path> [--json] [--fast] [--rule BAN-NN] [--puppeteer]
7
+ //
8
+ // Exit codes: 0 = clean · 2 = findings · 1 = invocation error.
9
+
10
+ const engine = require('./engine.cjs');
11
+
12
+ const HELP = `gdd-detect — scan HTML/CSS/JSX for GDD anti-patterns (BAN-NN).
13
+
14
+ Usage:
15
+ gdd-detect <path> [options]
16
+
17
+ Arguments:
18
+ <path> A file or directory (scanned recursively), or a http(s):// URL (needs --puppeteer).
19
+
20
+ Options:
21
+ --json Machine-readable JSON output.
22
+ --fast Regex-only; do not load jsdom even if present.
23
+ --rule <BAN-NN> Run a single rule (e.g. --rule BAN-08).
24
+ --puppeteer Allow scanning a URL via Puppeteer (an optional, separately-installed dependency).
25
+ -h, --help This help.
26
+
27
+ Exit codes: 0 clean · 2 findings · 1 invocation error.`;
28
+
29
+ function parseArgs(argv) {
30
+ const opts = { path: null, json: false, fast: false, rule: null, puppeteer: false, help: false };
31
+ for (let i = 0; i < argv.length; i++) {
32
+ const a = argv[i];
33
+ if (a === '--json') opts.json = true;
34
+ else if (a === '--fast') opts.fast = true;
35
+ else if (a === '--puppeteer') opts.puppeteer = true;
36
+ else if (a === '-h' || a === '--help') opts.help = true;
37
+ else if (a === '--rule') opts.rule = argv[++i] || null;
38
+ else if (a.startsWith('--rule=')) opts.rule = a.slice('--rule='.length);
39
+ else if (!a.startsWith('-') && opts.path === null) opts.path = a;
40
+ }
41
+ return opts;
42
+ }
43
+
44
+ function isUrl(p) {
45
+ return /^https?:\/\//i.test(String(p || ''));
46
+ }
47
+
48
+ /** Select the detection engine. Returns { mode, warning }. Regex-fast is the dep-free default. */
49
+ function selectEngine(opts, requireFn) {
50
+ if (opts.fast) return { mode: 'regex-fast', warning: null };
51
+ let hasJsdom = false;
52
+ try { requireFn('jsdom'); hasJsdom = true; } catch { hasJsdom = false; }
53
+ if (hasJsdom) return { mode: 'dom-aware', warning: null };
54
+ return { mode: 'regex-fast', warning: 'jsdom not installed — using regex-fast (install jsdom for DOM-aware mode, or pass --fast to silence this).' };
55
+ }
56
+
57
+ function renderHuman(result, mode) {
58
+ const lines = [];
59
+ for (const f of result.findings) {
60
+ lines.push(`${f.file}:${f.line}:${f.column} ${f.severity.toUpperCase()} ${f.ruleId} ${f.name} — ${f.references[0]}`);
61
+ }
62
+ const errs = result.findings.filter((f) => f.severity === 'error').length;
63
+ const warns = result.findings.length - errs;
64
+ lines.push('');
65
+ lines.push(`gdd-detect (${mode}): ${result.filesScanned} file(s), ${result.findings.length} finding(s) — ${errs} error, ${warns} warn.`);
66
+ return lines.join('\n');
67
+ }
68
+
69
+ /**
70
+ * @param {string[]} argv process.argv.slice(2)
71
+ * @param {{ cwd?: string, log?: fn, err?: fn, requireFn?: fn }} [io] injectable for tests
72
+ * @returns {number} exit code
73
+ */
74
+ function main(argv, io) {
75
+ const o = io || {};
76
+ const log = o.log || ((s) => process.stdout.write(s + '\n'));
77
+ const err = o.err || ((s) => process.stderr.write(s + '\n'));
78
+ const requireFn = o.requireFn || require;
79
+ const cwd = o.cwd || process.cwd();
80
+ const opts = parseArgs(argv);
81
+
82
+ if (opts.help || (!opts.path && argv.length === 0)) { log(HELP); return opts.help ? 0 : 1; }
83
+ if (!opts.path) { err('gdd-detect: missing <path>. See --help.'); return 1; }
84
+ if (opts.rule && !/^BAN-\d{2}$/i.test(opts.rule)) { err(`gdd-detect: --rule expects a BAN-NN id (got "${opts.rule}").`); return 1; }
85
+
86
+ // URL path → Puppeteer (optional, separately installed). Never a stack trace.
87
+ if (isUrl(opts.path)) {
88
+ if (!opts.puppeteer) { err('gdd-detect: scanning a URL requires --puppeteer. Pass --puppeteer (and `npm i -D puppeteer`) to enable URL scans.'); return 1; }
89
+ let hasPuppeteer = false;
90
+ try { requireFn('puppeteer'); hasPuppeteer = true; } catch { hasPuppeteer = false; }
91
+ if (!hasPuppeteer) { err('gdd-detect: --puppeteer given but puppeteer is not installed. Install it with `npm i -D puppeteer` (it stays an optional dependency).'); return 1; }
92
+ err('gdd-detect: URL scanning is not wired in this build; clone the page locally and scan the files instead.');
93
+ return 1;
94
+ }
95
+
96
+ const { mode, warning } = selectEngine(opts, requireFn);
97
+ if (warning && !opts.json) err('gdd-detect: ' + warning);
98
+
99
+ let result;
100
+ try { result = engine.run(opts.path, { ruleId: opts.rule, cwd }); }
101
+ catch (e) { err('gdd-detect: ' + (e && e.message ? e.message : String(e))); return 1; }
102
+
103
+ if (opts.json) log(JSON.stringify({ mode, ...result }, null, 2));
104
+ else log(renderHuman(result, mode));
105
+
106
+ return result.findings.length > 0 ? 2 : 0;
107
+ }
108
+
109
+ module.exports = { main, parseArgs, isUrl, selectEngine, HELP };
110
+
111
+ if (require.main === module) process.exit(main(process.argv.slice(2)));