Gododin Gododin Documentation

Linked repository document

Compositor exact-Godot harness

fixtures/compositor/live/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 live exact-target acceptance harness for the compositor rendering fixture. It does not own authored Odin declarations, the compiler-derived catalog, the generated bridge and runtime projections, the reviewed rendering policy, or platform support status. Since the ADR 0050 migration the project image is the generated bridge compiled from the runtime package selected by gododin.toml (repository: fixtures/compositor/gododin.toml); this directory contains no image source.

Under ADR 0047 this harness runs only the official snapshot selected by the active-target policy. There is no candidate target or compatibility matrix; exact 4.7.2 and 4.6.2 are frozen history and neither is built nor run here.

The Host is not authored in this directory. It is the stable authority Host entry (repository: host/entry). The build gives it separate gododin authority and gododin_project runtime collections and sets the configured gododin_compositor_init link name. The Host otherwise contains no compositor switch: it reads the generated compositor catalog through the project collection and uses the same image-expectation names and GODODIN_HOST sentinel prefix as every configured project.

Configured artifact owner

The configured six-stage owner is the only builder for this artifact. It reads the compiler, Apple linker, and macOS SDK paths from ignored local configuration, authenticates all three against gododin.lock, revalidates them immediately before the stages that consume them, and records their identities in the publication manifest:

sh
/absolute/canonical/gododin build \
  --project-root /absolute/gododin/fixtures/compositor \
  --profile debug

The stage audits the project image as a passive thin-arm64 Mach-O with macOS 13.0, no loader initializer/terminator section, exactly one gododin_image_v4 export, and only its install name plus libSystem as load names. Before link it also requires the object's generated prebound-binder symbols to match the generated, receipt-covered image call inventory exactly. It additionally audits that the Host exports gododin_compositor_init and does not export gododin_native_basic_init, so a Host built for a different configured entry cannot be passed off as the compositor Host.

run.sh accepts only explicit canonical CLI and Godot paths. It invokes the configured build, selects the accepted publication through its state and manifests, and refuses a publication whose toolchain differs from the lock:

sh
fixtures/compositor/live/run.sh \
  --cli /absolute/canonical/gododin \
  --godot /absolute/canonical/locked-Godot \
  --godot-sha256 <sha256> \
  --evidence-dir /absolute/new-directory

The runner copies the accepted pair into a private project, re-verifies both copies, and supplies the authenticated image facts through GODODIN_IMAGE_PATH, GODODIN_IMAGE_SIZE, GODODIN_IMAGE_SHA256, and GODODIN_EXPECTED_TARGET. These project-neutral names are launch configuration, not additions to the Host/image ABI. HOME is redirected into the private work directory so a run leaves no state outside it.

Real device, not headless

Unlike the native-basic harness, this fixture must not run --headless. It needs a real RenderingDevice: the fixture reads the viewport back, runs a global Godot-submitted compute pass, and drives an explicit local-device submit/sync/readback probe. timeout_runner.py therefore launches Godot with --verbose --rendering-method forward_plus --rendering-driver metal and bounds the run at 120 seconds, reporting a timeout as an explicit failure sentinel so a hung render loop can never read as a pass. test.sh fails if --headless appears in the process runner.

Evidence contract

The run is a pass only when every one of these holds:

  • the log reports a Metal Forward+ device (Metal … - Forward+ - Using Device #…);
  • the fixture's local RenderingDevice submit/sync/readback probe succeeds;
  • the viewport moves from the environment's (0.8, 0.102, 0.051, 1) baseline to the blue-dominant (0.4235, 0.6275, 0.9059, 1) compositor output across two render callbacks;
  • the density-field-upload producer writes 4 MiB directly into a retained Godot packed-array backing store, and the shader verifies the transferred tail voxel for the published generation before it permits that tint;
  • the inspected 96×96 PNG is retained into the evidence directory; and
  • the Host reaches zero owners after legal project and extension teardown.

Two sentinels must each appear exactly once. The script sentinel is matched by its pinned prefix because the evidence path is run-specific:

text
GODODIN_COMPOSITOR_GDSCRIPT_PASS baseline=(0.8, 0.102, 0.051, 1.0) tinted=(0.4235, 0.6275, 0.9059, 1.0) baseline_count=1 tinted_count=2 bulk_payload_bytes=4194304 bulk_tail_verified=true evidence=<path>
text
GODODIN_HOST_PASS target=4.8.0 method_variant_calls=0 method_ptrcalls=8 virtual_calls=3 registrations=0 instances=0 owned_foreign_values=0 references=0 active_callback_scopes=0 host_allocations=0 image_allocations=0

Exit status alone is never a pass. The runner additionally rejects a failure sentinel, any ERROR:/WARNING:/SCRIPT ERROR:/USER ERROR:/USER WARNING: diagnostic, any RID or ObjectDB leak report, a missing renderer line, a missing or duplicated sentinel, a missing retained PNG, and a process timeout.

Offline contract test

test.sh needs no Godot, Odin, or built artifacts. It syntax-checks the three shell harnesses and both process runners, then proves the harness is bound to the recorded evidence rather than to free-floating literals. The installed SDK, first CLI, current source inputs, configured build identity and toolchain are joined to gododin.lock; the Godot identity, viewport color, render count, and zero-owner counters are reconstructed from the current rendering receipt (repository: fixtures/compositor/compositor-evidence-2026-10-19-sdk5.json); and the retained PNG is checked against the receipt's byte count and SHA-256. It also asserts both live harnesses reject missing explicit paths with exit 64 and that no second artifact builder is present. Installed add-on inventories and engine caches are derived local state; the source-purity check excludes those managed directories while still rejecting generated semantic files elsewhere in the live tree.

text
GODODIN_COMPOSITOR_HARNESS_CONTRACT_PASS target=4.8.0 renderer=forward_plus_metal artifact_builders=1 bulk_payload_bytes=4194304 bulk_tail_verified_processes=4 generated_outputs=0 zero_owner_counters=9 receipts=2 requalified_processes=5 support_promotion=0

Recorded evidence

The current rendering receipt (repository: fixtures/compositor/compositor-evidence-2026-10-19-sdk5.json) records the authenticated debug artifacts, the locked target's live run, the Forward+/Metal device line, the inspected viewport colors, the shader-verified 4 MiB density tail, and the zero-owner shutdown counters. compositor-evidence.png (repository: fixtures/compositor/compositor-evidence.png) is the inspected 96×96 output; all 9,216 pixels are blue-dominant and its center pixel is RGB (108, 160, 231), the 8-bit form of the recorded tinted color.

The retained trace (repository: fixtures/compositor/compositor-trace-2026-10-19-sdk5.tar.xz) contains the logs, manifests, images and exact add-on consumed by this campaign. Both receipts and the offline contract bind its byte count and SHA-256. The add-on starts its reader threads after the initial filesystem import settles; the campaign covers the cold-import teardown that previously faulted on beta1.

The rendering evidence is reproducible and the artifact digests are not, and the receipt's reproducibility block says so. The configured owner's accepted Host/image publication reproduces the byte-identical PNG, both sentinels, and the recorded viewport colors on the recorded host. That rendering result is conditional on the density tail arriving for the published generation. The recorded host_artifact_sha256 and image_artifact_sha256 do not survive a rebuild, because the debug profile embeds the builder's absolute output directory; they identify the specific artifacts this receipt was recorded from and assert no reproducible build.

This receipt does not promote macOS arm64 platform support. Under ADR 0042 that promotion additionally requires the configured editor/export matrix and the complete clean-machine matrix under the version policy.

Requalifying the Phase 4 matrix

phase4.sh is the second live harness here, and it compiles nothing. It drives the public commands only — gododin build, gododin editor with explicit --recovery and normal authoring modes, gododin run, and gododin export for both profiles — then executes both exported applications itself, because compiling, exporting, and signing an application is not evidence that it runs. bounded_runner.py bounds each step and supplies the exact environment, so nothing is inherited and an ambient GODODIN_COMPOSITOR_* variable cannot stand in for an authenticated image fact. ADR 0055's authoring editor opens the source game, so the harness creates an isolated configured copy and prepares its addon and import UIDs before selecting the shared debug artifact. The checked-in fixture is never its save destination. That copy and its path are retained with the run evidence.

sh
fixtures/compositor/live/phase4.sh \
  --cli /absolute/extracted/sdk/bin/gododin \
  --godot /absolute/canonical/Godot \
  --godot-sha256 <sha256> \
  --evidence-dir /absolute/new-directory \
  --sdk /absolute/extracted/sdk

--sdk validates and attaches the isolated project to that installed authority; the CLI must be the SDK's own executable. Omitting it retains checkout-authority mode for implementation work. SDK publication requires the installed mode above.

A run is a pass only when the recovery editor reaches zero owners without loading the project image, the accepted editor loads and unloads the published pair making no call at all, the run and both exported applications each emit the two sentinels with a Metal Forward+ device line, and all three of those processes write an inspected PNG byte-identical to the one this rendering receipt pins. That last requirement is what binds the editor/build/export receipt (repository: fixtures/compositor/phase4-evidence-2026-10-19-sdk5.json) to the rendering receipt (repository: fixtures/compositor/compositor-evidence-2026-10-19-sdk5.json).

The focused rendering run and this matrix now consume the same configured debug publication: the matrix invokes the focused run.sh from the configured copy and requires its build ID to match before proceeding. Its evidence is retained under direct-rendering/. The checked-in receipts bind its build ID, source revision, catalog fingerprint, exact native toolchain, and inspected PNG rather than leaving two artifact histories to reconcile.

Re-freezing after a rendering change

Changes that invalidate the catalog, generated runtime, artifact, or toolchain evidence require a new phase4.sh run. Write new dated receipts from its direct-rendering/ focused evidence and phase4-run.json, then point test.sh at that pair. Retain earlier receipts unchanged. If the viewport color or PNG changes, retain a new inspected PNG and state why it was expected to move. Standalone run.sh remains useful for focused checks, but its separate artifact cannot replace the shared receipt identity. The historical rendering receipt (repository: fixtures/compositor/compositor-evidence.json) retains the earlier requalifications that preserved the viewport color and PNG.