Photorealistic Render Boundary
Photorealistic PNG/JPG renders are presentation artifacts only.
This skill may generate or update:
outputs/render-prompt.txt
outputs/*visualization*.png
outputs/*render*.png
This skill must NOT claim the design package is complete, and must NOT claim that a PNG validates post count, beam count, rafter count, brace count, span, height, pitch, miter angles, cut lengths, or structural safety.
Every render output must be accompanied by:
Visual concept only — construction geometry is governed by validated JSON/SVG artifacts.
If a render appears to conflict with deterministic geometry, the render is subordinate to:
context/staging/structure.json
outputs/*.svg
After generating a render, hand control back to design-orchestrator to confirm deterministic artifacts and quality dashboard status.
context/staging/structure.json(must be locked:_locked: true; includes members, geometry, and intent/meta sections)
Outputs
outputs/render-prompt.txt— single self-contained file: all geometry locks, structural description, camera direction, and exclusions. Paste the whole thing verbatim into ChatGPT or any image model.outputs/photorealistic-render.png— generated image (if the user pastes and generates)outputs/RENDER_FAILED.md— written if the skill cannot complete; prompt file still saved
Phase 1 — Read Locked Model
Read context/staging/structure.json. If _locked is not true, halt with:
ERROR: structure.json is not locked. Run structural-engine first.
Extract the fields that describe this specific structure — the exact fields vary by structure type:
structureType→ what kind of structure (gazebo, pergola, arbour, shed, screen, trellis…)planShape→ geometry (hexagonal, rectangular, square, L-shaped, octagonal…)members.posts.dimensions,members.posts.quantitymembers.beams.dimensions(if present)members.rafters.dimensions,members.rafters.quantity(if present)members.bracing.*(if present — type, angle, quantity)members.roofType→ open rafter, solid, pergola-style, lean-to, flat, no roof…roofStructure.pitch(if present)materials.primary→ species and finishjoinery.type→ mortise-and-tenon, screwed, bolted, notched…- Any unique members (king post hub, ridge beam, purlins, lattice panels, gates…)
Also read context/staging/structure.json (geometry section):
total_height_ft,post_cut_ft,span_ft,diameter_ft— whatever dimensions are present
Also read context/staging/structure.json (intent/meta section, if present):
site.location,site.setting,site.surroundings→ used to set the scene realistically
Phase 2 — Compose and Write Prompt
Write outputs/render-prompt.txt using the CAD-SPEC format — structured sections with a title, explicit geometry locks, per-member subsections, and a final Exclude: block. All values are derived from structure.json; nothing is hardcoded.
Format overview
[SHAPE] TIMBER FRAME — CAD-SPEC PROMPT (MAX ENFORCEMENT)
ABSOLUTE GEOMETRY DEFINITION (TOP PRIORITY — DO NOT VIOLATE):
[geometry constraints]
PLAN GEOMETRY (EXPLICIT CONSTRUCTION LOGIC)
[dimensions and spacing]
STRUCTURAL FRAME
[one subsection per member type that exists in the model]
MATERIAL + FINISH
[species, finish, character]
SCENE + ENVIRONMENT
[site, planting, lighting]
CAMERA + VISUAL VERIFICATION (CRITICAL)
[angle, lens, counting test]
ANTI-FAILURE CONSTRAINTS
[explicitly forbid wrong shapes and wrong counts]
FINAL VALIDATION CHECK (MANDATORY)
[list of things that must be true for the image to be correct]
Exclude: [comma-separated list]
Section 1 — Title
[SHAPE] TIMBER FRAME — CAD-SPEC PROMPT (MAX ENFORCEMENT)
Derive shape from structure.shape (e.g. HEXAGONAL, SQUARE, OCTAGONAL).
Section 2 — ABSOLUTE GEOMETRY DEFINITION
Always first. Derive every value from the model — no guessing.
- Shape definition: N sides, N vertices, N structural corner posts ONLY
- Perimeter rule: "The outer boundary consists of exactly N straight edges. The viewer must be able to visually trace the perimeter and make exactly N directional turns ([interior_angle]° each). Interior angle at every corner = [interior_angle] degrees."
- Name the failure shape explicitly: "This is NOT an [confabulation_shape] — never [wrong_N] sides, never [wrong_N] posts." For hexagon the failure shape is octagon. For square it is hexagon. Name whatever the model is most likely to confuse.
- Post count hard lock: "TOTAL POSTS = N. One post per vertex. No additional vertical supports anywhere on the perimeter or inside. No doubled posts, no closely spaced posts, no decorative posts. Posts must be evenly spaced at [360/N]° around the center."
- System parity constraint: "N posts = N beam segments = N roof edges = N hip rafters. All systems must match this count exactly." Only include systems that actually exist in the model.
Interior angles by shape: triangle=60°, square=90°, pentagon=108°, hexagon=120°, octagon=135°.
Section 3 — PLAN GEOMETRY
Derive from layout.* and structure.*:
- Shape name
- Span or diameter (from
inscribed_radius_ft× 2, orcircumscribed_radius_ft× 2) - Post positioning logic ("Posts positioned on a perfect circumscribed circle")
- Post spacing in degrees (360 / post_count)
Section 4 — STRUCTURAL FRAME
One subsection per member type that exists in the model. Do not include sections for members that are absent. Use nominal lumber sizes (6x6, 4x8) — not actual dimensions (5.5×5.5). Do not include cut angles or miter values — those are carpenter specs, not visual descriptions.
Posts subsection (always present):
Posts
- [species] timber, nominal [size]
- Quantity: EXACTLY [post_count]
- Height: [cut_length_ft rounded to nearest half-foot]' to beam soffit
- Mounted on visible [footing description]
- Perfect vertical alignment
Beam Ring subsection (if beams exist):
[descriptor] Primary Beam Ring
- [beam_count] segments (one between each pair of posts)
- Material: [nominal_size] [species] timber
- Each segment connects post-to-post only
- Forms a closed [N]-sided ring — no extra segments
Roof Structure subsection (if roof exists):
Roof Structure (OPEN FRAME — NO ROOFING)
- [primary_rafter_count] exposed hip rafters ([nominal_size] [species])
- One rafter per post
- Decorative rafter tails extending past the beam ring
- Rafters converge into a central [hub description]
- Pitch: [pitch]
If jack rafters exist (secondary_rafters.enabled = true):
- Each roof bay contains exactly [count_per_side] jack rafters (shorter, [nominal_size])
- Jack rafters terminate into adjacent hip rafters — do not reach the hub
- Creates layered timber framing detail in each bay
If purlins are enabled (purlins.enabled = true AND show_purlins = true in visibility_rules):
Purlin Ring
- Continuous horizontal ring inside roof
- Follows [shape] symmetry — no added segmentation
If purlins are disabled or suppressed: omit this subsection entirely.
Knee Bracing subsection (if bracing enabled):
Knee Bracing
- [total_brace_count] total diagonal knee braces
- [count_per_post] per post
- Material: [nominal_size] [species]
- Curved or chamfered profile, ~[angle_deg]° angle
- Symmetrical and evenly distributed
Joinery subsection (always):
Joinery
- Traditional mortise-and-tenon
- Visible joinery / connector detailing at post-to-beam and brace intersections
- No modern metal hardware visible anywhere
Section 5 — MATERIAL + FINISH
Derive from materials.primary, intent.finish (if present), or project context:
Wood: warm [species] timber appearance
Finish: [finish description]
Visible grain, tonal variation, subtle tool marks
Realistic, professional-grade timber frame presentation
Section 6 — SCENE + ENVIRONMENT
Derive from intent.site, intent.jurisdiction, and project context:
Photorealistic setting in a [location] garden/patio:
- [hardscape description]
- [planting palette]
- [lighting conditions]
- [atmosphere]
Section 7 — CAMERA + VISUAL VERIFICATION
For symmetrical structures use a slightly elevated 3/4 corner view at 6–7 ft — this camera height is critical for making all posts countable without foreshortening. For linear structures use a 3/4 angled view along the length.
CAMERA + VISUAL VERIFICATION (CRITICAL)
- Perspective: slightly elevated 3/4 view (camera height ~6–7 ft)
- Lens: 35mm equivalent
- Aperture: f/8
- All [N] posts must be clearly visible — no post fully hidden behind another
- No overlap that could obscure counting
- Counting test: viewer must be able to count 1, 2, 3…[N] posts clearly
Section 8 — ANTI-FAILURE CONSTRAINTS
ANTI-FAILURE CONSTRAINTS
Explicitly forbid:
- [failure shape] geometry (e.g. Octagonal geometry)
- [wrong_count+1] or [wrong_count+2] posts
- Any extra vertical elements
- Uneven spacing
- Distorted or non-regular polygon shapes
This is a simple [N]-node structural system.
The perimeter contains ONLY [N] structural verticals.
No visual clutter that could resemble additional posts.
Section 9 — FINAL VALIDATION CHECK
List exactly what must be true. Derive counts from the model — never hardcode.
FINAL VALIDATION CHECK (MANDATORY)
The generated image is ONLY correct if:
- The perimeter is a true [shape] ([N] edges)
- There are exactly [N] posts on [footing type]
- There are exactly [N] exposed [primary member] with [tail description]
[- There are exactly [jack_count] jack rafters (if they exist)]
- There are exactly [brace_count] diagonal knee braces (if bracing enabled)
- The structure is symmetrical and physically believable
If any of these conditions fail, the image is incorrect.
Section 10 — Exclude block
Always last. One paragraph starting with Exclude:. Include:
- Standard hardware:
metal brackets, joist hangers, hurricane ties, screws, bolts, plywood, pressure treated lumber, green lumber - Wrong geometry by name:
octagonal geometry(if hex),7 posts, 8 posts, extra post, 5 posts - Confabulation patterns:
doubled posts, closely spaced posts, decorative posts, asymmetric posts, uneven post spacing, extra vertical members - Absent members:
roofing material, shingles(if open-rafter);walls, railings, partial walls(if open-sided);purlins(if purlins disabled) - Style exclusions:
modern furniture, string lights, anime style, cartoon, illustration, watercolor, blueprint overlay, distorted perspective, fisheye, people, animals, cars, shadows too dark, overexposed sky, clipping, grain noise, JPEG artifacts
Example — hexagonal cedar pergola (Vancouver Island): See
references/example-hex-gazebo-prompt.mdfor a fully worked example showing what the output looks like for this specific project. That file shows the level of detail and section structure expected — not a template to copy verbatim.
Phase 3 — Tell the User to Paste
The Copilot CLI is text-only — it cannot generate images. After writing outputs/render-prompt.txt, output this message:
Render prompt ready: outputs/render-prompt.txt
Paste the ENTIRE file verbatim into:
• ChatGPT (chatgpt.com) — uses gpt-image-1 / DALL-E 4 internally
• Midjourney (midjourney.com) — use /imagine
• Adobe Firefly (firefly.adobe.com)
• OpenAI API: openai api images.generate --model dall-e-3
Known issue: even with geometry locks, some image model runs still produce
7 or 8 posts. Verify the count before accepting the result. Regenerate if
needed — the geometry lock improves odds but is not a guarantee.
Gotchas
- Prompt file is always written first. A user should always get a usable prompt even if image generation is not available in the environment.
- Do not hardcode angles. Read
miter_deg,bevel_deg,pitchfromstructure.json(geometry section) every time. - Model must be locked. Never generate a render prompt from an unlocked
structure.json. - Image output path is
outputs/photorealistic-render.png— notoutput/. - Copilot CLI cannot generate images. Every model in the CLI (GPT-5.4, GPT-5.5, Claude, etc.) is a language model only. Direct the user to ChatGPT, Midjourney, Firefly, or the OpenAI images API. Do not call
copilot image— that command does not exist. - The CAD-SPEC approach is the only validated technique for exact post counts. Simple count statements and stop-sign analogies alone still produced 7–8 posts across multiple generations. What finally worked: (1) perimeter rule with explicit turn count and interior angle, (2) naming the specific failure shape ("NOT an octagon"), (3) system parity constraint cross-locking all member counts, (4) plan geometry construction logic (circumscribed circle, equal angular increments), (5) camera raised to 6–7 ft, (6) dedicated Anti-Failure Constraints section. All of these together produced a correct 6-post image on the first run.
- Even with the CAD-SPEC approach, verify the count. It maximises probability but is not a guarantee. Instruct the user to regenerate if wrong.
Smoke Test
- Locked model → single prompt file written: Given
structure.jsonwith_locked: true:outputs/render-prompt.txtis created with real values substituted, geometry lock block at top,Exclude:block at bottom. ✓ - Unlocked model → halt: Given
structure.jsonwith_locked: false: skill halts with clear error message; no prompt files written. ✓ - CLI unavailable → graceful fallback: Given
copilotCLI not in PATH:outputs/RENDER_FAILED.mdis written andoutputs/render-prompt.txtis still present for manual use. ✓ - Value substitution check:
[POST_CUT_FT]and[TOTAL_HEIGHT_FT]must not appear literally in the output prompt — they must be replaced with model values. ✓
Completion: HANDOFF_BLOCK
{
"stage": "photorealistic-renderer",
"status": "COMPLETE",
"outputs": [
"outputs/render-prompt.txt",
"outputs/photorealistic-render.png"
],
"prompt_ready_for_paste": true,
"image_generated": true
}
If image generation failed, set "image_generated": false and add "outputs/RENDER_FAILED.md" to the outputs array.