58 lines
3.3 KiB
Markdown
58 lines
3.3 KiB
Markdown
# ADR 0043: Content-Addressed Import Fingerprints
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
Generated model artifacts and the project asset registry must be stable across contributors, CI,
|
|
Git worktrees, and LFS checkouts. Git does not preserve source-file modification times. Persisting a
|
|
checkout mtime as source identity therefore caused the editor to rewrite otherwise equivalent
|
|
animation and static-mesh manifests during startup. Static-mesh manifests also used only byte length
|
|
and mtime, so a same-size source edit could evade the persisted identity contract.
|
|
|
|
Formatting-only publication was a second source of noise. Re-serializing an equivalent RON
|
|
document could normalize its final newline or layout even when import semantics had not changed.
|
|
That made clean-checkout release evidence unreliable and obscured intentional asset edits.
|
|
|
|
## Decision
|
|
|
|
`shared::AssetSourceFingerprint` is the persisted imported-source identity. It contains the exact
|
|
source byte length and lowercase BLAKE3 digest. Filesystem timestamps are not serialized or compared
|
|
as semantic identity; an importer may use them only as an in-memory scan hint before confirming
|
|
content.
|
|
|
|
The asset registry stores this fingerprint for every imported model, texture, and audio source.
|
|
Content identity also drives unique move reconciliation, so metadata-only drift cannot replace a
|
|
stable registry UUID. Ambiguous copies still receive a new identity.
|
|
|
|
Animation and static-mesh manifests use the same fingerprint. Animation schema v3 already contained
|
|
a content hash, so its schema remains v3 and legacy `modified_unix_secs` fields are accepted as
|
|
ignored unknown metadata. Static-mesh schema v4 replaces its length-plus-mtime record with length
|
|
plus BLAKE3. Existing schema-v3 static artifacts are regenerated once; unrelated assets are not
|
|
reimported.
|
|
|
|
Registry and generated-manifest writers parse the existing RON and compare the semantic value before
|
|
publication. Equivalent documents preserve their exact existing bytes, including layout and final
|
|
newlines. Changed documents publish canonical pretty RON. Registry records are ordered by normalized
|
|
project path before comparison, so filesystem enumeration order cannot change their serialized
|
|
sequence on a fresh checkout.
|
|
|
|
Authoritative project validation remains read-only. It validates registry, animation, and
|
|
static-mesh fingerprints by length and digest, including same-size source edits. CI runs both
|
|
headless validators and then asserts that tracked and untracked checkout state is unchanged.
|
|
|
|
## Consequences
|
|
|
|
- A source touch or fresh checkout mtime cannot dirty the project.
|
|
- Same-size source edits invalidate the affected registry/manifests deterministically.
|
|
- Model, texture, and audio IDs survive uniquely identifiable moves by content.
|
|
- Initial migration adds fingerprints to imported registry records and upgrades static manifests to
|
|
schema v4. Legacy animation files can remain byte-identical indefinitely because their timestamp
|
|
field is ignored.
|
|
- Startup hashing reads imported source bytes. Future scan caches may use metadata to avoid work,
|
|
but they must verify content before persisting a changed identity.
|
|
- External glTF/FBX dependency paths remain explicit manifest dependencies; extending fingerprints
|
|
to a dependency graph requires a separate versioned contract.
|