# ADR 0047: Editor Authored-Asset Documents and Two-Phase Publication

## Status

Accepted

## Context

Material controls previously updated the viewport immediately but also wrote source when a pointer
interaction ended. That publication could trigger file guards, Git refresh, watcher work,
thumbnail invalidation, and whole-project processing on the editor frame thread. A slider release
therefore behaved like an implicit save and could freeze the editor.

Project RON files and registry metadata are already suitable authoritative source documents. The
editor needs a fast, durable edit boundary without adding an opaque asset database or conflating
editor-dirty documents with source-control status.

## Decision

The editor owns an `AuthoredAssetDocumentStore` keyed by stable asset ID and document kind. It
holds clean and current values, source path, loaded file revision, editor revision, publication
error, recovery state, and derived-processing state for Materials, Material Instances, model import
settings, Texture import settings, and project content defaults.

Interactive controls mutate the current document and `blacksite_surface`'s stable-ID-keyed
`LiveMaterialDocumentOverlay` in the same tick. `SurfaceMaterialCache` is the sole owner of project
Material and Material Instance handles; resolution is overlay-first and disk-second. Controls
perform no source write, watcher refresh, Git query, thumbnail invalidation, or derived processing,
including when the pointer is released. Dirtiness is derived from `current != clean` and remains
distinct from Git `MODIFIED`, `UNTRACKED`, and `CONFLICT` state.

The cache never polls file metadata or reparses a project Material for every bound entity. Explicit
Save and accepted watcher events invalidate the disk generation once; interactive overlay
revisions mutate the existing cached handle in place. Imported glTF/FBX source materials stay on
their AssetServer-owned path and do not enter the project-material resolver.

`Ctrl+S` saves the last edited context. `Ctrl+Shift+S` and **File > Save All** save every dirty
scene, authored asset document, and project setting. Source publication remains guarded and atomic.
Registry-backed documents use a clean registry baseline plus per-document overlays so saving one
setting cannot publish another unsaved setting.

Successful source publication advances the clean value, then classifies its
`DerivedProcessingImpact`. Scalar, color, emissive, shader-value, label, and render-state Material
changes queue no derived work. ARM/ORM texture or channel changes queue material packing; Texture
settings, model settings, and project defaults queue only their exact dependency closure. Packing
signatures exclude scalar multipliers and are checked before image decoding so an existing
content-addressed artifact can be reused. The previous valid runtime artifact remains authoritative until replacement
publication succeeds; a processing failure is reported separately and does not make saved source
dirty again. Stale job completions are ignored.

Dirty asset documents receive editor-local recovery snapshots after two seconds of inactivity,
with five generations retained outside `assets/`. Startup restoration never overwrites source: a
changed source fingerprint restores the document as an external conflict. Guarded shutdown and
project switching count scenes, assets, and project settings in the same Save All / Discard /
Cancel decision. Returning a document exactly to its clean value retires any older recovery
generation on the next editor tick. Startup also discards a recovery envelope whose value already
matches authoritative source, covering a crash between the clean edit and that cleanup tick.

## Consequences

- Parameter editing and pointer release stay frame-local and responsive.
- Material and direct-base Instance users share one stable live handle authority instead of
  competing editor and renderer caches.
- Saving source and generating derived artifacts are observable, independent phases.
- The project remains plain, reviewable RON plus source assets; no asset binary database is added.
- Unsaved editor state survives selection changes and can be recovered after a crash without
  affecting Git until the user saves.
- Packaging and read-only processing validation must reject required pending or failed derived
  work rather than silently packaging stale content.
- Import, extract, create, rename, move, and delete remain explicit immediate transactions because
  they create or remove project identity.
