pathway-ds

Agent instructions for pathway-ds

Persistent rules for any AI agent working on this repository. These apply across sessions — don’t wait to be told them again. If a rule here conflicts with something in a specific conversation, follow the rule here unless the user explicitly overrides it in the moment.

1. Source of truth — who wins when sources disagree

Different layers of this system have different sources of truth. Keep them straight.

What Source of truth Flow
Design tokens (primitives, semantics, modes) Figma → exported to tokens/figma-export/pathwaytokens.json Automatic. CI runs sync-tokens.jsstyle-dictionary → Storybook.
Component implementations (HTML demos, specs, stories) GitHub (the files in this repo) Manual. Designer changes a component in Figma → user asks agent to pull → agent uses Figma MCP tools to fetch the updated node → agent edits the component’s files in this repo.
Component visual design (variants, frames, anatomy, variables-bound properties) Figma Same manual flow as above. Figma is the design artifact; this repo carries the implementation.

Practical implications:

2. Token sync — how Figma flows into this repo

The pipeline, in order:

Figma (source of truth for tokens)
  │
  │  Designer exports via "Variables Import Export" plugin
  ▼
tokens/figma-export/pathwaytokens.json          ← committed as-is
  │
  │  scripts/sync-tokens.js  (GitHub Action: sync-tokens.yml on push to figma-export/)
  ▼
tokens/pathway-design-tokens.json               ← DTCG-format derived file
  │
  │  node style-dictionary.config.js  (called by deploy-storybook.yml)
  ▼
src/tokens/tokens.css, src/tokens/tokens.js     ← consumed by Storybook + components

Rules:

2.1 Dark mode — ENABLED (2026-05-05)

Dark-mode tokens are now imported from the Figma export. The EXCLUDED_MODE_SLUGS set in sync-tokens.js is empty — all modes come through, including dark.

3. Component reconciliation after token changes

When the token library changes — every time sync-tokens.js runs and modifies tokens/pathway-design-tokens.json or the CSS variable set — every component in components/** that references those tokens must be reconciled against Figma.

Principle: the source of truth for which tokens a component uses is Figma, not the component’s current GitHub files. If Figma says the SideNav uses fill/contextual/navitem/base and the repo says it uses some other token, Figma wins. If a token the repo mentions no longer exists, the fix comes from Figma.

3.1 When to run reconciliation

3.2 Algorithm

  1. Diff the token set. Compare tokens/pathway-design-tokens.json at HEAD against its state before the sync. Classify each change: added, removed, renamed (a disappeared name + a new name whose value matches are probably a rename — flag as a rename candidate for the user to confirm; don’t auto-rename aggressively).

  2. Find components that reference changed tokens. For each file under components/**, src/stories/Library/**, and any src/tokens/tokens.* consumer, grep for:
    • CSS variable names like --semantic-color-light-mode-icon-static-neutral-base
    • Token-path mentions in Markdown like icon.static.neutral.base or Icon/Contextual/NavItem/Base
    • Any direct hex values that the spec claimed came from a token (these indicate a hand-copy that’s now stale) If the mentioned token appears in the removed or renamed set, the component is a reconciliation candidate.
  3. For each candidate component, fetch Figma truth. Open the component’s Figma node (see §3.4 for where its node ID lives) and call:
    • get_variable_defs(nodeId) — returns every variable currently bound to that node and its descendants
    • get_design_context(nodeId) — the current reference code with token bindings Compare the set of tokens returned by Figma against the set the component’s GitHub files reference.
  4. Reconcile in this order:
    • If Figma’s token set matches the repo’s updated token set: update the component’s GitHub files to use the new token names / values. Update HTML, CSS, stories, spec — all of them, together. Verify Storybook still builds.
    • If Figma’s token set also references a missing token (Figma itself is out of sync with the newly-updated tokens): add this component to the “needs manual attention” list (see §3.5). Do not rewrite the component to use a different token as a guess.
    • If the Figma fetch fails (node deleted, MCP error after retry): add the component to the list. Do not guess.
  5. Commit reconciled components. One commit per logical component update, with a message that says why the change was needed (e.g. “reconcile spinner: icon.static.brand-warm renamed to icon.static.brand”).

  6. Report unresolved items at the end of the run. Format (one line per item):
    <component-name>  ·  <file-path>  ·  <stale-token-name>  ·  <reason>
    

    Where reason is removed-from-tokens, renamed-to-<new>, figma-also-stale, or figma-fetch-failed. The user fixes these in Figma, re-exports, and re-runs the sync.

3.3 What reconciliation does NOT do

3.4 Every component must expose its Figma node ID

For reconciliation to work without asking the user every time, every components/<name>/<name>-spec.md must contain a “Figma source” section with the file key and the root node ID in a parseable form. The existing sidenav and spinner specs follow this convention:

### Figma source
- **File:** [<display name>](https://www.figma.com/design/<fileKey>/...)
- **<Component> component:** [Open in Figma](https://www.figma.com/design/<fileKey>/...?node-id=<nodeId>)

Reconciliation agents extract <fileKey> and <nodeId> from the URLs with a regex. Do not remove those links or change their format. When adding a new component, copy the pattern exactly.

3.5 Reporting unresolved reconciliation items

When a component can’t be reconciled cleanly, emit a short block at the end of the run. Example:

Reconciliation — 2 components need manual attention:

  spinner
    file:   components/spinner/spinner-spec.md
    stale:  icon.static.accent-jade.base
    reason: removed-from-tokens
    next:   delete the accent-jade branch from the Figma spinner node,
            or restore the accent-jade tokens in Figma

  sidenav
    file:   components/sidenav/sidenav-spec.md §3.3
    stale:  text.contextual.navitem.active
    reason: figma-also-stale  (Figma still aliases this to {Blue.180},
            which no longer exists)
    next:   open sidenav in Figma, re-bind the Active text variable
            to a real primitive, re-export, re-run sync-tokens

Keep entries short. The user decides which ones to act on; your job is to surface the list accurately, not to fix it silently.

3.6 Updating a component from Figma (unrelated to token changes)

When the user says “I changed the spinner in Figma, update GitHub” or “pull the new sidenav design” — i.e. the component itself changed, not just its tokens — follow this flow. It’s related to but distinct from §3.2 (which runs in response to token changes).

  1. Identify the Figma node. Use the spec’s Figma source section (§3.4); ask for a URL if one isn’t there.
  2. Fetch the current state via the Figma MCP server:
    • get_design_context — reference code + variable bindings
    • get_metadata — structural overview for large nodes
    • get_screenshot — visual reference
    • get_variable_defs — resolved token values bound to the node
  3. Extract raw assets when needed. For SVG geometry, get_design_context returns a figma.com/api/mcp/asset/<uuid> URL; curl it. If it 500s, retry a few times before giving up.
  4. Diff against the current files in components/<name>/. Update the HTML demo, the -spec.md, and any src/stories/Library/<Name>/ files together — they must stay consistent.
  5. Keep the spec structure intact. See §5 for the required spec sections.
  6. Verify. Rebuild Storybook locally (npx storybook build) before committing. A broken Storybook build blocks CI.

4. File layout and naming

5. Component specs

Every <name>-spec.md must follow the structure of components/sidenav/sidenav-spec.md. At minimum it has:

  1. Component Overview — what it is, what it isn’t, decision boundaries
  2. Governance table — “where things live” mapping (Figma nodes, this spec, token files)
  3. Anatomy — DOM structure, key elements
  4. Variant system — if the component has variants, how they compose
  5. Token mappings — every colour/size/motion must cite a semantic token. Never reference primitives or raw hex directly in specs.
  6. Decision tree — when to use / when not to use
  7. Accessibility — role, ARIA, keyboard, screen reader announcements, reduced motion, contrast
  8. Motion spec (if animated) — keyframe, duration, easing, direction, reduced-motion behaviour
  9. HTML usage examples — real markup, at least one minimal + one in-context
  10. Constraints — hard rules that must not be broken
  11. Gaps — known problems, flagged by priority

New components that don’t yet need every section can omit, but match the depth of sidenav-spec for the ones they do include.

6. Colour rules for components

Components resolve colour only through semantic tokens — never raw hex, never primitive tokens, never invented semantic names.

Forbidden in any component CSS or spec:

Before writing any colour into a component, grep tokens/pathway-design-tokens.json to confirm the token name and family exist.

7. Naming, casing, and slugs

8. Non-Pathway content belongs elsewhere

If files accumulate at the repo root that don’t belong to the design system (one-off audits, scratch prototypes, unrelated assets), move them to the sibling repo:

Don’t let the design system repo become a junk drawer.

9. Deployment and CI

Three GitHub Actions live in .github/workflows/:

  1. sync-tokens.yml — fires on push to tokens/figma-export/**. Runs sync-tokens.js, commits the result.
  2. sync-component.yml — fires on push to components/sidenav/sidenav.html. Regenerates sidenav-figmamake.html.
  3. deploy-storybook.yml — fires on push to tokens/, src/, .storybook/, components/, docs/, or config. Runs Style Dictionary + Storybook build, commits the output to /storybook/ on main, GitHub Pages serves it.

The deployed Storybook lives at:

Data flows one way: GitHub → Storybook. Nothing ever flows from Storybook back to GitHub. If Storybook appears out of date, the fix is a push to main, not a Storybook rebuild.

10. Component pipeline: Figma to GitHub to Storybook

Every new component follows the sequence documented in docs/component-pipeline.md. The key points for agents:

  1. The .jsx is the shared source of truth. components/<name>/<name>.jsx exports the React component. Storybook stories import from it; the standalone .html demo inlines the same logic. When the component changes, update both.
  2. File convention: <name>.jsx + <name>.html + <name>-spec.md in components/<name>/. Stories at src/stories/Library/<Name>/.
  3. Map Figma variants → Storybook argTypes. Boolean props → boolean control. Enum props → select control. Number props → number control with min/max.
  4. MDX docs follow docs/storybook-authoring.md — narrative prose, Playground + Controls at the top, state matrices as live components (not tables), token rows as name/swatch/hex, accessibility section that cites the overarching spec for system-wide rules. Never bury the Playground below reference tables.
  5. components/manifest.json is the machine-readable component registry. Update it when adding or changing a component.
  6. Designer prep: the designer must complete docs/figma-prep-checklist.md before handoff. If they haven’t, run the /pathway:component-readiness skill (or send them the checklist) — don’t guess.
  7. The overarching design-system spec (docs/design-system-spec.md) defines system-wide rules for motion, accessibility, colour, spacing, typography, naming. Every component spec inherits from it. Conflicts between a component spec and the overarching spec are resolved by the /pathway:spec-review skill, which requires explicit human sign-off on any deviation.

10.1 The Pathway skills

The component pipeline is broken into four skills so different audiences can use what applies to them:

Skill Audience What it does Touches repo?
/pathway:component-readiness Any designer Runs Figma prep checklist against a component, reports findings ❌ read-only
/pathway:component-spec-maker Any designer Drafts a -spec.md from a Figma component using the template; marks Status: PENDING HUMAN REVIEW ❌ local only
/pathway:spec-review Any designer Reads a draft spec + the overarching spec; walks the user through every conflict; flips Status: to REVIEWED only when all resolved ❌ local only
/pathway:component-pipeline DS owner --mode=create or --mode=update. Composes the three skills above → generates .jsx + .html + stories + MDX + manifest → commits + pushes ✅ writes + pushes
/pathway:tokens-sync DS owner Syncs Figma token export, rebuilds Style Dictionary + Storybook, commits + pushes ✅ writes + pushes

All five skills ship in the JoLopez-Product-Plugins plugin (Claude Code). To install:

/plugin marketplace add helloimjolopez-collab/JoLopez-Product-Plugins
/plugin install pathway@jolopez-product-plugins

Token sync (update-tokens) is separate — it runs on token changes, independent of component work.

11. Human review at every step

Non-negotiable principle: every Pathway skill requires explicit human approval at every gate. Claude drafts, recommends, flags — humans decide.

11.1 What this means in practice

11.2 What this means for agents

Any agent working on a Pathway task must preserve these gates. If you’re composing a larger workflow (e.g. “create a dashboard with the design system”), you still pause at each gate. Skipping a gate to “save time” breaks the principle; a batched-questions implementation is a bug, not an optimisation.

11.3 When the user is explicit

If the user says “just do it, don’t ask me” for a specific action, proceed with that action — their explicit permission replaces the gate. But the next gate still applies unless they’ve scoped the permission broadly (“do the whole thing, don’t ask me”).

12. Things that are always wrong