| name | photo-art-direction |
| description | Preserve source-specific photographic storytelling when planning, generating, reviewing, or implementing images for websites and mockups. Use with mockup-to-code or image generation when source subject relationships, gaze, environment, copy space, focal geometry, responsive crops, tone, or distinct semantic photo stories must survive instead of becoming generic substitutes. |
Photo Art Direction
Treat each source photo as a spatial story, not a bag of visual keywords. Freeze the story contract before generation, bind every candidate to the exact prompt receipt, and adopt only evidence-backed candidates.
Workflow
- Read the source and implementation constraints. Create one
stories[] entry per semantically distinct source photo or photo field. Never merge stories to save generation calls or reuse one candidate for different stories.
- Record the source path and a verbatim source quote that explains why the photo exists. If no quote exists, keep the plan
blocked; do not invent client intent.
- Map every subject as a normalized
[0,1] zone. Record gaze, relationships, environment, copy spaces, tone, semantic cause-and-effect, and one focal point per responsive frame.
- Write each exact prompt to a UTF-8 file. Issue a pre-generation
prompt-generation-receipt/v1 receipt. When mockup-to-code is available, prefer its scripts/prompt_receipt.py; otherwise emit the same receipt contract. Never cite a prompt that was merely consulted.
- Validate the plan before generation. Do not generate while the validator reports malformed data or unresolved placeholders. A valid pre-generation plan still remains incomplete until candidates are reviewed.
- Generate candidates only when the user authorizes image generation. Preserve identities only when permitted; otherwise preserve roles, relative geometry, gaze logic, and semantic relationships without claiming identity fidelity.
- Review every candidate against all seven axes: subject relationships, gaze, environment, copy space, focal geometry, tone, and semantic story. Record real candidate, comparison, review, and responsive evidence paths.
- Reject explicitly. A rejection needs at least one failed axis and concrete reasons. Adoption needs every axis passing, every responsive frame checked, copy-space intersections within limits, and exactly one adopted candidate per story.
- Run the validator again before handing assets to mockup-to-code. Keep originals and evidence; implementation derivatives do not replace review evidence.
Hard rules
- Preserve relationships before isolated appearance: who looks at whom, distance, ordering, scale, gesture, and shared activity.
- Preserve environment as story evidence. Do not replace a meaningful workplace, home, street, landscape, or object system with a generic backdrop.
- Keep declared copy spaces empty at every target viewport. Do not solve collisions by shrinking the subject until the source hierarchy disappears.
- Keep responsive focal points attached to the named subject zone; do not use one desktop crop as proof for mobile.
- Keep tone concrete: lighting direction, palette, contrast, texture, era, and forbidden drift.
- Keep each prompt receipt story-local. A candidate may reference exactly one receipt and one story.
- Never mark a placeholder, missing file, unevidenced score, or all-rejected set as adopted.
- Do not let aesthetic preference override a failed semantic or geometric check.
Contract and templates
Resolve relative paths from the plan file's directory. Use normalized geometry: x, y, width, height, and focal x, y all range from 0 to 1.
Validate
SKILL_ROOT="${SKILL_ROOT:-${CODEX_HOME:-$HOME/.codex}/skills}"
"$SKILL_ROOT/mockup-to-code/scripts/skill-pack-python" \
"$SKILL_ROOT/photo-art-direction/scripts/validate_photo_art_direction.py" \
path/to/photo-art-direction.json
The validator uses only the Python standard library and emits deterministic JSON. Exit 0 means a fully adopted plan. Exit 1 means malformed contract data. Exit 2 means structurally readable but honestly incomplete or blocked. Use --base-dir only when evidence paths intentionally resolve somewhere other than the plan directory.
After exit 0, emit the parent manifest receipt from the mockup work root:
SKILL_ROOT="${SKILL_ROOT:-${CODEX_HOME:-$HOME/.codex}/skills}"
"$SKILL_ROOT/mockup-to-code/scripts/skill-pack-python" \
"$SKILL_ROOT/photo-art-direction/scripts/validate_photo_art_direction.py" \
reports/photo-art-direction.json \
--receipt --receipt-root .
Store the emitted {contract,path,sha256} at specialistReports.photoArtDirection. Blocked or invalid plans never emit a receipt.
Do not weaken the schema or validator to make a candidate pass. Fix the plan, prompt provenance, candidate, or evidence.