sheleg-design-skill 1.9.0 → 1.11.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 (43) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/README.md +34 -17
  3. package/bin/cli.js +10 -5
  4. package/cursor/rules/sheleg-design.mdc +36 -1
  5. package/kits/atrium/src/styles.css +1 -2
  6. package/kits/blueprint/src/styles.css +2 -2
  7. package/kits/editorial-luxury/src/styles.css +5 -2
  8. package/kits/field-notes/src/styles.css +6 -0
  9. package/kits/instrument-console/src/styles.css +4 -1
  10. package/kits/maquette/src/styles.css +1 -1
  11. package/kits/orchard/src/styles.css +6 -1
  12. package/kits/showroom/src/styles.css +2 -2
  13. package/kits/workbench/src/styles.css +1 -1
  14. package/package.json +3 -3
  15. package/plugins/sheleg-design/.claude-plugin/plugin.json +2 -2
  16. package/plugins/sheleg-design/commands/sheleg-design.md +24 -8
  17. package/plugins/sheleg-design/skills/sheleg-design/DESIGN_SYNC_BRIDGE.md +19 -4
  18. package/plugins/sheleg-design/skills/sheleg-design/MOTION_DOCTRINE.md +10 -2
  19. package/plugins/sheleg-design/skills/sheleg-design/SHELEG_DESIGN.md +58 -14
  20. package/plugins/sheleg-design/skills/sheleg-design/SKILL.md +57 -84
  21. package/plugins/sheleg-design/skills/sheleg-design/SURFACE_COMPOSITION.md +96 -0
  22. package/plugins/sheleg-design/skills/sheleg-design/styles/STYLE_PACK_TEMPLATE.md +42 -0
  23. package/plugins/sheleg-design/skills/sheleg-design/styles/atrium.md +36 -4
  24. package/plugins/sheleg-design/skills/sheleg-design/styles/blueprint.md +21 -12
  25. package/plugins/sheleg-design/skills/sheleg-design/styles/briefing-room.md +16 -6
  26. package/plugins/sheleg-design/skills/sheleg-design/styles/cyclorama.md +2 -0
  27. package/plugins/sheleg-design/skills/sheleg-design/styles/editorial-luxury.md +18 -7
  28. package/plugins/sheleg-design/skills/sheleg-design/styles/field-notes.md +13 -5
  29. package/plugins/sheleg-design/skills/sheleg-design/styles/instrument-console.md +10 -0
  30. package/plugins/sheleg-design/skills/sheleg-design/styles/maquette.md +4 -2
  31. package/plugins/sheleg-design/skills/sheleg-design/styles/orchard.md +20 -6
  32. package/plugins/sheleg-design/skills/sheleg-design/styles/prism.md +9 -5
  33. package/plugins/sheleg-design/skills/sheleg-design/styles/showroom.md +12 -7
  34. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/atrium.css +1 -1
  35. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/blueprint.css +2 -2
  36. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/editorial-luxury.css +5 -1
  37. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/field-notes.css +6 -0
  38. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/instrument-console.css +4 -0
  39. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/maquette.css +1 -1
  40. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/orchard.css +6 -0
  41. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/showroom.css +2 -2
  42. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/workbench.css +1 -1
  43. package/plugins/sheleg-design/skills/sheleg-design/styles/workbench.md +28 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,176 @@ All notable changes to this project are documented in this file. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions
5
5
  follow [SemVer](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.11.0] - 2026-08-10
8
+
9
+ The bundle now stands on its own. A repeat audit ran the skill the way an agent
10
+ actually uses it — six application scenarios in fresh contexts, not routing
11
+ questions — and found the same defect class three times: **a rule inside the
12
+ shipped bundle instructing the reader to use something only the repository has.**
13
+ 1.10.0 had fixed one instance of this and swept the literal form (a repo path in
14
+ backticks, now zero) without sweeping the class.
15
+
16
+ ### Fixed — the class, in its three shipped shapes
17
+
18
+ - **The bundle carries its own version.** `SKILL.md` front-matter gains
19
+ `metadata.version`, making version sync ×5. `DESIGN_SYNC_BRIDGE.md` §7 has told
20
+ readers since 1.6.0 to record the pack version in the synced project; there was
21
+ no version anywhere in the bundle to read, only historical mentions in two packs
22
+ ("until 1.10.0 the header rule read…"). A rule whose input does not ship is not
23
+ a rule.
24
+ - **The spine is named.** §1 built its "names are the interface" argument on "the
25
+ same six component names" and named none of them. They are now stated —
26
+ `Button`, `Card`, `Chip`, `Stat`, `Heading`, `Rule` — so a delivered kit can be
27
+ checked against the claim. A test agent refused to guess them and said asserting
28
+ them would be "inventing a value and believing I read it".
29
+ - **Pack-authoring rules ship with the template.** *Never ship on the nine*, *no
30
+ addressable reference, no pack*, *a derived value is marked derived where it is
31
+ declared*, and *the three gates are what done means* lived in `CONTRIBUTING.md`,
32
+ which no install contains. They are now in `styles/STYLE_PACK_TEMPLATE.md`,
33
+ which does.
34
+ - **`validate_bundle_self_sufficiency()`** gates all three shapes, each watched
35
+ failing on a planted defect *and* discriminated by its own message. It checks
36
+ the three forms that have actually shipped and says so — it is not a general
37
+ proof, so a fourth instance has to be a new shape.
38
+
39
+ ### Fixed — two files that disagreed, and two constants with no value
40
+
41
+ - **The scrub recipe now obeys the doctrine it contradicted.** `SHELEG_DESIGN.md`
42
+ §9 shipped `useLayoutEffect` with hand-rolled teardown; `MOTION_DOCTRINE.md` §6
43
+ names that exact pattern as where leaked triggers and doubled animations come
44
+ from. Neither file acknowledged the other, and an agent reading only the
45
+ reference copied the banned shape into a junior-ready plan.
46
+ - **`arcAmp` and `drop` are declared tuning constants.** Both appeared inside
47
+ formulas with no value anywhere in the skill, which reads as an omission rather
48
+ than a decision. Neither is invented here; the rule is to tune, then record the
49
+ value beside the formation rather than inline.
50
+
51
+ ### Changed
52
+
53
+ - **The entry point is back under its disclosure budget** — 6157 → 4856 tokens.
54
+ Scene depth and the `dataviz` handoff moved to `SURFACE_COMPOSITION.md` with
55
+ stated load triggers; the quick-reference table moved next to the mechanisms it
56
+ summarises in `SHELEG_DESIGN.md`. No doctrine was deleted.
57
+ - **The front-matter budget was measuring the wrong thing, and fixing it raises
58
+ the total ceiling from 1024 to 1280.** That is a loosening, named as one. The
59
+ single 1024 cap over the whole block conflated the spec's limit on
60
+ `description` with the bookkeeping keys beside it, leaving the check stricter
61
+ than the standard it claimed to implement — so a 24-character version key
62
+ consumed the description's headroom and would have blocked the widening board
63
+ row B-006 asks for. Now two budgets: `description` ≤ 1024 (the spec),
64
+ everything else ≤ 256, against 74 characters used today.
65
+ - **Six scenario results recorded** with their commit, closing most of board row
66
+ B-005. The harness had 20 scenarios and 7 recorded results, so the repository
67
+ could not answer "do the usage scenarios work" from its own records.
68
+
69
+ ## [1.10.0] - 2026-08-10
70
+
71
+ A fresh-eyes audit of the whole skill, and the finding is the green: at 1.9.0 all
72
+ three gates passed — 1270 / 412 / 224 — while the skill told a reading agent
73
+ there were six style packs, handed the chart layer a token ramp no pack defines,
74
+ and stated thirteen contrast ratios that are wrong.
75
+
76
+ Full report with every `file:line`, and the reproductions:
77
+ [`docs/audit/2026-08-10-skill-audit.md`](./docs/audit/2026-08-10-skill-audit.md).
78
+
79
+ ### Fixed — what an agent was told that was not true
80
+
81
+ - **The `dataviz` handoff named tokens no pack defines.** `SKILL.md` promised a
82
+ ramp `--accent-tint … --accent-deep`: `--accent-tint` exists in **one** pack of
83
+ twelve, `--accent-deep` in three, and **no pack has both**. It promised a
84
+ status set of `--good` / `--warning` / `--danger` that seven packs lack and
85
+ two have no version of at all. An undefined custom property does not error —
86
+ the declaration goes invalid at computed-value time and the property silently
87
+ inherits — so the agent follows the instruction exactly and the page is wrong.
88
+ The table is now written by role, and the non-uniform mappings are named.
89
+ - **Thirteen stated contrast ratios, recomputed and corrected.** `blueprint`'s
90
+ ratio column is headed ``On `--bg` `` and every number in it was computed
91
+ against pure white (`--ink` 17.74 → **17.15**, `--accent` 7.53 → **7.28**,
92
+ pure black 21 → **20.31**). `prism` claimed ink "≥18:1 over all four stops"
93
+ three times; it is **15.85–16.82** — 18.95 is ink on plain white, carried onto
94
+ the wash. Also `showroom` 15.9 → **15.35** and 7.7 → **7.08**, `maquette` 5.0 →
95
+ **5.62** and 13.9 → **13.57**, `editorial-luxury` 6.1 → **6.93**, `workbench`
96
+ 5.0 → **4.57**. None crossed a floor; all were presented as measured.
97
+ - **Two packs justified one accent by a "symmetry" that is a mathematical
98
+ identity.** WCAG contrast is symmetric for every pair by definition. In
99
+ `showroom`, whose field is white, the sentence stated one measurement twice; in
100
+ `blueprint`, whose field is not, the two directions genuinely differ and the
101
+ pack asserted one number for both.
102
+ - **`atrium` prescribed `transition: padding-top .2s` on a sticky header** — a
103
+ layout property, transitioned, on scroll: the exact form `MOTION_DOCTRINE.md`
104
+ forbids, shipped inside the bundle that ships the ban.
105
+ - **`field-notes`' radius rule, its worked example and its token layer were three
106
+ different systems.** "Subtract the padding … `12 - 12 ≈ 7.2`" — subtraction
107
+ gives 0; the token layer uses `calc(var(--radius) * 0.6)`.
108
+ - **`blueprint`'s Components and Hero instructed the violation its own Signature
109
+ element section names** (registration marks on both CTAs). `test/scenarios.md`
110
+ recorded this as "fixed in the same run"; only half of it had landed.
111
+ - **`atrium` said three shadows exist**; its token layer defines four.
112
+ - **The colour-blindness ban was copy-pasted into six packs**, asserting a
113
+ measurement across "several pairs" in packs owning one status colour or none —
114
+ and naming four states as if the pack supplied them, which is an invitation to
115
+ invent a hue. Rewritten for `orchard`, `editorial-luxury` and `briefing-room`.
116
+ - **`MOTION_DOCTRINE.md` §5 over-banned**, forbidding everything outside four
117
+ properties while §2 prescribes an ease for colour changes. The ban is on
118
+ layout, which is what its own rationale says.
119
+ - **ADR-0001 named a pack that never existed** (`lecture-hall`; the pack that
120
+ shipped from graphify.com is `field-notes`). The decision stands; the example
121
+ was written on a branch that never merged.
122
+
123
+ ### Added — the half-library nobody declared
124
+
125
+ Six of twelve packs carry `## Components`, `## Hero`, `## Responsive` and
126
+ `## Signature element`; six do not, and nothing said which. Every pack now
127
+ declares **`Contract: core` or `Contract: widened`** above its Register, a core
128
+ pack states what it leaves the reader to decide, the `SKILL.md` routing table
129
+ marks it, and a check enforces the declaration against the headings present.
130
+
131
+ ### Added — six checks, each watched failing on a planted defect
132
+
133
+ Counted claims (whitespace-normalised: the README's "six locked style packs" was
134
+ split across a line break) · exhaustive pack enumerations in both manifests, the
135
+ slash command, the CLI, the README and the Cursor rule · one name for the pack
136
+ contract · the `Contract:` declaration · the core role vocabulary (`--bg`,
137
+ `--ink`, and an accent role every pack resolves) · and **every stated contrast
138
+ ratio, recomputed from the token layer**.
139
+
140
+ The ratio check is scoped to claims whose base the document declares — a column
141
+ headed ``On `--bg` ``, an `on/over --token` phrase, or an `--on-X` name. A first
142
+ draft that inferred the partner produced 22 false positives out of 40.
143
+
144
+ ### Fixed — three gates that could not fail
145
+
146
+ - **Deleting requirements made two gates quieter, and green.** Stripping a pack's
147
+ four widened headings took `validate.py` 1270 → 1269 and `sloplint.py` 224 →
148
+ 223, both exit 0. **Ratchet floors** now live in `test/floors.json` and are
149
+ enforced by all three.
150
+ - **One decoy comment disabled a slop-lint ban for a whole file, permanently.**
151
+ The check took the first match only and `continue`d past a nearby negation
152
+ word, so the counter fell and later occurrences went unexamined. Suppression is
153
+ now per occurrence, and ban-quoting sections are exempted by heading.
154
+ - **`validate.py --self-test` printed OK for a self-test that did not exist** —
155
+ the same defect the 2026-08-05 retrospective recorded in `validate_palette.py`.
156
+ All three scripts now exit 2 on an unknown argument, and `validate.py` has a
157
+ real self-test: six planted defects, run against a copy of the tree.
158
+ - **The slop lint read only fenced code blocks**, and no style pack contains one —
159
+ so all twelve packs, `SKILL.md`, both bridges and the AI patterns were never
160
+ linted. It now reads the inline CSS the packs prescribe in prose.
161
+ - **`npm test` and both workflows now run every gate and every self-test.** The
162
+ release path was gated on one of three.
163
+
164
+ ### Fixed — stale counts and reach
165
+
166
+ "six locked style packs" and "all six kits" (twelve), "T1–T7" (T1–T19), "Three
167
+ packs extracted" (eight), the pack contract called nine / ten / thirteen in five
168
+ places at once — one of which told an author to ship nine headings, which the
169
+ gate then passed. `plugin.json`, `marketplace.json` and the `/sheleg-design`
170
+ command named three packs of twelve, so nine could not be asked for by name.
171
+ `MOTION_DOCTRINE.md`, marked REQUIRED, appeared on no install surface: it is now
172
+ in the README table, the CLI help and banner, the slash command, and the Cursor
173
+ rule — which gains the whole doctrine in condensed form.
174
+
175
+ Gates: **1364 / 469 / 320**, from 1270 / 412 / 224.
176
+
7
177
  ## [1.9.0] - 2026-08-09
8
178
 
9
179
  Four style packs, taking the library from eight to twelve — and a fix to the
package/README.md CHANGED
@@ -10,7 +10,8 @@ nothing. Ask it for a dashboard and you get a different flavor of the same
10
10
  problem — invented colors, six accent hues, dark mode retrofitted later.
11
11
 
12
12
  This skill is the taste layer. It gives a coding agent **one motion
13
- methodology** for cinematic, scroll-driven pages and **six locked style
13
+ methodology** for cinematic, scroll-driven pages, **a motion doctrine** that
14
+ decides whether to animate before it decides how, and **twelve locked style
14
15
  packs** with ready-made design tokens, so what it builds reads as one system
15
16
  instead of a pile of effects.
16
17
 
@@ -34,11 +35,13 @@ and collectively cinematic. One scroll "clock" feeds a WebGL particle field, a
34
35
  rail — each an independent, degrade-to-calm layer. Nothing crossfades; things
35
36
  *redeploy*.
36
37
 
37
- **Style packs** — the visual identity, pluggable per project. Two of them are
38
- meant to be used **standalone**, with none of the motion layer: `workbench`
39
- (quiet light/dark product UI for dashboards, admin panels, internal and dev
40
- tools) and `briefing-room` (a dark 16:9 presentation deck, where the presenter's
41
- voice is the timeline and slides therefore never animate).
38
+ **Style packs** — the visual identity, pluggable per project. Three of them are
39
+ meant to be used **standalone**: `workbench` (quiet light/dark product UI for
40
+ dashboards, admin panels, internal and dev tools) and `briefing-room` (a dark
41
+ 16:9 presentation deck, where the presenter's voice is the timeline and slides
42
+ therefore never animate) take none of the motion layer at all; `field-notes` is
43
+ standalone by default — its reference carries no motion library — but may opt
44
+ into the cinematic layer, and says so in its own *Motion flavor* section.
42
45
 
43
46
  | Pack | Look | Choose for |
44
47
  |---|---|---|
@@ -123,11 +126,12 @@ skills.
123
126
  |---|---|
124
127
  | `SKILL.md` | The agent-facing skill: discovery triggers, the principles, how to apply them, quick-reference rules, common mistakes |
125
128
  | `SHELEG_DESIGN.md` | The full reference: architecture, layer-by-layer mechanics with code, the exact morph math, the DOM↔WebGL projection bridge, a build-from-scratch recipe, and why each piece works |
129
+ | `MOTION_DOCTRINE.md` | Whether to animate at all, before how: the frequency table that kills motion on high-repetition paths, the easing tree and the `ease-in` ban, the duration ceiling, the forbidden forms, and the reduced-motion contract. `SKILL.md` marks it required before any animation |
126
130
  | `DESIGN_SYNC_BRIDGE.md` | The Claude Design contract: what a pack sends to claude.ai/design and in what shape, the rule for each of the four reference types, and the border motion does not cross |
127
131
  | `FIGMA_BRIDGE.md` | The design↔code contract: how a pack's tokens map onto Figma variable collections and modes, how to implement a design without importing raw values, and what cannot cross the border |
128
132
  | `AI_PRODUCT_PATTERNS.md` | The surfaces a model drives: the five states of a call, streaming instead of spinners, latency, provenance and uncertainty, agent confirmations, and the bans that keep it honest |
129
133
  | `styles/*.md` | The twelve style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
130
- | `styles/tokens/*.css` | The ready-made token layer per pack, copied verbatim instead of transcribed (workbench ships a light `:root` plus a `data-theme="dark"` twin) |
134
+ | `styles/tokens/*.css` | The ready-made token layer per pack, copied verbatim instead of transcribed (`workbench` and `field-notes` each ship a light `:root` plus a `data-theme="dark"` twin) |
131
135
  | `styles/STYLE_PACK_TEMPLATE.md` | The pack contract as a skeleton, so a new style is authored against the same headings rather than improvised |
132
136
 
133
137
  ## What you get out of it
@@ -197,7 +201,7 @@ cd ./ds-workbench && npm install && npm run build
197
201
  then `/design-sync` in that directory, from Claude Code. Three layers cross: the
198
202
  pack's **bans** as the design system's own README, `styles.css` built from
199
203
  `tokens/<pack>.css` verbatim, and the components — a six-name spine that is
200
- identical in all six kits, so switching packs swaps identity rather than API,
204
+ identical in all twelve kits, so switching packs swaps identity rather than API,
201
205
  plus each pack's signature parts. **Motion does not cross**, exactly as it does
202
206
  not cross into Figma: a kit is the static half of a pack, and saying so is what
203
207
  stops an agent inventing motion to fill the silence.
@@ -224,16 +228,29 @@ repo. Entirely optional; without it the skill works from the pack alone.
224
228
  python3 test/validate.py # or: npm test
225
229
  ```
226
230
 
227
- The validator is the repo's contract, not a formality — it checks manifests and
228
- four-way version sync, skill/command/rule front-matter and description canon,
229
- the full style-pack section contract, pack ↔ `SKILL.md` ↔ CLI-help agreement,
230
- the bundled template against `templates/`, both installers' file lists, the
231
- entire `.cursor/` mirror against the plugin copy, and every relative link. CI
232
- runs it on each push and PR alongside a negative self-test (the validator must
233
- fail on a corrupted version) and installs the bundle through **both** installers,
234
- diffing the result against the source.
231
+ `npm test` is **four gates**, not one, and `validate.py` alone is about a third
232
+ of the contract:
235
233
 
236
- `test/scenarios.md` (T1–T7) is the behavioral harness: fresh subagents given a
234
+ | Gate | What it decides |
235
+ |---|---|
236
+ | `test/validate.py` | manifests and four-way version sync · skill/command/rule front-matter and the description canon · the pack section contract (nine always, the widened four all-or-nothing) and each pack's `Contract:` declaration · the core role vocabulary (`--bg`, `--ink`, and a resolvable accent) in every token layer · every counted claim (packs, kits, scenarios, headings) · exhaustive pack enumerations in the manifests, the command, the CLI, the README and the rule · one name for the pack contract · fork reciprocity · the eleven kit checks · `install.sh`'s file list, both directions · the whole `.cursor/` mirror · every relative link |
237
+ | `test/validate_palette.py` | contrast floors and semantic separation per theme, including three simulated dichromacies · AI-default-cluster provenance · **every contrast ratio the docs state, recomputed from the token layer** |
238
+ | `test/sloplint.py` | the bundle obeying its own bans, in token layers, fenced examples **and the inline CSS the packs prescribe in prose** · doctrine completeness · pack origin addressability |
239
+ | `node --check bin/cli.js` | the installer parses |
240
+
241
+ Each gate ships a `--self-test` that plants a defect it must catch (`npm run
242
+ selftest`), rejects an unknown argument instead of silently running the normal
243
+ pass, and enforces a **ratchet floor** from `test/floors.json` — a check count
244
+ that falls means a requirement stopped being required, which is how stripping
245
+ a pack's four widened sections used to make two gates *quieter* and still green.
246
+
247
+ One honest limit: the npx installer is checked by asserting its runtime bundle
248
+ walker exists, not by reading a file list — it has none by design. What proves
249
+ it ships the right files is CI, which installs the bundle through **both**
250
+ installers and `diff -r`s the result against the source, then builds all twelve
251
+ kits.
252
+
253
+ `test/scenarios.md` (T1–T19) is the behavioral harness: fresh subagents given a
237
254
  task, checking that the skill is discovered, applied and quoted correctly.
238
255
  Re-run the affected scenarios after any edit to `SKILL.md`, a pack or the
239
256
  reference.
package/bin/cli.js CHANGED
@@ -228,7 +228,11 @@ ${c("bold", "Default")}
228
228
  ${c("bold", "What it installs")}
229
229
  SKILL.md the agent-facing skill (discovery + principles)
230
230
  SHELEG_DESIGN.md the full reference (architecture, recipes, why it works)
231
+ MOTION_DOCTRINE.md whether to animate at all — frequency, easing, duration,
232
+ forbidden forms, the reduced-motion contract
231
233
  FIGMA_BRIDGE.md the design↔code contract (tokens ⇄ Figma variables)
234
+ DESIGN_SYNC_BRIDGE.md the Claude Design contract (what a pack sends, and
235
+ what does not cross)
232
236
  AI_PRODUCT_PATTERNS.md chat / agent / streaming surfaces (honest state)
233
237
  styles/ twelve style packs — instrument-console (dark console),
234
238
  editorial-luxury (warm editorial), workbench (light/dark
@@ -317,12 +321,13 @@ function main() {
317
321
  const rel = path.relative(cwd, targetDir) || ".";
318
322
  console.log(
319
323
  `\n${c("green", "✓")} ${c("bold", "SHELEG Design")} installed to ${c("blue", rel + "/")}\n` +
320
- ` ${c("dim", "SKILL.md")} the agent skill\n` +
321
- ` ${c("dim", "SHELEG_DESIGN.md")} the full reference\n` +
322
- ` ${c("dim", "styles/")} style packs + token CSS (instrument-console / editorial-luxury / workbench / briefing-room / atrium / orchard / field-notes / cyclorama / showroom / blueprint / prism / maquette)\n\n` +
324
+ ` ${c("dim", "SKILL.md")} the agent skill\n` +
325
+ ` ${c("dim", "SHELEG_DESIGN.md")} the full reference\n` +
326
+ ` ${c("dim", "MOTION_DOCTRINE.md")} whether to animate at all — read before any animation\n` +
327
+ ` ${c("dim", "styles/")} style packs + token CSS (instrument-console / editorial-luxury / workbench / briefing-room / atrium / orchard / field-notes / cyclorama / showroom / blueprint / prism / maquette)\n\n` +
323
328
  `Your Cursor / Claude agent can now discover the skill and build\n` +
324
- `cinematic, scroll-driven pages — or style product UI (dashboards,\n` +
325
- `admin, internal tools) from the workbench pack — on its principles.\n\n` +
329
+ `cinematic, scroll-driven pages — or style product UI (dashboards, admin,\n` +
330
+ `internal tools) from a standalone pack — on its principles.\n\n` +
326
331
  `${c("dim", "Docs: " + pkg.homepage)}\n`,
327
332
  );
328
333
  }
@@ -9,7 +9,8 @@ A page feels cinematic from a **single source of truth** (measured scroll
9
9
  position) driving **many cheap, layered, independently-degradable responses** —
10
10
  not from many animations. If the project has the full skill installed
11
11
  (`.cursor/skills/sheleg-design/`), read its `SKILL.md`, `SHELEG_DESIGN.md`,
12
- and the chosen style pack in `styles/` first (instrument-console — dark
12
+ `MOTION_DOCTRINE.md` (before any animation) and the chosen style pack in
13
+ `styles/` first (instrument-console — dark
13
14
  console; editorial-luxury — warm editorial; workbench — quiet light/dark
14
15
  product UI for dashboards and tools, used standalone without the cinematic
15
16
  motion layer; briefing-room — dark 16:9 presentation deck, standalone, slides
@@ -29,6 +30,40 @@ static iridescent wash over mono body copy; maquette — enterprise data
29
30
  infrastructure as a cream axonometric model on a near-black table);
30
31
  otherwise follow the contract below (self-contained on purpose).
31
32
 
33
+ ## Whether to animate at all — before how
34
+
35
+ Frequency decides before taste gets a vote. (Full doctrine:
36
+ `MOTION_DOCTRINE.md` in the installed skill.)
37
+
38
+ - Seen 100+ times a day — command palette, keyboard shortcut, tab switch:
39
+ **no animation, ever.** Never animate a keyboard-initiated action; it turns
40
+ instant into laggy and disconnects the result from the keypress.
41
+ - Tens of times a day — hover, list navigation, inline toggles: remove it or
42
+ cut it to the floor. Occasional (modals, drawers, toasts): standard. Rare or
43
+ first-time (onboarding, empty-to-filled): delight is allowed.
44
+ - Every animation answers "why does this move?" in one sentence — spatial
45
+ consistency, state indication, feedback, explanation, or preventing a jarring
46
+ cut. "It looked cool" is not an answer; if you cannot write the sentence,
47
+ delete the animation.
48
+ - **`ease-in` is banned in UI.** It starts slow, in the exact moment the user is
49
+ watching hardest. Entering or leaving → `ease-out`; moving or morphing on
50
+ screen → `ease-in-out`; hover or colour change → `ease`; constant motion →
51
+ `linear`. Curves: `--ease-out: cubic-bezier(.23,1,.32,1)`,
52
+ `--ease-in-out: cubic-bezier(.77,0,.175,1)`,
53
+ `--ease-drawer: cubic-bezier(.32,.72,0,1)`.
54
+ - **UI motion stays under 300 ms.** Button press 100–160ms · tooltip 125–200ms ·
55
+ dropdown 150–250ms · modal/drawer 200–500ms. Marketing and scrollytelling are
56
+ deliberately longer.
57
+ - Never animate a property that triggers layout (`width`, `height`, `top`,
58
+ `left`, `padding`, `margin`, `gap`, `font-size`). Never a bare scroll
59
+ listener, never `requestAnimationFrame` writing component state, never
60
+ `backdrop-filter` or grain on a scrolling container, never a left-behind
61
+ `will-change`, never two marquees.
62
+ - **Reduced motion is a contract, not a feature.** Anything beyond a colour
63
+ change honours `prefers-reduced-motion: reduce`; loops, parallax and springs
64
+ collapse to static or instant, never to "slower". Shipping an animation
65
+ without that branch is a bug, not a polish item.
66
+
32
67
  ## Five principles, in order
33
68
 
34
69
  1. **One clock.** All motion derives from one measured scroll state in one
@@ -119,7 +119,7 @@
119
119
  --track-mono: 0.1em;
120
120
  --track-mono-sm: 0.07em;
121
121
 
122
- /* ---- Elevation: three shadows, one job each -------------------------- */
122
+ /* ---- Elevation: four shadows, one job each --------------------------- */
123
123
  --shadow-panel: 12px 32px 80px 0 rgba(42, 43, 47, 0.1); /* the hero panel */
124
124
  --shadow-lift: 0 4px 30px 0 rgba(0, 0, 0, 0.1); /* a card pulled forward */
125
125
  --shadow-cta: 0 2px 12px 0 rgba(0, 0, 0, 0.1); /* a button on photography */
@@ -175,7 +175,6 @@
175
175
  --marquee-cycle: 0s;
176
176
  }
177
177
  }
178
-
179
178
  /* ── components ── */
180
179
 
181
180
  /* Everything below consumes var(--…) only. Colour never appears as a literal:
@@ -32,8 +32,8 @@
32
32
  quietly changes a value it claims to have measured is worse than one that
33
33
  changes it and says so. Pure black is 21:1 on the sheet; this is 17.74:1,
34
34
  and both are far above any floor that matters. */
35
- --ink: #111827; /* 17.74:1 on --bg */
36
- --ink-soft: #4b5563; /* 7.5:1 — secondary copy, safe as body */
35
+ --ink: #111827; /* 17.15:1 on --bg */
36
+ --ink-soft: #4b5563; /* 7.31:1 on --bg — secondary copy, safe as body */
37
37
  --ink-faint: #9ca3af; /* 2.5:1 — RULES AND MARKS ONLY, never text */
38
38
  --on-ink: #ffffff;
39
39
 
@@ -15,7 +15,7 @@
15
15
  --accent-deep: #2f5e47;
16
16
  --accent-weak: rgba(63, 125, 95, 0.12); /* tint fill (badges, wash) */
17
17
  --accent-med: rgba(63, 125, 95, 0.34); /* hairline / border tint */
18
- --accent-ink: #fbf6ec; /* text ON the accent — 6.1:1 on --accent-deep; large text only on --accent */
18
+ --accent-ink: #fbf6ec; /* text ON the accent — 6.93:1 on --accent-deep; 4.52:1 on --accent, AA by 0.02, so large text only there */
19
19
  --accent-on-dark: #9fd9bc;
20
20
  --terra: #b5623f;
21
21
  --red: #a83a2b;
@@ -51,8 +51,11 @@
51
51
  background-color: var(--paper);
52
52
  color: var(--ink);
53
53
  color-scheme: light;
54
- }
55
54
 
55
+ /* Core role vocabulary — every pack resolves --bg, --ink and --accent, so a
56
+ cross-pack document can name them truthfully. Alias, never a new colour. */
57
+ --bg: var(--paper); /* role alias -> --paper, this pack's field */
58
+ }
56
59
  /* ── components ── */
57
60
 
58
61
  /* Everything below consumes var(--…) only. The token block above is the whole
@@ -231,6 +231,12 @@
231
231
 
232
232
  background-color: var(--bg);
233
233
  color: var(--ink);
234
+
235
+ /* Core role vocabulary — every pack resolves --bg, --ink and --accent, so a
236
+ cross-pack document can name them truthfully. Alias, never a new colour. */
237
+ /* @role accent: --brand — this pack's ONE functional accent. It is not
238
+ aliased to --accent because that would make it a status peer, and the
239
+ palette gate measures it 5.5 from --danger (hard floor 10). */
234
240
  }
235
241
 
236
242
  /* The dark twin. Warm, one family, and clean on contrast throughout —
@@ -41,8 +41,11 @@
41
41
  background-color: var(--base);
42
42
  color: var(--ink);
43
43
  color-scheme: dark;
44
- }
45
44
 
45
+ /* Core role vocabulary — every pack resolves --bg, --ink and --accent, so a
46
+ cross-pack document can name them truthfully. Alias, never a new colour. */
47
+ --bg: var(--base); /* role alias -> --base, this pack's field */
48
+ }
46
49
  /* ── components ── */
47
50
 
48
51
  /* Everything below consumes var(--…) only. Colour never appears as a literal.
@@ -30,7 +30,7 @@
30
30
  warm object on a cold page. */
31
31
  --ink: #fff9f4; /* 17.49:1 on --bg */
32
32
  --ink-soft: #b3b5c1; /* 8.95:1 — secondary copy, comfortably AA */
33
- --ink-faint: #8a8f98; /* 5.0:1 — captions and leader lines */
33
+ --ink-faint: #8a8f98; /* 5.62:1 on --bg — captions and leader lines */
34
34
  --on-ink: #151515;
35
35
 
36
36
  /* ---- Lines ------------------------------------------------------------ */
@@ -107,6 +107,12 @@
107
107
  background-color: var(--bg);
108
108
  color: var(--ink);
109
109
  color-scheme: light;
110
+
111
+ /* Core role vocabulary — every pack resolves --bg, --ink and --accent, so a
112
+ cross-pack document can name them truthfully. Alias, never a new colour. */
113
+ /* @role accent: --cta — this pack's ONE functional accent. It is not
114
+ aliased to --accent because that would make it a status peer, and the
115
+ palette gate measures it 5.5 from --danger (hard floor 10). */
110
116
  }
111
117
 
112
118
  /* The reference ships NO reduced-motion branch at all. This one is mandatory:
@@ -120,7 +126,6 @@
120
126
  --reveal-floor: 1;
121
127
  }
122
128
  }
123
-
124
129
  /* ── components ── */
125
130
 
126
131
  /* Everything below consumes var(--…) only. Colour never appears as a literal:
@@ -25,8 +25,8 @@
25
25
 
26
26
  /* ---- Ink -------------------------------------------------------------- */
27
27
  --ink: #1c1d1f; /* 16.87:1 on --bg */
28
- --ink-2: #232529; /* 15.9:1 — secondary headings */
29
- --ink-soft: #505967; /* 7.7:1 — captions that must actually be read */
28
+ --ink-2: #232529; /* 15.35:1 on --bg — secondary headings */
29
+ --ink-soft: #505967; /* 7.08:1 on --bg — captions that must actually be read */
30
30
  --on-ink: #ffffff;
31
31
 
32
32
  /* [CORRECTION] The reference names #a4adba "caption-foreground" and it
@@ -11,7 +11,7 @@
11
11
  --border-strong: #d7dce4;
12
12
  --accent: #2f6feb;
13
13
  --accent-weak: #eaf0fe;
14
- --accent-ink: #ffffff; /* text ON the accent — 5.0:1 on --accent */
14
+ --accent-ink: #ffffff; /* text ON the accent — 4.57:1 on --accent */
15
15
  --ok: #1a7f37;
16
16
  --ok-weak: #e6f4ea;
17
17
  --warn: #9a6700;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sheleg-design-skill",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "Design taste as an installable agent skill. Cinematic scroll-driven landing pages built on one scroll clock and layered degrade-to-calm motion, a motion doctrine that decides whether to animate before it decides how, three calibration dials, and twelve locked style packs with ready-made design tokens — instrument-console, editorial-luxury, workbench, briefing-room, atrium, orchard, field-notes, cyclorama, showroom, blueprint, prism and maquette. Colour, slop and fork-reciprocity gates run as scripts, not opinions. Works with Cursor, Claude Code and any agent that reads a SKILL.md.",
5
5
  "bin": {
6
6
  "sheleg-design-skill": "bin/cli.js"
@@ -19,12 +19,12 @@
19
19
  "node": ">=16"
20
20
  },
21
21
  "scripts": {
22
- "test": "python3 test/validate.py && python3 test/validate_palette.py && python3 test/sloplint.py && node --check bin/cli.js",
22
+ "test": "python3 test/validate.py && python3 test/validate_palette.py && python3 test/sloplint.py && node --check bin/cli.js && npm run selftest",
23
23
  "validate": "python3 test/validate.py && python3 test/validate_palette.py && python3 test/sloplint.py",
24
24
  "smoke": "node bin/cli.js --help",
25
25
  "palette": "python3 test/validate_palette.py",
26
26
  "sloplint": "python3 test/sloplint.py",
27
- "selftest": "python3 test/validate_palette.py --self-test && python3 test/sloplint.py --self-test"
27
+ "selftest": "python3 test/validate.py --self-test && python3 test/validate_palette.py --self-test && python3 test/sloplint.py --self-test"
28
28
  },
29
29
  "keywords": [
30
30
  "skill",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "sheleg-design",
3
3
  "displayName": "SHELEG Design",
4
- "description": "SHELEG Design methodology: cinematic scroll-driven landing pages (single scroll clock, layered degrade-to-calm motion, WebGL particle formations) plus pluggable visual style packs — instrument-console (dark console), editorial-luxury (warm editorial), workbench (light/dark product UI for dashboards and tools). Ships the sheleg-design skill, the architecture reference, style packs with ready-made token CSS, and the /sheleg-design command.",
5
- "version": "1.9.0",
4
+ "description": "SHELEG Design methodology: cinematic scroll-driven landing pages (single scroll clock, layered degrade-to-calm motion, WebGL particle formations), a motion doctrine that decides whether to animate before it decides how, and twelve pluggable visual style packs — instrument-console (dark console), editorial-luxury (warm editorial), workbench (light/dark product UI for dashboards and tools), briefing-room (dark 16:9 deck), atrium (warm consumer health), orchard (friendly consumer biotech), field-notes (warm paper for dev tools sold on auditability), cyclorama (a pastel field on a 32s cycle), showroom (the product as the exhibit), blueprint (a drawing sheet, zero radius), prism (one iridescent wash over mono body), maquette (cream axonometric models on a dark table). Ships the sheleg-design skill, the architecture reference, the motion doctrine, the Figma and Claude Design bridges, AI-surface patterns, style packs with ready-made token CSS, and the /sheleg-design command.",
5
+ "version": "1.11.0",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -5,14 +5,30 @@ argument-hint: "[what to build or upgrade]"
5
5
 
6
6
  Invoke the `sheleg-design` skill and apply it to the current request.
7
7
 
8
- - Read the skill's SKILL.md, then its full reference `SHELEG_DESIGN.md`
9
- (same directory) before designing anything.
10
- - Task: $ARGUMENTS — if empty, ask what page or section to build/upgrade,
11
- then proceed per the skill's "How to Apply" order. If the arguments name
12
- a style pack (instrument-console | editorial-luxury | workbench), use
13
- that pack without re-asking; otherwise pick per the SKILL.md table.
8
+ - Read the skill's `SKILL.md` first, then — **before designing anything** — its
9
+ full reference `SHELEG_DESIGN.md` and, **before any animation**,
10
+ `MOTION_DOCTRINE.md` (same directory). `SHELEG_DESIGN.md` says how motion is
11
+ built; the doctrine says whether to build it at all. Skipping the second is
12
+ how a keyboard path ends up animated.
13
+ - Task: $ARGUMENTS — if empty, ask what page or section to build/upgrade.
14
+ - **If the arguments name a style pack, use that pack without re-asking.** The
15
+ twelve are `instrument-console`, `editorial-luxury`, `workbench`,
16
+ `briefing-room`, `atrium`, `orchard`, `field-notes`, `cyclorama`, `showroom`,
17
+ `blueprint`, `prism`, `maquette`. Otherwise pick per the `SKILL.md` table,
18
+ and say which pack you picked and why before you build.
19
+ - **Set the three dials out loud before any layout exists** — `DESIGN_VARIANCE`,
20
+ `MOTION_INTENSITY`, `VISUAL_DENSITY`, with one line of reasoning. The
21
+ `SKILL.md` "Reading them off the brief" table gives the starting values;
22
+ baseline is `7 / 5 / 4`. Announcing them and then drifting is the failure this
23
+ step exists to prevent.
24
+ - Then proceed per the skill's "How to Apply" order.
14
25
  - Product UI (dashboard, admin, internal/dev tool, design tokens, theming):
15
- apply `styles/workbench.md` and its token CSS standalone — no scroll
16
- clock, no particle field, no cinematic motion.
26
+ apply a **standalone** pack and its token CSS — no scroll clock, no particle
27
+ field, no cinematic motion. `workbench` is the default; `field-notes` is the
28
+ fork for a developer product sold on auditability, and `briefing-room` for a
29
+ deck published as a page. The packs state the distinction; read it rather than
30
+ defaulting.
31
+ - AI surfaces (chat, agent runs, streaming, generated content): read
32
+ `AI_PRODUCT_PATTERNS.md` as well.
17
33
  - Follow the skill's non-negotiables (Quick Reference table) and ship every
18
34
  layer's reduced-motion/fallback branch in the same commit.
@@ -58,6 +58,13 @@ The pack is the primary reference type; the other three feed it rather than bypa
58
58
  - **Names are the interface.** The spine — the same six component names and props in
59
59
  every pack — exists so switching packs swaps identity, not API. This is the
60
60
  component-level form of a lesson the token layer already learned the hard way.
61
+ The six are `Button`, `Card`, `Chip`, `Stat`, `Heading` and `Rule`, and their
62
+ `*Props` bodies are byte-identical across all twelve kits once comments are
63
+ stripped. Everything a kit ships beyond them is that pack's signature —
64
+ `Specimen` in `showroom`, `RegistrationMarks` in `blueprint`, `ModelBlock` in
65
+ `maquette` — and belongs to it alone. Until 1.11.0 this paragraph asserted the
66
+ count and named none of the six, which left a reader with a number and no way
67
+ to check a delivered kit against it.
61
68
 
62
69
  ## 3. Figma — one border at a time
63
70
 
@@ -91,12 +98,13 @@ hierarchy, content order. It never answers what it looks like.
91
98
 
92
99
  ## 5. Live-site extraction — the pack first, the sync second
93
100
 
94
- Three packs in this skill were extracted from production sites by reading their live
101
+ Most packs in this skill were extracted from production sites by reading their live
95
102
  computed styles. That is a legitimate way to *make a pack* and never a way to make a
96
103
  kit.
97
104
 
98
- **The order is the rule:** extraction lands in a pack first — all nine headings and a
99
- `tokens/<pack>.css` — and only a pack syncs. A site's raw values never reach
105
+ **The order is the rule:** extraction lands in a pack first — **the full thirteen
106
+ headings** (plus `## Motion flavor` if it is cinematic) and a `tokens/<pack>.css` —
107
+ and only a pack syncs. A site's raw values never reach
100
108
  claude.ai/design, because a kit assembled straight from a scrape carries that site's
101
109
  accidents, its dead ends and its one-off hexes, and the design agent will treat every
102
110
  one of them as a decision.
@@ -116,7 +124,14 @@ and it is a contract rather than a gap:
116
124
  half of a pack**, and saying so out loud is what stops an agent from inventing
117
125
  motion to fill the silence.
118
126
  - **Reduced-motion branches have nothing to attach to** once motion is gone, so they
119
- do not ship either. They are not missing; they are meaningless there.
127
+ do not ship either. They are not missing; they are meaningless there. **This
128
+ governs components, not the token layer.** §1 requires `tokens/<pack>.css` be
129
+ copied byte for byte, and several packs' token layers carry a
130
+ `@media (prefers-reduced-motion: reduce)` block that zeroes their duration
131
+ tokens — so a verbatim copy ships one, and that is correct. Verbatim wins,
132
+ because it is the half a machine can check; this bullet is about the branches a
133
+ component would otherwise carry. Stated because a reader following both rules
134
+ literally found them in collision and had to adjudicate alone.
120
135
  - **Anything a component cannot render itself.** If a preview needs markup the
121
136
  component does not produce, the fix is the composition — props, children, a
122
137
  provider — never a hand-written imitation.