> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uspec.design/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Product updates and release history

<Update label="V2.3 — May 2026" description="Typed componentProperties snapshot threaded end-to-end through the Figma plugin, SLOT-binding bug fix, and a renderer rewrite that drops the booleanOverrides projection in favor of the typed snapshot for the Referenced components table">
  ## uSpec V2.3

  The Figma plugin now captures every placed instance's full typed `componentProperties` surface (booleans, instance-swaps, text overrides, variant choices) and threads that snapshot end-to-end through the extraction pipeline so the `create-component-md` renderer's "Referenced components" override table reads typed values directly instead of guessing from a value-only `booleanOverrides` projection. The same release fixes a long-standing SLOT-binding bug where the plugin was matching SLOT nodes via the wrong `componentPropertyReferences` key and silently dropping default-child instances from the classification UI.

  ### Typed componentProperties snapshot (Figma plugin 2.4.0)

  * **Phase E** captures `componentProperties` on every walked INSTANCE via the new `snapshotComponentProperties` helper in `figma-plugin/src/safe.ts`. The snapshot mirrors Figma's `InstanceNode.componentProperties` API exactly — every entry carries `{ type, value }` with `type` typed to `BOOLEAN | INSTANCE_SWAP | TEXT | VARIANT | SLOT` — and strips Figma's `#…` clean-key suffix from each property name
  * **Phase F′** (`childComposition.ts`) forwards the snapshot into every `_childComposition.children[*]` entry, and the plugin UI round-trips it back into the sandbox so the `extract` merge can attach it to slot-origin entries that bypass the first-guess builder. `null` for non-INSTANCE entries (FRAMEs, vectors, layout wrappers) and for slot-preferred entries (which describe a referenced component, not a placed instance — read `propertyDefinitions.slots[].preferredInstances[]` for those defaults)
  * **`booleanOverrides` is now legacy.** The field is still emitted on every entry — it's used by the first-guess fingerprinting that groups identical sub-component placements — but it's now a booleans-only projection over the typed snapshot instead of an independent read. Slot-default-child entries that previously carried an empty `booleanOverrides` now carry the projected booleans correctly
  * The new field is documented in `figma-plugin/docs/base-json-schema.md` and the plugin's post-change checklist

  ### SLOT-binding bug fix (Figma plugin 2.4.0)

  * SLOT nodes are now matched to their declared slot property via the new `getSlotPropName` helper, which prefers the authoritative `componentPropertyReferences.mainComponent` binding (per Figma's SlotNode docs) and falls back to the SLOT node's own `name` when that binding is absent — the common case in real files, where SLOTs typically only carry the `visible` binding to a separate BOOLEAN prop
  * This replaces a buggy `Object.values(cpRefs)[0]` lookup in `phaseA.ts` and `code.ts` that was picking up the `visible` binding (e.g., "show leading slot") instead of the slot binding (e.g., "leading slot"), causing every later lookup-by-slot-prop-name to miss and silently dropping default-child instances from the classification UI
  * The plugin now also logs a soft `console.warn` when a declared slot property has no matching SLOT node in the default variant — surfaces designer-side renames or genuinely empty slots so the gap is visible

  ### Renderer rewrite for Referenced components (uspec-skills 0.2.11)

  * `references/component-md/agent-component-md-instruction.md` introduces three small helpers shared by the Composition bullet rules and the API "Referenced components" `####` block:
    * `displayName(child)` prefers `parentSetName` over the variant-identifier `mainComponentName`. When a referenced child is a variant of a COMPONENT\_SET, Figma's `mainComponentName` is the variant identifier (`"layout=icon-only, size=small, color=default"`) — useful as a configuration but useless as a component name. `parentSetName` is the human-readable set name (`"action button"`)
    * `slug(child)` derives the spec filename from `displayName(child)` instead of the raw main-component name, so multi-variant references resolve to the right `./{slug}.md`
    * `slotSuffix(child)` appends `" (via slot **{slotName}**)"` when a referenced child lives inside a SLOT, so the engineer can locate it in the parent's anatomy without cross-referencing the API's slot table
  * The "Referenced components" override table now reads `child.componentProperties` exclusively. One row per entry in the typed dict, with per-`type` value formatting:
    * `BOOLEAN` → `true` / `false`
    * `INSTANCE_SWAP` → `(instance \`{nodeId}\`)\`
    * `TEXT` → the literal string in backticks
    * `VARIANT` → the bare option, with `"Variant axis on the placed instance."` in the Notes column
  * The legacy `booleanOverrides` field remains on every entry for backward compatibility with the first-guess fingerprinting, but is no longer the source of truth for the rendered table. `subCompVariantAxes` is also explicitly demoted from the table — it lists *what axes the child exposes*, not what the parent's placement chose, and belongs in the referenced child's own spec
  * Slot context is folded into the lead paragraph as a participle clause ("…as the default fill of the **{slotName}** slot") so it shows up exactly where the engineer needs it
  * Decorative-children rollup is now scoped to top-level entries only — slot-origin entries never appear at the top level and are not part of that count

  ### Documentation

  * `implementation.md` now documents the two new `safe.ts` exports (`snapshotComponentProperties`, `getSlotPropName`), the SLOT-binding bug fix that motivated the latter, and the Phase F′ → renderer flow for the typed `componentProperties` snapshot
  * `figma-plugin/docs/base-json-schema.md` documents the new `componentProperties` field on `_childComposition.children[]`, demotes `booleanOverrides` to a backward-compat projection, and adds the field to the post-change checklist

  Run `npx uspec-skills update` to pick up the renderer change. To get the new Figma plugin behavior, rebuild `figma-plugin/` locally (`cd figma-plugin && npm install && npm run build`) and re-import the manifest in Figma Desktop. The plugin doesn't ship via npm — it's built per-machine.
</Update>

<Update label="V2.2 — May 2026" description="Render-meta JSON appendix for component-md, layer-identity stamping in extract-structure, borderWidth/borderAlign row pair, and Figma plugin 2.3.0 with node-id stamping and boolean-gated layer fallback">
  ## uSpec V2.2

  Component Markdown specs now ship with a machine-readable render-meta appendix, structure extraction stamps Figma layer identity on every section and group header, and border rows are emitted as a `borderWidth` + `borderAlign` pair. The release ships a new Figma plugin (`uspec-extract` 2.3.0) that stamps Figma node ids on every walk entry, captures `strokeAlign`, and resolves boolean-gated layers even when they're absent from the default variant. Two follow-up fixes to the structure skill (revert to unified flow, gate `borderWidth` on a painted stroke, forbid node-id / TODO stubs in Notes) ship in the same release.

  ### Render-meta appendix in Component Markdown

  * The `component-md` template gains a fenced JSON block delimited by `<!-- render-meta:start v=1 -->` / `<!-- render-meta:end -->` carrying machine-readable component metadata: `schemaVersion`, `extractedAt`, `sourceHash`, `fileKey`, `nodeId`, `component`, `variantAxes` / `variantAxesDefaults`, `propertyDefs`, `booleanDefs`, `subComponents`, `slotContents`, `sectionTargets`, `groupTargets`
  * Downstream `create-*` skills (structure, color, anatomy, property, …) read this block to resolve sections, row-groups, and boolean-gated layers back to live Figma layers — no more fuzzy name matching against `layoutTree` and no need to re-extract through MCP
  * `schemaVersion` is pinned at `"1.0"` for V2.2; future breaking changes will bump it. `sourceHash` is a SHA-256 of the underlying `_base.json` so consumers can detect drift between the `.md` and the extraction it was rendered from
  * The block is **mechanical pass-through** of `_base.json` and the structure cache — no interpretation, no synthesis. Two `create-component-md` runs against the same `_base.json` produce byte-identical render-meta

  ### Layer identity stamped on structure output

  * `extract-structure`'s new **R6** rule populates `section._anchor` (`{ layerName, layerId }`) on every section and `row._layerName` / `row._layerId` on every group-header row, reading directly from `_base.json.variants[<default>].layoutTree`
  * Composition sections anchor to the variant root with `layerName: "__root__"`; sub-component sections anchor to the in-context INSTANCE node (NOT the canonical `subCompSetId`, which is already covered by render-meta `subComponents[]`); slot-content sections anchor to the slot's host frame; zone-specific sections anchor to the named FRAME
  * Group-header rows (any row where `isSubProperty !== true` AND `spec` is a zone descriptor, not a property family) carry the literal Figma layer name and node id. Layers present only in `revealedByVariantName[*]` (e.g., a `clear button` parked under `state=active`) emit `_layerId: null` with an explanatory `notes` entry — the row is still present, just unpinned
  * The `create-component-md` orchestrator now reads these fields directly into render-meta. A legacy fallback (name-walk against `layoutTree`) covers caches produced before this release; re-running `extract-structure` is recommended to regenerate the cache with the new fields

  ### `borderWidth` + `borderAlign` row pair

  * Whenever a `borderWidth` row is queued (gate: `strokePaintToken != null`), a sibling `borderAlign` row is queued from `dimensions.strokeAlign.display` (`inside` / `outside` / `center`). The two rows share the same gate — emit both, or neither
  * The coverage matrix (`_extractionArtifacts.coverageMatrix`) accepts `borderAlign` as a first-class family alongside `borderWidth`, with identical R4/R5 detection rules
  * Legacy fallback: when `dimensions.strokeAlign` is absent from a `_base.json` produced by a pre-2.3.0 plugin build, `borderAlign` emits as `"—"` with `provenance: "not-measured"` and `generalNotes` surfaces a single line recommending re-extraction. No row is silently dropped

  ### Figma plugin 2.3.0 (`uspec-extract`)

  * **Boolean-gated layer fallback (Phase A).** Boolean property → gated layer resolution now walks `componentPropertyReferences.visible` instead of relying on the default variant's `componentProperties` keys. When the gated layer is absent from the default variant (e.g., a "clear" button that only appears when input is active), the resolver falls back to scanning every sibling variant in the COMPONENT\_SET. First match wins; the resulting `associatedLayerId` is canonical and downstream-consumable
  * **`strokeAlign` capture (Phase E).** `extractDims()` now emits `strokeAlign` as `{ value, token: null, display }` where `value` is the raw Figma enum (`"INSIDE"` / `"OUTSIDE"` / `"CENTER"`) and `display` is the lower-cased prose form. Present on `variants[].dimensions`, `variants[].treeHierarchical[*].dimensions`, and every `subComponentVariantWalks` entry. **Not** on `variants[].revealedTree[*].dimensions` — Phase G uses a minimal `dim()` extractor focused on topology; dimensional ground truth always comes from the baseline `treeHierarchical`
  * **Node ids on every walk entry.** `treeHierarchical`, `layoutTree`, `treeFlat`, `colorWalk`, `revealedTree`, `revealedColorWalk`, and Phase I's `measureHierarchical` all carry the Figma node `id` (or `nodeId` for color entries) of the source layer. Downstream consumers resolve walk entries back to live layers without name- or path-based search
  * Rebuild locally to pick up the changes: `cd figma-plugin && npm install && npm run build`, then re-import the manifest in Figma Desktop. The plugin doesn't ship via npm — it's built per-machine

  ### `borderWidth` gate fix and authoring discipline

  * `borderWidth` rows now require `strokeWeight.value > 0`. The extractor emits `strokeWeight: { value: 0 }` for nodes that have the property set but no paint in `node.strokes`; without this gate the agent emitted a phantom `borderWidth: 0` row even though no border is painted on the component
  * The structure rendering rules now forbid Figma node ids and `TODO: confirm with Figma` stubs in `Notes` columns. Notes is engineer-facing implementation context — when a value cannot be confirmed, skip the row or surface the gap in `generalNotes` rather than leak extraction-time artifacts into the rendered spec
  * The Mode A / Mode B split, per-group annotation resolver, and cross-variant 4d/4e drivers added on top of V2.1.4's `7d2e7f4` baseline are reverted — they made the workflow brittle without improving output. `create-structure` is back on the unified `rootOnly` / `fullTree` annotation model with cleaner output

  ### Housekeeping

  * `maintaining.md` updated for npm's current **web-based 2FA** flow — `npm publish` now opens a browser tab for approval and no longer requires `--otp=…`. The authenticator-app fallback is documented for accounts not on web-based 2FA
  * New root-level `.npmrc` mirrors `packages/cli/.npmrc` and pins the registry to public npm at the repo level. The layered registry safety (publish config + `.npmrc` + prepublish guard) still aborts mis-pointed publishes with a clear error
  * `utils/README.md` removed (`utils/` is no longer a meaningful directory in the repo)
  * `README.md` and `implementation.md` prose tightened — the canvas-measurements paragraph now documents the `rootOnly` vs `fullTree` annotation policy explicitly and the new `{ success, plannedColumns }` return semantics

  Run `npx uspec-skills update` to pick up the skill changes. To get the new Figma plugin behaviour, rebuild `figma-plugin/` locally and re-import the manifest in Figma Desktop. No action needed on existing Figma libraries.
</Update>

<Update label="V2.1.4 — May 2026" description="create-structure accepts an authoritative .md input, ships an explicit reasoning-discipline contract, gates borderWidth on strokePaintToken, and adds use_figma string-escaping guidance">
  ## uSpec V2.1.4

  The `create-structure` skill now accepts an authoritative `components/<name>.md` (produced by `create-component-md`) as its highest-precedence input. When provided, the `.md` is the source of truth for every property it documents — `borderWidth`, `padding`, `cornerRadius`, sizing modes, slot dimensions, sub-component identity, bound token names. Figma extraction is demoted to node-ID resolution and drift detection. Alongside this, the structure instruction file gains an explicit reasoning-discipline contract, `borderWidth` rows now require evidence of a painted stroke, the architecture doc captures a `use_figma` script-escaping rule, and the Figma plugin manifest carries its registration `id`.

  ### `.md`-authoritative mode (Structure)

  * `skills/create-structure/SKILL.md` adds **Step 0 — Detect Input Mode**. Mode A is description-only (today's behavior). Mode B reads `components/<name>.md` in full and persists it as `MD_SPEC` before any extraction runs
  * Step 4 (visual context, enhanced extraction, cross-variant comparison, non-dimensional axis diff) still runs in Mode B, but its output is demoted to a **node-ID resolver and drift detector**. Extraction values that disagree with the `.md` are logged in `generalNotes` and the `.md` value wins
  * Step 6 in Mode B is reduced to (1) mapping each `.md` row to extraction nodes for annotation rendering, (2) reconciling each `.md` row against the corresponding extraction value, (3) skipping the cross-section pattern recognition pass (`create-component-md` already did it)
  * Every emitted row now carries a required `provenance` field: `"md"` (value came from the `.md`), `"measured"` (`.md` was silent, value came from extraction), `"user-rule"` (value came from a user adjustment rule), or `"inferred"` (with an accompanying note explaining what was inferred from what). Rows without a defensible provenance are not emitted
  * When both a description and an authoritative `.md` are provided, the `.md` wins for properties it documents and the description applies only to anything the `.md` is silent on

  ### Reasoning discipline (Structure)

  * `references/structure/agent-structure-instruction.md` adds a **Reasoning Discipline** section that applies at every step — extraction interpretation through rendering. Five rules: (1) the `.md` is the source of truth when provided, (2) every row needs provenance, (3) no confabulation — skip rows or surface gaps in `generalNotes` rather than fill in defaults, (4) screenshots verify layout intent only, not paints/strokes/spacings/radii/tokens, (5) `strokeWeight` alone is not evidence of a border
  * The Conflicts table grows a new top row covering authoritative `.md` precedence, and the existing "Figma contradicts description" row is qualified to "no `.md` provided"
  * The Common Mistakes section adds matching entries: hand-rolling canvas measurements, hand-curating the annotation plan, treating `strokeWeight` as evidence of a border, citing screenshots for paint or border decisions
  * The Do NOT list adds: overriding an authoritative `.md` value with anything inferred from extraction or screenshots, emitting `borderWidth` when `strokePaintToken == null`, citing a screenshot as evidence for paints/strokes/spacing/radii/tokens, inventing values to fill rows

  ### `strokeWeight` no longer implies a border (Structure)

  * The Stroke weight reading reference in `references/structure/agent-structure-instruction.md` is rewritten around a new `strokePaintToken` signal co-emitted by the extractor. A frame can carry `strokeWeight: 1` with `strokes: []` — no border is painted, and a phantom `borderWidth` row should never be emitted from such a node
  * New emission rule: emit a `borderWidth` row only when `strokePaintToken != null`. The Inspect Reference table's Stroke width row is updated to match
  * The collapsed dimensional schema description in `## Dimensional Data` clarifies that `strokeWeight` is only authoritative as evidence of a border when paired with a non-null `strokePaintToken`

  ### `use_figma` / `figma_execute` script escaping (architecture)

  * `implementation.md` adds a new "Authoring `code` strings for `use_figma` / `figma_execute`" subsection under Figma MCP Tools. Both providers serialize the `code` argument through JSON before the Figma sandbox runs it, so `\'` inside a `'...'` JS string is a recurring source of `SyntaxError` after re-escape
  * **Rule:** when authoring note text, descriptions, or any content with apostrophes (clear-button copy like `"Visible when value isn't empty"`, contracted English in design-intent notes), wrap the JS string in `"..."` (double quotes) or use template literals (backticks). Never reach for `\'` inside a `'...'` string. This applies to every skill that ships note-bearing rows through `__ROWS_JSON__` or its equivalents

  ### Figma plugin manifest id

  * `figma-plugin/manifest.json` now declares its registration `id: "1635184425006534227"`. This is the plugin's permanent identity in the Figma plugin registry — it does not change anything about how the plugin runs locally or what `_base.json` it produces, but it stabilises the manifest for future plugin distribution work

  ### Scope

  * No changes to extraction shape, table contents, sub-component walks, slot handling, or canvas measurement overlay behavior beyond the `borderWidth`-gating rule above
  * Already-rendered Figma structure specs are unaffected — the new mode and the new emission rule only change future `create-structure` runs

  Run `npx uspec-skills update` to pick up the new skill content. No action needed on Figma libraries.
</Update>

<Update label="0.2.8 — May 2026" description="CLI build script wipes templates/ before each build so deleted files no longer ship as zombies">
  ## uspec-skills 0.2.8

  The `packages/cli/scripts/build.mjs` build now wipes `templates/` before re-syncing it from the source `skills/` and `references/` trees. Previously the build only overlaid via `cpSync`, so any file ever copied stayed forever — files deleted from the source persisted in `templates/`, shipped in the npm tarball, and were resurrected into consumer `references/` directories on every `npx uspec-skills update`.

  ### What you might notice after updating

  * Running `npx uspec-skills update` may **delete** stale files in your local `references/` directory that were never part of the current source tree (e.g., files like `references/_shared/mcp-adapter.md` or `references/structure/scripts/*.js` that were removed from the source long ago but kept resurrecting). This is the cleanup catching up
  * No skill or spec behavior changes. This is a packaging hygiene fix only

  Run `npx uspec-skills update` to pick up the change.
</Update>

<Update label="V2.1.3 — May 2026" description="create-structure extraction no longer crashes on TEXT children when reading auto-layout properties">
  ## uSpec V2.1.3

  The `create-structure` skill's variant-walk and cross-variant comparison scripts now tolerate non-container children (TEXT, VECTOR, GROUP, …) when reading auto-layout properties such as `itemSpacing`, `counterAxisSpacing`, and the `padding*` family. Previously, the first TEXT child encountered during the walk threw a synchronous `TypeError` and aborted the entire extraction — leaving the spec unrenderable.

  ### Why the walk could throw (Structure)

  * Step 4b `extractDimensions` and Step 4d `measureNode` recurse into every child via `extractChildren` / `measureChildren`. Children include heterogeneous node types — TEXT, VECTOR, GROUP — that do not support auto-layout properties
  * The Figma plugin API throws synchronously when you read `itemSpacing` (or other layout-only properties) on a node that doesn't support them. The previous guard `node[p] !== undefined && node[p] !== figma.mixed` ran the access *first*, so the throw fired before the comparison
  * Step 4e already used the correct defensive pattern (per-access `try/catch` plus an `isContainer = 'layoutMode' in node` gate); Steps 4b and 4d now match it

  ### Defensive read pattern (Structure)

  * Every property read in Steps 4b and 4d is now wrapped in `try { ... } catch {}`, mirroring the `sg(node, prop)` accessor in `figma-plugin/src/safe.ts`
  * Layout-only property groups (padding, `itemSpacing`, `counterAxisSpacing`, `layoutMode`, primary/counter axis aligns, `layoutSizing*`, `clipsContent`) are gated on `isContainer = 'layoutMode' in node` so leaf nodes skip them entirely instead of throwing
  * The collapsed dimensional schema (`padding`, `cornerRadius`, `strokeWeight`, `typography`) is unchanged — Steps 5, 6, and 11 read the same shape they always did

  ### Documentation (`uspec-skills` 0.2.7)

  * `skills/create-structure/SKILL.md` adds a maintainer note above the Step 4b script explaining the throw-on-leaf hazard and the `try/catch` + `isContainer` pattern, so future script edits stay safe by default

  ### Scope

  * No changes to extraction shape, plan-building, table contents, sub-component walks, or canvas measurement overlays
  * Already-rendered Figma structure specs are unaffected — this fix unblocks future runs on components whose default variant has TEXT children at the root or inside auto-layout containers

  Run `npx uspec-skills update` to pick up the fix. No action needed on Figma libraries.
</Update>

<Update label="V2.1.2 — May 2026" description="create-structure padding measurement overlays now match autolayout values on cross-axis-centered children">
  ## uSpec V2.1.2

  The `create-structure` skill now picks the right anchor child when drawing native Figma measurement overlays for hardcoded padding rows, so canvas labels match the autolayout values documented in the table — even when other children are HUG-sized and centered along the cross axis. This corrects a divergence introduced when the measurement overlays were restored in V2.1 (`uspec-skills` 0.2.5).

  ### Why the labels could disagree with the table (Structure)

  * Hardcoded padding rows draw a measurement line whose pixel length is what Figma renders as the label. Until V2.1.2 the line always anchored to the first or last visible child, so on a horizontal capsule with `counterAxisAlignItems: CENTER` and HUG-sized children the line measured the centering offset rather than the autolayout padding
  * Token-bound padding rows were unaffected — `freeText` carries the token name regardless of geometry — and gap / `itemSpacing` rows were unaffected because consecutive children sit edge-to-edge with the gap by definition. Only **hardcoded counter-axis padding** rows misread

  ### Padding anchor rule (Structure)

  * The Step 11c annotation script now picks the child whose edge sits on the container's inner-content edge for that side (within a 0.5-px epsilon of `paddingTop` / `paddingBottom` / `paddingLeft` / `paddingRight`) and draws the line against that child. Figma's default numeric label then matches the autolayout value the table documents
  * When no child aligns to that edge, the line falls back to the first/last visible child but carries a `freeText` override of the autolayout value so the label still matches the table
  * Implemented inline as a new `findEdgeAnchor` helper above `annotate`; no per-row configuration is required

  ### Documentation (`uspec-skills` 0.2.6)

  * `references/structure/agent-structure-instruction.md` splits the `freeText` policy bullet into "hardcoded padding row" (anchor + fallback) vs "hardcoded gap/itemSpacing row" (default label) so the contract the agent reads matches what the SKILL implements
  * `implementation.md` updates the "Canvas measurements (Structure)" architecture summary to describe the anchor + `freeText`-fallback policy

  ### Scope

  * No changes to extraction, plan-building, table contents, or the markdown spec
  * Already-rendered Figma structure specs keep their old labels until they are explicitly re-annotated; the fix changes only future runs and any explicit re-annotation pass

  Run `npx uspec-skills update` to pick up the fix. No action needed on Figma libraries.
</Update>

<Update label="0.2.5 — May 2026" description="Native Figma measurement overlays restored in create-structure with high-fidelity preview rendering">
  ## uspec-skills 0.2.5

  The `create-structure` skill restores native Figma measurement overlays on its preview instances and renders previews with full slot content and recursive boolean state. This closes the loop on the temporary pause from V1.6.0 — the Figma MCP `use_figma` tool now supports `page.addMeasurement(...)`, so measurement lines appear directly on the canvas alongside table-driven token rows. No edits to `create-component-md`; this is a rendering-layer patch.

  ### Native canvas measurements (Structure)

  * Step 11c emits `page.addMeasurement(...)` for the allow-listed auto-layout properties documented in the section table: `paddingTop` / `paddingRight` / `paddingBottom` / `paddingLeft`, `itemSpacing`, `minWidth` / `maxWidth`, and `minHeight` / `maxHeight`. Other properties (corner radius, typography, color) remain table-only by design
  * Token-bound rows pass the token name as `freeText` so the measurement label reads as the token, not just the resolved pixel value. Hardcoded rows render Figma's default numeric label. Min/max constraints render with a `"min N"` / `"max N"` prefix
  * Per-instance idempotency is provided by `getMeasurementsForNode(...)` + `deleteMeasurement(...)` before each annotation pass, so re-running a section never duplicates overlays
  * Both `figma-console` (`figma_execute`) and `figma-mcp` (`use_figma`) execute the identical script — no MCP-specific branching

  ### Preview fidelity (Structure)

  * **Slot content previews** now nest the preferred component instance into the actual `SLOT` node inside the preview, so the slot region renders with real content instead of an empty placeholder. If `appendChild` fails (for example in a read-only context), the preview falls back to a 0.6-opacity ghost overlay positioned at the slot bbox
  * **Recursive boolean enabling** reaches every nested instance in the preview except inside boolean-toggled sections, so optional children documented in the table actually appear in the rendered preview
  * Step 12 verification adds a `measurementCount` / `plannedColumns` contract check on the value returned by Step 11c. Measurement overlays are a canvas layer that does not appear in `figma_take_screenshot` / `get_screenshot` output, so visual screenshot review is no longer the source of truth for measurement coverage

  ### Documentation

  * `references/structure/agent-structure-instruction.md` adds a Canvas Measurements subsection covering the allow-list, `freeText` semantics, annotation scope, and the screenshot caveat
  * `implementation.md` documents the render-time slot nesting and canvas measurement architecture parallel to the existing marker positioning notes

  Run `npx uspec-skills update` to pick up the change. No action needed on Figma libraries.
</Update>

<Update label="V2.1.1 — May 2026" description="Standardize transient state naming on past-participle form (hovered)">
  ## uSpec V2.1.1

  Transient interactive state names now use the past-participle form (`hovered`, `pressed`, `focused`) so they read in parallel with persistent ones (`enabled`, `disabled`). Previously the recommendation mixed `hover` with the participle forms, which read inconsistently in property tables, color spec column headers, and prompt examples. This is a non-breaking change: existing Figma libraries that name their state-axis options `hover` continue to be recognized.

  ### Recommendation update

  * `references/api/api-library.md` now recommends `hovered` alongside `pressed` and `focused`. The recommendation table also explicitly documents that earlier docs and many existing Figma libraries use `hover`, and that both forms are recognized by the extractor.
  * All instruction files (`agent-api`, `agent-color`, `agent-structure`, `agent-anatomy`) and skill prose updated to use `Hovered` / `hovered` in state listings, JSON examples, and worked examples.
  * Mintlify spec pages, Getting started examples, and Troubleshooting prompt suggestions updated to match.

  ### Backwards compatibility (figma-plugin 2.1.1)

  * The `stateKeywords` matcher in `figma-plugin/src/phaseF.ts` and `skills/create-color/SKILL.md` accepts **both** `hover` and `hovered` as state-axis option names, so designers who keep the legacy name continue to get correct axis classification.
  * Real design-token identifiers (`hoverOverlayAlpha`, `interactivePrimaryHover`, etc.) are unchanged — these are platform variable names, not state labels.
  * Generated specs continue to render whichever form the source Figma file uses; output is truthful pass-through, not a silent rewrite.

  Run `npx uspec-skills update` to pick up the recommendation. No action needed on Figma libraries unless you want to rename your state-axis options to match.
</Update>

<Update label="V2.1 — May 2026" description="Figma plugin layout-wrapper descent and sub-component placement dedup">
  ## uSpec V2.1

  The uSpec Extract Figma plugin now handles layout-wrapper FRAMEs and repeated sub-component placements correctly, so the classification checklist surfaces the real sub-components and arrays of identical instances are documented as one entry with a count instead of N duplicates. A coordinated `uspec-skills` patch keeps `create-component-md` from misreading the new entry shapes.

  ### Layout-wrapper descent (Figma plugin 2.1.0)

  * Designers commonly wrap a component's real sub-components in a single auto-layout FRAME for clipping, scroll, padding, or grouping (for example, a Button group's `group` wrapper for the `overflow=scroll` variant). The plugin now descends through these wrappers so the classification UI surfaces the actual sub-components instead of the wrapper
  * Each wrapper is recorded as an explicit decorative entry in `_childComposition.children[]` with `topLevelInstanceId: "wrapper:<depth>"` and `classificationEvidence: ["layout-wrapper"]`, so layout chrome remains visible to downstream consumers
  * `idx:N` in `topLevelInstanceId` now indexes into the *effective* container (post wrapper descent), not the variant root. Phase I and `treeHierarchical` are unaffected

  ### Sub-component placement dedup (Figma plugin 2.1.0)

  * Repeated placements of the same sub-component (for example, six Selection Button instances inside a Button group) now collapse to one `_childComposition` entry instead of N. The designer classifies once; multiplicity is recorded in three new fields:
    * `placementCount` — number of sibling placements that share the entry's identity
    * `placementIndices` — original positions in the effective container's children
    * `placementsVary` — `true` when at least two placements differ in main component or boolean overrides, signalling a heterogeneous array
  * The plugin UI surfaces a `× N` badge on grouped rows and a `varies in state` tag when `placementsVary` is true, so the designer can spot heterogeneous arrays at a glance
  * Equivalence fingerprint covers `mainComponentName` (which encodes variant choice for component-set members) and `booleanOverrides` — instance-swap and text-override differences are intentionally not in the fingerprint and remain visible in `treeHierarchical`

  ### `create-component-md` Step 4.5 fix (uspec-skills 0.2.3)

  * The post-extract review previously flagged any `_childComposition` entry without `user-selected` evidence as malformed. The new wrapper FRAME entries legitimately carry `["layout-wrapper"]` evidence, so the check is now scoped to `nodeType === "INSTANCE"` — the only entries the plugin UI asks the designer to confirm
  * Prevents a spurious "the plugin UI did not reach the designer's confirmation step" warning and a redundant override pass on every plugin run that contains a layout wrapper
  * Run `npx uspec-skills update` to pick up the fix
</Update>

<Update label="0.2.2 — April 2026" description="First run experience fix">
  ## uspec-skills 0.2.2

  Fixed the first run experience so the skip option works as intended. Run `npx uspec-skills update` to pick up the fix.
</Update>

<Update label="V2.0 — April 2026" description="New create-component-md skill, uSpec Extract Figma plugin, and uspec-skills install CLI">
  ## uSpec V2.0

  A major milestone release. uSpec now supports two rendering paths: the original Figma-native annotations, and a new **Component Markdown** path that produces a single self-contained `.md` specification you can hand to any LLM. The release ships with a new Figma plugin that captures every variant, token binding, and sub-component deterministically inside Figma's sandbox, and a new `uspec-skills` CLI that replaces the clone-and-copy install flow.

  ### New: `uspec-skills` install CLI (0.2.0)

  * Run `npx uspec-skills init` from any project root. The CLI prompts for your agent host (Cursor, Claude Code, or Codex) and your Figma MCP provider, installs every skill into the matching platform directory (`.cursor/skills/`, `.claude/skills/`, or `.agents/skills/`), copies references into `./references/`, and writes `uspecs.config.json`
  * `npx uspec-skills install --platform <cursor|claude-code|codex>` reinstalls or repairs skills non-interactively
  * `npx uspec-skills update` re-renders skills against the current package version
  * `npx uspec-skills doctor` validates your install and reports missing skills, missing references, or broken cross-references
  * `init` bootstraps a fresh uSpec project into the current directory when no project root marker (`.git/`, `package.json`, or `uspecs.config.json`) is found above it, so the documented "create a new folder, then run init" walkthrough works from an empty directory. A one-line note (`bootstrapping a new uSpec project here.`) is printed when this happens
  * `uspec-skills install` points you at `npx uspec-skills init` when run from a directory with no project root, instead of failing with a generic message
  * All CLI error and log prefixes consistently say `uspec-skills` (the legacy `uspec` shorthand has been removed)
  * The previous flow (cloning the repo and running `utils/sync-skills.sh`) is no longer required. Existing users can keep their clone, but new setups should use `npx uspec-skills init` from their own project root
  * `uspecs.config.json` now records the chosen platform and MCP provider so `firstrun` reads them from disk instead of asking again

  ### New skill: `create-component-md`

  * Orchestrator skill that turns a plugin-produced `_base.json` into a single `components/{componentSlug}.md` file
  * Runs four interpretation specialists: `extract-api` (serial, produces the shared property dictionary), then `extract-structure`, `extract-color`, and `extract-voice` in a parallel batch
  * Deterministic reconciliation gate catches typed disagreements between specialists (conflicting child classifications, mismatched axes, missing states) and serially re-dispatches only the specialist that owns the mismatch
  * Integrity gate validates cache-file shapes, axis consistency, and structure coverage matrix before rendering the Markdown
  * Output sections: Overview, API, Structure, Color, Voice / Screen reader, Provenance. Everything needed to implement the component from scratch without opening Figma
  * Cost envelope: 50k–200k tokens per run. Recommended model: Opus 4.7 High or above
  * [Full guide →](/specs/component-md)

  ### uSpec Extract Figma plugin

  * New Figma plugin that captures a component's complete extractable state in one pass
  * Walks every variant (no default-variant sampling), resolves library-linked variables with name, `codeSyntax`, alias chains, and remote collection metadata, and captures inline font properties alongside text style IDs
  * **Phase I: sub-component variant walks.** Constitutive sub-components are measured across their own variant axes, not only the configuration the parent embeds, so a Button inside a Text Field is specified at every size and density
  * Designer-in-the-loop classification checklist: confirm or flip whether each top-level child is constitutive, referenced, or decorative before extraction
  * Runs entirely inside the Figma plugin sandbox with no network access. Nothing is stored, nothing leaves your machine. To build locally, clone the [uSpec repo](https://github.com/redongreen/uSpec), run `npm install && npm run build` inside `figma-plugin/`, then import the manifest in Figma Desktop. See the [install walkthrough](/specs/component-md#what-you-need)
  * Output is a validated `_base.json` (Ajv schema at `figma-plugin/docs/base-json-schema.md`) that becomes the sole input for `create-component-md`

  ### Documentation

  * New [Component Markdown spec page](/specs/component-md) covering install, usage, the four-specialist pipeline, and skill-side troubleshooting
  * New **Figma Extract plugin** tab on the [Troubleshooting page](/help/troubleshooting) covering build steps, Node version requirements, the watch-mode dev loop, and common install failure modes
  * [Getting Started](/getting-started) rewritten around the CLI flow with platform-specific tabs
  * [Troubleshooting](/help/troubleshooting) updated with `npx uspec-skills doctor` and per-platform repair commands

  ### Structure skill: coverage matrix artifact

  * `extract-structure` now emits a `_extractionArtifacts.coverageMatrix` artifact listing every auto-layout frame walked, the non-zero layout properties found on it, and whether a corresponding row was emitted in the final spec
  * The orchestrator's integrity step asserts `coverageMatrix.complete === true` and independently recounts frames walked, so silently dropped padding or spacing is caught before rendering
  * Fixes a class of bugs where inner wrapper frames with non-zero `horizontalPadding` or `itemSpacing` could be measured but not emitted

  ### Dual-path architecture

  * `implementation.md` fully rewritten to describe both rendering paths, the plugin phases (A–I), the orchestrator workflow, the `.uspec-cache/` layout, and the `extract-*` interpretation skills
  * `uspecs.config.json` gains `extractionSource: "plugin"` and `reconciliation: { autoRetry: true }` to control the new path
  * `.uspec-cache/{componentSlug}/` directory stages the plugin payload and caches each specialist's JSON output. Useful for debugging and for re-running only part of the pipeline
</Update>

<Update label="V1.8.1 — April 2026" description="Recursive nested container measurement and wrapper frame padding coverage in structure specs">
  ## uSpec V1.8.1

  The structure skill now recursively measures nested auto-layout containers and enforces per-wrapper padding documentation — no more collapsed padding notes on parent groups.

  ### Recursive nested container measurement (Structure)

  * `measureChildren` now calls itself recursively instead of using a flat loop for grandchildren — deeply nested wrapper frames (e.g., icon containers inside `trailingContent`) are fully measured and surfaced as `__children` entries in the cross-variant data
  * Fixes cases where intermediate auto-layout frames with their own padding were invisible to the completeness check

  ### Wrapper frame padding coverage (Structure)

  * New verification procedure in the completeness judgment: for each sub-component section, walk `__children` entries recursively — every entry with non-zero padding is an auto-layout container that needs its own group with dedicated rows
  * Catches content areas (e.g., `leadingContent`, `trailingContent`) whose children each have individual padding that was previously collapsed into a single note on the parent
  * Cross-checks against `enrichedTree` when available for redundant validation

  ### Common mistake guidance (Structure)

  * New "Collapsing wrapper frame padding into notes" entry in the instruction file — documents the anti-pattern of merging per-child padding into a parent group header note instead of giving each wrapper its own group
</Update>

<Update label="V1.8.0 — April 2026" description="Composite color specs, context-aware property exhibits, non-dimensional axis coverage, and sub-pixel precision">
  ## uSpec V1.8.0

  The color skill now specs composite paint styles — gradients, multi-layer fills, and blended overlays — with nested hierarchy rows breaking down each layer. The property skill gains a new exhibit planning system with context axis rendering, sparse matrix chapters, and a dedicated instruction file. Structure now diffs every variant axis for structural or property-level changes, and measurements preserve sub-pixel precision.

  ### Composite style support (Color)

  * New `buildCompositeDetail` function in the extraction script detects paint styles with 2+ visible fill layers and emits a `compositeDetail` object with layer stacking order, blend modes, opacities, and gradient stops
  * Token resolution priority updated: paint/stroke style names (`fillStyleId`, `strokeStyleId`) now take precedence over variable bindings (`boundVariables.color`), matching how effect styles are already handled
  * AI interpretation builds `compositeChildren` arrays on elements — solid layers, gradient layers with per-stop detail, and image layers — rendered as nested rows with hierarchy indicators (`#hierarchy-indicator` frame toggled per child row)
  * Both Strategy A (simple) and Strategy B (state-consolidated) rendering scripts support composite child rows with `showIndicator` for middle/last-child visual connectors
  * Instruction file adds composite breakdown guidance, worked examples, rendering rules, and validation checklist items

  ### Exhibit planning and context axis rendering (Property)

  * New Step 1 reads a dedicated instruction file (`agent-property-instruction.md`) containing data validation, exhibit planning, pre-render checklist, common mistakes, and do-not rules — previously inline in SKILL.md
  * Step 4e now includes exhibit planning (Phase B) that produces an `exhibitPlan` array routing each property to the correct rendering template
  * New **context axis** system: when a variant axis qualifies as a visual context (e.g., `variant: primary/subtle`), all other illustrated chapters render grouped rows per context value using new `6a-ctx` and `6b-ctx` templates
  * New **6a-matrix** template for sparse variant matrices — absolute-positioned grid with N/A placeholders for missing combinations, plus standalone chapters for both axes
  * Step renumbering (1–11) with a new Step 5 audit pass that re-reads the instruction file's pre-render checklist before rendering
  * All implementation notes moved from the SKILL.md Notes section to the instruction file, reducing SKILL.md scope to pure orchestration

  ### Non-dimensional axis coverage (Structure)

  * New Step 4e runs a diff script measuring root and direct children across every variant axis not already covered by size/density/shape extraction
  * Step 6 classifies each axis as structural (children differ → separate sections per configuration), property-variant (dimensional properties differ → state-conditional section), or visual-only (skip)
  * New Step 6b runs targeted follow-up extractions for structural axes, giving each configuration complete dimensional data across all sizes
  * Instruction file adds non-dimensional variant axis guidance, decision table entries, and common mistake warnings for skipped diffs and missing property-variant sections
  * User-provided value adjustments now replace extracted values in existing rows with explanatory notes instead of creating duplicate rows

  ### Sub-pixel precision (Structure)

  * All rounding functions updated from `Math.round()` to a `rv()` helper that preserves one decimal place (`Math.round(v * 10) / 10`) — values like 1.5px stay 1.5 instead of rounding to 2
  * Applied across both Step 4b enhanced extraction and Step 4d cross-variant comparison scripts
  * Instruction file updated: "Preserve one decimal place; whole numbers stay whole"

  ### Anatomy refinements

  * Root variant fills/effects now fold into the container note when a container synthetic already exists, instead of always creating a separate statelayer/backplate element
  * Ghost overlays for failed slot insertions deferred to after auto-layout reflow so they use final positioning
  * `instAbsX`/`instAbsY` recomputed after centering to fix absolute transform drift

  ### Element naming (Color)

  * Fill-bearing elements now consistently use a property qualifier: "Container fill" instead of "Container", "Background fill" instead of "Background" — removes ambiguity when the same element also has a stroke
</Update>

<Update label="V1.7.4 — April 2026" description="Evidence-based API reasoning with ownership hints, override promotion, and compound component guidance">
  ## uSpec V1.7.4

  The API skill now separates deterministic evidence from AI reasoning with a structured evidence model, ownership hints, and an explicit override promotion pass. The instruction file adds compound component ownership rules, nested property grouping heuristics, and a worked Text Field example demonstrating state decomposition and child override promotion.

  ### Evidence-based API reasoning

  * New `ownershipHints` array in the extraction script collects deterministic ownership cues from root properties, child overrides, text nodes, and variable collections — each hint includes `evidenceType`, `suggestedExposure`, and a `rationale`
  * New Step 4c requires assembling a structured `ComponentEvidence` object before reasoning about the API — keeping raw facts separate from semantic interpretation
  * `relevantVariableCollections` are now extracted inline during property extraction, with component-name and generic-property matching to discover mode-controlled capabilities like density and shape
  * The instruction file introduces a `ComponentEvidence` TypeScript interface as the required intermediate model between extraction and API generation

  ### Override promotion pass

  * Step 5 now includes a mandatory override promotion pass: every `composableChildren` override key is classified as parent-owned, child-only, or shared
  * Master boolean + sub-boolean combinations are merged into single enums (e.g., `leadingContent: none, icon, text, iconAndText`) instead of being exposed as separate boolean properties
  * New validation checklist items verify that parent-owned properties are not buried in sub-component tables and that broad state axes are decomposed

  ### Compound component guidance

  * New "Critical Rules" quick-reference section at the top of the instruction file highlights the five most commonly violated rules
  * New ownership rules table for compound components with tie-breaker heuristics (parent vs child vs both)
  * New "Choosing Top-Level vs Nested Rows" section with heuristics for `isSubProperty` usage
  * New "Do NOT" section replaces the former "Common Property Categories" with explicit anti-patterns
  * New worked example: Text Field with state axis decomposition, promoted child overrides, and sub-component tables

  ### API library updates

  * Added compound component ownership guidance with decision table and examples
  * Added nested property grouping patterns (`trailingContentType` → nested `label`, `variant`)
  * Added `showCharacterCount` to the Text field canonical API
  * Added `validationState` enum guidance for components with multiple validation-like states
</Update>

<Update label="V1.7.3 — April 2026" description="Screen reader specs now handle preferred slot fills in focus-order planning and artwork previews">
  ## uSpec V1.7.3

  This update extends the voice and screen reader workflow so slot-hosted controls can be documented from the right scenario. The skill now distinguishes default slot children from preferred interactive fills, carries that decision into preview rendering, and validates that the rendered artwork matches the documented focus order.

  ### Preferred slot fills for screen reader specs

  * `create-voice` now resolves SLOT `preferredValues` to local components during extraction and records both preferred instances and default slot children
  * Focus-order planning can choose between the default slot content and a representative preferred interactive fill when a slot-hosted control changes the traversal order
  * Slot metadata now includes visibility bindings, descriptions, raw keys, and contextual child overrides so the agent can reason about conditional focus stops more accurately

  ### Slot-aware artwork rendering

  * Screen reader previews now support `slotInsertions`, allowing the render step to populate slot content before marker resolution and bbox capture
  * The focus-order fallback logic reapplies slot insertions while searching for the richest preview state, improving marker placement for slot-hosted actions
  * States with zero focus stops still render the component preview, while slot-populated states can now show the correct interactive control instead of a default placeholder scenario

  ### Clearer guidance and validation

  * The screen reader instruction file now frames focus order as a single top-level section and removes anatomy-specific language from the task definition
  * Validation guidance is split into pre-render and post-render checks, including explicit checks for slot-hosted focus stops and slot-populated previews
  * `implementation.md` now documents the voice skill's preferred-slot extraction and insertion flow alongside the existing SLOT support across other skills
</Update>

<Update label="V1.7.2 — April 2026" description="Figma slot support refined with ownership-aware structure planning and hosting-context slot sections">
  ## uSpec V1.7.2

  This update sharpens the structure skill's Figma slot support. Section planning now resolves ownership before rendering, so parent-owned roles stay on the sub-component path while true preferred slot content gets slot-specific documentation. Slot content sections also stay focused on hosting context and placement-specific deltas instead of duplicating another component's full structure spec.

  ### Ownership-aware structure planning

  * Section planning now treats `subComponents`, `slotContents`, `enrichedTree`, and `layoutTree` as discovery inputs instead of final section types
  * New ownership resolution classifies each candidate onto exactly one path: `subComponent`, `slotContent`, or composition/root-only
  * Parent-owned structural roles remain sub-components even when they are placed through a slot or slot-like composition
  * Generic library-owned preferred content stays on the `slotContent` path, and overlapping candidates are deduplicated before any sections are emitted

  ### Clearer slot content boundaries

  * Slot content sections now render only for preferred instances that still classify as `slotContent` after ownership resolution
  * `slotContext` is the primary source for hosting-container properties such as sizing mode, padding, and alignment
  * The preferred component's measured `self` values are used only for placement-specific deltas caused by slot context, not as a second full structure spec
  * Section descriptions now explicitly defer component internals to the referenced component spec

  ### Stronger validation and authoring guidance

  * Validation checks now confirm that every instance still classified as a sub-component is covered after ownership resolution
  * Slot-related validation also checks that each surfaced instance is documented on exactly one section path
  * Structure guidance adds clearer examples for container-only rows in slot sections and for single-path ownership decisions
</Update>

<Update label="V1.7.1 — April 2026" description="Slot-aware previews, sub-component token ownership, composition Pattern B, and slot mutation safety">
  ## uSpec V1.7.1

  API configuration examples now render live slot content and text overrides in previews. Color applies a token ownership framework to sub-component entries. Structure gains Pattern B composition sections for standalone components, boolean-toggled previews, and section ID-based rendering. All slot-traversing scripts use a crash-safe recursive collector.

  ### Slot-aware API configuration previews

  * Configuration examples now support `textOverrides` — a map of Figma TEXT node layer names to replacement text, applied to the main instance so previews show the example's actual text instead of default placeholders
  * New `slotInsertions` parameter populates named SLOT nodes with fresh component instances: specify the slot name, a component node ID, and optional `nestedOverrides` / `textOverrides` on the inserted child
  * All overrides are applied **before** `appendChild` into the slot — after adoption, child nodes get compound IDs and become inaccessible (see slot mutation ordering constraint below)
  * Extraction returns `textNodeMap` — an array of `{ name, characters, parentName }` for every TEXT node in the default variant — eliminating guesswork for `textOverrides` keys

  ### Sub-component token ownership (Color)

  * New **token ownership decision framework** in the color instruction file — evaluate each `subComponentName` entry against four signals (full component vs leaf instance, slot-hosted, parent override) before including or excluding
  * Leaf instances (icon fills, divider strokes) stay in the parent spec; full sub-components (buttons, badges, checkboxes) are excluded and noted in `generalNotes`
  * Worked examples table covers common cases (MicroButton → exclude, Chevron icon → include, Divider → include, IconButton → exclude)
  * Slot-based component guidance: document default slot content tokens, note slot architecture and preferred instances in `generalNotes`, explain extraction behavior with nested booleans

  ### Composition Pattern B (Structure)

  * New **Pattern B — Structural map** for standalone components or components without a size axis (e.g., Section Heading with leading slot + heading area + trailing slot)
  * Uses `Spec | Default | Notes` columns with group rows for the host container and each structural zone — replaces the need for a separate "container" section
  * **Boundary rule**: when any section says "See X spec", only document the hosting container (sizing mode, padding, spacing, alignment) — never re-document the component's own internals
  * Slot container properties (sizing mode, alignment, clipsContent) belong as group rows in the composition section, not repeated in each slotContent section
  * HUG-sized container guidance: document `widthMode: hug` instead of reporting measured pixel dimensions, which are artifacts of current content

  ### Boolean-toggled previews (Structure)

  * New preview type for standalone components with booleans controlling structural elements (slots, accessories, subtext)
  * Shows meaningful boolean combinations as labeled instances (e.g., Default, With subtext, Full)
  * `PROPERTY_OVERRIDES` array drives per-column boolean configurations in the preview script

  ### Section ID-based rendering (Structure)

  * Step 11b now returns the rendered section's node ID (`sectionId`)
  * Step 11c preview script locates the section by ID instead of by name — eliminates name-collision issues when multiple sections share similar names
  * Page context is loaded explicitly via `figma.setCurrentPageAsync` for stable child traversal

  ### Slot-safe tree traversal

  * `loadAllFonts` across API, color, and structure skills now uses a manual recursive collector with per-node try-catch instead of `findAll` — prevents crashes on SLOT nodes with compound IDs
  * Color extraction adds `figma.setCurrentPageAsync` before traversal for stable child resolution
  * `enableNestedBooleans` and `directUnhide` in the color skill wrapped with try-catch guards for slot-hosted instances
  * `implementation.md` documents the **slot mutation ordering constraint**: all mutations on a child instance must happen before `appendChild` into a SLOT, with code examples for both correct and incorrect patterns, plus the default-slot-child replacement workaround

  ### Response truncation guidance (Structure)

  * Added guidance for handling MCP response truncation (>\~20KB): run targeted follow-up extraction for missing fields instead of re-running the full script
</Update>

<Update label="V1.7.0 — April 2026" description="Figma slot detection, nearest-edge marker placement, component-relative spec placement, and improved rendering">
  ## uSpec V1.7.0

  All seven skills now detect and handle native Figma SLOT nodes — preferred instances, boolean visibility bindings, and slot content population. Marker placement uses a new nearest-edge algorithm with collision avoidance, specs are placed next to the source component, and rendering is more resilient with dynamic font loading and font-family fallbacks.

  ### Figma SLOT node support

  * **Anatomy** extraction detects SLOT-type properties, resolves `preferredValues` to local component nodes, reads `componentPropertyReferences.visible` for boolean bindings, and surfaces `slotDefaultChildren` for default content. Step 4 enriches slot notes with preferred component names, marks hidden/empty slots for artwork population, and sets section eligibility for sub-component anatomy sections.
  * **API** extraction collects `slotProps` with preferred instances and `defaultChildren` including contextual overrides. Sub-component table defaults now reflect values the designer set *in the slot context*, not the standalone component's global defaults. Descriptions reference the source component.
  * **Property** extraction detects boolean-to-slot linkage — when a boolean controls a SLOT's visibility, the description reads "Controls slot: {name} (accepts: {preferred})" instead of the generic "Controls layer".
  * **Structure** resolves SLOT properties with `preferredValues` and generates dedicated `slotContent` sections per preferred component, measuring contextual dimensions when each preferred component is placed inside the slot across all parent sizes.
  * **Voice** deep-recurses into SLOT nodes during extraction so interactive elements inside slots appear as separate focus stop entries for merge analysis. Reads `slotVisibility` for conditional focus stop detection across states.

  ### Nearest-edge marker placement with collision avoidance

  * Replaces the previous clockwise / left-stagger / alternating strategy system with a unified **nearest-edge** algorithm across anatomy, per-child, and voice skills
  * For each element, all four sides are scored by distance to the component boundary — the marker is placed on the shortest side
  * Before placing, overlap with already-placed markers is checked (8 px minimum gap); on collision, perpendicular offsets are applied, falling back to the next-best side if bounds are exceeded
  * **Inline markers** for nested elements — elements visually contained inside another annotated element get a short stub line (16 px) on their nearest edge instead of a perimeter marker

  ### Component-relative spec placement

  * Specs are now placed on the **same page as the source component**, positioned to its right with a 200 px gap — no more viewport-center placement
  * The script resolves the component node, walks up to its PAGE ancestor, activates the page, and positions the frame at `compNode.x + compNode.width + 200`
  * Cross-file destination URLs retain the existing viewport-center behavior

  ### Completion link

  * Every skill now prints a clickable Figma deep-link URL to the rendered spec frame at the end of the run
  * URL format: `https://www.figma.com/design/{fileKey}/?node-id={frameId}`

  ### Improved example rendering

  * **Dynamic font loading** (`loadAllFonts`) runs after every mutation that may reveal new text nodes — `createInstance`, `setProperties`, `appendChild` into slots, and `directUnhide` — preventing "unloaded font" errors on components using non-template fonts
  * **Font-family fallback** (`loadFontWithFallback`) discovers exact font style strings via `listAvailableFontsAsync` instead of hardcoding style names, with graceful fallback through preferred → fallback → first-available → Inter
  * Template font loading moved from hardcoded family to discovery from existing marker and section text nodes
  * API configuration example preview now finds SLOT nodes via `findOne(n => n.type === 'SLOT')` instead of assuming `children[0]`

  ### Variant selection evaluation (Anatomy)

  * New Step 4 sub-step 0 evaluates whether the default variant is the best representative — when it yields only 1–2 elements and variant axis option names suggest a structurally richer alternative, the extraction re-runs with `PREFERRED_VARIANT_PROPS`
  * Does not re-extract for purely stylistic differences (color, size, theme)

  ### Brief description header

  * Anatomy and property specs now compose a 1-sentence `briefDescription` (max \~15 words) describing what the component IS and does, placed in the `#brief-component-description` header field
  * Replaces the previous generic "Anatomy breakdown of..." and "Configurable properties of..." text

  ### Root container detection (Anatomy)

  * New `childContainerIsVariant` flag indicates when the extraction traversed past the root container — a synthetic container element is always inserted when traversal occurred
  * When the root container was not traversed, the agent evaluates architectural significance (composable slots, conditional visibility, mixed layout) to decide whether annotation is warranted
  * `hasStrokes` on the root variant no longer triggers a separate synthetic element — strokes are described in the container note instead

  ### Voice rendering improvements

  * Removed `artworkLabels` and the detach-and-replace-text workflow — artwork instances stay live throughout rendering
  * `findStopNode` now uses ancestor-aware visibility matching (`isEffectivelyVisible`) for the Focus Order entry, correctly triggering the richest-variant fallback when boolean-enable alone cannot surface all focus stops
  * Preview wrapper width reads from `previewPlaceholder.width` to match the template layout instead of computing independently
  * Conditional focus stops and disabled/non-focusable states documented in merge analysis guidance
</Update>

<Update label="V1.6.2 — April 2026" description="FRAME-wrapped text detection, frame icon indicators, and effect style consolidation">
  ## uSpec V1.6.2

  Anatomy now detects FRAME-wrapped TEXT nodes and displays a dedicated frame icon indicator, while color consolidates effect style entries into a single token reference.

  ### FRAME-wrapped TEXT detection (Anatomy)

  * Frames containing a single TEXT child are now classified as `text` instead of `container` — the frame name is preserved in `originalName` and the element carries `nodeType: 'TEXT'`
  * Short text content (up to 30 characters) is included in the element notes for richer context in the attribute table
  * Applies to both extraction and the `name` / `originalName` documentation in the instruction file

  ### Frame icon indicator (Anatomy)

  * New `#frame` indicator icon for FRAME and GROUP node types, added alongside the existing `#instance`, `#text`, and `#slot` icons
  * Applied to both composition-level and per-child artwork rendering scripts — FRAME/GROUP elements now display their own icon instead of falling through to the default (no icon) case

  ### Name field semantics (Anatomy)

  * `name` now consistently returns the designer-facing layer name across all classifications
  * For `instance-unwrapped` elements, `name` is the wrapper frame's name (e.g., "Thumb") — the inner component name is available via `wrappedInstance.componentSetName`
  * Previously, unwrapped instances overwrote `name` with the inner component's `componentSetName`, losing the original frame label

  ### Effect style consolidation (Color)

  * When a node has an `effectStyleId`, extraction now emits a single `"effect style"` entry with the style name as the token, instead of iterating individual shadow layers
  * Individual `drop shadow` / `inner shadow` entries are still emitted when no effect style is applied
  * The `variantColorData` contract documents the new `"effect style"` property value and its semantics

  ### Effect and elevation token category (Color)

  * Added `Effect/Elevation` row to the token-naming reference table with common style names (`low`, `medium`, `high`)
  * Added `Effects` row to the element-naming reference table with common layer names (`Shadow`, `Elevation`, `Drop shadow`)
</Update>

<Update label="V1.6.1 — April 2026" description="Improved component anatomy and voice reader annotation">
  ## uSpec V1.6.1

  Anatomy and voice reader artwork rendering are now more robust — both skills use a dedicated wrapper frame for absolute positioning and voice gains dynamic preview sizing with smarter marker placement.

  ### Wrapper frame for artwork (Anatomy)

  * Artwork elements (component instance, outlines, markers, lines) are now placed inside a dedicated inner wrapper frame instead of directly on the preview placeholder
  * The wrapper uses `layoutMode = 'NONE'` with transparent fills and `clipsContent = true`, keeping absolute positioning isolated from the template's auto-layout
  * Applied to both composition-level and per-child artwork scripts

  ### Dynamic preview sizing (Voice)

  * Preview dimensions are now calculated from the live instance's `width`/`height` plus marker margins, replacing the stale `ROOT_SIZE` parameter
  * Eliminates centering drift when variant switching changes the component's rendered size
  * Sizing formula accounts for the number of focus stops so left-stagger markers never run out of room
  * Removed the `ROOT_SIZE` placeholder from the rendering template and instruction file

  ### Marker positioning strategies (Voice)

  * Voice artwork now uses the same three-strategy marker placement as anatomy: **clockwise**, **left stagger**, and **alternating**
  * Strategy is auto-detected by clustering focus stop centers — consistent with anatomy's approach
  * Replaces the previous simple alternating-only placement, producing cleaner annotations for concentric and vertically stacked components

  ### Pre-detach bounding box capture (Voice)

  * Bounding boxes for focus stops are now captured from the live instance before any `detachInstance()` call
  * Avoids fragility of post-detach name matching where SLOT nodes reorganize and `findStopNode` may fail
</Update>

<Update label="V1.6.0 — April 2026" description="Synthetic layer detection, clockwise markers, measurement annotation pause, and two-layer architecture">
  ## uSpec V1.6.0

  Anatomy now handles concentric components (checkbox, radio, toggle) with synthetic element detection and clockwise marker placement. Structure gains icon/component reference rows and temporarily removes measurement annotations until Figma MCP supports them natively. All seven skills follow a two-layer architecture separating orchestration from domain knowledge.

  ### Measurement annotation paused (Structure)

  * **Temporarily removed** measurement annotations (`TOKEN_MAPS`, `annotateNode`, and all native Figma `addMeasurement` calls) from the structure skill
  * The `addMeasurement` API is not yet exposed through Figma MCP — annotations will return once native support is available
  * Table-driven spec rows and token references are unaffected; only the visual measurement lines on preview instances are paused

  ### Synthetic element detection (Anatomy)

  * New `hasVisuals()` utility detects fills, strokes, and effects on any node — used to identify visually meaningful frames that wrapper traversal would otherwise skip
  * `rootVariantVisuals` and `traversedFrames` are now returned by the extraction script, surfacing visual layers (statelayers, backplates, shape containers) that exist on the root variant or intermediate wrapper frames
  * Step 4 inserts **synthetic elements** (`isSynthetic: true`) for skipped visual layers, with re-indexing — concentric components like checkbox now show all structural layers in the anatomy table
  * Instruction file adds note-writing guidelines, worked examples, and validation checklist items for synthetic elements

  ### Clockwise marker placement (Anatomy)

  * Three marker placement strategies based on element center clustering: **clockwise** (concentric/overlapping), **left stagger** (vertical stack), and **alternating** (mixed layouts)
  * Clockwise strategy rotates markers around the component (left → top → right → bottom) — ideal for concentric components where all elements share the same center
  * Both composition and per-child artwork scripts use the same `isClustered` detection and strategy selection

  ### Richest variant fallback (Anatomy)

  * When the default variant produces 0 elements after wrapper traversal (e.g., an unchecked checkbox with an empty structure frame), extraction falls back to the variant with the most descendant children
  * `selectedVariantId` is returned by extraction and reused by the rendering step, ensuring artwork matches the extraction data
  * `resolveChildContainer` refactored into a reusable function shared by the fallback logic

  ### Icon and component references (Structure)

  * INSTANCE children now carry `parentSetName` — the component set name (e.g., `"checkmark"`, `"chevron-down"`) — at all tree depths, not just depth 0
  * New `iconName` / `leadingIcon` / `trailingIcon` spec rows document which component is used, placed before the corresponding size row
  * Instruction file adds a Component References section, decision-table entry, common-mistake warning, and validation checklist item

  ### Two-layer skill architecture

  * **SKILL.md** is now strictly the orchestration layer — step-by-step workflow, MCP adapter mapping, Plugin API scripts, script output contracts, intermediate data structures, and template mechanics
  * **Instruction files** are now strictly the domain knowledge layer — interpretation guidance, decision frameworks, naming conventions, value formatting rules, worked examples, edge cases, and validation checklists
  * Every skill retains its two-tier extraction model: deterministic scripts for data gathering, AI reasoning for interpretation and enrichment

  ### Housekeeping

  * Deleted `data-example.json` — no longer referenced by any skill
  * Updated `api/api-library.md` with improved reference patterns
  * Updated `implementation.md` with variant selection and marker positioning docs
</Update>

<Update label="V1.5.0 — March 2026" description="Composable slot support, blown-out rendering, and artwork label replacement">
  ## uSpec V1.5.0

  All seven skills now handle composable slot components (button groups, tab bars, chip groups) — with new SLOT node traversal, composition-level deduplication, blown-out child rendering, and realistic artwork labels.

  ### Composable slot support across skills

  * New `slot` classification type in the anatomy extraction script — SLOT nodes are detected, traversed, and annotated with a dedicated `#slot` indicator in the table
  * Slot traversal added to all three wrapper-walking paths (extraction, composition artwork, per-child artwork) so components using Figma's composable slot pattern are handled consistently
  * Voice/screen reader extraction recurses into slot containers with identically-named children, assigning `slotIndex` for index-based matching across focus stop resolution

  ### Composition-level deduplication

  * Multiple instances of the same sub-component (e.g., 4 buttons in a button group) are collapsed into a single representative element with an `(xN)` suffix at the composition level
  * Prevents redundant markers, outlines, and table rows — one entry per unique sub-component, with a note explaining the repeated pattern
  * Per-child sections are also deduplicated by `mainComponentSetId` so only one anatomy section is created per unique sub-component

  ### Blown-out child rendering (property skill)

  * New rendering mode creates instances directly from a child's component set instead of modifying nested instances in a parent — immune to sparse variant matrices and nested-instance property access issues
  * Automatic fallback: when `setProperties()` fails on a nested instance, the chapter is re-rendered in blown-out mode
  * Sparse variant matrix detection added to AI validation — identifies missing axis combinations and adds `constrainedBy` metadata for correct base variant selection
  * Coupled axis detection improved with heuristics for semantically coupled axes where option names differ

  ### Artwork label replacement (voice skill)

  * Artwork previews now replace generic "Label" placeholder text with realistic, state-specific labels (e.g., "Day", "Week", "Month", "Year")
  * Labels are passed per-state via `artworkLabels` and applied by detaching the instance and its nested sub-instances before modifying text nodes
  * Focus stop outlines (pink dashed rectangles) added to voice artwork for visual consistency with the anatomy skill

  ### Color token resolution improvements

  * Token resolution now prefers `codeSyntax.WEB` over raw variable names, producing cleaner developer-ready token references
  * Paint style fallback added for fills, strokes, and effects — when no variable binding exists but a Figma paint style is applied, the style name is used as the token
  * Container/slot component detection: when the parent has no direct color entries, extraction re-targets to the sub-component automatically
  * Mode token maps updated to use web code syntax

  ### API child overrides for slot components

  * Configuration examples now support `childOverrides` — per-child property overrides applied to composable slot children by index
  * Item-level properties (e.g., `item 1 isSelected`) can be documented in example tables to reflect the preview state

  ### Figma MCP compatibility (property skill)

  * Added method restriction table and replacement helpers (`findByName`, `findAllText`, font-loading via `tn.fontName`) for `figma-mcp` where `findAll`, `findOne`, and `getRangeAllFontNames` throw `TypeError`
  * Page-loading block updated to use explicit page name lookup instead of parent traversal

  ### User-provided design context

  * Anatomy and property skills now integrate user-provided notes (behavioral descriptions, usage constraints, coupling hints) into semantic notes and validation logic
  * Voice skill documents behavioral states from user context (e.g., single-select vs. multi-select) as separate entries when they produce different semantic properties

  ### Robustness

  * Font loading wrapped in try/catch across all rendering scripts to prevent crashes on mixed-font or empty text nodes
  * Instance-wrapper terminology standardized from "slot-wrapper" to "instance-wrapper" across all skills and instruction files
</Update>

<Update label="V1.4.1 — March 2026" description="Dual MCP support across all documentation">
  ## uSpec V1.4.1

  Documentation now covers both Figma MCP providers — Figma Console MCP (Southleft) and native Figma MCP (Figma) — across the entire docs site.

  ### Dual MCP documentation

  * All references to "Figma Console MCP" replaced with MCP-agnostic phrasing throughout spec pages, diagrams, and prerequisites
  * Architecture overview in How It Works rewritten to show both MCP paths in a single diagram
  * Mermaid diagrams across all 7 spec pages and the How It Works page updated to use generic "Figma MCP" nodes
  * Removed tool-specific labels (`figma_execute`) from diagram nodes — tool names are implementation details

  ### Expanded troubleshooting

  * Figma connection troubleshooting restructured into Console MCP and Native Figma MCP tabs
  * Added native MCP troubleshooting for connection issues, token validation errors, and file/node resolution
  * Updated multiple-agent guidance to cover both MCP models

  ### Pre-verification callout

  * Added a prominent warning between MCP setup and firstrun in Getting Started — test your MCP connection before running firstrun
  * MCP-specific verification instructions with links to each provider's documentation

  ### MCP documentation freshness notices

  * Added notes throughout setup and troubleshooting pages reminding readers that MCP providers update their instructions frequently
  * Direct links to [Figma Console MCP docs](https://docs.figma-console-mcp.southleft.com/) and [native Figma MCP docs](https://github.com/figma/figma-mcp) wherever configuration is discussed

  ### Global navigation

  * Removed the Figma Console MCP anchor from the global nav — with dual MCP support, a single provider link is misleading
</Update>

<Update label="V1.4 — March 2026" description="Updated create-color with consolidated extraction and AI reasoning">
  ## uSpec V1.4

  The `create-color` skill now uses a single consolidated extraction script and a clearer AI interpretation layer — replacing the previous multi-step flow with a faster, more accurate pipeline.

  ### Consolidated extraction script

  * A single `figma_execute` call (Step 4b) replaces the previous multi-step flow (token extraction + separate boolean enrichment + separate axis classification), handling everything in one pass
  * The script walks the component tree, resolves color variable bindings, classifies variant axes by token fingerprint, detects boolean-gated elements, and discovers mode-controlled collections

  ### Sub-component tagging

  * Nested instances are now tagged with their parent component set name, producing richer and more descriptive element labels in the output tables

  ### Nested boolean enablement

  * Live preview instances now show all optional elements (icons, prefix/suffix, clear button, hints) by recursively enabling boolean properties on nested instances, so the artwork matches the documented tokens

  ### Updated AI interpretation layer

  * Step 4c strategy selection logic is clearer — the two-gate model (variant count and token similarity) now has explicit thresholds and reasoning guidance for choosing Strategy A vs Strategy B
</Update>

<Update label="V1.3 — March 2026" description="Improved create-voice skill output and token usage">
  ## uSpec V1.3

  The `create-voice` screen reader skill now produces more detailed, more accurate specs while using fewer tokens — smarter extraction, better artwork fidelity, and automatic state deduplication.

  ### More detailed screen reader output

  * Focus stop discovery uses deep traversal (`findOne`) instead of shallow children lookup — correctly resolves nested elements like a clear button inside an Input child instance
  * Focus Order artwork now maximizes element visibility: boolean properties are force-enabled and the richest state variant is selected automatically, so all documented focus stops appear in the preview even when the default variant hides some of them
  * `booleanDefs` extracted alongside `variantAxes` in the component scan, giving the rendering step full knowledge of toggleable sub-elements

  ### Fewer tokens via state grouping

  * States with identical accessibility semantics (same focus stops, roles, labels, and announcements) are collapsed into a single entry with a combined title — e.g., "Text field Enabled / Pressed / Active" instead of three separate sections
  * Cuts redundant output for components like Text field that have many visual-only state differences but identical screen reader behavior
  * Guidance added to both the skill workflow and the agent instruction file, with a new validation checklist row and common-mistake entry

  ### Housekeeping

  * Added `FONT_FAMILY` placeholder to the rendering template for consistent font resolution across specs
</Update>

<Update label="V1.2 — March 2026" description="Drastically improved create-structure skill">
  ## uSpec V1.2

  Major overhaul of the `create-structure` skill with smarter measurements, template-driven layout, and a clear deterministic/AI split.

  ### Smarter measurement annotations

  * Padding and spacing now use **Figma's native measurement display** instead of custom text labels — cleaner output with no mislabeled annotations
  * Min/max constraints show actual node values (e.g., `min 32`, `max 200`)

  ### Template-driven previews

  * Preview layout is defined by the template; the script no longer overrides direction or spacing
  * Section template hidden by default, eliminating an extra manual step

  ### Clearer agent instructions

  * Removed ambiguous language that caused layout direction changes
  * Updated validation rules for new measurement behavior

  ### Deterministic vs AI split (\~60/40)

  * \~60% deterministic scripts handle extraction, cross-variant comparison, and rendering
  * \~40% AI reasoning handles section planning, design-intent notes, and anomaly detection
  * Output is highly consistent across runs
</Update>

<Update label="V1.1.0 — March 2026" description="Multi-platform support and improved layer detection">
  ## uSpec V1.1.0

  Added support for Claude Code CLI and Codex CLI alongside Cursor, and improved anatomy and property skills for complex components.

  ### Multi-platform support

  * **Claude Code CLI** and **Codex CLI** are now supported as agent hosts alongside Cursor
  * New `firstrun` skill handles environment setup — run `/firstrun` in Claude Code or `$firstrun` in Codex to get started
  * Skills are deployed to the chosen platform on demand, keeping each environment clean
  * `CLAUDE.md` and `AGENTS.md` provide platform-specific project instructions

  ### Improved layer detection

  * **Anatomy** and **Property** skills now handle complex component structures with better layer detection and classification
  * More accurate marker placement for deeply nested or auto-layout-heavy components

  ### Infrastructure

  * `sync-skills.sh` supports `--target` flag for platform-specific skill deployment
  * `uspecs.config.json` now stores the active environment alongside template keys
  * `.gitignore` updated to keep generated skill copies out of version control
</Update>

<Update label="V1 — March 2026" description="Initial open-source release">
  ## uSpec V1

  First public release of uSpec — an agentic system that generates design system documentation directly in Figma, powered by AI agent skills in Cursor.

  ### Spec types

  * **Anatomy**: numbered markers and attribute tables for component structure, with AI-driven element classification, per-child sections, and property-aware unhide
  * **Properties**: variant axes, boolean toggles, variable mode exhibits, and child component chapters with live instance previews
  * **API**: property tables with values, defaults, required status, sub-component tables, and configuration examples
  * **Color Annotation**: design token mapping for fills, strokes, and shadows across states and variants, with automatic strategy selection
  * **Structure**: dimensions, spacing, and padding across density, size, and shape variants with token references
  * **Screen Reader**: VoiceOver (iOS), TalkBack (Android), and ARIA (Web) accessibility specs with focus order and merge analysis
  * **Motion**: animation timeline bars and easing detail tables from After Effects keyframe data, with pre-computed segments and color-coded easing visualization

  ### Infrastructure

  * Agent skills architecture running in Cursor via `.cursor/skills/`
  * Figma Console MCP integration for real-time component data extraction
  * Template library system with one-time `@firstrun` configuration
  * Documentation site at [docs.uspec.design](https://docs.uspec.design)
</Update>
