Exact source used by this build. SHA-256: 55df67e4c71ae8e6da4e268ae5db7c65183004f382bf11bd809bc3dd2545222b.

1 # Tamarack pixel art
2 
3 This is the original asset collection through art round three, separate from the current runtime placeholders.
4 It does not change the client, simulation, server, or gameplay content. The setting
5 uses Vermont clapboard buildings, a covered bridge, maples, birches, white pines,
6 stone walls, and split-rail fencing. Terrain also covers the mountain, beach,
7 rainforest, canyon, cave, and peat bog described in `world-areas.md`.
8 
9 Open `apps/client/public/assets/gen/preview.html`, or run `bun run art:preview`
10 and open the printed localhost address. The preview is static HTML with embedded
11 manifest data and relative PNGs; it needs no build, CDN, or external service.
12 Some browser guest modes block local file navigation; the localhost server is
13 provided for that case. Atlases display at 4× on checkerboards. The season buttons
14 change the scene and seasonal atlas groups. Search and click a frame for metadata;
15 the motion studies show walking and animated water.
16 
17 ## Native scale and drawing rules
18 
19 | Asset | Exact native frame |
20 | --- | --- |
21 | Ground, item icons, small decor, rocks, weeds | 16×16 |
22 | Tall objects, fences, crops, characters, hair layers | 16×32 |
23 | Shipping crate, fallen log | 32×16 |
24 | Bushes, boulders, large stump | 32×32 |
25 | Wild trees, all five stages | 48×96 |
26 | Farmhouse | 128×112, eight tiles wide |
27 | Store | 112×96, seven tiles wide |
28 | Covered bridge | 112×80, seven tiles wide |
29 | Sugar shack | 96×96, six tiles wide |
30 | UI panel / slot / energy / clock / money / button | 32×32 / 20×20 / 16×48 / 48×32 / 64×24 / 48×16 |
31 
32 Frame dimensions include transparent space. Seedlings remain small inside a full
33 tree or crop frame. Character feet stay at the bottom tile, with head and body
34 inside the 16-pixel width. Growth stages are separate designs. Future fruit trees
35 should use 48×80 frames and an explicit corresponding size class/test.
36 
37 The intended game display is 4× nearest-neighbor. The scene is 30×17 tiles,
38 480×272 native pixels, exported at 2× as **960×544**, rather than cropping four
39 pixels to imitate the 960×540 references. Placement origins lie on the 16-pixel
40 grid; transparent margins and foot anchors position individual silhouettes.
41 
42 Use top-left light, saturated warm colors, dark chromatic outlines, and compact
43 flat material ramps, aiming for three to five tones per material. Avoid black
44 outlines, smooth shading, gradients, blur, and antialiasing. Ground needs small
45 tufts, flowers, stones and leaf litter, with irregular boundaries rather than
46 straight rectangular path edges. Separate oval shadows use RGB 36/31/43 and
47 alpha 65; ordinary sprites have binary alpha only. Never bake those shadows into
48 the source artwork.
49 
50 ## Palette and source policy
51 
52 The first round supplied **26 unchanged original generated PNG sheets** plus
53 extraction catalogs; round-two additions and totals are listed below. The complete exact prompt record is `tools/art/prompts.md`;
54 the crop and character records are also kept as smaller working documents.
55 There were 26 successful image generations and two rejected over-limit reference
56 requests that generated no image. The first maple source is retained, while a
57 second, taller mature-maple sheet supplies the final stage.
58 
59 The supplied official screenshots were style references only. Do not copy,
60 trace, sample colors or pixels from, or closely imitate an existing game's
61 sprites, buildings, characters, maps, or interfaces. No reference screenshot is
62 stored here. There is no downloaded placeholder art in this set; attribution
63 and provenance are in `assets/CREDITS.md`.
64 
65 Terrain entries have explicit five-color palettes. Crops and characters have
66 curated multi-material palettes. Tree seasons have separate palettes, retaining
67 spring greens, strong fall reds/golds, white birch bark, and winter snow. Other
68 sources use bounded deterministic weighted median-cut palettes. Explicit
69 `entry.palette` overrides the source palette; `manifest.palettes` records the
70 source fallback palettes. The catalog is authoritative for per-frame palettes.
71 Palette reduction selects existing colors and performs no dithering or blur.
72 
73 All calls requested pure #FF00FF backgrounds and integer pixel enlargement. The
74 tool returned transparent images with irregular spacing and some soft edge
75 pixels. Preserve those originals. The snapper handles alpha and magenta,
76 estimates a grid from color-run lengths and repeating boundary phases, and uses
77 the dominant color of each output cell. For irregular images, it falls back to
78 area sampling into the requested dimensions. Alpha coverage is decided before
79 opaque-color voting so thin stems are not erased by a plurality of background
80 pixels. Alpha below 128 is removed, surviving pixels become fully opaque, and
81 remote singleton islands are removed without deleting intentional interior marks.
82 
83 ## Regenerating and adding art
84 
85 ```sh
86 bun install --frozen-lockfile
87 bun run art:snap
88 bun test tools/art
89 bun run art:typecheck
90 bun run check
91 ```
92 
93 `art:snap` reads only the raw PNGs and `raw/catalog.json`; it makes no model or
94 network calls. It rebuilds the atlases, manifest, standalone frames, preview, and
95 all scene PNGs, the portrait lineup, and the review boards deterministically. No new PNG dependency was added: `png.ts`
96 uses Bun/Node's built-in zlib and implements PNG scanline filters and CRCs.
97 
98 To add a source:
99 
100 1. Generate one coherent group, stating exact native dimensions, integer
101    enlargement, frame order, palette, light, outline, and pure magenta background.
102    Supply style references plus an approved original source, respecting the tool's
103    five-reference limit. Use original designs only.
104 2. Copy the returned PNG unchanged into `tools/art/raw/`. Record the exact prompt,
105    references, intended frame order, and any rejected attempts in `prompts.md`.
106 3. Add extraction entries to the appropriate partial catalog or to `catalog.ts`.
107    Inspect actual spacing: equal cells are a convenience, not an assumption.
108    Use integer-pixel `sourceRect` overrides when the generator moves sprites.
109 4. Run `bun run art:catalog` to assemble `raw/catalog.json`, then `art:snap`.
110    Check isolated frames and the composed scene at native and integer zoom.
111 5. Run the validation commands. Keep original sources; change extraction/palette
112    metadata or generate a new original source when an asset needs revision.
113 
114 Partial catalogs hold trees/terrain/buildings, crops, and characters. Round two
115 adds ground, environment, town and life partials named `catalog-r2-*.json`.
116 Assembly replaces explicitly repeated frame names without changing old PNG sources.
117 `catalog.ts` assembles them with props/decor/UI and the mature-maple refinement.
118 Keep these source definitions in sync: direct edits to assembled `catalog.json`
119 are overwritten by `art:catalog`.
120 
121 Example entry:
122 
123 ```json
124 {
125   "name": "crop.leafy.stage4",
126   "width": 16,
127   "height": 32,
128   "category": "crops",
129   "family": "crop.leafy",
130   "sourceCell": 4,
131   "sourceRect": { "x": 1400, "y": 200, "width": 300, "height": 400 },
132   "contentWidth": 14,
133   "contentHeight": 23,
134   "fit": "contain",
135   "palette": ["#173b28", "#295c2b", "#4b862e", "#7bb437", "#bdd85b"]
136 }
137 ```
138 
139 The coordinates above illustrate the format; use measured coordinates for the
140 actual sheet. `contain` preserves aspect ratio and bottom-centers the silhouette.
141 `frame` resamples the entire specified window, retaining registration and allowing
142 explicit dimensions for UI and animation frames. `contentWidth/contentHeight`
143 fit a small growth stage into its larger canonical canvas. Character hair uses
144 explicit content offsets and per-pose attachment offsets instead of independent
145 automatic centering.
146 
147 ## Terrain and connecting pieces
148 
149 `autotile.ts` repairs isolated texture flecks using wrapped neighbors and
150 reconciles opposite boundaries using existing palette colors. It builds all 47
151 canonical blob variants. Bit order clockwise is N=1, NE=2, E=4, SE=8, S=16,
152 SW=32, W=64, NW=128. A diagonal is retained only if both adjacent cardinals exist;
153 use `normalizeMask()` before indexing. Mask 255 is the full interior tile.
154 
155 Terrain absent edges are transparent so they can overlay another ground layer.
156 Wavy coverage profiles, corner cutouts, and palette-based edge shading agree at
157 neighbor seams. Layer grass beneath dirt, shore ground beneath shallow water,
158 and shallow water beneath deep water. Two water materials each have four phases,
159 with a four-frame animation for every mask. The first round's sixteen materials produced **22 sets
160 of 47 variants** after water phases; cobblestone, wood and boardwalk are simple
161 seamless base tiles. Thus 19 bases + 1,034 blob derivatives = 1,053 terrain frames.
162 
163 Fence and stone-wall connectors derive 16 four-direction pieces per material
164 from generated posts/rails/stone pixels. Connection bits are N=1,E=2,S=4,W=8;
165 mask 10 is east-west. They are separate from the eight-neighbor terrain masks.
166 
167 ## Manifest contract
168 
169 `gen/manifest.json` contains `frames`, `atlases`, `animations`, `autotiles`,
170 `palettes`, `seasons`, `sourceCounts`, and total packed `counts`. Names are stable;
171 atlas coordinates are rebuild outputs and must not be hard-coded.
172 
173 ```json
174 {
175   "atlas": "characters.png",
176   "file": "frames/player.walk.down.0.png",
177   "rect": { "x": 1, "y": 1, "width": 16, "height": 32 },
178   "size": { "width": 16, "height": 32 },
179   "sizeClass": "character",
180   "category": "characters",
181   "anchor": { "x": 8, "y": 32 },
182   "collision": { "width": 1, "height": 1 },
183   "shadow": "shadow.small",
184   "animation": "player.walk.down",
185   "attachments": { "hair": { "x": 0, "y": 0 } },
186   "source": { "file": "player-walk.png", "cell": 0 }
187 }
188 ```
189 
190 This illustrates the contract; consult the actual manifest for current values.
191 Rects, dimensions, anchors, nine-slice borders, and attachment offsets use native
192 pixels. Collision width/height use tiles and are art placement proposals for
193 future integration, not simulation rules. Draw at `footPosition - anchor`, draw
194 the linked shadow separately at the ground position, and add hair attachment
195 offsets to a same-direction hair overlay. Zero-sized collision means decorative.
196 
197 Animation records contain ordered frame names, per-frame `durationMs`, and
198 `loop`. Human walks have four frames per direction; each tool has three poses in four
199 directions and does not loop. Base teal, rust, and indigo shirts share animation
200 geometry. Legacy hair styles are curls, side-part, and tied-back, each with four views. The round-three wardrobe adds the six modular styles described below.
201 UI frames include nine-slice metadata; the panel uses six-pixel preserved corners.
202 
203 Every authored frame, wardrobe variant and shadow also has an exact-size PNG
204 under `gen/frames/`. Blob and connection derivatives are packed directly into
205 atlases. Atlas pages have a transparent one-pixel gutter; use nearest-neighbor
206 sampling. `source` points to a raw file/cell or identifies a procedural parent;
207 the catalog supplies the exact source rectangle.
208 
209 ## Adding a season
210 
211 Keep `spring`, `summer`, `fall`, and `winter` suffixes and a shared `family`, and
212 set `entry.season`. Use the same canonical frame, ground anchor and collision
213 across variants. Deciduous winter art needs new bare branching, not a green-tree
214 palette swap. Buildings retain the same geometry with snow/seasonal details.
215 The preview automatically filters seasonal entries. Winter sample plots contain
216 no regular crops. Rainforest art uses explicit `.wet` and `.dry` names and tags independently of
217 the four Vermont seasons; neither is a palette-only surrogate for the other. Simple color-only variants can use catalog
218 `variants` with explicit color replacements; preserve the original parent.
219 
220 ## Validation, review, and storage
221 
222 Tests recover a synthetic integer grid and offset exactly at several scales,
223 check imperfect boundaries and alpha-majority sampling, validate the PNG codec,
224 test all 47 masks and compatible seams, check four water phases, verify every
225 manifest frame and size class, and rebuild into a temporary directory twice.
226 SHA-256 hashes must match recursively for every output, including standalone
227 frames, HTML, manifest, seven scenes, and review boards. Temporary test outputs are
228 removed after the run. `bun run check` also validates all existing project tests,
229 types and content.
230 
231 The first batch contains **265 authored frames**, expanded to **1,438 packed
232 frames in 28 atlases**, including three separate shadows and three shirt colors.
233 Source counts: 19 terrain, 27 decor, 60 trees, 12 debris, 36 crops, 9 objects,
234 16 seasonal building views, 80 character/hair frames and 6 UI components.
235 
236 ## Round two
237 
238 **22 successful built-in image generations** were used in this round: 1 ground,
239 5 environment (including a ladder refinement), 7 town/icons/UI, and 9 life/repairs
240 (including one unnecessary background-extraction retry). Together with the first
241 round there are 48 preserved raw PNGs; 47 source sheets currently supply the
242 catalog. The unused retry remains as a provenance record.
243 
244 The complete set has **532 authored frames**, expanded to **2,786 packed frames
245 in 29 atlases**, with 45 complete 47-mask autotile sets. This round replaces 11
246 existing frames and adds 267; there are 278 selected round-two source frames.
247 Authored totals are 42 terrain, 44 decor, 61 trees, 19 debris, 108 crops, 89 objects
248 (including inventory icons and animals), 29 buildings, 128 character/monster/hair
249 frames and 12 UI pieces. Packed counts additionally include 104 shirt variants,
250 32 fence/wall connectors, 2,115 blob/water derivatives and 3 shadows.
251 
252 New raw source sheets use the `r2-` prefix. The exact prompts and extraction notes
253 are in `tools/art/prompts-r2-{ground,environment,town,life}.md`; `prompts.md` links
254 these records. Images were made with the built-in image generator, then snapped
255 and palette-reduced locally. All original source files remain unchanged, including
256 superseded designs. No reference screenshot is stored in the project.
257 
258 - Four grass interiors per spring/summer/fall (12 total). Fall retains olive
259   green turf with copper and orange tips. A stable spatial hash selects interiors;
260   broad patches use existing palette tones. A separate sparse decor pass places
261   blades, flowers, pebbles and leaf litter.
262 - All 47 blob masks retain compatible seams, with broader convex corners and
263   softer irregular shoulders. Shallow water has a light shoreline rim. The scene
264   compositor extends these materials along continuous distance-field contours,
265   avoiding tile-sized river steps. Deep water uses quiet blue ripple sources and
266   spatial phase offsets; it has a blue depth rim rather than white coastal foam.
267 - Path and soil shoulders have irregular cutouts exposing the grass substrate.
268   Receding fence rails preserve negative space, with central posts occluding
269   junctions. The sprinkler and three rear-facing axe poses have new source art.
270 - Three mine bands each include two floors, a wall, ladder, rock and ore node.
271   Beach contains sand/wet sand/ripple sand, tide pool, driftwood, three shells,
272   modular pier and lighthouse. Mountain contains two cliffs, snow pine, three
273   ground/ice tiles, mine entrance and boulder. Rainforest has two ground materials
274   and three plants drawn independently in wet and dry seasons.
275 - Eleven town buildings: general store, blacksmith, inn, six Vermont houses,
276   meeting hall, and community ruin. The existing sugar shack remains available.
277 - Eighteen crop families now have five stages and a harvested icon apiece.
278   Twenty fish, fifteen weapons and ten food/artisan icons use 16×16 frames.
279 - Eight monsters have two distinct poses each for idle, move and hit. Six farm
280   animals plus cat/dog have four distinct right-facing walk poses each. Animals
281   use 16×16 for chicken/duck/rabbit/cat and 32×32 for cow/sheep/goat/dog; these are
282   side-view cycles, not full four-direction character sets. Monsters use 32×32.
283 - Six additional UI components: inventory slot 20×20, tooltip 64×32,
284   dialogue 144×64, portrait 48×64, tab 48×16 and arrow 16×16. Rectangular pieces have
285   measured nine-slice borders; the arrow does not.
286 
287 The static preview selects spring, summer, fall, winter, beach, mine and town.
288 Every scene is 30×17 native tiles (480×272), exported at 2× (960×544). Town shows
289 seven buildings at their native scale; the complete collection is in the atlas.
290 The mine scene is a three-band review layout, not a gameplay map. Review boards
291 show icons, crop/creature poses, all fence junctions, rear axe with hair, and UI
292 frames actually stretched from their nine-slice metadata.
293 
294 Original PNG sources are intentional versioned inputs (60.2 MB total; this round
295 adds 30.6 MB). Reproducible exports under
296 `assets/gen/` are ignored by its local `.gitignore`; temporary QA data stays under
297 `tools/art/.work/`. No runtime dependency, game code or root lockfile changed.
298 
299 ## Round-two weakest assets after native-size review
300 
301 1. `decor.mine.stone.wall` (and sister bands): narrow 16×32 source compression
302    makes repeated vertical buttresses more mechanical than a bespoke corner set.
303 2. `terrain.beach.sand-ripple`: diagonal ridges still reveal repetition when used
304    densely; the sample now mixes this variant sparingly among plain sand.
305 3. `item.fish.rainbow-smelt`: the slender silver silhouette converges with herring
306    and whitefish at 16×16; stronger silhouette differences would aid inventory use.
307 4. `item.weapon.carved-bow`: the string is fragile at native scale; the wooden bow
308    outline remains readable, but the interior detail could be stronger.
309 5. `decor.rainforest.fern.wet`: the finest frond tips simplify during snapping;
310    chunkier individual leaf groups would better survive 32×32.
311 
312 Validation includes distinct frame hashes for every new animal/monster motion
313 sequence, 18 complete crop families, 20 fish/15 weapons/10 food icons, all seven
314 scene dimensions, PNG alpha/atlas bounds, and a full output SHA-256 rebuild check.
315 
316 Final validation for this pass:
317 
318 | Command | Result |
319 | --- | --- |
320 | `bun run art:catalog` | 47 selected source sheets, 532 authored frames |
321 | `bun run art:snap` | 2,786 packed frames, 29 atlases, seven scenes, four review boards |
322 | `bun test tools/art` | 30 passed, including recursive identical SHA-256 rebuilds |
323 | `bun run art:typecheck` | Passed |
324 | `bun run check` | All package types, 60 tests, and existing runtime content validation passed |
325 | `git diff --check` | Passed |
326 
327 Only the requested art paths changed. No commit, deployment, remote push or
328 reference-image import was performed. The pre-existing untracked
329 `docs/stardew-feel.md` and `tasks/art-round2.md` were left untouched. Temporary
330 review renders/scripts were removed after validation; the 48 original raw PNGs
331 remain required inputs for reproducible snapping.
332 
333 ## Round three — characters, interiors and the working farm
334 
335 The round-three additions are art assets and review tooling. Villagers use only
336 `villager_01` through `villager_10`; their work/age descriptions below are visual
337 art direction, not gameplay content or NPC definitions. The sources and four
338 catalog partials use the `r3-` prefix, and exact prompts are linked from
339 `tools/art/prompts.md`. Existing source originals and runtime code are unchanged.
340 
341 ### Native frames and composition
342 
343 - Ten villagers each have a 16×32 idle plus four walking directions with four
344   frames per direction. Their 64×64 portraits have neutral, happy, sad, angry,
345   surprised and blushing expressions. The lineup shows all sixty portraits.
346 - Player overlays use 16×32 canvases throughout. Draw skin/body, pants, shirt,
347   hair, optional hat, then optional glasses at the same pose anchor. Each body
348   layer retains the boots, face, tool and outlines; garment regions are replaced
349   by the corresponding clothing layers. The picker in `preview.html` exercises
350   this exact composition. Eight hair colors are palette variants of six shapes.
351 - Eleven farm-building families each have four generated seasonal views. Native
352   frames and collision footprints remain consistent within a family; the winter
353   art has generated snow. Shipping-crate art remains available from round one.
354 - Room assets are separate wallpaper, floor, furniture and fixture sprites.
355   Six wallpapers and six floors can be tiled; twenty furniture pieces can be
356   placed individually. Fireplace and forge use four-frame flicker sequences.
357   The farmhouse preview includes the optional kitchen upgrade nook.
358 - Fifteen effects have four phases apiece. Most use 16×16 canvases, rain streaks
359   use 16×32, and lamp/window light overlays use 32×32. Impact sequences are
360   non-looping; ambient weather, fireflies and light flicker loop. Light overlays
361   have binary source alpha and stepped colors; use reduced opacity or additive
362   blending in a future renderer. The interior samples use reduced opacity.
363 
364 `CatalogEntry.flipX` explicitly normalizes a generated profile's direction during
365 snapping, without modifying its source. Fixed extraction windows preserve action
366 origins. The ambient-effect sheet uses measured row boundaries to keep neighboring
367 lamp/window pixels out of particle frames. Source originals remain the authority;
368 re-snap never calls a model or reads any style reference.
369 
370 The preview adds the full villager lineup, farmhouse, store, blacksmith and inn
371 interiors, and winter coop/barn farm. Room/farm exports retain the established
372 480×272 native canvas (960×544 at 2×); the full portrait review is 544×824 native
373 (1088×1648 at 2×). The player wardrobe and effects have separate review boards.
374 
375 
376 ### Generation accounting and current totals
377 
378 Round three used **29 successful built-in image generations**: ten villager
379 sheets, six player calls (including two background/rod corrections), eleven
380 building/interior calls (including one unnecessary fireplace background edit),
381 and two effects sheets. Twenty-six selected new sheets supply **492 new authored
382 frames**. All 29 original results are preserved, including the three earlier
383 candidates superseded by edits. No reference screenshot was added.
384 
385 | New group | Authored frames | Derived exports |
386 | --- | ---: | ---: |
387 | Ten villagers | 230: 160 walk, 10 idle, 60 portraits | — |
388 | Player components and actions | 108 | 5,092 layers and 4 player idle aliases |
389 | Farm buildings | 44: 11 families × 4 seasons | — |
390 | Interiors | 50: 6 wallpapers, 6 floors, 20 furniture, 18 fixture frames | — |
391 | Effects | 60: 15 sequences × 4 phases | — |
392 
393 The complete collection now contains **1,024 authored frames**, **8,374 packed
394 frames**, **35 atlases**, and the existing 45 autotile sets. There are 73 selected
395 source sheets and 77 preserved original PNG results across all three rounds.
396 Raw originals occupy 103.1 MiB; this round adds 42.9 MiB. These files are required
397 inputs for deterministic snapping. Reproducible exports remain ignored in `gen/`.
398 
399 Each of the 67 wardrobe options covers the same **76 poses**: 16 walk, 4 idle,
400 36 hoe/watering/axe poses, 12 fishing casts, 4 overhead holds, and 4 sleeping
401 phases. The options are 48 hairstyle/color combinations, 6 shirts, 4 pants,
402 3 skin tones, 4 hats and 2 glasses. Generated garment pixels are fitted to the
403 existing body's material masks; they preserve its silhouette, rather than
404 introducing independent body shapes. Long hair and accessories share the same
405 scalp registration. The preview lets reviewers compose every combination.
406 
407 | ID | Visual role | Age direction |
408 | --- | --- | --- |
409 | villager_01 | Shopkeeper | 48 |
410 | villager_02 | Blacksmith | 27 |
411 | villager_03 | Innkeeper | 53 |
412 | villager_04 | Farmer | 39 |
413 | villager_05 | Teacher | 44 |
414 | villager_06 | Retiree | 77 |
415 | villager_07 | Fisher | 72 |
416 | villager_08 | Doctor | 29 |
417 | villager_09 | Carpenter | 46 |
418 | villager_10 | Kid | 16 |
419 
420 ### Resource limits and reproduction
421 
422 The interrupted run did not finish exporting. The completed pipeline releases
423 scratch memory between source sheets and batches of standalone PNG writes, and
424 stops if resident memory after collection exceeds 2 GiB. A serial catalog/export
425 run measured **460.7 MiB peak resident memory** with `getrusage`; it took 104 s on
426 this machine. These are observations, not guaranteed limits on every transient
427 allocation. Run builds and tests serially on a 16 GB Mac. Determinism tests use
428 one temporary directory under the system temp directory and remove it afterward.
429 No browser or external service is needed for rebuilding.
430 
431 Sparse action particles use an explicit 12% occupied-sample threshold while
432 ordinary sprites retain 50%. The last sparkle frame previously vanished at
433 native resolution; focused tests now check all sixty nonempty effect frames and
434 four distinct phases per sequence. This sampling choice preserves original
435 particle colors and registration, with binary output alpha.
436 
437 ### Five weakest round-three assets
438 
439 1. `villager_02.portrait.sad`: its lowered eyes read, but its mouth and brow are
440    subtler than the other villagers' sad expressions at phone size.
441 2. `wardrobe.glasses.round.walk.down.0`: the dark rims occupy much of the tiny
442    face, especially when combined with a low hat brim.
443 3. `player.cast.up.1`: the rod and line are highly compressed to remain inside
444    the 16×32 frame; the release pose has limited reach.
445 4. `interior.fixture.tv`: the blue screen is clear, but the small wooden casing
446    and controls simplify to a few pixels beside the richer furniture.
447 5. `interior.floor.03`: repeated pale parquet creates a busy pattern across a
448    large room; it works best in smaller areas broken up by rugs and furniture.
449 
450 ### Round-three validation and handoff
451 
452 Completed after the interrupted session, with no additional image generations,
453 workers or browsers. Heavy commands ran one at a time.
454 
455 | Command / review | Result |
456 | --- | --- |
457 | `bun run art:catalog` | 73 selected sheets; 1,024 authored entries |
458 | `bun run art:snap` | 8,374 frames; 35 atlases; all 13 scene exports |
459 | `bun test tools/art` | 39 passed, 0 failed; 419,030 assertions |
460 | Deterministic rebuild test | Two complete builds produced identical SHA-256 hashes for every output |
461 | `bun run art:typecheck` | Passed |
462 | `bun run check` (once at the end) | Passed: project typechecks, 69 tests, and content validation |
463 | Generated preview JavaScript | Parsed successfully without opening a browser |
464 | Visual review | Portrait lineup, wardrobe, effects, farmhouse, winter farm, store, blacksmith and inn inspected |
465 | `git diff --check` | Passed |
466 
467 Changes are confined to `tools/art/` (sources, prompts, extraction catalogs,
468 layer composition, scenes, preview and tests), ignored exports in
469 `apps/client/public/assets/gen/`, `apps/client/public/assets/CREDITS.md`, and
470 this document. No game code or reference screenshot was added. No commit was
471 made. The pre-existing untracked `tasks/art-round3.md` remains untouched.
472 
473 Superseded task-only QA images and measurement helpers were removed. Tests
474 remove their system-temp export directory on completion. The 42.9 MiB of new
475 raw PNGs remain necessary provenance and reproducible-build inputs; generated
476 exports stay in the designated ignored directory.
477