Forensics — art production specification (Phase 1: The Alley)

Status: drafted 2026-10-13 by Claude for Sarah's review. Supersedes the pilot brief's art sections where the two differ; the brief remains the statement of goals.

This spec commissions every painted asset for the first Forensics environment. The alley's geometry, cameras and slots already exist and are checked. The painter's job is to make one coherent, attractive place that sits exactly on that geometry. Everything that is a number, a line or a label is drawn by the app and never painted.

Phase 2 (the parking lot) has its own spec, docs/spec/forensics-parking-art-spec.md (review page 2026-10-14-forensics-next.html). Its geometry was authored and checked on 2026-10-14, before its art was commissioned.

1. Sources of truth

WhatFileRule
Geometry, cameras, lights, slotsforensics/alley.scene.jsonAuthoritative. The painting conforms to it.
Props, sizes, painted variantsforensics/props.jsonAuthoritative.
Painter's guidesforensics/guides/alley_<view>.guide.svgWireframe of the architecture and every slot, rendered from each plate's camera at 1536 × 2304. Use it as the structural reference for the painting.
Control pointsforensics/guides/alley_<view>.points.jsonNamed world points and their pixel positions. Used for acceptance (section 8).
Cases the art must serveforensics/fx-a1-*.json, fx-a2-*, fx-a3-*Six cases, three investigations.
Narrative-world styleART_DIRECTIONApplies in full, including its visual QA checklist.
Asset handlingASSET_PRODUCTIONApplies in full: masters, honest resolution, transparency, manifest.
Contract and checkerforensics-scene-contract.md, forensics/check_forensics.pyRegenerate the guides with python3 docs/spec/forensics/check_forensics.py --guides docs/spec/forensics/guides.

If the geometry makes a composition impossible, report it. Do not paint around it. The geometry changes only through the scene file, after which the guides are regenerated and every case is rechecked.

2. The place

An older service alley behind a commercial block, at night, deserted but in use. Twenty metres long and five and a half wide, dead-ended by a concrete-block wall at one end, opening onto a cross street at the other.

ElementDescriptionGeometry
Wall A (right side of the wide view)Aged red-brown brick, four storeys, mortar dark with soot. The building's working side.wall_a, 9.0 m
Second-floor windowDouble-hung wooden sash, lower sash raised (open). Painted frame, chipped. Warm lamplight inside, seen as a lit interior, not a glow.window_2f: sill 3.6 m, head 5.0 m, 1.0 m wide
Service doorSteel, painted blue-gray, scuffed at kick height. No exterior handle; a plain keyhole plate. Steel frame, concrete step flush with the pavement.service_door: 0.9 × 2.1 m
Door lampSmall caged wall fixture above the door, warm incandescent.door_lamp fixture
Fire-escape landingBlack steel landing and railing, drop ladder stowed up. Toward the street end, nowhere near the window.fire_escape, 3.2–3.35 m
Wall B (left, mostly out of frame)Brick painted cream long ago, gone gray.wall_b, 7.5 m
Dead-end wallConcrete block, stained.wall_end
PavementOld asphalt, patched with concrete toward the street end. Dry. Grime and grit at the wall bases, a shallow drainage channel down the centre is allowed if it stays flat and unobstructed.alley_floor
StreetCross street beyond the mouth: kerb, a lamppost's light falling on the far side, dark storefront. Seen in the wide view and the plan.street

Lighting. Three sources, as in the scene file: the window's warm interior light spilling onto Wall A above the sill, the door lamp's pool on the pavement around the door, and a cool ambient night fill. The street end is slightly brighter from the street lamp. Pavement is dry: it takes the lamp pool as a matte warm patch with no reflections or sheen. Shadows fall consistently away from each source.

Permitted set dressing. Flat wall detail that creates no measurable surface: downpipes, conduit, a dead meter box, old fixings, a ghost of a painted sign with no legible lettering. Anything that occupies floor space or could be mistaken for a measurable object must be in the geometry first: no extra bins, pallets, vehicles, ladders, crates or doors in the plates.

Never in a plate. People, text or numbers, measurement graphics, evidence markers, any prop listed in section 4, wet pavement, glowing windows, bloom, neon, hanging lamps. The plate must look complete and attractive with every prop and overlay removed.

3. Plates

All plates are opaque, text-free and prop-free. Portrait 2:3. Paint at 1536 × 2304 if the tool supports it; the minimum acceptable native width is 1170 px (one iPhone screen width at 3×). Record the true native resolution in the manifest. An enlarged image is not a master.

PlateViewCameraMust show clearly
alley_scene_wideEstablishing, eye height, from near the dead end toward the street. Wall A runs down the right.scene_wideWindow (large, upper right), door, fire-escape landing, the alley mouth and street in the distance, open pavement where the ladder lies
alley_scene_doorCloser view from the street end looking back at the door.scene_doorDoor (about a third of the frame width), the stretch of Wall A where the flat crate leans, pavement around the door
alley_planOverhead, orthographic, street at the top.planWalls as thick top edges, the door and window positions marked by their sills/thresholds, pavement texture, the street. Reads as an illustrated site plan at true scale: 1 m = 96 px at 1536 wide.

The two perspective plates show the same place: brick colour, mortar, door paint, window frame, lamp and wear must match between them. The plan must agree with both.

Keep the top 8% and bottom 20% of each plate visually quiet. The app's header and tools sit there, and the plate may pan within the viewport.

The three guides

ladder_ground_1 · ladder_extdumpster_wall_a_1 · dumpster_01crates_door_1 · crate_01decal_below_window_1 · scuffsdecal_past_cases_1 · footprints
alley_scene_wide — fitted to plate 1
flat_crate_wall_a_1 · crate_flat
alley_scene_door — fitted to the door plate
window 2fservice doorladder_ground_1dumpster_wall_a_1crates_door_1flat_crate_wall_a_1decal_below_window_1decal_past_cases_1STREET
alley_plan — overhead, street at top

4. Props and decals

Every prop is painted in place: on a copy of its plate, in its slot, matching the guide's outline, then delivered as a full-canvas transparent PNG registered pixel-for-pixel to the plate. Its cast shadow is a separate full-canvas layer (multiply). Contact darkening where the object meets the ground belongs to the prop layer. A prop is painted once per view and size it appears in.

PropSizesViewsLayers
Extension ladder, aluminium, lying on the pavement5.4 m, 4.8 mscene_wide, plan4 prop + 4 shadow
Dumpster, steel, lid closedonescene_wide, plan2 + 2
Equipment cases, stacked two highonescene_wide, plan2 + 2
Flat packing crate, opened and empty, standing on its long edge against Wall A, straw spilling2.5 × 2.2 m, 2.5 × 2.4 mscene_door, plan4 + 4
Ladder scuffs (ground decal): two short scrapes side by side along the wall, one under each ladder rail: 0.39 m between inside edges, 0.45 m between outside edgesonescene_wide, plan2, no shadow
Footprints (ground decal): a heel smear and a partial sole print, turningonescene_wide, plan2, no shadow

Total: 16 prop layers and 12 shadow layers. The lengths are exact. A 4.8 m ladder painted at the 5.4 m length fails acceptance, because students measure it.

The evidence marker, every measurement line, the ghost ladder, routes and outlines are drawn by the app.

Occlusion. No foreground element passes in front of a slot in these three plates, so no occlusion masks are needed. If a revision adds one, it needs a mask layer per plate.

Layer order. Plate, prop shadows, props, foreground occluders, then the app's overlays and UI.

5. Painting to the guide

The guide is the structure; the painting is the finish. Plates use forensics/guides/alley_<view>.guide-lines.png; props use the per-layer guides in forensics/guides/props/. Guides are regenerated whenever a plate's camera is refitted, so use the current ones (the plan guide and the per-layer guides were first written 2026-10-13, after all three plates were accepted). Use the guide as the composition and perspective reference (as a conditioning or reference image if the tool is an image generator). Architecture edges, opening corners, slot outlines and the floor plane must land on the guide. Style references: the approved Peregrine environment art in Image-Assets/ (The Raid's locations and the Darkroom).

For props, the image model paints over a geometry-locked render, never freehand: check_forensics.py --blockouts <dir> renders each prop flat-shaded in place from the calibrated camera at native resolution, with an edit mask, native-resolution 1024 × 1536 crops and their offsets. The edit restyles the surface; the layer is then cut with the render's own silhouette, so the outline registers by construction. (Added 2026-10-13, after a freehand ladder missed its slot by about 80 px.)

Lines that converge in the guide must converge in the painting. A tool that cannot hold a wireframe will fail acceptance, and the fix is a better-registered painting.

6. Deliverables

Into Image-Assets/Forensics/Alley/:

7. Process

  1. Plate proof. Paint alley_scene_wide only. Run the calibration check (section 8). Sarah reviews composition, mood and fit before anything else is painted.
  2. Matching plates. Paint alley_scene_door and alley_plan against the approved wide plate's materials and light.
  3. Props. Paint the ladder at both lengths first, in both views, and run the length check. Then the rest.
  4. Assembly review. Composite every case's staging over its plates with the app's overlays (check_forensics.py output beside the composite) and review at phone size.

8. Acceptance

Calibration. Mark the control points visible in the painting (world point and measured pixel position) in forensics/calibration/<plate>.observed.json, then run check_forensics.py --fit <that file>. The tool re-solves the plate's camera from the marks and reports each point's miss. A point within 0.75 m of anything a case measures on that plate is case-critical and must land within 1% of the plate width (15 px at 1536); every other point must land within 2% (31 px). The tool refuses fewer than 6 marks, and refuses marks that all lie on one plane unless every case anchor on that plate lies within 0.3 m of it; on the wide plate, floor marks (the alley-mouth kerb) supply the off-wall constraint. Overhead plates fit centre and scale with rotation held. When the fit passes and every scene and case check still passes with it, --apply writes the camera into the scene file, and the guides are regenerated so props register to the painting. A plate whose fit fails is repainted or retouched. (Rule amended 2026-10-13, Sarah.)

Prop registration. Each prop layer is painted to its own guide, forensics/guides/props/<prop>[_<size>]_<view>.guide.png: the architecture in gray, that one prop at that one size in blue, its anchors circled in red. Run check_forensics.py --check-props Image-Assets/Forensics/Alley --props-review <dir>. It measures each layer against the projected outline: the painted extent along the prop's long axis and the bounding box, within 1% of plate width for the ladder and the flat crate (case-critical: A1 and A3 measure them) and 2% for the rest; a decal's centroid within 1% of its point. Every layer must be 1536 × 2304 RGBA, and every prop with a shadow must have its shadow layer. The review overlays show the plate, shadow and prop with the expected outline.

Reuse. Removing every prop leaves a complete, attractive plate. Each prop can be toggled without visible seams, halos or missing shadow.

Consistency. Materials, wear and light agree across the three plates. The window, door and fire escape match in every view they appear in.

Style. ART_DIRECTION's visual QA checklist, every item recorded. Dry pavement. No unrequested additions.

Phone. At 390 pt width the window, door, ladder, crates and decals are identifiable and tappable, and the quiet bands hold the header and tools without fighting the art.

Cases. All six alley cases pass check_forensics.py, and their composites read correctly: in A1 the ladder and the scuffs below the window, in A2 the footprints past the stacked cases with the route to the street, in A3 the door and the flat crate side by side.

9. Open items