Skip to content

Studio: external change to index.html silently discards unsaved editor state (data loss in the documented agent + Studio workflow) #2982

Description

@ajp-productions

Summary

When index.html changes on disk, Studio hot-reloads the composition and silently discards any uncommitted editor state. There is no warning, no conflict prompt, no merge, and no recovery affordance. The user finds out minutes later when they notice their work is gone.

This is not an edge case in agent-assisted workflows — it is the documented workflow. The scaffolded CLAUDE.md tells the coding agent to edit index.html directly, and tells the user to keep npm run dev running in the background. Studio watches that file and reloads on change. So the intended way to use the product puts an agent and Studio on the same file with no guard between them.

Impact

Two separate sessions of work lost in one evening on a single project. The failure is silent in both directions: the agent has no signal that Studio holds unsaved state, and Studio gives the user no signal that a reload threw their edits away.

It also compounds with #2981 — a stray backspace deletes a design element, the user retypes it, an agent writes the file, and the retyped work is discarded too.

Steps to reproduce

  1. Open a project in Studio (npm run dev).
  2. Make an edit in the canvas or a property field — enough to dirty the editor, but do not wait for autosave.
  3. From outside Studio, write to index.html (an agent edit, sed -i, a formatter, git checkout, anything).
  4. Studio hot-reloads.

Expected: the user is told the file changed underneath them and offered a choice — keep editor state, take the file, or diff. Or Studio flushes pending edits before accepting the reload.

Actual: the reload silently wins. Uncommitted editor state is gone with no message and no way to get it back from the UI.

Evidence

.hyperframes/backup/ records every Studio write, so the divergence is visible in the timestamps. From the affected session (times local):

20:16:21   Studio write          }
20:18:10   Studio write          }  normal autosave cadence,
20:18:17   Studio write          }  seconds apart
20:18:19   Studio write          }
20:18:44   Studio write          <- last write Studio ever made

~20:20     external write (agent)
~20:23     external write (agent)
 20:25:25  external write (agent)

20:32      user reports having made edits in Studio; nothing on disk

Diffing index.html against the 20:18:44 snapshot returns only the agent's changes. None of the user's post-20:18:44 edits are present anywhere on disk.

An earlier occurrence in the same session has the same shape: a write at 20:11:26 landed mid-session, and the edits the user had in flight at that moment never appeared in any subsequent backup.

Secondary observation

After the final external write at 20:25:25, Studio made no further writes at all for 14+ minutes, while the user was actively editing and reported making changes. Its autosave had been firing every few seconds up to that point.

Notably, autosave did recover after the earlier 20:11:26 write (writes resumed at 20:16:21), so this is not consistently reproducible from the trail alone and may be a separate problem. Flagging it as an observation rather than a firm second bug — but if the reload path can leave autosave unarmed, that turns one lost edit into every subsequent edit being lost.

Suggested direction

Studio already writes .hyperframes/backup/ before every save, so it has the data needed to detect divergence — it knows the content it last wrote, and can compare against what is on disk now.

Roughly in order of value:

  1. Guard the reload. If the editor is dirty and the on-disk content is not what Studio last wrote, prompt instead of reloading: keep mine / take theirs / show diff.
  2. Flush before reload. Commit pending edits to disk first, then reconcile. Turns silent loss into a normal merge.
  3. At minimum, make it visible and recoverable. A toast — "index.html changed on disk; your unsaved changes were discarded" — with one-click restore from .hyperframes/backup/. Cheap, and it converts silent data loss into an inconvenience.
  4. Shorten the autosave debounce, to narrow the window where uncommitted state exists at all.

A companion for the agent side would help too: a documented way to ask the preview server whether Studio has unsaved state, so an agent can decline to write rather than clobber. Right now an agent has no way to know, and the scaffolded docs actively encourage it to write.

Environment

  • hyperframes 0.7.90 (latest at time of report)
  • Node v22.17.0, linux x64 (WSL2)
  • Studio via npm run dev (hyperframes preview) on 127.0.0.1:3003
  • Single-file index.html, ~36 KB, 46 timed elements across 8 tracks
  • hyperframes check passes with 0 errors throughout; nothing in lint or check surfaces this

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions