| name | figma-from-code-validate |
| description | Subagent for figma-from-code Phase 5. Validates the completed Figma rebuild by comparing assembled screen frames against app screenshots. Runs fix loops on mismatched screens and produces a structured report. |
| model | claude-sonnet-4-5 |
Skill: Validate + Fix (Phase 5)
Validates the completed Figma rebuild by comparing full-page screen frames against app screenshots. Instead of re-validating every individual component (which already passed during Phase 3's build loop), this phase checks the assembled screens as a whole — verifying that components compose correctly and that nothing was lost during screen assembly. Runs fix loops on mismatched screens and produces a structured report. Runs as a subagent dispatched by the orchestrator.
When to Use
- When
figma-from-code orchestrator reaches Phase 5
- Standalone to validate assembled screens after a rebuild
Required Inputs
| Input | Description | Source |
|---|
fileKey | Figma file key | State ledger |
builtComponents | Map of {name: nodeId} for all built components | state.json -> builtComponents |
figmaNodes | All page and frame node IDs | state.json -> figmaNodes |
buildOrder | Tiered component list | state.json -> buildOrder |
devServerUrl | URL of the running dev server | state.json → config.devServerUrl (default http://localhost:5173) |
precaptureScreens | Screen manifest from Phase 2.5 | .temp/figma-from-code/precapture-screens.json |
Output Files
| File | Contents | Consumed by |
|---|
.temp/figma-validation/report.md | Full validation report with per-screen comparisons | User review |
.temp/figma-from-code/validation-summary.json | Small summary for the orchestrator | Orchestrator only |
Workflow
Placeholders like {devServerUrl} and {skillRoot} resolve from state.json → config.
1. Validate screens (full-page comparisons only)
For each screen built in Phase 4 (read from .temp/figma-from-code/build-results/screens/):
- Read the screen result — get the screen's Figma node ID from
build-results/screens/{screenName}.json
- Capture a fresh Figma screenshot —
get_screenshot(fileKey, screenNodeId) at scale: 1
- Compare against the app screenshot — the pre-captured full-page screenshot from Phase 2.5:
node {skillRoot}/scripts/compare.js \
".temp/figma-from-code/screenshots/screens/{screenName}/app.png" \
".temp/figma-validation/screenshots/{screenName}/figma.png" \
".temp/figma-validation/screenshots/{screenName}/"
- Record the verdict — thresholds:
matchPct ≥ 85% → match, 70-85% → minor_diff, < 70% → mismatch (screen thresholds are slightly lower than component thresholds because full pages have more variation in dynamic content)
Fix loop for mismatched screens: For screens with verdict: "mismatch" or "minor_diff", run up to 2 fix iterations:
- Diagnose from
diff.png — identify which region/component is off
- Apply targeted fix via
use_figma (adjust instance position, swap variant, fix spacing)
- Re-screenshot and re-compare
- If after 2 iterations the screen still doesn't pass, record as
partial_match
Pre-existing screens (in state.json → preExistingScreens) are compared read-only — screenshot and record the verdict, but do NOT run the fix loop. Surface mismatches for user review.
2. Clean up Components page layout
After validation, clean up any misplaced components on the Components page. Subagents sometimes create their own frames instead of using the designated tier frames.
const componentsPage = figma.root.children.find((p) => p.name.includes('Components'));
await figma.setCurrentPageAsync(componentsPage);
const tierFrameIds = new Set([
iconsFrameId,
tier1FrameId,
tier2FrameId,
]);
const strayFrames = componentsPage.children.filter((c) => !tierFrameIds.has(c.id));
const frameOrder = [iconsFrameId, tier1FrameId, tier2FrameId ];
let yPos = 0;
const gap = 80;
for (const id of frameOrder) {
const frame = figma.getNodeById(id);
frame.x = 0;
frame.y = yPos;
yPos += Math.round(frame.height) + gap;
}
3. Stop the Playwright server
kill $(cat .temp/figma-from-code/pw-server.pid 2>/dev/null) 2>/dev/null
rm -f .temp/figma-from-code/pw-endpoint.txt
4. Write validation summary
Parse the results and write a concise summary for the orchestrator:
{
"screensCompared": 8,
"match": 6,
"minorDiff": 1,
"mismatch": 0,
"fixedDuringValidation": 1,
"averageMatchPct": 89.7,
"overallVerdict": "PASS",
"preExistingFlagged": [],
"screenResults": [
{ "name": "CasesPage", "matchPct": 92.1, "verdict": "match" },
{ "name": "CreateCasePage", "matchPct": 87.3, "verdict": "match" }
],
"reportPath": ".temp/figma-validation/report.md"
}
Write to .temp/figma-from-code/validation-summary.json.
Overall verdict: PASS if >= 75% of compared screens are match. Otherwise FAIL.
5. Report
Phase 5 complete:
- {screensCompared} screens validated (full-page comparison)
- {match} match, {minorDiff} minor diff, {mismatch} mismatch
- {fixedDuringValidation} fixed during validation
- Average match: {averageMatchPct}%
- Overall verdict: {overallVerdict}
- Individual components already validated during Phase 3 build loop (not re-checked)
Skip / Resume
Skip if .temp/figma-from-code/validation-summary.json exists and state.json -> phases.phase5 is complete.
Error Handling
| Scenario | Action |
|---|
| Validator skill fails | Report error; partial results may exist in .temp/figma-validation/ |
Cleanup use_figma fails | Report error; cleanup is non-critical — the components are already validated |
| Playwright server already stopped | Ignore the kill failure |
| Dev server not running | Halt validation and tell the user to start the dev server |