"Make it a bit more polished" is not an instruction. craft-qa converts it into the items below and judges it.
Order: machine first, eyes later
Do not spend model cost on what can be judged deterministically. If even one item in Group A (scripts) fails, Group B (visual inspection) is not run.
Group A — Deterministic checks (scripts, hard fail)
If even one item is caught, it is rejected immediately. It is not offset by score.
| Check | Criterion | Failure example (actually observed) |
|---|---|---|
| Canvas spec | All pages in one pack have the same pixel size, declared aspect ratio error ≤0.5% | ppt-motie Only 5 of 10 are 2560×1440; the rest are 2752×1616, 2752×1640, 2736×1616 |
| Canvas contract consistency | prompt.md·tokens.json's canvas declarations are consistent with each other and with the actual render |
ppt-motielists "16:9" and "1285×910" (=1.412) as equivalent |
| Version freshness | prompt.md·tokens.json·meta.yaml의 spec_version 3-way match |
ppt-motie prompt v4 / meta v4 / tokens v3 |
| Render freshness | The render manifest's source hash = current prompt.md+tokens.json hash |
ppt-motie 06-diagram is a different slide (map of Korea), not the spec (deep-navy arc diagram) |
| Self-contradicting instructions | Zero conflicting values for the same target and same attribute | The cover slogan is 7686pt / 6080pt / 60–72pt declared three ways |
| Forbidden self-violation | Zero conflicts between "things not to do" and body instructions | ppt-mcst Card body specified at 14pt + "24pt or below prohibited" stated at the same time |
| Font loading | Declared fonts actually load 100%, zero tofu (口) | Calligraphy silently falls back to a generic sans-serif |
| Text clipping | clipping·overflow 0건 | The card's last row goes outside the container |
| Contrast | Role-specific criteria in the "Contrast and Source Fidelity" section below | White labels on a light sky-blue map (≈1.9:1) with no declaration |
| Chart data | Values, units, and order match the original 100%; bar y-axis starts at 0 | Exaggerating differences with a truncated axis |
| Page ID consistency | pages/ Filename, order, and kind match the meta.yaml·catalog.jsonmatches |
Named 05-chart but is actually a diagram |
Contrast and Source Fidelity — Split by Role
Here the rules conflict. ppt-design-idioms는 Treat accessibility as one of the three exceptions where deviation from the original is allowed, but actual reference decks use low contrast as intentionally as a design device — Krafton's ghost table of contents (inactive items #1A1A1A on black, about 1.2:1) is a case where the active/inactive contrast itself is the table-of-contents grammar, and Samsung Bio, POSCO, and Shinhan each have their own intentional low-contrast points.
"Correct everything" and "leave everything as is" are both wrong. Divide by the role of the text.
| Role | Criterion | Basis |
|---|---|---|
| Meaning-bearing text — body text, data labels, axes, table figures, CTAs, sole information sources | 4.5:1 (3:1 for large text) hard fail | if it cannot be read, the information disappears |
| Intentional de-emphasis — inactive table-of-contents items, decorative background watermarks, duplicate elements where the same information fully exists elsewhere | No lower bound. However, declaration is mandatory | the low contrast itself conveys meaning (inactive) |
To keep low contrast, the pack must declare it. transform_contractLow contrast that does not leave the following in is not an exception but a defect:
{ "element_id": "toc-inactive", "action": "preserve",
"role": "decorative-deemphasis",
"contrast": { "measured": "1.2:1", "below_aa": true },
"justification": "활성/비활성 대비가 목차 문법. 같은 정보가 활성 상태로 다른 페이지에 존재",
"accessibility_note": "이 팩 사용 시 해당 요소에 정보를 의존하지 말 것" }
craft-qa treats undeclared text below 4.5:1 as a hard fail, and for declared text it only checks whether the role is actually de-emphasis(preventing body text from being disguised as de-emphasis).
Group B — Visual inspection (0–4 points × 6 items, 24 points)
Only what machines cannot catch. Look directly at the render and score it.
| Item | What to look at | 4점 | 0점 |
|---|---|---|---|
| C1 Grid snap | Do the edges of key elements snap to the declared grid | 95% or more within 2px | 3-up cards each have different heights |
| C2 Optical alignment | Visual center, not mathematical center | Icons and glyphs optically corrected | Play triangle sits low inside the circle |
| C3 Korean line breaking | Zero mid-word/mid-eojeol breaks, no widows | Breaks at eojeol boundaries | "memory semi / conductor", "dis / play" |
| C4 Spacing rhythm | Are repeated gaps and paddings token multiples | Coefficient of variation ≤10% | Card padding mixed at 24/31/44px |
| C5 Density balance | Does the share occupied by meaning elements match the declared space axis | airy 3065% / balanced 5080% / dense 70~90% | Dead void in the bottom-center 25% |
| C6 Data ink | In charts, (meaning marks + direct labels) / all elements | ≥0.70, gridlines ≤3 | Legend, grid, and background darker than the data |
C3 is the biggest weakness of the Korean pack. English-based line-breaking logic ignores Korean eojeol and breaks them. word-break: keep-alland eojeol-unit checking as the default.
Pass condition
A군 hard fail = 0
AND B군 총점 ≥ 19 / 24
AND 전 항목 ≥ 2
Inspection input
Do not judge by looking at the PNG alone. When possible, structural datais read together.
- Web track — when rendering, dump the DOM computed style and measure contrast, fonts, and spacing
- PPT track — native
.pptxwhen generating, measure shape coordinates and font list from the XML, confirm 0 objects outside the slide - If neither is possible, state
structural_check: unavailableexplicitly and leave some of Group A asunverified—passdo not upgrade to
Deliverables
_workspace/{batch}/craft_qa/{slug}.json
{ "slug": "...", "hard_fails": [],
"checks_A": { "canvas_uniform": "pass", "version_sync": "pass",
"render_fresh": "pass", "contrast": "pass", "fonts": "pass" },
"scores_B": { "C1": 4, "C2": 3, "C3": 4, "C4": 3, "C5": 3, "C6": 4 },
"total_B": 21, "verdict": "pass",
"structural_check": "pptx-xml",
"repair_requests": [] }
Do not do
- Padding out Group A by eye. Aspect ratio, hash, and contrast are to be measured, not looked at.
- Overall comments like "generally clean." Write per-item scores and failure coordinates.
- Using lack of time/limit as a reason for passing.
needs_reviewis the honest answer.