Gododin Gododin Documentation

Linked repository document

cavern-asset-bake — designer flow and process contract

examples/cavern_lab/bake/README.md

This document retains its design, example or evidence context. References outside this guide show their repository paths.

View original Markdown · Download · Return to the guide

This directory owns the Phase 14 workload definition. Godot owns the editable mask/settings Resource, the output asset, the scene integration, and the editor UI; the pure Odin cavern kernel does the substantial computation; the existing six-stage build authority remains the only compiler and publication owner. This admits one native tool, not a general cooking or EditorPlugin framework.

Resources

  • Request — res://bake/bake_request.tres, a CaveBakeRequest Resource: one occupancy mask (Image, 8-bit L8, 0/255) plus the settings fields the kernel already validates (smoothing_steps, minimum_region_size). The designer edits it in the Inspector with the editor's own undo.
  • Output — res://bake/cave_bake_data.tres, a CaveBakeData Resource: the baked floor grid (PackedByteArray), its width/height, the kernel diagnostics hash, the request digest it was baked from, and the native source revision that produced it.
  • Destination policy — the output path is fixed by the request Resource's output_path; one request owns exactly one destination asset.

Designer flow

  1. Edit — the designer changes the mask or settings on the request Resource. Inspector edits use the editor's standard undo/redo; nothing here touches the output asset.
  2. Bake — the Bake Shell (a GDScript panel in the authoring editor, or its scripted equivalent in evidence runs) saves the request, then launches one bounded headless child process: the same editor binary, this project, --headless --script res://bake/bake_process.gd, with the request path, output path, and the request digest as user arguments. The child loads the current accepted native image through the standard runtime staging contract (the same environment gododin run uses) and runs the pure kernel's process_mask on the mask bytes.
  3. Inspect — when the child prints GODODIN_BAKE_PUBLISH, the destination asset has been atomically replaced; the scene reimport/reload picks it up on the next open or explicit reload, and the shell's preview refreshes from the file. The shell streams the child's sentinels into its log.
  4. Cancel — the shell may cancel an outstanding bake: it terminates the child process. A cancelled bake never touches the destination.
  5. Repair — if the child cannot load an accepted image (GODODIN_BAKE_NOIMAGE), the shell surfaces the diagnostic and the normal rebuild path (the editor addon / gododin build) repairs it; the bake shell never compiles, links, or stages an artifact itself.
  6. Reopen/reimport — the output is an ordinary Resource. On reopen, the freshness state below decides the inspector badge; the asset stays loadable in every state.

Identity and freshness

  • Request digest — SHA-256 over the canonicalized mask bytes plus the settings fields, computed by the shell before launch and recomputed inside the child before processing. A mismatch fails the bake; the shell never bakes a request it cannot digest identically to the child. (The engine exposes plain SHA-256 over files, so the shared digest helper hashes the canonical bytes through a per-process temporary file.)
  • Output identity — the destination ResourcePath plus the recorded request digest and native source revision. Deterministic repeat: the same digest and the same pure kernel produce an identical payload and provenance — grid bytes, dimensions, diagnostics, digest, and revision — asserted by the campaign. The serialized .tres itself is not byte-compared: the engine writes a fresh resource UID into every save, and the kernel's wall-clock generation_usec is a measurement, not identity.
  • Freshness — FRESH when the asset's recorded digest equals the current request digest; STALE when it differs; MISSING before the first successful bake. Staleness is a badge, never a blocker: the last valid asset remains loaded, exported, and inspectable.
  • Undo/redo — request edits are undoable through the Inspector's own history. Output publication is a file replacement, not an editor action, so it is recorded in the shell log instead of the undo history; this is stated behavior, not a gap.

Ownership, failure, and publication bounds

  • One outstanding bake per request resource. Launching a new bake supersedes the outstanding one: the child is terminated and its partial output ignored.
  • The child validates the kernel result (bounds, border safety, single-region validation, expected byte count) before publication. Publication is atomic: write to a temporary file in the same directory, then rename over the destination. A failed, cancelled, or superseded bake preserves the last valid asset byte for byte.
  • Process failure — non-zero exit, missing sentinel, or timeout — is bounded: the shell reports BAKE_FAILED with the child's log tail and keeps the last valid asset. The child owns native execution; project native code never runs inside the recovery shell or the panel.
  • The child keeps no engine state beyond the run: no scene is saved, no editor state is read, and the process exits after publishing or failing.

The committed designer asset

The configured project carries one committed product of this flow: live/project/bake/cave_bake_request.tres (a 256x192 L8 mask with smoothing 5 and minimum region 48) and its published destination live/project/bake/cave_bake_data.tres. They were produced by the real shell and supervised child through bake_authoring.gd, which also verifies the published asset the way a consumer does — freshness against the recomputed request digest and oracle parity with the accepted kernel. Exported applications consume this asset in a bake-consume self-check: the app loads the asset, recomputes the digest, verifies FRESH and kernel parity through the normal installed-image path, and tears down with zero owners. The harness gates both export profiles on that sentinel and on a bundle closure with no compiler, OLS, or CLI helper (verify_bake_export.py).

Evidence obligations (Phase 14 bullets)

The real-editor exercises run through the bake_probe plugin (live/project/editor/bake_probe/, a no-op outside the exercise mode): the no-image editor drives the real shell into the unavailable-image refusal with the destination preserved, and the accepted-image editor proves deterministic repeat, mid-bake cancellation, native-process failure, the stale reimport through the editor's own import pipeline, and two consumers sharing the cached request Resource (bake_editor=true in the installed sentinel). Editor reload while a bake is outstanding is exercised in the same real-editor run as the background workload's reload exercise (the harness signals the probe when the addon's rebuild child exits, so the supervised bake child is in flight when reload_extension lands; reload=true in the installed sentinel). The shared C3 checkpoint is complete: the SDK/user docs and the affected release-matrix rows updated with it.