redongreen/uspec/extract-voice

Claude Code and agent skill by redongreen/uspec

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Interpret a component's screen-reader accessibility spec (focus order, merge analysis, per-state platform tables for VoiceOver/TalkBack/ARIA, slot insertion plans) from the `_base.json` produced by the uSpec Extract Figma plugin, and write the normalized JSON to disk. Read-only interpretation — no Figma calls except an optional tiny delta script.

Install

npx vskill@latest install redongreen/uspec/extract-voice

SKILL.md

Extract Voice / Screen Reader Data

Interpretation-only companion to create-voice. This skill does not extract data from Figma. It reads {cachePath}/{componentSlug}-_base.json (produced by the uSpec Extract Figma plugin), applies the same reasoning layer as create-voice, and writes the finalized VoiceSpecData object to disk for the create-component-md orchestrator.

Quality contract: every reasoning step (visual parts listing, merge analysis, focus-stop counting, state grouping with A11Y_AXES filter, behavioral state detection, slot scenario selection, state-to-variant mapping, platform section population, audit) mirrors create-voice/SKILL.md and its platform reference files.

Batch-mode contract. This skill MUST NOT call AskQuestion, prompt for confirmation, or pause for user input. Behavioral states are inferred from optionalContext and platform defaults; if a state can't be inferred, omit it rather than asking. On missing _base.json sections, abort with a single-line diagnostic. No mid-interpretation clarifications.

Invocation Contract

The orchestrator calls this skill with these inputs (already resolved — do NOT re-parse URLs or re-read uspecs.config.json):

  • componentSlug — filename-safe slug
  • cachePath — cache directory, typically .uspec-cache/{componentSlug}/
  • optionalContext — free-form user context. Especially important for voice specs — behavioral states ("single-select vs multi-select", "collapsed vs expanded", "validation error") are typically only discoverable from user context.
  • mcpProvider — figma-console or figma-mcp (only used if a Step 3-delta escape hatch fires)
  • deltaAvailable — boolean derived from _base.json._meta.fileKey + nodeId. Plugin exports normally make this true; a separately-passed figmaLink is not required.
  • apiDictionaryPath — absolute or workspace-relative path to {cachePath}/{componentSlug}-api-dictionary.json. Optional. When present, the file is the canonical vocabulary for axis/value/sub-component/state naming (see Step 2.5). When absent, the skill continues with _dictionaryUnavailable: true in its output envelope.
  • evidencePath — optional. Path to {cachePath}/{componentSlug}-evidence-voice.json from CLI prepare. When present and hash-valid, use data as the Step 3 working evidence set.

fileKey and nodeId are not pass-through parameters anymore. Read them from {cachePath}/{componentSlug}-_base.json._meta.fileKey and _meta.nodeId at the start of Step 1.

Output:

  • Writes {cachePath}/{componentSlug}-voice.json with a { _meta, data } envelope. data follows the VoiceSpecData shape (componentName, guidelines, optional focusOrder, states[]).
  • Returns a single-line summary: "Voice extracted: N focus stops, M states, platforms=[VoiceOver, TalkBack, ARIA] → {path}".
  • Never creates or mutates Figma nodes.

MCP Adapter

Typically zero MCP calls — this skill reads _base.json from disk. The adapter applies only to the optional Step 3-delta escape hatch.

Operationfigma-consolefigma-mcp
Execute Plugin JS (delta only)figma_execute with codeuse_figma with fileKey, code, description

For figma-mcp delta scripts, include the page-focus preamble after getNodeByIdAsync:

javascript
let _p = node; while (_p.parent && _p.parent.type !== 'DOCUMENT') _p = _p.parent;
if (_p.type === 'PAGE') await figma.setCurrentPageAsync(_p);

Workflow

Task Progress:
- [ ] Step 1: Read instruction and platform reference files
- [ ] Step 2: Load _base.json and optionalContext
- [ ] Step 2.5: Load API dictionary (canonical vocabulary) — optional
- [ ] Step 3: Build working evidence set (elements, slotDefs, slotVisibility from _base.json)
- [ ] Step 3-delta: OPTIONAL — read-only Figma call if a fact is genuinely missing
- [ ] Step 4: Visual parts, merge analysis, focus stops (+ retain layerName per stop), states, slot scenarios
- [ ] Step 5: Generate VoiceSpecData (guidelines, focusOrder, states with 3 platform sections)
- [ ] Step 6: Audit (re-read instruction file)
- [ ] Step 7: Write JSON to cache and return one-line summary
Step 1: Read References

Read these files before generating output:

These are the same references used by create-voice. They are the single source of truth for the VoiceSpecData schema, merge analysis, state grouping, announcement patterns, and the Validation Checklist.

Rendering-only sections to skip

The shared instruction file describes both extraction and Figma rendering. This skill only performs interpretation — ignore guidance below. The data schema and audit checklists still apply.

  • §Analysis Process — "The rendering script uses visibility-aware focus stop resolution for the Focus Order artwork…" — rendering path. The preceding guidance about flagging conditional focus stops still applies.
  • §Validation Checklist — the entire "After Rendering in Figma" sub-section — rendering-only. Replace in-mind with the extraction-side audit in Step 6.
  • §Validation Checklist — the "Before Rendering in Figma" sub-section — DO still apply.
  • §Examples — narrative references to rendered output — example data shapes still apply; rendered-table narration is irrelevant.

Note: Fields that look like rendering config but are part of the output schema (e.g., slotInsertions, focusOrder.tables, variantProps, per-state sections) must still be populated.

Step 2: Load _base.json

Read {cachePath}/{componentSlug}-_base.json. If missing or required sections are null, abort with a diagnostic asking the user to re-run the uSpec Extract plugin.

Top-level keys this skill consumes:

  • component — for componentName and compSetNodeId
  • variantAxes — for A11Y_AXES filtering and state-to-variant mapping
  • defaultVariant — for default variant properties
  • propertyDefinitions.booleans — for boolean defaults
  • propertyDefinitions.slots — for slotDefs including defaultChildren, preferredInstances
  • variants[*].treeFlat — primary evidence source for voice. Preserve variant identity while comparing ordered focus candidates.
  • variants[*].treeHierarchical — supporting evidence for each corresponding variant.
  • ownershipHints[] where evidenceType === "textNode" — text-node hints useful for announcement authoring.
  • _extractionNotes.warnings

Also absorb optionalContext as authoritative (voice especially depends on user-described behavioral states).

Step 2.5: Load API dictionary (canonical vocabulary)

The create-component-md orchestrator writes {cachePath}/{componentSlug}-api-dictionary.json alongside _base.json after extract-api finishes. When present, this file is the canonical vocabulary for axis names, value names, sub-component names, and state runtime conditions. See the `ApiDictionary` artifact section in api/agent-api-instruction.md for the schema.

Resolution order:

  1. If the orchestrator passed apiDictionaryPath, read that file.
  2. Otherwise look for {cachePath}/{componentSlug}-api-dictionary.json on disk.
  3. If neither resolves (e.g., the skill is being run standalone), continue with existing behavior but set data._dictionaryUnavailable = true on the output envelope.

How this skill uses the dictionary (keep it in scope through Steps 3–5):

  • State names. When emitting states[].state, prefer the dictionary's canonical axis value names. When the dictionary is decomposed (a states[] entry exists with runtimeCondition), use the runtime condition as the state name — e.g., "focused" rather than "active", "validationState='error'" rather than "error". This keeps the voice spec aligned with the engineer-facing condition an implementer can check at runtime.
  • Behavioral state cross-check. Link each runtime substate to its parent API assignment when one exists. For example, disclosure (expanded) and disclosure (collapsed) both reference the canonical type=disclosure value plus runtime expanded=true|false; they are not dictionary extras merely because expanded is behavioral.
  • Slot / sub-component names inside focus stops — prefer dictionary.subComponents[].name over raw Figma layer names.

Mismatch protocol — do NOT silently rename, do NOT silently keep.

When your evidence (the focus walk, state grouping, or user-described behavioral states) contradicts the dictionary — for example, the dictionary lists a state value you cannot derive focus behavior for, or you documented a state value the dictionary did not list — emit the observed value AND attach a _dictionaryMismatch annotation:

json
{
"observed": "<what you measured / observed>",
"dictionary": "<what the dictionary named; null when the dictionary listed a value you couldn't find>",
"kind": "value-missing" | "value-extra" | "name-drift",
"note": "<short rationale; ≤160 chars>"
}

`value-extra` guard — only vocabulary-controlled fields can mismatch. Resolve API-facing states and component identities against axes[], booleanProps[], states[], subComponents[], referencedComponents[], and slots[]. Announcements, roles, focus grouping, and runtime substates linked to a canonical parent API assignment are specialist semantics, not dictionary extras. Emit value-extra only for an API-facing name/value that resolves nowhere.

Aggregate every mismatch into data._extractionArtifacts.dictionaryMismatches[]. The orchestrator's Step 8.5 reconciliation pass consumes this list.

Retry semantics — the orchestrator may re-dispatch this skill.

When optionalContext begins with the literal prefix create-component-md retry: , the rest of the string is an authoritative scope expansion from the orchestrator's Step 8.5 reconciliation step. Parse it as a comma-separated list of state values / sub-components the dictionary exposed but this skill previously did not cover. The retry run MUST emit evidence for every listed item — either a real states[] entry citing variant/behavioral evidence, or an explicit _dictionaryMismatch entry explaining why no evidence could be gathered. Never silently drop a listed item.

Step 3: Build Working Evidence Set

Evidence fast path (preferred). When evidencePath is provided, read it first. If the file exists, parses as JSON, has _meta.domain === "voice", and _meta.baseSourceHash matches {cachePath}/{componentSlug}-prepare-manifest.json, treat data as the Step 3 evidence set and proceed to Step 4 without rebuilding from raw treeFlat[].

Populate the voice evidence structure by reading only from _base.json when the fast path is unavailable. Key mappings:

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
249
Repository forks
29
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/redongreen/uspec/extract-voice/badge)](https://verified-skill.com/skills/redongreen/uspec/extract-voice)

Something wrong with this skill or its page? Tell us.