Repository navigation
Version Packages - #169
Merged
Merged
Version Packages#169
Conversation
github-actions
Bot
force-pushed
the
changeset-release/main
branch
16 times, most recently
from
November 5, 2026 01:27
bf543b0 to
b0b7913
Compare
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
November 5, 2026 02:10
b0b7913 to
6799d11
Compare
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.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@typeonce/ritmo-browser@0.21.0
Minor Changes
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.Patch Changes
@typeonce/ritmo@0.21.0
Minor Changes
50597a8: Breaking (debug runtimes only): a runtime made with
debugfreezes every value it is handed, so mutating one afterwards throws where it mutates. Values were stored by reference: an object passed toGame.Command.spawn,commands.insert, a cell'sset/update, a resource write,emit,runtime.send, a next-stateset, orGame.Runtime.makestayed connected to the code that made it. Mutating it later changed the world with no write, sochangedreaders missed it, and arewindbrought back the mutated value instead of the checkpointed one. A debug runtime now deep-freezes each value as it is queued or written, and the mutation throws aTypeError. Typed arrays are skipped,MapandSetcontents stay writable, and runtimes withoutdebugbehave as before.If your game's tests or devtools sessions now throw, build a new value instead of mutating the one you handed over:
Runtime.ticknow points toFixedLoop.startfor ticking at a fixed rate from a frame loop. Theritmoskill now treats a variable a system closes over like a module variable: host input reaches systems through a resource, a sent event, or an input source service.d1d864d: Breaking: the packages require Node 22 or newer (Node 20 reached end of life on 2026-04-30).
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.87466e9: Breaking: a query's
each()returns entities, and values are read throughqueries.x.data. Matches, theirdatacells, andentity.proofare gone. Iterating no longer keeps an object per entity and query, so loops over many entities run up to 3x faster, a game-shaped frame about 2x faster, and memory no longer grows with each query.Every slot method takes the entity first. The fix for each old form:
match.data.x.get()data.x.get(entity)data.x.set(value),update(f)data.x.set(entity, value),update(entity, f)data.x.setRaw(raw),updateRaw(f)data.x.setRaw(entity, raw),updateRaw(entity, f)data.state.transition({ from, to })data.state.transition(entity, { from, to })data.state.update({ state, data })data.state.update(entity, { state, data })data.sprite?.get()data.sprite.get(entity),undefinedwhen it lacks the componentdata.note !== undefineddata.note.has(entity)commands.despawn(match.entity)commands.despawn(entity)match.entity.identity.idfound.value.data.x.get()afterqueries.q.get(id)queries.q.data.x.get(found.value)QueryMatch<S, Q>QueryEntity<S, Q>, withQueryData<Q>for the slotsQuery.Cells<Q>QueryData<Q>WriteCellForDescriptor<D>WriteSlotOf<D>match.entity.proof.positiondata.position.get(entity)single(),singleOptional(),get,getHandle,children, anddescendantsreturn entities too.ReadCellandWriteCellremain for resources.Entity.EntityRefnow takes<S, Root, Proves, Lacks, Relates>.Entity.EntityMut,Entity.ref, andEntity.mutare removed: only a query produces an entity.The type checks are the same or stricter: a read slot has no
set, a slot rejects an id or an entity whose query does not prove its component, and entities carry their proofs tocommands.Kept values changed.
queries.x.datakept past its run throws, as a kept match did. A kept entity no longer throws by itself: it keeps naming its entity, reading its current value, and throws once the entity no longer holds the component. It never reads another entity, since ids are never reused, but it does not re-check the query, so an entity that left throughwithoutstays readable. To follow an entity across runs and re-check the query, keepentity.idand resolve it withqueries.x.get(id), as before.RenderSynccallbacks are unchanged:context.data.x.get()still works. Lint messages name the new forms.Patch Changes
15e5aa9:
ritmo-tools fx: judge effects at native size, and see when an approved effect has changed. Ideas from PVFX Foundry.fx notesandfx renderlistchangedSinceApproved("frames 3-5 look different"), and the page shows it with Approve it as it is now. The status stays approved: only the person changes it. A palette edit counts as a change. A review saved before this has no hashes, and reports nothing until the effect is approved again.ritmo-fxskill adds a craft rule (each material dies its own way), the native-size question for the person, what to do withchangedSinceApproved, and PVFX Foundry's Strict tier as a reference to look at.explosiondraftanow sits on the floor, with thrown debris, embers, dust, and smoke that comes apart in clumps.Breaking:
fx renderwrites sprite sheets in rows of up to 8 frames, not one row, so a long effect stays within a device's texture limit. A game that reads each frame's rectangle from the JSON (frames["hit 0"].frame, as Pixi and Phaser do) needs no change. Replace code that computes a frame's place asx = frame * widthwithx = (frame % 8) * widthandy = Math.floor(frame / 8) * height.6b7df96:
ritmo-tools musicandsound: review all of a game's music on one page, and see when something approved has changed.music reviewtakes songs, audio files, and folders, and shows them all on a list with each one's status, filtered by what is left to do. A folder is searched for*.song.jsonand audio files, leaving out what the tool wrote beside a song (its render, its stems, its hum). What the person has not saved yet is written before another piece opens..wav,.flac,.mp3,.ogg,.m4a): play, loop, hear the loop point, read the length, loudness, and peak, approve or ask for changes, and comment on a stretch of time. Their reviews live in onemusic.review.jsonbeside the game'spackage.json, not beside the files, since those often sit in a folder that ships with the game.musicandsoundas it already did infx. When an approved song, sound, or file later differs,music notes,music render,sound notes, andsound renderlistchangedSinceApproved, and the page shows it with Approve it as it is now. The status stays approved: only the person changes it. An edit to words alone (anabout, a track's name) is no change. A review from before this keeps its approval, with nothing to compare against until it is approved again.Breaking:
music notesnow prints{ summary, music: [...] }for any paths, one entry per piece, withfile,kind, andreviewbeside what it printed before. Replace.status,.note,.comments,.edits, and.nextwith.music[0].statusand so on.music reviewprintsmusic(the list of what it found) in place ofsongandreview.f30c9c6:
ritmo-tools pixel: hold a frame, see an animation as a still, and check a tile's edges. Ideas from Pixelorama.pixel sheet --animations "attack=5,6x3,7,8"shows frame 6 for 3 beats, a beat being one frame at--fps. The JSON'sduration, the GIF, the recipe (sheet.frames[i].beats), and the page's player all follow it, the page sets it on the chosen frame, and the report lists each frame's time indurations.pixel sheetwrites<name>.<animation>.onion.png: a panel per step of playback, each frame over the one before in red and the one after in blue, so an agent that cannot watch an animation can see a jump, a drift, or a change of size.pixel lint tile.png --tile both(orx,y) warns of aseamwhen a tile's edges do not meet, andpixel preview tile.png --tile bothwrites it repeated.ritmo-pixel-artskill says when to use each, and that a game plays each frame for itsduration.Breaking: the sprite sheet JSON of
pixel sheetandfx renderno longer hasmeta.fps, since one rate would lose a frame's hold. Replacemeta.fps[name]with each frame's time,frames["<name> 0"].duration, in milliseconds. With Pixi, giveAnimatedSprite{ texture, time }objects built from those durations.d989c0b:
ritmo-tools pixel: review all of a game's pixel art with a person on one page, and read back what they said.pixel review <paths...>serves a local page (port 5193) with every PNG and text sprite under the folders named, by folder, each with its status. A person looks at each asset at whole-number zooms, opening as large as fits with 1× a key away, over a dark, light, checkerboard, or custom backdrop, plays sheets by animation with their durations, sees a tile repeated, lines the whole set up at one scale on a grid by size (picking several to compare or approve at once), approves or asks for changes, and drags over the art to pin a comment to an area of pixels on one frame. Each asset's lint against its nearestpixel.config.jsonshows beside it. What the tools write beside the art (previews, project PNGs, onion pictures, scaled copies, frame folders) is left out, and a fix shows as one row with what it was made from.pixel notes <paths...>prints asummaryof what is left, then each asset's status, note, open comments (numbered, with their area and frame), how many are resolved, its lint, andnext, changes asked first.pixel resolve <asset> <numbers...> --reply "..."marks comments done; the open page shows them with the reply.pixel notesand the page say which frames underchangedSinceApproved, and the page offers Approve it as it is now.pixel.review.jsonbeside the game'spackage.json, keyed by path, out of the folder that ships.review,notes, andresolveexit 0 or 2 only.pixel lintno longer runs out of memory on a picture of thousands of colors (a smooth app icon took gigabytes comparing every pair): past 512 colors it says the picture is not pixel art yet instead. On the review page and inpixel notes, a sheet frame with nothing drawn in it is anempty-frameerror.The
ritmo-pixel-artskill says when to open the review and how to act on it, and that approving on the page does not replace looking at the art in the game at display size.027634b: The
ritmo-prototypeskill prototypes where the fun lives. It used to start from a verb or the smallest goal, with one exception for story. Now it names five cases. For a verb, build the verb and its feedback. For goals, build the smallest goal. For a story, characters, or a mystery, write a small slice by hand; paper or text is fine when it is faster. For a place to explore, hand-build a small map with a landmark you can see before you can reach it and something off the obvious path. For a mood, bring in the look and sound early. Before this, a game about wandering and discovery got a one-screen loop as its prototype, which tests none of what makes it fun.@typeonce/ritmo-devtools@0.21.0
Minor Changes
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.Patch Changes
@typeonce/ritmo-math@0.21.0
Minor Changes
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.Patch Changes
@typeonce/ritmo-netcode@0.21.0
Minor Changes
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.Patch Changes
@typeonce/oxlint-plugin-ritmo@0.21.0
Minor Changes
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.Patch Changes
87466e9: Breaking: a query's
each()returns entities, and values are read throughqueries.x.data. Matches, theirdatacells, andentity.proofare gone. Iterating no longer keeps an object per entity and query, so loops over many entities run up to 3x faster, a game-shaped frame about 2x faster, and memory no longer grows with each query.Every slot method takes the entity first. The fix for each old form:
match.data.x.get()data.x.get(entity)data.x.set(value),update(f)data.x.set(entity, value),update(entity, f)data.x.setRaw(raw),updateRaw(f)data.x.setRaw(entity, raw),updateRaw(entity, f)data.state.transition({ from, to })data.state.transition(entity, { from, to })data.state.update({ state, data })data.state.update(entity, { state, data })data.sprite?.get()data.sprite.get(entity),undefinedwhen it lacks the componentdata.note !== undefineddata.note.has(entity)commands.despawn(match.entity)commands.despawn(entity)match.entity.identity.idfound.value.data.x.get()afterqueries.q.get(id)queries.q.data.x.get(found.value)QueryMatch<S, Q>QueryEntity<S, Q>, withQueryData<Q>for the slotsQuery.Cells<Q>QueryData<Q>WriteCellForDescriptor<D>WriteSlotOf<D>match.entity.proof.positiondata.position.get(entity)single(),singleOptional(),get,getHandle,children, anddescendantsreturn entities too.ReadCellandWriteCellremain for resources.Entity.EntityRefnow takes<S, Root, Proves, Lacks, Relates>.Entity.EntityMut,Entity.ref, andEntity.mutare removed: only a query produces an entity.The type checks are the same or stricter: a read slot has no
set, a slot rejects an id or an entity whose query does not prove its component, and entities carry their proofs tocommands.Kept values changed.
queries.x.datakept past its run throws, as a kept match did. A kept entity no longer throws by itself: it keeps naming its entity, reading its current value, and throws once the entity no longer holds the component. It never reads another entity, since ids are never reused, but it does not re-check the query, so an entity that left throughwithoutstays readable. To follow an entity across runs and re-check the query, keepentity.idand resolve it withqueries.x.get(id), as before.RenderSynccallbacks are unchanged:context.data.x.get()still works. Lint messages name the new forms.@typeonce/ritmo-pixi@0.21.0
Minor Changes
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.Patch Changes
@typeonce/ritmo-render@0.21.0
Minor Changes
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.Patch Changes
87466e9: Breaking: a query's
each()returns entities, and values are read throughqueries.x.data. Matches, theirdatacells, andentity.proofare gone. Iterating no longer keeps an object per entity and query, so loops over many entities run up to 3x faster, a game-shaped frame about 2x faster, and memory no longer grows with each query.Every slot method takes the entity first. The fix for each old form:
match.data.x.get()data.x.get(entity)data.x.set(value),update(f)data.x.set(entity, value),update(entity, f)data.x.setRaw(raw),updateRaw(f)data.x.setRaw(entity, raw),updateRaw(entity, f)data.state.transition({ from, to })data.state.transition(entity, { from, to })data.state.update({ state, data })data.state.update(entity, { state, data })data.sprite?.get()data.sprite.get(entity),undefinedwhen it lacks the componentdata.note !== undefineddata.note.has(entity)commands.despawn(match.entity)commands.despawn(entity)match.entity.identity.idfound.value.data.x.get()afterqueries.q.get(id)queries.q.data.x.get(found.value)QueryMatch<S, Q>QueryEntity<S, Q>, withQueryData<Q>for the slotsQuery.Cells<Q>QueryData<Q>WriteCellForDescriptor<D>WriteSlotOf<D>match.entity.proof.positiondata.position.get(entity)single(),singleOptional(),get,getHandle,children, anddescendantsreturn entities too.ReadCellandWriteCellremain for resources.Entity.EntityRefnow takes<S, Root, Proves, Lacks, Relates>.Entity.EntityMut,Entity.ref, andEntity.mutare removed: only a query produces an entity.The type checks are the same or stricter: a read slot has no
set, a slot rejects an id or an entity whose query does not prove its component, and entities carry their proofs tocommands.Kept values changed.
queries.x.datakept past its run throws, as a kept match did. A kept entity no longer throws by itself: it keeps naming its entity, reading its current value, and throws once the entity no longer holds the component. It never reads another entity, since ids are never reused, but it does not re-check the query, so an entity that left throughwithoutstays readable. To follow an entity across runs and re-check the query, keepentity.idand resolve it withqueries.x.get(id), as before.RenderSynccallbacks are unchanged:context.data.x.get()still works. Lint messages name the new forms.Updated dependencies [50597a8]
Updated dependencies [15e5aa9]
Updated dependencies [6b7df96]
Updated dependencies [d1d864d]
Updated dependencies [f30c9c6]
Updated dependencies [d989c0b]
Updated dependencies [027634b]
Updated dependencies [87466e9]
@typeonce/ritmo-tools@0.21.0
Minor Changes
15e5aa9:
ritmo-tools fx: judge effects at native size, and see when an approved effect has changed. Ideas from PVFX Foundry.fx notesandfx renderlistchangedSinceApproved("frames 3-5 look different"), and the page shows it with Approve it as it is now. The status stays approved: only the person changes it. A palette edit counts as a change. A review saved before this has no hashes, and reports nothing until the effect is approved again.ritmo-fxskill adds a craft rule (each material dies its own way), the native-size question for the person, what to do withchangedSinceApproved, and PVFX Foundry's Strict tier as a reference to look at.explosiondraftanow sits on the floor, with thrown debris, embers, dust, and smoke that comes apart in clumps.Breaking:
fx renderwrites sprite sheets in rows of up to 8 frames, not one row, so a long effect stays within a device's texture limit. A game that reads each frame's rectangle from the JSON (frames["hit 0"].frame, as Pixi and Phaser do) needs no change. Replace code that computes a frame's place asx = frame * widthwithx = (frame % 8) * widthandy = Math.floor(frame / 8) * height.6b7df96:
ritmo-tools musicandsound: review all of a game's music on one page, and see when something approved has changed.music reviewtakes songs, audio files, and folders, and shows them all on a list with each one's status, filtered by what is left to do. A folder is searched for*.song.jsonand audio files, leaving out what the tool wrote beside a song (its render, its stems, its hum). What the person has not saved yet is written before another piece opens..wav,.flac,.mp3,.ogg,.m4a): play, loop, hear the loop point, read the length, loudness, and peak, approve or ask for changes, and comment on a stretch of time. Their reviews live in onemusic.review.jsonbeside the game'spackage.json, not beside the files, since those often sit in a folder that ships with the game.musicandsoundas it already did infx. When an approved song, sound, or file later differs,music notes,music render,sound notes, andsound renderlistchangedSinceApproved, and the page shows it with Approve it as it is now. The status stays approved: only the person changes it. An edit to words alone (anabout, a track's name) is no change. A review from before this keeps its approval, with nothing to compare against until it is approved again.Breaking:
music notesnow prints{ summary, music: [...] }for any paths, one entry per piece, withfile,kind, andreviewbeside what it printed before. Replace.status,.note,.comments,.edits, and.nextwith.music[0].statusand so on.music reviewprintsmusic(the list of what it found) in place ofsongandreview.d1d864d: Breaking: the packages require Node 22 or newer (Node 20 reached end of life on 2026-04-30).
engines.nodeis>=22for@typeonce/ritmo,-browser,-render,-pixi,-math, and-netcode;>=22.12for@typeonce/oxlint-plugin-ritmo(oxlint's own floor);>=22.15for@typeonce/ritmo-devtools(unchanged); and>=22.19for@typeonce/ritmo-tools(what@effect/platform-nodeneeds). On Node 20, upgrade Node:nvm install 22(or 24), or"node": ">=22"in your CI's setup step.f30c9c6:
ritmo-tools pixel: hold a frame, see an animation as a still, and check a tile's edges. Ideas from Pixelorama.pixel sheet --animations "attack=5,6x3,7,8"shows frame 6 for 3 beats, a beat being one frame at--fps. The JSON'sduration, the GIF, the recipe (sheet.frames[i].beats), and the page's player all follow it, the page sets it on the chosen frame, and the report lists each frame's time indurations.pixel sheetwrites<name>.<animation>.onion.png: a panel per step of playback, each frame over the one before in red and the one after in blue, so an agent that cannot watch an animation can see a jump, a drift, or a change of size.pixel lint tile.png --tile both(orx,y) warns of aseamwhen a tile's edges do not meet, andpixel preview tile.png --tile bothwrites it repeated.ritmo-pixel-artskill says when to use each, and that a game plays each frame for itsduration.Breaking: the sprite sheet JSON of
pixel sheetandfx renderno longer hasmeta.fps, since one rate would lose a frame's hold. Replacemeta.fps[name]with each frame's time,frames["<name> 0"].duration, in milliseconds. With Pixi, giveAnimatedSprite{ texture, time }objects built from those durations.215ba15:
ritmo-tools pixel: one-pixel outlines, bent grids, and a shrink that keeps strokes whole, after ToPixel.outlinesin a recipe,--outlines auto|on|off, Outlines on the page;"auto"by default): when the picture's dark strokes are about one cell wide, a stroke a grid line split between two pixels goes back to one, never breaking the outline or a corner, and followed lines keep off dark strokes. The report'sgrid.outlinessays whether it ran."off","straight"(every line placed at once, each on a strong edge with every gap near the cell size, instead of one after another), or"bend"(lines placed in each row and column of cells on their own, for a grid the generator warped). The page draws bent lines bent.--shrink-to, Size) carries outlines over as strokes: thinned back to one pixel without breaking, one-pixel steps turned into diagonals. A one-pixel ring shrunk from 16 to 11 pixels stays whole, where it used to lose its sides.Breaking: a recipe's
followis"off","straight", or"bend", no longertrueorfalse, and--followtakes one of them. Replace"follow": truewith"follow": "straight"(--follow straight), and"follow": falsewith"follow": "off"(or leave it out).d989c0b:
ritmo-tools pixel: review all of a game's pixel art with a person on one page, and read back what they said.pixel review <paths...>serves a local page (port 5193) with every PNG and text sprite under the folders named, by folder, each with its status. A person looks at each asset at whole-number zooms, opening as large as fits with 1× a key away, over a dark, light, checkerboard, or custom backdrop, plays sheets by animation with their durations, sees a tile repeated, lines the whole set up at one scale on a grid by size (picking several to compare or approve at once), approves or asks for changes, and drags over the art to pin a comment to an area of pixels on one frame. Each asset's lint against its nearestpixel.config.jsonshows beside it. What the tools write beside the art (previews, project PNGs, onion pictures, scaled copies, frame folders) is left out, and a fix shows as one row with what it was made from.pixel notes <paths...>prints asummaryof what is left, then each asset's status, note, open comments (numbered, with their area and frame), how many are resolved, its lint, andnext, changes asked first.pixel resolve <asset> <numbers...> --reply "..."marks comments done; the open page shows them with the reply.pixel notesand the page say which frames underchangedSinceApproved, and the page offers Approve it as it is now.pixel.review.jsonbeside the game'spackage.json, keyed by path, out of the folder that ships.review,notes, andresolveexit 0 or 2 only.pixel lintno longer runs out of memory on a picture of thousands of colors (a smooth app icon took gigabytes comparing every pair): past 512 colors it says the picture is not pixel art yet instead. On the review page and inpixel notes, a sheet frame with nothing drawn in it is anempty-frameerror.The
ritmo-pixel-artskill says when to open the review and how to act on it, and that approving on the page does not replace looking at the art in the game at display size.Patch Changes
ea008a4:
ritmo-toolsdepends on Effect 4.1.1 (effect,@effect/platform-node, and@effect/platform-node-shared, still pinned exactly and together).f715940:
pixel reviewandpixel notesfixes, from trying them on real games:pixel fixdoes, puttingX.fixed.pngin place ofX.png). Saves used to fail until a reload, which lost what was unsaved. The old review stays inpixel.review.jsonunder its old name, andpixel noteslists it undergone.pixel notesno longer says "Leave it as it is" about an approved asset with open comments. An asset with a note or comments but no status comes ahead of untouched ones, and the summary counts it apart.pixel reviewandpixel noteswarn to name narrower folders. The page gets a picture's file as it is, rather than a copy written for it up front, so a large folder takes about a third less time and far less memory.