8.1 KiB
Build Artifacts and Deterministic Packing Decision
Status
Accepted
Date
2026-03-11
Context
This decision closes the architectural questions raised in 01.3. Build Artifacts and Deterministic Packing Agenda.
The packer must produce build artifacts that are:
- deterministic;
- aligned with the runtime-facing
assets.pacontract already established in../runtime; - usable by Studio and tooling without creating a second source of truth;
- stable enough to support future specs and implementation.
The runtime-side contract already establishes that:
assets.pais the runtime-facing artifact;asset_tableandpreloadlive in the internal JSON header;- offsets are relative to the payload region;
- preload is boot-time input only.
This decision closes how the packer should produce these artifacts.
Decision
The packer adopts an assets.pa-authoritative, deterministically ordered, canonical-header model.
1. Artifact authority
assets.pa is the authoritative runtime-facing artifact.
Rules:
- the
assets.paheader is the runtime-facing source of truth forasset_tableandpreload; build/asset_table.jsonand other JSON outputs are companion artifacts only;- runtime must not depend on companion JSON files as its primary contract.
2. Companion artifacts
The packer emits separate companion artifacts for tooling and debugging.
Baseline companion outputs:
build/asset_table.jsonbuild/preload.jsonbuild/asset_table_metadata.json
Rules:
build/asset_table.jsonmirrorsheader.asset_table1:1;build/preload.jsonmirrorsheader.preload1:1;build/asset_table_metadata.jsonis tooling-only and may carry richer packer metadata;- richer tooling data must not be smuggled into the runtime-facing mirror files.
3. assets.pa v1 prelude
The baseline packer-side prelude for assets.pa v1 includes:
magicschema_versionheader_lenpayload_offsetflagsreserved
Rules:
flagsexists from day 1 for forward compatibility;reservedexists from day 1 for forward compatibility;flags = 0in the current baseline unless a future spec says otherwise;reserved = 0in the current baseline unless a future spec says otherwise;header_checksumis not part of the baselineassets.paenvelope contract.
4. Checksum policy
Header checksum is not part of the baseline runtime-facing envelope.
Rules:
- runtime validation does not depend on header checksum;
- cartridge-level integrity may be handled elsewhere;
- Studio/tooling may compute checks or hashes separately if needed;
- such checks must not redefine the runtime-facing
assets.paenvelope.
5. Canonical JSON header
The JSON header of assets.pa must be serialized canonically.
Canonicalization rules:
- UTF-8 encoding;
- no extra whitespace;
- object keys sorted lexicographically;
- arrays preserve declared order;
- canonicalization applies recursively, including nested metadata objects;
- runtime-facing header values in v1 must avoid floating-point numbers.
This is required so equivalent inputs produce byte-identical headers and therefore byte-reproducible artifacts.
6. Ordering and determinism
The global asset_table order is deterministic by increasing asset_id.
Rules:
- usage-based or hot-first packing is not part of the baseline contract;
- format-specific heuristics must not reorder the global asset list;
- deterministic ordering is preferred over physical-layout heuristics;
- future locality optimization requires a separate explicit decision and spec.
7. asset_id continuity
The asset_id used in runtime-facing artifacts is the same stable asset_id allocated by the packer registry.
Rules:
- the packer does not generate a second runtime-only asset identity;
preloadrefers to the sameasset_idvalues that appear inasset_table;- table position does not define identity;
- cross-build identity stability comes from
asset_id, not from table index.
8. Asset table shape
asset_table is emitted as a deterministically ordered list of asset entries.
Rules:
- one emitted entry per managed asset in the build set;
- no synthetic dense reindexing layer is introduced;
- omission of removed assets happens naturally because the emitted table reflects the current build set only;
- the runtime sees a normal contiguous list of entries, but the IDs inside it remain the stable packer IDs.
9. asset_name in runtime-facing artifacts
asset_name remains present in asset_table.
Meaning:
asset_nameis logical descriptive and API-facing metadata;- current runtime/game-facing calls may still use it for normal asset lookup;
- preload/bootstrap integrity relies on
asset_id, notasset_name; - renaming
asset_nameis an API-visible/content-visible change, but not an asset identity change.
10. Preload mapping
Preload emission is derived deterministically from per-asset declaration.
Rules:
- assets with
preload.enabled = falsedo not appear in emitted preload data; - assets with
preload.enabled = trueproduce preload entries in the runtime-facing preload list; - emitted preload ordering is deterministic by increasing
asset_id; - preload is boot-time input only and must be emitted in a form consistent with the runtime contract.
11. Alignment
Alignment exists only when explicitly required by spec.
Rules:
- there is no implicit baseline alignment beyond what is required by the envelope and chosen formats;
- if a format requires alignment, the requirement must be normative and visible in the relevant spec;
- computed offsets must always be emitted explicitly in the runtime-facing descriptor.
12. Offsets
All emitted asset offsets are relative to the payload region.
Rules:
- offsets are never relative to the start of the whole
assets.pafile; - this rule must be preserved consistently across packer outputs and specs;
- companion artifacts must mirror the same offset semantics.
Invariants and Constraints
The following invariants now apply:
assets.pais the authoritative runtime-facing artifact.- Companion JSON files do not replace the internal
assets.paheader. build/asset_table.jsonmirrorsheader.asset_table1:1.build/preload.jsonmirrorsheader.preload1:1.build/asset_table_metadata.jsonis tooling-only.- The prelude includes
magic,schema_version,header_len,payload_offset,flags, andreserved. header_checksumis not part of the baseline envelope contract.- Header JSON is canonicalized.
- Global asset ordering is deterministic by increasing
asset_id. - The runtime-facing
asset_idis the same stable packerasset_id. asset_tableis a deterministically ordered list, not a second identity system.asset_nameremains present as logical/API-facing metadata.- Preload is emitted deterministically from
preload.enabled. - Offsets are relative to the payload region only.
Explicit Non-Decisions
This decision does not yet define:
- the exact field-level metadata contract of each output format;
- richer preload policies beyond the current baseline;
- future physical locality optimization;
- game-language lowering of asset references from names to IDs;
- cartridge-level integrity/signature strategy.
Those belong to later decisions and specs.
Propagation Targets
This decision must propagate to:
- packer artifact and envelope specs;
- packer determinism and reproducibility specs;
- packer preload emission specs;
- Studio tooling expectations for companion artifacts;
- future implementation of canonical header generation and companion-file emission.
Validation Notes
Example: artifact relationship
assets.pa
prelude
canonical header JSON
asset_table
preload
payload bytes
build/asset_table.json
mirrors header.asset_table
build/preload.json
mirrors header.preload
build/asset_table_metadata.json
tooling-only enrichment
Example: stable identity
- packer registry assigns asset IDs
3,7, and11 - emitted
asset_tableis ordered[3, 7, 11] - runtime-facing preload entries reference
3,7, or11 - no additional dense runtime ID layer is introduced