Skip to content

Releases: DirectedEdges/spectacular

@directededges/specs-schema v0.39.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 29 Oct 17:47

Breaking

  • Settings.spec.format — defaults to YAML, previously JSON (ADR-112)
  • Settings.spec.keys — defaults to CAMEL, previously SAFE (ADR-112)
  • Settings.spec.color — defaults to HEXA, previously HEX (ADR-112)
  • Settings.curation.preserveManualSelections — defaults to true, previously false (ADR-112)
  • Settings.spec.collapsePrimitiveWrapper — defaults to true, previously false (ADR-112)

Added

  • Conventions.storybook — typed as StorybookConventions, an open concern-keyed map of feature settings loaded from conventions/storybook.yaml; also on ResolvedConventions
  • Settings.curation — which components of a library a run specs, defaulting to today's behaviour
  • Settings.curation.defaultSelection — READY_FOR_DEV or ALL; defaults to READY_FOR_DEV
  • Settings.curation.preserveManualSelections — hand edits outrank a changed Figma status; defaults to false
  • Settings.curation.includeDependencies — select what a component is built from; defaults to true
  • SpecsConventions.slots.default.match — naming patterns identifying a component's designated default slot, authored in conventions/specs.yaml. A spec convention, not a platform one: what it names is a SlotProp the spec declares, so every platform reads the same answer (ADR-099)
  • MetadataConventions.specs — the spec conventions a run was performed under, recorded beside the one platform entry. Required by a reader that cannot re-derive one from the spec it holds: a render resolving a nested instance's default slot does not hold that instance's own component spec (ADR-099)
  • SlotProp.defaultSlot — durable marker set at generation time when a slot prop matched specs.slots.default.match, read by consumers with no dependency on Conventions (ADR-099)
  • PrimitiveEntry.match — layer-name prefixes selecting a promotion entry, ahead of style scoring; longest prefix wins (ADR-100)
  • PrimitiveSlotContent — reserved anyOf values naming a primitive a slot accepts: $text and $glyph (ADR-102)
  • SlotProp.anyOf — carries PrimitiveSlotContent markers alongside component names, and only where the slot already names a component. Type and absence semantics unchanged (ADR-102)
  • Element.contentStyles — typed as ContentStyles; how primitive content filling an element is formatted, recorded and layered per variant exactly as styles is (ADR-102)
  • ContentStyles, TextContentStyles, GlyphContentStyles — a $text/$glyph map over two closed property sets: text takes colour, typography, alignment, overflow and line clamp; a glyph takes fill colour, width and height (ADR-102)
  • PlatformConventions.slotPrimitives — the library's slots carry the primitives they accept in their default content; defaults to true, and required on ResolvedPlatformConventions (ADR-102)
  • ObjectProp — a prop whose value is an object of named scalar members (ADR-111)
  • PropConfigurationValue — accepts a member-keyed ObjectPropValue under an object-prop key (ADR-111)
  • InstanceExample.propConfigurations — accepts ObjectPropValue for object props (ADR-111)
  • platforms.<platform>.objectProps — opt-in folding of separator-named flat props into object props (ADR-111)

Changed

  • $extensions['com.figma'].name — documented rule corrected on props, anatomy elements and platforms.<platform>.naming. The field was described as absent under naming: NONE; NONE declares no source convention, which means nothing can be re-derived from a key, not that no name is kept. The field is recorded wherever formatting changed the name (ADR-066). Description only — no type or validation change

Migration

  • Settings.spec.format, Settings.spec.keys, Settings.spec.color, Settings.curation.preserveManualSelections, Settings.spec.collapsePrimitiveWrapper: a workspace that sets the member explicitly is unaffected. One that left it unset now resolves to the new value — set it explicitly to keep the former output.
  • Settings.spec.keys carries the largest cost: a spec regenerated with CAMEL renames every anatomy key, prop key and reference to one, and every name derived from a key. Treat it as a migration, or set keys: SAFE.

ADRs

Accepted

  • ADR-111 — Object-Typed Props
  • ADR-112 — Settings defaults adopt their scaffolded values

@directededges/specs-cli v0.36.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 29 Oct 18:56

Breaking

  • A workspace that leaves a setting unset now resolves it to a new value for spec.format, spec.keys, spec.color, curation.preserveManualSelections and spec.collapsePrimitiveWrapper. Every workspace specs init scaffolded already writes four of the five, so only a hand-written settings.yaml that omitted them sees a change (ADR-112)

Added

  • Declaring objectProps in your figma conventions folds separator-named properties into one prop with named members — Margin.compact and Margin.expanded become a single margin (ADR-111). specs init scaffolds the block commented out. Dependency and prop analysis, visual manifests, version grading and generated CSS all read members rather than skipping them

  • A slot whose default content holds a text layer or a glyph now says so (ADR-102). The slotPrimitives figma convention is on unless you turn it off: $text/$glyph markers join the slot's anyOf wherever it already names a component, and the formatting that primitive content takes is recorded on the slot element. Set slotPrimitives: false in config/conventions/figma.yaml to stop; specs init scaffolds that off-switch commented out

    • The generated stylesheets carry that formatting, in both the React and custom-element sheets. Every rule is an ordinary declaration, never !important — it styles a slot's unstyled content, so anything you write for the content you pass in wins by ordinary cascade
    • On a slot that accepts a component as well as a primitive, only the inheriting properties are emitted — colour and typography. A glyph's fill and dimensions are withheld there, because nothing in the emitted markup distinguishes a component's own root from a primitive fill, and a rule strong enough to reach one would reshape the other. A mixed slot is the one case where the scaffolds still inline the formatting, because these withheld rules are the only ones that could have carried it

Changed

  • specs init writes every setting with a comment saying what that setting decides, rather than a comment describing the value you would get by changing it. Three settings are scaffolded on while the schema defaults them off, and the file says which three and why

Fixed

  • An invalid spec.collapsePrimitiveWrapper now warns and falls back to the default instead of silently turning the setting off

  • specs analyze styling lists tokens alphabetically in every set of the by-token report — variables, color styles, text styles and effect styles — instead of in the order the catalogue happened to reach them

  • specs analyze styling now reads the token references a name-shaped spec.tokens emits. Under TOKEN_NAME and FIGMA_NAME a reference serializes to the token's name alone, which the analysis skipped — so every styling report came out empty while the run reported success. Names are now matched against the fetched variables and styles, so these two profiles report what TOKEN reports

  • specs analyze styling says so when spec.tokens is a profile it cannot fully read. CUSTOM and the three FIGMA_SYNTAX_* profiles serialize references into shapes the analysis cannot recognise without reproducing the generator, and FIGMA_SYNTAX_* falls back to TOKEN for tokens with no code syntax — so the reports were quietly partial rather than obviously empty. A warning now names the setting and what it costs. A name-shaped profile with no fetched data files warns too, and points at specs fetch

Dependency updates

  • Your specs now record the formatting a slot's primitive content takes. Via @directededges/specs-from-figma 0.38.0, a slot whose default content holds a text layer or a glyph carries that formatting on the slot element and marks the primitive kinds it accepts — which is what the generated stylesheets in this release read. A slot whose only content is primitives names no accepted types at all, because listing them would declare a restriction your design never stated

  • A prop whose Figma name was changed by key formatting keeps a record of the original spelling. Via @directededges/specs-from-figma 0.38.0, that record is now written under naming: NONE as well, so a name is recoverable wherever formatting altered it. This matters more in this release than it used to: a separator-named property folded into an object prop puts a dot in the name, which no formatted key can reverse

  • A default slot is only marked on a slot that children actually go into. Via @directededges/specs-from-figma 0.38.0, a well-named prop bound to a text, instance, glyph or vector element is refused as the default slot, and the run warns with the prop name and the rule

  • The types behind all of it. Via @directededges/specs-schema 0.39.0: ObjectProp and its member-keyed values (ADR-111), ContentStyles for a slot's primitive formatting (ADR-102), and the five settings whose defaults changed (ADR-112)

@directededges/specs-schema v0.38.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 21 Oct 20:19

Breaking

  • SpecApiDocument, SpecVariantsDocument, SpecExamplesDocument, SpecConcernDocument renamed to ComponentApiDocument, ComponentVariantsDocument, ComponentExamplesDocument, ComponentConcernDocument (ADR-110)
  • SpecApiSubcomponent, SpecVariantsSubcomponent, SpecExamplesSubcomponent renamed to ComponentApiSubcomponent, ComponentVariantsSubcomponent, ComponentExamplesSubcomponent (ADR-110)
  • schema/concern.schema.json renamed to schema/component-concern.schema.json; the ./schema/concern package export becomes ./schema/component-concern (ADR-110)

Added

  • CompositionApiDocument, CompositionVariantsDocument, CompositionExamplesDocument — type a composition's splitConcerns files, each exact to what it carries (ADR-109)
  • CompositionConcernDocument unions the three composition concern documents, reachable from root.schema.json (ADR-109)
  • Composition.images and CompositionExamplesDocument.images register image data referenced by a composition's elements, matching Component.images (ADR-109 amendment)

Migration

  • SpecApiDocument → ComponentApiDocument, SpecVariantsDocument → ComponentVariantsDocument, SpecExamplesDocument → ComponentExamplesDocument, SpecConcernDocument → ComponentConcernDocument: update imports to the new names — no shape change.
  • SpecApiSubcomponent → ComponentApiSubcomponent, SpecVariantsSubcomponent → ComponentVariantsSubcomponent, SpecExamplesSubcomponent → ComponentExamplesSubcomponent: update imports to the new names — no shape change.
  • ./schema/concern → ./schema/component-concern: update any package export subpath resolution or direct reference to schema/concern.schema.json.

ADRs

Accepted

  • ADR-109 — Composition Concern Documents
  • ADR-110 — Rename Spec*Document to Component*Document

@directededges/specs-cli v0.35.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 21 Oct 20:48

Fixed

  • A composition's split-concern files now carry only what a composition has. api.yaml drops the meaningless props key, variants.yaml holds elements/layout instead of default/variants, and examples.yaml uses slotContent (ADR-109)

Dependency updates

  • A composition's generated output is correct end to end now. Via @directededges/specs-from-figma 0.37.0, the engine itself emits a composition's flat shape — no props, no default — matching this release's file-writer fix, so neither layer reintroduces the old component-shaped output
  • Composition contract types got names and fields to match. Via @directededges/specs-schema 0.38.0: new CompositionApiDocument/CompositionVariantsDocument/CompositionExamplesDocument types; the component-side equivalents renamed from Spec*Document to Component*Document

@directededges/specs-schema v0.37.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 20 Oct 17:31

The schema's home is now the DirectedEdges/spectacular repository. The repo that was DirectedEdges/specs was renamed alongside the plugin's rebrand to Spectacular. Nothing in the types or the JSON Schema changes — this release updates the package's repository link so npm points at the right home, and every old link keeps resolving through GitHub's rename redirect.

Changed

  • The package's repository link points at DirectedEdges/spectacular, the renamed home of the schema. Old DirectedEdges/specs links keep resolving via GitHub's redirect

@directededges/specs-schema v0.36.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 20 Oct 11:50

An annotation survives a collapsed layer knowing which layer it came from. When a wrapper is folded into the element it wraps, a role annotated on the wrapper used to be indistinguishable from one annotated on the element itself — so writing the spec back to Figma could put it on the wrong layer. A spec now records the two separately, and a round trip returns each annotation to the layer that carried it. Generated code is unaffected: it still reads only the element's own role.

Added

  • FigmaAnatomyElementExtension.childRole records a role annotated on the layer wrapper collapse folded into an element, so role keeps meaning the element itself was annotated and a round trip returns each annotation to its own layer. Only role reaches emitted code (ADR-104)

@directededges/specs-cli v0.34.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 20 Oct 17:42

The CLI's documentation and repository links follow the repo's rename to DirectedEdges/spectacular. No command behaves differently — this release repoints the README that npm renders and the package's repository link at the renamed home, and picks up the companion releases of the schema and the Figma transform. Every old DirectedEdges/specs link keeps resolving through GitHub's rename redirect.

Changed

  • The README npm renders and the package's repository link point at DirectedEdges/spectacular, the renamed home of the CLI and schema. Old links keep resolving via GitHub's redirect

Dependency updates

  • Specs now name their schema's renamed home. Via @directededges/specs-from-figma 0.36.0, every spec the CLI generates points its $schema URL at DirectedEdges/spectacular; specs you already generated keep validating through GitHub's redirect
  • @directededges/specs-schema 0.37.0 carries the same rename in its package metadata — no change to the types or the JSON Schema

@directededges/specs-cli v0.33.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 20 Oct 11:50

Specs is now Spectacular, and the documentation lives at spectacular.systems. Figma shipped a feature of its own called Specs, so the product takes a new name — but nothing you type changes. The command is still specs, and every package keeps its name on npm.

Editing a convention regenerates your specs, not just what was built from them. A convention change used to re-run the analysis and both platform trees against specs written under the old convention, producing a pass that looked clean and emitted from stale input. Declaring a glyphs convention no longer needs a manual specs generate to take effect. Alongside that, a chain now names the steps your workspace has nothing for and why, so three skipped steps of six read as a workspace that has not got there yet rather than a broken run.

Changed

  • The product is Spectacular; the command is still specs. Printed output and scaffolded config comments say Spectacular, and every documentation link now points at spectacular.systems. The old specsplugin.com links redirect, so nothing you have saved breaks. Package names are unchanged — @directededges/specs-cli, @directededges/specs-schema and the rest keep their names permanently, because npm has no rename

  • The bridge names the Figma plugin by role rather than by brand. "Enable the CLI Bridge in the Figma plugin to connect" reads the same whether the plugin is listed as Specs 2 or Spectacular, so the guidance stays correct while the Figma Community listing catches up

  • specs init and specs storybook init print the chain the docs teach, ending at specs run rather than at specs generate, and no longer offering a way of starting Storybook that the setup flow forbids.

  • The role-adoption skills say which page answers which question, so a first sweep reads the two that carry the judgment and fetches precedence only when a role, a states classification and an action land on the same element. The apply step now names conceptsInertInUse as the way to tell a role that could not emit from one that failed to land, and the proposal step's parts checklist covers the slider, progressbar and live-region families.

Fixed

  • Editing a convention now regenerates your specs, not just the reports and the code built from them. scan and generate did not watch config/, so a convention change re-ran the analysis and both platform trees against specs written under the old convention — a pass that looked clean and emitted from stale input. Declaring a glyphs convention needed a manual specs generate to take effect; it no longer does. A convention edit re-derives the manifest from Figma's dev status, the same as new data arriving, so settings.curation.preserveManualSelections applies to it too.

  • specs run and specs build name the steps your workspace has nothing for, and why, so a chain with three of its six steps reads as a workspace that has not got there yet rather than as a broken run: not in this workspace: storybook (no Storybook host scaffolded).

  • analyze keys records in keys.yaml whether it measured anything. Without a naming convention there is nothing to measure names against, so every name passes and zero divergence means "not checked" — indistinguishable in the file from a library that round-trips perfectly. measured and namingConvention now say which, where a reader opening the committed file will see them.

  • specs generate no longer warns that it overwrote files. Overwriting is what it does on every run after the first, and warning about the expected case taught readers to skim the warnings that matter.

@directededges/specs-schema v0.35.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 14 Oct 13:35

A library declares the slot its nested layouts fill through. SpecsConventions.slots.default.match names it, SlotProp.defaultSlot marks the prop that matched, and MetadataConventions.specs records the conventions a run used — so a reader holding only a spec can resolve a nested instance's default slot (ADR-099).

Conventions and settings grow two open surfaces. Conventions.storybook is a concern-keyed map a new Storybook concern can join without a schema change, and Settings.curation states which components of a library a run specs (ADR-093, ADR-098).

Glyph membership can be declared by structure rather than by name. PlatformConventions.glyphs.structure derives it from child shapes and fill, which makes glyphs.match optional (ADR-103).

Added

  • Conventions.storybook carries a workspace's Storybook settings, typed as StorybookConventions — an open concern-keyed map loaded from conventions/storybook.yaml, also on ResolvedConventions. Adding a concern needs no change to the type or its schema (ADR-098)
  • Settings.curation states which components of a library a run specs, with defaultSelection (READY_FOR_DEV or ALL), preserveManualSelections for whether hand edits outrank a changed Figma status, and includeDependencies. Every default matches today's behaviour (ADR-093)
  • SpecsConventions.slots.default.match names the patterns identifying a component's designated default slot, authored in conventions/specs.yaml. It is a spec convention, not a platform one — what it names is a SlotProp the spec declares, so every platform reads the same answer (ADR-099)
  • MetadataConventions.specs records the spec conventions a run was performed under, beside the one platform entry, for the reader that cannot re-derive them: a render resolving a nested instance's default slot does not hold that instance's own component spec (ADR-099)
  • SlotProp.defaultSlot marks a slot prop that matched specs.slots.default.match, set at generation time and read by consumers with no dependency on Conventions (ADR-099)
  • PrimitiveEntry.match selects a promotion entry by layer-name prefix, ahead of style scoring; the longest prefix wins (ADR-100)
  • PlatformConventions.glyphs.structure derives glyph membership from child structure and fill, typed as GlyphStructure, naming the glyph from the main component's name (ADR-103)

Changed

  • PlatformConventions.glyphs.match becomes optional, and a declared glyphs block now requires at least one of match or structure (ADR-103)

Migration

  • glyphs.match → glyphs.match or glyphs.structure: existing declarations stay valid; code reading glyphs.match must handle its absence when only structure is declared

ADRs

Accepted

  • ADR-093 — Curation is a settings concern
  • ADR-094 — Subcomponent Pattern Matching Rules
  • ADR-095 — Compositions Are Curated Like Components, From a Smaller Eligible Set
  • ADR-096 — The specs/ Directory Names What Kind of Thing Each Folder Is
  • ADR-097 — A Composition Emits One Story in Its Own Nav Group, and Only Under Pro
  • ADR-098 — Storybook Conventions — config/conventions/storybook.yaml
  • ADR-099 — slots.default.match — Naming the Default Slot, and Flattened Instance Nesting
  • ADR-100 — PrimitiveEntry.match — Promoting a Layer by Its Name, Short-Circuiting Style Scoring
  • ADR-101 — The Workspace Stage Graph
  • ADR-103 — Structural glyph membership — glyphs.structure convention

@directededges/specs-cli v0.32.0

Choose a tag to compare

@nathanacurtis nathanacurtis released this 14 Oct 14:02

A workspace is now a documented, tested library, and screens are first-class in it. Three themes:

  • The CLI specs compositions — the frames your library marks ready for dev — so a screen or a pattern becomes a spec and working code the same way a component does.
  • specs storybook scaffolds and publishes a workspace Storybook, with generated pages for your foundations, components, analyses and visual test results.
  • specs testing visual measures your emitted code against your designs, and against the renders you last accepted.

Breaking

  • specs/ now names what each folder holds: components/, compositions/ and analysis/. A directory written before this release is read as legacy and says so once per run; re-run specs generate to write the current layout. Nothing migrates out of _analysis/ (ADR-096).

  • --combine-as-library and --combine-concerns collapse a catalogue per kind, writing components/ and compositions/ each their own set of documents, so a composition and a component of the same name can no longer overwrite each other.

  • -o names a directory, and a path ending in .yaml, .yml or .json is refused unless both splits are off. A split run writes a folder per component, so a filename was never what you meant — it used to be honoured literally.

  • specs scan matches subcomponent patterns exactly, every character outside {C} and {S} included, spaces and slashes among them. A library spelling a separator two ways now declares a pattern for each (ADR-094).

  • specs fetch writes each file payload as a page-split <alias>.file/ directory — root.json plus one JSON per Figma page — so a file of any size flows through the pipeline. Existing single-file payloads still read; only scripts opening <alias>.file.json directly need changing.

Added

Compositions

  • specs scan lists compositions in a third manifest section, curated exactly as components are. A frame earns a row by being marked ready for dev in Figma, and inside another marked frame the outermost wins, so one arrangement is never specced twice (ADR-095).

  • specs generate writes checked composition specs to specs/compositions/<key>/, carrying metadata.source.nodeType: FRAME as the marker for what the spec describes. -c narrows to one by name, id or key, as it does for a component.

  • specs react and specs webcomponents emit a composition as one story in a Compositions nav group, at <tree>/src/compositions/<Name>/, so screens browse separately from the component list. Compositions are Pro; the free tier skips them with a note (ADR-097).

  • --compositions and --no-compositions scope a run to one kind, on specs generate, specs react and specs webcomponents, so iterating on component output no longer pays for the slowest specs in the catalogue. A scoped run never prunes the kind it excluded.

  • Compositions reach specs analyze and specs version. dependencies and styling read them, so which components a screen is built from shows in the blast radius; props and keys stay component-only. Every change to a composition is a patch, because it declares no contract.

Storybook

  • specs storybook scaffolds and publishes a workspace Storybook. init writes the host once and prints the one install you run yourself; a bare specs storybook rewrites the generated content per concern — overview, foundations, components, analysis, versions. The CLI ships no browser.

  • specs storybook dev is the one process a designer runs. It publishes, re-emits each platform as specs change, serves Storybook, republishes when config or assets move, and recovers an index poisoned by a half-saved story file. One Ctrl-C stops it all.

  • Generated pages cover your foundations, components, analyses and visual test results. Colour and typography read your library's own variables and styles, each component gets one entry with React · Web Components · Specs tabs, and a section appears only once its data exists.

  • Your pages win. Copy any generated page to the same path under storybook/content-overrides/ and it is used instead, live and in both directions. No command ever writes there, and publish reports which overrides are in effect.

  • A workspace can declare the port its Storybook serves on, as host.port in conventions/storybook.yaml, so each workspace keeps a localhost you can bookmark. A --port flag outranks it, then the scaffolded npm script, then 6006 (ADR-098).

  • conventions/storybook.yaml declares how a page presents. modes.collections turns each variable collection into a toolbar dropdown, color.collections narrows and orders which collections render, and color.rowGroup and color.groupLeaves decide what shares a row. An unknown concern or wrong value shape warns by name (ADR-098).

Visual testing

  • specs testing visual measures your emitted Storybook against two baselines. Fidelity mode diffs each variant against a Figma export of the same node; regression mode diffs against the renders you last accepted. A composition is diffed as one full-page pair and reported as advisory, never deciding the run's exit status.

  • Each stage is its own subcommand, and each platform is measured separately. manifest and status need neither browser nor network, baseline captures Figma exports and only ever runs when named, shoot screenshots, diff re-scores in seconds, and accept promotes reviewed renders. --target <react|webcomponents> selects the platform and keys every artifact.

  • specs testing visual init scaffolds the browser dependencies you install, and seeds visual-ignore.yaml. Playwright, pixelmatch and pngjs are declared in testing/visual/package.json for you to install. The ignore file is seeded only when absent, and --force never touches it, because every line in it is a decision.

  • specs testing visual baseline scopes itself to what changed. Each capture records a fingerprint of the Figma node it photographed, so status reports each baseline as current, changed or missing, and a recapture after a refetch covers only the designs that moved.

The workspace chain

  • specs build and specs run perform your whole workspace in order — data, manifest, specs, each platform's code, then Storybook. build runs the chain once and exits non-zero at the first failure; run runs it once and then watches, redoing only what a change affects. Experimental (ADR-101).

  • --render adds rendering back into Figma as the last step of either command. Off by default, because it is the only step that writes somewhere other than disk and it needs a running bridge. specs run --render overwrites the existing same-titled page; specs build --render treats a title collision as an error.

  • Having nowhere to render to is reported and skipped, not treated as a failure. No bridge running, no Figma file connected, or several with nothing naming one — each says so in a line and the chain carries on. Both commands take --file <fileKey> rather than prompting.

Conventions and settings

  • conventions/specs.yaml can name your library's default slot, and a nested hierarchy then reads as one tree. Declare slots.default.match and content you place in a nested instance's default slot is captured as that instance's children, in the spec's own anatomy, instead of a $slotContent reference. A non-default slot is unchanged (ADR-099).

  • Glyphs are detected by structure, not only by name. The glyphs convention gains a structure form — child node shapes plus an optional shared fill — so a library whose icons are plainly named gets glyph detection without renames. A property-bearing component is never structurally claimed (ADR-103).

  • settings.curation decides which components a scan selects, with defaultSelection, preserveManualSelections for whether your manifest edits outrank a changed Figma dev status, and includeDependencies. --include-all and --keep-checks override the first two for one run; every default matches previous behaviour (ADR-093).

  • match in conventions/figma.primitives.yaml names the layers that promote to a component, for a layout family whose members share one set of styles and so cannot be told apart by them. An entry declaring none is chosen by its styles, as before (ADR-100).

  • settings.yaml rejects what the schema does not declare, out loud. An unknown top-level key warns by name and is ignored; an invalid enum value warns with the valid list and uses the default. Nothing is silently transformed on a governed surface.

Analysis

  • specs analyze has a command reference, and runs every analyzer when you name none. The reference covers its arguments, options and exit codes, including an unknown analyzer name as the warning that skips rather than a failure.

  • The props analysis flags a name that means two things. typeDiscordance names which components hold which type for a prop they disagree on, and enumDiscordance now also reports a name some components close with an enum while others leave open, marked openAndClosed.

Roles

  • specs analyze roles reports which anatomy elements declare a role and which are bare, with the concepts your library uses, the ones it has never reached for, and the concepts in use that nothing emits for yet. An unrecognized value is reported rather than refused, because a role is an open string and a near-miss is almost always a typo.

  • specs skills install ships two skills that carry role adoption across a library. One proposes a role for every unannotated element as a table you mark up; the other adds the approved ones to your Figma file a page at a time, then regenerates so you can see what landed. Nothing reaches Figma before you have checked the table.

  • **The bridge reads a component's structure a...

Read more