Repository navigation
ritmo-tools pixel: review a game's pixel art on one page, and read back what the person said - #187
Merged
Merged
Conversation
The music review walked folders, named files by their path, and found the game's root on its own. The pixel review needs the same, so the three move to src/internal/files.ts and music uses them from there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
…eet back from its JSON A review holds a status, a note, and comments pinned to an area of one frame. Approving keeps a hash of each frame's decoded pixels and its duration, so a re-export that looks the same is no change while new pixels or new timing are named, frame by frame. A transparent pixel hashes the same whatever color it hides, since nobody can see it. Sheets are read back from the JSON pixel sheet writes, or from Aseprite's, so the page can play each animation with its durations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
pixel review serves the art under the named folders on a local page. The server finds, decodes, hashes, and lints every asset (against its nearest pixel.config.json, each frame of a sheet apart), so the page only draws. An id names an asset the server found, never a path it reads. pixel notes reads back what the person said, the changes first, and pixel resolve closes comments by number, the way fx resolve does. The review is one pixel.review.json at the game's root, out of the folder that ships. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
Every asset by folder with its status, one asset at a whole-number zoom over a backdrop of the person's choosing, sheets playing by animation, and the whole set side by side at its own size. Dragging over the art pins a comment to that area, and the agent's lint results sit beside it. Each panel redraws on its own, so typing is never interrupted when the agent writes, and the review stays owed until the server has it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
…ing out of memory A game's folder holds more than pixel art: a smooth 512 px app icon has tens of thousands of colors, and comparing every pair of them for near-duplicates took gigabytes and never finished, so the review of a game with an icon in it crashed. Past 512 colors the lint now says the picture is not pixel art yet, and only the first few pairs are kept as text below that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
A sheet frame with nothing drawn in it is an error on that frame, since it plays as a blink. The read kept for each asset holds its size, not its pixels. A broken asset still names the rules it would be linted against. Long file paths wrap in the side panel, and the playback bar stays one row on a phone. V, not Tab, switches between one asset and the whole set, since Tab moves through the page's controls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
The built review page ships in dist/pixel/page and its compiled source is left out, as for the other review pages; pack-check holds both. The README, the ritmo-pixel-art skill, and the website's tools page say what the review is for and how an agent acts on it, and the skill's Judging rule now says an approval on the page still leaves the art to be seen in the game at display size. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
… PNG or a JPEG
The decoder's own words ("unrecognised content at end of stream") named
nothing the person could act on; the other pixel commands already say it
this way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HendNec6exyZNa2zBVD977
…out on a grid Tried on the real games' art: at 1× a 24×24 sprite is too small to judge or to press on, and big pictures made the stage scroll. - An asset opens at the largest whole zoom that fits, up to 16×, and a picture too big for the stage shrinks to fit. 0 shows it at 1×, a zoom the person picks stays for the next asset, and F fits again. A zoom kept from a small asset no longer makes a canvas too big to draw. - It fits again when the stage changes size: WebKit first measures it before it has its full height. - The set is a grid by size, at one scale taken from its median asset. A picture too big for the grid is smaller and says its own zoom. - Nothing moves when it needn't: 1× and Fit stay in the bar, and the picks bar stays above the set, stuck 8px under the top bar as it scrolls. - The top bar's two pills line up, and so do the icons in the list and tiles. The View section starts closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Sandro · project thread
ritmo-tools pixelgets the review the music has:pixel review <paths...>serves a local page with all of a game's pixel art,pixel notesreads back what the person said, andpixel resolvecloses their comments. It follows #186 in shape (one review file at the game's root, a list by folder with a filter, approvals that notice a change), and the page is in the pixel fixer's look.What the person gets
0shows 1×, a zoom the person picks stays for the next asset, andFfits again. It sits over a dark, light, checkerboard, or custom backdrop, with a 3×3 repeat for tiles. A sheet plays each animation with its own durations, and the playback bar pauses and steps.pixel.config.json(each frame of a sheet linted on its own, and Show rings a rule's pixels), plus the files the asset comes from.pixel notessay which frames, and Approve it as it is now takes the new version.What the agent gets
pixel notesprints{ summary, assets, gone }. Each asset hasfile,status,note, its open comments numbered withwhere("pixels 1,2 to 2,2"),resolved,changedSinceApproved, the lint as lines, andnext. The order is changes asked, then changed since approved, then new, then approved.pixel resolve <asset> <numbers...> --replyworks likefx resolve, and the open page shows the result within a couple of seconds.review,notes, andresolveexit 0 or 2, never 3 or 4.ritmo-pixel-artskill says when to open the review and how to act on it. Its Judging rule now says an approval on the page still leaves the art to be looked at in the game at display size.Decisions to check
*.preview.png,*.project.png,*.onion.png,*@Nx.pngand its JSON,*.frames/,node_modules, and hidden folders.X.fixed.png,.sheet.png,.pixel.png, and.render.pngshow as one row with their source named..txtfile beside a shown PNG with the same stem (X.txtorX.sprite.txt) is taken as that PNG's source, so it gets no row of its own..sheet.pngnamesX.pngas its source when that file exists, even whenX.pngis also a.fixed.png's source.empty-frameerror on that frame. The sheetpixel sheetmade from the fire-spirit sample has one, and on the page it plays as a blink.pixel lintcompared every pair of colors for near-duplicates, which ran out of memory on a smooth 512 px app icon (tens of thousands of colors). Past 512 colors it now says the picture is not pixel art yet. This affectspixel lintandpixel checktoo, not just the review.Verification
pnpm run check,pnpm --dir website build, andpnpm pack:checkpass. The tarball hasdist/pixel/page/index.htmland leaves outdist/pixel/review/.test/pixel-review.test.tshas 26 tests:.txtskipped in a folder and refused when named outright, a foreignatlas.jsonshown as a still;notesandresolvethrough the CLI, with their exit codes.buildandbuild:page, thennode packages/tools/dist/cli.js) and against the source through Vite. The fixture game was a temp folder with its ownpackage.json: 95 assets, made from the website's town tiles, characters and nature art, text sprites under nested configs, a sprite rendered withpixel render, a picture fixed withpixel fix, and a sheet made withpixel sheetfrom the fire-spirit sample. All 28 checks pass on both. They check:aria-pressedand saves hashes;pixel notes, and Approve it as it is now clears the flag;pixel resolveshows on the open page, and the count drops;pixel notesran on a copy of Spirit Call'spublic/with its ownpackage.json. That run found the out-of-memory crash on its app icons, and it now finishes in about 2 seconds. Spirit Call's checkout has no changes.Tried on the real games' art
After the review above, this ran on copies of the art folders of Still Time, Warden, Spirit Call, Dungeon Paint, Pixel Probe, and Style Probe (208 assets on one page), in Chromium and WebKit, in dark and light. The real game folders were not changed. Sandro looked at the page, which led to the last commit: the zoom that fits, the grid, and nothing moving when it needn't.
All 208 draw, none scrolls by default, each game's review lands at its own root, a re-save of the same pixels doesn't flag an approved asset, and one changed pixel does.
Known problems, left for a follow-up
pixel fixputsX.fixed.pngin place ofX.png, the page still holds the old name. Every later save then fails withno such assetuntil a reload, which loses what wasn't saved.pixel resolvereaches the open page.pixel notesmisleads on open comments. An approved asset with an open comment says "Leave it as it is", and an asset with a comment but no status click counts as not reviewed.spirit-call/art(2128 PNGs, mostly 3D renders) the server can't answer for about 5 minutes, andpixel notestakes 314 s. Nothing warns about it.sourceonly shows when the source sits beside the PNG. Still Time keeps its sources in another folder, so its notes don't name them.Not covered
touch-action: none.Generated by Claude Code