# ADR 0023: Transactional Scene Persistence And Recovery

## Status

Accepted

## Context

Blacksite previously wrote scene RON directly to the authored path. An interruption during that
write could corrupt the last good scene. The save serializer also strips hydrated runtime state
before extraction and only rebuilt it after a successful write, so serialization or filesystem
failure could leave the live editor world partially stripped.

Daily production additionally needs a recovery path for dirty scenes that does not modify project
assets, mark a scene clean, enter source control, or silently replace authored work.

## Decision

- Manual scene, prefab, and selection writes use a temporary file in the destination directory,
  flush and sync its bytes, atomically rename it over the destination, and sync the parent
  directory where the platform permits.
- Authored document serialization is separate from persistence. Hydrated state is always rebuilt
  after serialization attempts, including validation and serialization failures.
- Dirty saved scenes produce recovery snapshots every 120 seconds by default. The interval has a
  15-second safety floor and the newest five generations are retained by default.
- Recovery data lives under `$XDG_STATE_HOME/blacksite-editor/recovery` or
  `~/.local/state/blacksite-editor/recovery`. Stable hashes of project root and scene path keep
  recovery files outside the project without leaking path names into directory names.
- A recovery snapshot never clears the dirty flag and uses the same authoring-only serialization
  contract as manual save.
- On scene load, a newer recovery snapshot is surfaced in the status strip and File menu. The
  editor never restores it automatically. Restore loads the snapshot into the original scene
  context and leaves the scene dirty; the snapshot remains available until manual Save commits it
  or Discard removes that scene's recovery generations. Save Recovery Copy As writes the snapshot
  to a separate transactional scene file without changing the active scene or recovery lifecycle.
- A successful manual save retires recovery generations for that scene.
- A successful load or manual save establishes that tab's canonical authored-content checkpoint.
  Undo and redo compare the current stable authored projection with this checkpoint to derive dirty
  state. Failed writes, cancelled Save As, and recovery restores do not advance it.
- Native editor exit is authorized only after all dirty scene tabs save successfully or the user
  explicitly discards them. See [ADR 0042](0042-guarded-editor-shutdown-and-document-savepoints.md).

## Consequences

- Interrupted manual writes retain the previous complete destination on filesystems with atomic
  same-directory rename semantics.
- Recovery is machine-local and does not pollute builds or source control.
- Undoing exactly to the last loaded or saved authored state clears the dirty marker without
  weakening recovery after direct edits or failed saves.
- Autosave still performs authored serialization and hydration rebuild work. Performance
  instrumentation and background snapshotting remain follow-up work under the production roadmap.
- Unsaved new scenes do not yet have a stable recovery identity; they require a later session-ID
  recovery extension.
- The initial controls use user preference fields and documented defaults; a dedicated Preferences
  panel can expose them later without changing the storage contract.
