Agent-ready Material Generation Skill
Derive the design-system definition; delegate Figma mutation to the official execution skills. Optimize for 10% high-leverage user decisions and 90% traceable system derivation.
Stage -1 — Required host and Figma MCP gate
Before user input collection, derivation, inspection, or generation, follow agent-environment.md. This prerequisite applies to every user-facing mode, including Markdown-only output. Reuse a verified official Figma connection; if missing, install it through the active host, complete OAuth/reload, and verify use_figma plus the other required tools. Stop and explain missing capabilities or an unsupported host. A configured server or successful whoami alone is not READY.
Use the actual host's skill loader and namespaced skill names. Resolve all bundled script/reference paths from this skill's directory, not the user's working directory. If companion skills are not separately discovered, load their SKILL.md under this bundle's skills/ directory. Install missing official Figma execution skills through the host's supported route before any Figma execution.
Non-negotiable boundary
Treat this skill as the decision, grammar, derivation, and validation layer.
-
Do not reimplement Figma Plugin API mechanics, node-ID handling, state ledgers, idempotency, cleanup, metadata inspection, screenshots, or error recovery.
-
Load and obey
$figma-generate-librarybefore planning or building the library in Figma. -
Load and obey
$figma-usebefore everyuse_figmacall. Never calluse_figmawithout it. -
Load
$figma-create-new-filebefore creating a Figma file when no target file exists. -
Load
$design-system-contract-genonly when the user requests the L0–L7 Markdown contract, either beside a generated Figma library or from an existing read-only Figma source. In a Figma-only run, preserve every existing Figma workflow artifact and gate, but do not add Contract IR, the L0–L7 package, or a Markdown acceptance gate. -
Resolve conflicting instructions in this order:
agent-ready-material-generation-skillspecific domain contract → generic$figma-generate-libraryworkflow →$figma-useAPI mechanics. Apply the higher-priority rule only to the conflicting concern, and continue to obey every non-conflicting lower-priority API, safety, schema, and runtime requirement. -
Treat existing
figma-design-system-gen.*schema, writer, package, validator, and contract identifiers as a stable legacy artifact namespace, not as the public skill name. Preserve them for compatibility unless an explicit artifact-format migration is requested. -
Apply the top-level Agent-ready text contract to every public component: expose text as a Figma Text Property when an instance consumer must supply or override it as content. Prioritize
Button.label;Input.value,placeholder,label,helperText;Dialog.title,description,confirmLabel,cancelLabel;Card.title,description; andEmptyState.title,message,actionLabel. Do not manufacture a property for content the component does not own, and keep decorative text, fixed brand copy, and non-overridable system labels internal. This content-parameter decision overrides a designated structure's omission, but never mutates the raw source IR. -
Apply the direct Semantic Color contract:
bg/*pairs withtext/*;border/*,ring/*, anddecorative/*are the other public prefixes. Treat Status as a documentation grouping overbg/{destructive|success|warning}andtext/{destructive|success|warning}-foreground, not astatus/*namespace. Fold shared primary interaction states intobg/primary-hoverandbg/primary-pressed. Defaultbg/accentto the neutral scale—neutral/100in Light andneutral/800in Dark—and permitbrand/100plusbrand/900only whenvisual.accent_source=brandis explicitly supplied. Generateborder/default,border/strong, andborder/destructive, withborder/strongas the reusable one-step-higher-contrast boundary formerly namedborder/input. Generate the pairedring/focus,ring/strong, andring/destructive; each Ring aliases the next stronger Primitive step than its corresponding Border in the effective mode: Light moves+100, Dark moves-100. Therefore the defaults arering/focus=neutral/300|700,ring/strong=neutral/400|600, andring/destructive=destructive/600|400. Do not generatedata/*; charts and categorical visualization usedecorative/*directly. Every Semantic Variable owns Light/Dark Primitive aliases directly. Do not introducecolor/*,utility_aliases,chart-*,tag/*,fill/chart-*,stroke/chart-*, component categories, or parallel surface tiers such asbase,subtle, orraised;strongis reserved exclusively for the paired reusable boundary rolesborder/strongandring/strong. Every projected Primitive and Semantic Color Variable must have aVariable.descriptionstatingWhat it controlsandUsed by.text/secondary-foregroundis mandatory for every meaningful description, explanation, supporting line, caption, note, timestamp, author, and metadata item; in Light bind it toneutral/500with the canonical recorded contrast waiver.text/muted-foregroundis restricted exclusively to placeholder and disabled content. It is forbidden for every meaningful descriptive, explanatory, supporting, caption, note, or metadata text and its Variable description must explicitly direct designers totext/secondary-foreground; in Light bind it toneutral/200with the canonical contrast waiver, and in Dark choose the lowest-emphasis neutral step meeting the requested text-contrast target on bothbg/backgroundandbg/muted. Shadcn compatibility names remain code mapping metadata only. -
Generate
text/brandas the direct brand-emphasis text role. Use it only for links, inline navigation/actions, and short highlighted brand text. For each mode, choose the nearest brand step tobrand/500that meets the configured normal-text contrast target on bothbg/backgroundandbg/secondary. Do not use it for body copy, descriptions or metadata, status content, placeholders, disabled content, or content onbg/primary; Link Button label, icons, and spinner useBRAND_CONTENT → text/brand. -
Keep neutral hue coherence deliberately restrained. Cap derived neutral OKLCH chroma by personality at
minimal=.0045,modern=.012,expressive=.018,editorial=.006, andtechnical=.005; validation permits only.002conversion tolerance above the applicable cap. -
Before building or repairing every component, load the live
Colorcollection and read every candidate Variable's ID, exact name,description, collection, resolved type, scopes, code syntax, mode values, and Primitive alias targets. The caller supplies only structured consumer facts and a local appearance intent; it must not preselect an exact Variable name. Apply the global surface/foreground pair, status-family/channel, and content-purpose constraints first, then filter the live metadata catalog by name, usage description, scope, resolved type, and complete aliases; exactly one candidate must survive. Metadata is therefore the selection input and decisive filter, not a post-selection check.bg/primarypairs withtext/primary-foreground,bg/secondarywithtext/secondary-foreground,bg/accentwithtext/accent-foreground, and each status surface with its same-family foreground. Structured Error states route their status-bearing boundary/content channels to the destructive family: for example Input Error usesborder/destructive; a Destructive Button usesbg/destructiveplustext/destructive-foreground. Placeholder content usestext/muted-foreground. Name-only lookup, component/Variant substring inference, caller-supplied standard roles, direct Primitive binding, missing/generic descriptions, stale catalogs after a foundation change, global constraint mismatches, and zero or multiple candidates are blocking errors. Before callingsetBoundVariableForPaint, resolve the selected Semantic Variable for the actual consumer and effective mode, and seed the paint's raw RGB/opacity with that resolved value; a generic gray/black placeholder behind a valid binding is a blocking visual mismatch because Figma exports and screenshots can expose the fallback. Record consumer facts, candidate counts, decisive metadata fields, selected Variable metadata, resolved fallback color, and rationale for every binding. -
Treat component-inventory.json as the only authoritative Core/Normal/Pro component catalog. Interpret its
core,normal, andprogroups cumulatively, preserve their order and bilingual labels, and never add components automatically fromproduct_type. Add any business-specific or retired component only through an explicitscope.include, then applyscope.excludelast. -
Treat a user-designated component's source node kind, root Auto Layout, and resizing as structure, not visual styling. Preserve whether the source is a
COMPONENT_SETor a standaloneCOMPONENT, its explicit unavailable Variant combinations, and each actual configuration's direction, wrap, HUG/FILL/FIXED axes, alignment/distribution, padding, gap, stroke-in-layout behavior, and intentional fixed dimensions. A designated Button root must remain horizontalHUG × HUG; fixed-width Button main Components are a blocking error. An instance may use FILL when composed in a compatible parent, but that does not change the main Component's default HUG contract. -
Execute every Figma mutation sequentially, including writes to different Pages. Never use parallel multi-Page fan-out for calls that create, update, delete, import, bind, move, rename, or otherwise mutate Figma nodes, Variables, Styles, Components, libraries, or workflow state. Split multi-Page writes into one
use_figmacall per target Page, set the current Page at most once in that call, wait for its result, validate it, and only then issue the next write. -
Parallel multi-Page fan-out is allowed only for read-only discovery or audit calls that cannot mutate Figma, shared state ledgers, or external state and whose results do not depend on one another. If read-only status is uncertain, execute sequentially.
-
Never write guessed node IDs or Figma execution data into the canonical grammar.
-
Treat presentation-style-contract.json as the sole runtime authority for generated presentation styling. When the user supplies a Figma object as a visual standard, inspect it once, normalize its complete role-based structure and visual properties into this bundled local contract, update the matching validation profile, and then generate exclusively from the local contract. Never require the source Figma file, URL, file key, node ID, or live object to remain accessible. Keep presentation styling in this contract and keep foundation derivation, color semantics, component behavior, and inventory logic outside it.
-
Use raw unbound #FFFFFF (Light) / #000000 (Dark) presentation paint on every Page-direct documentation root and Contract Bar, including Component and instructional roots. Never generate
bg/documentationor an equivalent documentation-only product Variable, token export, or color swatch. Every Frame named exactlySpecimen Stageor ending in/ Specimen Stageis fill-less (fills=[]) with no fill Variable binding in both Foundation and Component documentation. Keep the primary Component groupHUG × HUGand center its bounding box horizontally and vertically within the stage's inner bounds; annotation chrome is not part of the centering measurement. The raw unbound root background rule and the fill-less Stage rule must both be verified from live Figma read-back. In the Foundation Typography frame,Type Scale / 字体层级itself is also fill-less (fills=[]) and has no fill Variable binding. -
Treat component-appearance-contract.json as the sole runtime authority for component appearance. Every active Core, Normal, and Pro component is fully refined in the
design-system-v0.6baseline and must resolve one exact bundled local appearance authority before projection: a normalized profile record or an explicit executable requirement record. Preserve its public properties and defaults, anatomy, child order, layout laws, intrinsic geometry, paint/stroke/effect presence, semantic part roles, state deltas, icon/Slot composition, ComponentSet documentation grammar, and mandatory Examples. Re-derive only Foundation values and semantic token resolutions from the current run's key design decisions.UNREFINED, generic/inferred appearance, Foundation-only fallback, runtime source reads, and old cached plans without the exact current baseline ID and contract SHA-256 are blocking errors. Source file/node IDs remain provenance only. -
Treat Skeleton as a transparent structural Component whose visible Avatar, Line, and Object placeholder Instances—and their local helper main Components—bind their fill to
bg/secondary. Never paint the Skeleton root, never usebg/mutedfor its visible placeholders, and never substitute a raw or unbound literal fill. -
Treat Slider Horizontal as a freeform
240 × 16ComponentSet whose Variant roots are always fillless. Center every.Markervertically, bind its primary fill and 1pxborder/defaultOUTSIDE stroke through local Variables, and keep the local.Markermain Component childless so the Marker instance has no descendants; a nestedVectoror any other geometry child is forbidden. Remove every stroke fromValue; Active-state surface rules never apply to the Slider root. -
Treat every Date Picker Variant root as
HUG × HUGand stroke-free in every State, including Focus; focus presentation belongs only to the nested Input. Fail when its nested Input exceeds the root bounds. BindDecoration leftdirectly to the exact bundled local.Icon / CalendarComponent with proportionalSCALE / SCALEbehavior; Generic Icon wrappers, generated calendar geometry, remote icons, and substitutes are forbidden. -
Preserve the explicit v0.8 detail contract in every future generation: each Tabs Slot contains exactly two Label Tab instances ordered
ActivethenInactive; every Dialog Footer two-Button group binds an 8pxspace/2gap; Dialog Slot left/right padding bindsspace/4(16px) to match Header/Footer; Select ends with the exact local.Icon / Chevron Down; every visible Field Label Text layer alignsLEFTand its fill-width Label container aligns content to the leading edge with primary-axisMIN; Slider stays 240×16 withOverall=240×4@(0,6), Default0–60%, Range Narrow40–60%, Range Wide20–80%, and 16px endpoint-centered Markers; Date Picker fixes.Icon / Calendarleft and.Icon / Chevron Downright; Empty Description is exactly 280px wide withCENTERtext alignment; every Pagination Number Button defaults to the editable text1; and Pagination documentation contains exactly one first-page-active Example with exactly five numbered pages ordered1, 2, 3, 4, 5between Previous and Next, with no ellipsis or additional page. Treat zero gaps, placeholder 100×100 Slider children, wrapper substitutes, centered Field labels, genericButtonpagination copy, the old two-row/ten-page Pagination specimen, or derived alternatives as blocking drift. -
Preserve the explicit shallow status-tint refinement in every future generation: derive only
destructive/100andsuccess/100with a0.90light-endpoint blend instead of the generic0.80interpolation so they remain visually closer to their50tints. With canonical anchors the exact results aredestructive/100=#FFE7E4andsuccess/100=#D1FBD7. Keep their50,200–950, and500anchor values unchanged, and never apply this exception to warning, brand, or decorative families. -
Generate Calendar dates through one local reusable
.Calendar / DayComponentSet:Position = Middle | Left | Right | Single×State = Default | Selected | Active | Disabled, plus one editabledayText Property. Cells are 28×28 and centered; selected/active range edges follow the joined full-radius law, Default/Disabled remain standalone full-radius cells, and all paint/radius decisions bind generated local Foundations. Document this set deterministically with non-Size axes vertical and explanatory copy. Every Calendar header includes real local Small/Outline/Default Button instances using the exact bundled.Icon / Chevron Leftand.Icon / Chevron RightComponents with proportional scaling. Every Calendar root is verticalHUG × HUGand binds all four paddings tospace/4(16px), resolving the three-month root to652 × 252around its intrinsic620 × 220visual. Never read the designated external sample at generation time. -
Obey
component-appearance-contract.json#/learning_policywhenever an Obra source is captured or refreshed. Learn only node kind, ordered public properties, Variant axes/defaults/unavailable combinations, semantic anatomy and child order, Auto Layout and resizing, intrinsic fixed dimensions, paint/stroke/effect channel presence, state deltas, text roles, icon roles and anchors, Slots, responsive behavior, and specimen composition. Do not learn Obra brand copy, example text/data, images, canvas coordinates, runtime IDs, raw colors or source Variable IDs, unmapped foundation values, accidental implementation, missing Text Style bindings, broken constraints, deprecated APIs, or unrequested prototypes. Normalize colors to local semantic intent, typography to canonical local Text Styles, and icons to real Instance/Swap nodes with proportionalSCALE / SCALE; unresolved or ambiguous evidence is an error. The latest explicit user rule always wins after source capture. The bundled 44-recordsource_learning_snapshotis the complete run-independent evidence set; do not reread Obra during generation unless the user explicitly asks to refresh the learned source. -
Obey
component-appearance-contract.json#/deterministic_generationfor every derivation and Figma projection. Randomness, time-based branching, arbitrary copy variation, unordered emission, generic fallback, and “choose any valid option” are forbidden. Resolve the same normalized inputs through the declared inventory, source, property, Variant axis/value, profile-layer, anatomy, and row-major documentation orders; use contract-defined or content-derived stable identities; and fail on missing or ambiguous contracted values. Before a generated artifact can drive Figma, derive it twice and usescripts/determinism_contract.pyto require equal canonical UTF-8 JSON SHA-256 values after excluding only the declared runtime identity fields. A mismatch is blocking, not a retry signal. -
Apply
shared_slot_stylefrom component-appearance-contract.json to every generated real Slot whose default content is empty or placeholder text. Keep the Slot container's raw unbound#C89DFFdashed inside stroke as authoring chrome, but bind the centeredEditable slotplaceholder Text fill through the contract'sPLACEHOLDER_OR_DISABLED_CONTENTSemantic intent; metadata selection must resolve it to the existingtext/muted-foregroundColor Variable and seed the fallback paint from that Variable's effective mode. Raw or unbound Slot placeholder text color is forbidden. The Slot container uses left/start primary-axis alignment with centered counter-axis alignment andHUG × HUGsizing. The placeholder must use automatic layout positioning, centered text alignment, and fit without clipping; shrink only fallback placeholder typography when necessary and never force the Slot back to a former fixed size. Treat every visible non-placeholder child, including user-supplied Text, as real Slot content: preserve it, never inject the placeholder, and remove the Slot container’s authoring stroke and dash pattern immediately after insertion. Apply this to nested instances and examples as well as main Components; empty main Slots keep their placeholder chrome. Treat the local record as the sole runtime source and fail closed when it is missing; the historical Figma source is not a runtime dependency. -
For the Agent package, load GENERATION.md and the affected component contracts before deriving or repairing. These local contracts drive the shared writer and live audits. Preserve the accepted v0.8 refinements: Markdown Link and Inline Code use
text/brand; Response usesAvatar With Imagefollowed by an editable Label and default-visible Hover actions; Complete expanded Reasoning wraps with HUG height and no truncation; ToolCall Text contains only Summary, collapsed disclosure uses.Icon / Chevron Right, and File includes a substantial code example; SourceCard defaults to the Card width (380px) and fills its nested content tracks; populated Slots have no authoring stroke; DiffViewer shares the Markdown Code Block file shell. ChatMessageFile is file-only with all 23 formats × Loading/Complete/Error; ChatMessageMedia is a separate Queued/Generating/Complete/Error Component Set, normalized from its bundled reference contract and using canonical local tokens/styles. Reconcile Media before File to migrate legacy media consumers, and map legacy file Default to Complete. ChatBox preserves its bundled composer reference with visible editable input text and independentShow upload,Show model, andShow voiceBooleans; compose its connected four-state Send Button and five-state Upload Card, remove Folder/Permissions and hidden text proxies, and run the dedicated eight-combination ChatBox audit. -
Treat
packages/agent/components/a2ui.jsonas the canonical A2UI reference contract. Generate all nine public groups inside oneComponent / A2UIframe: shell, Header, Footer, Question Item, Question, Text, Capabilities, Card and Table. Preserve the 22 public configurations, native Content/Options Slots, connected local controls and Avatar With Image, HUG heights and FILL content widths. The shell uses Default / Collapsed / Complete; Complete hides Footer. Place exactly three examples below every group: ChatMessageApprovalRequest (Text), ChatMessageTaskPlan (Table), ChatMessageClarification (Question), each a real A2UI instance populated through Content Slot. Retire the former three independent public families and docs; check live consumers before deleting owned legacy sources. Keep the reference file/node IDs as provenance only. Execute the sharedagent-a2uigroups,agent-a2ui-docsandagent-a2ui-auditin both repeatability runs. -
Paint presence is semantic.
fills=[]orstrokes=[]means absent and must remain absent unless the resolved local appearance profile explicitly declares a paint slot. Variable binding may replace the color of an existing/required slot but may not create a fill, stroke, or focus ring implicitly. Disabled, hover, focus, invalid, and selection states may change only fields declared by their resolved profile. By default, every focus boundary uses a declared stroke channel withring/focus, orring/destructivefor an error/destructive focus selection; only an explicit local user refinement may define an exact alternative such as Tab Inactive Focus matching Hover. Focus shadows and DROP_SHADOW effects remain forbidden. -
Treat icon color as terminal vector geometry, never as a wrapper paint. For every icon, spinner, glyph, or decoration target, keep the owning Instance and every non-terminal
Icon,Icon Vector, Frame, Group, Component, or Instance wrapper free of fills and strokes; bind the selected Semantic foreground to each actual terminal vector fill/stroke leaf. Fail closed when no terminal paint leaf exists, and make live validation reject any painted icon wrapper so a semantic fill can never become a rectangular icon background. -
Treat component-appearance-contract.json
#/image_assetsas the only image source for every generated component. Use bundledassets/images/avatar-primary.pngfor every avatar/person image, including everyAvatar With Imagesize and every nested Avatar inAvatar Stack; useassets/images/content-primary.jpgonly for general content imagery. Verify path existence and exact SHA-256 while compiling the single generation plan. After component structure reconciliation and before component appearance reconciliation, emit the canonicalasset-targetsstage, resolve target nodes only through documentation-frame/component/contract paths, upload the bundled bytes to every returned node withscaleMode=FILL, and reject external URLs, generated substitutes, additional uploads, stale hashes, persisted target IDs, or one-off target patches. -
Make every generated Foundation and Component documentation title bilingual. Render the documentation-frame title as
{English} · {中文}and every first-level or nested content title as{English} / {中文}. Kicker text, Contract Bar values, token labels, and Variable names are not content titles and keep their canonical forms. Reject monolingual documentation headings in the spec and require live Figma template read-back to verify the projected text. -
Treat spec-only validation as preflight, never as completion. Every concrete Figma run must persist a run manifest, compile the bundled presentation templates into an execution contract, and finish with a machine-readable live Figma audit from the exact target file. The final validator must bind all four artifacts by run ID, file key, SHA-256 digests, exact projection inventory, and template read-back before
completion_eligiblemay be true. -
Record every user-designated Figma style source in the run manifest even after its visual rules are normalized locally. Preserve its file key, node ID, URL, role, active/superseded status, and normalized contract pointer for provenance, while setting
runtime_dependency: FORBIDDENso generation never depends on that external object.
Start by routing references
Read only the references needed for the current stage, but read each selected file completely.
Resolve all bundled paths relative to this SKILL.md. Invoke bundled scripts by their resolved absolute paths; do not assume the current working directory is the skill folder.
| Stage | Required reference | |---|---| | Collect or normalize inputs | design-decisions.md | | Resolve Core, Normal, or Pro component scope | component-inventory.json | | Apply read-only discovery evidence | discovery-evidence.schema.json | | Derive foundations | foundation-derivation.md | | Define the canonical IR | system-spec.md | | Extract or derive components, states, composition, or appearance | component-grammar.md, shadcn-component-ir.schema.json, figma-component-structure-ir.schema.json, and component-appearance-contract.schema.json when user-designated Figma references exist | | Define or audit Agent-ready behavior | agent-ready-rules.md | | Lay out Figma documentation | presentation-grammar.md | | Capture or update user-supplied presentation styling | presentation-style-contract.json | | Validate, repair, or hand off | validation-and-repair.md |
Execution modes
Select one mode before Phase 0:
FIGMA_ONLY— the user requests only a Figma design system. Run the existing Phase 0–8 workflow and existing 12 deliverables unchanged. Do not create Contract IR or the L0–L7 Markdown package.MARKDOWN_WITH_FIGMA_EVIDENCE— the user supplies an existing Figma library and wants only Markdown. Keep Figma strictly read-only, clarify missing key decisions, derive and freezesystem-spec.json, reconcile its Tokens and components against live Figma evidence, then invoke$design-system-contract-gento render and validate the contract. Read figma-evidenced-markdown.md completely before starting this mode.COMBINED— the user requests both Figma and the Agent-readable Markdown contract. Run Phase 0–3 once, freeze the validatedsystem-spec.jsonand exact SHA-256, project Figma through the existing Phase 4–8 workflow, project Markdown through$design-system-contract-genusing its from-spec branch withcontract.generation_mode=COMBINED, then run Phase 9 combined acceptance.
If the user requests only Markdown without a Figma source, route to $design-system-contract-gen in MARKDOWN_STANDALONE or MARKDOWN_FROM_SPEC mode. If the user supplies a Figma library as evidence for that Markdown, this skill owns the read-only orchestration and the Markdown skill owns only the frozen-spec projection.
Mode selection must not alter design derivation. FIGMA_ONLY and COMBINED use the same Phase 0–3 inputs, defaults, schemas, generator, validation, and canonical spec bytes. Combined mode adds a sibling projection and a final cross-artifact gate; it does not make Figma depend on Markdown.
Read-only Figma evidence branch
In MARKDOWN_WITH_FIGMA_EVIDENCE, execute only the read-only parts of Phase 0, the decision collection in Phase 1, and the canonical derivation and spec-only validation in Phases 2–3. Focus Figma discovery on Variables, Styles, aliases, modes, semantic bindings, public Components and Component Sets, Properties, defaults, states, anatomy, Auto Layout, resizing, descriptions, and relationships. Do not inspect unrelated product screens or flows unless needed to resolve an explicitly scoped component or Token.
Before freezing the spec, apply the source and conflict policy in figma-evidenced-markdown.md. After freezing it, compare every scoped Token and component against a second live read-only Figma capture and write figma-spec-reconciliation.json. Do not execute Phases 4–8, do not load a Figma writer, do not create temporary specimens, and do not run Phase 9 combined acceptance. Pass the frozen spec, accepted contract context, and reconciliation artifact to $design-system-contract-gen, then run its validate-figma-evidence gate. A conflict may be documented, but it may never silently rewrite the frozen spec or be marked verified.
Fixed entry pages
Always generate Cover and Getting Started from references/presentation-style-contract.json#/templates/instructional_panel/entry_pages. Cover uses the selected B fixed 1440×900 dark editorial template (dark grid, two-line title with brand-emphasis System, native orbit geometry, footer); only declared content fields and token resolutions vary. Getting Started contains both Human and Agent four-step paths, shared delivery checks, and an Agent task example. Never retain the old generic paragraph or infer new copy/layout each run. After all presentation passes, run canonical entry-pages batches 0 and 1 sequentially, then entry-pages-audit batches 0 and 1; require zero violations and visually verify both frames in both repeatability runs. Preserve root identities when replacing owned content.
Workflow
Complete the phases in order. Keep a canonical spec on disk and update it after each accepted decision. Do not start Figma writes before Phase 3 passes.
Phase 0 — Discover source truth
- Inspect the codebase for tokens, components, prop vocabulary, frameworks, icon packages, fonts, and naming conventions.
- Inspect the target Figma file read-only through the official skills for pages, variables, styles, collections, modes, aliases, scopes, code syntax, component bindings, libraries, and conventions. Under Rule 4, do not create a new token system before this inventory and gap analysis.
- Classify each fact by provenance:
user,code,figma,library,derived-default. - Produce a gap analysis: code-only, Figma-only, compatible overlap, and conflicts.
- Resolve a conflict automatically only when one source is clearly authoritative. Otherwise present both values with provenance and ask one focused question.
When the bundled shadcn baseline applies, treat shadcn-component-ir.json as the source snapshot. It was extracted from the installed b1VoQUK0 Vite preset and contains behavior only: source identity, anatomy slots, public CVA axes, primitive dependencies, exports, data/ARIA contracts, and source-evidenced states. Never recover or copy its utility classes, resolved colors, spacing, radii, typography, or elevation into the canonical grammar.
When the user designates Figma components as structural standards, capture them in figma-component-structure-ir.json under its strict schema. Read only ComponentSet identity, ordered Component Properties, types, defaults, value sets, child Property bindings, each partial binding's exact applies_when Variant selection, root layout profiles with exact applies_when coverage, semantic anatomy profiles, variant counts, and requested documentation-frame colocation. A root layout profile includes Auto Layout direction/wrap, per-axis HUG/FILL/FIXED behavior, alignment/distribution, padding, gap, stroke inclusion, and dimensions only on FIXED axes. Exclude visual styles, resolved Variables, Descriptions, annotations, plugin metadata, and shared plugin data. This source overrides the default Figma structural projection only; it does not silently replace the shadcn behavior/code contract or the generated system's visual/token/metadata contracts.
When the user designates a Kit as the component visual baseline, capture its executable result separately in component-appearance-contract.json. Save the complete source-node index so the user never has to resend links, but normalize every ready component into local selectors and layered profiles in BASE → SIZE → VARIANT → STATE → COMPOUND order. Conflicting writes to the same target/field in one layer are errors. Correct an obvious source anomaly only through a recorded source_anomaly_corrections entry. A future generation or repair reads the local record, not the source Kit.
During an Obra refresh, inspect every source component in the bundled snapshot scope and record source variant count, ordered property types, ordered Variant axes/values, root-layout signature count, hierarchy signature count, and actual Text Style coverage before applying user refinements. Source coverage is evidence, not permission to copy defects: Obra's known missing Text Style bindings are recorded with unstyled_source_policy=DO_NOT_COPY, while generated output still requires exactly one canonical local Text Style on every Text node. Preserve the source-observed 120 Button variants in the snapshot, then deterministically project the explicit user refinement that removes Invalid to the 96-variant local structure. Reject an incomplete refresh, an unexpected source-drift relation, or a snapshot hash mismatch.
Do not mutate Figma in this phase.
Phase 1 — Collect high-leverage decisions
- Normalize the user's input against design-decisions.schema.json.
- Reuse decisions already evident in code or Figma; do not ask the user to repeat them.
- Ask only for unresolved brand, product, visual-direction, theme, accessibility, completeness, or scope decisions that materially change the result.
- Apply documented smart defaults to everything else and record every applied default.
- Lock the v1 component scope before derivation. Require
scope.completenessascore,normal, orpro; default tonormalonly when the user does not choose. Resolve it from the user-designated cumulative catalog, then apply explicit includes and excludes. Product type must not mutate the catalog. Completeness never changes foundation variables, but it may project a component's internal axes, values, public Properties, bindings, and anatomy when component-completeness-contract.json explicitly declares that projection.
Prefer inputs such as platform, product type, component-library completeness, primary color, font family, icon source, personality, density, radius character, themes, and accessibility target. Never ask the user to configure individual hover colors, spacing steps, component padding, radii, icon sizes, states, variants, or low-level Figma properties.
Phase 2 — Derive the canonical system spec
Use the deterministic generator when possible. After Phase 0, serialize verified font/icon findings separately and pass them through --discovery; never hand-edit an availability flag:
python3 <skill-dir>/scripts/derive_system.py decisions.yaml --discovery discovery-evidence.json --output system-spec.json
JSON input works with the Python standard library. YAML input requires PyYAML; use JSON when it is unavailable. Then review the result rather than accepting it blindly.
Derive in this order:
-
Foundation grammar: color, typography, spacing, radius, and iconography; preserve every supplied or canonical chromatic base at its family’s
500step, bindbg/primarytobrand/500, bind Light status backgrounds to their family100with same-family500foregrounds, and bind Dark status backgrounds to their family800with same-family400foregrounds. The Light fixed pairs retain explicit contrast waivers; the Dark pairs must meet the configured text-contrast target. Derive the neutral scale with the restrained personality-specific chroma caps above even when an explicit neutral endpoint exists, and bindbg/accentto neutral100/800by default rather than borrowing the brand ramp. Use brand100/900for Accent only after the explicitvisual.accent_source=brandopt-in. Generate the exact 52 direct Semantic Colors underbg,text,border,ring, anddecorative, includingtext/brand; include the fixed cross-theme aliasesbg/tooltip=black/100 (#000000)andbg/mask=black/50 (#00000080), plustext/inverse=neutral/0 (#FFFFFF)in both modes for every visible Tooltip foreground element; the Border/Ring pairs areborder/default=neutral/200|800 → ring/focus=neutral/300|700,border/strong=neutral/300|700 → ring/strong=neutral/400|600, andborder/destructive=destructive/500|500 → ring/destructive=destructive/600|400. Bind Lighttext/secondary-foregroundtoneutral/500for descriptions and metadata, and bind Lighttext/muted-foregroundtoneutral/200for placeholders and disabled states only; record both explicit contrast waivers and keep Dark muted content contrast-aware againstbg/backgroundandbg/muted. Keep shadcn identities such ascard,popover, andsidebaronly as code compatibility metadata. Derivevariable_descriptionsfor the 146 Primitive and 52 Semantic Variables, plus the canonical component Variable-metadata selection contract. Derive eight hue-balanced vivid decorative scales with reusable background/foreground/stroke sets for tags, badges, charts, data visualization, and accents; do not generate a duplicatedata/*layer. Generate the tier-independentShadow/sm,Shadow/md,Shadow/lg, andShadow/xlEffect Styles with exactEffectStyle.descriptionvalues and exact softened(radius, opacity)layers[(3,.06)],[(5,.08),(3,.05)],[(20,.09),(8,.06)], and[(40,.12),(15,.08)]; every node with a drop shadow must reference one of these shared Effect Styles, never a detached literal effect. Reserve motion as an extension point. Expose typography through exactly three public categories:heading,paragraph, andmonospace; generate Paragraphmini/sm/md/lg = 12/14/16/18pxat all three weights400/500/600, and generate Monospace only atmini=12pxandsm=14pxusing the selected or default monospace family. Normalizecontext.interface_languagetochineseorenglish(default English), and let it affect only Typography line height: Chinese body/monospace1.5×and heading1.3×; English body/monospace1.4×and heading1.2×. Round every result to the nearest integer and reject decimal line heights; language must not alter any other Foundation, component, or presentation output. Use the canonical radius inventorynone/xs/sm/md/lg/xl/2xl/3xl/4xl/full = 0/4/8/12/16/24/28/36/44/9999unless explicit source truth requires other values. Whenradius=round,radius/fullis conditional rather than universal: use it only for a genuinely pill-like single-line control/item or a structural pill/circle; line count alone does not force full radius. Any configuration with two or more stacked text lines, a visible supporting/description row, wrapped content, or a multiline editor must usemultiline_controland an appropriate hierarchical radius (radius/lgin the round character). Compact transient surfaces may also declare a component-specific hierarchical exception: Tooltip always resolves its dedicated role through the compact-control tier (radius/smin the round character), including Default and Shortcut one-line variants, and must never switch toradius/full. Line count overrides the component-level default only where the component contract declares line-driven radius behavior, so never classify an entire ComponentSet from its component name alone; a public second-line option must be a Variant axis when its radius differs from the one-line configuration. -
Token architecture: Primitive Color → direct designer-facing Semantic Color → code-only compatibility mappings. The exact Semantic prefixes are
bg,text,border,ring, anddecorative; every Semantic Variable owns a Light/Dark Primitive alias directly. Status is a documentation grouping overbg/*andtext/*, not a prefix. Do not createstatus/*,interaction/*,data/*, a genericcolor/*value-owner layer, autility_aliaseslayer,chart-*,tag/*,fill/chart-*, orstroke/chart-*. Color variables named for a component category are forbidden. Do not add theme tiers; compose product surfaces frombg/background,bg/secondary,bg/muted, andbg/accentinstead of inventingbase,strong, orbg/{component}. Keep shadcn component names only incompatibility_aliasesmetadata for code generation; never project them to Figma Variables. -
Component grammar: structure + variability + semantics + constraints. Apply Rule 2 to classify every capability as Variant, Boolean, Text, Instance Swap, Slot, Nested Component, or fixed anatomy before building an adapter. Every canonical
stringthat is an instance content parameter must appear inadapter_plan.text_properties; every semantic Text layer must either bind to one of those properties or carry an allowed fixed-internal classification. Start from the behavior-onlyb1VoQUK0shadcn IR when a canonical component has a baseline mapping. Preserve the ordered union of source-evidenced states that the component actually owns, then append only visual states proven by canonical code Booleans; merge semantic aliases such asselected ↔ checkedinstead of exposing duplicate states. A generic HTML/ARIA passthrough attribute or styling hook is not sufficient state ownership by itself: keep it in the source accessibility/code contract. Do not invent a code state from generic component knowledge or an old blueprint. Custom extensions without a source mapping may use explicitly declared canonical states. Keep this code-facing grammar separate fromadapter_plan.figma_component_sets: whenfigma_structure_refsexist, retain the exact source node kind, user-designated Figma Property names, order, types, defaults, values, unavailable combinations, binding targets, binding occurrence counts andapplies_whendistributions, actual configuration count, root layout profiles, and anatomy profiles as immutable source evidence even when they differ from normalized code props or state vocabulary. Reconcileadapter_plan.figma_text_property_projectionsafterward: reuse an equivalent source Text Property and audit all semantic bindings, or add the missing Agent-ready Text Property overlay. UseALL_SEMANTIC_TEXT_LAYERSwhen matching text exists throughout the anatomy andPRESENT_SEMANTIC_TEXT_LAYERSwhen it is configuration-specific; never synthesize a layer solely to satisfy binding coverage. When a target delegates or derives the content instead of owning it, recordfigma_text_property_omissionsand do not create an unbound property. Project every active component through exactly onedesign-system-v0.6refined authority: orderedfigma_appearance_refsplus exact normalized profile copies, or the equally complete explicit executable requirement record declared for that component. Missing authority blocks compilation; an absent normalized profile never authorizes structure-plus-Foundations, generic, or inferred appearance. Materialize every entry inreferences/icon-asset-contract.jsonas a real local standalone.IconComponent before component reconciliation. User-supplied SVGs stored underassets/icons/are the only icon-geometry authority: preserve their bytes and SHA evidence, append future user batches to the contract (or explicitly replace the same semantic id), and never draw, approximate, image-generate, or fall back to generated icon geometry. A registered legacy alias resolves only to its exact bundled Component. The existing Breadcrumb dot is a structural separator exception, not a reusable icon asset. Bind every imported terminal paint to its declared semantic foreground role, preserve proportional geometry, and set both terminal artwork and every use Instance toSCALE × SCALEwithconstrainProportions=true. Clear stale swap geometry overrides before proportional appearance while preserving semantic names, visibility, and Property references. A single canonical family may project to multiple public Figma structures: Tabs ownsTabandTabsinComponent / Tabs; Field ownsVertical FieldandHorizontal FieldinComponent / Field; Dialog ownsDialog,.Dialog Header, and.Dialog FooterinComponent / Dialog; Table ownsBasic Table HeaderandBasic Table CellinComponent / Table. Continue to keepTabsandSegmentedSelectoras separate canonical semantics. -
Composition grammar: rigid → instance swap; optional rigid → boolean plus instance swap; flexible → slot.
-
Presentation grammar: use the exact page skeleton
Cover → Getting Started → Foundations → --- → Components. Utilities, a trailing separator, andPlayground / Component Compositionsare forbidden in Core, Normal, and Pro. Make all five Foundation documentation frames direct children of the Foundations Page, and everyComponent / {Name}documentation frame a direct child of the Components Page. Never wrap these documentation frames in an intermediate grid, section, or root container. Place the direct Page children with explicit coordinates in horizontal-first row-major (Foundations: 10×N; Components: 6×N, excluding the index) order usingspace/20gaps. Applyframe_fill_policyfrom presentation-style-contract.json to every generated presentation Frame: immediately afterfigma.createFrame()orfigma.createAutoLayout(), assignfills=[], then add a fill only for an explicit allowlisted visual-surface role whose contract path declares it. Never let Figma's default white Frame fill survive on Header, Identity, Section, Row, column/grid wrappers, card collections, annotation containers, or component-group containers. Foundation documentation roots and other non-exempt Page-direct display Frames use an unbound raw outer background:#FFFFFFin Light and#000000in Dark. Resolve Dark from an explicit Color mode first, then an exact Dark name hint, and otherwise default to Light. Component documentation roots follow the same raw unbound background rule; their nested Specimen Stages remain fill-less. The three instructional roots (Components / Index,Foundations / Summary, andGetting Started / Root) retain their instructional template. After changing an outer paint, revalidate all visible foreground contrast and repair stale foreground bindings that depended on the former surface. Build every documentation and explanatory shell exclusively from presentation-style-contract.json. The explanatory frames preserve target text and content-stage children while matching the localinstructional_panelroles; their root and Contract Bar use raw unbound white/black presentation paint, and the Contract Bar has dividers only between cells, and their transparentradius/nonestage has zero padding. Never fetch a historical Figma source while generating. Keep the foundation summary and component index above the documentation frames as direct Page children. Never create category or one-page-per-component pages. Frame overflow policy: generatedFRAMEcontainers default toclipsContent=falseso nested effects and shadows remain visible. The only enabled-clipping roles are root Frames namedApplication Color / {Mode} / {VariableName}andDecorative Hue / {Mode} / {Hue}; both must keepclipsContent=truewith their contracted non-zero rounded corners so their internal regions are clipped to the card shape. Run the canonical frame-clip reconciliation after all frame-creating mutations, then block completion unless live readback exactly matches this allowlist, including rendered Instance descendants. Current presentation-surface override: everySpecimen StageFrame is fill-less and unbound, regardless of Foundation, Component, or instructional parent. InColor / Application, bindLight Columntobg/mutedandDark Columntobg/background. This explicit rule supersedes any older raw Stage-fill or same-token-for-both-columns wording that remains in historical rationale. Toast source specialization: expose onlyType = Success | Info | Warning | Error | Loading, keep fixed anatomyLeading icon / Message / Action / Close icon, and use exact type messagesThis is a {type} toast. Preserve instance editability without letting one shared Text Property overwrite every Type: keepmessagefor Success and use deterministic conditional Text Property isolation for Info, Warning, Error, and Loading, each with its exact type default. The root is horizontal, exactly 40px high, 320–480px wide, stroke-free,Shadow/md, andradius/fullin the round character; bind both horizontal paddings tospace/4(16px). Use exact Type pairs: Successbg/success + text/success-foreground, Infobg/secondary + text/foreground, Warningbg/warning + text/warning-foreground, Errorbg/destructive + text/destructive-foreground, Loadingbg/secondary + text/foreground. Message and leading artwork share the same Type foreground Variable. The trailing.Icon / Closealways usestext/secondary-foreground.Show actionreveals the real Extra small Ghost Default Button without changing height. Reject any raw or unbound#FFFFFFinside component definitions; structural Frames such asALremain fillless unless a named appearance contract assigns a semantic surface. Avatar source specialization: project onlyAvatar With Image,Avatar Placeholder, andAvatar Stackas separate public ComponentSets colocated inComponent / Avatar; deleteAvatar With IconandAvatar With Status Badge. Every individual Avatar boundary, image, placeholder surface, Stack holder, and nested Avatar instance must be a perfect circle with equal width and height,FIXED × FIXEDsizing, proportional constraints, andradius/full; the Stack container itself remainsHUG × HUG.Avatar With ImagepreservesSize = Default | Small | Large, contains exactly oneImagerectangle, never creates aContentwrapper, and appliesavatar-primarydirectly as aFILLimage paint at every size.Avatar Placeholderpreserves the same three fixed square sizes, centers Background andCNon both axes, uses the generated secondary surface/foreground pair, and has aborder/defaultstroke withweight=1andalign=OUTSIDE.Avatar Stackfollows the captured Obra sample withSize = Small | Regular, horizontalHUG × HUGAuto Layout, centered counter axis, exact-8pxoverlap, three avatars visible by default, and independentShow 3rd,Show 4th, andShow 5thBooleans. In every Stack variant, the root and all Holders remain paint-free, every Holder hasclipsContent=false, and the exact visible circular root of each nested Avatar instance—including hidden fourth and fifth items—owns exactly one Variable-boundborder/defaultstroke withweight=1andalign=OUTSIDE. Never put the Stack border on the Holder or behind the image, because the Small 24px Avatar intentionally overflows its 20px Holder and would cover that stroke. Every nested Avatar usesavatar-primaryonly. Breadcrumb source specialization: project.Breadcrumb item,.Breadcrumb separator, and the standaloneBreadcrumbtogether inComponent / Breadcrumb. Every item root is paint-free and borderless in every legal state.State=Defaultbinds the visible Label text or Icon terminal vector paint totext/secondary-foreground; Hover and Active change only that visible foreground totext/foreground, use the same visual result, and do not change geometry, typography, root paint, stroke, or effects. Preserve the unavailableState=Active, Content=Iconcombination.Content=Labelcontains only editable Label text;Content=Iconcontains only the replaceable Icon instance—never add Dropdown Menu or chevron-down anatomy. Preserve the two separator variants (Defaultchevron-right andCustomdot). The standalone public Breadcrumb remains a horizontalHUG × HUGcomposition container, but its realBreadcrumb ItemsSlot must ship with a visible, immediately useful local default composition: four local item instances alternating with three local separator instances, final item Active. Never renderEditable slot, an empty dashed Slot, fixed placeholder geometry, remote nested instances, or a placeholder-only public Breadcrumb. A Breadcrumb repair is incomplete until all three public sources coexist in the liveComponent / Breadcrumbframe and an independent Figma readback proves the exact variant inventory, conditional anatomy, semantic paint bindings, canonical Text Style binding, proportional icon constraints, seven-child local default composition, no placeholder text, and screenshot-visible breadcrumb content; a contract-only or test-only update must never be reported as a Figma repair. Progress source specialization: reproduce Obra node1953:17809through the bundled local contracts as one 13-variantProgressComponentSet withProgress = 0 | 10 | 20 | 25 | 33 | 40 | 50 | 60 | 66 | 75 | 80 | 90 | 100and one independentShow %Boolean defaulting to false. Every variant root is horizontalFIXED × HUGat a default width of 342, start/center aligned, with a Variable-boundspace/4gap. Its first child is aFILL × FIXED 8clipped no-paintBar;Barcontains a342 × 4defaultOveralltrack and, except at 0, one exact default-widthProgressindicator. Center Overall and Progress vertically aty=2inside Bar. Set Overall to horizontalSTRETCHand every Progress indicator to horizontalSCALE, so the track fills the root and the represented percentage remains proportional whenever an instance is stretched horizontally. Give Overall and every nonzero Progress indicatorradius/fullon both left and right ends; asymmetric leading-only or zero-radius indicators are forbidden.Percentageis the second root child, usesparagraph/mini/500, binds a metadata-purpose foreground, and binds visibility toShow %. Preserve the source indicator node types and default widths exactly: Rectangle at 10/20/25/40/50 with widths 34/68/86/137/171; Vector at 33/60/66/75/80/90/100 with widths 113/205/226/256/274/308/342. Use the generated muted surface, primary surface, metadata foreground, radius/full, and no strokes or effects on reusable anatomy. Select source specialization: preserve the full Obra source as the Pro projection withLines = 1 Line | 2 Lines | 2 Lines Altand 54 variants. Core and Normal expose onlyLines = 1 Line | 2 Lines Altand therefore contain exactly 36 variants;2 Linesis Pro-only. Keep the Lines axis in every tier, preserve1 Lineas the default, and recompute every layout/binding occurrence after tier filtering. Every projected Select variant, regardless of Size or Lines, binds both horizontal paddings tospace/3(12px), one spacing step above the formerspace/2. In a Normal or Core Figma repair, remove only exactLines=2 Linesvariants and compact the remaining2 Lines Altcolumn plus its external annotation chrome; never delete2 Lines Altas a substring match. Update the documentation Contract Bar to the projected count (36 CONFIGSfor Core/Normal,54 CONFIGSfor Pro) and reject a visually stale count even when the ComponentSet itself is correct. DropdownMenu source specialization: projectDropdown Menu,Dropdown Menu Item,Dropdown Menu Overflow,Dropdown Menu Group Label, and.Dropdown Menu Item Left Decorationas five separate public ComponentSets colocated inComponent / DropdownMenu. Preserve the source evidence, menu Slot, item visibility bindings, decoration Instance Swap, and source-specific layout profiles before explicit local projection. Every tier retainsDropdown Menu.Stylewith onlyDefaultacross five Spacing values (5 variants; Translucent forbidden), and retainsDropdown Menu Item.Statewith only Default/Hover/Active/Disabled across three Sizes and three Types (36 variants; Focus forbidden). In the projected.Dropdown Menu Item Left Decoration, everyType=Iconterminal paint and everyType=TextText node binds totext/secondary-foregroundfor Default, Large, and Small;text/foreground, muted foreground, raw colors, and unbound paints are forbidden. The parentDropdown Menu Itemalso treats both left and right decoration Instances as supporting content bound totext/secondary-foreground; State and Type profiles must never recolor those decoration Instances. Do not absorb neighboring Menubar or Navigation Menu sets. Below the primary group, add exactly three top-aligned equal-column examples: avatar single-select, grouped options with real separators, and avatar two-line items. Build every menu, row, group label, separator, nested decoration, and selected check from real local instances inserted through the real Dropdown Slot API; detached copies, manual row reconstruction, remote imports, and copied reference colors are forbidden. -
Adapter plan: keep the canonical record target-neutral, then project it independently to Figma and code. Without a designated structural source, use the normalized
figma_variant_axes, Boolean/Text/Instance/Slot lists, and owning-State strategy. Withfigma_structure_refs, treatadapter_plan.figma_component_setsas the immutable source structure contract, then apply only the higher-priorityfigma_text_property_projectionsreconciliation for canonical content parameters. Do not merge other normalized code properties into that instance panel. Keep explicit code mappings for any different Figma state/value vocabulary; never turn transient states into a public code prop or copy structural-only Figma controls into code without an explicit mapping. -
Agent-ready contract: apply Rules 0–6 from agent-ready-rules.md to every public component, then finish with an MCP-only Agent Readiness Validation that scores Discoverable, Understandable, Configurable, Composable, and Implementable without filling evidence gaps from code, screenshots, or prior knowledge.
-
Explainability ledger: record input, rule, output, and provenance for important derivations.
Resolve component inventory from user-designated cumulative completeness catalog + explicit include - explicit exclude. Read the exact ordered groups and bilingual labels from component-inventory.json; do not maintain a second executable inventory in prose.
Treat system-spec.schema.json as the interchange contract. Keep grammar platform-neutral and implementation-independent; keep adapter plans separate.
Phase 3 — Validate grammar before Figma
Run:
python3 <skill-dir>/scripts/validate_system.py system-spec.json --report preflight-validation-report.json
This produces SPEC_ONLY_PREFLIGHT evidence and is never completion-eligible. Before the first Figma write, create a run manifest conforming to run-manifest.schema.json. Record the target file, every active or superseded user-designated visual source, all required local template targets, and the artifact names for the run. Then compile the executable style and projection contract:
python3 <skill-dir>/scripts/compile_execution_contract.py system-spec.json run-manifest.json --output execution-contract.json
python3 <skill-dir>/scripts/emit_figma_library.py compile \
--spec system-spec.json \
--execution-contract execution-contract.json \
--output figma-generation-plan.json
Compilation must fail if any bundled presentation template is absent, duplicated, or not projected exactly into the spec. The execution contract pins the system-spec and run-manifest digests, the bundled style-contract digest, the cross-session refinement-registry digest, exact Variable/Style inventory, target selectors, expected node counts, the one-contract-one-writer gates, and mandatory live read-back. Core, Normal, and Pro must all execute scripts/emit_figma_library.py; completeness may change only component inclusion and property/variant projection. Tier-specific writers, one-off repair entrypoints, skip-if-exists behavior, persisted target node IDs, and runtime imports from external Figma files or libraries are forbidden.
The writer packs appearance repair and appearance audit jobs greedily in canonical component/variant order under the 50,000-character use_figma source limit. Shared Foundation aliases, radius roles, and target identity are emitted once per pack; jobs still execute sequentially and fail closed at the first component error. A Figma rate-limit response is an execution error and must never be counted as a successful mutation or audit.
Resolve all errors. Review warnings and record explicit waivers with reasons. At minimum verify:
- color coherence, exact 52-variable direct Semantic vocabulary, theme completeness, foreground contrast, accessibility target, exact projected-variable description coverage, role-aware selection-strategy conformance, and exact
token_policy.component_variable_metadata_selection; rejectstatus/*,interaction/*,data/*,color/*,chart-*,tag/*,fill/chart-*,stroke/chart-*, component names, andbase,default,subtle, orraisedtheme roles; allowstrongonly forborder/strongandring/strong; verifytext/brandis the nearest accessible brand step and passes onbg/backgroundplusbg/secondary, every neutral stays below its personality chroma cap plus.002,bg/accentusesneutral/100in Light andneutral/800in Dark unlessvisual.accent_source=brandexplicitly permitsbrand/100andbrand/900,ring/focususesneutral/300Light andneutral/700Dark,ring/strongusesneutral/400Light andneutral/600Dark, andring/destructiveusesdestructive/600Light anddestructive/400Dark unless explicitly overridden, Lighttext/secondary-foregroundis exactlyneutral/500, Lighttext/muted-foregroundis exactlyneutral/200, Light status pairs use same-family100/500, Dark status pairs use same-family800/400, every deliberate Light low-contrast choice retains its canonical waiver, every Dark status pair meets the configured text threshold, and Darktext/muted-foregroundis the first lowest-emphasis candidate meeting the configured text threshold on bothbg/backgroundandbg/muted; - control-height coherence: Web must expose exactly
xs / sm / md / lg = 24 / 28 / 32 / 36; the values must be strictly increasing on a 4px rhythm with equal 4px adjacent increments, while density changes derived padding and gaps instead of inflating this foundation scale; - direct Primitive-bound Semantic values, complete code-only shadcn compatibility coverage, scopes/code-syntax intent, naming, and token economy; require zero projected compatibility or application aliases;
- type hierarchy, spacing/radius monotonicity, and icon-source viability;
- component anatomy, mainstream property vocabulary, semantics, constraints, and composition;
- all five Rule 0 capabilities—Discoverable, Understandable, Configurable, Composable, and Implementable—are derivable for both Coding Agent and Design Agent consumers;
- Rule 1 naming and taxonomy are normalized across component identities, categories, layers, properties, and variant values, with explicit adapter mappings for authoritative source API differences;
- Rule 2 classifies every capability into the correct schema mechanism, keeps public enum combinations within budget, and defines one stable hierarchy signature or an explicit split/composition rationale;
- every canonical string content parameter has a Figma Text Property projection, every semantic Text layer is bound or explicitly classified as decorative text, fixed brand copy, or a non-overridable system label, and the recommended Button/Input/Dialog/Card/EmptyState property names are considered before less common text controls;
- Rule 3 defines semantic layer trees, Auto Layout intent, per-axis HUG/FILL/FIXED behavior, nested-component reuse, constraints, overflow, and required resize/content probes;
- every designated root layout profile selects its declared occurrence count, all profiles cover the full Variant matrix exactly once without overlap, FIXED axes alone carry fixed dimensions, and every Button profile is horizontal
HUG × HUGwith centered content; - Rule 4 starts from an existing Variable/Style inventory, preserves one designated token vocabulary, classifies raw/duplicate/drift values, and defines semantic bindings plus a safe migration plan;
- Rule 5 defines source-backed PURPOSE/USE/AVOID/KEYWORDS descriptions, Property semantics, composition records, relationship metadata, review flags, and natural-language discovery probes for reusable public Components;
- Rule 6 defines the post-build MCP-only sample, evidence classifications, five-dimension scoring, readiness thresholds, issue severity, Component IR probes, and final report contract;
- the bundled shadcn IR passes its schema, excludes resolved visual values, and resolves every baseline reference;
- every component state set preserves source order, incorporates canonical state-backed code Booleans without semantic duplicates, and has complete ownership, Boolean binding, runtime mapping, order, and per-state descriptions;
- variant budget and illegal combinations;
- Agent, developer, and designer projections remain derivable from one canonical source.
Do not begin Figma compilation while validation errors remain.
In COMBINED mode, now freeze system-spec.json. Compute its exact byte SHA-256 and prohibit further writes to that file for the rest of both projection branches. Pass its path, digest, the normalized design decisions, and any already accepted product/contract context to $design-system-contract-gen using its from-spec branch, while recording contract.generation_mode=COMBINED in Contract IR. The Markdown branch must not rederive the spec, inspect Figma, or reinterpret canonical Foundation and component values. The Figma branch continues below unchanged.
Phase 4 — Compile foundations in Figma
Load $figma-generate-library and $figma-use, then follow their workflow under the precedence and mutation-order rules defined in the non-negotiable boundary above. This skill's specific Page, component-matrix, checkpoint, and sequential-write contracts override conflicting generic workflow guidance.
- Reconcile the validated spec with a final read-only Rule 4 inventory of existing Variables, Styles, collections, modes, aliases, scopes, code syntax, and live bindings. Produce reuse, conflict, drift, and gap decisions before creating tokens.
- Reuse compatible existing tokens first. For proven gaps, create primitives before semantics and semantics before justified component tokens; never establish a parallel token system.
- Generate the complete foundation infrastructure regardless of
core,normal, orpro: Primitive Color, the exact direct Semantic Color vocabulary, modes, scopes, code syntax, text styles, and all four canonical Shadow Effect Styles. Completeness controls component inventory only. Treat a missingShadow/sm,Shadow/md,Shadow/lg, orShadow/xlEffect Style, missing/incorrectEffectStyle.description, or detached replacement effect in any tier as a blocking error. In Figma, create exactlybg/{background|primary|primary-hover|primary-pressed|secondary|muted|accent|destructive|success|warning},text/{foreground|primary-foreground|inverse|secondary-foreground|muted-foreground|accent-foreground|destructive-foreground|success-foreground|warning-foreground},border/{default|strong|destructive},ring/{focus|strong|destructive}, and everydecorative/{hue}/{background|foreground|stroke}role. Each one binds directly to a Primitive Color in both Light and Dark. Fixbg/mutedtoneutral/200Light andneutral/700Dark; derivetext/primary-foregroundfromneutral/0orneutral/950by the highest minimum contrast across primary, hover, and pressed, then use that endpoint in both modes. Recompute Darktext/muted-foregroundagainst bothbg/background=neutral/950andbg/muted=neutral/700. Do not createstatus/*,interaction/*,data/*,color/*owner Variables,utility_aliases,chart-*,tag/*,fill/chart-*, orstroke/chart-*. Write the canonical usage string toVariable.descriptionon every projected Primitive and Semantic Color Variable; do not reuse one generic sentence across a layer. Write each shadow's canonical two-part description toEffectStyle.description. Component-named shadcn identities exist only as code mapping metadata incompatibility_aliases; they are not Figma Variables, own no values, and never appear in a picker or on the canvas. Keep an explicit old→new migration map and rebind live nodes before removing legacy Variables. Resolve every live Figma binding through an exact, collection-aware lookup that throws when the variable is missing or ambiguous. Never passundefinedto the official paint or scalar binding mechanism; a black fallback is a failed binding, not a valid default. Bind fills, strokes, and gradient stops on their paint objects, then read backpaint.boundVariables.color. Bind supported scalar geometry such as padding, size, and corner radii on the node field, then read back the matching nodeboundVariablesentry. Do not treat a node-level paint lookup as proof of a paint binding. When creating a child that must uselayoutSizingHorizontal = "FILL"orlayoutSizingVertical = "FILL", append it to an Auto Layout parent first and set FILL sizing only afterward. Setting FILL on an unparented node is an execution error. After any faileduse_figmamutation, assume the write may be partial: run a narrow read-only audit, then repair idempotently by exact IDs or deterministic names before continuing. - Create navigable foundation documentation with five independent top-level frames:
Color / Application,Typography,Scale,Radius, andElevation.Color / Applicationis a designer-facing selection guide, not an infrastructure diagram: show Background, Text, Border, Ring, Status, and Decorative as functional groups. Status displays thebg/{status}andtext/{status}-foregroundpairs without creating astatus/*namespace. Never showstatus/*,interaction/*,data/*,color/*,chart-*,tag/*,fill/chart-*,stroke/chart-*,base,card,popover,sidebar, or another component category. Decorative Colors must not become a standalone root group: place the eight Light hue cards insideLight Column → Section / Decorative → Cardsand the eight Dark hue cards inside the matching Dark path. Each hue card shows itsbackground,foreground, andstrokeroles together; document tags, badges, charts, data visualization, and non-semantic accents as valid uses. Code compatibility mappings stay outside Figma and off the canvas. Separate modes into two complete side-by-side columns—Light on the left and Dark on the right. Set one explicit Color mode on each column, let all swatches inherit that mode, and bind both column surfaces tobg/backgroundso the Dark column renders on the actual dark background. Never place Light and Dark as two mini-swatches inside the same card. For every Decorative hue-set card, load and follow the bundled localtemplates.decorative_color_cardentry in presentation-style-contract.json: use the 284×146 title-plus-three-equal-role-tiles hierarchy, exactbackground / foreground / strokeorder, mode-aware role-label contrast, fixed usage copy, local token bindings, and the required matching-mode parent. Remove any legacy root-levelDecorative Colors / Gridand fail live audit if one remains or if any card is outside its matching mode board. Never read, import, clone, or retain an external Figma node, file key, node ID, component key, or remote Variable ID during generation. For every single-role application color card, load and follow the localtemplates.application_color_cardentry; preserve its hierarchy, dimensions, variable bindings, typography, contrast indicators, raw theme root fill, and metadata rules while adapting role/mode content. Never fetch the historical source Figma object during generation. Resolve every displayed HEX value from the card's current Semantic Variable alias in its effective Light/Dark mode; after any alias mutation, regenerate those static labels and fail final live validation if a label is stale. Bind color Variables at paint level withfigma.variables.setBoundVariableForPaint; directsetBoundVariable("fills", ...)calls are invalid. Treat the contrast-dot group as visibility-dependent HUG content: validate its horizontal layout, 4px gap, two 4px dots, explicit modes, and contrast visibility rather than a fixed width. Do not apply the single-role template to decorative hue-set cards; usedecorative_color_cardinstead. When reading shared plugin data, query only namespaces matching[A-Za-z0-9_.]+; hyphens are invalid in Figma's Plugin API namespace and must never be passed togetSharedPluginDataKeys. After any failed Figma write, read the target back before retrying because transaction rollback behavior can differ by runtime. Do not display Primitive palettes, compatibility targets, CSS properties, CSS variable names, code syntax, or mapping chains on the canvas. Present typography, spacing, radius, and the four Shadow Effect Styles as labeled specimens matching the local presentation contract. Build Type Scale as one vertical, no-wrap, single-column list; withinheading,paragraph, andmonospace, order font size from large to small and equal-size weights from 400 to 600. In Scale, placeSpacing / 间距andControl Size / 控件尺寸in two equal-width columns and keep the contents of each column vertical. Render the canonical six Control Size variablessize/control/xs|sm|md|lg|xl|2xl = 24|28|32|36|40|44as fill-width specimens in ascending order. Render the ten Radius tokensnone/xs/sm/md/lg/xl/2xl/3xl/4xl/fullin a five-column, two-row grid while preserving the canonical0/4/8/12/16/24/28/36/44/9999values. - Validate metadata and screenshots; repair before continuing. Read back every local Color Variable and require exact equality with the 146-Primitive + 52-Semantic projection, including exact
black/100=#000000,black/50=#00000080,bg/tooltip→black/100,bg/mask→black/50, andtext/inverse→neutral/0in both modes, including descriptions, scopes, code syntax, and direct Primitive bindings in both modes. Require zero projected compatibility/application aliases and rejectstatus/*,interaction/*,data/*,color/*,chart-*,tag/*,fill/chart-*, andstroke/chart-*. Resolvetext/secondary-foregroundandtext/muted-foregroundin every mode, verify their explicit Light bindings and waivers, verify status pairs resolve to same-family100/500in Light and800/400in Dark, verify all three Border→Ring one-step-stronger alias pairs, retain the canonical Light contrast records, require Dark status contrast to pass, and fail if Dark muted content skips a lower-emphasis eligible candidate. Reject any remainingbase,default,subtle, orraisedrole and anystrongrole outsideborder/strongandring/strong. Read back all four Effect Styles and require exact names, ordered effects, and canonical descriptions. After changing any foundational variable, search all Foundation and Component documentation text for stale resolved values or sequences derived from that variable. Variable-bound geometry may update automatically while contract bars, guidance cards, and token labels remain static; treat any mismatch as a failed migration.
Use the canonical spec as input, not as permission to bypass upstream safety checks.
Checkbox color completion is evaluated on rendered terminal geometry, not the Instance wrapper. After local icon materialization, both Checked?=Indeterminate configurations require every visible fill or stroke inside Lucide / minus to bind text/primary-foreground; text/foreground, unbound fallback paint, and non-terminal wrapper paint are forbidden. Complete component localization, structural/default-composition repair, Slot reconciliation, and component-specific repair before the canonical appearance pass, then run the blocking appearance audit before geometry and live-readback completion.
Phase 5 — Compile components one at a time
Process components in dependency order: primitives/atoms → controls → fields → composites → overlays.
For each component:
- Inventory existing local assets by deterministic local name/type and record provenance. Remote libraries and historical Figma nodes may be inspected only before normalization when the user explicitly designates them; the executable plan and writer may never retain or import their file keys, node IDs, component keys, Variable IDs, or Styles. Resolve every nested instance, icon, and Slot prototype from the target file's local assets or fail closed.
- Choose reuse, wrap, or rebuild using API, token, naming, and ownership compatibility.
- Compile canonical anatomy and properties through the Figma adapter plan. If
adapter_plan.figma_component_setsis non-empty, first reproduce each listed source exactly at the structure level:source_node_type, Property order/name/type/default/value set, explicit unavailable combinations, actual configuration count, child binding targets, fields, occurrence counts andapplies_whenVariant selections, root layout profiles, anatomy profiles, and documentation-frame colocation. Create a standaloneCOMPONENTwhen declared; never wrap it in a one-child ComponentSet. For every actual root configuration, create/resize children first, then set direction, wrap, alignment, padding, gap, and finally its per-axis sizing; becauseresize()resets Auto Layout sizing to FIXED, perform any requiredresize()before restoring HUG/FILL. Never carry a fixed width into a HUG profile, and never generate a combination listed inunavailable_variant_combinations. Then applyadapter_plan.figma_text_property_projections: reuse an equivalent source Text Property when present, otherwise add the canonical lowerCamelCase Text Property. Bind every matching layer forALL_SEMANTIC_TEXT_LAYERS; forPRESENT_SEMANTIC_TEXT_LAYERS, bind every layer that exists and preserve configurations where the source contains none. Do not create a property listed infigma_text_property_omissions. This text-only Agent-ready reconciliation is the sole permitted Property overlay; it does not alterfigma_component_setsor authorize merging other normalized code properties. Keep an unbound Text layer only whenfigma_internal_text_exemptionsrecords its ComponentSet, semantic role, one allowed category, and rationale. Before any visual write, resolve the component's exactdesign-system-v0.6refined authority from the plan. Materialize every required target, apply explicitNONEversusSEMANTIC_INTENTpaint presence, and preserve all contracted geometry, visibility, state and effect channels while resolving the current generated Foundations. Use figma_component_builder.js for normalized appearance records or the exact explicit requirement executor for requirement-backed records such as Toast; neither path authorizes invented generic anatomy or Foundation-only appearance. Colocate Tabs' two structures inComponent / Tabs, Field's two structures inComponent / Field, Dialog's three structures inComponent / Dialog, and Basic Table Header/Cell inComponent / Table. Keep the local visual/token/metadata system on every generated node. For Input, apply the persisted structure projection before creation: removeShow cursorandState=Emptyin every tier and keep Cursor hidden in every remaining State, including Focus and Error Focus; usespace/3for both horizontal paddings in every size. Pro keeps PositionDefault/Left/Right/Middleand SizeRegular/Large/Small/Extra small; Normal keeps only Position Default, removes the Position axis, and removes Extra small; Core additionally removes the Prepend/Append layers and visibility Properties. In Pro, Left removes only the right stroke, Right removes only the left stroke, Middle removes both side strokes, and Default keeps all four. Treat Prepend, Append, Decoration left, and Decoration right asdescription_or_metadata; pass that purpose to the live Variable-metadata selector and requiretext/secondary-foregroundin every state. For Textarea, removeState=Emptyin every tier, retain onebg/backgroundfill in every remaining state, and seteffects=[]in every state. Input/Textarea Focus bindring/strongon the root stroke; Error Focus bindsring/destructive; neither uses a shadow effect. For Select, projectSizetoDefault/Large/Smallin every tier and removeExtra small. Every variant ends with a required realRight iconInstance whose default component is.Icon / Chevron Down; expose it through an Instance Swap but never a visibility Boolean. MakePrepend:use HUG width. For a FigmaTEXTnode, materialize and audit this astextAutoResize=WIDTH_AND_HEIGHTpluslayoutGrow=0; the Plugin API normalizeslayoutSizingHorizontalback toFIXEDfor TextNode even though its width follows content. TreatState=Placeholdervalue text as the explicitdescription_or_metadataexception—bind it totext/secondary-foreground, not the globaltext/muted-foregroundplaceholder role. For Tabs, remove the publicShow counterBoolean and its visibility binding in every tier while keeping the internal counter hidden. Every tier exposes exactlyDefault/Largeon bothTabandTabs. Every Tabs root binds all four paddings tospace/1(4px); nested Default/Large Tab heights remain 28/32px and the HUG outer Tabs heights resolve to 36/40px. The real Tabs Slot is always paint-free; selected Tab instances alone own their selected surface. MakeTab.State=Inactive Focusvisually identical toInactive Hoverwith no ring or effect, and keep Active effect-free unless a later explicit user declaration overrides it. For Badge, project eight additionalDecorative {Hue}Variant values—Blue, Cyan, Teal, Green, Amber, Orange, Purple, and Pink—in every completeness tier without mutating the captured source IR, then remove the State axis,Show spinner, and Spinner anatomy. The result is exactly 13 Variants. Useparagraph/mini/400for every label, a defaultminHeight=20with HUG height, and retain independent false-by-defaultShow left icon/Show right iconBooleans plus their swaps on every standard and Decorative Variant. Each Decorative Variant uses its exactdecorative/{hue}/backgroundanddecorative/{hue}/foregroundpair. For Card, retain only the root outer border: Header, Body, and Footer section wrappers have no strokes, and no Divider or Separator anatomy may be inserted between them. The Card root and all three section wrappers are HUG height; a fixed section or Card height is forbidden. Header, Body, and Footer apply the current design-decision spacing on all four sides through one bound spacing token (space/5=20pxin the round/pro test profile), while keeping 380px fixed width. Every Header, Body, and Footer Slot uses vertical Auto Layout,FILLwidth,HUGheight, top-left alignment (MIN / MIN), and a Variable-boundspace/4(16px) gap; this Card-specific layout overrides the shared empty-Slot layout. For Separator, preserve all sixSpacing × Directionvariants. Its root is a spacing-only container and must have no fill, stroke, effect, or radius. Every variant contains exactly one Rectangle namedDividerand no genericContent: Default direction usesFILL × FIXED 1, Vertical usesFIXED 1 × FILL, and the Divider fill binds toborder/default. Theborder/defaultVariable must support bothSTROKE_COLORandSHAPE_FILL. For Checkbox and Radio, project the State axis toDefault/Disabledonly in every tier, removing Focus and Error Focus. Both roots are fixed16×16, paint-free, and may contain only their exact source-backed Background and indicator anatomy; never create a genericContentlayer and fail if any child exceeds the root bounds. Checkbox Background binds theselection_controlradius role, which is alwaysradius/xs(4px); False usesbg/backgroundplusborder/default, while True and Indeterminate usebg/primarywith exactly one centered 12px proportionaltext/primary-foregroundcheck or minus icon. Radio uses a 16px Ellipse Background; False usesbg/backgroundplusborder/default, while True usesbg/primarywith one centered 6pxtext/primary-foregroundDot. Disabled changes root opacity only. For Toast, expose exactly one designer-facingTypeVariant axis in the orderSuccess / Info / Warning / Error / Loadingand never expose aStateVariant axis. Every Toast keeps the exact child orderLeading icon / Message / Action / Close icon; leading icon, editable Message text, and the trailing Close icon are always present. The root has no stroke, uses a default 320px minimum and 480px maximum width, gives MessageFILLwidth, and keeps Close anchored at the trailing edge. ExposeShow actionas a false-by-default Boolean; when true it reveals one real Button instance immediately before Close withVariant=Ghost,Size=Extra small, andState=Default, without changing root height. Apply the generatedShadow/mdEffect Style to every Toast root. The exact localcomponent-appearance-contract.component_requirements.toastrecord is Toast's completedesign-system-v0.6refined appearance authority; it is not an exception, an unrefined component, or permission for a generic/Foundation-only fallback. Preserve the Rule 0 code-oriented mapping: Figma properties map to typed props, nested instances and slots map to composition, Variables map to tokens, and Auto Layout exposes machine-readable layout intent. Apply Rule 2 before node creation: finite exclusive enums become Variants; independent optional capabilities become Booleans; editable core content becomes Text Properties; replaceable rigid elements become Instance Swaps; flexible regions become constrained Slots; required reusable substructures remain Nested Components. - Compile
adapter_plan.state_axison the owning ComponentSet when it contains more thandefault. Never create__{Component}State, and never turn transient states into a public code prop. Applystate_backed_boolean_propertiesbefore adding Figma properties: remove every mapped code Boolean from the Figma Boolean list, including semantic aliases and inverse states, while retaining its real code mapping. Keep only independent configuration Booleans. Reject unresolvedSOURCE_EVIDENCEmappings before node creation. Every state-bearing Variant and description must retain the exact canonical state ID. - Before binding visuals, reload the live Color Variable metadata catalog and resolve each component-part/state intent through
token_policy.component_variable_metadata_selection; use the bundled variable_metadata_selector.js helper or an exact equivalent. All creation, reconciliation, incremental repair, exact appearance application, shared Slot styling, and read-back must be emitted by the sole emit_figma_library.py entrypoint fromfigma-generation-plan.json; the bundled JavaScript files are internal templates/libraries and are never standalone execution paths. Process appearance mutations in bounded batches of at most ten configurations and rediscover targets by canonical local name/type on every call. Do not infer color from a component name, Variant label, or substring such asinvalid,error, ordestructive. Validate the exact Variable name, canonical description, scopes, mode aliases, and usage intent, then persist binding evidence. Bind visual properties to the selected variables and preserve only explicitly allowed fixed geometry. Resolve every root and nested part throughadapter_plan.radius_usage; never assign a literal corner radius or use the generic control radius when theroundpolicy requiresradius/full. Apply Rule 3 to reusable anatomy: use Auto Layout for normal flow, set HUG/FILL/FIXED independently per axis from real responsive behavior, reuse compatible nested Components, and document any intentional absolute positioning, clipping, or fixed dimension. Apply Rule 4 to fills, strokes, text, typography, gaps, padding, radius, effects, borders, and reusable sizing. Reuse the correct existing semantic Variable/Style; do not bind business semantics directly to primitives or create component-local duplicates. Treat both Text Style and text-color binding as file-wide component invariants, not per-component appearance opt-ins. Every sourceTEXTnode owned by a local Main Component or ComponentSet variant—including hidden variants, private helpers, and Slot placeholders—must bind exactly one non-mixedtextStyleIdresolving to a local canonical Text Style and must bind every visible SOLID text-fill paint to an eligible Semantic Color Variable withTEXT_FILLscope. Resolve Text Style in this order: explicit appearancetypography_role; exact canonical typography signature after treating zeroPIXELSand zeroPERCENTletter spacing as equivalent; then the exact shared Slot placeholder roleparagraph/mini/400. Missing or ambiguous styles are blocking errors. Repair nested Instance content through its local Main Component source once, then audit proxy descendants for inheritance instead of writing duplicate overrides. Any raw font-only text, empty/mixed/unresolvabletextStyleId, raw/unbound/primitive text paint, missing fill, or unresolved alias blocks completion. - Add component properties, nested instances, slots, documentation, a component-set description, and a non-empty description on every individual public Variant Component. Derive each Variant description from its exact designer-facing property values—including
state—plus the canonical component semantics; never copy one generic sentence across all variants. Derive documentation contract-bar axis names, option counts, and tier labels from the final completeness-projectedadapter_plan.figma_component_sets, never from the immutable source capture; stale Pro counts on a Normal/Core frame are blocking. Keep the component canvas designer-facing: do not add anAPI & Accessibilitypanel or expose code-mapping logic there. Apply Rule 1 naming throughout reusable subtrees unless a user-designated structural contract supplies exact public Property/value spelling. Preserve those exact Figma names and values, and keep normalized lowerCamelCase/lowercase vocabulary in the code adapter mapping instead of renaming the source-backed Figma API. Keep a stable semantic layer hierarchy across all variants. Preserve optional nodes and control visibility instead of deleting anatomy; split or compose configurations that require incompatible trees. Apply Rule 5 to the public ComponentSet: write the concise four-section PURPOSE/USE/AVOID/KEYWORDS Description, add semantic guidance for ambiguous Properties, and expose a separate source-backed composition/relationship record. Do not duplicate long descriptions on private helpers or state specimens. - Resize the component set from actual child bounds after layout. Keep only the configured compact structural padding; reject oversized fixed rectangles or unused blank regions. After all text and annotation children exist, recompute every fixed freeform card or callout from its final child bounds plus padding; a structurally contained parent may still clip late-created text.
- Load
templates.component_set_matrixfrom the bundled presentation-style contract and apply it to every generated ComponentSet without any adaptive or square-grid fallback. Style the boundary with a raw, unbound#9747FFdashed outline, no fill, and 4px corner radius; add matching raw, unbound dashed dividers between every adjacent variant row and column.Sizeis the only horizontal column axis, in declared order from left to right.Stateis always a vertical row axis. Every other Variant Property—includingVariant,Type,Position,Style,Spacing,Side, and multiple remaining axes—forms declared-order outer groups stacked vertically by Cartesian order; a ComponentSet withoutSizeis therefore single-column. Apply the explicitProgressoverride: its soleProgressVariant Property is a vertical single-column row axis, ordered0, 10, 20, 25, 33, 40, 50, 60, 66, 75, 80, 90, 100. Put an explanatory axis note plus exactProperty: Valuelabels outside the boundary in raw, unbound#9747FF: Size labels above columns, State labels left of rows, and every other Variant Property label left of its group with a bracket whenever the group spans multiple rows. Treat this authoring chrome as a documented raw-value exception and keep it as non-published siblings in the outer documentation matrix frame. Matrix identities, ordering, coordinates, labels, dividers, and brackets are deterministic contract output; random, adaptive, square-root, fixed-column, or unordered grids are blocking errors. - Run a compact structural and appearance audit that returns one pass/fail summary, failed check IDs with minimal evidence, and every temporarily mutated node ID. Re-read the real Variant nodes and compare anatomy, geometry, paint-slot presence, effect channels, Variable bindings, and allowed state deltas with the resolved local contract. Require zero unprofiled variants, generic fallbacks, source-signature mismatches, and invariant violations. In particular, Switch must contain one
Backgroundand oneToggle, preserve checked/unchecked endpoint motion through focus/disabled, and have no visible root paint; Button must preserve its per-Variant border policy so Primary disabled never gains a stroke. Every Focus selection must use a stroke-boundring/*role and resolve its effect channel to NONE unless its explicit local user refinement declares and validates an exact non-shadow alternative. Do not dump a full record for every Variant when the success path can be summarized; truncated audit output is incomplete evidence. - Validate the public ComponentSet with metadata, then screenshot the complete
Component / {Name}documentation frame. Treat metadata and screenshots as complementary and equally blocking: metadata proves structure; the screenshot must catch overflow, clipping, implausible type scale, matrix-order drift, overlapping or duplicate Size/State/group labels, missing dividers, illegible annotation, literal escape text such as\\n, implausible visible copy, remote nested-component fallback blocks, opaque black scaffold fallbacks, visually empty composites, indistinguishable declared states, uncontracted fills, and unexplained whitespace. Persist the screenshot SHA-256 and native pixel dimensions, exact detected-versus-verified ComponentSet counts, and explicit zero counters for every listed defect; a barePASSassertion is invalid. Structural wrappers such asWrapperand Field layoutALare fillless unless a named appearance target explicitly contracts a surface. EmptyState generates only Default and preserves the visual orderSlot → Title → Description → Button groupthrough direct root childrenSlot → Title + Description → Button group. The root bindsspace/4(16px); the fillless nested text stack alone bindsspace/1(4px), so live pairwise gaps are exactly 16/4/16px. The first child follows the shared generic Slot contract, Button group is the local.Empty / Button Grouphelper with its own nested Slot, Description usestext/secondary-foreground, and Content/Content Stack/a second direct Slot/Media-only/Link anatomy is forbidden. Dialog generates only Desktop scrollable with Size 480/640/800, width-FILL Header/Slot/Footer, height-FILL shared-style body Slot, and no mobile Footer; right and full-width Footer layouts must pass explicit alignment and Button-width readback. Calendar, Progress, Dropdown, Dialog, Field, EmptyState and every other active composite must expose enough visible anatomy to prove the learned relationship contract rather than merely pass node-count checks. Drawer, DataTable, and ToggleGroup are excluded from Core, Normal, and Pro and must never be generated. Field-specific gate: every Field root and structuralWrapper/AL/Selection ContentFrame is fillless and borderless in all states. Both Field families retain their fixed 320px root; Horizontal Field retains its fixed 120px Label Wrapper, while itsALcontent track is FILL and vertical. Every Label, Input, Select, Textarea, Slider, Selection Content row, and Option label fills its available content width. Description and Error message keep non-empty canonical defaults,HEIGHTauto-resize, exact Text Property bindings, and FILL width whenever visible; Figma's forcedFIXEDreadback for hidden Boolean-controlled Text is the only allowed exception. Radio and Checkbox Types use a FILL-width horizontalSelection Contentrow containing one exact fixed 16px local Default-unchecked control followed by a non-emptyOption labelbound to the editableoptionText Property; the control itself never stretches and Field exposes no Slot. - Repair all failures, repeat the compact audit and screenshot, and record the checkpoint. Pause for approval only when the user explicitly requests per-component review; otherwise continue through the selected completeness tier without intermediate confirmation.
Never create an icon variant per icon or a standalone IconButton. Never create a full Cartesian variant matrix above the configured budget. Apply the split/composition strategy from component-grammar.md.
Phase 6 — Apply designer presentation
Project the canonical grammar into designer-readable documentation:
- stable pages and categories;
- one named 1440px shared-template presentation frame per component set, using vertical auto layout, hug-content height,
space/12padding and section gap, and an unbound raw outer fill of#FFFFFFin Light or#000000in Dark; - Foundation and Component documentation frames as direct Page children below the foundation summary and component index; do not create an intermediate container, and explicitly place the frames in horizontal-first row-major (Foundations: 10×N; Components: 6×N, excluding the index) order with variable-bound
space/20horizontal and vertical gaps; - the template header's uppercase kicker, merged
{English} · {Chinese}Section Title at exactly 44px, one-sentence Chinese definition, and four-cell contract bar; - the shared specimen stage with
space/8padding,radius/md, andmutedfill; set every first-level content heading to exactly 24px and render every first-level or nested content title bilingually, includingApplication Colors / 应用颜色,Variants / 变体, andStates / 状态; use a component-specific freeform matrix or foundation-specific auto-layout specimen rows inside it; make Type Scale a direct-child, fill-width, single-column vertical list and order each category by font size descending then weight ascending; give every Type Scale card two equal-fill horizontal columns with metadata left and styled sample right; make Scale a two-column layout whose Spacing and Control Size columns each stack vertically; show the ten Radius Scale tokens in semantic order in a five-column, two-row equal-width grid; Components / Index,Foundations / Summary, andGetting Started / Rootuse the bundled localinstructional_paneltemplate: preserve target text and content-stage children, allow text width and root height to follow content, and match every other root/header/Identity/Contract Bar/stage-container property exactly;- the instructional root and Contract Bar use raw unbound #FFFFFF in Light / #000000 in Dark; its Contract Bar is borderless with
border/defaultdividers only between cells; its content-stage container hasspace/8gap, zero padding, no fill, andradius/none. Never reintroduceframe_style_overridesor the specimen-template gray stage on these three frames; - readable and stable variant order;
- in
Component / Card, placeExamples / 使用案例below the primary component group and render exactly three real Card-instance compositions matching the reference: Login Form, Image Card, and Meeting Notes. Insert Header/Body/Footer content through the real Card Slot API, reuse matching local Field/Input/Link/Button/Badge/Avatar instances, and never detach or reconstruct a Card for documentation. Do not add example dividers unless an example explicitly requires one; every permitted divider is horizontal,FILLwidth, parented inside the Slot content container, and must not exceed that container's edges; - in
Component / Pagination, placeExamples / 使用案例below the primary component group and render exactly one fillless row with five pages:Previous, 1, 2, 3, 4, 5, Next, with page 1 active. Previous and Next must be real local Ghost Button instances; every page number must be a real local Pagination Number Button instance with its nested Button label configured through the component API. Ellipsis, extra pages, a second row, detached copies, manual page text, and one-off reconstruction are forbidden; - in
Component / Table, place oneExamples / 使用案例block after the Basic Table Header/Cell matrices. Compose exactly one 4-column, 5-row table from 4 real local Basic Table Header instances plus 16 real local Basic Table Cell instances. Use the contract copy, right-align the body price column, bind alternating rows tobg/secondary, bind the remaining cells tobg/background, and bind every bottom separator toborder/default. Never detach, import remote cells, manually reconstruct a cell, or copy raw screenshot colors; - in
Component / DropdownMenu, placeExamples / 使用案例below the primary component group and render exactly three top-aligned equal columns titledSelect Example: avatar single-select, grouped options with real separators, and avatar two-line items. Every surface and row is a real local Dropdown-family or Separator instance, nested Avatar/check decorations are configured through component properties, and menu content is inserted through the real Slot. Detached copies, manual row reconstruction, remote imports, and reference-image colors are forbidden; - Alert uses
bg/backgroundwith a 1px INSIDEborder/defaultstroke.Icon + Content,Icon-aligner, andContentare fillless/strokeless;Contentis vertical HUG so Description is the second line. Neutral Description usestext/secondary-foreground. In Error, Title, Description, and every rendered terminal fill or stroke channel of Icon bind the exact sametext/destructive-foregroundVariable; a wrapper-only binding, an unbound nested vector, or a gate that accepts merely one matching leaf is forbidden. Reapply these terminal bindings after every Instance Swap orresetOverrides()geometry normalization. Add exactly two real-local-instance examples below the primary group with bundled Success/Error icon Components; - a no-fill ComponentSet with
#9747FFdashed outline, 4px radius, matching internal dividers, and external variant-property labels; - meaningful anatomy layer names;
- concise component description containing the agent-readable grammar projection.
- a concise, property-specific description on every public Variant Component; the canonical
presentation.variant_descriptionsmap is the source of truth. - a source-backed state matrix and one concise description per state from
presentation.state_descriptions; state labels use exact IDs such asfocus-visible, never hand-normalized synonyms. - no Utilities page, trailing separator, or standalone Playground frame; component examples belong only inside their owning
Component / {Name}documentation frame.
Example generation is a mandatory atomic phase of its owning component documentation, never an optional repair or a stage that may be remembered manually. After compiling figma-generation-plan.json, read only generation_chain.mandatory_example_execution.required as the tier-active source of truth. In both repeatability runs, execute each entry's exact required_sequence—build stage first, dedicated audit stage immediately afterward—and persist exact count, pass status, and SHA-256 evidence for both results. Do not skip an active Card, Dropdown, Alert, Table, EmptyState, or Pagination Example because the primary ComponentSet exists or a later geometry/screenshot audit might notice the omission. Missing, reordered, extra, failed, stale, or unaudited Example evidence blocks final live-audit assembly and completion. Use python3 scripts/emit_figma_library.py example-schedule --plan figma-generation-plan.json to obtain the deterministic per-run schedule; never substitute a handwritten stage list.
Derive the template header, contract bar, and component description from the same canonical component record. Do not maintain them as separate sources of truth.
Component page placement is a terminal generation requirement: after all component, Agent documentation, example, and instructional-frame size changes, emit and execute documentation-layout through scripts/emit_figma_library.py for batch 0 (Foundations) and batch 1 (Components), then execute the matching documentation-layout-audit batches before final screenshots and completion. Repeat these steps in the second-run repeatability check. Use the bundled page_frame_placement contract: Components has six Component / * artboards per row, the index sits above the rows, and Integration / * artboards sit below them. Preserve frame sizes and source identities; hidden helpers do not consume columns. Reflow again after any later frame-size change. Never reuse the old 10-column Markdown placement or leave all component artboards on one unbounded row.
Phase 7 — Technical QA and repair
Run the production loop:
generate → validate → repair → validate again
Check the canonical spec with the bundled validate_system.py and the Figma library with the official skills. Finish only when required checks pass for:
- foundations and tokens, including all four Shadow Effect Styles in every completeness tier;
- live Effect Style read-back from
getLocalEffectStylesAsync(): require exactlyShadow/sm,Shadow/md,Shadow/lg, andShadow/xlwith the canonical descriptions and ordered effects, then prove each Elevation specimen resolves through a non-emptyeffectStyleIdto the matching local style. A screenshot, detachedeffectsarray, generated JSON record, or visible shadow alone is not completion evidence; stale copy such as0 published effect stylesis a repair failure; - each component and its bindings;
- accessibility;
- agent-readable metadata and predictable naming;
- developer-mappable tokens and APIs;
- designer readability, findability, inspectability, and maintainability;
- every-top-level-artboard screenshots captured after the final write and matched exactly to the live artboard inventory, with screenshot SHA-256, native dimensions, explicit zero-valued overflow/type-scale/literal-escape/fill/matrix/remote-instance/black-fallback/empty-composite/indistinguishable-state/label-overlap counters, and equal detected-versus-verified ComponentSet matrix counts, plus unresolved-binding audits. Missing or stale screenshots, unchecked artboards, literal
\\n/\\t, implausible visible copy, metadata-only matrix claims, or any visual finding block completion. - tight component-set content bounds, all five independent foundation frames, canonical stacked template headers, and zero Utilities/Playground output.
- direct-Page freeform horizontal-first row-major placement (Foundations: 10×N; Components: 6×N, with the index excluded), no intermediate documentation container, raw
#FFFFFFLight /#000000Dark outer frame fills with no Variable binding, and the canonical annotated ComponentSet visual treatment. - exact 44px Section Titles and exact 24px first-level content headings in every Foundation and Component documentation frame.
- exact role-based live read-back evidence that
Components / Index,Foundations / Summary, andGetting Started / Rootmatch the bundled localinstructional_panelcontract for the root shell, header, Identity, Contract Bar, and content-stage container while preserving target content; pre-Figma spec validation alone is never sufficient. - complete read-back evidence that every Variant Component has a non-empty description matching its property combination.
- Figma MCP read-back evidence that a Coding Agent can derive the code schema and a Design Agent can discover, configure, and compose real component instances without guessing or detaching them.
- a full Rule 1 MCP naming audit with no placeholder layers, ambiguous component identities, generic properties, mixed variant-value synonyms, or undocumented Figma-to-code name mappings.
- a full Rule 2 MCP schema audit proving correct Property classification, bounded Variant combinations, constrained swaps/slots, canonical defaults, and consistent Variant hierarchy signatures.
- a full Rule 3 MCP layout audit plus short/long/minimum-width/larger-container/multilingual instance probes proving semantic hierarchy, responsive sizing, alignment, and overflow behavior.
- a full Rule 4 MCP audit of Variables, Styles, aliases, modes, scopes, code syntax, raw values, drift candidates, and live Component bindings, including safe migration evidence for every replacement.
- a live component-variable metadata audit proving the Color catalog was reloaded after the final foundation mutation; every bound semantic Variable has the expected name, canonical non-generic description, compatible scopes, direct per-mode Primitive aliases, current-mode-resolved raw paint fallback, and recorded component/part/state intent; no component/Variant substring heuristic, whole-root invalid-state status binding, Primitive binding, unresolved black fallback, or generic-gray fallback remains.
- a live component-appearance audit pinned to the current local contract SHA-256, proving every checked legal Variant was read back from the target file; every required anatomy path, intrinsic geometry, paint-slot presence, stroke rule, effect channel, anchoring, visibility, and permitted state delta matches;
unprofiled_variants,generic_fallback_variants, andsource_signature_mismatchesare all zero. Screenshots complement this deterministic evidence and can never replace it. - a full Rule 5 MCP semantic audit proving four-section public descriptions, Property guidance, composition/relationship accuracy, visible review flags, and successful natural-language component discovery probes.
- radius-binding evidence that every eligible pill-like
roundsingle-line root/item resolves toradius/full, while multiline inputs, cards, messages, overlays, and the component-specific Tooltip compact-surface exception retain their documented hierarchy; every Tooltip Type resolves toradius/smin the round profile. - compact-audit evidence that successful runs fit within the tool output budget and list only failures in detail; output truncation invalidates the affected audit.
- fixed documentation-card fit evidence computed after final text insertion, plus screenshot confirmation that no content is clipped or hidden.
Report waivers and residual risks explicitly. Never label a best-effort approximation as production-ready.
Phase 8 — AGENT READINESS VALIDATION
After Phase 7 passes and the intended Library is complete, read and execute Rule 6 from agent-ready-rules.md.
- Freeze source Components for the duration of scoring. Do not repair metadata, properties, bindings, or composition while the audit is running.
- Build the deterministic sample and run all five dimensions using Figma MCP evidence only.
- Record each answer field as
DIRECT,SUPPORTED_INFERENCE,GUESS_REQUIRED, orCONFLICTING; leave unsupported values unknown instead of guessing. - For Composable testing, create only temporary real-instance specimens in an audit sandbox, retain exact returned IDs, validate through MCP, and remove only those owned temporary nodes.
- Generate the required Button, TextField-or-resolved-Input, Card, and Dialog MCP-only Component IR samples.
- Calculate the five 0–100 scores, Overall score, issue severities,
Ready for Agentresult, and ordered repairs using the Rule 6 thresholds. - If repairs are needed, close the audit as-is, return to Phase 7, repair, and run a fresh Phase 8 audit. Never reuse the pre-repair score as the final result.
Finish only when the final report is self-contained, evidence-backed, and explicit about every unavailable or conflicting field.
Phase 9 — Combined Figma and Markdown acceptance
Run this phase only in COMBINED mode and only after Phase 8 and the Markdown skill's native validation both pass.
Require these artifacts from the Markdown branch:
contract-ir.json;- the complete L0–L7
design-system-contract/package; contract-manifest.json;- successful Contract IR and package validation;
- byte-identical second rendering.
Run the combined validator from the installed $design-system-contract-gen skill:
python3 <design-system-contract-gen-dir>/scripts/contract_package.py validate-combined \
--ir contract-ir.json \
--package design-system-contract \
--system-spec system-spec.json \
--figma-plan figma-generation-plan.json \
--figma-audit figma-live-audit.json \
--figma-validation validation-report.json \
--report combined-acceptance-report.json
Completion requires:
- the exact system-spec SHA-256 in
figma-generation-plan.json#/artifact_digests/system_spec_sha256; - the same digest with
sha256:prefix incontract-manifest.json#/canonical_spec_sha256and every managed Markdown file; validation-report.json#/status=PASSED;figma-live-audit.json#/passed=true, zero violations, and identical two-run normalized readback;- Markdown-native validation and deterministic repeat rendering;
- every scoped Foundation Token and component Figma mapping is
verifiedwith non-empty live targets and readback evidence; - no unresolved drift that contradicts the canonical spec.
Do not claim combined completion when either branch merely generated files without passing its own native validation. A combined failure does not retroactively invalidate a separately passing Figma branch; report branch results independently and the combined verdict as failed.
Decision policy
For each potential input, classify it before acting:
USER: brand, product context, visual direction, accessibility target, or genuine scope fork.DERIVE: scales, state colors, component dimensions, property defaults, inventory, and other predictable consequences.FIGMA_ADAPTER: variables, styles, auto layout, component properties, slots, nodes, and page construction.CODE_ADAPTER: framework-specific component code, prop typing, CSS variables, and package exports.
When evidence conflicts, use this precedence only when it matches the stated goal:
explicit user decision → designated source of truth → existing compatible convention → mainstream convention → skill default
Never silently replace a user's existing design-system convention merely because the default differs.
Mainstream compatibility rules
- Textarea uses two editable Text Properties with deterministic visible defaults:
value = Valueandplaceholder = Enter value. Placeholder alone binds toplaceholder; Value, Focus, Error, Error Focus, and Disabled bind tovalue. Any visible non-placeholder Textarea state with empty characters, a missing Value layer, or the wrong Text Property binding blocks generation and screenshot approval. - Input Position controls both joining borders and joining radii.
Defaultkeepssingle_line_controlon all four corners;Leftbinds its two right corners toradius/none;Rightbinds its two left corners toradius/none;Middlebinds all four corners toradius/none. Apply and audit four explicit corner Variable bindings; unbound numeric seam radii are forbidden. - Prefer stable property names:
variant,size,state,orientation,side,align,disabled,selected,checked,expanded,loading,label,value,showLabel,leadingIcon,trailingIcon,showLeadingIcon,showTrailingIcon. Usestateas the owning Figma ComponentSet's designer-facing Variant axis for finite evidence-backed conditions, but explicitly omit it from code props. Keep real state-like code Booleans in the code contract, record their State bindings, remove their duplicate Figma Boolean controls, and map remaining State values to CSS/HTML/data/role/ARIA mechanisms. - Apply Rule 1 casing and taxonomy: semantic
PascalCasecomponent/layer names, controlled categories,lowerCamelCaseproperties, normalized lowercase variant values, and explicit adapter mappings when an authoritative code API uses different strings. - Map Figma variants to enum props, booleans to boolean props, text to string props, instance swap to component props, slots to children/slots, and tokens to CSS/theme variables.
- Never encode independent optional elements, arbitrary content, or asset identity as Variant axes. Use Boolean, Text, Instance Swap, Slot, or Nested Component mechanisms according to Rule 2, and keep equivalent Variant trees structurally consistent.
- Use Auto Layout for normal component flow and map its direction, gap, padding, alignment, distribution, and per-axis sizing to code layout rules. Permit absolute positioning and fixed sizes only for documented intrinsic or layered behavior.
- Bind reusable visual properties through the existing Primitive → Semantic → justified Component token architecture. Prefer semantic tokens, keep one designated vocabulary, and allow raw values only for documented fallbacks, fixed structural geometry, assets, or excluded documentation chrome.
- Describe every reusable public Component with concise, source-backed PURPOSE/USE/AVOID/KEYWORDS semantics. Keep uncertain claims marked
Needs Product/Design Review, and keep composition/relationship metadata separate from the short public Description. - Use the installed shadcn preset only for component rules and the abstract
comfortable + softbaseline. Do not copy Tailwind utilities or preset-resolved colors, spacing, radii, typography, elevation, or lime brand values. Resolve the brand from the user'sdesign_decisions.brand.primary_color. - Preserve
design_decisions.brand.primary_colorexactly atcolor/brand/500. Derive all other brand steps around it, requesting38%of the500anchor chroma at every chromatic family’s100step before gamut mapping so pale colors remain visibly tinted instead of gray. Reduce that request only when required to fit sRGB; never rotate hue or change the exact500anchor. Tint the neutral scale subtly toward the brand hue, and mapbg/primarytobrand/500in every theme; never silently substitutebrand/600or a theme-specific step. - Add the exact Primitive
neutral/0=#FFFFFF. In Light, bindbg/backgroundtoneutral/0andbg/secondarytoneutral/50. In Dark, derive the counterpart through the fixed hierarchybg/background→neutral/950andbg/secondary→neutral/800. Semantic values must remain Primitive aliases; never store raw#FFFFFFdirectly onbg/background. - Treat every accepted color-generation change as a two-surface transaction: update the bundled generator/contract and the in-scope live test Figma file in the same task. In Figma, create or update the exact Primitive, rewrite every affected Light/Dark Semantic alias, refresh all displayed HEX labels, and then read back Primitive values, alias target IDs, swatch Variable bindings, mode resolution, descriptions, scopes, and code syntax. A local-only pass or an auto-updated swatch with a stale HEX label is incomplete.
- Unless explicitly overridden per family in
design_decisions.status_colors, preservesuccess/500=#16A34A,destructive/500=#EB1C23, andwarning/500=#FA8714. Derive each remaining scale around its selected 500 anchor. Bind Lightbg/{success|destructive|warning}to its family100and the paired foreground to family500; bind Dark status backgrounds to family800and the paired foreground to family400. Retain canonical contrast waivers only for the explicit Light pairs; Dark pairs must meet the configured text-contrast target. - Keep Button content color coupled: label, leading icon, trailing icon, and spinner must bind every terminal descendant fill/stroke paint leaf to one identical Semantic foreground Variable. Set
figma.skipInvisibleInstanceChildren=falsebefore resolving nested targets: an ancestor's hidden default never exempts its descendants, and zero terminal paint leaves is a blocking error rather than a vacuous pass. Primary content usestext/primary-foreground, nevertext/foreground; Destructive content usestext/destructive-foreground. Code icons inheritcurrentColor. Never introduce separate Button icon/spinner color properties or tokens. Configure each icon and spinner Instance withconstrainProportions=trueand{horizontal:SCALE, vertical:SCALE}constraints; require its content to stay within the Instance bounds, and use a compatible intrinsic-size helper or rescale source and wrapper together instead of resizing only the wrapper. - Treat proportional icon scaling as a global base rule, not a Button exception: every icon-like Instance in every component uses
constrainProportions=trueand{horizontal:SCALE, vertical:SCALE}constraints, even when a local appearance profile omitsscale_mode. Apply the rule explicitly to the standalone Spinner component as well: every Spinner root, its internal Ellipse indicator, and every nested Spinner Instance preserve proportions and useSCALE / SCALEconstraints. - Size every component-consumer content icon, decoration, and spinner from the owning component's exact
Sizevalue:Extra small=12px,Small=14px,Default|Regular|Medium=16px, andLarge=20px; components without a Size axis use16px. A bundled SVG may retain a24×24intrinsic viewBox/source Component, but24pxis never a fixed consumer-instance size. Apply the size after localization/Instance Swap reset so source geometry cannot leak back into the component. Checkbox check/minus, Radio indicator, and Slider marker remain governed by their explicit state-indicator contracts. - Treat icon visibility Booleans as visibility-only capabilities. For the same component Variant selection, enabling or disabling any icon Boolean must leave the root height unchanged. Every hidden optional icon is pre-sized to the same Size-derived value as its visible state, and that value must fit within the root's inner height after vertical padding; a Boolean that causes Button, Input, Select, Badge, Toast, or any other component to grow is a blocking generation and live-audit failure.
- Treat terminal icon occupancy as a blocking geometry contract, not a subjective screenshot check. For every bundled local icon source Component and every generated content-icon consumer Instance, compute the union of rendered terminal fill/stroke geometry (including stroke render bounds). Its maximum axis must occupy at least 55% of the owning square canvas and no terminal render bound may exceed that canvas by more than 0.51px. Validate both the 24px source Component and the final Size-derived consumer after every SVG import, localization, Instance Swap, reset, and proportional resize. Never call
resize(24,24)on the container returned byfigma.createNodeFromSvg()because the current Figma runtime may return a 100px import wrapper and scale the already-canonical 24px path data a second time; preserve the canonical path coordinates, move its children into the 24px source Component, and validate their rendered occupancy before allowing the stage to pass. - Keep Button state ownership narrow. The canonical code state remains
state=[default, hover, active, focus-visible, disabled]; the Figma Button State axis is exactlyDefault / Hover & Active / Focus / Disabled. Preservearia-invalidandaria-expandedonly as non-owning passthrough/code evidence; never expose Invalid as a Button State value. Require separateshowLeadingIconandshowTrailingIconBoolean visibility bindings on every live Button Variant. - Apply the explicit Button appearance refinements from the bundled local contract: Extra small labels use 12px and every other size uses 14px; for a fixed Size and Variant, label typography and every internal element size are invariant across State; Outline has no root fill in any state and uses its stroke channel, with Focus switching that stroke to the applicable
ring/*role and never adding an effect; Link Hover & Active and Focus underline the label through disjoint Size-aware conditional Text Properties whose selectors never overlap; Destructive usesbg/destructiveand pairs label, icons, and spinner withtext/destructive-foreground, with no component-specific exception. - Allow the documented designer-only Figma
stateaxis only on the owning ComponentSet, withcode_state_property=false, explicitstate_backed_boolean_properties, and a concrete runtime mapping for every value. Do not expose the same condition again as a Boolean even when code and state use different names. Avoid all other Figma-only public APIs and duplicate synonyms such astype,style,appearance,look, andmodefor the same variant concept. - Never create a component-specific Color Variable. When a direct Semantic role is insufficient, extend the shared role with a reusable level or emphasis axis. A component-named color may exist only as code-compatibility metadata targeting one of the direct Semantic names; it is never projected to Figma. Non-color component tokens still require stable independent semantics, a complex shared state model, or an explicit theme override.
Deliverables
For FIGMA_ONLY, produce these artifacts for a complete run:
- normalized design decisions;
- gap/conflict analysis with provenance;
- canonical
system-spec.jsonconforming to the bundled schema; run-manifest.jsonwith target and user-designated Figma source provenance;- spec-only
preflight-validation-report.json; - compiled
execution-contract.jsonproving the local style templates are required inputs; - deterministic
figma-generation-plan.jsonproduced by the sole writer entrypoint and containing no external runtime locators; - compiled Figma foundations and component library;
- two complete live writer/reconciler runs whose normalized read-back SHA-256 values are equal;
figma-live-audit.jsoncaptured from the exact target file with exact inventory, role-based template evidence, cross-session registry provenance, writer provenance, and full component visual-fidelity evidence;- final
validation-report.jsonproduced with all live artifacts andcompletion_eligible: true; - concise derivation summary explaining repairs, waivers, residual risks, and the highest-impact inferred decisions.
For MARKDOWN_WITH_FIGMA_EVIDENCE, produce these artifacts without modifying Figma:
- normalized
design-decisions.jsonand, when needed,contract-context.json; - focused read-only Figma evidence for the scoped Tokens and public components, with file identity and stable evidence locators;
- spec-only validated and frozen
system-spec.jsonplus its exact SHA-256 and preflight report; figma-spec-reconciliation.json, preserving both canonical and Figma comparison snapshots for every scoped Token and component;contract-ir.jsonbound to the frozen system-spec SHA-256 and reconciliation evidence;- the complete L0–L7
design-system-contract/package andcontract-manifest.json; - Markdown-native validation and deterministic repeat-render evidence;
figma-evidenced-markdown-report.json, including comparison totals, conflict resolutions, mapping status, andfigma.modified=false.
For COMBINED, preserve all 12 Figma artifacts and additionally produce:
contract-context.jsonwhen product, principle, governance, or lifecycle inputs extend the canonical design-decision schema;contract-ir.jsonbound to the frozen system-spec SHA-256;- the complete L0–L7
design-system-contract/package andcontract-manifest.json; - Markdown-native validation and deterministic repeat-render evidence;
combined-acceptance-report.jsonreporting the independent Figma result, independent Markdown result, shared digest result, mapping-evidence result, drift result, and overall verdict.
Numeric width-style Size axes such as Dialog 480|640|800 are non-control sizing: content icons resolve through the no-Size default 16px, never through the numeric width value.
Treat 1440px as the minimum documentation-frame width. If a canonical ComponentSet matrix is wider than the specimen stage's inner bounds, expand the documentation frame and its fixed intermediate component-group wrappers until every declared Size column and annotation is fully visible; clipping a legal column is blocking.
Run the final gate only after live Figma read-back:
python3 <skill-dir>/scripts/validate_system.py system-spec.json \
--run-manifest run-manifest.json \
--execution-contract execution-contract.json \
--figma-audit figma-live-audit.json \
--require-live-figma \
--report validation-report.json
Preserve the spec and validation report outside /tmp when they are intended as project artifacts. Use /tmp only for ephemeral execution state required by the official Figma skills.
-
v0.8 asset refinement: all Loading glyphs use exact bundled
assets/icons/loading.svg, including Core Button/Toast, Agent media and uploads. Run the sharedloading-iconsstage after icon imports, before component construction, and as a terminal repair/audit. Preserve its SVG geometry, node opacity and paint opacity; only semantic color and proportional size may change. Generated spinner rings and dashed-circle substitutes are forbidden. -
Markdown Code Block, ToolCall File and DiffViewer share
appearance.actions_gap=space/4(16px), with HUG action groups and local connected icon instances. -
Content images use the five original user JPEGs registered in Markdown
default_media.content_assets. Never inline a downsampled thumbnail to fit the 50k script transport. Runagent-markdown-media-assetto resolve carriers, verify each local SHA-256, then call Figmaupload_assetsfor its pending targets and POST the verifiedupload_source_assetbytes. Use original bytes by default. The fifth image has one pinned JPEG-80 upload encoding at the unchanged 5400×3600 size because its original exceeds the upload limit; retain both originals and this explicit transport derivative. Continue only after all upload responses succeed. Markdown build/audit must verify each image's original dimensions. Media Set tiles use the five assets in declared order; Image ratios share content-primary. Preserve avatar-primary. -
2026-09-07 ChatBox/A2UI refinement: resolve their
role/*radius references through the current Foundation radius usage map, never substitute fixed scale levels learned from a reference. ChatBox shell uses multiline_control, Upload Card uses card and its icon tile compact_control; A2UI shell/content/Card use card and Footer Buttons use control. ChatBox text states are Placeholder / Value / Focus / Disabled, with separate Recording waveform and Sending state. Voice is a 40px icon-only control using the exact bundled user microphone.svg, not a text Button; Recording replaces typing text with the contracted waveform. Populate five connected upload cards with distinct Markdown/PDF/Document/Spreadsheet/ZIP assets, preserve editable names, and keep one clipped horizontal scrolling row at every width. A2UI Header Show progress is a default-false Boolean, including all three default examples. Every A2UI Slot, empty or populated, is FILL horizontally and HUG vertically; this explicit family rule overrides generic empty-Slot HUG width. Check these rules in canonical validation, shared writer and live audits. -
ChatBox action refinement: every toolbar action, including Send and both Recording actions, uses the same
controlradius role. Never mix circular Send with rectangular peers; a full-radius role makes every icon action circular and text action pill-shaped, while a small-radius role applies to all. Focus includes a separate visible caret beside editable text. Recording uses a 24px waveform track with 128 narrow bars, maximum 16px high; its toolbar contains only left Cancel (Close/X) and right Finish (Check), no other control nodes. Upload cards never wrap: five fixed-width cards remain in a clipped FILL-width viewport withoverflowDirection=HORIZONTAL, verified at 800px and 420px composer widths.
Documentation preview surfaces
Documentation backgrounds are presentation chrome, not product semantics. Do not generate bg/documentation, a renamed equivalent, CSS variable, alias, or product color swatch for them. Use raw unbound #FFFFFF in Light and #000000 in Dark on documentation roots and Contract Bars. Resolve the explicit Color preview mode through ancestors first, then a Dark name hint, otherwise Light, at generation/reconciliation time. Raw paints do not switch automatically when the user changes a mode: rerun documentation-backgrounds to reconcile, then audit. Preserve the fixed Cover B, fill-less Specimen Stages, and real product surfaces. For legacy files, unbind all documentation consumers, remove exact obsolete swatches, verify no remaining references on all pages, then run documentation-variable-cleanup to remove the exact legacy Variable. Run documentation-backgrounds and documentation-backgrounds-audit for Getting Started, Foundations, and Components; require zero violations and absence of the forbidden Variable.
Scan to join WeChat group