PixelWeaver v0.5.0 /Changelog
On this page

#Changelog

#0.5.0

strictspec boundary validation, a refreshed editor theme, and a working CLI on strictcli 0.36.0

Context

Document validation moves to strictspec. The hand-rolled dual-target validator generator is gone; the constraint-manifest, part-manifest, and character-preview documents are now validated by generated strictspec validators at the at-rest and ingress boundaries, with the same diagnostics on both the Python and TypeScript sides. That tightening is deliberately breaking: documents the old validators silently accepted (float lexemes in integer fields, duplicate JSON object keys) are now rejected, and every governed document must carry the format_version gate. scripts/stamp-format-version.py stamps existing files on disk.

The CLI fix restores pixelweaver on strictcli 0.36.0, which requires every command to declare whether it changes anything and no longer lets handlers absorb unnamed keyword arguments.

Test isolation adopts the stricttest floor with fully denied socket stances; the server suite runs entirely in-process through wesktop's TestClient, so no test reaches the network. The Playwright e2e suite was also run for the first time since the strictspec work landed and is green end to end.

#Breaking

  • Stricter document validation (strictspec). Constraint-manifest, part-manifest, and character-preview documents are now validated by strictspec at the at-rest/ingress boundaries (project save/load, MCP, part export) instead of the old hand-rolled/pydantic validators. Documents that were previously accepted are now hard-rejected: a float lexeme in an integer field (e.g. seed: 7.0), duplicate JSON object keys (previously silently last-wins), and any governed document missing the new format_version gate. Projects are auto-stamped with format_version: 1 on save; to stamp existing on-disk documents run scripts/stamp-format-version.py <paths>.

#Features

  • Refreshed editor theme. The dark and light UI palettes (backgrounds, panels, text, accent, and status colors) now adopt the shared tinymoon design language for cross-app visual kinship. Layout, spacing, and the canvas dock chrome are unchanged.

#Fixes

  • **The pixelweaver CLI works again on strictcli 0.36.0.** The framework now requires every command to declare whether it changes anything, and no longer lets a handler absorb unnamed keyword arguments; all nine commands were updated.

#0.4.0

Draw-first workspace with a fully customizable UI, live drawing previews everywhere, solo layer view, and working keyboard shortcuts

Context

The app used to open as an overwhelming 15-tab pile with invisible strokes and selections. This release ships a curated minimal default where every feature remains available through a data-driven Customize system, plus complete before/during-draw feedback so you always see what a tool will paint.

#Features

  • Solo a single layer. Alt+click a layer's eye (or press /) to isolate one layer and hide the rest.
  • Pixel-accurate shape previews. Rubber-band previews for shape and region tools now show the exact cells that will be drawn, including the real dither pattern and actual gradient.
  • Tools show where they will paint. A size-aware hover footprint cursor, per-tool CSS cursors, and live hover events now preview the affected cells before you click.
  • Noise preview and size control. A seed-locked ghost preview shows the noise before you commit it, plus a new noise size option.
  • Simpler by default, everything customizable. The app now opens with a focused Draw-first workspace -- core tools and Layers front and center, advanced pipeline features hidden but one toggle away -- and your customizations to what's shown and where persist across reloads.
  • Customize every surface. Menus, the toolbar, right-click context actions, and the command palette now all honor your UI profile, so you can enable, disable, or relocate any item across the whole interface.
  • Choose how previews look. Paint previews can now be rendered in three visual styles, switchable from the command palette and remembered between sessions.
  • Customize panel. A new Customize panel lets you tailor the interface from one place -- a five-tab UI to show, hide, reorder, and rebind menu items, toolbar buttons, panels, and shortcuts.

#Fixes

  • Context menu stays out of the menu bar. Right-click context actions no longer leak into the top menu bar.
  • Saved layouts stay put. Panels are no longer re-injected into saved layouts, so a saved workspace no longer regrows every time a new panel is added.
  • Fresh load opens a curated workspace. A first load now applies the curated Default preset -- Layers active beside Colors -- instead of piling up a 15-tab dock.
  • Pencil and eraser strokes appear as you draw. Freehand strokes now echo progressively during a drag instead of staying invisible until you release.
  • Selections are now visible. The selection tool draws a live rubber-band and marching-ants outline while you drag, instead of leaving the marquee invisible.
  • Keyboard shortcuts that actually work. Menus and context rows used to show shortcuts that did nothing -- now Ctrl+S, Ctrl+O, and Ctrl+Shift+S really save, open, and save-as, every row shows its live binding, and shortcuts you rebind persist across restarts.
  • Command palette no longer spams errors. Running a command from the command palette -- or just closing it -- no longer triggers a page error on every use.
  • Disabled panels stay hidden. Panels turned off in your configuration no longer appear as toggles under View > Panels, and the "new panels available" notice no longer advertises panels you cannot open.
  • Readable names in Customize. The Customize panel's Toolbars tab now shows human-readable button names instead of raw internal ids, keeping the id as secondary text so it stays searchable.
  • Failed saves are unmistakable. When saving a project fails, the app now shows a clear error notification instead of a subtle warning.

#0.3.0

Server-authoritative editing: edits now persist and sync live; level-editor persistence, server-backed variant presets with deterministic MCP tools, 12 new character-preview MCP tools, and dozens of fixes

Context

Through 0.2.x, edits were tab-local: the server never applied incoming commands, so changes never persisted or synced across clients. This release is the systematic fix -- every command now applies-or-rejects on the server with total command coverage, making edits durable and live-syncing.

#Features

  • Invert Selection and Select by Color are implemented -- they previously did nothing.
  • MCP agents can now drive the character preview. Twelve new tools: granular setters for part variants, palettes, locks, randomizer seed and weights, oscillator management, plus a validated full-document set_character_preview.
  • Layers can now be grouped from the UI. Multi-select layers (Ctrl/Shift-click) and use the new Group/Ungroup entries in the Layer menu and context menu.
  • The level editor is now server-authoritative. Tiles, entities, and collision shapes persist across reloads, sync to other clients, and are undoable server-side; existing projects migrate with an empty level.
  • MCP agents can generate and bake variants. New tools: deterministic generate_variant (required seed), apply_variant that bakes the palette swap into pixels with full undo, plus list/remove preset tools.
  • Entities have a properties editor. Select an entity in the level editor and edit its key-value properties in the Map Properties panel.

#Fixes

  • Stale cached frontends now self-heal. The server serves a self-destruct service worker (at /sw.js and /__fastware/sw.js) that unregisters any stale worker and clears its caches, so clients pinned to an old cached build recover automatically on next load.
  • Browser edits now actually persist. Drawing in the browser was never applied to the server's authoritative project state -- every stroke vanished on reload, other clients saw blank canvases, and exports were empty. The server now applies drawing, shape, fill, and role commands as they arrive and broadcasts live state patches to other clients.
  • MCP layer-management and role-drawing tools no longer silently do nothing. rename_layer, set_layer_visibility, set_layer_opacity, move_layer, remove_layer and all six role-drawing tools reported success without changing the project; they now mutate authoritative state.
  • **MCP resize_canvas and apply_effect now really modify the project.** Resize remaps all frame/layer buffers with anchor semantics; apply_effect gained real server-side effect implementations, and unsupported effect/parameter combinations error clearly instead of pretending success.
  • Server-side undo/redo now actually revert the canvas. Undo/redo (including via MCP) only shuffled history bookkeeping while pixels stayed unchanged; they now restore the affected buffers.
  • The server remembers your active project across restarts. Restarting the server no longer dumps you into a different project on reconnect.
  • Part exports on projects without a part registry return a clear 422 error instead of an opaque 500.
  • The pixel Canvas is now the active center view on first load instead of the Level Editor.
  • The New Project dialog no longer auto-opens on every fresh load. It appears only when the server genuinely has no active project.
  • File > New Project now creates a real server project. Projects get a name, are created and activated on the server, and can be reopened later; server errors (duplicate/invalid names) are shown in the dialog.
  • The command palette opens again via Ctrl+P and a new View menu entry.
  • Fixed a crash in the History panel (duplicate-key error) after undoing and redoing an action.
  • Context menus are keyboard- and screen-reader-accessible: proper menu roles plus Arrow/Home/End/Enter navigation.
  • Copy/paste works again. Copy invoked from the menu or Ctrl+C captured nothing, so paste did nothing.
  • Effects applied from the menu actually change the canvas. All thirteen effects (Invert, Grayscale, Blur, Flip, ...) did nothing when clicked in the Effects menu; they now apply with sensible defaults and are undoable.
  • Crop to Selection no longer corrupts the image. It cropped the canvas dimensions without moving pixels; it now remaps content across all frames and layers and is undoable.
  • The Variants wand works on ordinary pixel content. Variant generation was gated to layer groups, so single-layer projects always produced nothing; a flat pixel layer is now a valid target.
  • Gradient, noise, dither, and pattern-stamp drawing now persists. These tools computed pixels only in the browser; the server now applies them authoritatively (deterministic, seed-driven), so they survive reload and appear in exports.
  • Drawing commands now target the correct layer. Forwarded commands carried an empty layer id, so with multiple layers the server guessed the target; the client now resolves and sends the active layer, and purely client-local commands (view, selection, dialogs) are no longer sent to the server at all.
  • The Server Projects panel stays in sync. The active-project highlight now follows server-side switches and reconnects instead of freezing at its mount-time snapshot.
  • Layer and frame edits made in the browser now persist. Layer add/remove/rename/reorder, visibility, opacity, blend mode, and frame add/remove/duplicate/reorder/duration changes were silently dropped by the server; they are now applied authoritatively, broadcast live to other clients, and undoable server-side.
  • Copy/cut/paste failures now tell you why. Copying with nothing selected or pasting with an empty clipboard showed nothing at all; you now get a clear notification.
  • Opening an unsupported or corrupt file now shows an error instead of silently doing nothing.
  • The command palette no longer lists commands that can't run from it. Tool commands that need canvas geometry (flood fill, draw shapes, move selection, ...) were shown but did nothing when invoked -- one even crashed the palette; they are now hidden.
  • Manifest, part, and isometric settings edited in the browser now persist. Setting the manifest, defining/updating parts, pairing canvases, and iso tile/footprint changes were silently dropped by the server; they are now applied, validated (invalid input is rejected loudly), broadcast live, and undoable.
  • Character-preview and oscillator edits made in the browser now persist (part variants, randomizer weights, oscillator add/update/remove/assign) instead of being silently dropped.
  • Frame and layer edits from menus and shortcuts now persist and are undoable. Add/duplicate/remove frame and layer operations invoked via the menu bar, context menus, or keyboard shortcuts bypassed the undo stack and never reached the server -- they vanished on reload.
  • Undo/redo now syncs to the server. Pressing Ctrl+Z reverted your canvas locally while the server kept the edit, so reloading resurrected undone strokes; undo/redo is now verified against server history, and any divergence is reported loudly instead of silently ignored.
  • Merge Down and Flatten Image no longer discard pixels. Merging layers dropped the upper layer's content instead of compositing it; both operations now composite correctly (honoring visibility, opacity, and blend modes) and are fully undoable.
  • Cut, paste, move/delete selection, and the remaining drawing primitives now persist. Clipboard and selection edits, scatter, copy region, replace color, checkerboard, polygon, iso outline, and tolerance fill were silently dropped by the server; they are now applied authoritatively and undoable.
  • Canvas resize, crop, rotate, and scale now persist. Dimension changes vanished on reload; resizing also bypassed undo entirely. All dimension operations are now forwarded, applied server-side with correct anchor semantics, and undoable.
  • Character-preview palette and lock changes made in the browser now persist, including for parts that were never explicitly selected.
  • Merge Down and Flatten Image now persist on the server with faithful compositing (visibility, opacity, blend modes) and full undo -- previously the merge existed only in your browser tab and un-merged itself on reload.
  • Layer groups now survive reload. The server modeled layers as a flat list, so groups made in the browser silently disappeared on reconnect; the server now stores the full layer tree, and group/ungroup/duplicate/flatten operations persist with undo. Also fixed: duplicating a layer produced a visibly empty copy -- pixel content is now copied.
  • The Rotate and Scale effects now persist -- rotating or scaling the active layer was lost on reload.
  • Character-preview rerolls now persist -- the randomize outcome is applied authoritatively instead of living only in your tab.
  • Animation frame tags now persist. Tags lived only in the browser and vanished on reload; the server now stores and syncs them.
  • Merge Down and Flatten Image work on layers nested inside groups -- they previously failed for nested layers.
  • Pasting and deleting animation frames now persists across reloads and to other clients.
  • The server no longer silently drops any command. Every command from the browser is now either applied to authoritative state or loudly rejected; a build-breaking contract test guarantees new commands can never silently lose your work again.
  • The command palette opens reliably again. A frame command's description crashed the palette's result list, so Ctrl+P did nothing; all command descriptions are now crash-proof and param-only commands are hidden.
  • Layer opacity changes now persist. The opacity slider sent a 0-100 value the server rejected, so opacity silently reverted on reload.
  • Frames can be reordered by dragging again -- the drag never registered a drop target.
  • Fixed a Svelte state error when renaming a layer or editing a frame duration.
  • Ctrl+C/X/V and Ctrl+A keyboard shortcuts work. They were advertised in the Edit menu but never bound; they now trigger copy/cut/paste/select-all and are correctly suppressed while typing in text fields.
  • MCP undo/redo now reverts every kind of change. Undoing an MCP layer/frame/resize/effect/manifest/part operation reported success while changing nothing; undo records are now attached everywhere, and an unrevertable entry fails loudly instead of pretending.
  • Creating a part family in the browser now persists -- the created canvases are applied authoritatively and fully undoable (including via MCP).
  • Manifest ramp transforms now persist. Applying a palette-class transform rewrote role planes only in your tab; the server now applies the manifest change and every remapped byte, with one-step undo of both (including via MCP).
  • Zero exceptions left: every command from the browser is now applied to authoritative state or rejected loudly. The last transitional allow-list is deleted; a contract test enforces total coverage.
  • Variant presets now persist and sync. Presets were a browser-only store that vanished on reload; they now live in the project on the server, survive restarts, and sync to other clients (generate, add, remove, color overrides).
  • Level-editor layers and grid settings now persist. Adding/removing map layers, visibility toggles, and grid/tile-size/mode changes bypassed the server and reset on reload; they are now synced, persistent, and undoable. Your selected tile brush is no longer wiped by server updates.
  • Fixed a freeze after generating a variant. Reloading a project containing a variant preset triggered an infinite reactive loop that silently disabled menus and panels app-wide.
  • Commands run from the command palette no longer raise a Svelte state error.
  • Layers (and level-editor map layers) can be reordered by dragging -- the drag never registered a drop target, including into and out of groups.

#0.2.2

Restore npm publishing for the 0.2.x line and give the npm package a real description.

Context

v0.2.1 shipped to PyPI but the npm publish failed: the workflow ran npm publish --provenance --access public, and sigstore provenance requires a public source repository. This repo is private, so npm rejected every publish and 0.2.x was uninstallable from npm.

--provenance had been deliberately removed on 2025-05-28 (commit dcc086e) for exactly this reason, then silently re-added by a scaffold three-way merge (commit 100947a). Token auth via the NPM_TOKEN secret is the correct path for a private repo, so 0.2.2 removes --provenance again while keeping --access public, the dist-tag argument, and the workflow-level id-token: write permission that PyPI Trusted Publishing needs.

This release also adds a real package.json description; previously the npm page derived its description from README line 1, which is the selfdoc auto-generated HTML comment header.

#Fixes

  • npm publishing restored, with an accurate package description. npm users could not install 0.2.x because publishes from the private source repo were rejected by npm's provenance requirement; 0.2.2 switches to token auth so npm install pixelweaver works again. The npm page also now shows a proper one-line summary instead of a raw HTML comment.

#0.2.1

Republish the 0.2.x line to PyPI and npm after the 0.2.0 publish gate failed in CI.

Context

0.2.0 completed its git side (tag pushed, GitHub Release created) but its CI-gated publish never ran: three part-export tests compared exported PNGs byte-for-byte against committed goldens, and the GitHub runner's zlib emits different compressed IDAT bytes than local zlib 1.3.1 for identical pixels (Pillow versions matched on both sides). The failing gate left PyPI and npm at 0.1.3.

0.2.1 fixes those tests to compare decoded image semantics (mode, size, palette, pixel data, transparency) instead of raw compressed bytes, and republishes the 0.2.x line. 0.2.0 remains a git-tag-only release that never reached the package registries.

#Fixes

  • 0.2.x now installable. The 0.2.0 release never reached PyPI/npm because its publish gate failed on environment-dependent PNG byte comparisons in CI; 0.2.1 publishes the 0.2.x line.

#0.2.0

Composable part authoring (parts, part-sets, manifests, character preview, iso tools, part export), restore-on-load connect handshake, same-origin dev mode; breaking CLI flag changes

Context

First publication of the villager/iso part-authoring feature program built across recent sessions, alongside the wesktop 0.8.1 / fastware 0.3.1 migration and typecheck enforcement. Includes two breaking CLI changes: --browser/--reload now require explicit --no-* forms, and the strictcli Tag->FlagSet migration.

#Breaking

  • Breaking. Bool flags --browser and --reload now require explicit --no-browser/--no-reload to disable.
  • Breaking. Update strictcli Tag to FlagSet rename.

#Features

  • Keyboard zoom shortcuts. The = and - keys now zoom in and out.
  • Version and build id in the status bar. The app version and build id are now shown in the status bar.
  • Open Server Project panel. Switch the active server project by name from a new panel; the canvas authoritatively re-renders on the newly activated project state.
  • **--server-url flag for the mcp command.** Target a specific collaboration server when starting the MCP server.
  • Parts panel. A part registry lets you define, update, remove, and reorder reusable parts from a Parts panel, synced to the server and persisted.
  • Reference underlay and whole-layer nudge. Toggle a reference image underlay with an opacity slider, and nudge an entire layer with the arrow keys.
  • Character preview. Assemble parts into a live character preview with oscillator-driven animation, randomization, playback, and per-part class/visibility overrides.
  • Part export. Export individual parts as indexed or RGBA PNGs from the UI, the headless CLI, and MCP, following the part-manifest format.
  • Isometric authoring tools. A new iso mode with a lattice/snap grid, tile-mode ghosts, footprint validation, seam checking, and view overlays for isometric tile art.
  • Canvases panel and split view. Manage multiple canvases in one project from a Canvases panel and view two at once with a split-view command.
  • New MCP tools. MCP tools for the manifest, part-set, role-layer, and layer-promotion surfaces.
  • Part sets. Group parts into sets with pairing validation and set-wide enforcement, assign parts to sets in the UI, mirrored on the server.
  • Manifest and role-layer authoring. A new surface for authoring the constraint manifest and role layers.
  • Per-layer offsets. Non-destructive per-layer compositor offsets let you shift a layer without moving its pixels.
  • Pressure-driven shading. On classed layers, pen pressure now selects a ramp role (lighter with more pressure).
  • Quick eyedropper. Alt+click samples under the cursor -- returning the role on classed layers and the RGBA color otherwise -- and sets it as the foreground color.
  • **pixelweaver dev now serves everything from a single origin.** Vite assets and HMR are proxied through the server and /ws is routed to the backend, so there's no longer a separate frontend port or VITE_SERVER_URL to configure -- the client derives its API and WebSocket URLs from the page location.
  • API reference now documents the raster, iso-seam, promote, part-export, and manifest-model modules. These server modules previously had no rendered reference pages.

#Fixes

  • Dependency installation no longer requires machine-local checkouts: uv.lock previously carried local paths for strictcli and wesktop, breaking installs and CI outside the author's machine. Dependencies now resolve from PyPI (strictcli 0.24.0, wesktop 0.7.0).
  • Layer opacity fix. Opacity from a server project now renders correctly -- values were previously applied at roughly 1% because the 0.0-1.0 server scale was not converted to the 0-100 client scale.
  • Canvas no longer stays blank on a server project. Binary WebSocket frames were being dropped so server state never reached the canvas; they are now delivered.
  • Startup crash fixed. The app could fail to render on load due to reactivity errors (effect update depth exceeded, unsafe state mutation) in the tile picker, action-log sync, and tool options.
  • No more stale cached app. Legacy service workers are now unregistered instead of serving an out-of-date cached version, so you always load the latest build.
  • **serve/open now find the built app.** A path bug pointed the SPA lookup at the wrong directory, so the built frontend failed to load.
  • MCP tools now expose usable schemas. The MCP server registers tools via the low-level Server API with authored input schemas and proper error reporting.
  • MCP drawing changes no longer silently dropped. Drawing mutations issued in headless MCP sessions are now applied.
  • **--vite-port is now honored by the dev command.** The port is forwarded to Vite with --strictPort instead of being ignored.
  • Bug fixes. Fixed a move_layer id collision, an incorrect error severity, and a broken toggle binding surfaced during strict typechecking.
  • Deterministic export. Exported pixels are now byte-identical between the browser and the headless Python exporter by matching JavaScript rounding.
  • Editor-mode toggle now works in the browser. Switching between the pixel and level editors was bound to Ctrl+Tab, which browsers hijack and often won't release; it's now on the backtick (`) key. The menu shows a mode-aware label ("Switch to Level Editor" / "Switch to Pixel Editor").
  • The canvas now shows the active server project on open. The app previously could load to a blank canvas; the client now requests a full snapshot every time the socket connects, and the server replies to just that socket. Reconnects restore fresh state instead of silently keeping stale pixels, and stale undo history is cleared when the server switches you to a different project.

#0.1.3

#Features

  • Feature. Each instance uses a random port, preventing conflicts when multiple windows are open simultaneously.

#Fixes

  • Fix. Static assets (dist/) are now resolved from the package install location instead of the current working directory.

#0.1.2

#Fixes

  • Fix. CI publish workflow no longer fails on private repos (removed npm provenance flag).

#0.1.1

#Features

  • Feature. npm CLI shim: npx pixelweaver now delegates to the Python CLI.

#Fixes

  • Fix. Fixed all Svelte accessibility warnings (labels, ARIA roles, keyboard handlers).

#0.1.0

#Features

  • Feature. Migrated server from FastAPI to wesktop ASGI framework.
  • Feature. Desktop mode via pywebview with native file dialogs, replacing Tauri.
  • Feature. CLI rewritten with strictcli. New commands: dev, open, stop, diagnose.
  • Feature. Single-command development mode (pixelweaver dev) using wesktop Vite integration.
  • Feature. Lazy-load dockview and fflate for smaller initial bundle size.

#Fixes

  • Fix. Desktop window icon now displays correctly (absolute path resolution).
Search