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.
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:
/absolute/canonical/gododin build \
--project-root /absolute/gododin/fixtures/compositor \
--profile debugThe 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:
fixtures/compositor/live/run.sh \
--cli /absolute/canonical/gododin \
--godot /absolute/canonical/locked-Godot \
--godot-sha256 <sha256> \
--evidence-dir /absolute/new-directoryThe 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
RenderingDevicesubmit/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:
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>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=0Exit 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.
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=0Recorded 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.
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.