Install
openclaw skills install @harven-droid/hatch-petTurn any keyword—animal, character, brand, object, or style—into a complete installable Codex pet package. Use when a user says ‘生成 Codex 宠物’, ‘做一个宠物包’, ‘Codex pet’, or provides a keyword or reference image and wants one-click pet creation, repair, upgrade, validation, packaging, or installation. Produces Codex-compatible v2 pets with all 9 standard animation rows, 16 look directions, deterministic QA, and spriteVersionNumber 2 packaging.
openclaw skills install @harven-droid/hatch-petInput one keyword or attach a reference image, then generate a complete Codex pet package that can be installed directly. The keyword can be an animal, character, brand, object, mood, or visual style. Every newly hatched pet is an 8x11 v2 atlas with the 9 standard animation rows plus 16 clockwise look directions and is packaged with spriteVersionNumber: 2.
Examples:
$hatch-pet 黑猫$hatch-pet 做一个森林精灵风格的 Codex 宠物$hatch-pet 把这张角色图变成可安装的 Codex 宠物包$hatch-pet upgrade my existing Totoro pet to v2 with looking directionsTreat the request as one-click creation unless the user explicitly asks to review intermediate choices. Infer a friendly name, description, and suitable style when omitted. Deliver an installed pet folder and, when requested, a clean shareable ZIP containing only pet.json and spritesheet.webp.
User-facing inputs are optional. If the user omits a pet name, infer one from the concept, brand, company, or reference filenames; if that is not possible, choose a short friendly name. If the user omits a description, infer one from the concept or references. If the user omits reference images, generate the base pet from text first, then use that base as the canonical reference for every animation row.
Treat character art, generated images, standard or v2 atlases, contact sheets, and built-in pet art as first-class grounding inputs.
0-8 intermediate after deterministic and visual validation, then generate rows 9-10 and package the result as v2.--neutral-cell; otherwise use the approved idle/default frame. The 16 directional cells never treat 000 as neutral.Use $imagegen for all normal visual generation.
Before generating base art, row strips, or repair rows, load and follow the installed image generation skill:
${CODEX_HOME:-$HOME/.codex}/skills/.system/imagegen/SKILL.md
Do not call the Image API, image CLI, or any other image-generation path directly. Let $imagegen choose its own built-in-first path and fallback rules. If $imagegen says a fallback requires confirmation, ask the user before continuing.
When invoking $imagegen, pass the generated pet prompt as the authoritative visual spec. Pet prompts should stay concise, state-specific, sprite-production oriented, and grounded in the listed input images. Keep longer policy and QA rules in this skill and the deterministic review scripts rather than expanding them into every image prompt. Do not wrap prompts in the generic $imagegen shared prompt schema.
Use this skill's scripts for deterministic image work only: preparing layout guides and prompts, mirroring approved running-left, extracting frames, validating rows, composing the final atlas, and creating contact-sheet plus motion-preview QA media. Parent-owned shell/jq steps handle manifest updates, packaging, and cleanup.
Before running any bundled script, call load_workspace_dependencies. Set PYTHON to the exact Python executable path returned by that tool and use "$PYTHON" for every command below. The bundled runtime includes Pillow, which these scripts require. Do not use a bare system python; if workspace dependencies are unavailable, stop and report that the bundled runtime is required.
The built-in $imagegen path stores generated PNG bytes in the rollout that invokes it, even when it also writes a file under ${CODEX_HOME:-$HOME/.codex}/generated_images. Deleting files later reduces filesystem use, but it does not shrink an already-written rollout. Keep image generation isolated and bounded:
selected_source=... and qa_note=...; they must not include Markdown image previews, base64, or extra visual attachments in their final response.decoded/, remove the selected original from ${CODEX_HOME:-$HOME/.codex}/generated_images when it lives there, then remove its now-empty generation directory if possible.$imagegen CLI fallback when available. That path requires local API credentials and explicit user confirmation, but it can avoid built-in image payloads being embedded in rollout events.If the user provides a brand, company, product, or prospect name rather than a concrete avatar description or reference image, run a lightweight discovery subagent before preparing the pet run. The discovery worker must use web search and prefer official sources such as the brand site, product pages, docs, about pages, press pages, or brand pages. Use reputable secondary sources only when official pages are too thin. Keep the search narrow: enough to extract visual and personality cues, not a market-research brief.
Skip discovery when the user already provides a concrete mascot/avatar description or reference images, unless the user explicitly asks for brand research.
Discovery worker responsibilities:
Generation handoff section containing only brand_name, brand_brief, avatar_seed, avoid, and brand_sourcesUse this discovery worker prompt:
Research a brand for hatch-pet mascot creation.
Brand/product/prospect: <brand name>
User context: <short user request>
Output file: <absolute path to brand-discovery.md>
Use web search. Prefer official brand, product, docs, about, press, or brand pages. Use reputable secondary sources only if official sources are too thin. Write an adaptive markdown brief to the output file. Headings may flex by brand, but the brief must cover:
- identity/category: canonical name, product type, what it does
- audience/use context: who it serves and where it appears
- visual system: palette, shapes, line quality, materials, typography feel, iconography, patterns
- personality/tone: emotional traits, energy, formality, playfulness
- product/domain motifs: objects, workflows, verbs, metaphors, environments
- mascot translation cues: candidate forms, signature traits, props, what must read at pet size
- avoidances: logos/text, trademark-sensitive elements, misleading cues, competitor confusion, poor mascot fits
- evidence/confidence: source URLs plus notes where evidence is weak or inferred
Do not copy logos, readable marks, UI screenshots, slogans, or text. Clearly label mascot guidance that is inferred rather than directly sourced.
End the brief with a `Generation handoff` section containing exactly:
- brand_name=<canonical brand/product name>
- brand_brief=<one sentence, max 45 words, covering palette/tone/domain motifs/personality>
- avatar_seed=<short mascot-safe visual idea, no logo copying>
- avoid=<short comma-separated list>
- brand_sources=<comma-separated source URLs>
Return exactly:
brand_discovery_file=<absolute output file path>
brand_name=<canonical brand/product name>
brand_brief=<same compact sentence from Generation handoff>
avatar_seed=<same short seed from Generation handoff>
avoid=<same short avoid list from Generation handoff>
brand_sources=<same comma-separated URLs from Generation handoff>
The parent should save the markdown brief before preparing the run, then pass it to prepare_pet_run.py as --brand-discovery-file together with --brand-name, --brand-brief, repeated --brand-source, and a concise --pet-notes value based on avatar_seed when the user did not provide a better avatar description. Keep the full brief for review; only the compact handoff fields should shape prompts. If web search is unavailable and the user gave only a bare brand name, ask for brand cues before generating.
Expect up to 13 visual jobs: 1 base pet, 9 standard row strips, 1 required four-cardinal anchor strip, and 2 required coherent look-direction row strips. The standard states are idle, running-right, running-left, waving, jumping, failed, waiting, running, and review. The only deterministic visual derivation is running-left, which may be produced by mirroring running-right only after running-right has been generated, visually inspected, and explicitly approved as safe to mirror. If mirroring is not appropriate, generate running-left as a normal grounded $imagegen row.
After validating rows 0–8, write qa/look-mechanics.md, then generate and approve one four-pose cardinal strip in this fixed order: 000 up, 090 screen-right, 180 down, and 270 screen-left. Generate row 9 as one coherent eight-pose family from those approved cardinal pose families, interpolating the intermediate directions as even 22.5-degree steps. Deterministically register its eight ordered pose groups, then run final-cell edge, semantic, and continuity QA immediately. Only after row 9 passes, generate row 10 as one coherent eight-pose family, using the approved cardinals for direction meaning and completed row 9 for identity, scale, registration, and boundary continuity. Run the same QA immediately after row 10. Row 9 contains 000, 022.5, 045, 067.5, 090, 112.5, 135, and 157.5; row 10 contains 180, 202.5, 225, 247.5, 270, 292.5, 315, and 337.5. 000 means up, not neutral/front. Never ask $imagegen to generate or repair a complete 8×11 atlas.
After selecting a visual output, the parent agent copies that exact image into the job's decoded/ path, runs its required incremental checks, and only then marks the job complete in imagegen-jobs.json. Do not write helper scripts that populate row outputs. The deterministic Python scripts may only process already-generated visual outputs.
Only the base job may be prompt-only. Every row-strip job generated through $imagegen must use the input images listed in imagegen-jobs.json, including the canonical base reference created after the selected base output is copied. Treat any row generation without attached grounding images as invalid.
Default style is auto: infer the pet's style from the user's prompt and references, then preserve that style across every row. If the user names a style, honor it. Supported style presets include pixel, plush, clay, sticker, flat-vector, 3d-toy, painterly, brand-inspired, and auto.
Any style is acceptable when it remains pet-safe:
192x208 cellNon-pixel styles are first-class. Plush, clay, sticker, vector, 3D toy, painterly mascot, ink, and brand-inspired looks should be accepted when they satisfy the atlas and readability constraints.
Pet rows are processed into transparent 192x208 cells, so every generated pixel must either belong to the pet sprite or be cleanly removable chroma-key background. Prefer pose, expression, and silhouette changes over decorative effects.
The deterministic raster pipeline owns the transparency and chroma-cleanup invariants. Its final edge-local spill-suppression step selects every translucent silhouette-boundary pixel plus opaque boundary pixels whose chroma points toward the known key, then extends clean interior RGB outward through that band in linear light. It preserves alpha exactly, clears hidden RGB under fully transparent pixels, and reports the algorithm and parameters used. The cleanup report plus atlas validator are authoritative for chroma contamination. Once the final report has ok: true and atlas validation passes, do not regenerate imagery or add another chroma-cleanup pass.
Fully transparent pixels are allowed outside the sprite silhouette, in unused cells, and in intentional negative-space openings that are part of the pet's design, such as loops or holes in a ribbon body. Reject any generated or repaired cell with accidental 100%-transparent holes inside a filled body, including horizontal bands, seam rows, scanline-like gaps, sliced-tile boundaries, or "see-through" interior stripes. Inspect suspect cells on a high-contrast background or alpha mask before accepting them; ordinary atlas validation is not enough when the hole is inside the silhouette.
Allowed effects must satisfy all of these conditions:
192x208 without clutter.Avoid these by default because they usually break transparent-background cleanup or component extraction:
State-specific guidance:
idle: keep this calm and low-distraction. Use only subtle breathing, a tiny blink, a slight head or body bob, a very small material sway, or another quiet persona-preserving motion. The loop must still contain visible micro-variation; do not accept six effectively identical copies. Do not show waving, walking, running, jumping, talking, working, reviewing, emotional reactions, large gestures, item interactions, or new props.waving: show the wave through paw, hand, wing, or limb pose only. Do not draw wave marks, motion arcs, lines, sparkles, symbols, or floating effects around the gesture.jumping: show vertical motion through body position only. Do not draw shadows, dust, landing marks, impact bursts, bounce pads, or floor cues.failed: tears, attached smoke puffs, or attached stars are allowed if they obey the allowed-effects rules; do not use red X marks, floating symbols, detached smoke, detached stars, or separate tear droplets.waiting: show that Codex needs approval, help, or user input through an expectant asking pose. Keep it distinct from ordinary idle and review.running: show active task work, processing, thinking, scanning, typing, or focused effort. Do not show literal foot-running, jogging, sprinting, treadmill motion, raised knees, long steps, pumping arms, directional travel, speed lines, dust clouds, floor shadows, motion trails, or detached motion effects.review: show focus through lean, blink, eyes, head tilt, or paw/hand position. Do not add magnifying glasses, papers, code, UI, punctuation, symbols, or other new props unless they already exist in the base pet identity.running-right and running-left: show directional drag movement through body, limb, and prop movement only. running-right must face and travel right; running-left must face and travel left. Their cadence must visibly alternate across the loop rather than repeating one nearly static stride. Do not draw speed lines, dust clouds, floor shadows, motion trails, or detached motion effects.For every pet run, keep a visible checklist so the user can see where the work is up to. Create the checklist before starting, keep one step active at a time, and update it as each step finishes.
Use this checklist for every v2 pet run, replacing <Pet> with the pet's name or your pet:
<Pet> ready.<Pet>'s main look.<Pet>'s poses.<Pet>.What each step means:
Getting <Pet> ready. Choose or confirm the pet name, description, source images, style preset, style notes, and working folder. For bare brand/product/company requests, first run the brand discovery worker and capture the compact brand brief, source URLs, and avatar seed.Imagining <Pet>'s main look. Generate the pet's main reference image. This becomes the visual source of truth.Picturing <Pet>'s poses. Generate and approve rows 0-8, write the pet-specific look mechanics plan, then generate rows 9-10. Only mirror running-left if running-right clearly works when flipped.Hatching <Pet>. Assemble the 8x11 atlas, review standard motion plus all 16 look directions, fix every failed cell or row, package spriteVersionNumber: 2, and report the output paths.Only mark a step complete when the real file, image, or decision exists. If this is a repair run, start from the first relevant step instead of restarting the whole checklist.
Aim to complete a normal pet run within 30 minutes while preserving every mandatory acceptance criterion. Treat this as a planning target and an incentive to maximize validated progress per minute, not as permission to weaken QA or package a failing pet.
At the start of the run, allocate an approximate budget:
Run independent generation jobs concurrently up to the worker limit, start deterministic checks as soon as each dependency is ready, and record actual stage plus repair time. Prefer character and prop constructions that naturally satisfy cell geometry, transparency, component connectivity, and direction semantics; identify likely conflicts such as open interior gaps, detached parts, thin connectors, asymmetric props, or ambiguous faces before row generation.
After every failed attempt:
If the same root failure recurs twice, stop varying the prompt and change strategy: strengthen the cardinal pose families or row-level direction instructions, simplify the pose or prop construction, change the deterministic extraction method, or redesign the problematic visual feature. If a repair merely moves a failure to another cell or gate, treat that as a cycle and change strategy immediately.
Use elapsed-time checkpoints:
Never use the time target to skip blind direction QA, labeled semantics, continuity review, atlas validation, despill validation, final visual QA, or any other acceptance criterion.
SKILL_DIR="${CODEX_HOME:-$HOME/.codex}/skills/hatch-pet"
"$PYTHON" "$SKILL_DIR/scripts/prepare_pet_run.py" \
--pet-name "<Name>" \
--description "<one sentence>" \
--reference /absolute/path/to/reference.png \
--output-dir /absolute/path/to/run \
--pet-notes "<stable pet description>" \
--brand-discovery-file /absolute/path/to/brand-discovery.md \
--brand-name "<optional researched brand name>" \
--brand-brief "<optional compact researched brand cue sentence>" \
--brand-source "https://example.com/source" \
--style-preset auto \
--style-notes "<optional freeform style notes>" \
--force
All arguments above are optional except any flags needed to express user constraints. For text-only requests, pass the concept through --pet-notes and omit --reference; prepare_pet_run.py will infer a name, description, chroma key, and output directory as needed.
For brand-only requests, run the discovery worker first, save the markdown brief, then pass the brief path through --brand-discovery-file, avatar_seed through --pet-notes, brand_name through --brand-name, brand_brief through --brand-brief, and each source URL through repeated --brand-source.
imagegen-jobs.json for the next ready $imagegen jobs. A job is ready when its status is not complete and every id in depends_on is already complete. Prefer reading the manifest directly with jq or the editor instead of adding helper scripts for status display:jq '.jobs[] | {id, kind, status, depends_on, prompt_file, retry_prompt_file, input_images, output_path, derivation_policy}' /absolute/path/to/run/imagegen-jobs.json
base first, using a lightweight base worker.idle and running-right next as the identity and gait check, using one lightweight worker per row.running-right; mirror running-left only when visual identity, prop placement, markings, lighting, and direction semantics remain correct.running-left normally with a lightweight worker when mirroring would change meaning or identity.look-cardinals as one four-pose strip, extract it into decoded/look-anchors/000.png, 090.png, 180.png, and 270.png, and approve all four. The 090 and 270 anchors must be unmistakable in viewer/screen coordinates and visibly oppose each other.Keep up to three generation workers active whenever three independent jobs are ready and worker capacity permits. Backfill an available slot immediately instead of waiting for a fixed wave to finish. Use two or one worker when the dependency graph exposes fewer ready jobs. Do not exceed three generation workers without explicit user direction.
For each ready visual job, invoke $imagegen with the prompt file listed in imagegen-jobs.json, every listed input image with its role label, and the default built-in image_gen path unless $imagegen itself routes otherwise. The parent agent must keep its own image handling minimal: do not open every generated base or row in the parent rollout. Workers return only the selected source path and a one-sentence QA note; the parent records the selected source path in the manifest.
prepare_pet_run.py creates matching layout guides under references/layout-guides/ for the nine standard rows, two look rows, and four-cardinal strip, and both look rows. Visual jobs attach the matching guide as a layout-only input so the model can follow the correct frame count, spacing, centering, and safe padding. Treat these guides as invisible construction references: generated strips must not include visible boxes, borders, center marks, labels, guide colors, or the guide background.
When generating row strips, keep the identity lock in the row prompt authoritative. Preserve the same style, face, markings, palette, materials, prop design, body proportions, and silhouette from the canonical base. Row jobs attach the layout guide and canonical base by default; the decoded base is kept in the run folder for deterministic processing rather than sent as a redundant generation input.
If $imagegen returns a transport-level Bad Request for a row, retry that same row once with its generated retry_prompt_file. The retry prompt preserves the row id, frame count, chroma key, canonical-base identity, and state action. Keep the canonical base attached. If the retry still fails, stop and report the failing row and prompt paths instead of switching to any other generation path.
base, also create the canonical identity reference:RUN_DIR=/absolute/path/to/run
JOB_ID=<job-id>
SOURCE=/absolute/path/to/generated-output.png
OUTPUT_REL=$(jq -r --arg id "$JOB_ID" '.jobs[] | select(.id == $id) | .output_path' "$RUN_DIR/imagegen-jobs.json")
mkdir -p "$(dirname "$RUN_DIR/$OUTPUT_REL")"
cp "$SOURCE" "$RUN_DIR/$OUTPUT_REL"
if [ "$JOB_ID" = "base" ]; then mkdir -p "$RUN_DIR/references"; cp "$RUN_DIR/$OUTPUT_REL" "$RUN_DIR/references/canonical-base.png"; fi
For every standard row-strip job, immediately extract and inspect only that row before marking the job complete. This overlaps deterministic QA and any repair with generation of other ready rows instead of waiting for all nine rows:
ROW_QA_DIR="$RUN_DIR/qa/rows/$JOB_ID"
"$PYTHON" "$SKILL_DIR/scripts/extract_strip_frames.py" \
--decoded-dir "$RUN_DIR/decoded" \
--output-dir "$ROW_QA_DIR/frames" \
--states "$JOB_ID" \
--method auto
"$PYTHON" "$SKILL_DIR/scripts/inspect_frames.py" \
--frames-root "$ROW_QA_DIR/frames" \
--json-out "$ROW_QA_DIR/review.json" \
--states "$JOB_ID" \
--require-components
Treat errors as an immediate repair request. Inspect warnings before accepting the row; do not defer a known clipping, component, or extraction problem to final atlas QA. Chroma cleanup belongs to the deterministic post-assembly despill pass and must not trigger row regeneration. If the only failure is component extraction and the source strip itself has stable scale and placement, use the existing stable-slots correction with --allow-stable-slots instead of regenerating imagery.
For look-cardinals, extract and validate all four anchors before marking the job complete:
CHROMA_KEY=$(jq -r '.chroma_key.hex' "$RUN_DIR/pet_request.json")
"$PYTHON" "$SKILL_DIR/scripts/extract_cardinal_anchors.py" \
--strip "$RUN_DIR/decoded/look-cardinals.png" \
--output-dir "$RUN_DIR/decoded/look-anchors" \
--chroma-key "$CHROMA_KEY" \
--json-out "$RUN_DIR/qa/cardinal-anchors.json"
"$PYTHON" "$SKILL_DIR/scripts/compose_cardinal_anchor_strip.py" \
--anchors-dir "$RUN_DIR/decoded/look-anchors" \
--output "$RUN_DIR/decoded/look-anchors-approved.png"
Approve the four extracted anchors semantically at final pet size. If one cardinal fails, regenerate that individual anchor with prompts/look-anchor-repairs/<degree>.md, replace only its extracted file, and rerun compose_cardinal_anchor_strip.py. Both final look rows use the approved cardinal strip, and row 10 additionally uses completed row 9. Mark the job complete only after its required deterministic and visual checks pass:
UPDATED_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)
TMP_MANIFEST=$(mktemp)
jq --arg id "$JOB_ID" --arg source "$SOURCE" --arg at "$UPDATED_AT" '(.jobs[] | select(.id == $id)) += {status: "complete", source_path: $source, completed_at: $at}' "$RUN_DIR/imagegen-jobs.json" > "$TMP_MANIFEST"
mv "$TMP_MANIFEST" "$RUN_DIR/imagegen-jobs.json"
After decoded/look-anchors-approved.png exists and all four cardinals have passed semantic review, mark look-cardinals complete. Row 9 then becomes ready immediately.
If the copied source is under ${CODEX_HOME:-$HOME/.codex}/generated_images, delete the original generated file after the decoded copy exists:
GENERATED_ROOT="${CODEX_HOME:-$HOME/.codex}/generated_images"
case "$SOURCE" in
"$GENERATED_ROOT"/*)
rm -f "$SOURCE"
rmdir "$(dirname "$SOURCE")" 2>/dev/null || true
;;
esac
running-left only when it is visually safe:"$PYTHON" "$SKILL_DIR/scripts/derive_running_left_from_running_right.py" \
--run-dir /absolute/path/to/run \
--confirm-appropriate-mirror \
--decision-note "<why mirroring preserves this pet's identity>"
That script mirrors each generated frame slot in place so the leftward row preserves the rightward row's temporal order. Do not replace it with a whole-strip mirror that reverses animation timing.
0-8:RUN_DIR=/absolute/path/to/run
mkdir -p "$RUN_DIR/final" "$RUN_DIR/qa"
"$PYTHON" "$SKILL_DIR/scripts/extract_strip_frames.py" \
--decoded-dir "$RUN_DIR/decoded" \
--output-dir "$RUN_DIR/frames" \
--states all \
--method auto
"$PYTHON" "$SKILL_DIR/scripts/inspect_frames.py" \
--frames-root "$RUN_DIR/frames" \
--json-out "$RUN_DIR/qa/review.json" \
--require-components
"$PYTHON" "$SKILL_DIR/scripts/compose_atlas.py" \
--frames-root "$RUN_DIR/frames" \
--output "$RUN_DIR/final/spritesheet.png" \
--webp-output "$RUN_DIR/final/spritesheet.webp"
"$PYTHON" "$SKILL_DIR/scripts/make_contact_sheet.py" \
"$RUN_DIR/final/spritesheet.webp" \
--output "$RUN_DIR/qa/contact-sheet.png"
"$PYTHON" "$SKILL_DIR/scripts/render_animation_previews.py" \
--frames-root "$RUN_DIR/frames" \
--output-dir "$RUN_DIR/qa/previews"
If the preview GIFs show size popping or baseline jumps caused by per-frame fit-to-cell extraction, and the original row strip itself had stable scale and placement, rerun frame extraction with the explicit row-stability mode and then re-run inspection, atlas composition, contact sheet generation, and previews:
"$PYTHON" "$SKILL_DIR/scripts/extract_strip_frames.py" \
--decoded-dir "$RUN_DIR/decoded" \
--output-dir "$RUN_DIR/frames" \
--states all \
--method stable-slots
"$PYTHON" "$SKILL_DIR/scripts/inspect_frames.py" \
--frames-root "$RUN_DIR/frames" \
--json-out "$RUN_DIR/qa/review.json" \
--require-components \
--allow-stable-slots
Use stable-slots as a deliberate QA-driven correction, not the default. It should reduce extraction-induced motion pops without hiding clipped wide poses or bad source strips.
Expected intermediate output before the required v2 look stage:
run/
pet_request.json
imagegen-jobs.json
prompts/
decoded/
frames/frames-manifest.json
final/spritesheet.webp
qa/contact-sheet.png
qa/previews/*.gif
qa/review.json
Inspect qa/contact-sheet.png and qa/previews/*.gif before generating look rows. qa/review.json plus visual motion review are the intermediate gates. The standard contact sheet intentionally predates chroma cleanup, so visible key-color fringe there is not a failure; judge chroma only on the cleaned final v2 atlas. Block progress if any standard row changes identity, style, prop handedness, or silhouette, or if playback pops, reverses cadence, faces the wrong direction, or is visually inert. Do not package or clean up yet.
Every new pet must complete this stage. After standard-row QA passes, write qa/look-mechanics.md, approve the four cardinals, synthesize and validate the complete look-row-9, then synthesize look-row-10. Row 10 becomes ready only after row 9 is deterministically registered, clears post-registration edge checks, and has no semantic or continuity hard failure; reviewed warnings may remain. It uses row 9 plus the approved cardinal strip as continuity evidence.
Before either look row, run the prepared look-cardinals strip job, extract its four cells with extract_cardinal_anchors.py, and approve them. Do not let a two-row sweep invent its own left/right basis. 090 must point toward the viewer's screen-right edge and 270 toward the viewer's screen-left edge; for faces, the nose tip and pupils must cross to the corresponding side of the head center. If one cardinal is ambiguous, regenerate only that anchor before continuing.
After copying row 9 into decoded/look-row-9.png, register and edge-check it with the same transform used by final assembly:
"$PYTHON" "$SKILL_DIR/scripts/assemble_extended_atlas.py" \
--base-atlas "$RUN_DIR/final/spritesheet.webp" \
--look-row-9 "$RUN_DIR/decoded/look-row-9.png" \
--neutral-cell "$RUN_DIR/frames/idle/00.png" \
--chroma-key "$CHROMA_KEY" \
--chroma-threshold 96 \
--registered-row-output "$RUN_DIR/qa/look-row-9-registered.png" \
--registration-manifest-output "$RUN_DIR/qa/look-row-9-registration.json"
Inspect the eight registered cells at normal pet size in 000 through 157.5 order. Record the row-9 semantic and adjacent-continuity review, resynthesize the complete row for any hard failure, and mark look-row-9 complete only after this check passes. That completion makes row 10 ready in imagegen-jobs.json.
Generate only the additional look-direction visuals with $imagegen:
000 -> 090 -> 180, then give completed row 9 to row 10 so 180 begins exactly one step after 157.5. Row 10 follows 180 -> 270 -> 000, and 337.5 in row 10 must land one step before the approved 000 in row 9.157.5 -> 180, 337.5 -> 000, and any row-strip boundary. Anchored parts must not jump, flip sides, or teleport between adjacent states; if a body part moves laterally, bends, stretches, or rotates, its position should progress gradually across the intervening directions.000 must clearly read as looking up, 090 as looking right, 180 as looking down, and 270 as looking left using the pet's natural mechanism. If the pet has no pupils or physical eyeballs, the head, face surface, eyelids, antennae, ears, or body bend must carry the direction clearly enough that a viewer can identify the cardinal without labels.270 cardinal that does not unmistakably read as left.000, 090, 180, and 270 together as one strip, then extract and approve them. The final look rows use those four pose families for direction meaning and interpolate the intermediate directions as a coherent arc. Define directions in viewer/screen coordinates, never character-relative coordinates. Do not require exact pupil or nose placement on intermediate poses; use the ordered loop and overall quadrant motion as the primary evidence.Direction order is fixed:
row 9: 000, 022.5, 045, 067.5, 090, 112.5, 135, 157.5
row 10: 180, 202.5, 225, 247.5, 270, 292.5, 315, 337.5
000 means looking up / 12 o'clock. Neutral/front is the pointer deadzone and should fall back to idle unless the target renderer explicitly uses a neutral cell.
Judge the completed 16-pose loop as an animation family. Cardinals must match their single axis exactly. Intermediate directions should preserve the intended axes, but isolated blind-review uncertainty is evidence for labeled loop review rather than an automatic regeneration trigger.
Hard failures require row regeneration:
000 up, 090 screen-right, 180 down, or 270 screen-left000 up, 090 screen-right, 180 down, or 270 screen-leftReview warnings do not require regeneration by themselves:
ambiguous, or produce an opposite-sign majority for an intermediate direction, provided labeled normal-size review confirms the intended direction and the ordered loop remains coherentBefore accepting the v2 atlas, create a focused direction QA sheet showing the neutral/rest frame next to all 16 look cells, labeled by degree and expected direction, at approximately the in-app display size. Run the adjacent continuity measurement separately and treat its findings as motion-review evidence, not automatic direction failures.
Perform an explicit semantic review for every direction and record pass, warning, or fail, plus separate visible evidence for its horizontal and vertical axes. A warning may accept blind-review uncertainty for an intermediate pose when labeled normal-size review confirms the intended axes and the ordered loop remains coherent. It may not waive a wrong or ambiguous cardinal, a labeled wrong-quadrant pose, or a visible reversal. If a direction receives fail, strengthen the containing row's instructions and resynthesize that complete coherent row. Never replace the final normalized cell directly.
Look rows must have transparent backgrounds after assembly. Do not accept or install the pet if qa/look-directions.png or qa/contact-sheet-extended.png shows chroma-key panels behind any look cell. If generated look rows contain slight chroma-key lighting variation, rerun assembly with a wider --chroma-threshold instead of packaging the opaque key color. Validation must pass without opaque chroma-key-pixel errors.
Extended look cells must also keep the same practical scale and body registration as the neutral/default pet. Do not accept a direction set where neutral/default is noticeably larger than the look cells, where the look cells appear to float above the baseline, or where the pet slides left/right within its 192x208 cell while only changing gaze. Extended assembly recovers each pose group from the complete original-resolution row and computes one shared scale from height plus every pose's left and right extents around the shared lower-body anchor, so asymmetric poses remain inside the final cell after alignment. It resizes each original crop exactly once and never enlarges an already-resampled cell. The neutral frame supplies the target body height, lower-body anchor, and baseline. Pass --neutral-cell when an external neutral frame is available; otherwise the assembler falls back to the populated neutral/default slot or first visible idle frame in the base atlas. If the focused QA sheet still shows scale or placement drift, repair before packaging.
Assemble the extended atlas from two generated row strips:
Use the run's selected chroma key for every assembly path; omitting it falls back to green and can misclassify a magenta background as clipped sprite pixels.
CHROMA_KEY=$(jq -r '.chroma_key.hex' "$RUN_DIR/pet_request.json")
Extended assembly reuses the approved registered row-9 cells and persisted scale exactly. It removes the chroma background from row 10, detects its eight separated pose groups, preserves their left-to-right order, crops each complete pose without fixed-slot slicing, and fits them against the same neutral-frame scale, lower-body anchor, and baseline. Only then does it apply the near-edge clipping check to row 10's normalized 192x208 cells. If pose-group recovery is ambiguous, or if row 10 cannot fit the approved row-9 transform without failing the post-registration edge check, resynthesize row 10; do not rescale row 9, patch an individual final cell, or relax the threshold for acceptance.
"$PYTHON" "$SKILL_DIR/scripts/assemble_extended_atlas.py" \
--base-atlas "$RUN_DIR/final/spritesheet.webp" \
--registered-row-9 "$RUN_DIR/qa/look-row-9-registered.png" \
--row-9-registration "$RUN_DIR/qa/look-row-9-registration.json" \
--look-row-10 "$RUN_DIR/decoded/look-row-10.png" \
--neutral-cell "$RUN_DIR/frames/idle/00.png" \
--chroma-key "$CHROMA_KEY" \
--chroma-threshold 96 \
--output "$RUN_DIR/final/spritesheet-extended.png" \
--webp-output "$RUN_DIR/final/spritesheet-extended.webp" \
--manifest-output "$RUN_DIR/final/spritesheet-extended.json"
For repair or upgrade of a user-provided 16-cell source that was already approved as one coherent set, individual-cell assembly remains available. Do not use this path for newly generated repair cells:
"$PYTHON" "$SKILL_DIR/scripts/assemble_extended_atlas.py" \
--base-atlas "$RUN_DIR/final/spritesheet.webp" \
--look-cells-dir /absolute/path/to/look-cells \
--neutral-cell "$RUN_DIR/frames/idle/00.png" \
--chroma-key "$CHROMA_KEY" \
--chroma-threshold 96 \
--output "$RUN_DIR/final/spritesheet-extended.png" \
--webp-output "$RUN_DIR/final/spritesheet-extended.webp" \
--manifest-output "$RUN_DIR/final/spritesheet-extended.json"
Run the single deterministic edge-local spill-suppression pass on the assembled v2 atlas, then validate and make a contact sheet:
"$PYTHON" "$SKILL_DIR/scripts/despill_chroma_edges.py" \
"$RUN_DIR/final/spritesheet-extended.png" \
--output "$RUN_DIR/final/spritesheet-extended.png" \
--webp-output "$RUN_DIR/final/spritesheet-extended.webp" \
--chroma-key "$CHROMA_KEY" \
--json-out "$RUN_DIR/qa/chroma-despill-extended.json"
Treat qa/chroma-despill-extended.json as the authoritative chroma result. When it has ok: true and validate_atlas.py --require-v2 passes, do not fail visual QA for perceived magenta fringe, regenerate any row, rerun despill, tune thresholds, or create an additional chroma-repair script. If either deterministic check fails, stop with a pipeline failure instead of retrying image generation.
This is the only chroma-cleanup invocation in the workflow. The intermediate 8×9 atlas is never despilled; rows 0-8 and the newly assembled look rows 9-10 are cleaned together exactly once in the completed 8×11 atlas.
"$PYTHON" "$SKILL_DIR/scripts/validate_atlas.py" \
"$RUN_DIR/final/spritesheet-extended.webp" \
--json-out "$RUN_DIR/final/validation-extended.json" \
--chroma-key "$CHROMA_KEY" \
--require-v2
"$PYTHON" "$SKILL_DIR/scripts/make_contact_sheet.py" \
"$RUN_DIR/final/spritesheet-extended.webp" \
--output "$RUN_DIR/qa/contact-sheet-extended.png"
Create the focused direction QA sheet:
"$PYTHON" "$SKILL_DIR/scripts/make_direction_qa_sheet.py" \
"$RUN_DIR/final/spritesheet-extended.webp" \
--output "$RUN_DIR/qa/look-directions.png"
Create the blind horizontal-and-vertical axis challenge and keep its answer key away from the visual QA worker:
"$PYTHON" "$SKILL_DIR/scripts/make_direction_blind_qa_sheet.py" \
"$RUN_DIR/final/spritesheet-extended.webp" \
--output "$RUN_DIR/qa/direction-blind-pairs.png" \
--answer-key "$RUN_DIR/qa/direction-blind-answer-key.json"
Give three fresh isolated workers only qa/direction-blind-pairs.png. Each row states whether to classify the horizontal or vertical axis. Every worker must classify A and B as screen-left, screen-right, up, down, or ambiguous as appropriate, without seeing degree labels, expected directions, the labeled direction sheet, the answer key, or another worker's verdicts. Write their classifications separately, then combine them by strict per-cell majority:
"$PYTHON" "$SKILL_DIR/scripts/combine_direction_blind_verdicts.py" \
--verdicts "$RUN_DIR/qa/direction-blind-verdicts-1.json" \
--verdicts "$RUN_DIR/qa/direction-blind-verdicts-2.json" \
--verdicts "$RUN_DIR/qa/direction-blind-verdicts-3.json" \
--json-out "$RUN_DIR/qa/direction-blind-verdicts.json"
Apply the hidden answer key only to the consensus verdict:
"$PYTHON" "$SKILL_DIR/scripts/validate_direction_blind_verdicts.py" \
--answer-key "$RUN_DIR/qa/direction-blind-answer-key.json" \
--verdicts "$RUN_DIR/qa/direction-blind-verdicts.json" \
--json-out "$RUN_DIR/qa/direction-blind-validation.json"
The hidden answer key contains seven horizontal pairs and seven vertical pairs. The cardinal pairs (000 vs 180 and 090 vs 270) are hard gates: a mismatch or ambiguous majority keeps validation at ok: false. All intermediate pairs are review gates: mismatches, same-direction votes, and ambiguous majorities are preserved as warnings while validation remains ok: true. The blind pass is mandatory, but intermediate warnings are resolved by labeled normal-size loop review instead of repeated regeneration by default.
After receiving a blind or final visual QA pass/fail result:
qa/direction-semantics.json, and qa/look-continuity.json before regenerating anything.major or minor:
major: wrong or ambiguous cardinal; labeled normal-size review confirms a wrong principal quadrant or visible reversal; conspicuous snap, scale pop, identity change, broken attachment, clipping, interior seam/hole, or deterministic validation failure.minor: exact pupil or nose placement differs from the numerical ideal; a near-vertical horizontal cue is subtle; isolated reviewers disagree or return ambiguous; an intermediate blind majority conflicts but the labeled ordered loop still reads correctly; continuity metrics warn without a visible defect.qa/blind-review-resolution.json with decision: "accept", severity: "minor", the failed checks, the labeled/continuity evidence that makes them acceptable, and reviewed_by: "parent" or "user". Never override a major failure.An override is a deliberate visual judgment, not a way to silence missing evidence. The blind sheet, consensus verdicts, validation output, labeled semantics, continuity report, and resolution file all remain in the final QA artifacts.
Measure adjacent direction continuity:
"$PYTHON" "$SKILL_DIR/scripts/measure_direction_continuity.py" \
"$RUN_DIR/final/spritesheet-extended.webp" \
--json-out "$RUN_DIR/qa/look-continuity.json"
Visually QA qa/contact-sheet-extended.png, qa/look-directions.png, and qa/look-continuity.json before accepting. Inspect the 16 normal-size look cells as an ordered loop, not only as isolated stills. For every direction label, compare the expected direction to the visible gaze/body direction and record pass, warning, or fail in qa/direction-semantics.json. Reject only the hard failures in the Direction Acceptance Policy. Record subtler semantic or metric concerns as warnings and accept them when the loop remains cohesive, readable, identity-preserving, and visually pleasing at normal pet size.
If a blind or final visual QA worker returns fail, apply Blind Review Severity Resolution before queuing a repair. Continue packaging when the failure is minor and qa/blind-review-resolution.json records the accepted override.
Only after all deterministic and visual QA passes, package the approved extended spritesheet as a v2 pet. spriteVersionNumber: 2 is mandatory; without it the app defaults to the 9-row v1 contract and rejects the 2288-pixel-tall asset.
PET_ID=$(jq -r '.pet_id' "$RUN_DIR/pet_request.json")
DISPLAY_NAME=$(jq -r '.display_name' "$RUN_DIR/pet_request.json")
DESCRIPTION=$(jq -r '.description' "$RUN_DIR/pet_request.json")
PET_DIR="${CODEX_HOME:-$HOME/.codex}/pets/$PET_ID"
mkdir -p "$PET_DIR"
cp "$RUN_DIR/final/spritesheet-extended.webp" "$PET_DIR/spritesheet.webp"
jq -n --arg id "$PET_ID" --arg displayName "$DISPLAY_NAME" --arg description "$DESCRIPTION" \
'{id: $id, displayName: $displayName, description: $description, spriteVersionNumber: 2, spritesheetPath: "spritesheet.webp"}' \
> "$PET_DIR/pet.json"
Write qa/run-summary.json after packaging:
jq -n --arg run_dir "$RUN_DIR" --arg spritesheet "$RUN_DIR/final/spritesheet-extended.webp" --arg validation "$RUN_DIR/final/validation-extended.json" --arg chroma_despill "$RUN_DIR/qa/chroma-despill-extended.json" --arg contact_sheet "$RUN_DIR/qa/contact-sheet-extended.png" --arg direction_sheet "$RUN_DIR/qa/look-directions.png" --arg direction_semantics "$RUN_DIR/qa/direction-semantics.json" --arg blind_direction_validation "$RUN_DIR/qa/direction-blind-validation.json" --arg blind_review_resolution "$RUN_DIR/qa/blind-review-resolution.json" --arg continuity "$RUN_DIR/qa/look-continuity.json" --arg review "$RUN_DIR/qa/review.json" --arg package "$PET_DIR" '{ok: true, spriteVersionNumber: 2, run_dir: $run_dir, spritesheet: $spritesheet, validation: $validation, chroma_despill: $chroma_despill, contact_sheet: $contact_sheet, direction_sheet: $direction_sheet, direction_semantics: $direction_semantics, blind_direction_validation: $blind_direction_validation, blind_review_resolution: $blind_review_resolution, continuity: $continuity, review: $review, package: $package}' > "$RUN_DIR/qa/run-summary.json"
After all QA and packaging succeed, keep pet_request.json, final/spritesheet-extended.webp, final/validation-extended.json, qa/chroma-despill-extended.json, qa/contact-sheet-extended.png, qa/look-directions.png, qa/direction-semantics.json, qa/direction-blind-pairs.png, qa/direction-blind-answer-key.json, qa/direction-blind-verdicts.json, qa/direction-blind-validation.json, qa/blind-review-resolution.json when an override was used, qa/look-continuity.json, qa/previews/, qa/review.json, and qa/run-summary.json. Remove prompts, layout guides, generated row strips, extracted frames, PNG intermediates, the 8x9 intermediate atlas, and the imagegen job manifest unless the user wants debug artifacts.
Use lightweight subagents for image-heavy work by default. This bounds each $imagegen rollout to one selected image, keeps contact-sheet vision payloads out of the parent thread, and reduces cost while preserving the full v2 contract.
Use lightweight workers unless the user specifically prohibits delegation.
Parent responsibilities:
imagegen-jobs.jsonimagegen-jobs.jsonreferences/canonical-base.png from the selected base outputrunning-left mirror derivation when appropriatedecoded/look-anchors-approved.pngBase worker responsibilities:
base jobprompts/base-pet.md and use any listed reference images$imagegen onlyselected_source=/absolute/path/to/selected-output.png and qa_note=<one sentence>Row worker responsibilities:
$imagegen only; do not draw, edit, tile, or synthesize sprites locallywaving, no speed lines or dust for directional running rows, no literal foot-running for the non-directional running row, and only attached opaque sprite-like tears/smoke/stars when allowed by the state promptlook-row-strip, synthesize the complete row as one coherent family from the approved cardinals and never independently restyle individual cellslook-row-strip, verify the output contains eight separated pose groups in the required order with no overlap or outer-canvas clipping; deterministic assembly owns exact cell cropping, one shared scale and baseline, recentering, and final-cell edge validationselected_source=/absolute/path/to/selected-output.png and qa_note=<one sentence>Blind direction QA worker responsibilities:
qa/direction-blind-pairs.png; do not provide the labeled direction sheet, atlas, prompt, degree order, prior verdicts, or hidden answer keyscreen-left, screen-right, up, down, or ambiguous, using visible pupils, nose, face surface, head turn, or the pet's natural aiming featureambiguous honestly when the requested axis is unreadable. Cardinal ambiguity blocks packaging; intermediate ambiguity becomes labeled-review evidence.combine_direction_blind_verdicts.pyFinal visual QA worker responsibilities:
visual_qa=pass or visual_qa=fail, plus row-specific repair notes when failingModel choice for workers:
gpt-5.4-mini with medium reasoning, when model override is available.look-cardinals passes, start row 9 immediately. Start row 10 only after row 9 has passed deterministic registration, post-registration edge, semantic, and continuity QA; give row 10 the completed row 9 strip as continuity evidence.Use this base worker prompt:
Generate the hatch-pet base image.
Run dir: <absolute run dir>
Job id: base
Prompt file: <absolute base prompt file>
Input images:
- <absolute path> — <role>
Use $imagegen only. Read the base prompt and attach every listed input image. If the prompt contains brand inspiration, use it only as broad mascot-safe guidance; do not copy logos, readable marks, UI screenshots, slogans, or text. Before returning, visually check that the result is one centered full-body pet on a flat chroma background, with no text, scenery, shadows, or detached effects.
Do not edit manifests, copy into decoded, mark jobs complete, generate rows, run image-processing scripts, repair, package, or open unrelated files.
Do not include Markdown image previews, base64, or extra attachments in the final response.
Return exactly:
selected_source=/absolute/path/to/selected-output.png
qa_note=<one sentence>
Use this cardinal-strip worker prompt:
Generate one hatch-pet four-cardinal anchor strip.
Run dir: <absolute run dir>
Job id: look-cardinals
Prompt file: <absolute prompt file>
Input images:
- <absolute path> — <role>
Use $imagegen only. Read the cardinal-strip prompt and attach every listed input image. Read `qa/look-mechanics.md`. Screen-left and screen-right are viewer/image coordinates, never character-relative coordinates. Before returning, verify all four slots in order without relying on their labels: for a face, cite the nose-tip and pupil positions relative to the head center; for other pets, cite the natural aiming feature. Any ambiguous cardinal fails the strip.
Do not edit manifests, copy files, generate rows, assemble, package, or inspect unrelated files. Do not include image previews or attachments in the final response.
Return exactly:
selected_source=/absolute/path/to/selected-output.png
qa_note=<one sentence with concrete landmark evidence for all four cardinals>
Use this row worker prompt:
Generate one hatch-pet row.
Run dir: <absolute run dir>
Row id: <row-id>
Prompt file: <absolute prompt file>
Retry prompt file: <absolute retry prompt file>
Input images:
- <absolute path> — <role>
- <absolute path> — <role>
Use $imagegen only. Read the row prompt and attach every listed input image. For a `look-row-strip` job, also read and obey `qa/look-mechanics.md`; use the approved cardinal strip for direction meaning and draw all eight cells together as one coherent family with even intermediate steps. Never paste, reuse, or independently restyle individual cells. If imagegen returns Bad Request, retry once with the retry prompt and the same input images.
Before returning, visually check: exact frame count, same pet identity as canonical base, flat chroma background, complete separated unclipped poses, and no detached effects or guide marks. For a `look-row-strip`, verify there are eight separated pose groups in the required left-to-right order, neighboring poses do not overlap, no foreground is cropped at the outer canvas edge, and the generated family keeps a consistent scale and baseline. Exact cell cropping, shared-scale normalization, recentering, and final-cell edge validation happen deterministically after generation. The prompt's transparency and effects rules are mandatory: no detached effects, no wave marks for `waving`, no speed lines or dust for directional running rows, no literal foot-running for the non-directional `running` row, and only attached opaque sprite-like tears/smoke/stars when allowed by the state prompt.
Do not edit manifests, copy into decoded, mark jobs complete, mirror rows, run image-processing scripts, repair, package, or open unrelated files.
Do not include Markdown image previews, base64, or extra attachments in the final response.
Return exactly:
selected_source=/absolute/path/to/selected-output.png
qa_note=<one sentence>
Use this blind direction QA worker prompt in a fresh worker that has not seen the labeled direction sheet. Spawn it without prior conversation context when the worker system supports context isolation (for example, fork_turns="none"):
Classify one required gaze axis in an unlabeled hatch-pet A/B challenge.
Blind sheet: <absolute run dir>/qa/direction-blind-pairs.png
Inspect only this sheet. Do not open the atlas, labeled direction sheet, prompts, prior QA, degree order, answer key, or any other file.
Each row contains two normal-size pet cells labeled A and B and identifies the axis to judge. For a horizontal row, classify each cell as exactly `screen-left`, `screen-right`, or `ambiguous`. For a vertical row, classify each cell as exactly `up`, `down`, or `ambiguous`.
Judge only what is readable at the displayed pet size. Use visible landmarks such as pupils, nose tip relative to head center, face surface, head turn, eyelids, or the pet’s natural aiming feature. If the requested axis is not definite without enlarging or guessing, classify it as `ambiguous`; do not invent confidence.
Do not infer from A/B order. If A and B point the same way, report the same classification; do not force one left and one right.
Return exactly one JSON object and nothing else:
{"pairs":[{"pair":"horizontal-1|vertical-1","A":"screen-left|screen-right|up|down|ambiguous","B":"screen-left|screen-right|up|down|ambiguous","reason":"short landmark evidence"}]}
Include every pair shown in the sheet.
Use this final visual QA worker prompt:
Visually QA one finalized hatch-pet contact sheet.
Run dir: <absolute run dir>
Contact sheet: <absolute run dir>/qa/contact-sheet.png
V2 contact sheet: <absolute run dir>/qa/contact-sheet-extended.png
Focused direction QA sheet: <absolute run dir>/qa/look-directions.png
Direction semantics JSON: <absolute run dir>/qa/direction-semantics.json
Blind direction validation JSON: <absolute run dir>/qa/direction-blind-validation.json
Look continuity JSON: <absolute run dir>/qa/look-continuity.json
Preview dir: <absolute run dir>/qa/previews
Review JSON: <absolute run dir>/qa/review.json
V2 validation JSON: <absolute run dir>/final/validation-extended.json
Inspect the contact sheet and the preview GIFs visually. Confirm the same pet identity, style, palette, silhouette, face, proportions, and props across all rows:
0 idle, 1 running-right, 2 running-left, 3 waving, 4 jumping, 5 failed, 6 waiting, 7 running, 8 review.
Require `qa/direction-blind-validation.json` to have `ok: true`, or require an explicit accepted minor override in `qa/blind-review-resolution.json`. Cardinal mismatches or ambiguity are major and block packaging. For intermediate warnings or a worker-level fail, inspect the labeled normal-size pose and ordered loop; accept when the issue is minor and there is no wrong-quadrant pose or reversal.
Inspect the 16 direction cells as a labeled ordered loop against the neutral frame and review `qa/look-continuity.json`. Produce a `pass`, `warning`, or `fail` semantic verdict for every expected direction: `000 up`, `022.5 up-right`, `045 up-right`, `067.5 up-right`, `090 right`, `112.5 down-right`, `135 down-right`, `157.5 down-right`, `180 down`, `202.5 down-left`, `225 down-left`, `247.5 down-left`, `270 left`, `292.5 up-left`, `315 up-left`, and `337.5 up-left`. Record separate horizontal and vertical landmark evidence for every diagonal. Fail wrong or ambiguous cardinals, labeled wrong-quadrant poses, and visible reversals. Record blind uncertainty on intermediate poses as warnings when labeled review and loop context confirm the intended direction.
Fail rows with identity drift, missing/blank frames, copied guide marks, white/nontransparent backgrounds, cropped bodies, slot overlap, detached effects, shadows/glows/smears/dust, motion that does not match the row state, unintended size popping, wrong facing direction, reversed or non-alternating gait, or idle loops that are effectively static. Judge chroma only on the cleaned extended contact sheet, not the pre-cleanup standard contact sheet. Do not fail or retry a row for magenta/chroma fringe after the final despill report and v2 atlas validation pass; those deterministic results are authoritative.
Do not edit files, queue repairs, package, clean up, or inspect unrelated files.
Return exactly:
visual_qa=pass|fail
qa_note=<one sentence summary>
direction_semantics=<semicolon-separated labels with pass/warning/fail and short visual reason>
review_warnings=<semicolon-separated accepted warnings, or none>
repair_rows=<comma-separated row ids, or none>
repair_notes=<short row-specific notes, or none>
If frame inspection or final visual QA fails, read qa/review.json, regenerate the smallest failing row, copy the replacement row into the same decoded output path, and keep that job marked complete with the new source_path and completed_at. Repair the failed row, not the whole sheet.
$imagegen as the primary generation layer.$imagegen as the only visual generation layer. Do not invoke image APIs, image CLIs, local raster generators, or one-off generation scripts from this skill.$imagegen whenever the chosen path supports references.references/layout-guides/<state>.png image to every row-strip job as a layout-only guide, and do not accept outputs that copy guide pixels.$imagegen: base plus all row strips that are not explicitly approved running-left mirror derivations.running-right before deciding whether running-left can be mirrored.running-left is mirrored, preserve frame order and timing semantics; derive it through the deterministic script instead of mirroring an entire strip wholesale.waiting, running, failed, review, jumping, or waving from another state; each has distinct app semantics and must be generated as its own row.$imagegen outputs.pet_request.json; do not force a fixed green screen.qa/direction-semantics.json as failed. The file must include every expected direction with verdict, expected, observed, and reason fields. Packaging requires no fail verdicts; reviewed warning verdicts are allowed.qa/direction-blind-validation.json as failed. Each of the three isolated blind reviewers must see only the randomized A/B sheet, never degree labels, the answer key, or another verdict. Cardinal mismatches or ambiguity fail validation; intermediate mismatches or ambiguity remain review warnings.qa/look-directions.png or ask the user to inspect it before packaging.qa/blind-review-resolution.json; never override a major failure.qa/direction-semantics.json. Intermediate verdicts may use holistic head, face, posture, and ordered-loop evidence; exact pupil or nose placement is advisory rather than mandatory.qa/review.json errors as blockers. Warnings require visual review.1536x2288, and based on 192x208 cells. The 1536x1872 standard atlas is intermediate-only.pet.json contains spriteVersionNumber: 2, the extended despill report has ok: true, and the packaged spritesheet passes validate_atlas.py --require-v2 with the run's chroma key. These deterministic results close chroma QA; no separate visual chroma-fringe gate or image retry is allowed.references/animation-rows.md.decoded/look-anchors-approved.png as the direction basis, interpolate all intermediate directions as even 22.5-degree steps, and preserve the fixed clockwise order.qa/direction-blind-validation.json has ok: true, or a worker-level/intermediate failure has an accepted minor resolution in qa/blind-review-resolution.json backed by labeled and continuity evidence.pass, warning, or fail semantic verdict with horizontal and vertical axis evidence where applicable; no wrong cardinal, labeled wrong-quadrant pose, or visible reversal remains.qa/direction-semantics.json records verdicts for all 16 directions from an independent visual QA worker or explicit user inspection, including review notes for accepted warnings.qa/look-continuity.json has been reviewed; metric warnings are acceptable when the normal-size ordered loop has no visible snap, pop, identity change, or semantic discontinuity.qa/review.json has no errors.${CODEX_HOME:-$HOME/.codex}/pets/<pet-name>/pet.json and ${CODEX_HOME:-$HOME/.codex}/pets/<pet-name>/spritesheet.webp are staged together for custom pets.