--- id: LSN-0039 ticket: packer-pipeline-metadata-ownership title: Runtime Header Boundary and Tooling-Owned Pipeline Metadata created: 2026-04-10 tags: [packer, metadata, runtime-contract, tooling, codec, assets-pa] --- ## Context The packer had drift between implementation and spec around `output.pipeline` ownership. The runtime-facing artifact `assets.pa` was documented as if pipeline metadata should materialize under `asset_table[].metadata.pipeline`, while the implementation already treated at least part of that surface as tooling-oriented and excluded palette payloads from the runtime header. This created the wrong architectural pressure: Studio and third-party tools could start depending on `assets.pa` for authoring/build provenance, and runtime-facing specs could silently absorb build-time structures that do not belong in the execution contract. The discussion resolved that split explicitly and implemented it end to end in specs, packer materialization, and tests. ## Key Decisions ### Tooling Metadata Must Not Leak Into the Runtime Header **What:** `output.pipeline` remains tooling-only metadata in `asset.json` and related sidecar outputs. The runtime-facing `assets.pa` header must not mirror `output.pipeline` by default. Runtime-owned metadata remains under explicit, normalized fields in `asset_table[].metadata`. **Why:** `assets.pa` is the authoritative runtime artifact. If it starts carrying build provenance, editor-oriented structures, or reverse-sync payloads merely because they exist in the authoring manifest, the runtime contract becomes larger, noisier, and harder to evolve safely. **Trade-offs:** Tools that want provenance cannot rely on one binary artifact alone. They must read `asset.json` and/or `build/asset_table_metadata.json`. That is a deliberate trade-off in favor of a cleaner runtime boundary. ### Promotion Must Be Explicit, Not a Bulk Mirror **What:** If pipeline-derived information is needed at runtime, it must be promoted into an explicit normative field under runtime-owned metadata. The packer must not reintroduce a generic mirrored `pipeline` object under another name. **Why:** Bulk mirroring hides product decisions inside implementation convenience. Explicit promotion forces each field to justify its presence in the runtime contract. **Trade-offs:** This adds small editorial and implementation work whenever a new runtime-facing derived field is introduced, but it keeps the contract intentional and testable. ### Codec Serialization Must Stay in `SCREAMING_SNAKE_CASE` **What:** Serialized asset entry `codec` values are locked to `SCREAMING_SNAKE_CASE`. The currently known `NONE` value remains serialized as `NONE`. **Why:** The implementation already had a stable manifest/runtime representation through `OutputCodecCatalog`. Recording that casing in spec prevents future drift when more codecs are added. **Trade-offs:** Future codec additions must preserve the established serialized style unless a new decision explicitly revises the contract. ## Patterns and Algorithms - Use separate surfaces for separate consumers: `assets.pa` for runtime contract, `asset_table_metadata.json` for tooling-oriented provenance, and `asset.json` for authoring intent. - Build runtime metadata from explicit normalized fields first, then derive tooling sidecars from a superset when needed. - Keep the runtime header free of raw authoring/build objects even if the sidecar keeps them intact for Studio or inspection tools. - Lock serialized enum casing in spec as soon as the first value ships, even if the current catalog is minimal. ## Pitfalls - Do not treat “already present in the manifest” as sufficient reason to serialize a field into the runtime header. - Do not let sidecar convenience become implicit runtime compatibility. - Do not partially filter a tooling object and leave an empty placeholder in runtime metadata unless that placeholder has explicit runtime meaning. - Do not leave enum casing as an implementation accident. If the manifest value matters, the spec must say so. ## Takeaways - The runtime header is a contract surface, not a metadata dump. - Tooling provenance belongs in `asset.json` and `build/asset_table_metadata.json`, not in `assets.pa`. - Runtime-facing derived metadata must be promoted explicitly field by field. - Stable serialized casing rules should be fixed in spec before the value set grows.