diff --git a/.changepacks/changepack_log_skill_refresh.json b/.changepacks/changepack_log_skill_refresh.json new file mode 100644 index 00000000..c59cd0bb --- /dev/null +++ b/.changepacks/changepack_log_skill_refresh.json @@ -0,0 +1,7 @@ +{ + "changes": { + "crates/devup-mcp/Cargo.toml": "Patch" + }, + "note": "Re-vendored the embedded agent skill documents that moved in their source repositories: devup-ui. The copies in this binary are what `devup_skills install` writes on a machine with no network, so a copy that has fallen behind installs rules the upstream project no longer states. Opened automatically by the scheduled skill-drift job; the bytes here are exactly what scripts/refresh-skills.mjs produced.", + "date": "2026-10-05T06:24:50+00:00" +} diff --git a/crates/devup-mcp/src/server/skills/devup-ui/SKILL.md b/crates/devup-mcp/src/server/skills/devup-ui/SKILL.md index ade2c1c0..31a78b3b 100644 --- a/crates/devup-mcp/src/server/skills/devup-ui/SKILL.md +++ b/crates/devup-mcp/src/server/skills/devup-ui/SKILL.md @@ -148,6 +148,10 @@ All standard CSS properties from `csstype` are also accepted directly (e.g., `di // padding: 20px (with unit = exact value) ``` +Unitless CSS properties keep the number as written: `lineHeight`, `zIndex`, `opacity`, `fontWeight`, `flexGrow`, `order`, `aspectRatio`, `columnCount`, `strokeWidth`, `zoom`, `counterReset`/`counterIncrement`/`counterSet`, and the rest of the unitless list vanilla-extract uses. Times are milliseconds, never scaled: `transitionDuration={300}`, `transitionDelay`, `animationDuration` and `animationDelay` give `300ms`. + +Styles from other libraries keep that library's number meaning instead of the scale: in `.css.ts` files, in vanilla-extract `style()`, `globalStyle()` and `keyframes()` calls inside ordinary modules, in Emotion and styled-components object styles, and in `stylex.create()`, `fontSize: 16` is `16px`. Devup UI shorthands (`p`, `bg`, ...) keep the scale everywhere. + ### Responsive Arrays (5 breakpoints) ```tsx @@ -215,8 +219,23 @@ Available: `_groupHover`, `_groupFocus`, `_groupActive`, `_groupDisabled`. // @ prefix syntax (equivalent) + +// Query in the key (Emotion style), also inside `selectors` and css()/styled() + +``` + +Media shorthands wrap styles in a fixed query and nest in either direction with selectors: +`_print`, `_screen`, `_all`, `_portrait`, `_landscape`, `_motionReduce` (`prefers-reduced-motion: reduce`), `_motionSafe` (`no-preference`), `_contrastMore`, `_contrastLess`, `_forcedColors`. + +```tsx + + +globalCss({ _motionReduce: { "*, *::before, *::after": { transition: "none" } } }) ``` +- Conditions beat breakpoint values: at-rule styles are emitted after every responsive rule. +- Nested `@media` rules merge into one query (`print and (prefers-reduced-motion:reduce)`); ones that can never match together (`_print` inside `_screen`) are dropped. + ### Custom Selectors ```tsx @@ -238,8 +257,14 @@ Available: `_groupHover`, `_groupFocus`, `_groupActive`, `_groupDisabled`. // Conditional -> preserved // className={isActive ? "a" : "b"} + +// Imported const -> static (resolved like the bundler: relative paths, tsconfig paths, packages; ESM or CommonJS) +import { PRIMARY } from "./tokens" // export const PRIMARY = "red" + // className="a"; a `let`, call or package import stays a variable ``` +A `.css.ts` file may import other stylesheets and modules (import cycles behave as in ES modules); an imported stylesheet exports the same names its own CSS uses. styled-components `.attrs()` (objects and functions) and `.withConfig()` compile, and `css(base, cond && { ... })` / `styled.div(base, cond ? a : b)` / `value || { ... }` / `value ?? { ... }` merge per property. A style argument that cannot be known at build time is a build error. StyleX `defineVars` / `defineConsts` / `createTheme` values imported from a `.stylex.ts` file resolve to the names that file generates, and variable/theme values may be condition objects (`{ default, [DARK]: ... }`, `@media` / `@supports` / `@container`). A `.css.ts` file that throws while evaluated is a build error carrying the exception. Build errors are reported all at once as `file:line:column: message`. + ### Responsive + Pseudo Combined ```tsx @@ -258,7 +283,10 @@ Changes the rendered HTML element or renders a custom component: // renders
// renders // renders with extracted styles + // renders // conditional element type + // undefined/null/false -> default element (
) + // any other value is read at runtime, default when empty ``` ### `props` (Pass-Through to `as` Component) @@ -310,11 +338,20 @@ globalCss({ body: { margin: 0 }, "*": { boxSizing: "border-box" } }); const spin = keyframes({ from: { transform: "rotate(0)" }, to: { transform: "rotate(360deg)" } }); + +// A const holding a keyframes name or a css() class is a build-time value +const card = css({ p: 4 }); +css({ animationName: spin, selectors: { [`.${card}:hover &`]: { m: 1 } } }); ``` +- Only a `const` declared in the same file works this way; an imported keyframes/class name is not known at build time. +- `import * as Devup from "@devup-ui/react"` works (`Devup.css`, `Devup.keyframes`, `Devup.styled.div`, ``). +- `styled()` takes any base: tag, Devup component, `motion.div`, `forwardRef(...)`, a variable. `null`/number/boolean/`undefined` bases are build errors. +- Compiled imports are removed: a top-level alias (`const myCss = css`, `const Row = Flex`) compiles and is removed, but any other runtime read (`export const C = Box`, `[Box]`, `styled('div')` alone, an alias inside a function) is a **build error**. + ### Dynamic Values with Custom Components -`css()` only accepts **static values**. For dynamic values on custom components, use ``: +`css()`, `globalCss()`, `keyframes()` and `stylex.create()` only accept values known at build time - literals, theme tokens, imported constants and module-level `const`s (templates, arithmetic and `Math.*` calls over them fold). Object, array and enum constants read as if written in place (`css(base)`, `{ ...base, color: 'red' }`, `_hover: hover`, `space[2]`, `Size.M`, ``), a later property replacing an earlier one. The build only runs code whose result is certain: `const`s, functions and enums this file declares, computing from literals and constants with exact built-ins (`String`, `Number`, `JSON`, `Object`, `Array`, string/array methods, `Math.abs/ceil/floor/round/trunc/sign/max/min/sqrt/fround/imul/clz32` and `Math` constants) - `const double = (n) => n * 2; css({ w: double(SIZE) })` is static. Imports are only read as the literal, object or array their module declares; code of another module never runs (`darken(0.1, PRIMARY)` with an imported `darken` is not computed). Not run: other globals (`window`, `Date`, `Intl`, ...), `Math.random` and approximate `Math` functions (`sin`, `pow`, ...), `**`, `toString(radix)`, `toLocale*`/`localeCompare`/`normalize`, `this`, `new`, classes, regex, `try`, getters, async/generators, JSX, `obj[key]()`, and functions writing module-level bindings - elements and `styled()` keep such values as CSS variables, while `css()`/`globalCss()`/`keyframes()` report a build error (as do `css()`/`styled()` given a whole style object computed that way). An object, array or enum constant that visible code changes (member assignment, `delete`, `++`, `push`/`sort`, `Object.assign`, changing elements in `for...of`/`forEach`, a method using `this`, passing it to an unknown function) is not a constant: elements read its members at runtime, and `css(obj)`, `styled.div(obj)` or `{...obj}` on an element is a build error naming where it changes. JSX props (except `ref`), `export default`, `module.exports` and `Object.freeze` only read it. Never mutate objects styles read; use theme tokens or props for values that change. A value known only at runtime (a prop, state, a parameter), and styles written where the build cannot read an object (a spread of an unknown object, `_hover={x}`, a computed key), are a **build error**. For dynamic values on custom components, use ``: ```tsx // WRONG - css() cannot handle dynamic values @@ -365,7 +402,7 @@ const spin = keyframes({ from: { transform: "rotate(0)" }, to: { transform: "rot ``` - **Colors**: Use with `$` prefix in JSX props: `` -- **Typography**: Use with `$` prefix: `` +- **Typography**: Use the preset name without `$`: ``. Under selectors or at-rules (`_hover={{ typography: "heading" }}`) the preset applies only under that condition. - **Length**: Responsive length tokens: ``, `` - **Shadow**: Responsive shadow tokens: `` - **extends**: Inherit from base config files (deep merge, last wins) @@ -548,6 +585,7 @@ One rule explains `Dynamic Values = CSS Variables`, `$token Scope` and |------|--------| | `` | Static class | | `` | Static class per value - **preferred** | +| `` where `PRIMARY` is a module-level or imported `const` string/number | Static class | | `` where `colors` is declared elsewhere | CSS variable | | `` | CSS variable (genuinely dynamic - correct) | | `const s = { a: css({ ... }) }` then `className={s[v]}` | Neither - see below | diff --git a/crates/devup-mcp/src/server/skills/manifest.json b/crates/devup-mcp/src/server/skills/manifest.json index 06a911d6..c327b0d6 100644 --- a/crates/devup-mcp/src/server/skills/manifest.json +++ b/crates/devup-mcp/src/server/skills/manifest.json @@ -10,16 +10,16 @@ "usedFor": "The TSX devup_figma_export returns is devup-ui code. Without this the agent does not know its components are compile-time placeholders, that $token means devup.json, or that a style prop takes a responsive array.", "repo": "dev-five-git/devup-ui", "path": "SKILL.md", - "commit": "c7295916e43657ee357e35f2682b78900c5232c2", - "committedAt": "2026-09-21T14:05:45Z", + "commit": "cebcfb2a3f94649f297315e702dd468026474ff6", + "committedAt": "2026-09-30T02:49:17Z", "documents": [ { "path": "SKILL.md", - "bytes": 23101, - "sha256": "12787e610016e90ef9e483bd2b82e3c9312aec4b106fed29f07c816e5b0c7fba" + "bytes": 29525, + "sha256": "cd750ecb6b49340a2cf4c386ef7c69eeff4d495d115f58223b963430da9f87a2" } ], - "sourceUrl": "https://github.com/dev-five-git/devup-ui/blob/c7295916e43657ee357e35f2682b78900c5232c2/SKILL.md", + "sourceUrl": "https://github.com/dev-five-git/devup-ui/blob/cebcfb2a3f94649f297315e702dd468026474ff6/SKILL.md", "latestUrl": "https://github.com/dev-five-git/devup-ui/blob/HEAD/SKILL.md" }, {