Reviewed-on: #3 Co-authored-by: bQUARKz <bquarkz@gmail.com> Co-committed-by: bQUARKz <bquarkz@gmail.com>
6.2 KiB
Asset Declaration and Virtual Asset Contract Specification
Status: Draft
Scope: Common asset.json contract
Purpose: Define the shared declaration model for raw and virtual assets.
Authority and Precedence
This specification consolidates the initial packer agenda and decision wave into normative form.
Core Rules
The common asset.json contract requires these top-level fields:
schema_versionasset_uuidnametypeinputsoutputpreload
The common contract may also include:
build
Meaning of asset_uuid
asset_uuid is the stable asset-local identity anchor.
Rules:
- it is required;
- it must be stable across relocate and rename flows;
- it is not the project-local runtime artifact identity;
- it is not a substitute for registry-owned
asset_id; - it exists so the asset root can preserve identity even when path-based assumptions drift;
- it must remain compatible with packer reconcile behavior and migration flows.
Meaning of name
name is the logical asset reference label.
Rules:
- it is required;
- it is not the stable artifact identity;
- it may still be used by runtime-facing APIs and source-level workflows.
Meaning of type
type identifies the authoring-side asset family.
Rules:
- it is not the runtime bank identity;
- the runtime-facing technical target belongs in
output.format.
Examples:
glyph_banksound_bank
Inputs
inputs is a structured object keyed by semantic role.
Rules:
- each key names an input role such as
sprites,palettes, orsources; - each value is a list of paths;
- paths are relative to the asset root;
- even a single input is represented as a list.
This model supports grouped virtual assets such as atlases and bank-style assets.
Output
output is the runtime-relevant output declaration.
Required baseline fields:
output.formatoutput.codec
Optional baseline field:
output.metadataoutput.pipeline
Rules:
output.formatdefines the semantic/runtime format contract;output.codecdefines storage/extraction behavior;output.codecserialized values must useSCREAMING_SNAKE_CASE;output.metadatacarries runtime-relevant format-specific detail;output.pipelinecarries tooling/build metadata kept separate at authoring time;- codec must remain explicit and must not be hidden inside format naming.
Explicit Index Collections
When output.pipeline carries ordered collections whose members need stable semantic identity, that identity must not depend on raw list position alone.
Rules:
- collections such as
output.pipeline.palettesmay remain JSON arrays for authoring ergonomics; - when a collection member has runtime- or packing-relevant identity, each entry must carry an explicit
index; output.pipeline.palettesentries must use the shape{ "index": <int>, "palette": { ... } };- the packer must sort such entries by numeric
index, not by physical array position; - duplicate or malformed indices are structural errors;
- missing or malformed
palettepayloads are structural errors; - editorial reordering of the JSON array alone must not change semantic meaning.
Example:
{
"output": {
"pipeline": {
"palettes": [
{
"index": 0,
"palette": {
"originalArgb8888": [4294901760, 4278255360],
"convertedRgb565": [63488, 2016]
}
}
]
}
}
}
Metadata Source Segmentation and Runtime Sink
asset.json may keep metadata segmented by concern during authoring.
Rules:
- declaration-time metadata may come from multiple sources under the asset contract (for example, format metadata, codec-related metadata, and build/pipeline-derived declarations);
output.pipelinemay carry nested pipeline-derived metadata objects;- this segmentation exists for authoring clarity and does not define multiple runtime sinks;
output.pipelineis tooling-only and must not become part of the runtime-facing asset header by default;- pipeline-derived values required at runtime must be promoted explicitly into normative runtime-owned metadata fields;
- runtime consumers must read effective metadata from the runtime asset entry metadata sink (
AssetEntry.metadata); - convergence/normalization behavior is normative in the build artifact specification.
Build
build is optional and process-oriented.
Rules:
- it may describe how authoring inputs are transformed or organized;
- if a parameter affects the runtime-facing output contract, it belongs in
output.metadata; buildmust not hide runtime-relevant semantics.
Operational State Exclusion
asset.json is a declaration artifact, not a catalog cache.
Rules:
- transient UI state must not be stored in
asset.json; - registry-managed fields such as
asset_idandincluded_in_buildmust not be duplicated intoasset.json; - packer cache or snapshot bookkeeping must not be materialized into
asset.jsonas normal operational state; asset.jsonshould remain focused on identity anchoring plus declared authoring/packing behavior.
Preload
Each registered asset must declare preload intent explicitly.
Baseline shape:
{
"preload": {
"enabled": true
}
}
Rules:
preload.enabledis required and boolean;- preload participation is declared, not inferred;
- richer preload policy fields are deferred.
Defaults and Materialization
Defaults that affect runtime-visible behavior must not remain hidden.
Rules:
- runtime-relevant defaults should be materialized in
asset.jsonwhenever practical; - if materialized later, the resulting artifact must expose effective values explicitly.
Versioning
The asset.json schema is versioned independently from:
- registry schema
- runtime-facing artifact schema
- format contract versions
Format-specific contracts evolve through values such as GLYPH/indexed_v1.
Non-Goals
- field-level format schemas for every output family
- rich preload policies
- source-language lowering behavior for asset references
Exit Criteria
This specification is complete enough when:
- the common
asset.jsonshape is stable; - raw and virtual assets share a coherent baseline contract;
- format-specific specs can build on it cleanly.