Skip to content

Project integrity — eliminate cross-tab and stale-save corruption #337

Description

@Flow-Fly

Why

While testing #334, an imported file appeared to replace the active drawing and older drawing pixels sometimes reappeared after save or reopen.

The replacement itself matches the pre-#334 importer still running from a cached installed PWA. The current #334 path stores the import under a fresh identity and rejects the ninth open before touching the active context.

The artifact report exposed several independent project-integrity bugs that are real and deterministic.

Confirmed and repaired in #334

  • project loads retained cel entries from the drawing previously held by a reused context
  • palette events were global, so a palette change in tab A remapped pixel buffers in tab B
  • hard-linked cels could remap their shared index buffer once per linked cel
  • save serialized current PNG pixels together with stale indexed pixels; reopen then rebuilt the canvas from the stale indices
  • a context hydrated during a tab-cap race could be rejected without disposal

Confirmed remaining hazards

  1. Shared blank-cel contamination

    • blank cels share a transparent canvas
    • selection fill, delete, paste, transform, layer transform, and patch paths can write the canvas without first detaching the active cel
    • editing one blank frame can therefore paint another blank frame
  2. Out-of-order auto-save writes

    • blur, debounce, and forced saves can overlap
    • an older save can finish after a newer save and overwrite it
    • project identity is read after asynchronous serialization, so a reused context can target the wrong repository key
  3. Default-context actions in a multi-tab editor

    • rename and duplicate still have default-context save calls
    • PF and Aseprite export still read singleton stores
    • several shortcuts and editor actions still read singleton stores instead of the active ProjectContext
    • a non-default tab can therefore save, duplicate, export, or mutate another project

Recommended slice

Do one bounded project-integrity wave before backend work. Split the three remaining hazards into child issues and stack them in one PR because they serve one feature boundary: a drawing must remain isolated and round-trip exactly.

Acceptance

  • editing a blank cel never changes another frame or tab
  • concurrent saves for one context commit in request order and the newest state wins
  • every save captures and writes the intended project identity
  • rename, duplicate, PF export, Aseprite export, and shortcuts use the active ProjectContext
  • draw, delete or transform, save, reload preserves exactly the visible pixels
  • two-tab palette and edit tests prove no cross-project mutation
  • browser smoke on a non-default tab produces no persistence or console errors

Metadata

Metadata

Assignees

No one assigned

    Labels

    agentic-loopTracked by the reusable agentic loop workflowbugSomething isn't workingneeds-humanNeeds a human decision, approval, review, or playtest before agent work proceedsrisk:mediumMedium-risk work touching shared behavior, architecture, or broader design

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions