Pixelbolt test suite at v0.9.0 (2c180d6), run 2026-10-19 with: node --test Windows 11 Pro (build 26200), Node.js v24.19.0 ✔ pose instances flip their grid, anchor and points inside the part (4.6024ms) ✔ mirrored poses reflect parts, points and markers around the origin corner and inherit timing (1.1062ms) ✔ pose origins become recipe or frame anchors and markers become atlas points (0.9171ms) ✔ autotile compiler composes every blob mask from the template pieces its neighbours call for (3.4703ms) ✔ autotile variants become palette-cycled frames with one animation per mask (2.6024ms) ✔ the autotile op draws the quarters a mask selects, exactly like four copies, and the compiler emits one per frame (8.4234ms) ✔ canvas-only overlays survive unrelated base edits but refuse changes to the frames they touch (8.4688ms) ✔ PNG import keeps up to 256 colours as compact, lossless palette grids (4.0006ms) ✔ a compiled mirror placed by its anchor draws exactly what drawFrame draws when flipping the original (3.5945ms) ✔ hex shorthand, alpha and named colors (1.2864ms) ✔ grid dots skip existing pixels, with exact palette colors (2.3676ms) ✔ grid shape and color errors include the exact source path (0.2653ms) ✔ non-square stamp rotates clockwise and flips before rotation (0.3119ms) ✔ Bresenham line includes both endpoints in every direction (0.4575ms) ✔ outlined ellipse has a transparent center; rectangles can be outlined (0.2991ms) ✔ flood fill respects boundaries and fills the target region exactly (0.2159ms) ✔ clear erases alpha and replace matches the full RGBA value (0.1791ms) ✔ layer opacity applies once after the layer is flattened (0.2053ms) ✔ frame inheritance copies pixels without mutating the parent (0.262ms) ✔ animation direction preserves timings and avoids duplicate pingpong endpoints (0.2096ms) ✔ atlas positions include scaled padding and no color interpolation (0.587ms) ✔ clipping warns once, and invalid fill seeds are rejected (0.2684ms) ✔ invalid references, duplicate names, typos and resource limits fail early (2.6629ms) ✔ prototype-like palette keys are safe and are not inherited (0.2149ms) ✔ integer scaling replicates pixels exactly (0.0777ms) ✔ portable output names reject devices, case collisions and null options (0.3552ms) ✔ dither draws a canvas-anchored ordered pattern, ramps density and respects over/erase (4.5506ms) ✔ noise dither is seeded and non-periodic, and a rising density only ever adds pixels (12.045ms) ✔ value dither grows seeded clumps of a chosen size and keeps density as the share of pixels drawn (90.3281ms) ✔ outline adds inside, middle, width and direction masks (1.1404ms) ✔ rewrite rules grow, clean and decorate deterministically (3.2785ms) ✔ cleanup finds doubled corners and strays without touching filled areas or right-angle corners (0.8835ms) ✔ a cleanup patch proposes corrections with a report, and diagnostics count what it would change (19.3959ms) ✔ rotation keeps colours, turns around the pivot pixel and is exact at right angles (2.0824ms) ✔ easing presets start at 0, end at 1 and keep their character (0.3463ms) ✔ diorama: the committed sources match build.mjs (135.4301ms) ✔ diorama: every scene, lit or re-themed, keeps exactly its palette (378.3207ms) ✔ diorama: the hero is drawn behind the barrel it walks past, and the smear only shows during the strike (100.5481ms) ✔ the studio keeps one draft with its name and time, and forgets it on request (1.0732ms) ✔ a draft that cannot be stored or read never breaks the studio (0.4203ms) ✔ Emberfall double jump, landing, dash cooldown, pause and restart form a coherent movement cycle (3.996ms) ✔ Emberfall elemental interactions persist and charged shots consume breakable health (2.5467ms) ✔ Emberfall checkpoint healing, death, retry and portal gating preserve progression (0.5227ms) ✔ Emberfall guided tour traverses gaps, destroys scenery, defeats boss and wins without unbounded effects (99.2074ms) ✔ PNG encodes exact RGBA scanlines including transparency (1.5426ms) ✔ APNG contains exact durations, loop flag and source replacement (0.6116ms) ✔ bundle emits CSS for variable duration and multi-row atlas (19.5157ms) ✔ exports are deterministic, including ZIP bytes (5.2126ms) ✔ export refuses overwrite before changing any existing files (29.4085ms) ✔ all bundled examples validate and produce complete exports (16.6997ms) ✔ formatJSON keeps short records on one line and grids one row per line, and parses back to the same value (0.7425ms) ✔ clipping reports each source location and pixel count (4.813ms) ✔ copy takes rectangles from symbols or earlier frames, with transforms, and validates its source (1.694ms) ✔ frame copies remap exact colours named by palette key or hex (1.0437ms) ✔ outline wraps the current buffer, 4-connected by default or 8-connected with diagonal (0.667ms) ✔ remap recolors palette characters for one operation only (0.4324ms) ✔ frame palettes recolor declared keys for that frame, including symbols and corrections (1.5282ms) ✔ layer palettes recolor keys for one layer only, on top of the frame palette (2.2198ms) ✔ wrapping translation scrolls pixels around the canvas without clipping (0.2056ms) ✔ anchors and named points reach the atlas in exported pixels with a normalized pivot (1.0002ms) ✔ trimmed atlases pack visible bounds deterministically and keep full-canvas source coordinates (1.129ms) ✔ tile view repeats frames 3x3 and reports doubled edges and wrap steps instead of edge equality (2.6836ms) ✔ palette file references and astral grid characters fail with actionable paths (0.3726ms) ✔ every fluid example compiles to its golden recipe, using only its palette and grid operations (1897.9728ms) ✔ looping examples close their loop and one-shot examples end empty or at rest (50.9817ms) ✔ the committed fluid GIFs match the examples (106.0762ms) ✔ heat rises and curls, smoke thins, obstacles stay clear and a still pool stays still (19.9925ms) ✔ sparks draw as blocks of their size, with a streak back along their path (4.0398ms) ✔ in a liquid, spray ends where it falls back into the water and a bubble bursts in a ring, then two droplets (13.4458ms) ✔ depth bands stay level under water standing on the surface (0.9117ms) ✔ whitewater throws spray where water lands and sheds drops off a fast stream (17.8092ms) ✔ emitters can fall off toward their rim, orbit on an ellipse and lay a smooth trail (10.2541ms) ✔ loops repeat their forcing, blend their seam and wrap sparks round (49.1514ms) ✔ fluid sources fail early with paths an agent can act on (86.0429ms) ✔ limits are reported with the effect path, extreme settings stay finite, and any palette key draws its own colour (162.2595ms) ✔ the fluid schema lists exactly the fields the compiler reads (58.5484ms) ✔ fluid sources compile from the CLI with a shared palette, and preview and sequence accept them (608.747ms) ✔ MCP pixel_compile builds fluid sources and pixel_help serves their schema (100.5489ms) ✔ the documented fluid example compiles as written (39.9712ms) ✔ the package ships the fluid schema and example sources (5.8726ms) ✔ effects compile deterministically into ordinary frames, one animation per effect (11.576ms) ✔ gravity, floors, trails, variants, remaps and dissolve bake into stamps, grids, lines and pixels (2.9739ms) ✔ looping effects warm up so the first frame continues the last (1.0517ms) ✔ effect sources fail early with paths an agent can act on (2.3102ms) ✔ rotated pose parts bake into editable symbols and carry their points (5.7205ms) ✔ tweened poses interpolate offsets and angles, switch shapes at the eased midpoint and keep attachments (4.5626ms) ✔ scene trajectories ease each segment and still land on whole pixels (2.8468ms) ✔ the CLI compiles effect sources and keeps their shared palette link (611.5783ms) ✔ GIF frames, colours, timing and loop flag are read back exactly by a separate decoder (3.5541ms) ✔ GIF blends onto a background instead of thresholding, and keeps a sequence's length when rounding delays (0.688ms) ✔ GIF uses a table per frame when the animation needs more than 256 colours, and never quantizes (22.4865ms) ✔ GIF compression survives dictionary resets and 12-bit codes on noisy frames (44.7455ms) ✔ a busy opaque animation keeps unchanged pixels under a transparent index and stays within 1.5x of ffmpeg, every frame exact (1326.6074ms) ✔ GIF writes the end code as wide as a decoder reads it after the last code fills the table (0.4629ms) ✔ a sprite with transparency is cleared only where a pixel turns transparent, also when the loop restarts (0.8941ms) ✔ GIF keeps unchanged pixels only where a table has room, and stays exact when it has none (3.5103ms) ✔ an animation exports as a GIF with a default scale, notes about what GIF cannot keep, and named errors (50.5782ms) ✔ CLI gif writes only the requested file and refuses to replace it (639.5373ms) ✔ MCP pixel_render writes GIFs on request and leaves nothing behind when one is refused (698.3057ms) ✔ framesGIF times frames on the frame-rate grid, counts plays and keeps every colour of every frame (2.1303ms) ✔ numbered frames are read in number order, with gaps and other files reported and mixed sequences refused (0.4984ms) ✔ CLI gif-frames turns a folder of PNG frames into an exact GIF and writes only --out (1099.2034ms) ✔ grids read pixels back as palette keys, transparency and one shared legend (8.4949ms) ✔ inspection keeps frame order, crops regions and rejects bad options with paths (1.8693ms) ✔ contact sheet scales cells exactly over a checkerboard inside dark gutters (0.565ms) ✔ automatic layout picks the largest readable scale and enforces size limits (58.7882ms) ✔ a stride picks the A or B frames of a strobe that evenly spaced samples would mix (60.8552ms) ✔ CLI inspect takes --step and --offset (574.6951ms) ✔ the legacy CLI agrees on help, stdin validation, errors and every rendered byte (1887.5864ms) ✔ both CLI names initialize Pixelbolt and expose the same eight MCP tools and schemas (194.1465ms) ✔ CLI help describes its text output and commands for checkout and portable builds (85.1771ms) ✔ CLI consumes stdin, emits machine-readable diagnostics and handles unknown flags (254.1261ms) ✔ CLI init protects an existing recipe with an actionable JSON error and honours --force (258.488ms) ✔ MCP handshake, discovery, help, errors and render work over stdio (32.7087ms) ✔ MCP pixel_inspect returns a contact sheet and ruled grids, saving only its revision (14.9061ms) ✔ MCP revisions let pixel_patch edit, compare and export without resending the recipe (45.4856ms) ✔ MCP revisions from validate, inspect and paint survive process restarts before export (331.6543ms) ✔ MCP render previews every frame or an animation in playback order, with exact timing and cells (226.9835ms) ✔ CLI patch previews by default and writes only the requested recipe and image (482.5864ms) ✔ MCP exports a maximum-length animation with a bounded, explicit sampled preview (423.2824ms) ✔ CLI inspect prints cells and grids, and writes a PNG only when asked (571.6395ms) ✔ studio serves only its assets and exports ZIP over same-origin requests (488.193ms) ✔ studio returns frames for a video editor as one ZIP, built as the sequence command builds them (94.5203ms) ✔ every sample the studio lists is served, and the sidebar counts the list itself (2.2208ms) ✔ MCP answers an oversized request with an error, recovers its id and keeps serving (52.0866ms) ✔ MCP compiles pose sources and autotile templates into revisions it can render and review in scenes (71.0251ms) ✔ MCP imports PNGs, applies overlays, explains topics and resolves palettes only inside its root (55.4279ms) ✔ CLI resolves shared palettes, keeps the link when writing edits, builds autotiles and reports clipping (703.859ms) ✔ MCP compiles particle effects, explains the fx topic and previews cleanup patches (70.4041ms) ✔ registry source is metadata-only with a short description (190.1796ms) ✔ release workflow guards and assets use the renamed repository (3.2257ms) ✔ MCPB builds are byte-identical, including across CRLF and LF checkouts (111.3637ms) ✔ the standalone verifier runs bundled MCP help, render, import and scene export (638.0664ms) ✔ the verifier reports missing help and scene export assets and cleans up (485.4299ms) ✔ the verifier refuses traversal paths and a manifest/package version mismatch (114.7604ms) ✔ the builder refuses template versions, non-stable versions and different existing artifacts (132.6503ms) ✔ registry entry identifies the exact release bundle and preserves source metadata (8.4607ms) ✔ registry entry refuses bad tags, mismatched versions and packages in metadata (33.1284ms) ✔ registry entry cannot replace server.json or the bundle (3.4515ms) ✔ shipped JavaScript and studio resources make no external network calls (75.6753ms) ✔ the network check rejects regressions with the file and line (3.2056ms) ✔ the studio sends a self-only default Content-Security-Policy (43.3009ms) ✔ a generated pass rounds a shape: rims lean outward, the middle faces the viewer, and keys encode their directions (11.5874ms) ✔ the pass lines up with its colour recipe in a scene, and lights each side toward the light (6.1244ms) ✔ each separate shape rounds on its own; bevel flattens the top; mirrored frames get mirrored normals (2.89ms) ✔ detail raises lighter colours, ramps keep materials level, and the canvas border is not an edge unless frames wrap (2.9159ms) ✔ normals sources are validated with paths (0.7299ms) ✔ the normals schema lists exactly the fields the compiler accepts (8.0754ms) ✔ the CLI compiles a normals source whose recipe file sits beside it, keeping the colour palette link out of the pass (353.5336ms) ✔ MCP compiles a normals source from a saved revision and explains the normals topic (30.3103ms) ✔ the bundled spirit normal pass is what its source compiles to, and its night scene lights it (17.5368ms) ✔ patches address items by name, index or end and report what they replaced (6.5257ms) ✔ patch errors name the change that failed (1.2759ms) ✔ canvas painting replaces exact pixels after translated layers, and inherited frames keep the corrections (9.1107ms) ✔ paint rejects wrong targets and invalid pixels without mutating the source (0.8385ms) ✔ comparison reports changed, inherited, added and retimed frames with exact pixels (2.1395ms) ✔ comparison crops to the change, summarizes recolors and reports resized canvases (8.4201ms) ✔ native RGBA PNG and atlas roundtrip preserve hidden RGB, alpha, order, timing and once flags (9.3811ms) ✔ scene honors anchors, playback durations, state changes and persistent aftermath (4.2376ms) ✔ material passes align exactly; light direction changes hand-authored normals and unlit pixels remain intact (11.6799ms) ✔ tile repeat exposes a seeded doubled edge line and leaves a clean tile unflagged (1.0801ms) ✔ quality examples validate, preserve source poses and create deterministic scenes (100.0637ms) ✔ PF-EF-001: ZIP32 accepts 65,535 entries and preflights overflow before reading entries (413.6371ms) ✔ PF-EF-003: stamp references have the same string type as the schema (0.8683ms) ✔ PF-EF-002: oversized animation sheets can sample endpoints with honest omission metadata (116.1704ms) ✔ review views preserve pixels; silhouette is solid even for translucent detail (1.9802ms) ✔ layer isolation preserves inherited placement and validates the full source before hiding it (0.6192ms) ✔ onion neighbors follow reverse, sparse, repeated and pingpong positions with once boundaries (0.9295ms) ✔ diagnostics expose deliberate isolated pixels, undeclared colors and a loop jump, without rejecting holds (1.4166ms) ✔ regional grids preserve dots and masks, erase explicitly, and report inherited versus frame scope (17.8483ms) ✔ overlapping masked moves carry highlights and recoloring respects exact selected pixels (3.0562ms) ✔ named correction overlays survive identical rebuilds and refuse moved bases atomically (6.6363ms) ✔ large regional batches preflight bounded edit work without changing their source (0.6572ms) ✔ authored part replacements keep held objects attached and export timing in expanded order (2.3265ms) ✔ revisions persist across store instances and concurrent saves do not overwrite snapshots (34.1573ms) ✔ revision reads reject traversal and corruption, and never overwrite damaged files (15.9909ms) ✔ older rendered recipes recover the same revision id without modifying the bundle (20.8263ms) ✔ Canvas player respects durations, once/loop behavior, pause/resume and scaled atlas rectangles (4.2167ms) ✔ runtime helpers look up frames by time and draw trimmed, anchored and mirrored frames (2.3761ms) ✔ Canvas player keeps the full source size and draws trimmed frames at their offset (0.6989ms) ✔ placements can start hidden and be hidden again by a cue; named cues write related times once (11.7441ms) ✔ an attached placement follows a named point of another placement's current frame (2.9796ms) ✔ placements sorted by ground draw by the y of their placement point, so a hero passes behind a post (1.5676ms) ✔ tilemap placements expand a character map into frames, variants and animations as one declaration (11.3184ms) ✔ autotile legends pick compiled blob tiles from each cell's neighbours (6.0122ms) ✔ lighting scope "all" darkens plain assets too, and clipping names the placements (2.1818ms) ✔ banded lighting keeps a coloured light's hue: channels change band together (0.6477ms) ✔ null legend entries are context cells: matched by neighbours, never drawn (4.0917ms) ✔ scene file and revision references must be resolved before rendering (0.3484ms) ✔ anchor "frame" places each drawn frame by its own anchor, so animated placements follow per-frame anchors (1.4643ms) ✔ every operation field the schema lists is one the renderer accepts, and no others (15.9234ms) ✔ scene fields in the schema match what prepareScene accepts (11.1067ms) ✔ every generated schema defines each definition it references, and carries none it does not (10.1477ms) ✔ frame rates are exact fractions, including the NTSC rates (3.035ms) ✔ each video frame shows the pose that is active when the frame starts (2.6249ms) ✔ a sprite is enlarged by a whole number and placed on a video-sized canvas (1.8311ms) ✔ a recipe becomes numbered PNG frames with exact pixels, straight alpha, a sidecar and working instructions (8.236ms) ✔ cover fills the canvas with the sprite and crops what hangs over (2.4563ms) ✔ a background blends the alpha away, and the notes say what the frame grid changed (1.5523ms) ✔ a scene becomes a shot: each frame is the scene at that moment, and still moments share a file (1544.2504ms) ✔ CLI sequence writes a new folder for a recipe, an effects source and a scene, and never half of one (1188.5043ms) ✔ MCP render and scene tools write a sequence on request, beside what they already write (852.8682ms) ✔ validate --fps lists durations off the video frame grid and agrees with the sequence it predicts (259.1667ms) ✔ shade moves each pixel along its own ramp, clamped at the ends, and keeps the palette (9.259ms) ✔ ramps and shade validate with actionable paths (0.9937ms) ✔ shade placements darken whatever lies beneath along its ramps, so one shadow suits any floor (11.8743ms) ✔ ramp lighting moves colours along ramps instead of multiplying them, so a lit scene keeps its palette (1.6817ms) ✔ shared palette files may carry ramps, and themes override palette keys per scene or per asset (12.1269ms) ✔ new environment names take precedence and old names remain fallbacks when unset (0.7042ms) ✔ the build ZIP is deterministic, compressed where it helps and read back exactly (2.6313ms) ✔ the macOS and Linux archive keeps permissions, carries no host details and is read back exactly (347.8684ms) ✔ START HERE is one text with blocks for each system (0.4166ms) ✔ the macOS and Linux builds hold shell launchers marked executable, their own START HERE and the right runtime (696.5584ms) ✔ the build ships exactly the files npm pack ships (1200.401ms) ✔ every relative README link and image is shipped in the portable package (6.0098ms) ✔ the portable layout holds the package, runtime, launchers and build facts, and nothing from development (220.3507ms) ✔ a release build takes its files from the commit, whatever line endings the working copy holds (618.1295ms) ✔ the launcher is preview with a browser: the usual port, a free one beside it, and a dropped recipe opens (800.3826ms) ✔ the browser is opened by each system's own handler, with no shell to quote for (0.8764ms) ✔ the connect helper prints the same server for four agents and changes nothing (137.416ms) ✔ the Windows connect helper pauses after failure only when started without arguments (64.0742ms) ✔ an assembled build passes the release checks from a folder with a space and an accent (11845.4417ms) ✔ the built-in font covers printable ASCII, western European letters and common symbols, with tabular digits (6.8732ms) ✔ text is laid out with glyph spacing, line height and alignment (0.8704ms) ✔ the text operation draws exact glyph pixels, placed by align and changed by the usual transforms (5.5073ms) ✔ text errors name the field and the character (0.9966ms) ✔ the schema describes the text operation the renderer accepts (6.046ms) ✔ every module the browser imports is served by the studio and packed with scene exports (27.613ms) ✔ Tidewatch: every recipe validates without clipping warnings (133.0342ms) ✔ Tidewatch: compiled recipes and metadata match their authoritative pose, autotile and effect sources (60.2802ms) ✔ Tidewatch: particle effects keep the animations, anchor and hand-drawn frames the game uses (5.6186ms) ✔ Tidewatch: exported game atlases match the recipes byte for byte (1483.9067ms) ✔ Tidewatch: material passes stay aligned with their colour recipes (17.864ms) ✔ Tidewatch: Pixelbolt blob masks give every sand and grass cell a compiled tile (16.6765ms) ✔ Tidewatch: the game places sprites from atlas anchors and reads reach, held items and glyph advances from points (2.5559ms) ✔ Tidewatch: the island can be completed in a deterministic headless run (8.0236ms) ✔ rule tiles choose by the characters around a cell and may draw into a neighbouring cell (5.6738ms) ✔ rule chances and variant weights are seeded by position, and unweighted variants keep their old picks (7.9093ms) ✔ tilemap legends and rules fail with paths that name the entry (1.6263ms) ✔ a recipe tilemap composes symbols and autotile templates, and later operations see the composed result (2.8017ms) ✔ autotile variants may redraw the set from their own template (5.6992ms) ℹ tests 241 ℹ suites 0 ℹ pass 241 ℹ fail 0 ℹ cancelled 0 ℹ skipped 0 ℹ todo 0 ℹ duration_ms 13721.1791