Files
osmWorkflow/.trellis/tasks/archive/2026-08/08-11-asset-package-contract/implement.md

5.4 KiB

Asset Package Contract Implementation Plan

Phase 0: Contract Lock-In

  • Add a package-contract module that owns v1 schema constants, allowed roles and categories, URI containment validation, manifest construction and validation.
  • Add focused unit fixtures for valid manifests and each invalid condition: missing schema/placement/bounds, malformed coordinates, invalid role/category, absolute or traversing URI, duplicate asset ID, missing primary scene, and referenced file outside the package.
  • Document package/ as the sole downstream boundary in README and pipeline/config specs; retain a clear distinction between release assets and preview artifacts.

Gate: manifest v1 can be created and structurally validated without invoking Blender, Cesium or QGIS.

Phase 1: Package Paths and Static Export

  • Extend scripts/lib/area-config.js with paths for packageDir, package manifest, package model directory, primary GLB and semantic layer GLBs; keep all path derivation in this module.
  • Change blender/export_cesium.py metadata output to a static manifest seed: bounds, ENU placement and static scene/layer declarations only. Remove local source paths and inline Cesium source code from the published data.
  • Direct static GLB output to package staging paths and retain dynamic signal/countdown output as preview-only paths outside package staging.
  • Update build-area.js, semantic asset checks, stage manifests and diagnostics to consume the new path contract rather than constructing paths locally.

Gate: a Cesium export produces a valid static manifest seed and every declared static asset exists under package staging; no preview-only asset appears in it.

Phase 2: Compression and Atomic Publication

  • Refactor the default compression stage to operate on staged package files, preserving the final manifest shape while replacing only the primary GLB bytes and integrity data.
  • Add a package stage after compress; validate every asset and atomically promote staging to outputs/<area-id>/package/.
  • Update canonical stage ordering, all, interactive CLI labels and defaults.
  • Ensure a failed compression/package validation never replaces an existing published package; record diagnostics sufficient to identify the failed source/staging path.

Gate: a full build creates one publishable package with compressed primary GLB and no duplicate static GLBs at the area root.

Phase 3: Preview Adapter and Compatibility

  • Change preview HTML generation to reference package/manifest.json relative to the area output root.
  • Move route/vehicle/dynamic-signal discovery into a preview-only descriptor beneath _preview/, and make cesium-preview.js merge it after loading the package manifest.
  • Preserve existing preview controls and graceful behavior when preview-only data is absent; preview must still render the package static scene.
  • Update diagnose:area, check:area and stage manifest freshness to distinguish package artifacts from preview-only files.

Gate: the local Cesium preview loads the published package and continues to show optional cruise/dynamic preview content without adding either to package manifest.

Phase 4: Downstream Consumption Proof

  • Add Cesium example code that resolves the manifest URL, validates placement and loads the full scene or selected layers.
  • Add Three.js example code with a manifest-relative resolver and an explicit ENU placement handoff to the host's georeferencing integration.
  • Add automated resolver tests so neither example can regress to page-relative, desktop-absolute or repository-relative URLs.
  • Publish consumer documentation including overlap rules for complete scene vs layers.

Gate: examples run from a copied package/ directory and require no files outside it.

Phase 5: Full Verification and Migration

  • Run focused Node tests for package schema, stage resolution, compression metadata, preview behavior, diagnostics and asset budgets.
  • Run the full default build for the primary area, then check:area and package integrity validation.
  • Inspect the packaged GLB structure and validate the Cesium example in browser; verify Three.js resolver output with the same manifest.
  • Capture expected intentional output-contract changes in docs/changelog and update relevant Trellis pipeline/config/preview specs.
  • Preserve legacy root-level artifacts during rollout; document that downstream consumers must migrate to package/manifest.json rather than treating legacy files as fallback.

High-Risk Boundaries

  • blender/export_cesium.py to Node: static metadata fields and semantic asset file names are a cross-runtime contract.
  • Node packaging to preview runtime: preview-only dynamic data must never silently enter the package manifest.
  • Compression to publication: paths must remain package-relative and a partial write must not replace the last valid package.
  • Consumers: ENU axes and heading correction are load-bearing; examples must not create a second, incompatible georeferencing convention.

Validation Commands

npm run test:build-stages
npm run test:compress-glb
npm run test:preview-assets
npm run test:budgets
npm run test:preflight
npm run check:area -- --config config/areas/nantaizi-lake-innovation-valley.json
node scripts/glb-digest.js outputs/nantaizi-lake-innovation-valley/package/models/nantaizi-lake-innovation-valley.glb