7.8 KiB
Build Artifacts and Deterministic Packing Agenda
Status
Closed
Resolved by 003-build-artifacts-and-deterministic-packing-decision.md.
Purpose
Close the contract for packer build outputs and the determinism rules that make them reproducible.
Context
The draft proposes two core build artifacts:
build/assets.pabuild/asset_table.json
At least one of these artifacts must form a documented interface that ../runtime can consume safely.
That runtime-facing contract should be specified before the implementation hardens around incidental file structure.
It also states strong determinism requirements:
- deterministic asset order,
- deterministic derived outputs,
- explicit materialization of inferred defaults.
This is a strong basis for normative packer output specs.
Source Sections
8. Build Artifacts Produced by the Packer9. Determinism Rules
Runtime Normative Inputs
From ../runtime/docs/runtime/specs/13-cartridge.md:
assets.pais the runtime-facing artifact;assets.pav1 is an autocontained binary with:- fixed binary prelude,
- JSON header,
- binary payload region;
- the fixed prelude contains, at minimum:
magic,schema_version,header_len,payload_offset;
- the JSON header carries:
asset_table,preload.
From ../runtime/docs/runtime/specs/15-asset-management.md:
asset_tableentries currently expose:asset_id,asset_name,bank_type,offset,size,decoded_size,codec,metadata;
offsetis relative to the payload region insideassets.pa, not to the start of the full file;preloadis boot-time input only;- runtime loading is based on
open_sliceover payload slices; - the runtime must not require the entire payload to stay resident in RAM.
These are already normative runtime-facing requirements and should be treated as baseline constraints for packer output design.
For this agenda, the intended direction is:
assets.pais the authoritative runtime-facing artifact;build/asset_table.jsonis a companion tooling artifact derived from the same build result;- runtime must not depend on
build/asset_table.jsonas its primary source of truth.
Current runtime code now resolves preload by asset_id, but game-facing runtime APIs still refer to assets by asset_name.
Therefore this agenda distinguishes:
asset_idas stable artifact identity for preload/bootstrap and asset-table integrity;asset_nameas logical API-level identifier used by game/runtime-facing calls today.
This agenda does not introduce a second runtime-only asset identity.
The asset_id emitted by the packer is the same asset_id used in the runtime-facing artifact contract.
Key Questions
- How should the packer spec mirror the already normative
assets.pav1 envelope from runtime specs 13 and 15? - Which fields in
build/asset_table.jsonare companion tooling data versus runtime-facing contract data? - Should global asset packing order be deterministic by
asset_id, or influenced by usage and format-specific heuristics? - How should alignment be expressed and validated?
- What exactly counts as determinism for virtual asset pipelines?
- Which inferred values must be written back versus only emitted in build outputs?
- Which packer-side metadata is intentionally excluded from the runtime-facing contract?
- How should packer document
preloadlifecycle andoffsetsemantics so they match runtime reader behavior? - How should per-asset preload declarations be transformed into the
preloadsection ofassets.padeterministically? - How should the packer preserve both
asset_idintegrity andasset_namelookup semantics in runtime-facing artifacts? - Should
asset_tablebe modeled as a deterministically ordered asset list that preserves packerasset_idvalues end-to-end? - Which envelope fields are runtime-validated versus emitted only for Studio/tooling use?
Options
Option A
Keep assets.pa as the authoritative autocontained runtime-facing artifact and emit build/asset_table.json as a derived companion artifact for Studio and tooling.
Option B
Keep runtime-facing structure split across assets.pa and build/asset_table.json.
Tradeoffs
- Option A matches the runtime specs already in force.
- Option A keeps runtime authority in one artifact and prevents contract drift.
- Option A still allows rich tooling through a derived companion file.
- Option B risks splitting authority across artifacts and making runtime/tooling divergence easier.
Recommendation
Adopt Option A with these fixed directions:
assets.pais the authoritative runtime-facing artifact;- the
assets.paheader is the authoritative runtime-facing descriptor; build/asset_table.jsonis a derived companion artifact for Studio, debugging, inspection, and builder/tooling integration;- global packing order is deterministic by increasing
asset_id; - preload emission is derived deterministically from per-asset
preload.enabled; - alignment exists only when explicitly required by spec;
- offsets are always relative to the payload region, never to the start of the full file;
- checksum is not part of the baseline
assets.paenvelope contract.
Also adopt this performance direction:
- usage-based hot-first packing is not part of the baseline contract;
- deterministic stable ordering is preferred over heuristic physical reordering;
- future locality optimization may be introduced only through an explicit later decision and spec, not as an implementation shortcut now.
Also adopt this identity direction:
- runtime-facing preload entries should migrate to stable
asset_idinstead of mutableasset_name; - runtime-facing preload/bootstrap integrity should treat
asset_idas primary identity; asset_nameremains present inasset_tableas logical descriptive and API-facing metadata used by current runtime/game-facing calls;asset_tableshould be generated deterministically on every build from the current managed asset set;asset_tableshould be emitted as a deterministically ordered list of asset entries;- the runtime-facing
asset_idis exactly the stableasset_idallocated by the packer registry; - stable cross-build identity comes from
asset_id, not from table position; - rename of
asset_nameis therefore an API-visible/content-visible change, but not an identity change.
Also adopt this companion-artifact direction:
build/asset_table.jsonshould mirror the runtime-facing header data 1:1 for debugging and inspection;- if richer tooling artifacts are needed, they should be emitted as separate files instead of overloading
build/asset_table.json.
Expected Decisions to Produce
- v1 artifact boundary and ownership.
- Deterministic ordering and alignment rules.
- Descriptor schema responsibilities.
- Materialization requirements for inferred values.
- Runtime-facing artifact contract and reader expectations.
- Packer-side restatement of the runtime-owned
assets.paenvelope and slice semantics. - Deterministic mapping from asset declarations to runtime preload data.
- Explicit exclusion of usage-based packing heuristics from the baseline contract.
- Migration of preload/bootstrap integrity toward
asset_id-based identity while preservingasset_nameas current API-facing metadata. - Deterministically ordered
asset_tablepreserving packerasset_idvalues end-to-end. - Separation between runtime-validated envelope fields and non-envelope tooling concerns.
Expected Spec Follow-up
- Packed ROM artifact spec.
- Asset table descriptor spec.
- Determinism and reproducibility spec.
- Runtime consumption interface spec.
Non-Goals
- Asset workspace mutation commands.
- Quarantine behavior.
- Builder packaging flow.