[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H43T0K9PXASNKA02QKJD7J":3,"skill-same:01M6H43T0K9PXASNKA02QKJD7J":93},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":64,"commitSha":65,"skillDirectory":66,"forksCount":67,"repositoryHtmlUrl":68,"repositoryHomepageUrl":6,"ownerHtmlUrl":69,"ownerBlogUrl":70,"ownerDescription":71,"updatedAt":72,"install":73,"resources":86},"01M6H43T0K9PXASNKA02QKJD7J","dx-figma-verify",null,"Compare a generated prototype with the Figma reference screenshot in a browser, fix gaps, write a report. Use after \u002Fdx-figma-prototype. Not for components on AEM (aem-fe-verify) or pre-PR checks (dx-step-verify).","easingthemes\u002Fdx-aem-flow","easingthemes","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F2750284?v=4","01M6H3XYGJY8QCX9ES36P2WF4H","Dragan Filipović","01M6H3XYMN1XVSGKN7N79SW3RH",7,"MIT","https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-core\u002Fskills\u002Fdx-figma-verify\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"dx figma verify","dx","figma","verify","work","playwright mcp","ado","fix","generated","edit","write","read","design","png","search","screenshot","browser","code","components","MCP","2026-11-10 10:12:30",false,"---\nname: dx-figma-verify\ndescription: \"Compare a generated prototype with the Figma reference screenshot in a browser, fix gaps, write a report. Use after \u002Fdx-figma-prototype. Not for components on AEM (aem-fe-verify) or pre-PR checks (dx-step-verify).\"\nargument-hint: \"\u003CADO Work Item ID (optional — uses most recent if omitted)>\"\ncompatibility: \"Requires Playwright MCP (playwright) and a generated prototype from \u002Fdx-figma-prototype with figma-reference.png from \u002Fdx-figma-extract.\"\nmetadata:\n  version: 2.28.0\n  mcp-server: playwright\n  category: design-to-code\nallowed-tools: [\"read\", \"edit\", \"search\", \"write\", \"agent\", \"figma\u002F*\", \"playwright\u002F*\"]\n---\n\nYou visually verify a generated HTML\u002FCSS prototype against the original Figma design screenshot. You open the prototype in Chrome, take a screenshot, compare both images side by side using multimodal vision, and fix any visual gaps — up to 2 iterations.\n\nUse ultrathink for visual comparison — identifying layout, spacing, and color differences between two screenshots requires careful analysis.\n\n## 1. Locate the Spec Directory\n\n```bash\nSPEC_DIR=$(bash .ai\u002Flib\u002Fdx-common.sh find-spec-dir $ARGUMENTS)\n```\n\nIf the script exits with error, ask the user for the work item ID.\n\n## 2. Check Prerequisites\n\nVerify required files exist:\n\n- `$SPEC_DIR\u002Fprototype\u002Findex.html` — if missing: print `prototype\u002Findex.html not found — run \u002Fdx-figma-prototype first` and STOP.\n- Read `$SPEC_DIR\u002Ffigma-extract.md` — extract the node name, Figma URL, and **Viewports** field for the report header.\n\n**Detect viewport mode:**\n- Check the `**Viewports:**` field in `figma-extract.md`\n- If `single` or field absent → single-viewport mode. Require `prototype\u002Ffigma-reference.png`.\n- If multi-viewport (e.g., `2 — desktop (1440px), mobile (375px)`) → multi-viewport mode. Require `prototype\u002Ffigma-reference-desktop.png` (and any other listed viewport files). Also accept `figma-reference.png` as fallback for desktop.\n\nSet `verify_viewports` list:\n- Single: `[{ name: \"default\", reference: \"figma-reference.png\" }]`\n- Multi: `[{ name: \"desktop\", reference: \"figma-reference-desktop.png\", width: 1440 }, { name: \"mobile\", reference: \"figma-reference-mobile.png\", width: 375 }]` (parsed from figma-extract.md)\n\n**Run Steps 3–7 once per viewport.** For multi-viewport, iterate through each viewport sequentially — resize Chrome, screenshot, compare, fix. Aggregate all gaps into a single `figma-gaps.md`.\n\n## 3. Match Viewport to Figma Reference Size\n\nThe prototype screenshot MUST match the Figma reference width exactly — otherwise the visual comparison is meaningless (e.g., 390px mobile design vs 1000px desktop screenshot).\n\n**Step 3a.** Get the Figma reference image dimensions. Use one of these methods:\n\n1. **From figma-extract.md** — check for explicit width in the `**Viewports:**` field (e.g., `mobile (375px)`, `desktop (1440px)`). This is the most reliable source.\n\n2. **Via bash** — read image dimensions directly:\n   ```bash\n   file \u003Cabsolute-path-to-figma-reference.png>\n   ```\n   This outputs dimensions like `PNG image data, 390 x 844`. Parse the width.\n\n3. **Via browser_evaluate** — load the image in a blank page (before navigating to prototype):\n   ```\n   mcp__plugin_dx-aem_playwright__browser_navigate\n     url: \"about:blank\"\n   ```\n   ```\n   mcp__plugin_dx-aem_playwright__browser_evaluate\n     expression: |\n       (() => {\n         return new Promise((resolve) => {\n           const img = new Image();\n           img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });\n           img.onerror = () => resolve({ error: 'failed to load image' });\n           img.src = 'file:\u002F\u002F\u003Cabsolute-path-to-figma-reference.png>';\n         });\n       })()\n   ```\n\nIf none of these methods return a width, fall back to **1440x900**.\n\n**Step 3b.** Resize Chrome to match the Figma reference width:\n```\nmcp__plugin_dx-aem_playwright__browser_resize\n  width: \u003Cfigma-reference-width>\n  height: \u003Cfigma-reference-height or 900>\n```\n\n**Step 3c.** Verify the resize took effect:\n```\nmcp__plugin_dx-aem_playwright__browser_evaluate\n  expression: \"(() => ({ width: window.innerWidth, height: window.innerHeight }))()\"\n```\n\nIf `window.innerWidth` does not match the target width, retry the resize once. If still wrong, log a warning: `⚠️ Chrome viewport is \u003Cactual>px, expected \u003Ctarget>px. Screenshot may not match Figma reference dimensions.`\n\n**CRITICAL:** This resize MUST happen BEFORE navigating to the prototype (Step 4). The prototype screenshot must be taken at the same width as the Figma reference. A 390px Figma mobile design compared against a 1000px screenshot will produce false gaps everywhere.\n\n## 4. Open Prototype in Chrome\n\nNavigate to the prototype HTML file:\n```\nmcp__plugin_dx-aem_playwright__browser_navigate\n  url: \"file:\u002F\u002F\u003Cabsolute-path-to-SPEC_DIR>\u002Fprototype\u002Findex.html\"\n```\n\nWait for the page to load:\n```\nmcp__plugin_dx-aem_playwright__browser_wait_for\n  text: \"\u003C\u002Fhtml>\"\n  timeout: 10000\n```\n\nIf the prototype has a side-by-side comparison container (Figma reference panel), hide it so only the component renders:\n```\nmcp__plugin_dx-aem_playwright__browser_evaluate\n  expression: |\n    (() => {\n      \u002F\u002F Hide any Figma reference comparison panel\n      const panels = document.querySelectorAll('[class*=\"reference\"], [class*=\"comparison\"], [class*=\"figma-ref\"], [class*=\"side-by-side\"]');\n      panels.forEach(el => el.style.display = 'none');\n      \u002F\u002F Also hide any img pointing to figma-reference\n      document.querySelectorAll('img[src*=\"figma-reference\"]').forEach(el => el.style.display = 'none');\n      return { hiddenPanels: panels.length };\n    })()\n```\n\n## 5. Take Prototype Screenshot\n\n```\nmcp__plugin_dx-aem_playwright__browser_take_screenshot\n```\n\nSave the screenshot with viewport-aware naming:\n- **Single viewport:** `$SPEC_DIR\u002Fprototype\u002Fprototype-screenshot.png`\n- **Multi-viewport:** `$SPEC_DIR\u002Fprototype\u002Fprototype-screenshot-\u003Cviewport.name>.png` (e.g., `prototype-screenshot-desktop.png`, `prototype-screenshot-mobile.png`)\n\nIf Playwright returns the screenshot as a displayed image rather than a file path, note the output for visual comparison in the next step.\n\n## 6. Visual Comparison\n\nRead both images and compare them:\n\n1. Read the Figma reference for this viewport (`figma-reference.png` or `figma-reference-\u003Cviewport.name>.png`)\n2. Read the prototype screenshot for this viewport (`prototype-screenshot.png` or `prototype-screenshot-\u003Cviewport.name>.png`)\n\n**Compare across these categories:**\n\n| Category | What to check |\n|----------|--------------|\n| **Layout** | Flex\u002Fgrid direction, alignment, element ordering, overall structure |\n| **Typography** | Font sizes, weights, line heights, text alignment, letter spacing |\n| **Colors** | Background colors, text colors, border colors, accent colors |\n| **Spacing** | Margins, paddings, gaps between elements |\n| **Missing elements** | Buttons, icons, dividers, labels, images present in Figma but absent in prototype |\n| **Extra elements** | Anything in prototype not in the Figma design |\n\n**≈ Tolerance:** If `figma-extract.md` contains a `## Dynamic Content Elements` table, read it before comparing. Properties marked **≈** in the extract are content-dependent — allow reasonable deviation for these (e.g., ≈32px padding could be 28-36px without being flagged). Only flag ≈ values as gaps if the deviation is clearly wrong (>30% off or visually broken).\n\n**For each gap found, record:**\n- Category (from table above)\n- Description of the difference\n- Severity: `major` (structural\u002Flayout wrong, missing element) or `minor` (spacing off, color slightly different)\n- Whether the property is ≈ (content-dependent) — if so, note the tolerance\n\n**If no gaps found:** Skip to Step 8.\n\n## 7. Fix Loop (max 2 iterations)\n\nFor each iteration:\n\n### 7a. Apply Fixes\n\nEdit the prototype files directly based on the gaps found:\n\n- **CSS fixes** (colors, spacing, typography, sizing): Edit `prototype\u002Fstyles.css`\n- **HTML fixes** (missing elements, wrong structure, extra elements): Edit `prototype\u002Findex.html`\n- **JS fixes** (interactive behavior): Edit `prototype\u002Fscript.js` if it exists\n\nMake targeted, surgical edits — do not regenerate the entire file. Fix one gap at a time.\n\n### 7b. Re-screenshot\n\nReload the page in Chrome:\n```\nmcp__plugin_dx-aem_playwright__browser_navigate\n  url: \"file:\u002F\u002F\u003Cabsolute-path-to-SPEC_DIR>\u002Fprototype\u002Findex.html\"\n```\n\nHide the comparison panel again (Step 4 script), then take a new screenshot. Overwrite `prototype-screenshot.png`.\n\n### 7c. Re-compare\n\nRead the new screenshot and compare again against the Figma reference for this viewport. Update the gap list:\n- Mark fixed gaps as `fixed`\n- Note any remaining gaps\n- Note any new gaps introduced by fixes\n\n### 7d. Loop Control\n\n- If all gaps are fixed or only minor gaps remain → break\n- If iteration count reaches 2 → break (diminishing returns)\n- Otherwise → continue to next iteration\n\n## 8. Write figma-gaps.md\n\nAfter all viewports have been verified, write a single `$SPEC_DIR\u002Ffigma-gaps.md`.\n\nRead `.ai\u002Ftemplates\u002Fspec\u002Ffigma-gaps.md.template` and follow that structure exactly. The template uses HTML comments as authoring instructions — follow them but do not include them in the output. Key rules:\n\n- **Overall result** is the worst result across all viewports (e.g., desktop PASS + mobile NEEDS ATTENTION → overall NEEDS ATTENTION)\n- Include one **per-viewport section** for each verified viewport (or one \"Default\" section for single-viewport)\n- **Visual Acceptance Checklist** is mandatory — generate binary pass\u002Ffail assertions per viewport with concrete values (hex colors, pixel sizes). See `references\u002Facceptance-checklist.md` for assertion format rules.\n- Mark `[x]` for assertions verified during comparison, `[ ]` for unverified or manual-check items\n- Use **≈** prefix for assertions about content-dependent properties (from figma-extract.md's Dynamic Content Elements table)\n\n## 9. Present Summary\n\n```markdown\n## Prototype verification complete\n\n**Result:** \u003CPASS | PASS WITH MINOR GAPS | NEEDS ATTENTION>\n**Viewports:** \u003Clist with per-viewport results, e.g. \"desktop: PASS, mobile: PASS WITH MINOR GAPS\">\n- Gaps found: \u003Ctotal count>\n- Fixed: \u003Ccount> in \u003CN> iterations\n- Remaining: \u003Ccount> (\u003Cseverity breakdown>)\n- Acceptance checklist: \u003Ccount> assertions (\u003Ccount> verified, \u003Ccount> to check manually)\n- Report: figma-gaps.md\n\n\u003Cif PASS>\n### Prototype matches Figma reference. Ready for `\u002Fdx-plan`.\n\u003C\u002Fif>\n\u003Cif PASS WITH MINOR GAPS>\n### Minor differences remain — acceptable for implementation. Ready for `\u002Fdx-plan`.\n\u003C\u002Fif>\n\u003Cif NEEDS ATTENTION>\n### Major gaps remain after 2 fix rounds. Review figma-gaps.md and consider re-running `\u002Fdx-figma-prototype`.\n\u003C\u002Fif>\n```\n\n## Result Classification\n\n| Result | Criteria |\n|--------|----------|\n| **PASS** | 0 remaining gaps |\n| **PASS WITH MINOR GAPS** | Only minor remaining gaps (no major) |\n| **NEEDS ATTENTION** | 1+ major remaining gaps after max iterations |\n\n## Error Handling\n\n- **Playwright MCP not available:** Print `⚠️ Playwright MCP not available — cannot verify prototype visually. Ensure the playwright server is enabled and Chromium is installed (npx playwright install chromium).` and STOP.\n- **File URL blocked by Chrome:** Some Chrome configs block `file:\u002F\u002F` URLs. Print instructions: `Try: open -a \"Google Chrome\" --args --allow-file-access-from-files` and retry.\n- **Screenshot fails:** Continue with whatever was captured. If no screenshot at all, fall back to structural HTML comparison (read the HTML source and compare element structure against figma-extract.md).\n- **Resize fails:** Proceed with default viewport. Note the mismatch in the report.\n\n## Rules\n\n- **Real screenshots only** — always use Playwright, never \"mentally compare\"\n- **Match viewport** — resize Chrome to Figma reference dimensions before screenshotting\n- **Surgical fixes** — edit specific CSS properties\u002FHTML elements, don't regenerate files\n- **2 iterations max** — stop after 2 fix rounds regardless of remaining gaps\n- **Separate images** — compare prototype screenshot vs Figma reference as two independent images\n- **Classify severity** — major (structural) vs minor (cosmetic) determines the result\n- **Idempotent** — re-running overwrites prototype-screenshot.png and figma-gaps.md\n","You visually verify a generated HTML\u002FCSS prototype against the original Figma design screenshot. You open the prototype in Chrome, take a screenshot, compare both images side by side using multimodal vision, and fix any visual gaps — up to 2 iterations.\n\nUse ultrathink for visual comparison — identifying layout, spacing, and color differences between two screenshots requires careful analysis.\n\n## 1. Locate the Spec Directory\n\n```bash\nSPEC_DIR=$(bash .ai\u002Flib\u002Fdx-common.sh find-spec-dir $ARGUMENTS)\n```\n\nIf the script exits with error, ask the user for the work item ID.\n\n## 2. Check Prerequisites\n\nVerify required files exist:\n\n- `$SPEC_DIR\u002Fprototype\u002Findex.html` — if missing: print `prototype\u002Findex.html not found — run \u002Fdx-figma-prototype first` and STOP.\n- Read `$SPEC_DIR\u002Ffigma-extract.md` — extract the node name, Figma URL, and **Viewports** field for the report header.\n\n**Detect viewport mode:**\n- Check the `**Viewports:**` field in `figma-extract.md`\n- If `single` or field absent → single-viewport mode. Require `prototype\u002Ffigma-reference.png`.\n- If multi-viewport (e.g., `2 — desktop (1440px), mobile (375px)`) → multi-viewport mode. Require `prototype\u002Ffigma-reference-desktop.png` (and any other listed viewport files). Also accept `figma-reference.png` as fallback for desktop.\n\nSet `verify_viewports` list:\n- Single: `[{ name: \"default\", reference: \"figma-reference.png\" }]`\n- Multi: `[{ name: \"desktop\", reference: \"figma-reference-desktop.png\", width: 1440 }, { name: \"mobile\", reference: \"figma-reference-mobile.png\", width: 375 }]` (parsed from figma-extract.md)\n\n**Run Steps 3–7 once per viewport.** For multi-viewport, iterate through each viewport sequentially — resize Chrome, screenshot, compare, fix. Aggregate all gaps into a single `figma-gaps.md`.\n\n## 3. Match Viewport to Figma Reference Size\n\nThe prototype screenshot MUST match the Figma reference width exactly — otherwise the visual comparison is meaningless (e.g., 390px mobile design vs 1000px desktop screenshot).\n\n**Step 3a.** Get the Figma reference image dimensions. Use one of these methods:\n\n1. **From figma-extract.md** — check for explicit width in the `**Viewports:**` field (e.g., `mobile (375px)`, `desktop (1440px)`). This is the most reliable source.\n\n2. **Via bash** — read image dimensions directly:\n   ```bash\n   file \u003Cabsolute-path-to-figma-reference.png>\n   ```\n   This outputs dimensions like `PNG image data, 390 x 844`. Parse the width.\n\n3. **Via browser_evaluate** — load the image in a blank page (before navigating to prototype):\n   ```\n   mcp__plugin_dx-aem_playwright__browser_navigate\n     url: \"about:blank\"\n   ```\n   ```\n   mcp__plugin_dx-aem_playwright__browser_evaluate\n     expression: |\n       (() => {\n         return new Promise((resolve) => {\n           const img = new Image();\n           img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });\n           img.onerror = () => resolve({ error: 'failed to load image' });\n           img.src = 'file:\u002F\u002F\u003Cabsolute-path-to-figma-reference.png>';\n         });\n       })()\n   ```\n\nIf none of these methods return a width, fall back to **1440x900**.\n\n**Step 3b.** Resize Chrome to match the Figma reference width:\n```\nmcp__plugin_dx-aem_playwright__browser_resize\n  width: \u003Cfigma-reference-width>\n  height: \u003Cfigma-reference-height or 900>\n```\n\n**Step 3c.** Verify the resize took effect:\n```\nmcp__plugin_dx-aem_playwright__browser_evaluate\n  expression: \"(() => ({ width: window.innerWidth, height: window.innerHeight }))()\"\n```\n\nIf `window.innerWidth` does not match the target width, retry the resize once. If still wrong, log a warning: `⚠️ Chrome viewport is \u003Cactual>px, expected \u003Ctarget>px. Screenshot may not match Figma reference dimensions.`\n\n**CRITICAL:** This resize MUST happen BEFORE navigating to the prototype (Step 4). The prototype screenshot must be taken at the same width as the Figma reference. A 390px Figma mobile design compared against a 1000px screenshot will produce false gaps everywhere.\n\n## 4. Open Prototype in Chrome\n\nNavigate to the prototype HTML file:\n```\nmcp__plugin_dx-aem_playwright__browser_navigate\n  url: \"file:\u002F\u002F\u003Cabsolute-path-to-SPEC_DIR>\u002Fprototype\u002Findex.html\"\n```\n\nWait for the page to load:\n```\nmcp__plugin_dx-aem_playwright__browser_wait_for\n  text: \"\u003C\u002Fhtml>\"\n  timeout: 10000\n```\n\nIf the prototype has a side-by-side comparison container (Figma reference panel), hide it so only the component renders:\n```\nmcp__plugin_dx-aem_playwright__browser_evaluate\n  expression: |\n    (() => {\n      \u002F\u002F Hide any Figma reference comparison panel\n      const panels = document.querySelectorAll('[class*=\"reference\"], [class*=\"comparison\"], [class*=\"figma-ref\"], [class*=\"side-by-side\"]');\n      panels.forEach(el => el.style.display = 'none');\n      \u002F\u002F Also hide any img pointing to figma-reference\n      document.querySelectorAll('img[src*=\"figma-reference\"]').forEach(el => el.style.display = 'none');\n      return { hiddenPanels: panels.length };\n    })()\n```\n\n## 5. Take Prototype Screenshot\n\n```\nmcp__plugin_dx-aem_playwright__browser_take_screenshot\n```\n\nSave the screenshot with viewport-aware naming:\n- **Single viewport:** `$SPEC_DIR\u002Fprototype\u002Fprototype-screenshot.png`\n- **Multi-viewport:** `$SPEC_DIR\u002Fprototype\u002Fprototype-screenshot-\u003Cviewport.name>.png` (e.g., `prototype-screenshot-desktop.png`, `prototype-screenshot-mobile.png`)\n\nIf Playwright returns the screenshot as a displayed image rather than a file path, note the output for visual comparison in the next step.\n\n## 6. Visual Comparison\n\nRead both images and compare them:\n\n1. Read the Figma reference for this viewport (`figma-reference.png` or `figma-reference-\u003Cviewport.name>.png`)\n2. Read the prototype screenshot for this viewport (`prototype-screenshot.png` or `prototype-screenshot-\u003Cviewport.name>.png`)\n\n**Compare across these categories:**\n\n| Category | What to check |\n|----------|--------------|\n| **Layout** | Flex\u002Fgrid direction, alignment, element ordering, overall structure |\n| **Typography** | Font sizes, weights, line heights, text alignment, letter spacing |\n| **Colors** | Background colors, text colors, border colors, accent colors |\n| **Spacing** | Margins, paddings, gaps between elements |\n| **Missing elements** | Buttons, icons, dividers, labels, images present in Figma but absent in prototype |\n| **Extra elements** | Anything in prototype not in the Figma design |\n\n**≈ Tolerance:** If `figma-extract.md` contains a `## Dynamic Content Elements` table, read it before comparing. Properties marked **≈** in the extract are content-dependent — allow reasonable deviation for these (e.g., ≈32px padding could be 28-36px without being flagged). Only flag ≈ values as gaps if the deviation is clearly wrong (>30% off or visually broken).\n\n**For each gap found, record:**\n- Category (from table above)\n- Description of the difference\n- Severity: `major` (structural\u002Flayout wrong, missing element) or `minor` (spacing off, color slightly different)\n- Whether the property is ≈ (content-dependent) — if so, note the tolerance\n\n**If no gaps found:** Skip to Step 8.\n\n## 7. Fix Loop (max 2 iterations)\n\nFor each iteration:\n\n### 7a. Apply Fixes\n\nEdit the prototype files directly based on the gaps found:\n\n- **CSS fixes** (colors, spacing, typography, sizing): Edit `prototype\u002Fstyles.css`\n- **HTML fixes** (missing elements, wrong structure, extra elements): Edit `prototype\u002Findex.html`\n- **JS fixes** (interactive behavior): Edit `prototype\u002Fscript.js` if it exists\n\nMake targeted, surgical edits — do not regenerate the entire file. Fix one gap at a time.\n\n### 7b. Re-screenshot\n\nReload the page in Chrome:\n```\nmcp__plugin_dx-aem_playwright__browser_navigate\n  url: \"file:\u002F\u002F\u003Cabsolute-path-to-SPEC_DIR>\u002Fprototype\u002Findex.html\"\n```\n\nHide the comparison panel again (Step 4 script), then take a new screenshot. Overwrite `prototype-screenshot.png`.\n\n### 7c. Re-compare\n\nRead the new screenshot and compare again against the Figma reference for this viewport. Update the gap list:\n- Mark fixed gaps as `fixed`\n- Note any remaining gaps\n- Note any new gaps introduced by fixes\n\n### 7d. Loop Control\n\n- If all gaps are fixed or only minor gaps remain → break\n- If iteration count reaches 2 → break (diminishing returns)\n- Otherwise → continue to next iteration\n\n## 8. Write figma-gaps.md\n\nAfter all viewports have been verified, write a single `$SPEC_DIR\u002Ffigma-gaps.md`.\n\nRead `.ai\u002Ftemplates\u002Fspec\u002Ffigma-gaps.md.template` and follow that structure exactly. The template uses HTML comments as authoring instructions — follow them but do not include them in the output. Key rules:\n\n- **Overall result** is the worst result across all viewports (e.g., desktop PASS + mobile NEEDS ATTENTION → overall NEEDS ATTENTION)\n- Include one **per-viewport section** for each verified viewport (or one \"Default\" section for single-viewport)\n- **Visual Acceptance Checklist** is mandatory — generate binary pass\u002Ffail assertions per viewport with concrete values (hex colors, pixel sizes). See `references\u002Facceptance-checklist.md` for assertion format rules.\n- Mark `[x]` for assertions verified during comparison, `[ ]` for unverified or manual-check items\n- Use **≈** prefix for assertions about content-dependent properties (from figma-extract.md's Dynamic Content Elements table)\n\n## 9. Present Summary\n\n```markdown\n## Prototype verification complete\n\n**Result:** \u003CPASS | PASS WITH MINOR GAPS | NEEDS ATTENTION>\n**Viewports:** \u003Clist with per-viewport results, e.g. \"desktop: PASS, mobile: PASS WITH MINOR GAPS\">\n- Gaps found: \u003Ctotal count>\n- Fixed: \u003Ccount> in \u003CN> iterations\n- Remaining: \u003Ccount> (\u003Cseverity breakdown>)\n- Acceptance checklist: \u003Ccount> assertions (\u003Ccount> verified, \u003Ccount> to check manually)\n- Report: figma-gaps.md\n\n\u003Cif PASS>\n### Prototype matches Figma reference. Ready for `\u002Fdx-plan`.\n\u003C\u002Fif>\n\u003Cif PASS WITH MINOR GAPS>\n### Minor differences remain — acceptable for implementation. Ready for `\u002Fdx-plan`.\n\u003C\u002Fif>\n\u003Cif NEEDS ATTENTION>\n### Major gaps remain after 2 fix rounds. Review figma-gaps.md and consider re-running `\u002Fdx-figma-prototype`.\n\u003C\u002Fif>\n```\n\n## Result Classification\n\n| Result | Criteria |\n|--------|----------|\n| **PASS** | 0 remaining gaps |\n| **PASS WITH MINOR GAPS** | Only minor remaining gaps (no major) |\n| **NEEDS ATTENTION** | 1+ major remaining gaps after max iterations |\n\n## Error Handling\n\n- **Playwright MCP not available:** Print `⚠️ Playwright MCP not available — cannot verify prototype visually. Ensure the playwright server is enabled and Chromium is installed (npx playwright install chromium).` and STOP.\n- **File URL blocked by Chrome:** Some Chrome configs block `file:\u002F\u002F` URLs. Print instructions: `Try: open -a \"Google Chrome\" --args --allow-file-access-from-files` and retry.\n- **Screenshot fails:** Continue with whatever was captured. If no screenshot at all, fall back to structural HTML comparison (read the HTML source and compare element structure against figma-extract.md).\n- **Resize fails:** Proceed with default viewport. Note the mismatch in the report.\n\n## Rules\n\n- **Real screenshots only** — always use Playwright, never \"mentally compare\"\n- **Match viewport** — resize Chrome to Figma reference dimensions before screenshotting\n- **Surgical fixes** — edit specific CSS properties\u002FHTML elements, don't regenerate files\n- **2 iterations max** — stop after 2 fix rounds regardless of remaining gaps\n- **Separate images** — compare prototype screenshot vs Figma reference as two independent images\n- **Classify severity** — major (structural) vs minor (cosmetic) determines the result\n- **Idempotent** — re-running overwrites prototype-screenshot.png and figma-gaps.md\n",{"name":5,"metadata":54,"description":7,"allowed-tools":58,"argument-hint":62,"compatibility":63},{"version":55,"category":56,"mcp-server":57},"2.28.0","design-to-code","playwright",[40,38,43,39,59,60,61],"agent","figma\u002F*","playwright\u002F*","\u003CADO Work Item ID (optional — uses most recent if omitted)>","Requires Playwright MCP (playwright) and a generated prototype from \u002Fdx-figma-prototype with figma-reference.png from \u002Fdx-figma-extract.","main","a99cabc3f459fbeaa42b13a1604db1bccb6a364b","plugins\u002Fdx-core\u002Fskills\u002Fdx-figma-verify",3,"https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow","https:\u002F\u002Fgithub.com\u002Feasingthemes","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fdraganfilipovic\u002F","Agentic SDLC platform in production. I build agent-ready codebases. AEM MCP Server author.","2026-11-11 09:59:48",{"source":8,"skillName":5,"commands":74,"prompt":84,"zipAvailable":85},[75,78,81],{"tool":76,"command":77},"npx","npx skills add easingthemes\u002Fdx-aem-flow --skill dx-figma-verify",{"tool":79,"command":80},"bunx","bunx skills add easingthemes\u002Fdx-aem-flow --skill dx-figma-verify",{"tool":82,"command":83},"pnpm","pnpm dlx skills add easingthemes\u002Fdx-aem-flow --skill dx-figma-verify","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-core\u002Fskills\u002Fdx-figma-verify\u002FSKILL.md",true,[87],{"path":88,"resourceType":89,"resourceTypeDesc":90,"sizeBytes":91,"sourceHtmlUrl":92},"references\u002Facceptance-checklist.md","REFERENCE","参考文档",2502,"https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-core\u002Fskills\u002Fdx-figma-verify\u002Freferences\u002Facceptance-checklist.md",[94,117,138,154,170,185],{"skillNo":95,"name":96,"nameZh":6,"description":97,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":100,"publishedAt":49},"01M6H48W19F46A7B7TSSQAMYRW","dx-hub-status","Show hub dispatch status — which repos are running, done, blocked or failed. Use for 'hub status', 'what's running'.","https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-hub\u002Fskills\u002Fdx-hub-status\u002FSKILL.md",[],[30,101,102,103,104,105,106,107,108,109,110,111,112,113,114,40,39,115,116],"dx hub status","hub","status","hub status","which","show","for","ticket","clean","use","done","Bash","id","dispatch","repos","grep",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":49},"01M6H48R6ZH7YMVPMVWMMWT3RA","dx-hub-init","Initialize a hub directory for multi-repo orchestration. Discovers sibling repos, merges configs, validates CLI compatibility. Use when setting up hub mode for the first time. Trigger on \"init hub\", \"set up hub\", \"multi-repo setup\".","https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-hub\u002Fskills\u002Fdx-hub-init\u002FSKILL.md",[],[124,125,30,126,102,127,128,129,130,131,132,133,134,135,112,136,137,40,39,38],"init","hub init","dx hub init","SET","time","mode","default","up","repo setup","orchestration","configure","multi-repo","cli","directory",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":145,"publishedAt":49},"01M6H48K267CWEF8YNN3Y49BVT","dx-hub-dispatch","Dispatch a ticket to several repos — open an independent Claude session per repo in VS Code terminals. Use for 'hub dispatch', 'work on ticket across repos'.","https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-hub\u002Fskills\u002Fdx-hub-dispatch\u002FSKILL.md",[144],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[30,146,114,102,35,107,147,148,149,108,150,48,110,151,112,152,46,153,113,33],"dx hub dispatch","repo","work on","session","open","URL","vscode","across",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":160,"publishedAt":49},"01M6H48FAWKTT6AAWT3H80ZKE0","dx-hub-config","View and edit hub configuration — add repos, adjust terminal delay. Use to manage hub settings. Trigger on \"hub config\", \"add repo to hub\", \"terminal delay\".","https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-hub\u002Fskills\u002Fdx-hub-config\u002FSKILL.md",[],[30,161,102,162,106,163,147,164,165,166,167,110,134,112,168,40,169,39,38,115],"dx hub config","config","view","manage","trigger","true","adjust","terminal","settings",{"skillNo":171,"name":172,"nameZh":6,"description":173,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":174,"categories":175,"keywords":176,"publishedAt":49},"01M6H48BNMYEJY6CCWPYHNQDAT","dx-discover-repos","Resolve which repos a work item touches (explicit directive → simple block → cross-repo table → LLM). Used by the KAI-HUB router to fan an agent out across repos; 'which repos'.","https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-hub\u002Fskills\u002Fdx-discover-repos\u002FSKILL.md",[],[177,30,178,115,105,147,153,179,113,180,33,181,102,182,183,184],"discover","dx discover repos","router","directive","simple","block","sonnet","table",{"skillNo":186,"name":187,"nameZh":6,"description":188,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":189,"categories":190,"keywords":192,"publishedAt":49},"01M6H487QA1FDSBT1HTZGW4HAQ","dx-upgrade","Upgrade a consumer project to the installed plugin versions — run dx-doctor, fix stale and missing files, list manual actions. Use after upgrading plugins.","https:\u002F\u002Fgithub.com\u002Feasingthemes\u002Fdx-aem-flow\u002Fblob\u002Fmain\u002Fplugins\u002Fdx-core\u002Fskills\u002Fdx-upgrade\u002FSKILL.md",[191],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[193,30,194,195,196,43,36,197,198,199,40,39,38,200,201,202,203,110,204,205],"upgrade","dx upgrade","project","actions","files","auto","run","list","doctor","manual","missing","plugin","plugins"]