@ericrisco/rsc 3.1.4 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -7
- package/manifest.json +17 -68
- package/package.json +6 -1
- package/scripts/design-upstream.js +92 -0
- package/scripts/doctor.js +0 -24
- package/scripts/lib/default-skill-floor.js +5 -1
- package/scripts/lib/domains.js +2 -2
- package/scripts/lib/recommend.js +1 -3
- package/scripts/lib/retired-skills.js +7 -1
- package/skills/design/IMPECCABLE-LICENSE.txt +191 -0
- package/skills/design/SKILL.md +79 -328
- package/skills/design/THIRD_PARTY.md +26 -0
- package/skills/design/engine/LICENSE +21 -0
- package/skills/design/engine/RUN.md +515 -0
- package/skills/design/engine/UPSTREAM.json +4 -0
- package/skills/design/engine/assets/app.css +216 -0
- package/skills/design/engine/assets/base.css +105 -0
- package/skills/design/engine/assets/base.js +37 -0
- package/skills/design/engine/assets/charts.js +617 -0
- package/skills/design/engine/assets/scenes/stage.css +28 -0
- package/skills/design/engine/assets/scenes/stage.js +133 -0
- package/skills/design/engine/library/app.json +1327 -0
- package/skills/design/engine/library/directions.json +1078 -0
- package/skills/design/engine/library/heroes.json +1086 -0
- package/skills/design/engine/library/motions.json +92 -0
- package/skills/design/engine/library/palettes.json +1485 -0
- package/skills/design/engine/library/photos.json +7240 -0
- package/skills/design/engine/library/sections.json +4429 -0
- package/skills/design/engine/library/sites.json +8350 -0
- package/skills/design/engine/library/type.json +2024 -0
- package/skills/design/engine/references/app-screens.md +1199 -0
- package/skills/design/engine/references/colour.md +141 -0
- package/skills/design/engine/references/copy.md +177 -0
- package/skills/design/engine/references/critique.md +182 -0
- package/skills/design/engine/references/imagery.md +791 -0
- package/skills/design/engine/references/layout.md +292 -0
- package/skills/design/engine/references/motion.md +980 -0
- package/skills/design/engine/references/research.md +356 -0
- package/skills/design/engine/references/scenes.md +174 -0
- package/skills/design/engine/references/tells.md +115 -0
- package/skills/design/engine/references/type.md +170 -0
- package/skills/design/engine/scripts/assets.mjs +865 -0
- package/skills/design/engine/scripts/draw.mjs +584 -0
- package/skills/design/engine/scripts/inspect.mjs +303 -0
- package/skills/design/engine/scripts/lib/app-draw.mjs +203 -0
- package/skills/design/engine/scripts/lib/cdp.mjs +248 -0
- package/skills/design/engine/scripts/lib/probe.mjs +909 -0
- package/skills/design/engine/scripts/lib/rules.mjs +243 -0
- package/skills/design/engine/scripts/lint.mjs +119 -0
- package/skills/design/engine/scripts/scenes.mjs +124 -0
- package/skills/design/evals/cases.yaml +35 -46
- package/skills/design/references/design-md.md +49 -0
- package/skills/design/references/finish-review.md +46 -0
- package/skills/design/references/modes.md +51 -0
- package/skills/expo/SKILL.md +3 -4
- package/skills/marketing/references/landing-copy.md +2 -2
- package/skills/react/SKILL.md +2 -2
- package/skills/react-native/SKILL.md +3 -3
- package/skills/suggest/SKILL.md +12 -8
- package/skills/suggest/evals/cases.yaml +6 -0
- package/skills/swift-ios/SKILL.md +1 -1
- package/skills/ui-engineering/SKILL.md +3 -4
- package/skills/ui-engineering/evals/cases.yaml +2 -2
- package/skills/variant-explorer/SKILL.md +4 -4
- package/skills/variant-explorer/evals/cases.yaml +1 -1
- package/targets/clone-bootstrap.mjs +1 -1
- package/scripts/lib/design-identity.js +0 -117
- package/scripts/lib/starting-point.js +0 -314
- package/skills/design/evals/README.md +0 -53
- package/skills/design/references/ai-tells.md +0 -75
- package/skills/design/references/brand-grounding.md +0 -197
- package/skills/design/references/copywriting-frameworks.md +0 -138
- package/skills/design/references/design-systems.md +0 -49
- package/skills/design/references/inspiration-sources.md +0 -96
- package/skills/design/references/landing-anatomy-and-cro.md +0 -202
- package/skills/design/references/motion-and-interaction.md +0 -232
- package/skills/design/references/research-method.md +0 -154
- package/skills/design/references/signature-and-craft.md +0 -148
- package/skills/design/references/starting-point.md +0 -75
- package/skills/design/references/trends-2026.md +0 -80
- package/skills/design/references/visual-system.md +0 -237
- package/skills/design/scripts/verify.sh +0 -357
- package/skills/design-dna/PROMPT.md +0 -211
- package/skills/design-dna/SKILL.md +0 -162
- package/skills/design-dna/design-dna.schema.json +0 -230
- package/skills/design-dna/evals/README.md +0 -64
- package/skills/design-dna/evals/cases.yaml +0 -68
- package/skills/design-dna/references/method.md +0 -436
- package/skills/design-dna/scripts/emit.py +0 -164
- package/skills/design-dna/templates/PROMPT.md.tmpl +0 -42
- package/skills/design-dna/templates/SKILL.md.tmpl +0 -42
- package/skills/design-dna/templates/check.py.tmpl +0 -143
- package/skills/design-loop/SKILL.md +0 -160
- package/skills/design-loop/evals/README.md +0 -56
- package/skills/design-loop/evals/cases.yaml +0 -60
- package/skills/motion-craft/SKILL.md +0 -125
- package/skills/motion-craft/evals/cases.yaml +0 -38
- package/skills/motion-craft/scripts/verify.sh +0 -75
|
@@ -1,56 +1,45 @@
|
|
|
1
1
|
skill: design
|
|
2
2
|
|
|
3
3
|
should_trigger:
|
|
4
|
-
- prompt: "Design a landing page for our new analytics SaaS
|
|
5
|
-
why: "
|
|
6
|
-
- prompt: "Our homepage looks generic, like every other AI-generated startup site.
|
|
7
|
-
why: "
|
|
8
|
-
- prompt: "
|
|
9
|
-
why: "
|
|
10
|
-
- prompt: "
|
|
11
|
-
why: "
|
|
12
|
-
- prompt: "
|
|
13
|
-
why: "A
|
|
14
|
-
- prompt: "
|
|
15
|
-
why: "
|
|
16
|
-
- prompt: "Add a bento-grid features section to our marketing site that doesn't look like a template."
|
|
17
|
-
why: "'bento section' is an explicit named trigger; involves layout/composition for a marketing surface."
|
|
4
|
+
- prompt: "Design a landing page for our new analytics SaaS."
|
|
5
|
+
why: "A public page to design from scratch is the page run's core case (Persuade mode)."
|
|
6
|
+
- prompt: "Our homepage looks generic, like every other AI-generated startup site. Make it look designed."
|
|
7
|
+
why: "'Looks generic / AI-made' is named in the description; the skill exists to replace the model's default."
|
|
8
|
+
- prompt: "Hazme la web de un restaurante de mi pueblo, que no parezca una plantilla."
|
|
9
|
+
why: "A local business page in Spanish; the inventory of the subject and real pictures are exactly what the run forces."
|
|
10
|
+
- prompt: "Rediseña el dashboard de facturación, que se ve feo y desordenado."
|
|
11
|
+
why: "An app screen redesign (Operate mode) follows the app-screen run with its own draw and inspector."
|
|
12
|
+
- prompt: "Review this portfolio page and tell me the three changes that would improve it most."
|
|
13
|
+
why: "A review of an existing page: record the before in the browser, critique the screenshots, stop at findings."
|
|
14
|
+
- prompt: "Restyle our docs site so it stops looking like every other docs template."
|
|
15
|
+
why: "Read mode: the style owns the frame while the reading column stays calm."
|
|
18
16
|
|
|
19
17
|
should_not_trigger:
|
|
20
|
-
- prompt: "Write the
|
|
21
|
-
route_to: "
|
|
22
|
-
why: "
|
|
23
|
-
- prompt: "
|
|
18
|
+
- prompt: "Write the hero headline, offer and CTA copy for our pricing page."
|
|
19
|
+
route_to: "landing-copy"
|
|
20
|
+
why: "The words on a conversion page belong to landing-copy; design builds the page around them."
|
|
21
|
+
- prompt: "Where should the filter state live, in the URL or in the component, and how do we handle loading and errors?"
|
|
22
|
+
route_to: "ui-engineering"
|
|
23
|
+
why: "How interface is built (state, boundaries, async states) is ui-engineering, not visual design."
|
|
24
|
+
- prompt: "Make our web app pass WCAG 2.2 AA: fix the axe violations and keyboard traps."
|
|
25
|
+
route_to: "accessibility"
|
|
26
|
+
why: "Conformance remediation is the accessibility skill's job."
|
|
27
|
+
- prompt: "Create our logo brief and a full brand book with print colours."
|
|
28
|
+
route_to: "brand-identity"
|
|
29
|
+
why: "A brand system for every medium is brand-identity; design consumes it with --keep palette,type."
|
|
30
|
+
- prompt: "Set up Next.js App Router routing and server actions for these pages."
|
|
24
31
|
route_to: "nextjs"
|
|
25
|
-
why: "
|
|
26
|
-
- prompt: "Build a daily-use internal ops dashboard for our support team to triage tickets fast — pure data tables, no marketing."
|
|
27
|
-
route_to: "none"
|
|
28
|
-
why: "Dense internal operational tooling is explicitly a do-NOT-force-a-landing case; the skill says not to paint a marketing skin on a daily-use tool. Routes to product judgment, not a sibling."
|
|
29
|
-
- prompt: "Mirror our brand colors and typography into the Flutter mobile app's theme."
|
|
30
|
-
route_to: "flutter"
|
|
31
|
-
why: "Translating brand tokens into a Flutter app is the flutter sibling's job, not web UI design."
|
|
32
|
-
- prompt: "Implement an iOS 26 SwiftUI Liquid Glass material for this native settings panel."
|
|
33
|
-
route_to: "none"
|
|
34
|
-
why: "Native iOS Liquid Glass is the external liquid-glass-design reference; this skill ships only the web glass approximation, so it should decline/defer (no in-repo sibling)."
|
|
35
|
-
- prompt: "Help me wire up the spring physics and AnimatePresence layout animations for this modal in Framer Motion."
|
|
36
|
-
route_to: "none"
|
|
37
|
-
why: "Deep motion-code mechanics (springs, AnimatePresence internals) are explicitly deferred to the external motion-ui references; design only sets motion intent + budget."
|
|
32
|
+
why: "Framework build mechanics are nextjs."
|
|
38
33
|
|
|
39
34
|
capability:
|
|
40
|
-
- scenario: "
|
|
35
|
+
- scenario: "Asked to build a landing page for a bakery with no brand and no photographs."
|
|
41
36
|
must_include:
|
|
42
|
-
- "
|
|
43
|
-
- "
|
|
44
|
-
- "
|
|
45
|
-
- "
|
|
46
|
-
- "
|
|
47
|
-
|
|
48
|
-
- "Benefit-led, specific copy that avoids the ban-list (revolutionary, seamless, game-changer, unlock, supercharge, elevate, etc.)."
|
|
49
|
-
- scenario: "User asks: 'Here's our current pricing page — do a design review and tell me how good it actually is.'"
|
|
37
|
+
- "inventory of eight to twelve things only this client has"
|
|
38
|
+
- "draw.mjs deals three directions; one is chosen against the inventory with a written reason"
|
|
39
|
+
- "an idea sentence that fails the competitor test, and one live thing"
|
|
40
|
+
- "at least four real pictures found with assets.mjs and credited"
|
|
41
|
+
- "inspect.mjs at 1440, 768 and 390 with zero FAIL before reporting"
|
|
42
|
+
- scenario: "The machine has no Chrome and Node 20."
|
|
50
43
|
must_include:
|
|
51
|
-
- "
|
|
52
|
-
- "
|
|
53
|
-
- "For each dimension scoring below 8, gives a concrete actionable fix (e.g. exact spacing/token change), not a vague 'improve spacing'."
|
|
54
|
-
- "Checks copy against the ban-list and flags hype/vague value props that fail the 5s test."
|
|
55
|
-
- "Flags any transition: all, magic hex/px, cards-in-cards, or purple->blue everything gradient as defects, not preferences."
|
|
56
|
-
- "Ties findings back to the brand study / cited trend source where the bar is set, rather than asserting taste."
|
|
44
|
+
- "runs lint.mjs and critiques screenshots from another browser tool"
|
|
45
|
+
- "the report says 'inspector not run' with the reason and claims no gate pass"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# DESIGN.md: the record of the system
|
|
2
|
+
|
|
3
|
+
Adapted from impeccable's `document` by Paul Bakaus (Apache-2.0), which follows the open
|
|
4
|
+
`design.md` format. Rewritten and shortened.
|
|
5
|
+
|
|
6
|
+
The point: the next edit, the next session and the next tool keep the look instead of drifting back
|
|
7
|
+
to the model's default. Write it **after** the build, from what was actually built and measured,
|
|
8
|
+
never before. A rulebook written ahead of the build gets defended against reality.
|
|
9
|
+
|
|
10
|
+
## Where and when
|
|
11
|
+
|
|
12
|
+
- `DESIGN.md` at the project root, committed with the code.
|
|
13
|
+
- Written when a surface creates or replaces the visual system. Extending an existing surface reads
|
|
14
|
+
it and does not rewrite it.
|
|
15
|
+
- If `02-DOCS/wiki/brand/` exists, `DESIGN.md` uses the brand's colours and faces and names that
|
|
16
|
+
file as its source.
|
|
17
|
+
|
|
18
|
+
## Shape
|
|
19
|
+
|
|
20
|
+
YAML front matter holds the tokens; the body explains them.
|
|
21
|
+
|
|
22
|
+
```markdown
|
|
23
|
+
---
|
|
24
|
+
name: <product>
|
|
25
|
+
description: <one line: the idea sentence>
|
|
26
|
+
colors:
|
|
27
|
+
ground: "#…"
|
|
28
|
+
ink: "#…"
|
|
29
|
+
accent: "#…"
|
|
30
|
+
field: "#…"
|
|
31
|
+
typography:
|
|
32
|
+
display: { fontFamily: "…", fontWeight: 600, letterSpacing: "-0.03em", lineHeight: 0.95 }
|
|
33
|
+
text: { fontFamily: "…", fontSize: "18px", lineHeight: 1.5 }
|
|
34
|
+
rounded: { button: "0px", media: "0px" }
|
|
35
|
+
spacing: { margin: "24px", section: "200px" }
|
|
36
|
+
direction: { id: "<dealt id>", seed: <n> }
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Overview the idea, the mode, the direction and why it was chosen
|
|
40
|
+
## Colors roles and proportions (one ground, one ink, one accent, fields)
|
|
41
|
+
## Typography the scale actually used, tracking, measure
|
|
42
|
+
## Layout grid, outer margins, section rhythm, the phone composition
|
|
43
|
+
## Imagery sources, crops, treatment, where credits live
|
|
44
|
+
## Motion the signature move and the entrance recipe
|
|
45
|
+
## Components buttons, navigation, the live thing, footer
|
|
46
|
+
## Do's and Don'ts the house rules this project relies on, plus any `--allow` and its reason
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Values come from the built CSS and the inspector's measurements, not from memory.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# The fresh review
|
|
2
|
+
|
|
3
|
+
Adapted from impeccable's finish reviewer by Paul Bakaus (Apache-2.0); rewritten and shortened.
|
|
4
|
+
|
|
5
|
+
The builder believes its own page. The review runs **outside** the build: a fresh subagent with no
|
|
6
|
+
history of this conversation, so it does not inherit the builder's framing or optimism. Without
|
|
7
|
+
subagents, step fully out of the build and run the same checks yourself, and say in the report that
|
|
8
|
+
the review was not independent.
|
|
9
|
+
|
|
10
|
+
## The packet
|
|
11
|
+
|
|
12
|
+
Hand it only this:
|
|
13
|
+
|
|
14
|
+
- the original request and the user's answers;
|
|
15
|
+
- the screenshots from `.taste-skill/inspect/` at every width (the reviewer has no browser);
|
|
16
|
+
- the last `inspect.mjs` result;
|
|
17
|
+
- the direction sheet (`draw.mjs --show`), the idea sentence and the live thing;
|
|
18
|
+
- the paths of `../engine/RUN.md` (house rules) and `../engine/references/critique.md`.
|
|
19
|
+
|
|
20
|
+
## The checks, in order
|
|
21
|
+
|
|
22
|
+
0. **Evidence.** Every width captured, no blank or half-loaded screenshot, content where the
|
|
23
|
+
filename says. If one fails, the answer is `recapture` and nothing else.
|
|
24
|
+
1. **First screen.** Within five seconds: what is this, why does it matter, what do I do?
|
|
25
|
+
2. **The idea.** Is the idea sentence visible on the page, in every section, and does it fail the
|
|
26
|
+
competitor test (would it work for the nearest competitor)?
|
|
27
|
+
3. **The direction.** Was the dealt direction built, or did the build drift back to the layout the
|
|
28
|
+
model would have made anyway?
|
|
29
|
+
4. **Substance.** Real pictures, full content, no screen that is mostly empty ground.
|
|
30
|
+
5. **Truth.** No invented customers, quotes, numbers or logos. Sample content marked.
|
|
31
|
+
6. **Floor.** The house rules in `../engine/RUN.md`, plus what screenshots show and code hides:
|
|
32
|
+
states (hover, focus, loading, empty, error), themed selection and focus rings, text that fits.
|
|
33
|
+
|
|
34
|
+
## The four words
|
|
35
|
+
|
|
36
|
+
The first line of the answer is exactly one of these. The word follows from the checks:
|
|
37
|
+
|
|
38
|
+
- `recapture`: the evidence failed, not the page. Capture again, then a full review.
|
|
39
|
+
- `rebuild`: the focal element or the direction itself is wrong. Re-derive it; patches will not do.
|
|
40
|
+
- `fix`: an ordered list of material fixes, at most eight, most important first.
|
|
41
|
+
- `ship`: nothing material remains.
|
|
42
|
+
|
|
43
|
+
Then: `fixes` (when `fix`) and `keep`, one line naming what must not be diluted while fixing.
|
|
44
|
+
Apply the fixes in one batch, run the gate again, and send the new screenshots back for a verdict
|
|
45
|
+
on each fix: resolved, partial or unresolved. Two rounds at most. A partial or unresolved fix
|
|
46
|
+
never becomes `ship`. Report the reviewer's word as it was given.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# The four modes
|
|
2
|
+
|
|
3
|
+
Adapted from impeccable by Paul Bakaus (Apache-2.0); rewritten and shortened. The mode names what
|
|
4
|
+
the visitor's success looks like on this surface. Pick it from the surface, never the product: a
|
|
5
|
+
developer tool's landing page is Persuade, a fashion house's docs are Read.
|
|
6
|
+
|
|
7
|
+
## Persuade
|
|
8
|
+
|
|
9
|
+
The visitor decides and acts. The design is what they judge.
|
|
10
|
+
|
|
11
|
+
- The first screen makes the offer clear and shows **the action visitors came to take, working**: a
|
|
12
|
+
flight search, open appointment slots, add to cart. A button that points somewhere else is not it.
|
|
13
|
+
- The subject's world carries the page; it is never painted over it as a poster with no working parts.
|
|
14
|
+
- Refuse both ends: the poster, and the stock product page (headline, subline, button, a row of
|
|
15
|
+
equal cards; or the split hero with a badge row under it).
|
|
16
|
+
|
|
17
|
+
## Experience
|
|
18
|
+
|
|
19
|
+
The visitor is inside the work: portfolio, gallery, showcase. The work leads from the first
|
|
20
|
+
viewport and the interface recedes. Same page run as Persuade.
|
|
21
|
+
|
|
22
|
+
## Operate
|
|
23
|
+
|
|
24
|
+
The visitor completes a task. Someone who uses tools like this should know where everything is
|
|
25
|
+
before they notice the style.
|
|
26
|
+
|
|
27
|
+
- The direction lends four things only: **type, palette, density and one signature move** (service
|
|
28
|
+
health drawn as a transit map, a schedule in a timetable's column rhythm). Never the layout, the
|
|
29
|
+
navigation model or the controls.
|
|
30
|
+
- Every control is the standard one the visitor already knows. No costume of a terminal, an
|
|
31
|
+
instrument bezel or ledger paper.
|
|
32
|
+
- Colour does real jobs: a committed shell, state colours, data series, selection. A grey screen
|
|
33
|
+
with one accent is the category default without its polish.
|
|
34
|
+
- Realistic data with units and one state worth seeing (an alert, a degraded service, an empty
|
|
35
|
+
filter). Never grey placeholder bars.
|
|
36
|
+
- The bar is the cleanest product in its category; the signature move adds to that, never replaces it.
|
|
37
|
+
|
|
38
|
+
The run, rules and checks for these screens: `../engine/references/app-screens.md`
|
|
39
|
+
(`draw.mjs --app`, `inspect.mjs --app`).
|
|
40
|
+
|
|
41
|
+
## Read
|
|
42
|
+
|
|
43
|
+
The visitor understands something: docs, guide, article, changelog.
|
|
44
|
+
|
|
45
|
+
- The style owns **the frame**: masthead, rail, ground, title and section openers, how code and
|
|
46
|
+
tables are set. That is where palette, type and the signature move commit fully.
|
|
47
|
+
- The reading column stays calm: a reading face, real contrast, about 60–75 characters at about
|
|
48
|
+
16px. No monospace prose. Nothing performs behind the text.
|
|
49
|
+
- The style never supplies the reading order or replaces the navigation with something to learn.
|
|
50
|
+
- Check: can a reader tell where they are, where to go next, and read comfortably? Cover the name:
|
|
51
|
+
could this be any other product's docs? Then the frame has not taken the style yet.
|
package/skills/expo/SKILL.md
CHANGED
|
@@ -8,10 +8,9 @@ origin: risco
|
|
|
8
8
|
|
|
9
9
|
# Expo & EAS: shipping React Native
|
|
10
10
|
|
|
11
|
-
**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`../motion-craft/SKILL.md`'s.
|
|
11
|
+
**Scope.** This skill owns the Expo platform: router, config plugins, EAS, native modules, store
|
|
12
|
+
builds. Animation and gestures (Reanimated worklets, sheets, press feedback, haptics) follow
|
|
13
|
+
`../react-native/SKILL.md`. Visual design of web pages and screens is `../design/SKILL.md`'s.
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
## What this skill owns
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Landing Copy by Section
|
|
2
2
|
|
|
3
|
-
The words for every landing section
|
|
3
|
+
The words for every landing section. `../../design/SKILL.md` owns the visual treatment, the layout and which sections exist (its argument step: one claim per section); this file owns the copy that goes inside each section. Each section has **one copy job**; cut any section whose job you can't name. Ground every line in the brand study (`brand-grounding.md`) and run the value prop through the canvas (`copy-frameworks.md`) first.
|
|
4
4
|
|
|
5
5
|
## Section map (copy job + framework)
|
|
6
6
|
|
|
@@ -187,5 +187,5 @@ Good — "Stop babysitting staging. Start free — no credit card."
|
|
|
187
187
|
|
|
188
188
|
- `copy-frameworks.md` — the frameworks and headline formulas each section uses.
|
|
189
189
|
- `brand-grounding.md` — the value prop, proof, and voice every line is grounded in.
|
|
190
|
-
- `../../design/
|
|
190
|
+
- `../../design/SKILL.md` — the page these words fill; write the copy deck before its markup.
|
|
191
191
|
- `campaigns-and-channels.md` — driving traffic to this page.
|
package/skills/react/SKILL.md
CHANGED
|
@@ -10,8 +10,8 @@ origin: risco
|
|
|
10
10
|
|
|
11
11
|
**Hand-off — picking dependencies.** Which library to reach for (UI primitives, command menus,
|
|
12
12
|
toasts, OTP inputs, charts, virtualization, drag and drop, state, styling, theming) is
|
|
13
|
-
`../ui-engineering/SKILL.md`'s — build vs adopt is decided there, before hand-rolling a component.
|
|
14
|
-
|
|
13
|
+
`../ui-engineering/SKILL.md`'s — build vs adopt is decided there, before hand-rolling a component. The look of a page
|
|
14
|
+
or screen, and its motion layer, is `../design/SKILL.md`'s.
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
> Build or review a fast, typed, correctly-architected **client-side** React single-page app bundled by Vite. No server runtime, no RSC tree, no framework router. Server-rendered React (App Router, server actions, SSR/SSG) is not this skill — that is `../nextjs/SKILL.md`.
|
|
@@ -8,9 +8,9 @@ origin: risco
|
|
|
8
8
|
|
|
9
9
|
# React Native (app code)
|
|
10
10
|
|
|
11
|
-
**
|
|
12
|
-
|
|
13
|
-
`../
|
|
11
|
+
**Scope.** App code, including animation and gestures (Reanimated worklets on the UI runtime, gesture
|
|
12
|
+
handoff, sheets, press feedback, haptics), in bare React Native and in Expo. Visual design of web
|
|
13
|
+
pages and screens is `../design/SKILL.md`'s.
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
You write the code that runs *inside* the app: render, navigate, animate, list, persist, and author native modules. Mobile is split across two skills by **verb** — run the verb test before doing anything:
|
package/skills/suggest/SKILL.md
CHANGED
|
@@ -55,13 +55,12 @@ name it and offer it. This runs mid-conversation, not only at project start.
|
|
|
55
55
|
1. `npx @ericrisco/rsc catalog --available` lists every not-installed skill as
|
|
56
56
|
`id available short description`.
|
|
57
57
|
2. Pick the single best fit **by meaning**, the way you would match a request to a teammate's
|
|
58
|
-
expertise
|
|
59
|
-
|
|
60
|
-
and move on: a tangential suggestion is worse than none.
|
|
58
|
+
expertise, even when no keyword overlaps. If nothing genuinely fits, say so and move on: a
|
|
59
|
+
tangential suggestion is worse than none.
|
|
61
60
|
3. Ask once, plainly: "Para esto instalaría `<id>`, que aún no tienes. ¿La instalo? (sí/no)".
|
|
62
61
|
4. On yes, run `npx @ericrisco/rsc add <id>`, then continue the original task.
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
One suggestion at a time,
|
|
65
64
|
and never to interrupt a flow with a nice-to-have. Never recommend something already installed
|
|
66
65
|
(`npx @ericrisco/rsc list`).
|
|
67
66
|
|
|
@@ -78,9 +77,8 @@ Not covered → one line, skill or agent. Rules: `skill-scout`.
|
|
|
78
77
|
|
|
79
78
|
## 3. A harness that is broken fixes itself
|
|
80
79
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
nothing they recognise. When any of these is true, act on it **once** in the session:
|
|
80
|
+
Its owner rarely notices: the symptoms name nothing they know. When any of these
|
|
81
|
+
is true, act on it **once** in the session:
|
|
84
82
|
|
|
85
83
|
- `.rsc.json` exists and what it declares is not what is installed;
|
|
86
84
|
- the same hook seems to run several times;
|
|
@@ -100,7 +98,7 @@ a cause. Then:
|
|
|
100
98
|
teammate added, disarming a gate — **ask first**. A `git pull` never rewrites someone's
|
|
101
99
|
machine.
|
|
102
100
|
|
|
103
|
-
Offer once per session
|
|
101
|
+
Offer once per session; say nothing when the harness is healthy.
|
|
104
102
|
|
|
105
103
|
## 4. First contact
|
|
106
104
|
|
|
@@ -114,6 +112,12 @@ Before handling the first request of a session, check the workspace:
|
|
|
114
112
|
`.rsc/.no-harness`, confirm in one line, and never auto-start `init` in this repo again.
|
|
115
113
|
- With a profile, this gate is inert. Never re-onboard.
|
|
116
114
|
|
|
115
|
+
## 5. «Recuerda esto»
|
|
116
|
+
|
|
117
|
+
A project or business fact goes to its topic page in `02-DOCS/wiki/` (link a new page from
|
|
118
|
+
`wiki/index.md`); say the path. Your own memory sits outside the project, unseen by person and
|
|
119
|
+
team: keep there only how this person likes you to work (or all, without `02-DOCS/`).
|
|
120
|
+
|
|
117
121
|
## Explain without assuming
|
|
118
122
|
|
|
119
123
|
Define a term at first use; never give a command, flag or path without saying what it does.
|
|
@@ -76,3 +76,9 @@ capability:
|
|
|
76
76
|
- "Names that one missing automation/connector skill"
|
|
77
77
|
- "Asks one short confirmation before installing and does not auto-install"
|
|
78
78
|
- "On confirmation, runs `npx @ericrisco/rsc add <id>` for that one missing skill, then resumes the automation task"
|
|
79
|
+
|
|
80
|
+
- scenario: "In a workspace with `02-DOCS/wiki/`, the user says 'recuerda que toda la actividad, también la de Andorra, va por una sola sociedad, Nadsan 2006 S.L.'. Show where rsc-suggest puts it."
|
|
81
|
+
must_include:
|
|
82
|
+
- "Writes the fact into the `02-DOCS/wiki/` page of its topic (creating it and linking it from `wiki/index.md` if none exists), not only into the assistant's own memory under `~/.claude/projects/`"
|
|
83
|
+
- "Tells the person the path where it was saved"
|
|
84
|
+
- "Opens no FTD document and asks no lane question for it"
|
|
@@ -13,7 +13,7 @@ origin: risco
|
|
|
13
13
|
app lifecycle, Xcode, iOS APIs, App Store shipping. Language-level Swift — Swift 6 data-race safety
|
|
14
14
|
and approachable concurrency, actors and task groups, `some` vs `any`, ARC and performance, Swift
|
|
15
15
|
Testing, macros — is this skill's own ground. A concurrency error, a hang, a data race or a
|
|
16
|
-
retain cycle belongs here
|
|
16
|
+
retain cycle belongs here, and so do interface feel, springs and materials on iOS.
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
Native Apple-platform apps: the code is `.swift`, the UI is SwiftUI, and the compiler enforces actor isolation. If the answer is a `@MainActor`, `@Observable`, `async let`, `#expect`, `NavigationStack`, or `@Model`, you are in the right place.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: ui-engineering
|
|
3
3
|
description: "Use when the question is how interface should be BUILT — component boundaries, state that belongs in the URL vs the component, loading/empty/error states, forms, optimistic updates, build vs adopt. NOT the visual system (`design`), NOT framework mechanics (`react`/`nextjs`)."
|
|
4
4
|
tags: [interface, frontend, architecture, components, state, craft]
|
|
5
|
-
recommends: [design
|
|
5
|
+
recommends: [design]
|
|
6
6
|
profiles: [core, full]
|
|
7
7
|
origin: risco
|
|
8
8
|
---
|
|
@@ -108,7 +108,6 @@ The split is not about difficulty, it is about **who is the authority on the beh
|
|
|
108
108
|
|
|
109
109
|
## See Also
|
|
110
110
|
|
|
111
|
-
- `../design/SKILL.md` — the visual system these decisions serve
|
|
112
|
-
-
|
|
113
|
-
- `../design-loop/SKILL.md` — the graded critique that judges the result.
|
|
111
|
+
- `../design/SKILL.md` — the visual system these decisions serve, its motion layer, and the
|
|
112
|
+
browser-measured critique that judges the result.
|
|
114
113
|
- `../accessibility/SKILL.md` — the ground under focus, semantics and forms.
|
|
@@ -22,10 +22,10 @@ should_not_trigger:
|
|
|
22
22
|
route_to: "react"
|
|
23
23
|
why: "Framework mechanics. This skill decides what to build, not how the framework behaves."
|
|
24
24
|
- prompt: "The dropdown animation feels cheap, what duration should it use?"
|
|
25
|
-
route_to: "
|
|
25
|
+
route_to: "design"
|
|
26
26
|
why: "Once the component exists, how it moves is motion craft."
|
|
27
27
|
- prompt: "Grade this dashboard and tell me if it is actually good."
|
|
28
|
-
route_to: "design
|
|
28
|
+
route_to: "design"
|
|
29
29
|
why: "Judging a finished screen is the critique loop, not the build decisions."
|
|
30
30
|
- prompt: "Set up the Next.js App Router with server actions for this project."
|
|
31
31
|
route_to: "nextjs"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: variant-explorer
|
|
3
|
-
description: "Use when someone wants OPTIONS rather than an answer — 'show me a few versions', picking between approaches by seeing them. Genuinely different candidates, cheap to throw away, trade-off named. NOT the critique that judges one (`design
|
|
3
|
+
description: "Use when someone wants OPTIONS rather than an answer — 'show me a few versions', picking between approaches by seeing them. Genuinely different candidates, cheap to throw away, trade-off named. NOT the critique that judges one (`design`), NOT the spec (`specify`)."
|
|
4
4
|
tags: [prototyping, divergence, options, exploration, decision]
|
|
5
|
-
recommends: [design
|
|
5
|
+
recommends: [design]
|
|
6
6
|
profiles: [full]
|
|
7
7
|
origin: risco
|
|
8
8
|
---
|
|
@@ -84,10 +84,10 @@ handing the work back. Say which one you would pick and why, and make it easy to
|
|
|
84
84
|
| Present five or six to be thorough | Past three, they stop being compared and start being skimmed. |
|
|
85
85
|
| Give options with no recommendation | Standing back is not neutrality; it hands the work back to the person who asked. |
|
|
86
86
|
| Explore a decision that is cheap to reverse | Just ship one. Divergence is for what is expensive to unwind. |
|
|
87
|
-
| Keep iterating on the winner here | Once one is chosen, refining it is `../design
|
|
87
|
+
| Keep iterating on the winner here | Once one is chosen, refining it is `../design/SKILL.md` or the relevant build skill. |
|
|
88
88
|
|
|
89
89
|
## See Also
|
|
90
90
|
|
|
91
|
-
- `../design
|
|
91
|
+
- `../design/SKILL.md` — the graded critique that takes over once a direction is chosen.
|
|
92
92
|
- `../specify/SKILL.md` — when what is missing is an agreed WHAT/WHY, not options.
|
|
93
93
|
- `../design/SKILL.md` — building the chosen direction properly.
|
|
@@ -16,7 +16,7 @@ should_trigger:
|
|
|
16
16
|
|
|
17
17
|
should_not_trigger:
|
|
18
18
|
- prompt: "Review this checkout screen and grade it."
|
|
19
|
-
route_to: "design
|
|
19
|
+
route_to: "design"
|
|
20
20
|
why: "Judging one finished thing is critique, the opposite of divergence."
|
|
21
21
|
- prompt: "We need to agree what this feature is for before anyone builds it."
|
|
22
22
|
route_to: "specify"
|
|
@@ -95,7 +95,7 @@ export function readManifest(root) {
|
|
|
95
95
|
const ids = (v) => (Array.isArray(v) ? v.filter((x) => typeof x === 'string' && ID.test(x)) : []);
|
|
96
96
|
// Retired skills read as their successors. Canonical map: scripts/lib/retired-skills.js — inlined
|
|
97
97
|
// because this file cannot import anything, and tests/retired-skills.test.js holds the two equal.
|
|
98
|
-
const RETIRED = { eli5: 'orient', 'show-me': 'orient', bro: 'unslop' };
|
|
98
|
+
const RETIRED = { eli5: 'orient', 'show-me': 'orient', bro: 'unslop', 'design-loop': 'design', 'design-dna': 'design', 'motion-craft': 'design' };
|
|
99
99
|
const skills = [...new Set(ids(parsed.skills).map((id) => (Object.hasOwn(RETIRED, id) ? RETIRED[id] : id)))];
|
|
100
100
|
const own = ids(parsed.ownSkills);
|
|
101
101
|
// A manifest with nothing declared is not a clone waiting to be equipped; there is nothing to offer.
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
// Does this harness have a design identity, and can we tell?
|
|
2
|
-
//
|
|
3
|
-
// `design` has declared for a long time that without a brand study it STOPS and does not design.
|
|
4
|
-
// Nothing checked it: `grep -rln "wiki/brand" scripts/` returned nothing before this file existed.
|
|
5
|
-
// That is P2 — a rule declared binding with no mechanism is a decorative gate. Spec:
|
|
6
|
-
// 02-DOCS/wiki/sdd/specs/design-area-cleanup.md
|
|
7
|
-
//
|
|
8
|
-
// Three states, and the third is the whole point. A checker that cannot look must never report
|
|
9
|
-
// green: that exact defect was found and fixed in the design-dna style checker two days earlier,
|
|
10
|
-
// where regex probes ran against empty text and returned vacuous passes. Absence of evidence is
|
|
11
|
-
// reported as absence of evidence.
|
|
12
|
-
//
|
|
13
|
-
// Read-only. It never writes: 02-DOCS is untracked (P9) and there is no undo there.
|
|
14
|
-
import { existsSync, lstatSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
15
|
-
import { join } from 'node:path';
|
|
16
|
-
|
|
17
|
-
// Where the harness keeps durable design knowledge, and the section in the root instructions file
|
|
18
|
-
// that points at it. Both are the `design`/`harness` convention, not invented here.
|
|
19
|
-
export const BRAND_DIR = join('02-DOCS', 'wiki', 'brand');
|
|
20
|
-
export const BRAND_SECTION = '## Brand & voice';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @returns {{state: 'present'|'missing'|'inconclusive', linked: boolean, articles: string[],
|
|
24
|
-
* reason: string, fix?: string}}
|
|
25
|
-
* `present` — articles exist under the brand dir. `linked` says whether the root
|
|
26
|
-
* instructions file points at them, which is how other skills find it.
|
|
27
|
-
* `missing` — looked, found nothing. Carries the fix (P6: a denial carries its way out).
|
|
28
|
-
* `inconclusive` — could not look. Never conflated with `missing`, and never with green.
|
|
29
|
-
*/
|
|
30
|
-
export function designIdentity(root = process.cwd()) {
|
|
31
|
-
const dir = join(root, BRAND_DIR);
|
|
32
|
-
|
|
33
|
-
let articles;
|
|
34
|
-
try {
|
|
35
|
-
if (!existsSync(dir)) {
|
|
36
|
-
// existsSync FOLLOWS symlinks, so a dangling one reports false and would be filed as "no
|
|
37
|
-
// identity here". It is not absence, it is unreadability — the same conflation this whole
|
|
38
|
-
// area was cleaning up. lstat sees the link itself and tells the two apart.
|
|
39
|
-
let danglingLink = false;
|
|
40
|
-
try { danglingLink = lstatSync(dir).isSymbolicLink(); } catch { /* genuinely absent */ }
|
|
41
|
-
if (danglingLink) {
|
|
42
|
-
return {
|
|
43
|
-
state: 'inconclusive',
|
|
44
|
-
linked: false,
|
|
45
|
-
articles: [],
|
|
46
|
-
reason: `${BRAND_DIR} is a symlink that does not resolve`,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
state: 'missing',
|
|
51
|
-
linked: false,
|
|
52
|
-
articles: [],
|
|
53
|
-
reason: `no ${BRAND_DIR}/ in this harness`,
|
|
54
|
-
fix: 'run `design-loop` to converge on a winner, then `design-dna` to write its record here',
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
// Not statSync: it follows symlinks, so a symlink here could report on a directory outside the
|
|
58
|
-
// declared zone. Same reason drift-check.js:167 uses dirents.
|
|
59
|
-
if (!statSync(dir).isDirectory()) {
|
|
60
|
-
return {
|
|
61
|
-
state: 'inconclusive',
|
|
62
|
-
linked: false,
|
|
63
|
-
articles: [],
|
|
64
|
-
reason: `${BRAND_DIR} exists but is not a directory`,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
articles = readdirSync(dir).filter((f) => f.endsWith('.md') && f !== 'index.md');
|
|
68
|
-
} catch (e) {
|
|
69
|
-
// Unreadable for any reason (permissions, dangling symlink, ELOOP). We did not look, so we
|
|
70
|
-
// cannot say. Reporting `missing` here would invent a finding; reporting green would hide one.
|
|
71
|
-
return {
|
|
72
|
-
state: 'inconclusive',
|
|
73
|
-
linked: false,
|
|
74
|
-
articles: [],
|
|
75
|
-
reason: `cannot read ${BRAND_DIR}: ${e.code || e.message}`,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// The link matters on its own: five skills reach the identity through the root instructions file,
|
|
80
|
-
// so an unlinked identity is one they will not find.
|
|
81
|
-
let linked = false;
|
|
82
|
-
const claudeMd = join(root, 'CLAUDE.md');
|
|
83
|
-
if (existsSync(claudeMd)) {
|
|
84
|
-
try {
|
|
85
|
-
linked = readFileSync(claudeMd, 'utf8').includes(BRAND_SECTION);
|
|
86
|
-
} catch {
|
|
87
|
-
// The articles are what we were asked about and we did read them. A CLAUDE.md we could not
|
|
88
|
-
// read makes `linked` unknown, not the whole answer unknown — report it in the reason.
|
|
89
|
-
return {
|
|
90
|
-
state: articles.length ? 'present' : 'missing',
|
|
91
|
-
linked: false,
|
|
92
|
-
articles,
|
|
93
|
-
reason: `${articles.length} article(s), but CLAUDE.md could not be read to confirm the link`,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (!articles.length) {
|
|
99
|
-
return {
|
|
100
|
-
state: 'missing',
|
|
101
|
-
linked,
|
|
102
|
-
articles: [],
|
|
103
|
-
reason: `${BRAND_DIR}/ exists but holds no identity article`,
|
|
104
|
-
fix: 'run `design-loop` to converge on a winner, then `design-dna` to write its record here',
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
state: 'present',
|
|
110
|
-
linked,
|
|
111
|
-
articles,
|
|
112
|
-
reason: linked
|
|
113
|
-
? `${articles.length} article(s), linked from CLAUDE.md`
|
|
114
|
-
: `${articles.length} article(s), but no "${BRAND_SECTION}" section in CLAUDE.md points at them`,
|
|
115
|
-
...(linked ? {} : { fix: `add a "${BRAND_SECTION}" section to CLAUDE.md linking ${BRAND_DIR}/` }),
|
|
116
|
-
};
|
|
117
|
-
}
|