| name | ui-iterate |
| description | CONVERGE an EXISTING rendered UI surface to good craft through a closed measured loop — judge → fix-list → edit code → HMR re-render → re-judge → repeat until PROCEED or a 3-round cap. Probe-driven (Playwright-MCP computed-style JSON), not eyeballing, because GLM-5.2 has no vision. Inlines the 7-dim rubric + 13-tell slop gate so a surface can be converged in-loop. ROUTE BY INTENT, NOT KEYWORDS — load this whenever the intent is to REPEATEDLY IMPROVE a built surface until it is good, including indirect signals: "이거 계속 비슷해" (a prior one-shot fix did not land), "쓰레기 UI 고쳐", "UI 다듬어", "개선 루프 돌려", "craft 올려", "make this converge", any vibe that one-shot review is not enough and the user wants to iterate to satisfaction. NOT for designing a new screen from JTBD (that is ux-design-baseline). NOT for a single quality verdict (that is design-craft-rubric — judge once). NOT for runtime mechanics. |
UI Iterate — GLM-5.2 edition (closed probe-driven craft loop)
A closed, measured craft loop for an EXISTING rendered surface. The value over a single design pass is convergence with evidence: the judge probes real rendered values via Playwright-MCP (computed styles, a11y tree, console), returns a concrete fix-list (never a vibe score), a builder applies it, HMR re-renders, and it re-judges — so "0-satisfaction one-pass UI" becomes a surface that demonstrably passes a token-aware rubric + the AI-slop gate, with probe transcripts proving it.
Why this skill exists (and why it is probe-driven for GLM-5.2)
GLM-5.2 has no built-in vision (config-confirmed: modalities.input: ["text"] only). A loop that relies on the model "looking at" a screenshot will not converge — the model cannot see its own output. So this loop inlines the probe-driven rubric from design-craft-rubric: judgments come from browser_evaluate computed-style JSON, browser_snapshot a11y tree, and browser_console_messages — all text the model can reason over. A screenshot is captured only as a before/after audit artifact, never as the model's own verification input.
The rubric and slop gate are the SAME as design-craft-rubric — inlined here so a surface can be converged in-loop. No keyword heuristics, no vibe judgments — every dimension has a concrete pass-bar (≥1.25× size step, 4/8/12/16/24/32 spacing scale, rendered px/hex from probe), and every FAIL carries a target value the builder can apply directly.
When to use
- An existing UI surface whose craft is weak — cramped/flat hierarchy, ad-hoc spacing, off-token sizes, an action that visually disappears — and you want it converged, not just reviewed.
- After a build lands a screen and you want a measured craft pass before merge.
- The "make this not look like garbage" request on a concrete rendered route.
When NOT to use
- Designing a NEW screen from the job-to-be-done / flow →
ux-design-baseline (produces design.md).
- A single craft opinion with no fix loop → load
design-craft-rubric and judge once.
- Runtime correctness — scroll containment, viewport fit, console errors, selection sync → runtime verification (ui-verify equivalent), not this loop.
- A library/framework's own component docs →
context7.
How the loop runs
For each round until PROCEED or maxIterations (default 3):
Round N — Judge (probe-driven, ~3-4 tool calls):
browser_navigate the route; browser_resize to 1440×900 AND 390×812.
browser_wait_for a stable anchor (cold compile / hydration).
browser_snapshot — a11y tree (structural input).
browser_evaluate — computed-style probe (the "eyes" — see design-craft-rubric for the template). Returns JSON of fontSize/fontWeight/color/padding/margin/borderRadius/gap/rect per key element + fontLoaded + contrast + transitionCount.
browser_console_messages (warning) — font 404s, CSS overrides, 4xx/5xx render-blockers.
- Load owning DESIGN.md for token scale + tone.
- Score the 7 dimensions PASS/FAIL from probe values (not vibes) + run the 13 AI-slop tells gate. Emit prioritized fix-list (
surface/element · 무엇이 잘못 · target value). Verdict PROCEED or REVISE.
Round N — Fix (builder, in main context — no sub-agent needed):
- Edit
targetFile, reusing existing primitives, applying ONLY the fix-list. No hand-styling, no unrequested toggles/shortcuts, no chrome. [[feedback_no_speculative_ui_chrome]]
- Every color/type value must derive from the repo's token system (DESIGN.md / token CSS). Ad-hoc hex /
text-[Npx] BANNED unless the fix explicitly maps it to a token.
Round N → N+1: HMR re-renders → re-Judge (probe again from scratch — do NOT assume the prior probe still holds after edits).
Return: { converged: bool, rounds: N, history: [{ round, verdict, fixList, probeSnapshot }] }. The probe transcript of each round is the before/after evidence — stronger than a screenshot for a text-only model.
Required setup before invoking
- A running dev server for the surface and the route's devUrl + path. Operate in a worktree, not main (the fix step edits code).
- A surface that actually renders with data. If the route is data-gated (needs a backend / auth to render its real layout, else it shows a loading/error state), the judge will critique the wrong thing. Stand up a proof harness first: a dev-only page that mounts the real component with its data seeded — e.g. seed the React Query cache (
queryClient.setQueryData(key, fixture)) AND point the dev proxy at a tiny stub server returning the fixture for the endpoints (so the on-mount refetch/poll doesn't overwrite the seed). Then point route at that proof page. This is mechanical but essential — a judge that probes a spinner is worse than no judge (async-timing risk).
tokenTablePath (optional) → the design-token SSOT (e.g. the repo's token CSS) so the token-conformance dimension is real, not heuristic; absent it, the judge honest-degrades to raw-hex/text-[Npx] flags.
maxIterations (default 3) — cap to prevent infinite loops. If the surface does not converge in 3 rounds, STOP and surface the remaining FAILs to the user; do not silently keep looping.
Honesty limits
The judge is an LLM applying rules over probe output — a strong signal, not ground truth. Probes can lie (CSS specificity cancellation, late hydration, fonts loading after probe). Mitigations: browser_wait_for anchor before probe; document.fonts.ready await; cross-check browser_console_messages. Keep the real backstops: a human merge, axe CI for formal WCAG (defer there — never self-report axe), runtime verification for behavior, visual-regression CI for change/regression. ui-iterate converges craft; it does not certify the feature works.
A screenshot at the end of the loop (fullPage, mobile + desktop) is useful as a record for a human reviewer; GLM-5.2 itself cannot interpret it, so do not use it as in-loop verification.