FilmForge Frame QA
Nothing goes into the film on a thumbnail. Every painting is read at full size against its sheets, measured by the tools, scored, and given one of three verdicts. The verdict always says what happens next and what it costs: accept (free), fix in code (free, with the exact call), or repaint (2.75 credits, with the corrected prompt).
Paths: scripts/, templates/ and config/ below are folders inside this skill (the base directory shown when it loads), put there by ./install.sh. Working from a clone of the repository, they are tools/, templates/ and config/ at its root.
The procedure
- Contact sheet of the batch, to see it as a sequence (do neighbours cut together?):
python3 scripts/contact_sheet.py build art/film --shotlist shotlist.yaml --out out/contact_sheet.jpg - Full view of each painting (read the image itself, not the sheet).
- 100% crops of what matters: faces, hands, the scale-critical subject, anything small.
python3 scripts/contact_sheet.py zoom art/film/s03_x.png --out-dir out/zoom --grid 2x2or--box x0,y0,x1,y1. An image reader downsamples large images; crops show the real pixels. - Measure colour rules, palette and exposure:
python3 scripts/ledger.py palette continuity.yaml --paintings art/film --shotlist shotlist.yamlIt reports each painting's palette, its distance (delta E) from the scene's colour script, every forbidden-colour rule's share of the frame, and exposure jumps in stops between neighbours of one scene. - Score the rubric (below): nine criteria, 0 to 2.
- Decide the verdict by the rules below.
- Write the entry in
qa.yaml(format below), then rebuild the contact sheet with--qa qa.yamlfor badges. - Report: the verdict counts, each fix and repaint in one line, credits a repaint would cost.
The rubric (templates/qa-rubric.md has the score anchors)
| Criterion | What you check |
|---|---|
| identity | faces and costume markers against the sheets |
| anatomy | hands, eyes, limbs on the focal subject |
| scale | every scale lock and every count (measure pixels in the crops) |
| style | the look lock: medium, line, colour, texture |
| colour | the colour script and forbidden rules (from ledger.py palette) and exposure against neighbours |
| continuity | every prop and state the ledger lists for this shot, and nothing outside its span |
| story | the beat reads in two seconds |
| composition | framing as listed, the eye lands on the subject, the text area quiet |
| clean | no painted text, watermark, smear or stray figure |
Measuring scale: in a crop, measure the subject and its reference in pixels and compare the ratio with the scale lock. The engine's example: the moth spans 20 px on a 60 px finger, where its lock says a whole open hand (120 px or more at that framing): a sixth of its size, scale 0, repaint.
The verdict rules
- accept: no criterion at 0, total 15 of 18 or more, no measured violation.
- fix: every fault has a code fix (table below) and nothing at 0 on identity, scale or story.
- repaint: identity, scale or story at 0; anatomy at 0 on the focal subject; style at 0; or three or more faults.
Fix in code before credits (painted-film-pipeline modules)
| Fault | Module and call |
|---|---|
| one object in a wrong hue (a scarf that makes a side character read as the hero) | grade.py IN OUT recolor:x0:y0:x1:y1:lo:hi:new_hue:sat |
| a forbidden colour leaking (blue before the ending) | grade.py IN OUT blue:0.3 (pulls the band toward silver; keep=0.3) or recolor to an allowed hue |
| a stray figure in a clean area | a patch from a shifted clean region (the fix_s22.py pattern) |
| bad crop, tangent, wrong headroom | the shot's crop: [x0, y0, x1, y1] in source pixels |
| exposure or contrast off its neighbours | automatic: the matched grade maps each plate's 0.5 and 99.5 percentile luminance to shared targets |
| soft detail | automatic: Lanczos 4K upscale with sharpening only on edges |
| a lifeless frame | motion in code (forge-motion), never a repaint |
Each fix writes a new file (_g), is re-measured, and gets done: true only when the measurement passes.
Details and parameter meanings: references/code-fixes.md.
Repaint: diagnose, then correct
Name the cause as a prompt slot or a reference: "scale lock missing from slot 4", "sheet attached in the wrong order", "look paraphrased". Write the corrected prompt in full, check the budget, and hand it to forge-painter. If the cause would hit other shots (a lock missing from the ledger), say so: it is an engine change, not one repaint.
qa.yaml entry format
- shot: s02
file: art/film/s02_last_match.png
checked: [full frame, zoom 2x2 at 100%, ledger palette]
scores: {identity: 1, anatomy: 2, scale: 2, style: 2, colour: 0, continuity: 2, story: 2, composition: 2, clean: 2}
total: 15
max: 18
measured: {no_gold_pct: 4.4, script_dE: 5}
verdict: fix
notes: A gold glow from the match covers 4.4% of the frame (the rule allows 2% before s05) and tints the hood.
fix:
problem: gold glow, hue 38 to 58
module: painted-film-pipeline pipeline/grade.py (recolor)
call: python grade.py s02_last_match.png s02_last_match_g.png recolor:250:250:700:650:38:58:22:0.8
params: {box: [250, 250, 700, 650], hue_band: [38, 58], new_hue: 22, sat: 0.8}
why_not_repaint: one hue band in one box
verify: ledger.py palette shows no-gold under 2.0% on the _g file; the hood reads red at 100%
done: false
A repaint entry has repaint: {cause, prompt_changes, credits, corrected_prompt} instead of fix.
Worked findings from real productions
- Scale (repaint): five Simorgh frames drew the hoopoe too small beside the girl (s21, s25, s33, s36, s39). Code cannot enlarge a painted subject convincingly; they were scheduled for repaint at his true size, and the cause (no scale ratio in prompts or on the sheets) became an engine rule.
- Colour (fix): blue crept into frames before the ending; a band pull toward silver fixed them in code.
- Identity by colour (fix): a side character's scarf matched the hero's colour, so he read as her; a hue-band recolour inside a box moved it.
- Stray figure (fix): an extra painted figure in a quiet frame was patched out from shifted clean regions.
- The picture book's gate: faces match the references; the right look and colour-script colours; the text area really calm; the page's motif present; it makes you feel the line of text it sits with. One fail, redone.
Never
- Accept from a thumbnail or a contact sheet alone.
- Repaint what code can fix, or "fix" in code what makes the story wrong.
- Pass a painting whose measured rule fails, even if it looks fine.
Gate checklist (for the batch)
- Every painting read full size, with crops of faces, hands and scale-critical subjects
-
ledger.py paletterun; every error explained in a verdict - Every painting has a qa.yaml entry with scores, verdict and the next action
- Contact sheet rebuilt with badges and looked at
References
references/code-fixes.md: each fix's parameters, how to choose them, and how to verify