@aura3d/cli 3.0.1 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -15
- package/dist/admission/artDirection.d.ts +28 -0
- package/dist/admission/artDirection.d.ts.map +1 -0
- package/dist/admission/artDirection.js +47 -0
- package/dist/admission/artDirection.js.map +1 -0
- package/dist/admission/audio.d.ts +19 -0
- package/dist/admission/audio.d.ts.map +1 -0
- package/dist/admission/audio.js +31 -0
- package/dist/admission/audio.js.map +1 -0
- package/dist/admission/builder-patterns.d.ts +25 -0
- package/dist/admission/builder-patterns.d.ts.map +1 -0
- package/dist/admission/builder-patterns.js +40 -0
- package/dist/admission/builder-patterns.js.map +1 -0
- package/dist/admission/gates.d.ts +136 -0
- package/dist/admission/gates.d.ts.map +1 -0
- package/dist/admission/gates.js +335 -0
- package/dist/admission/gates.js.map +1 -0
- package/dist/admission/glb.d.ts +64 -0
- package/dist/admission/glb.d.ts.map +1 -0
- package/dist/admission/glb.js +128 -0
- package/dist/admission/glb.js.map +1 -0
- package/dist/admission/index.d.ts +8 -0
- package/dist/admission/index.d.ts.map +1 -0
- package/dist/admission/index.js +8 -0
- package/dist/admission/index.js.map +1 -0
- package/dist/admission/profiles.d.ts +52 -0
- package/dist/admission/profiles.d.ts.map +1 -0
- package/dist/admission/profiles.js +91 -0
- package/dist/admission/profiles.js.map +1 -0
- package/dist/admission/qrFlags.d.ts +12 -0
- package/dist/admission/qrFlags.d.ts.map +1 -0
- package/dist/admission/qrFlags.js +48 -0
- package/dist/admission/qrFlags.js.map +1 -0
- package/dist/admission/routeGates.d.ts +36 -0
- package/dist/admission/routeGates.d.ts.map +1 -0
- package/dist/admission/routeGates.js +144 -0
- package/dist/admission/routeGates.js.map +1 -0
- package/dist/admission/texel.d.ts +50 -0
- package/dist/admission/texel.d.ts.map +1 -0
- package/dist/admission/texel.js +177 -0
- package/dist/admission/texel.js.map +1 -0
- package/dist/admission/textureStats.d.ts +45 -0
- package/dist/admission/textureStats.d.ts.map +1 -0
- package/dist/admission/textureStats.js +201 -0
- package/dist/admission/textureStats.js.map +1 -0
- package/dist/animation-asset-validator.d.ts +44 -0
- package/dist/animation-asset-validator.d.ts.map +1 -1
- package/dist/animation-asset-validator.js +80 -1
- package/dist/animation-asset-validator.js.map +1 -1
- package/dist/asset-core-types.d.ts +100 -4
- package/dist/asset-core-types.d.ts.map +1 -1
- package/dist/asset-inspection-types.d.ts +9 -0
- package/dist/asset-inspection-types.d.ts.map +1 -1
- package/dist/asset-manifest.d.ts +1 -0
- package/dist/asset-manifest.d.ts.map +1 -1
- package/dist/asset-manifest.js +17 -5
- package/dist/asset-manifest.js.map +1 -1
- package/dist/asset-route-typegen.d.ts +37 -0
- package/dist/asset-route-typegen.d.ts.map +1 -0
- package/dist/asset-route-typegen.js +179 -0
- package/dist/asset-route-typegen.js.map +1 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +9 -4
- package/dist/cli-help.js.map +1 -1
- package/dist/cli-options.d.ts +7 -0
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +33 -2
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -11
- package/dist/cli.js.map +1 -1
- package/dist/codemods/engine-entry-imports.d.ts +22 -0
- package/dist/codemods/engine-entry-imports.d.ts.map +1 -0
- package/dist/codemods/engine-entry-imports.js +159 -0
- package/dist/codemods/engine-entry-imports.js.map +1 -0
- package/dist/codemods/lean-imports.d.ts +40 -0
- package/dist/codemods/lean-imports.d.ts.map +1 -0
- package/dist/codemods/lean-imports.js +175 -0
- package/dist/codemods/lean-imports.js.map +1 -0
- package/dist/codemods/renderer-imports.d.ts +36 -0
- package/dist/codemods/renderer-imports.d.ts.map +1 -0
- package/dist/codemods/renderer-imports.js +364 -0
- package/dist/codemods/renderer-imports.js.map +1 -0
- package/dist/codemods/renderer-mode.d.ts +38 -0
- package/dist/codemods/renderer-mode.d.ts.map +1 -0
- package/dist/codemods/renderer-mode.js +130 -0
- package/dist/codemods/renderer-mode.js.map +1 -0
- package/dist/commands/prd01/index.d.ts +8 -0
- package/dist/commands/prd01/index.d.ts.map +1 -0
- package/dist/commands/prd01/index.js +39 -0
- package/dist/commands/prd01/index.js.map +1 -0
- package/dist/commands/prd02/environmentsBake.d.ts +6 -0
- package/dist/commands/prd02/environmentsBake.d.ts.map +1 -0
- package/dist/commands/prd02/environmentsBake.js +174 -0
- package/dist/commands/prd02/environmentsBake.js.map +1 -0
- package/dist/commands/prd02/index.d.ts +2 -0
- package/dist/commands/prd02/index.d.ts.map +1 -0
- package/dist/commands/prd02/index.js +26 -0
- package/dist/commands/prd02/index.js.map +1 -0
- package/dist/commands/prd02/migrateLighting.d.ts +17 -0
- package/dist/commands/prd02/migrateLighting.d.ts.map +1 -0
- package/dist/commands/prd02/migrateLighting.js +86 -0
- package/dist/commands/prd02/migrateLighting.js.map +1 -0
- package/dist/commands/prd02/migrateLightingSweep.d.ts +20 -0
- package/dist/commands/prd02/migrateLightingSweep.d.ts.map +1 -0
- package/dist/commands/prd02/migrateLightingSweep.js +105 -0
- package/dist/commands/prd02/migrateLightingSweep.js.map +1 -0
- package/dist/commands/prd03/index.d.ts +7 -0
- package/dist/commands/prd03/index.d.ts.map +1 -0
- package/dist/commands/prd03/index.js +9 -0
- package/dist/commands/prd03/index.js.map +1 -0
- package/dist/commands/prd04/index.d.ts +10 -0
- package/dist/commands/prd04/index.d.ts.map +1 -0
- package/dist/commands/prd04/index.js +10 -0
- package/dist/commands/prd04/index.js.map +1 -0
- package/dist/commands/prd04/modelTintReport.d.ts +16 -0
- package/dist/commands/prd04/modelTintReport.d.ts.map +1 -0
- package/dist/commands/prd04/modelTintReport.js +114 -0
- package/dist/commands/prd04/modelTintReport.js.map +1 -0
- package/dist/commands/prd04/pinEmissiveDefaults.d.ts +3 -0
- package/dist/commands/prd04/pinEmissiveDefaults.d.ts.map +1 -0
- package/dist/commands/prd04/pinEmissiveDefaults.js +36 -0
- package/dist/commands/prd04/pinEmissiveDefaults.js.map +1 -0
- package/dist/commands/prd05/admit.d.ts +54 -0
- package/dist/commands/prd05/admit.d.ts.map +1 -0
- package/dist/commands/prd05/admit.js +153 -0
- package/dist/commands/prd05/admit.js.map +1 -0
- package/dist/commands/prd05/codemods/assetsRouteModules.d.ts +3 -0
- package/dist/commands/prd05/codemods/assetsRouteModules.d.ts.map +1 -0
- package/dist/commands/prd05/codemods/assetsRouteModules.js +92 -0
- package/dist/commands/prd05/codemods/assetsRouteModules.js.map +1 -0
- package/dist/commands/prd05/index.d.ts +9 -0
- package/dist/commands/prd05/index.d.ts.map +1 -0
- package/dist/commands/prd05/index.js +171 -0
- package/dist/commands/prd05/index.js.map +1 -0
- package/dist/commands/prd05/library.d.ts +23 -0
- package/dist/commands/prd05/library.d.ts.map +1 -0
- package/dist/commands/prd05/library.js +245 -0
- package/dist/commands/prd05/library.js.map +1 -0
- package/dist/commands/prd05/lookdev.d.ts +14 -0
- package/dist/commands/prd05/lookdev.d.ts.map +1 -0
- package/dist/commands/prd05/lookdev.js +68 -0
- package/dist/commands/prd05/lookdev.js.map +1 -0
- package/dist/commands/prd05/optimize.d.ts +16 -0
- package/dist/commands/prd05/optimize.d.ts.map +1 -0
- package/dist/commands/prd05/optimize.js +55 -0
- package/dist/commands/prd05/optimize.js.map +1 -0
- package/dist/commands/prd05/prune.d.ts +26 -0
- package/dist/commands/prd05/prune.d.ts.map +1 -0
- package/dist/commands/prd05/prune.js +104 -0
- package/dist/commands/prd05/prune.js.map +1 -0
- package/dist/commands/prd05/review.d.ts +24 -0
- package/dist/commands/prd05/review.d.ts.map +1 -0
- package/dist/commands/prd05/review.js +40 -0
- package/dist/commands/prd05/review.js.map +1 -0
- package/dist/commands/prd06/index.d.ts +6 -0
- package/dist/commands/prd06/index.d.ts.map +1 -0
- package/dist/commands/prd06/index.js +86 -0
- package/dist/commands/prd06/index.js.map +1 -0
- package/dist/commands/prd06/inspectAnimationClips.d.ts +86 -0
- package/dist/commands/prd06/inspectAnimationClips.d.ts.map +1 -0
- package/dist/commands/prd06/inspectAnimationClips.js +168 -0
- package/dist/commands/prd06/inspectAnimationClips.js.map +1 -0
- package/dist/commands/prd06/validateHero.d.ts +18 -0
- package/dist/commands/prd06/validateHero.d.ts.map +1 -0
- package/dist/commands/prd06/validateHero.js +91 -0
- package/dist/commands/prd06/validateHero.js.map +1 -0
- package/dist/commands/prd07/codemods.d.ts +28 -0
- package/dist/commands/prd07/codemods.d.ts.map +1 -0
- package/dist/commands/prd07/codemods.js +155 -0
- package/dist/commands/prd07/codemods.js.map +1 -0
- package/dist/commands/prd07/index.d.ts +2 -0
- package/dist/commands/prd07/index.d.ts.map +1 -0
- package/dist/commands/prd07/index.js +151 -0
- package/dist/commands/prd07/index.js.map +1 -0
- package/dist/commands/prd08/feelLint.d.ts +13 -0
- package/dist/commands/prd08/feelLint.d.ts.map +1 -0
- package/dist/commands/prd08/feelLint.js +32 -0
- package/dist/commands/prd08/feelLint.js.map +1 -0
- package/dist/commands/prd08/index.d.ts +2 -0
- package/dist/commands/prd08/index.d.ts.map +1 -0
- package/dist/commands/prd08/index.js +16 -0
- package/dist/commands/prd08/index.js.map +1 -0
- package/dist/commands/prd08/motionReport.d.ts +94 -0
- package/dist/commands/prd08/motionReport.d.ts.map +1 -0
- package/dist/commands/prd08/motionReport.js +197 -0
- package/dist/commands/prd08/motionReport.js.map +1 -0
- package/dist/commands/prd09/codemods/audio-wrapper.d.ts +9 -0
- package/dist/commands/prd09/codemods/audio-wrapper.d.ts.map +1 -0
- package/dist/commands/prd09/codemods/audio-wrapper.js +30 -0
- package/dist/commands/prd09/codemods/audio-wrapper.js.map +1 -0
- package/dist/commands/prd09/codemods/capture-branches.d.ts +10 -0
- package/dist/commands/prd09/codemods/capture-branches.d.ts.map +1 -0
- package/dist/commands/prd09/codemods/capture-branches.js +54 -0
- package/dist/commands/prd09/codemods/capture-branches.js.map +1 -0
- package/dist/commands/prd09/codemods/evidence-globals.d.ts +8 -0
- package/dist/commands/prd09/codemods/evidence-globals.d.ts.map +1 -0
- package/dist/commands/prd09/codemods/evidence-globals.js +19 -0
- package/dist/commands/prd09/codemods/evidence-globals.js.map +1 -0
- package/dist/commands/prd09/codemods/perf-script.d.ts +8 -0
- package/dist/commands/prd09/codemods/perf-script.d.ts.map +1 -0
- package/dist/commands/prd09/codemods/perf-script.js +24 -0
- package/dist/commands/prd09/codemods/perf-script.js.map +1 -0
- package/dist/commands/prd09/index.d.ts +8 -0
- package/dist/commands/prd09/index.d.ts.map +1 -0
- package/dist/commands/prd09/index.js +19 -0
- package/dist/commands/prd09/index.js.map +1 -0
- package/dist/commands/prd09/perf-report.d.ts +56 -0
- package/dist/commands/prd09/perf-report.d.ts.map +1 -0
- package/dist/commands/prd09/perf-report.js +118 -0
- package/dist/commands/prd09/perf-report.js.map +1 -0
- package/dist/commands/prd09/sfx-admit.d.ts +18 -0
- package/dist/commands/prd09/sfx-admit.d.ts.map +1 -0
- package/dist/commands/prd09/sfx-admit.js +120 -0
- package/dist/commands/prd09/sfx-admit.js.map +1 -0
- package/dist/commands/prd10/index.d.ts +2 -0
- package/dist/commands/prd10/index.d.ts.map +1 -0
- package/dist/commands/prd10/index.js +109 -0
- package/dist/commands/prd10/index.js.map +1 -0
- package/dist/commands/prd11/batchOptout.d.ts +35 -0
- package/dist/commands/prd11/batchOptout.d.ts.map +1 -0
- package/dist/commands/prd11/batchOptout.js +155 -0
- package/dist/commands/prd11/batchOptout.js.map +1 -0
- package/dist/commands/prd11/index.d.ts +2 -0
- package/dist/commands/prd11/index.d.ts.map +1 -0
- package/dist/commands/prd11/index.js +13 -0
- package/dist/commands/prd11/index.js.map +1 -0
- package/dist/commands/prd11/perfGate.d.ts +15 -0
- package/dist/commands/prd11/perfGate.d.ts.map +1 -0
- package/dist/commands/prd11/perfGate.js +98 -0
- package/dist/commands/prd11/perfGate.js.map +1 -0
- package/dist/commands/prd13/index.d.ts +15 -0
- package/dist/commands/prd13/index.d.ts.map +1 -0
- package/dist/commands/prd13/index.js +26 -0
- package/dist/commands/prd13/index.js.map +1 -0
- package/dist/commands/prd13/run.d.ts +10 -0
- package/dist/commands/prd13/run.d.ts.map +1 -0
- package/dist/commands/prd13/run.js +29 -0
- package/dist/commands/prd13/run.js.map +1 -0
- package/dist/commands/prd14/index.d.ts +6 -0
- package/dist/commands/prd14/index.d.ts.map +1 -0
- package/dist/commands/prd14/index.js +6 -0
- package/dist/commands/prd14/index.js.map +1 -0
- package/dist/commands/prd15/index.d.ts +8 -0
- package/dist/commands/prd15/index.d.ts.map +1 -0
- package/dist/commands/prd15/index.js +152 -0
- package/dist/commands/prd15/index.js.map +1 -0
- package/dist/commands/registry.d.ts +19 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +19 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/contracts/assetManifest.d.ts +80 -0
- package/dist/contracts/assetManifest.d.ts.map +1 -0
- package/dist/contracts/assetManifest.js +9 -0
- package/dist/contracts/assetManifest.js.map +1 -0
- package/dist/contracts/commands.d.ts +53 -0
- package/dist/contracts/commands.d.ts.map +1 -0
- package/dist/contracts/commands.js +37 -0
- package/dist/contracts/commands.js.map +1 -0
- package/dist/index.d.ts +17 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +297 -73
- package/dist/index.js.map +1 -1
- package/dist/library-manifest.d.ts +86 -0
- package/dist/library-manifest.d.ts.map +1 -0
- package/dist/library-manifest.js +95 -0
- package/dist/library-manifest.js.map +1 -0
- package/dist/look/capture.d.ts +51 -0
- package/dist/look/capture.d.ts.map +1 -0
- package/dist/look/capture.js +229 -0
- package/dist/look/capture.js.map +1 -0
- package/dist/look/judge.d.ts +24 -0
- package/dist/look/judge.d.ts.map +1 -0
- package/dist/look/judge.js +151 -0
- package/dist/look/judge.js.map +1 -0
- package/dist/look/lint-static.d.ts +45 -0
- package/dist/look/lint-static.d.ts.map +1 -0
- package/dist/look/lint-static.js +241 -0
- package/dist/look/lint-static.js.map +1 -0
- package/dist/look/rubric.d.ts +70 -0
- package/dist/look/rubric.d.ts.map +1 -0
- package/dist/look/rubric.js +169 -0
- package/dist/look/rubric.js.map +1 -0
- package/dist/meshy/admission.d.ts.map +1 -1
- package/dist/meshy/admission.js +32 -7
- package/dist/meshy/admission.js.map +1 -1
- package/dist/meshy/import.d.ts +7 -1
- package/dist/meshy/import.d.ts.map +1 -1
- package/dist/meshy/import.js +84 -6
- package/dist/meshy/import.js.map +1 -1
- package/dist/migrate-three/CompatibilityWarnings.d.ts +6 -0
- package/dist/migrate-three/CompatibilityWarnings.d.ts.map +1 -0
- package/dist/migrate-three/CompatibilityWarnings.js +24 -0
- package/dist/migrate-three/CompatibilityWarnings.js.map +1 -0
- package/dist/migrate-three/ImportMap.d.ts +19 -0
- package/dist/migrate-three/ImportMap.d.ts.map +1 -0
- package/dist/migrate-three/ImportMap.js +35 -0
- package/dist/migrate-three/ImportMap.js.map +1 -0
- package/dist/migrate-three/R3fMigration.d.ts +32 -0
- package/dist/migrate-three/R3fMigration.d.ts.map +1 -0
- package/dist/migrate-three/R3fMigration.js +70 -0
- package/dist/migrate-three/R3fMigration.js.map +1 -0
- package/dist/migrate-three/ThreeToA3DAdapter.d.ts +8 -0
- package/dist/migrate-three/ThreeToA3DAdapter.d.ts.map +1 -0
- package/dist/migrate-three/ThreeToA3DAdapter.js +20 -0
- package/dist/migrate-three/ThreeToA3DAdapter.js.map +1 -0
- package/dist/migrate-three/emit.d.ts +21 -0
- package/dist/migrate-three/emit.d.ts.map +1 -0
- package/dist/migrate-three/emit.js +117 -0
- package/dist/migrate-three/emit.js.map +1 -0
- package/dist/migrate-three/mappings.d.ts +21 -0
- package/dist/migrate-three/mappings.d.ts.map +1 -0
- package/dist/migrate-three/mappings.js +42 -0
- package/dist/migrate-three/mappings.js.map +1 -0
- package/dist/migrate-three/parse.d.ts +20 -0
- package/dist/migrate-three/parse.d.ts.map +1 -0
- package/dist/migrate-three/parse.js +56 -0
- package/dist/migrate-three/parse.js.map +1 -0
- package/dist/migrate-three/report.d.ts +18 -0
- package/dist/migrate-three/report.d.ts.map +1 -0
- package/dist/migrate-three/report.js +16 -0
- package/dist/migrate-three/report.js.map +1 -0
- package/dist/pull-bridge/adapters.d.ts +1 -1
- package/dist/pull-bridge/adapters.d.ts.map +1 -1
- package/dist/pull-bridge/adapters.js +17 -4
- package/dist/pull-bridge/adapters.js.map +1 -1
- package/dist/pull-bridge/provenance.d.ts.map +1 -1
- package/dist/pull-bridge/provenance.js +3 -2
- package/dist/pull-bridge/provenance.js.map +1 -1
- package/dist/pull-bridge/pullable.d.ts.map +1 -1
- package/dist/pull-bridge/pullable.js +14 -3
- package/dist/pull-bridge/pullable.js.map +1 -1
- package/dist/pull-bridge/scoring.d.ts +36 -8
- package/dist/pull-bridge/scoring.d.ts.map +1 -1
- package/dist/pull-bridge/scoring.js +143 -47
- package/dist/pull-bridge/scoring.js.map +1 -1
- package/dist/pull-bridge/search.d.ts +2 -0
- package/dist/pull-bridge/search.d.ts.map +1 -1
- package/dist/pull-bridge/search.js +17 -10
- package/dist/pull-bridge/search.js.map +1 -1
- package/dist/pull-bridge.d.ts +2 -2
- package/dist/pull-bridge.d.ts.map +1 -1
- package/dist/pull-bridge.js +24 -8
- package/dist/pull-bridge.js.map +1 -1
- package/package.json +6 -3
- package/skills/agent-files/AGENTS.md +3 -0
- package/skills/aura3d-animation-studio/SKILL.md +153 -0
- package/skills/aura3d-animation-studio/references/shot-looks.md +26 -0
- package/skills/aura3d-art-direction/SKILL.md +84 -0
- package/skills/aura3d-art-direction/references/failure-gallery.md +64 -0
- package/skills/aura3d-art-direction/references/framing-and-shots.md +45 -0
- package/skills/aura3d-art-direction/references/look-recipes.md +32 -0
- package/skills/aura3d-art-direction/references/quality-bar.md +103 -0
- package/skills/aura3d-art-direction/references/reference-frames.md +82 -0
- package/skills/aura3d-assets/SKILL.md +151 -0
- package/skills/aura3d-assets/references/preview-under-look.md +26 -0
- package/skills/aura3d-browser-game/SKILL.md +149 -0
- package/skills/aura3d-browser-game/references/genre-looks.md +52 -0
- package/skills/aura3d-character-animation/SKILL.md +129 -0
- package/skills/aura3d-character-animation/references/stage-and-lighting.md +31 -0
- package/skills/aura3d-core/SKILL.md +143 -0
- package/skills/aura3d-core/references/boundaries.md +91 -0
- package/skills/aura3d-evidence-review/SKILL.md +106 -0
- package/skills/aura3d-game-art/SKILL.md +118 -0
- package/skills/aura3d-game-art/references/sheet-check.mjs +58 -0
- package/skills/aura3d-game-art/references/sprite-palettes.md +25 -0
- package/skills/aura3d-materials-environments/SKILL.md +139 -0
- package/skills/aura3d-performance/SKILL.md +97 -0
- package/skills/aura3d-retexture/SKILL.md +115 -0
- package/skills/aura3d-retexture/references/geometry-hash.mjs +89 -0
- package/skills/aura3d-scene-authoring/SKILL.md +132 -0
- package/skills/aura3d-scene-authoring/references/look-by-family.md +28 -0
- package/skills/aura3d-threejs-migration/SKILL.md +125 -0
- package/skills/aura3d-threejs-migration/references/look-mapping.md +27 -0
- package/skills/llms.txt +147 -0
- package/skills/manifest.json +163 -0
- package/skills/meshy-cli/SKILL.md +148 -0
package/dist/index.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
2
3
|
import { createHash } from "node:crypto";
|
|
3
|
-
import {
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
4
7
|
import { inflateSync } from "node:zlib";
|
|
8
|
+
import { writeAgentSkills } from "create-aura3d";
|
|
9
|
+
import { measureLoudness } from "@aura3d/audio";
|
|
5
10
|
import { admitAssetForRole } from "./asset-role-admission.js";
|
|
11
|
+
import { hasStylizedFlatApproval } from "./admission/artDirection.js";
|
|
12
|
+
import { AUDIO_SYNTH_RELEASE_ALLOWLIST, isSynthesizedAudioProvenance } from "./admission/audio.js";
|
|
13
|
+
import { profileForRole, requiresPbrTextures } from "./admission/profiles.js";
|
|
6
14
|
import { DEFAULT_AURA_ASSET_MANIFEST, DEFAULT_AURA_ASSET_OUTPUT_DIR, DEFAULT_AURA_ASSET_PUBLIC_PATH, DEFAULT_AURA_ASSET_TYPEGEN } from "./asset-constants.js";
|
|
7
15
|
import { shouldScanSource, validateAssetSource } from "./asset-source-validation.js";
|
|
8
16
|
import { listAssets, readAssetManifest, writeAssetManifest, writeTypedAssets } from "./asset-manifest.js";
|
|
@@ -99,6 +107,39 @@ export function readRenderedProbeMetadata(options) {
|
|
|
99
107
|
...(foregroundBounds ? { foregroundBounds } : {})
|
|
100
108
|
};
|
|
101
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* BS.1770 loudness + true-peak for `assets add --type audio` — the same
|
|
112
|
+
* decode→measureLoudness path `sfx admit` uses (48 kHz f32 PCM). Returns
|
|
113
|
+
* `loudnessMeasured: true` even when integrated LUFS is unmeasurable
|
|
114
|
+
* (sub-400 ms files), so a short blip records a measured-null rather than
|
|
115
|
+
* looking unmeasured to the C-25 release gate. `undefined` when ffmpeg is
|
|
116
|
+
* missing or the file will not decode.
|
|
117
|
+
*/
|
|
118
|
+
function measureAudioLoudness(sourcePath) {
|
|
119
|
+
try {
|
|
120
|
+
const channelCount = Number(execFileSync("ffprobe", ["-v", "error", "-select_streams", "a:0", "-show_entries", "stream=channels", "-of", "csv=p=0", sourcePath], {
|
|
121
|
+
maxBuffer: 1 << 24
|
|
122
|
+
})
|
|
123
|
+
.toString("utf8")
|
|
124
|
+
.trim()) || 1;
|
|
125
|
+
const pcm = execFileSync("ffmpeg", ["-hide_banner", "-loglevel", "error", "-y", "-i", sourcePath, "-f", "f32le", "-ac", String(channelCount), "-ar", "48000", "-"], { maxBuffer: 1 << 28 });
|
|
126
|
+
const channels = Array.from({ length: channelCount }, (_, c) => {
|
|
127
|
+
const out = new Float32Array(pcm.length / 4 / channelCount);
|
|
128
|
+
for (let i = 0; i < out.length; i++)
|
|
129
|
+
out[i] = pcm.readFloatLE((i * channelCount + c) * 4);
|
|
130
|
+
return out;
|
|
131
|
+
});
|
|
132
|
+
const measured = measureLoudness({ channels, sampleRate: 48_000 });
|
|
133
|
+
return {
|
|
134
|
+
loudnessMeasured: true,
|
|
135
|
+
...(Number.isFinite(measured.lufs) ? { loudnessLufs: measured.lufs } : {}),
|
|
136
|
+
truePeakDb: measured.truePeakDb
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
102
143
|
export function addAsset(options) {
|
|
103
144
|
const projectDir = resolve(options.projectDir ?? process.cwd());
|
|
104
145
|
const sourcePath = resolve(projectDir, options.file);
|
|
@@ -170,6 +211,29 @@ export function addAsset(options) {
|
|
|
170
211
|
...(options.suitabilityReason ?? existing?.suitabilityReason ? { suitabilityReason: options.suitabilityReason ?? existing?.suitabilityReason } : {}),
|
|
171
212
|
...(options.renderedProbe ?? existing?.renderedProbe ? { renderedProbe: options.renderedProbe ?? existing?.renderedProbe } : {}),
|
|
172
213
|
...(options.gameGeometry ?? existing?.gameGeometry ? { gameGeometry: options.gameGeometry ?? existing?.gameGeometry } : {}),
|
|
214
|
+
...(options.artDirection ?? existing?.artDirection ? { artDirection: options.artDirection ?? existing?.artDirection } : {}),
|
|
215
|
+
/*
|
|
216
|
+
* `#165`/C-25: audio entries carry a measured loudness record — `assets
|
|
217
|
+
* add --type audio` runs BS.1770 itself (ffmpeg decode + measureLoudness),
|
|
218
|
+
* and `--loudness-lufs`/`--true-peak-db` remain manual overrides that win
|
|
219
|
+
* over the measured values.
|
|
220
|
+
*/
|
|
221
|
+
...(type === "audio"
|
|
222
|
+
? (() => {
|
|
223
|
+
const measured = measureAudioLoudness(sourcePath);
|
|
224
|
+
const supplied = options.audio ?? existing?.audio;
|
|
225
|
+
const merged = { ...measured, ...supplied };
|
|
226
|
+
return Object.keys(merged).length > 0 ? { audio: merged } : {};
|
|
227
|
+
})()
|
|
228
|
+
: options.audio ?? existing?.audio
|
|
229
|
+
? { audio: options.audio ?? existing?.audio }
|
|
230
|
+
: {}),
|
|
231
|
+
// C-17 clip objects: written only when the inspection produced real
|
|
232
|
+
// durations (the lane-06 inspector hook, Q-05-1); a prior richer record is
|
|
233
|
+
// preserved on re-add.
|
|
234
|
+
...(c17AnimationClips(inspection.animation) ?? existing?.animationClips
|
|
235
|
+
? { animationClips: c17AnimationClips(inspection.animation) ?? existing?.animationClips }
|
|
236
|
+
: {}),
|
|
173
237
|
warnings: createAssetWarnings(sourcePath, inspection)
|
|
174
238
|
};
|
|
175
239
|
if (options.orientation) {
|
|
@@ -182,7 +246,9 @@ export function addAsset(options) {
|
|
|
182
246
|
}
|
|
183
247
|
}
|
|
184
248
|
const manifest = sortManifest({
|
|
185
|
-
|
|
249
|
+
// C-17 stub rule: the stored schema is preserved/1.0 until the writer
|
|
250
|
+
// upgrades under A3D_QR_ASSETS (`writeAssetManifest` decides).
|
|
251
|
+
schema: current.schema ?? "aura3d.assets/1.0",
|
|
186
252
|
assetBasePath: publicPath,
|
|
187
253
|
outputDir,
|
|
188
254
|
typegen,
|
|
@@ -634,6 +700,7 @@ export function inspectAsset(options) {
|
|
|
634
700
|
file: normalizeRelativePath(relative(projectDir, sourcePath)),
|
|
635
701
|
format,
|
|
636
702
|
sizeBytes: statSync(sourcePath).size,
|
|
703
|
+
...(inspection.vertexCount !== undefined ? { vertexCount: inspection.vertexCount } : {}),
|
|
637
704
|
bounds: inspection.bounds,
|
|
638
705
|
boundsMetadata: inspection.boundsMetadata,
|
|
639
706
|
materials: inspection.materials,
|
|
@@ -691,11 +758,31 @@ export function validateAssets(options = {}) {
|
|
|
691
758
|
}
|
|
692
759
|
if (release)
|
|
693
760
|
warnings.push(...createDurableReleaseProvenanceWarnings(asset, provenance));
|
|
761
|
+
// R-09-1 (lane 09): synthesized audio may not hold `release` unless the id
|
|
762
|
+
// is on the admission allowlist.
|
|
763
|
+
if (release && asset.type === "audio" && isSynthesizedAudioProvenance(provenance) && !AUDIO_SYNTH_RELEASE_ALLOWLIST.includes(asset.id)) {
|
|
764
|
+
warnings.push(`${asset.id}: release audio asset has synthesized provenance without an admission allowlist entry.`);
|
|
765
|
+
}
|
|
766
|
+
// #165 (C-25 sfx provenance, adopted from lane 09's `sfx admit`): a
|
|
767
|
+
// release audio entry requires license + sourceUrl + author + loudness
|
|
768
|
+
// measurements on its `audio` block.
|
|
769
|
+
if (release && asset.type === "audio") {
|
|
770
|
+
const meta = asset.audio;
|
|
771
|
+
const missingAudio = [
|
|
772
|
+
!hasUsableLicenseEvidence(provenance) ? "license" : undefined,
|
|
773
|
+
!(provenance?.sourceUrl || provenance?.sourcePage || meta?.sourceUrl) ? "sourceUrl" : undefined,
|
|
774
|
+
!(provenance?.author || meta?.author) ? "author" : undefined,
|
|
775
|
+
meta?.loudnessLufs === undefined && meta?.loudnessMeasured !== true ? "loudnessLufs" : undefined,
|
|
776
|
+
meta?.truePeakDb === undefined ? "truePeakDb" : undefined,
|
|
777
|
+
].filter(Boolean);
|
|
778
|
+
if (missingAudio.length)
|
|
779
|
+
failures.push(`${asset.id}: release audio missing C-25 provenance fields: ${missingAudio.join(", ")}.`);
|
|
780
|
+
}
|
|
694
781
|
warnings.push(...createDerivedMetadataDriftWarnings(outputPath, asset));
|
|
695
782
|
if (release)
|
|
696
|
-
warnings.push(...createReleaseStructuredQualityWarnings(asset));
|
|
783
|
+
warnings.push(...createReleaseStructuredQualityWarnings(projectDir, asset));
|
|
697
784
|
if (release)
|
|
698
|
-
warnings.push(...createReleaseAssetQualityWarnings(asset));
|
|
785
|
+
warnings.push(...createReleaseAssetQualityWarnings(projectDir, asset));
|
|
699
786
|
if (release)
|
|
700
787
|
warnings.push(...createReleaseRenderedProbeWarnings(projectDir, manifest, asset));
|
|
701
788
|
if (release)
|
|
@@ -707,7 +794,7 @@ export function validateAssets(options = {}) {
|
|
|
707
794
|
const tempProvenance = createTempProvenanceWarning(asset, provenance);
|
|
708
795
|
if (tempProvenance)
|
|
709
796
|
warnings.push(tempProvenance);
|
|
710
|
-
const storedWarnings = release ? releaseStoredAssetWarnings(asset) : asset.warnings ?? [];
|
|
797
|
+
const storedWarnings = release ? releaseStoredAssetWarnings(projectDir, asset) : asset.warnings ?? [];
|
|
711
798
|
warnings.push(...storedWarnings.map((warning) => `${asset.id}: ${warning}`));
|
|
712
799
|
if (asset.format === "gltf") {
|
|
713
800
|
for (const dependency of asset.dependencies ?? asset.textures) {
|
|
@@ -781,7 +868,9 @@ export function checkDeploy(options = {}) {
|
|
|
781
868
|
const distDir = normalizeRelativePath(options.distDir ?? "dist");
|
|
782
869
|
const failures = [];
|
|
783
870
|
const warnings = [];
|
|
871
|
+
const referencedServed = new Set();
|
|
784
872
|
for (const asset of manifest.assets) {
|
|
873
|
+
referencedServed.add(normalizeServedUrl(asset.url));
|
|
785
874
|
const distPath = resolve(projectDir, distDir, asset.url.replace(/^\//, ""));
|
|
786
875
|
const publicPath = resolve(projectDir, asset.outputPath);
|
|
787
876
|
if (!existsSync(distPath) && !existsSync(publicPath)) {
|
|
@@ -789,6 +878,41 @@ export function checkDeploy(options = {}) {
|
|
|
789
878
|
}
|
|
790
879
|
if (!/[a-f0-9]{8}\.[^.]+$/i.test(asset.url))
|
|
791
880
|
warnings.push(`${asset.id}: URL is not fingerprinted: ${asset.url}`);
|
|
881
|
+
// §6.8: copy referenced derived files (url/mobile/collision) into the dist
|
|
882
|
+
// tree so a deploy ships exactly what the manifest points at.
|
|
883
|
+
const derived = asset.derived;
|
|
884
|
+
if (derived) {
|
|
885
|
+
for (const served of [derived.url, derived.mobileUrl, derived.collisionUrl]) {
|
|
886
|
+
if (!served)
|
|
887
|
+
continue;
|
|
888
|
+
referencedServed.add(normalizeServedUrl(served));
|
|
889
|
+
const target = resolve(projectDir, distDir, served.replace(/^\//, ""));
|
|
890
|
+
const derivedOutput = served === derived.url && derived.outputPath
|
|
891
|
+
? derived.outputPath
|
|
892
|
+
: join(dirname(derived.outputPath ?? join("public", manifest.assetBasePath)), served.split("/").pop() ?? served);
|
|
893
|
+
const source = resolve(projectDir, derivedOutput);
|
|
894
|
+
if (!existsSync(source)) {
|
|
895
|
+
failures.push(`Deploy check missing derived asset for "${asset.id}": expected ${derivedOutput} (url ${served})`);
|
|
896
|
+
continue;
|
|
897
|
+
}
|
|
898
|
+
if (!existsSync(target) || !sameBytes(source, target)) {
|
|
899
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
900
|
+
copyFileSync(source, target);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
// §6.8: schema 1.1 manifests make the deploy subset exact — a file in
|
|
906
|
+
// <dist>/<assetBasePath> that no manifest entry references fails the check.
|
|
907
|
+
if (manifest.schema === "aura3d.assets/1.1") {
|
|
908
|
+
const base = manifest.assetBasePath.replace(/\/$/, "");
|
|
909
|
+
const servedRoot = resolve(projectDir, distDir, base.replace(/^\//, ""));
|
|
910
|
+
for (const file of walkFilesUnder(servedRoot)) {
|
|
911
|
+
const asServed = normalizeServedUrl(`${base}${file.slice(servedRoot.length).split(sep).join("/")}`);
|
|
912
|
+
if (!referencedServed.has(asServed)) {
|
|
913
|
+
failures.push(`Deploy check found unreferenced file in ${distDir}: ${file.slice(projectDir.length + 1)}`);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
792
916
|
}
|
|
793
917
|
const validation = validateAssets({
|
|
794
918
|
projectDir,
|
|
@@ -905,20 +1029,27 @@ export function createCharacterAssemblyPlan(options) {
|
|
|
905
1029
|
};
|
|
906
1030
|
}
|
|
907
1031
|
export function initAgentFiles(options) {
|
|
1032
|
+
return initAgentSetup(options).written;
|
|
1033
|
+
}
|
|
1034
|
+
export function initAgentSetup(options) {
|
|
908
1035
|
const projectDir = resolve(options.projectDir ?? process.cwd());
|
|
909
1036
|
const targets = options.agent === "all" ? ["generic", "claude", "cursor", "copilot"] : [options.agent];
|
|
910
1037
|
const written = [];
|
|
1038
|
+
const mode = options.skills ?? "core";
|
|
911
1039
|
for (const target of targets) {
|
|
912
1040
|
if (target === "generic")
|
|
913
|
-
written.push(writeAgentFile(projectDir, "AGENTS.md", genericAgentText()));
|
|
1041
|
+
written.push(writeAgentFile(projectDir, "AGENTS.md", genericAgentText("AI coding agent", mode !== "none" ? ".agents/skills" : undefined)));
|
|
914
1042
|
if (target === "claude")
|
|
915
|
-
written.push(writeAgentFile(projectDir, ".claude/CLAUDE.md", genericAgentText("Claude")));
|
|
1043
|
+
written.push(writeAgentFile(projectDir, ".claude/CLAUDE.md", genericAgentText("Claude", mode !== "none" ? ".claude/skills" : undefined)));
|
|
916
1044
|
if (target === "cursor")
|
|
917
|
-
written.push(writeAgentFile(projectDir, ".cursor/rules/aura3d.mdc", genericAgentText("Cursor")));
|
|
1045
|
+
written.push(writeAgentFile(projectDir, ".cursor/rules/aura3d.mdc", genericAgentText("Cursor", mode !== "none" ? ".cursor/skills" : undefined)));
|
|
918
1046
|
if (target === "copilot")
|
|
919
|
-
written.push(writeAgentFile(projectDir, ".github/copilot-instructions.md", genericAgentText("GitHub Copilot")));
|
|
1047
|
+
written.push(writeAgentFile(projectDir, ".github/copilot-instructions.md", genericAgentText("GitHub Copilot", mode !== "none" ? ".github/skills" : undefined)));
|
|
920
1048
|
}
|
|
921
|
-
|
|
1049
|
+
if (mode === "none")
|
|
1050
|
+
return { written, skills: [], skippedUserModified: [] };
|
|
1051
|
+
const result = writeAgentSkills({ projectDir, agent: options.agent, skills: mode, template: options.template, skillsDir: options.skillsDir });
|
|
1052
|
+
return { written: [...written, ...result.written], skills: result.skills, skippedUserModified: result.skippedUserModified };
|
|
922
1053
|
}
|
|
923
1054
|
function validateAssetReadiness(profile, options) {
|
|
924
1055
|
const projectDir = resolve(options.projectDir ?? process.cwd());
|
|
@@ -1758,9 +1889,21 @@ function inspectGlb(buffer, baseDir) {
|
|
|
1758
1889
|
if (chunkType !== "JSON")
|
|
1759
1890
|
throw new Error("Invalid GLB JSON chunk. Suggested fix: re-export the GLB.");
|
|
1760
1891
|
const json = JSON.parse(buffer.toString("utf8", 20, 20 + chunkLength).trim());
|
|
1761
|
-
|
|
1892
|
+
// Q-05-1 (lane 06): carry the BIN chunk through so the enriched clip
|
|
1893
|
+
// inspector can read sampler input times (duration/frameRate).
|
|
1894
|
+
let offset = 20 + chunkLength;
|
|
1895
|
+
let bin;
|
|
1896
|
+
while (offset + 8 <= buffer.length && offset + 8 <= length) {
|
|
1897
|
+
const chunkLen = buffer.readUInt32LE(offset);
|
|
1898
|
+
if (buffer.readUInt32LE(offset + 4) === 0x004e4942) {
|
|
1899
|
+
bin = buffer.subarray(offset + 8, offset + 8 + chunkLen);
|
|
1900
|
+
break;
|
|
1901
|
+
}
|
|
1902
|
+
offset += 8 + chunkLen;
|
|
1903
|
+
}
|
|
1904
|
+
return inspectGltf(json, baseDir, bin);
|
|
1762
1905
|
}
|
|
1763
|
-
function inspectGltf(json, baseDir) {
|
|
1906
|
+
function inspectGltf(json, baseDir, bin) {
|
|
1764
1907
|
const dependencies = [
|
|
1765
1908
|
...(json.images ?? []).map((image) => image.uri).filter(isExternalUri),
|
|
1766
1909
|
...(json.buffers ?? []).map((buffer) => buffer.uri).filter(isExternalUri)
|
|
@@ -1772,13 +1915,15 @@ function inspectGltf(json, baseDir) {
|
|
|
1772
1915
|
}
|
|
1773
1916
|
}
|
|
1774
1917
|
const boundsMetadata = extractBoundsDetails(json);
|
|
1918
|
+
const vertexCount = positionAccessors(json).reduce((sum, accessor) => sum + (typeof accessor.count === "number" && Number.isFinite(accessor.count) ? accessor.count : 0), 0);
|
|
1775
1919
|
return {
|
|
1920
|
+
vertexCount,
|
|
1776
1921
|
bounds: boundsMetadata?.size,
|
|
1777
1922
|
boundsMetadata,
|
|
1778
1923
|
materials: (json.materials ?? []).map((material, index) => material.name ?? `material-${index}`),
|
|
1779
1924
|
materialMetadata: inspectGltfMaterials(json),
|
|
1780
1925
|
animations: (json.animations ?? []).map((animation, index) => animation.name ?? `clip-${index}`),
|
|
1781
|
-
animation: inspectGltfAnimations(json),
|
|
1926
|
+
animation: inspectGltfAnimations(json, bin),
|
|
1782
1927
|
humanoid: inspectGltfHumanoid(json),
|
|
1783
1928
|
skeleton: inspectGltfSkeleton(json),
|
|
1784
1929
|
morphTargets: inspectGltfMorphTargets(json),
|
|
@@ -1797,7 +1942,33 @@ function emptyAnimationInspection() {
|
|
|
1797
1942
|
messages: ["No embedded animation clips detected."]
|
|
1798
1943
|
};
|
|
1799
1944
|
}
|
|
1800
|
-
|
|
1945
|
+
let lane06ClipInspector;
|
|
1946
|
+
function inspectLane06AnimationClips(json, bin) {
|
|
1947
|
+
if (lane06ClipInspector === undefined) {
|
|
1948
|
+
lane06ClipInspector = null;
|
|
1949
|
+
try {
|
|
1950
|
+
const require = createRequire(import.meta.url);
|
|
1951
|
+
const mod = require("./commands/prd06/inspectAnimationClips.js");
|
|
1952
|
+
if (typeof mod?.inspectAnimationClips === "function") {
|
|
1953
|
+
lane06ClipInspector = mod.inspectAnimationClips;
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
catch {
|
|
1957
|
+
lane06ClipInspector = null;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
if (!lane06ClipInspector)
|
|
1961
|
+
return undefined;
|
|
1962
|
+
try {
|
|
1963
|
+
const result = lane06ClipInspector(json, bin);
|
|
1964
|
+
return Array.isArray(result) ? result : undefined;
|
|
1965
|
+
}
|
|
1966
|
+
catch {
|
|
1967
|
+
return undefined;
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
function inspectGltfAnimations(json, bin) {
|
|
1971
|
+
const lane06Clips = inspectLane06AnimationClips(json, bin);
|
|
1801
1972
|
const clips = (json.animations ?? []).map((animation, index) => {
|
|
1802
1973
|
const channels = animation.channels ?? [];
|
|
1803
1974
|
const targetPaths = uniqueStrings(channels.map((channel) => channel.target?.path).filter(isString));
|
|
@@ -1805,13 +1976,18 @@ function inspectGltfAnimations(json) {
|
|
|
1805
1976
|
const nodeIndex = channel.target?.node;
|
|
1806
1977
|
return typeof nodeIndex === "number" ? json.nodes?.[nodeIndex]?.name ?? `node-${nodeIndex}` : undefined;
|
|
1807
1978
|
}).filter(isString));
|
|
1979
|
+
const name = animation.name ?? `clip-${index}`;
|
|
1980
|
+
const enriched = lane06Clips?.find((clip) => clip.index === index || clip.name === name);
|
|
1808
1981
|
return {
|
|
1809
1982
|
index,
|
|
1810
|
-
name
|
|
1983
|
+
name,
|
|
1811
1984
|
channelCount: channels.length,
|
|
1812
1985
|
samplerCount: animation.samplers?.length ?? 0,
|
|
1813
1986
|
targetPaths,
|
|
1814
|
-
targetNodes
|
|
1987
|
+
targetNodes,
|
|
1988
|
+
...(typeof enriched?.duration === "number" ? { duration: enriched.duration } : {}),
|
|
1989
|
+
...(typeof enriched?.hasRootMotionCandidate === "boolean" ? { hasRootMotionCandidate: enriched.hasRootMotionCandidate } : {}),
|
|
1990
|
+
...(typeof enriched?.frameRate === "number" ? { frameRate: enriched.frameRate } : {})
|
|
1815
1991
|
};
|
|
1816
1992
|
});
|
|
1817
1993
|
return {
|
|
@@ -1822,6 +1998,18 @@ function inspectGltfAnimations(json) {
|
|
|
1822
1998
|
: [`Detected ${clips.length} embedded animation clip${clips.length === 1 ? "" : "s"}.`]
|
|
1823
1999
|
};
|
|
1824
2000
|
}
|
|
2001
|
+
/**
|
|
2002
|
+
* C-17 `animationClips` manifest objects (Q-05-1). Emitted only when every
|
|
2003
|
+
* clip carries a real duration from the lane-06 inspector — the names-only
|
|
2004
|
+
* Phase-0 inspection does not fabricate `duration: 0`.
|
|
2005
|
+
*/
|
|
2006
|
+
function c17AnimationClips(inspection) {
|
|
2007
|
+
if (inspection.clipCount === 0)
|
|
2008
|
+
return undefined;
|
|
2009
|
+
if (!inspection.clips.every((clip) => typeof clip.duration === "number" && Number.isFinite(clip.duration)))
|
|
2010
|
+
return undefined;
|
|
2011
|
+
return inspection.clips.map((clip) => ({ name: clip.name, duration: clip.duration ?? 0, channelCount: clip.channelCount }));
|
|
2012
|
+
}
|
|
1825
2013
|
function inspectGltfHumanoid(json) {
|
|
1826
2014
|
const skinCount = json.skins?.length ?? 0;
|
|
1827
2015
|
const jointIndexes = uniqueNumbers((json.skins ?? []).flatMap((skin) => skin.joints ?? []));
|
|
@@ -2346,16 +2534,34 @@ function readOptionalForegroundBounds(record, failures) {
|
|
|
2346
2534
|
return undefined;
|
|
2347
2535
|
return { x, y, width, height };
|
|
2348
2536
|
}
|
|
2537
|
+
const GLB_COMPLEXITY_BYTE_LIMIT = 10 * 1024 * 1024;
|
|
2538
|
+
const GLB_COMPLEXITY_VERTEX_LIMIT = 50_000;
|
|
2539
|
+
function createGlbComplexityWarnings(sizeBytes, vertexCount, format) {
|
|
2540
|
+
const warnings = [];
|
|
2541
|
+
if (format === "glb" && sizeBytes > GLB_COMPLEXITY_BYTE_LIMIT) {
|
|
2542
|
+
warnings.push(`asset exceeds 10 MB (${(sizeBytes / (1024 * 1024)).toFixed(2)} MB); simplify meshes with MeshoptSimplifier to <= 20,000 vertices and compress textures to 1024x1024 before route use`);
|
|
2543
|
+
}
|
|
2544
|
+
if ((format === "glb" || format === "gltf") && (vertexCount ?? 0) > GLB_COMPLEXITY_VERTEX_LIMIT) {
|
|
2545
|
+
warnings.push(`asset has ${vertexCount} vertices (> 50,000 limit); simplify meshes with MeshoptSimplifier to <= 20,000 vertices and compress textures to 1024x1024 before route use`);
|
|
2546
|
+
}
|
|
2547
|
+
return warnings;
|
|
2548
|
+
}
|
|
2349
2549
|
function createAssetWarnings(path, inspection) {
|
|
2350
2550
|
const warnings = [];
|
|
2351
2551
|
const size = statSync(path).size;
|
|
2552
|
+
const format = extname(path).slice(1).toLowerCase();
|
|
2553
|
+
warnings.push(...createGlbComplexityWarnings(size, inspection.vertexCount, format));
|
|
2352
2554
|
if (size > 25 * 1024 * 1024)
|
|
2353
2555
|
warnings.push("asset exceeds 25 MB; consider compression before deployment");
|
|
2354
|
-
|
|
2556
|
+
// Bounds are only meaningful on geometry-bearing formats — audio/texture
|
|
2557
|
+
// files can never produce them, so warning (and release-blocking) on them
|
|
2558
|
+
// is noise, matching the format scoping the texture/orientation warnings
|
|
2559
|
+
// below already use.
|
|
2560
|
+
if (!inspection.bounds && ["glb", "gltf"].includes(format))
|
|
2355
2561
|
warnings.push("bounds could not be extracted");
|
|
2356
|
-
if (inspection.textures.length === 0 && ["glb", "gltf"].includes(
|
|
2562
|
+
if (inspection.textures.length === 0 && ["glb", "gltf"].includes(format))
|
|
2357
2563
|
warnings.push("no texture references detected");
|
|
2358
|
-
if (inspection.orientation.source === "unknown" && ["glb", "gltf"].includes(
|
|
2564
|
+
if (inspection.orientation.source === "unknown" && ["glb", "gltf"].includes(format))
|
|
2359
2565
|
warnings.push("orientation metadata missing; facing direction cannot be validated until GLTF extras declare aura3d.orientation.forwardAxis");
|
|
2360
2566
|
if (inspection.materialMetadata.some((material) => !material.visible || !material.readable))
|
|
2361
2567
|
warnings.push("one or more materials are invisible or unreadable");
|
|
@@ -2641,9 +2847,16 @@ function createDerivedMetadataDriftWarnings(outputPath, asset) {
|
|
|
2641
2847
|
}
|
|
2642
2848
|
}
|
|
2643
2849
|
}
|
|
2850
|
+
const existingWarnings = new Set(asset.warnings ?? []);
|
|
2851
|
+
const sizeBytes = statSync(outputPath).size;
|
|
2852
|
+
for (const complexityWarning of createGlbComplexityWarnings(sizeBytes, inspection.vertexCount, asset.format)) {
|
|
2853
|
+
if (!existingWarnings.has(complexityWarning)) {
|
|
2854
|
+
warnings.push(`${asset.id}: ${complexityWarning}`);
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2644
2857
|
return warnings;
|
|
2645
2858
|
}
|
|
2646
|
-
function createReleaseStructuredQualityWarnings(asset) {
|
|
2859
|
+
function createReleaseStructuredQualityWarnings(projectDir, asset) {
|
|
2647
2860
|
if (asset.type !== "model")
|
|
2648
2861
|
return [];
|
|
2649
2862
|
const warnings = [];
|
|
@@ -2663,7 +2876,7 @@ function createReleaseStructuredQualityWarnings(asset) {
|
|
|
2663
2876
|
}
|
|
2664
2877
|
return warnings;
|
|
2665
2878
|
}
|
|
2666
|
-
function createReleaseAssetQualityWarnings(asset) {
|
|
2879
|
+
function createReleaseAssetQualityWarnings(projectDir, asset) {
|
|
2667
2880
|
if (asset.type !== "model")
|
|
2668
2881
|
return [];
|
|
2669
2882
|
const warnings = [];
|
|
@@ -2688,8 +2901,17 @@ function createReleaseAssetQualityWarnings(asset) {
|
|
|
2688
2901
|
if (asset.materialMetadata?.some((material) => !material.visible || !material.readable)) {
|
|
2689
2902
|
warnings.push(`${asset.id}: release primary model has invisible or unreadable material metadata.`);
|
|
2690
2903
|
}
|
|
2691
|
-
if (["glb", "gltf"].includes(asset.format) && asset.textures.length === 0
|
|
2692
|
-
|
|
2904
|
+
if (["glb", "gltf"].includes(asset.format) && asset.textures.length === 0) {
|
|
2905
|
+
// PRD-05 Phase 0: the hash-bound flat-color evidence waiver is deleted.
|
|
2906
|
+
// The check fails unless the role's profile does not require PBR coverage
|
|
2907
|
+
// (G3 waived-by-role) or `artDirection` resolves to a `stylized-flat`
|
|
2908
|
+
// document with an approved look-dev record (G10).
|
|
2909
|
+
const role = asset.role ?? "unknown";
|
|
2910
|
+
const size = asset.boundsMetadata?.size ?? asset.bounds;
|
|
2911
|
+
const profile = profileForRole(role, size);
|
|
2912
|
+
if (requiresPbrTextures(role, profile) && !hasStylizedFlatApproval(projectDir, asset)) {
|
|
2913
|
+
warnings.push(`${asset.id}: release primary model has no texture references; admit through assets admit (G3) or declare a stylized-flat artDirection with an approved look-dev record.`);
|
|
2914
|
+
}
|
|
2693
2915
|
}
|
|
2694
2916
|
return warnings;
|
|
2695
2917
|
}
|
|
@@ -2846,32 +3068,18 @@ function hasValidManifestOrientationOverride(asset) {
|
|
|
2846
3068
|
return createManifestOrientationOverrideWarnings(asset).length === 0 &&
|
|
2847
3069
|
asset.orientation?.source === "manifest-override";
|
|
2848
3070
|
}
|
|
2849
|
-
function releaseStoredAssetWarnings(asset) {
|
|
3071
|
+
function releaseStoredAssetWarnings(projectDir, asset) {
|
|
2850
3072
|
let warnings = asset.warnings ?? [];
|
|
2851
3073
|
if (hasValidManifestOrientationOverride(asset)) {
|
|
2852
3074
|
warnings = warnings.filter((warning) => !/orientation metadata missing; facing direction cannot be validated/i.test(warning));
|
|
2853
3075
|
}
|
|
2854
|
-
|
|
3076
|
+
// G10: an approved stylized-flat artDirection + look-dev record sanctions
|
|
3077
|
+
// the absence of textures — the stored no-texture warning stops blocking.
|
|
3078
|
+
if (hasStylizedFlatApproval(projectDir, asset)) {
|
|
2855
3079
|
warnings = warnings.filter((warning) => !/^no texture references detected$/i.test(warning.trim()));
|
|
2856
3080
|
}
|
|
2857
3081
|
return warnings;
|
|
2858
3082
|
}
|
|
2859
|
-
function hasHashBoundFlatColorMaterialEvidence(asset) {
|
|
2860
|
-
if (asset.materials.length === 0)
|
|
2861
|
-
return false;
|
|
2862
|
-
const materialMetadata = asset.materialMetadata ?? [];
|
|
2863
|
-
if (materialMetadata.length < asset.materials.length)
|
|
2864
|
-
return false;
|
|
2865
|
-
if (materialMetadata.some((material) => !nonEmpty(material.name) || material.visible !== true || material.readable !== true ||
|
|
2866
|
-
typeof material.opacity !== "number" || material.opacity <= 0))
|
|
2867
|
-
return false;
|
|
2868
|
-
const probe = asset.renderedProbe;
|
|
2869
|
-
return nonEmpty(probe?.url) &&
|
|
2870
|
-
nonEmpty(probe?.sha256) &&
|
|
2871
|
-
nonEmpty(probe?.assetHash) &&
|
|
2872
|
-
probe?.assetHash === asset.hash &&
|
|
2873
|
-
["browser-screenshot", "aura-probe-render"].includes(String(probe?.kind));
|
|
2874
|
-
}
|
|
2875
3083
|
function createRenderedProbeForegroundWarnings(assetId, foregroundBounds, probeMetrics) {
|
|
2876
3084
|
if (!foregroundBounds)
|
|
2877
3085
|
return [];
|
|
@@ -2900,7 +3108,6 @@ function createRenderedProbeForegroundWarnings(assetId, foregroundBounds, probeM
|
|
|
2900
3108
|
return warnings;
|
|
2901
3109
|
}
|
|
2902
3110
|
function createRoleAwareReleaseQualityWarnings(projectDir, manifest, asset) {
|
|
2903
|
-
void projectDir;
|
|
2904
3111
|
void manifest;
|
|
2905
3112
|
if (asset.type !== "model" || asset.quality !== "release")
|
|
2906
3113
|
return [];
|
|
@@ -2909,6 +3116,7 @@ function createRoleAwareReleaseQualityWarnings(projectDir, manifest, asset) {
|
|
|
2909
3116
|
const suitabilityReason = asset.suitabilityReason?.trim() ?? "";
|
|
2910
3117
|
const size = asset.boundsMetadata?.size ?? asset.bounds;
|
|
2911
3118
|
const dimensions = createRoleAwareDimensions(size);
|
|
3119
|
+
const profile = profileForRole(role, dimensions);
|
|
2912
3120
|
const hasMaterialEvidence = asset.materials.length > 0 && !(asset.materialMetadata?.every((material) => !material.visible || !material.readable) ?? false);
|
|
2913
3121
|
const hasTextureEvidence = asset.textures.length > 0 || (asset.hierarchy?.textureCount ?? 0) > 0;
|
|
2914
3122
|
if (role === "unknown") {
|
|
@@ -2941,8 +3149,13 @@ function createRoleAwareReleaseQualityWarnings(projectDir, manifest, asset) {
|
|
|
2941
3149
|
if (requiresMaterialEvidence(role) && !hasMaterialEvidence) {
|
|
2942
3150
|
warnings.push(`${asset.id}: role-aware release ${role} validation requires readable material evidence.`);
|
|
2943
3151
|
}
|
|
2944
|
-
|
|
2945
|
-
|
|
3152
|
+
// PRD-05 Phase 0: `requiresTextureEvidence` (the stylized-suitabilityReason
|
|
3153
|
+
// regex waiver) is deleted — texture requirements now come from the §6.2
|
|
3154
|
+
// role profile, matching G3. An approved stylized-flat artDirection + look-dev
|
|
3155
|
+
// record is the only remaining exemption (G10).
|
|
3156
|
+
const stylizedFlatApproved = hasStylizedFlatApproval(projectDir, asset);
|
|
3157
|
+
if (requiresPbrTextures(role, profile) && !hasTextureEvidence && !stylizedFlatApproved) {
|
|
3158
|
+
warnings.push(`${asset.id}: role-aware release ${role} validation requires texture evidence.`);
|
|
2946
3159
|
}
|
|
2947
3160
|
if (requiresForwardOrientation(role) && !hasForwardOrientationEvidence(asset, suitabilityReason)) {
|
|
2948
3161
|
warnings.push(`${asset.id}: role-aware release ${role} validation requires orientation/forward-axis evidence.`);
|
|
@@ -3066,14 +3279,6 @@ function hasRoleAwareSuitabilityReason(role, suitabilityReason) {
|
|
|
3066
3279
|
function requiresMaterialEvidence(role) {
|
|
3067
3280
|
return role !== "debug" && role !== "abstract";
|
|
3068
3281
|
}
|
|
3069
|
-
function requiresTextureEvidence(role, suitabilityReason) {
|
|
3070
|
-
if (role === "debug" || role === "abstract")
|
|
3071
|
-
return false;
|
|
3072
|
-
if (/\b(stylized|stylised|flat[-\s]?color|flat[-\s]?colour|untextured|procedural material|clay render|solid material)\b/i.test(suitabilityReason)) {
|
|
3073
|
-
return false;
|
|
3074
|
-
}
|
|
3075
|
-
return role === "character" || role === "vehicle" || role === "product" || role === "track" || role === "world" || role === "environment" || role === "weapon";
|
|
3076
|
-
}
|
|
3077
3282
|
function requiresForwardOrientation(role) {
|
|
3078
3283
|
return role === "character" || role === "vehicle" || role === "weapon";
|
|
3079
3284
|
}
|
|
@@ -3324,6 +3529,30 @@ function normalizePublicPath(path) {
|
|
|
3324
3529
|
const withStart = path.startsWith("/") || path.startsWith("http") ? path : `/${path}`;
|
|
3325
3530
|
return withStart.endsWith("/") ? withStart : `${withStart}/`;
|
|
3326
3531
|
}
|
|
3532
|
+
function normalizeServedUrl(url) {
|
|
3533
|
+
const withSlash = url.startsWith("/") ? url : `/${url}`;
|
|
3534
|
+
return withSlash.replace(/\/+/g, "/");
|
|
3535
|
+
}
|
|
3536
|
+
function sameBytes(a, b) {
|
|
3537
|
+
const as = statSync(a);
|
|
3538
|
+
const bs = statSync(b);
|
|
3539
|
+
return as.size === bs.size && readFileSync(a).equals(readFileSync(b));
|
|
3540
|
+
}
|
|
3541
|
+
function* walkFilesUnder(dir) {
|
|
3542
|
+
if (!existsSync(dir))
|
|
3543
|
+
return;
|
|
3544
|
+
const stack = [dir];
|
|
3545
|
+
while (stack.length > 0) {
|
|
3546
|
+
const current = stack.pop();
|
|
3547
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
3548
|
+
const path = join(current, entry.name);
|
|
3549
|
+
if (entry.isDirectory())
|
|
3550
|
+
stack.push(path);
|
|
3551
|
+
else if (entry.isFile())
|
|
3552
|
+
yield path;
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3327
3556
|
function normalizeRelativePath(path) {
|
|
3328
3557
|
return path.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
3329
3558
|
}
|
|
@@ -3339,29 +3568,24 @@ function writeAgentFile(projectDir, path, contents) {
|
|
|
3339
3568
|
writeFileSync(output, contents);
|
|
3340
3569
|
return output;
|
|
3341
3570
|
}
|
|
3342
|
-
function genericAgentText(agent = "AI coding agent") {
|
|
3571
|
+
function genericAgentText(agent = "AI coding agent", skillsPath) {
|
|
3572
|
+
const skillsLine = skillsPath
|
|
3573
|
+
? `Load the Aura3D skills in ./${skillsPath}/ on demand. Start with aura3d-core; it routes to the task skill (scene authoring, assets, evidence review, games, animation, migration, materials, performance).\n`
|
|
3574
|
+
: "";
|
|
3575
|
+
// Q-05-1 (#242): the body is the canonical agent file shipped in
|
|
3576
|
+
// skills/agent-files/AGENTS.md (PRD-13 T2.15), not a copy — scaffolded
|
|
3577
|
+
// files can never drift from it again. Its own `# ` title line is dropped;
|
|
3578
|
+
// the per-agent prelude keeps the heading + skills path.
|
|
3579
|
+
// Both src/index.ts (tsx) and dist/index.js sit one level below the package
|
|
3580
|
+
// root, whose published `files` include `skills/`.
|
|
3581
|
+
const canonicalPath = resolve(fileURLToPath(import.meta.url), "..", "..", "skills", "agent-files", "AGENTS.md");
|
|
3582
|
+
if (!existsSync(canonicalPath)) {
|
|
3583
|
+
throw new Error(`canonical agent file not found at ${canonicalPath}`);
|
|
3584
|
+
}
|
|
3585
|
+
const canonical = readFileSync(canonicalPath, "utf8").replace(/^#[^\n]*\n+/, "").trimEnd();
|
|
3343
3586
|
return `# Aura3D Instructions For ${agent}
|
|
3344
3587
|
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
Use @aura3d/engine public imports only:
|
|
3348
|
-
- createAuraApp
|
|
3349
|
-
- scene
|
|
3350
|
-
- model
|
|
3351
|
-
- camera
|
|
3352
|
-
- lights
|
|
3353
|
-
- material
|
|
3354
|
-
- effects
|
|
3355
|
-
- timeline
|
|
3356
|
-
- interactions
|
|
3357
|
-
- defineAuraAssets
|
|
3358
|
-
|
|
3359
|
-
Do not invent asset paths or asset ids. Read ./src/aura-assets.ts after running:
|
|
3360
|
-
|
|
3361
|
-
npx @aura3d/cli@latest assets add ./assets/model.glb --name model
|
|
3362
|
-
|
|
3363
|
-
Use model(assets.model), not model("model").
|
|
3364
|
-
Run npm run build and the template route-health/screenshot tests before claiming the scene is done.
|
|
3588
|
+
${skillsLine}${canonical}
|
|
3365
3589
|
`;
|
|
3366
3590
|
}
|
|
3367
3591
|
function escapeXml(value) {
|