Blacksite/docs/adr/0047-editor-authored-asset-documents.md

4.4 KiB

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.