Skip to content

Conversation

@lukasoppermann
Copy link
Collaborator

Summary

List of notable changes:

What should reviewers focus on?

Steps to test:

@lukasoppermann lukasoppermann requested review from a team as code owners January 21, 2026 16:43
@changeset-bot
Copy link

changeset-bot bot commented Jan 21, 2026

⚠️ No Changeset found

Latest commit: ffab5e0

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions
Copy link
Contributor

Design Token Diff (CSS)

The message is too long to be displayed here. For more details, please check the job summary.

@github-actions
Copy link
Contributor

Design Token Diff (StyleLint)

The message is too long to be displayed here. For more details, please check the job summary.

@github-actions
Copy link
Contributor

Design Token Diff (Figma)

/figma/dimension/dimension.json

+++ /home/runner/work/primitives/primitives/dist/figma/dimension/dimension.json	2026-01-21 16:44:51.068153002 +0000
@@ -972,6 +972,7 @@
   "name": "borderWidth/default",
   "value": 1,
   "type": "FLOAT",
+    "description": "Default border width for most UI elements. Alias of borderWidth.thin (1px)",
   "refId": "functional/size/borderWidth/default",
   "reference": "functional/size/borderWidth/thin",
   "collection": "functional/size",
@@ -983,6 +984,7 @@
   "name": "borderWidth/thin",
   "value": 1,
   "type": "FLOAT",
+    "description": "Standard 1px border width. Use for most borders, dividers, and outlines throughout the interface",
   "refId": "functional/size/borderWidth/thin",
   "collection": "functional/size",
   "mode": "default",
@@ -993,6 +995,7 @@
   "name": "borderWidth/thick",
   "value": 2,
   "type": "FLOAT",
+    "description": "Thick 2px border for emphasis. Use for focus indicators, selected states, or to emphasize important boundaries",
   "refId": "functional/size/borderWidth/thick",
   "collection": "functional/size",
   "mode": "default",
@@ -1003,6 +1006,7 @@
   "name": "borderWidth/thicker",
   "value": 4,
   "type": "FLOAT",
+    "description": "Extra thick 4px border for maximum emphasis. Use sparingly for high-contrast focus indicators or critical visual separators",
   "refId": "functional/size/borderWidth/thicker",
   "collection": "functional/size",
   "mode": "default",
@@ -1010,9 +1014,32 @@
   "scopes": ["STROKE_FLOAT", "EFFECT_FLOAT"]
 },
 {
+    "name": "outline/focus/offset",
+    "value": -2,
+    "type": "FLOAT",
+    "description": "Focus outline offset (-2px). Negative value creates an inset outline for keyboard focus indicators, ensuring the focus ring stays within the element bounds",
+    "refId": "functional/size/outline/focus/offset",
+    "collection": "functional/size",
+    "mode": "default",
+    "group": "functional/size",
+    "scopes": ["STROKE_FLOAT", "EFFECT_FLOAT"]
+  },
+  {
+    "name": "outline/focus/width",
+    "value": 2,
+    "type": "FLOAT",
+    "description": "Focus outline width (2px). Standard width for keyboard focus indicators to meet WCAG 2.4.7 accessibility requirements",
+    "refId": "functional/size/outline/focus/width",
+    "collection": "functional/size",
+    "mode": "default",
+    "group": "functional/size",
+    "scopes": ["STROKE_FLOAT", "EFFECT_FLOAT"]
+  },
+  {
   "name": "borderRadius/small",
   "value": 3,
   "type": "FLOAT",
+    "description": "Small border radius (3px). Use for small variants of components or small UI elements like badges, tags, or anything below 16px in height",
   "refId": "functional/size/borderRadius/small",
   "collection": "functional/size",
   "mode": "default",
@@ -1026,6 +1053,7 @@
   "name": "borderRadius/medium",
   "value": 6,
   "type": "FLOAT",
+    "description": "Medium border radius (6px). The default choice for most buttons, cards, and containers",
   "refId": "functional/size/borderRadius/medium",
   "collection": "functional/size",
   "mode": "default",
@@ -1039,6 +1067,7 @@
   "name": "borderRadius/large",
   "value": 12,
   "type": "FLOAT",
+    "description": "Large border radius (12px). Use for larger containers, dialogs, or when more visual softness is desired. Always use this for buttons.",
   "refId": "functional/size/borderRadius/large",
   "collection": "functional/size",
   "mode": "default",
@@ -1066,6 +1095,7 @@
   "name": "borderRadius/default",
   "value": 6,
   "type": "FLOAT",
+    "description": "Default border radius for most UI elements. Alias of borderRadius.medium (6px). Use when in doubt",
   "refId": "functional/size/borderRadius/default",
   "reference": "functional/size/borderRadius/medium",
   "collection": "functional/size",
@@ -1075,25 +1105,5 @@
   "codeSyntax": {
     "web": "var(--borderRadius-default) /* utility class: .rounded-2 */"
   }
-  },
-  {
-    "name": "outline/focus/offset",
-    "value": -2,
-    "type": "FLOAT",
-    "refId": "functional/size/outline/focus/offset",
-    "collection": "functional/size",
-    "mode": "default",
-    "group": "functional/size",
-    "scopes": ["STROKE_FLOAT", "EFFECT_FLOAT"]
-  },
-  {
-    "name": "outline/focus/width",
-    "value": 2,
-    "type": "FLOAT",
-    "refId": "functional/size/outline/focus/width",
-    "collection": "functional/size",
-    "mode": "default",
-    "group": "functional/size",
-    "scopes": ["STROKE_FLOAT", "EFFECT_FLOAT"]
 }
]

/figma/themes/dark-colorblind.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/dark-colorblind.json	2026-01-21 16:44:50.704153679 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/dark/base/color/neutral/1",
   "collection": "mode",
@@ -1312,6 +1313,7 @@
   },
   "type": "COLOR",
   "alpha": 0.1,
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/dark/base/color/orange/4",
   "collection": "mode",
@@ -1331,6 +1333,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/dark/base/color/orange/5",
   "collection": "mode",

/figma/themes/dark-dimmed.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/dark-dimmed.json	2026-01-21 16:44:50.017154957 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/dark/base/color/neutral/3",
   "collection": "mode",
@@ -1311,6 +1312,7 @@
   },
   "type": "COLOR",
   "alpha": 0.1,
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/dark-dimmed/base/color/red/4",
   "collection": "mode",
@@ -1330,6 +1332,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/dark-dimmed/base/color/red/5",
   "collection": "mode",

/figma/themes/dark-high-contrast.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/dark-high-contrast.json	2026-01-21 16:44:51.032153069 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/dark/base/color/neutral/0",
   "collection": "mode",
@@ -1310,6 +1311,7 @@
   },
   "type": "COLOR",
   "alpha": 0.1,
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/dark-high-contrast/base/color/red/4",
   "collection": "mode",
@@ -1329,6 +1331,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/dark-high-contrast/base/color/red/9",
   "collection": "mode",

/figma/themes/dark-tritanopia.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/dark-tritanopia.json	2026-01-21 16:44:50.343154351 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/dark/base/color/neutral/1",
   "collection": "mode",
@@ -1312,6 +1313,7 @@
   },
   "type": "COLOR",
   "alpha": 0.1,
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/dark/base/color/red/4",
   "collection": "mode",
@@ -1331,6 +1333,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/dark/base/color/red/5",
   "collection": "mode",

/figma/themes/dark.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/dark.json	2026-01-21 16:44:49.680155584 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/dark/base/color/neutral/1",
   "collection": "mode",
@@ -1311,6 +1312,7 @@
   },
   "type": "COLOR",
   "alpha": 0.1,
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/dark/base/color/red/4",
   "collection": "mode",
@@ -1330,6 +1332,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/dark/base/color/red/5",
   "collection": "mode",

/figma/themes/light-colorblind.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/light-colorblind.json	2026-01-21 16:44:48.942156957 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/light/base/color/neutral/0",
   "collection": "mode",
@@ -1306,6 +1307,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/light/base/color/orange/0",
   "collection": "mode",
@@ -1325,6 +1327,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/light/base/color/orange/5",
   "collection": "mode",

/figma/themes/light-high-contrast.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/light-high-contrast.json	2026-01-21 16:44:49.310156273 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/light/base/color/neutral/0",
   "collection": "mode",
@@ -1305,6 +1306,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/light-high-contrast/base/color/red/0",
   "collection": "mode",
@@ -1324,6 +1326,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/light-high-contrast/base/color/red/5",
   "collection": "mode",

/figma/themes/light-tritanopia.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/light-tritanopia.json	2026-01-21 16:44:48.607157580 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/light/base/color/neutral/0",
   "collection": "mode",
@@ -1306,6 +1307,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/light/base/color/red/0",
   "collection": "mode",
@@ -1325,6 +1327,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/light/base/color/red/5",
   "collection": "mode",

/figma/themes/light.json

+++ /home/runner/work/primitives/primitives/dist/figma/themes/light.json	2026-01-21 16:44:48.197158343 +0000
@@ -924,6 +924,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Default background color for pages and main content areas",
   "refId": "mode/bgColor/default",
   "reference": "base/color/light/base/color/neutral/0",
   "collection": "mode",
@@ -1305,6 +1306,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Muted danger background for error states and destructive action contexts",
   "refId": "mode/bgColor/danger-muted",
   "reference": "base/color/light/base/color/red/0",
   "collection": "mode",
@@ -1324,6 +1326,7 @@
     "a": 1
   },
   "type": "COLOR",
+    "description": "Emphasized danger background for critical errors and delete confirmations",
   "refId": "mode/bgColor/danger-emphasis",
   "reference": "base/color/light/base/color/red/5",
   "collection": "mode",

/figma/typography/typography.json

+++ /home/runner/work/primitives/primitives/dist/figma/typography/typography.json	2026-01-21 16:44:51.095152952 +0000
@@ -40,46 +40,6 @@
   "scopes": ["FONT_WEIGHT"]
 },
 {
-    "name": "fontStack/system",
-    "value": "SF Pro Text",
-    "type": "STRING",
-    "refId": "typography/fontStack/system",
-    "collection": "typography",
-    "mode": "default",
-    "group": "typography",
-    "scopes": ["FONT_FAMILY"]
-  },
-  {
-    "name": "fontStack/sansSerif",
-    "value": "SF Pro Text",
-    "type": "STRING",
-    "refId": "typography/fontStack/sansSerif",
-    "collection": "typography",
-    "mode": "default",
-    "group": "typography",
-    "scopes": ["FONT_FAMILY"]
-  },
-  {
-    "name": "fontStack/sansSerifDisplay",
-    "value": "SF Pro Display",
-    "type": "STRING",
-    "refId": "typography/fontStack/sansSerifDisplay",
-    "collection": "typography",
-    "mode": "default",
-    "group": "typography",
-    "scopes": ["FONT_FAMILY"]
-  },
-  {
-    "name": "fontStack/monospace",
-    "value": "SF Mono",
-    "type": "STRING",
-    "refId": "typography/fontStack/monospace",
-    "collection": "typography",
-    "mode": "default",
-    "group": "typography",
-    "scopes": ["FONT_FAMILY"]
-  },
-  {
   "name": "lineBoxHeight",
   "value": 1.4,
   "type": "FLOAT",
@@ -343,5 +303,49 @@
   "mode": "default",
   "group": "typography",
   "scopes": ["FONT_WEIGHT"]
+  },
+  {
+    "name": "fontStack/system",
+    "value": "SF Pro Text",
+    "type": "STRING",
+    "description": "System font stack optimized for cross-platform rendering. Primary font for all UI text.",
+    "refId": "typography/fontStack/system",
+    "collection": "typography",
+    "mode": "default",
+    "group": "typography",
+    "scopes": ["FONT_FAMILY"]
+  },
+  {
+    "name": "fontStack/sansSerif",
+    "value": "SF Pro Text",
+    "type": "STRING",
+    "description": "Sans-serif font stack for body text and general UI elements.",
+    "refId": "typography/fontStack/sansSerif",
+    "collection": "typography",
+    "mode": "default",
+    "group": "typography",
+    "scopes": ["FONT_FAMILY"]
+  },
+  {
+    "name": "fontStack/sansSerifDisplay",
+    "value": "SF Pro Display",
+    "type": "STRING",
+    "description": "Display font stack for headings and titles. Same as sansSerif but semantically distinct.",
+    "refId": "typography/fontStack/sansSerifDisplay",
+    "collection": "typography",
+    "mode": "default",
+    "group": "typography",
+    "scopes": ["FONT_FAMILY"]
+  },
+  {
+    "name": "fontStack/monospace",
+    "value": "SF Mono",
+    "type": "STRING",
+    "description": "Monospace font stack for code, technical content, and tabular data.",
+    "refId": "typography/fontStack/monospace",
+    "collection": "typography",
+    "mode": "default",
+    "group": "typography",
+    "scopes": ["FONT_FAMILY"]
 }
]

@github-actions
Copy link
Contributor

Design Token Diff (Fallbacks)

/fallbacks/base/motion/motion.json

+++ /home/runner/work/primitives/primitives/dist/fallbacks/base/motion/motion.json	2026-01-21 16:44:45.408163532 +0000
@@ -1,5 +1,6 @@
{
 "--base-easing-linear": [0, 0, 1, 1],
+  "--base-easing-ease": [0.25, 0.1, 0.25, 1],
 "--base-easing-easeIn": [0.7, 0.1, 0.75, 0.9],
 "--base-easing-easeOut": [0.3, 0.8, 0.6, 1],
 "--base-easing-easeInOut": [0.6, 0, 0.2, 1],

/fallbacks/functional/size/border.json

+++ /home/runner/work/primitives/primitives/dist/fallbacks/functional/size/border.json	2026-01-21 16:44:44.723164806 +0000
@@ -6,11 +6,6 @@
 "--borderWidth-thin": "0.0625rem",
 "--borderWidth-thick": "0.125rem",
 "--borderWidth-thicker": "0.25rem",
-  "--borderRadius-small": "0.1875rem",
-  "--borderRadius-medium": "0.375rem",
-  "--borderRadius-large": "0.75rem",
-  "--borderRadius-full": "624.9375rem",
-  "--borderRadius-default": "0.375rem",
 "--outline-focus-offset": "-0.125rem",
 "--outline-focus-width": "0.125rem"
}

@github-actions github-actions bot temporarily deployed to Preview (Storybook) January 21, 2026 16:45 Inactive
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds LLM (Large Language Model) guidelines functionality to design tokens, enabling AI assistants to understand proper token usage through structured metadata. The implementation creates a new extension namespace (org.primer.llm) in design tokens and generates a dedicated JSON file with usage guidelines.

Changes:

  • Added org.primer.llm extension schema and integration across token types
  • Created new filter, format, and platform for generating LLM guidelines output
  • Added LLM usage metadata to typography, sizing, color, shadow, and motion tokens
  • Moved font stack definitions to a separate file and added LLM guidelines
  • Created human-readable markdown guideline documents for typography, spacing, motion, and color

Reviewed changes

Copilot reviewed 49 out of 52 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/schemas/llmExtension.ts New Zod schema defining LLM extension structure (usage array, rules string)
src/filters/hasLlmExtensions.ts Filter to identify tokens with LLM extensions
src/formats/jsonLlmGuidelines.ts Formatter outputting flat JSON with token guidelines
src/platforms/llmGuidelines.ts Platform configuration for LLM guidelines output
src/tokens/functional/typography/typography.json5 Added LLM extensions to typography tokens; has critical syntax errors
src/tokens/functional/typography/font-stack.json5 New file extracting font stacks with LLM guidelines
src/tokens/functional/size/radius.json5 New file for border radius tokens with LLM guidelines; has documentation conflicts
src/tokens/functional/size/border.json5 Added descriptions and LLM extensions to border tokens
src/tokens/functional/shadow/shadow.json5 Added LLM extensions to shadow tokens
src/tokens/functional/color/bgColor.json5 Added LLM extensions to background color tokens
src/tokens/base/motion/easing.json5 Added LLM extensions to easing curve tokens
src/schemas/*Token.ts Added optional LLM extension support to multiple token schemas
scripts/buildTokens.ts Added LLM guidelines build step
scripts/buildFigma.ts Updated to include new font-stack file
contributor-docs/llm-token-guidelines.md Documentation using incorrect namespace (org.primer.ai vs org.primer.llm)
guidelines/*.llm.md Human-readable guideline documents for various design areas
.gitignore Has critical syntax error preventing proper file exclusion
package.json Added output files to package distribution
package-lock.json Unrelated peer dependency flag removals
Comments suppressed due to low confidence (1)

src/tokens/functional/typography/typography.json5:458

  • Missing line break between the closing brace of $extensions and the closing brace of the shorthand object. Line 458 has two closing braces that should be on separate lines for proper JSON5 formatting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +41 to +54
$description: 'Large border radius (12px). Use for larger containers, dialogs, or when more visual softness is desired. Always use this for buttons.',
$type: 'dimension',
$extensions: {
'org.primer.figma': {
collection: 'functional/size',
scopes: ['radius'],
codeSyntax: {
web: 'var(--borderRadius-large) /* utility class: .rounded-3 */',
},
},
'org.primer.llm': {
usage: ['dialog', 'card', 'modal'],
rules: 'Recommended for dialogs and modals.',
},
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conflicting guidance for button border radius. The description on line 41 states "Always use this for buttons" but the llm usage array on line 52 doesn't include 'button', and line 34 shows 'button' is listed under medium radius. Additionally, line 17 explicitly says "Do NOT use for buttons or cards" for small radius, but line 52 includes 'card' in the usage for large radius. This creates inconsistent guidance across the three radius sizes.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +147
# AI Token Guidelines

This document describes how to add AI-specific usage guidelines to design tokens for consumption by AI assistants like GitHub Copilot.

## Overview

AI Token Guidelines is a feature that outputs a dedicated JSON file (`dist/ai/ai-token-guidelines.json`) containing usage guidelines for AI assistants. This file helps AI tools understand how and when to use specific design tokens.

## Source Format

Add AI guidelines to tokens using the `$extensions['org.primer.ai']` namespace, following the existing pattern for Figma extensions:

```json5
{
borderRadius: {
large: {
$value: '12px',
$type: 'dimension',
$description: 'Large border radius (12px). Use for larger containers, dialogs, or when more visual softness is desired.',
$extensions: {
'org.primer.figma': { /* existing Figma extensions */ },
'org.primer.ai': {
usage: ['button', 'dialog', 'card', 'modal'],
rules: 'MUST use for all buttons. Recommended for dialogs and modals.',
},
},
},
},
}
```

### Extension Properties

| Property | Type | Description |
|----------|------|-------------|
| `usage` | `string[]` | Array of use cases where this token applies |
| `rules` | `string` | Prescriptive guidance using RFC 2119 keywords (MUST, SHOULD, etc.) |

The `$description` field from the token itself is also included in the output.

## Output Format

The build process generates `dist/ai/ai-token-guidelines.json` with a flat structure:

```json
{
"borderRadius-large": {
"description": "Large border radius (12px). Use for larger containers, dialogs, or when more visual softness is desired.",
"usage": ["button", "dialog", "card", "modal"],
"rules": "MUST use for all buttons. Recommended for dialogs and modals."
},
"borderWidth-thick": {
"description": "Thick 2px border for emphasis...",
"usage": ["focus-indicator", "selected-state"],
"rules": "MUST use for focus rings on interactive elements."
}
}
```

## Adding AI Guidelines to Tokens

### Step 1: Identify High-Priority Tokens

Focus on tokens where AI assistants commonly make mistakes or need explicit guidance:
- Focus indicators and accessibility-related tokens
- Semantic color tokens (danger, success, accent)
- Border radius for specific component types
- Shadow tokens for elevation hierarchy

### Step 2: Add the Extension

Add `org.primer.ai` to the token's `$extensions`:

```json5
{
bgColor: {
danger: {
emphasis: {
$value: '{base.color.red.5}',
$type: 'color',
$description: 'Emphasized danger background for critical errors',
$extensions: {
'org.primer.figma': { /* ... */ },
'org.primer.ai': {
usage: ['delete-button', 'critical-alert'],
rules: 'MUST use for destructive action buttons. Use fgColor.onEmphasis for text.',
},
},
},
},
},
}
```

### Step 3: Build and Verify

```bash
npm run build:tokens
```

Check that your token appears in `dist/ai/ai-token-guidelines.json`.

## Best Practices

### Writing Good Usage Arrays

- Use lowercase, hyphenated terms: `focus-indicator`, `delete-button`
- Be specific about component types: `modal` instead of `overlay`
- Include common synonyms if helpful

### Writing Effective Rules

Use RFC 2119 keywords for clarity:
- **MUST** - Absolute requirement
- **MUST NOT** - Absolute prohibition
- **SHOULD** - Recommended but not required
- **SHOULD NOT** - Discouraged but not prohibited
- **MAY** - Optional

Example rules:
- ✅ "MUST use for focus rings on interactive elements"
- ✅ "Do NOT use for subtle dividers"
- ✅ "SHOULD pair with fgColor.onEmphasis for text"
- ❌ "Use this for buttons" (too vague, no clear directive)

## Architecture

### Files

| File | Purpose |
|------|---------|
| `src/filters/hasAiExtensions.ts` | Filter for tokens with `org.primer.ai` |
| `src/formats/jsonAiGuidelines.ts` | Format outputting flat AI-optimized JSON |
| `src/platforms/aiGuidelines.ts` | Platform configuration |

### Build Integration

The AI guidelines build step in `scripts/buildTokens.ts` processes all functional tokens and outputs only those with AI extensions.

## Testing

Run the tests to verify your changes:

```bash
npm test -- src/filters/hasAiExtensions.test.ts
npm test -- src/formats/jsonAiGuidelines.test.ts
```
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation references 'org.primer.ai' but the actual implementation uses 'org.primer.llm'. The documentation consistently refers to the extension namespace as 'org.primer.ai' throughout, but all code files (schemas, filters, formats) use 'org.primer.llm'. This creates confusion and will mislead contributors.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +50
{
"base": {
"color": {
"aquaBlue": {
"500": {
"key": "{base.color.aquaBlue.500}",
"$value": "#2C29FF",
"$type": "color",
"$description": "The primary color for interactive elements.",
"filePath": "integration/tokens/base.json5",
"isSource": true,
"original": {
"$value": "#2C29FF",
"$type": "color",
"$description": "The primary color for interactive elements.",
"key": "{base.color.aquaBlue.500}"
},
"name": "500",
"attributes": {},
"path": [
"base",
"color",
"aquaBlue",
"500"
]
}
}
}
},
"fgColor": {
"link-rest-01": {
"key": "{fgColor.link-rest-01}",
"$value": "#2C29FF",
"$type": "color",
"filePath": "integration/tokens/functional.json5",
"isSource": true,
"original": {
"$value": "{base.color.aquaBlue.500}",
"$type": "color",
"key": "{fgColor.link-rest-01}"
},
"name": "link-rest-01",
"attributes": {},
"path": [
"fgColor",
"link-rest-01"
]
}
}
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These integration build files appear to be generated test artifacts that should be excluded by .gitignore. The .gitignore file has a syntax error on line 10 that prevents "integration/build" from being properly ignored. Once the .gitignore syntax is fixed, these files should not be tracked in version control.

Copilot uses AI. Check for mistakes.
$type: 'typography',
$description: 'Compact small font with a smaller line height of 16px. Use it for single-line scenarios, as the small sizing doesn’t pass accessibility requirements.',
},
$description: 'Compact small font with a smaller line height of 16px. Use it for single-line scenarios, as the small sizing doesn’t pass accessibility requirements.', $extensions: {
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing line break between the closing brace of $description and the $extensions property. The $description string on line 453 runs directly into the $extensions object on line 453 without proper JSON5 formatting. These should be on separate lines.

This issue also appears in the following locations of the same file:

  • line 458

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants