@aura3d/cli 3.0.1 → 4.0.0
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 +2 -2
- 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 +99 -4
- package/dist/asset-core-types.d.ts.map +1 -1
- package/dist/asset-inspection-types.d.ts +8 -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 +13 -4
- 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 +271 -71
- 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/import.d.ts +7 -1
- package/dist/meshy/import.d.ts.map +1 -1
- package/dist/meshy/import.js +80 -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 +132 -0
- package/skills/aura3d-assets/references/preview-under-look.md +26 -0
- package/skills/aura3d-browser-game/SKILL.md +127 -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 +121 -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 +117 -0
- package/skills/manifest.json +163 -0
- package/skills/meshy-cli/SKILL.md +133 -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,
|
|
@@ -691,11 +757,31 @@ export function validateAssets(options = {}) {
|
|
|
691
757
|
}
|
|
692
758
|
if (release)
|
|
693
759
|
warnings.push(...createDurableReleaseProvenanceWarnings(asset, provenance));
|
|
760
|
+
// R-09-1 (lane 09): synthesized audio may not hold `release` unless the id
|
|
761
|
+
// is on the admission allowlist.
|
|
762
|
+
if (release && asset.type === "audio" && isSynthesizedAudioProvenance(provenance) && !AUDIO_SYNTH_RELEASE_ALLOWLIST.includes(asset.id)) {
|
|
763
|
+
warnings.push(`${asset.id}: release audio asset has synthesized provenance without an admission allowlist entry.`);
|
|
764
|
+
}
|
|
765
|
+
// #165 (C-25 sfx provenance, adopted from lane 09's `sfx admit`): a
|
|
766
|
+
// release audio entry requires license + sourceUrl + author + loudness
|
|
767
|
+
// measurements on its `audio` block.
|
|
768
|
+
if (release && asset.type === "audio") {
|
|
769
|
+
const meta = asset.audio;
|
|
770
|
+
const missingAudio = [
|
|
771
|
+
!hasUsableLicenseEvidence(provenance) ? "license" : undefined,
|
|
772
|
+
!(provenance?.sourceUrl || provenance?.sourcePage || meta?.sourceUrl) ? "sourceUrl" : undefined,
|
|
773
|
+
!(provenance?.author || meta?.author) ? "author" : undefined,
|
|
774
|
+
meta?.loudnessLufs === undefined && meta?.loudnessMeasured !== true ? "loudnessLufs" : undefined,
|
|
775
|
+
meta?.truePeakDb === undefined ? "truePeakDb" : undefined,
|
|
776
|
+
].filter(Boolean);
|
|
777
|
+
if (missingAudio.length)
|
|
778
|
+
failures.push(`${asset.id}: release audio missing C-25 provenance fields: ${missingAudio.join(", ")}.`);
|
|
779
|
+
}
|
|
694
780
|
warnings.push(...createDerivedMetadataDriftWarnings(outputPath, asset));
|
|
695
781
|
if (release)
|
|
696
|
-
warnings.push(...createReleaseStructuredQualityWarnings(asset));
|
|
782
|
+
warnings.push(...createReleaseStructuredQualityWarnings(projectDir, asset));
|
|
697
783
|
if (release)
|
|
698
|
-
warnings.push(...createReleaseAssetQualityWarnings(asset));
|
|
784
|
+
warnings.push(...createReleaseAssetQualityWarnings(projectDir, asset));
|
|
699
785
|
if (release)
|
|
700
786
|
warnings.push(...createReleaseRenderedProbeWarnings(projectDir, manifest, asset));
|
|
701
787
|
if (release)
|
|
@@ -707,7 +793,7 @@ export function validateAssets(options = {}) {
|
|
|
707
793
|
const tempProvenance = createTempProvenanceWarning(asset, provenance);
|
|
708
794
|
if (tempProvenance)
|
|
709
795
|
warnings.push(tempProvenance);
|
|
710
|
-
const storedWarnings = release ? releaseStoredAssetWarnings(asset) : asset.warnings ?? [];
|
|
796
|
+
const storedWarnings = release ? releaseStoredAssetWarnings(projectDir, asset) : asset.warnings ?? [];
|
|
711
797
|
warnings.push(...storedWarnings.map((warning) => `${asset.id}: ${warning}`));
|
|
712
798
|
if (asset.format === "gltf") {
|
|
713
799
|
for (const dependency of asset.dependencies ?? asset.textures) {
|
|
@@ -781,7 +867,9 @@ export function checkDeploy(options = {}) {
|
|
|
781
867
|
const distDir = normalizeRelativePath(options.distDir ?? "dist");
|
|
782
868
|
const failures = [];
|
|
783
869
|
const warnings = [];
|
|
870
|
+
const referencedServed = new Set();
|
|
784
871
|
for (const asset of manifest.assets) {
|
|
872
|
+
referencedServed.add(normalizeServedUrl(asset.url));
|
|
785
873
|
const distPath = resolve(projectDir, distDir, asset.url.replace(/^\//, ""));
|
|
786
874
|
const publicPath = resolve(projectDir, asset.outputPath);
|
|
787
875
|
if (!existsSync(distPath) && !existsSync(publicPath)) {
|
|
@@ -789,6 +877,41 @@ export function checkDeploy(options = {}) {
|
|
|
789
877
|
}
|
|
790
878
|
if (!/[a-f0-9]{8}\.[^.]+$/i.test(asset.url))
|
|
791
879
|
warnings.push(`${asset.id}: URL is not fingerprinted: ${asset.url}`);
|
|
880
|
+
// §6.8: copy referenced derived files (url/mobile/collision) into the dist
|
|
881
|
+
// tree so a deploy ships exactly what the manifest points at.
|
|
882
|
+
const derived = asset.derived;
|
|
883
|
+
if (derived) {
|
|
884
|
+
for (const served of [derived.url, derived.mobileUrl, derived.collisionUrl]) {
|
|
885
|
+
if (!served)
|
|
886
|
+
continue;
|
|
887
|
+
referencedServed.add(normalizeServedUrl(served));
|
|
888
|
+
const target = resolve(projectDir, distDir, served.replace(/^\//, ""));
|
|
889
|
+
const derivedOutput = served === derived.url && derived.outputPath
|
|
890
|
+
? derived.outputPath
|
|
891
|
+
: join(dirname(derived.outputPath ?? join("public", manifest.assetBasePath)), served.split("/").pop() ?? served);
|
|
892
|
+
const source = resolve(projectDir, derivedOutput);
|
|
893
|
+
if (!existsSync(source)) {
|
|
894
|
+
failures.push(`Deploy check missing derived asset for "${asset.id}": expected ${derivedOutput} (url ${served})`);
|
|
895
|
+
continue;
|
|
896
|
+
}
|
|
897
|
+
if (!existsSync(target) || !sameBytes(source, target)) {
|
|
898
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
899
|
+
copyFileSync(source, target);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
// §6.8: schema 1.1 manifests make the deploy subset exact — a file in
|
|
905
|
+
// <dist>/<assetBasePath> that no manifest entry references fails the check.
|
|
906
|
+
if (manifest.schema === "aura3d.assets/1.1") {
|
|
907
|
+
const base = manifest.assetBasePath.replace(/\/$/, "");
|
|
908
|
+
const servedRoot = resolve(projectDir, distDir, base.replace(/^\//, ""));
|
|
909
|
+
for (const file of walkFilesUnder(servedRoot)) {
|
|
910
|
+
const asServed = normalizeServedUrl(`${base}${file.slice(servedRoot.length).split(sep).join("/")}`);
|
|
911
|
+
if (!referencedServed.has(asServed)) {
|
|
912
|
+
failures.push(`Deploy check found unreferenced file in ${distDir}: ${file.slice(projectDir.length + 1)}`);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
792
915
|
}
|
|
793
916
|
const validation = validateAssets({
|
|
794
917
|
projectDir,
|
|
@@ -905,20 +1028,27 @@ export function createCharacterAssemblyPlan(options) {
|
|
|
905
1028
|
};
|
|
906
1029
|
}
|
|
907
1030
|
export function initAgentFiles(options) {
|
|
1031
|
+
return initAgentSetup(options).written;
|
|
1032
|
+
}
|
|
1033
|
+
export function initAgentSetup(options) {
|
|
908
1034
|
const projectDir = resolve(options.projectDir ?? process.cwd());
|
|
909
1035
|
const targets = options.agent === "all" ? ["generic", "claude", "cursor", "copilot"] : [options.agent];
|
|
910
1036
|
const written = [];
|
|
1037
|
+
const mode = options.skills ?? "core";
|
|
911
1038
|
for (const target of targets) {
|
|
912
1039
|
if (target === "generic")
|
|
913
|
-
written.push(writeAgentFile(projectDir, "AGENTS.md", genericAgentText()));
|
|
1040
|
+
written.push(writeAgentFile(projectDir, "AGENTS.md", genericAgentText("AI coding agent", mode !== "none" ? ".agents/skills" : undefined)));
|
|
914
1041
|
if (target === "claude")
|
|
915
|
-
written.push(writeAgentFile(projectDir, ".claude/CLAUDE.md", genericAgentText("Claude")));
|
|
1042
|
+
written.push(writeAgentFile(projectDir, ".claude/CLAUDE.md", genericAgentText("Claude", mode !== "none" ? ".claude/skills" : undefined)));
|
|
916
1043
|
if (target === "cursor")
|
|
917
|
-
written.push(writeAgentFile(projectDir, ".cursor/rules/aura3d.mdc", genericAgentText("Cursor")));
|
|
1044
|
+
written.push(writeAgentFile(projectDir, ".cursor/rules/aura3d.mdc", genericAgentText("Cursor", mode !== "none" ? ".cursor/skills" : undefined)));
|
|
918
1045
|
if (target === "copilot")
|
|
919
|
-
written.push(writeAgentFile(projectDir, ".github/copilot-instructions.md", genericAgentText("GitHub Copilot")));
|
|
1046
|
+
written.push(writeAgentFile(projectDir, ".github/copilot-instructions.md", genericAgentText("GitHub Copilot", mode !== "none" ? ".github/skills" : undefined)));
|
|
920
1047
|
}
|
|
921
|
-
|
|
1048
|
+
if (mode === "none")
|
|
1049
|
+
return { written, skills: [], skippedUserModified: [] };
|
|
1050
|
+
const result = writeAgentSkills({ projectDir, agent: options.agent, skills: mode, template: options.template, skillsDir: options.skillsDir });
|
|
1051
|
+
return { written: [...written, ...result.written], skills: result.skills, skippedUserModified: result.skippedUserModified };
|
|
922
1052
|
}
|
|
923
1053
|
function validateAssetReadiness(profile, options) {
|
|
924
1054
|
const projectDir = resolve(options.projectDir ?? process.cwd());
|
|
@@ -1758,9 +1888,21 @@ function inspectGlb(buffer, baseDir) {
|
|
|
1758
1888
|
if (chunkType !== "JSON")
|
|
1759
1889
|
throw new Error("Invalid GLB JSON chunk. Suggested fix: re-export the GLB.");
|
|
1760
1890
|
const json = JSON.parse(buffer.toString("utf8", 20, 20 + chunkLength).trim());
|
|
1761
|
-
|
|
1891
|
+
// Q-05-1 (lane 06): carry the BIN chunk through so the enriched clip
|
|
1892
|
+
// inspector can read sampler input times (duration/frameRate).
|
|
1893
|
+
let offset = 20 + chunkLength;
|
|
1894
|
+
let bin;
|
|
1895
|
+
while (offset + 8 <= buffer.length && offset + 8 <= length) {
|
|
1896
|
+
const chunkLen = buffer.readUInt32LE(offset);
|
|
1897
|
+
if (buffer.readUInt32LE(offset + 4) === 0x004e4942) {
|
|
1898
|
+
bin = buffer.subarray(offset + 8, offset + 8 + chunkLen);
|
|
1899
|
+
break;
|
|
1900
|
+
}
|
|
1901
|
+
offset += 8 + chunkLen;
|
|
1902
|
+
}
|
|
1903
|
+
return inspectGltf(json, baseDir, bin);
|
|
1762
1904
|
}
|
|
1763
|
-
function inspectGltf(json, baseDir) {
|
|
1905
|
+
function inspectGltf(json, baseDir, bin) {
|
|
1764
1906
|
const dependencies = [
|
|
1765
1907
|
...(json.images ?? []).map((image) => image.uri).filter(isExternalUri),
|
|
1766
1908
|
...(json.buffers ?? []).map((buffer) => buffer.uri).filter(isExternalUri)
|
|
@@ -1778,7 +1920,7 @@ function inspectGltf(json, baseDir) {
|
|
|
1778
1920
|
materials: (json.materials ?? []).map((material, index) => material.name ?? `material-${index}`),
|
|
1779
1921
|
materialMetadata: inspectGltfMaterials(json),
|
|
1780
1922
|
animations: (json.animations ?? []).map((animation, index) => animation.name ?? `clip-${index}`),
|
|
1781
|
-
animation: inspectGltfAnimations(json),
|
|
1923
|
+
animation: inspectGltfAnimations(json, bin),
|
|
1782
1924
|
humanoid: inspectGltfHumanoid(json),
|
|
1783
1925
|
skeleton: inspectGltfSkeleton(json),
|
|
1784
1926
|
morphTargets: inspectGltfMorphTargets(json),
|
|
@@ -1797,7 +1939,33 @@ function emptyAnimationInspection() {
|
|
|
1797
1939
|
messages: ["No embedded animation clips detected."]
|
|
1798
1940
|
};
|
|
1799
1941
|
}
|
|
1800
|
-
|
|
1942
|
+
let lane06ClipInspector;
|
|
1943
|
+
function inspectLane06AnimationClips(json, bin) {
|
|
1944
|
+
if (lane06ClipInspector === undefined) {
|
|
1945
|
+
lane06ClipInspector = null;
|
|
1946
|
+
try {
|
|
1947
|
+
const require = createRequire(import.meta.url);
|
|
1948
|
+
const mod = require("./commands/prd06/inspectAnimationClips.js");
|
|
1949
|
+
if (typeof mod?.inspectAnimationClips === "function") {
|
|
1950
|
+
lane06ClipInspector = mod.inspectAnimationClips;
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
catch {
|
|
1954
|
+
lane06ClipInspector = null;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
if (!lane06ClipInspector)
|
|
1958
|
+
return undefined;
|
|
1959
|
+
try {
|
|
1960
|
+
const result = lane06ClipInspector(json, bin);
|
|
1961
|
+
return Array.isArray(result) ? result : undefined;
|
|
1962
|
+
}
|
|
1963
|
+
catch {
|
|
1964
|
+
return undefined;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
function inspectGltfAnimations(json, bin) {
|
|
1968
|
+
const lane06Clips = inspectLane06AnimationClips(json, bin);
|
|
1801
1969
|
const clips = (json.animations ?? []).map((animation, index) => {
|
|
1802
1970
|
const channels = animation.channels ?? [];
|
|
1803
1971
|
const targetPaths = uniqueStrings(channels.map((channel) => channel.target?.path).filter(isString));
|
|
@@ -1805,13 +1973,18 @@ function inspectGltfAnimations(json) {
|
|
|
1805
1973
|
const nodeIndex = channel.target?.node;
|
|
1806
1974
|
return typeof nodeIndex === "number" ? json.nodes?.[nodeIndex]?.name ?? `node-${nodeIndex}` : undefined;
|
|
1807
1975
|
}).filter(isString));
|
|
1976
|
+
const name = animation.name ?? `clip-${index}`;
|
|
1977
|
+
const enriched = lane06Clips?.find((clip) => clip.index === index || clip.name === name);
|
|
1808
1978
|
return {
|
|
1809
1979
|
index,
|
|
1810
|
-
name
|
|
1980
|
+
name,
|
|
1811
1981
|
channelCount: channels.length,
|
|
1812
1982
|
samplerCount: animation.samplers?.length ?? 0,
|
|
1813
1983
|
targetPaths,
|
|
1814
|
-
targetNodes
|
|
1984
|
+
targetNodes,
|
|
1985
|
+
...(typeof enriched?.duration === "number" ? { duration: enriched.duration } : {}),
|
|
1986
|
+
...(typeof enriched?.hasRootMotionCandidate === "boolean" ? { hasRootMotionCandidate: enriched.hasRootMotionCandidate } : {}),
|
|
1987
|
+
...(typeof enriched?.frameRate === "number" ? { frameRate: enriched.frameRate } : {})
|
|
1815
1988
|
};
|
|
1816
1989
|
});
|
|
1817
1990
|
return {
|
|
@@ -1822,6 +1995,18 @@ function inspectGltfAnimations(json) {
|
|
|
1822
1995
|
: [`Detected ${clips.length} embedded animation clip${clips.length === 1 ? "" : "s"}.`]
|
|
1823
1996
|
};
|
|
1824
1997
|
}
|
|
1998
|
+
/**
|
|
1999
|
+
* C-17 `animationClips` manifest objects (Q-05-1). Emitted only when every
|
|
2000
|
+
* clip carries a real duration from the lane-06 inspector — the names-only
|
|
2001
|
+
* Phase-0 inspection does not fabricate `duration: 0`.
|
|
2002
|
+
*/
|
|
2003
|
+
function c17AnimationClips(inspection) {
|
|
2004
|
+
if (inspection.clipCount === 0)
|
|
2005
|
+
return undefined;
|
|
2006
|
+
if (!inspection.clips.every((clip) => typeof clip.duration === "number" && Number.isFinite(clip.duration)))
|
|
2007
|
+
return undefined;
|
|
2008
|
+
return inspection.clips.map((clip) => ({ name: clip.name, duration: clip.duration ?? 0, channelCount: clip.channelCount }));
|
|
2009
|
+
}
|
|
1825
2010
|
function inspectGltfHumanoid(json) {
|
|
1826
2011
|
const skinCount = json.skins?.length ?? 0;
|
|
1827
2012
|
const jointIndexes = uniqueNumbers((json.skins ?? []).flatMap((skin) => skin.joints ?? []));
|
|
@@ -2351,7 +2536,11 @@ function createAssetWarnings(path, inspection) {
|
|
|
2351
2536
|
const size = statSync(path).size;
|
|
2352
2537
|
if (size > 25 * 1024 * 1024)
|
|
2353
2538
|
warnings.push("asset exceeds 25 MB; consider compression before deployment");
|
|
2354
|
-
|
|
2539
|
+
// Bounds are only meaningful on geometry-bearing formats — audio/texture
|
|
2540
|
+
// files can never produce them, so warning (and release-blocking) on them
|
|
2541
|
+
// is noise, matching the format scoping the texture/orientation warnings
|
|
2542
|
+
// below already use.
|
|
2543
|
+
if (!inspection.bounds && ["glb", "gltf"].includes(extname(path).slice(1).toLowerCase()))
|
|
2355
2544
|
warnings.push("bounds could not be extracted");
|
|
2356
2545
|
if (inspection.textures.length === 0 && ["glb", "gltf"].includes(extname(path).slice(1).toLowerCase()))
|
|
2357
2546
|
warnings.push("no texture references detected");
|
|
@@ -2643,7 +2832,7 @@ function createDerivedMetadataDriftWarnings(outputPath, asset) {
|
|
|
2643
2832
|
}
|
|
2644
2833
|
return warnings;
|
|
2645
2834
|
}
|
|
2646
|
-
function createReleaseStructuredQualityWarnings(asset) {
|
|
2835
|
+
function createReleaseStructuredQualityWarnings(projectDir, asset) {
|
|
2647
2836
|
if (asset.type !== "model")
|
|
2648
2837
|
return [];
|
|
2649
2838
|
const warnings = [];
|
|
@@ -2663,7 +2852,7 @@ function createReleaseStructuredQualityWarnings(asset) {
|
|
|
2663
2852
|
}
|
|
2664
2853
|
return warnings;
|
|
2665
2854
|
}
|
|
2666
|
-
function createReleaseAssetQualityWarnings(asset) {
|
|
2855
|
+
function createReleaseAssetQualityWarnings(projectDir, asset) {
|
|
2667
2856
|
if (asset.type !== "model")
|
|
2668
2857
|
return [];
|
|
2669
2858
|
const warnings = [];
|
|
@@ -2688,8 +2877,17 @@ function createReleaseAssetQualityWarnings(asset) {
|
|
|
2688
2877
|
if (asset.materialMetadata?.some((material) => !material.visible || !material.readable)) {
|
|
2689
2878
|
warnings.push(`${asset.id}: release primary model has invisible or unreadable material metadata.`);
|
|
2690
2879
|
}
|
|
2691
|
-
if (["glb", "gltf"].includes(asset.format) && asset.textures.length === 0
|
|
2692
|
-
|
|
2880
|
+
if (["glb", "gltf"].includes(asset.format) && asset.textures.length === 0) {
|
|
2881
|
+
// PRD-05 Phase 0: the hash-bound flat-color evidence waiver is deleted.
|
|
2882
|
+
// The check fails unless the role's profile does not require PBR coverage
|
|
2883
|
+
// (G3 waived-by-role) or `artDirection` resolves to a `stylized-flat`
|
|
2884
|
+
// document with an approved look-dev record (G10).
|
|
2885
|
+
const role = asset.role ?? "unknown";
|
|
2886
|
+
const size = asset.boundsMetadata?.size ?? asset.bounds;
|
|
2887
|
+
const profile = profileForRole(role, size);
|
|
2888
|
+
if (requiresPbrTextures(role, profile) && !hasStylizedFlatApproval(projectDir, asset)) {
|
|
2889
|
+
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.`);
|
|
2890
|
+
}
|
|
2693
2891
|
}
|
|
2694
2892
|
return warnings;
|
|
2695
2893
|
}
|
|
@@ -2846,32 +3044,18 @@ function hasValidManifestOrientationOverride(asset) {
|
|
|
2846
3044
|
return createManifestOrientationOverrideWarnings(asset).length === 0 &&
|
|
2847
3045
|
asset.orientation?.source === "manifest-override";
|
|
2848
3046
|
}
|
|
2849
|
-
function releaseStoredAssetWarnings(asset) {
|
|
3047
|
+
function releaseStoredAssetWarnings(projectDir, asset) {
|
|
2850
3048
|
let warnings = asset.warnings ?? [];
|
|
2851
3049
|
if (hasValidManifestOrientationOverride(asset)) {
|
|
2852
3050
|
warnings = warnings.filter((warning) => !/orientation metadata missing; facing direction cannot be validated/i.test(warning));
|
|
2853
3051
|
}
|
|
2854
|
-
|
|
3052
|
+
// G10: an approved stylized-flat artDirection + look-dev record sanctions
|
|
3053
|
+
// the absence of textures — the stored no-texture warning stops blocking.
|
|
3054
|
+
if (hasStylizedFlatApproval(projectDir, asset)) {
|
|
2855
3055
|
warnings = warnings.filter((warning) => !/^no texture references detected$/i.test(warning.trim()));
|
|
2856
3056
|
}
|
|
2857
3057
|
return warnings;
|
|
2858
3058
|
}
|
|
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
3059
|
function createRenderedProbeForegroundWarnings(assetId, foregroundBounds, probeMetrics) {
|
|
2876
3060
|
if (!foregroundBounds)
|
|
2877
3061
|
return [];
|
|
@@ -2900,7 +3084,6 @@ function createRenderedProbeForegroundWarnings(assetId, foregroundBounds, probeM
|
|
|
2900
3084
|
return warnings;
|
|
2901
3085
|
}
|
|
2902
3086
|
function createRoleAwareReleaseQualityWarnings(projectDir, manifest, asset) {
|
|
2903
|
-
void projectDir;
|
|
2904
3087
|
void manifest;
|
|
2905
3088
|
if (asset.type !== "model" || asset.quality !== "release")
|
|
2906
3089
|
return [];
|
|
@@ -2909,6 +3092,7 @@ function createRoleAwareReleaseQualityWarnings(projectDir, manifest, asset) {
|
|
|
2909
3092
|
const suitabilityReason = asset.suitabilityReason?.trim() ?? "";
|
|
2910
3093
|
const size = asset.boundsMetadata?.size ?? asset.bounds;
|
|
2911
3094
|
const dimensions = createRoleAwareDimensions(size);
|
|
3095
|
+
const profile = profileForRole(role, dimensions);
|
|
2912
3096
|
const hasMaterialEvidence = asset.materials.length > 0 && !(asset.materialMetadata?.every((material) => !material.visible || !material.readable) ?? false);
|
|
2913
3097
|
const hasTextureEvidence = asset.textures.length > 0 || (asset.hierarchy?.textureCount ?? 0) > 0;
|
|
2914
3098
|
if (role === "unknown") {
|
|
@@ -2941,8 +3125,13 @@ function createRoleAwareReleaseQualityWarnings(projectDir, manifest, asset) {
|
|
|
2941
3125
|
if (requiresMaterialEvidence(role) && !hasMaterialEvidence) {
|
|
2942
3126
|
warnings.push(`${asset.id}: role-aware release ${role} validation requires readable material evidence.`);
|
|
2943
3127
|
}
|
|
2944
|
-
|
|
2945
|
-
|
|
3128
|
+
// PRD-05 Phase 0: `requiresTextureEvidence` (the stylized-suitabilityReason
|
|
3129
|
+
// regex waiver) is deleted — texture requirements now come from the §6.2
|
|
3130
|
+
// role profile, matching G3. An approved stylized-flat artDirection + look-dev
|
|
3131
|
+
// record is the only remaining exemption (G10).
|
|
3132
|
+
const stylizedFlatApproved = hasStylizedFlatApproval(projectDir, asset);
|
|
3133
|
+
if (requiresPbrTextures(role, profile) && !hasTextureEvidence && !stylizedFlatApproved) {
|
|
3134
|
+
warnings.push(`${asset.id}: role-aware release ${role} validation requires texture evidence.`);
|
|
2946
3135
|
}
|
|
2947
3136
|
if (requiresForwardOrientation(role) && !hasForwardOrientationEvidence(asset, suitabilityReason)) {
|
|
2948
3137
|
warnings.push(`${asset.id}: role-aware release ${role} validation requires orientation/forward-axis evidence.`);
|
|
@@ -3066,14 +3255,6 @@ function hasRoleAwareSuitabilityReason(role, suitabilityReason) {
|
|
|
3066
3255
|
function requiresMaterialEvidence(role) {
|
|
3067
3256
|
return role !== "debug" && role !== "abstract";
|
|
3068
3257
|
}
|
|
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
3258
|
function requiresForwardOrientation(role) {
|
|
3078
3259
|
return role === "character" || role === "vehicle" || role === "weapon";
|
|
3079
3260
|
}
|
|
@@ -3324,6 +3505,30 @@ function normalizePublicPath(path) {
|
|
|
3324
3505
|
const withStart = path.startsWith("/") || path.startsWith("http") ? path : `/${path}`;
|
|
3325
3506
|
return withStart.endsWith("/") ? withStart : `${withStart}/`;
|
|
3326
3507
|
}
|
|
3508
|
+
function normalizeServedUrl(url) {
|
|
3509
|
+
const withSlash = url.startsWith("/") ? url : `/${url}`;
|
|
3510
|
+
return withSlash.replace(/\/+/g, "/");
|
|
3511
|
+
}
|
|
3512
|
+
function sameBytes(a, b) {
|
|
3513
|
+
const as = statSync(a);
|
|
3514
|
+
const bs = statSync(b);
|
|
3515
|
+
return as.size === bs.size && readFileSync(a).equals(readFileSync(b));
|
|
3516
|
+
}
|
|
3517
|
+
function* walkFilesUnder(dir) {
|
|
3518
|
+
if (!existsSync(dir))
|
|
3519
|
+
return;
|
|
3520
|
+
const stack = [dir];
|
|
3521
|
+
while (stack.length > 0) {
|
|
3522
|
+
const current = stack.pop();
|
|
3523
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
3524
|
+
const path = join(current, entry.name);
|
|
3525
|
+
if (entry.isDirectory())
|
|
3526
|
+
stack.push(path);
|
|
3527
|
+
else if (entry.isFile())
|
|
3528
|
+
yield path;
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3327
3532
|
function normalizeRelativePath(path) {
|
|
3328
3533
|
return path.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
3329
3534
|
}
|
|
@@ -3339,29 +3544,24 @@ function writeAgentFile(projectDir, path, contents) {
|
|
|
3339
3544
|
writeFileSync(output, contents);
|
|
3340
3545
|
return output;
|
|
3341
3546
|
}
|
|
3342
|
-
function genericAgentText(agent = "AI coding agent") {
|
|
3547
|
+
function genericAgentText(agent = "AI coding agent", skillsPath) {
|
|
3548
|
+
const skillsLine = skillsPath
|
|
3549
|
+
? `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`
|
|
3550
|
+
: "";
|
|
3551
|
+
// Q-05-1 (#242): the body is the canonical agent file shipped in
|
|
3552
|
+
// skills/agent-files/AGENTS.md (PRD-13 T2.15), not a copy — scaffolded
|
|
3553
|
+
// files can never drift from it again. Its own `# ` title line is dropped;
|
|
3554
|
+
// the per-agent prelude keeps the heading + skills path.
|
|
3555
|
+
// Both src/index.ts (tsx) and dist/index.js sit one level below the package
|
|
3556
|
+
// root, whose published `files` include `skills/`.
|
|
3557
|
+
const canonicalPath = resolve(fileURLToPath(import.meta.url), "..", "..", "skills", "agent-files", "AGENTS.md");
|
|
3558
|
+
if (!existsSync(canonicalPath)) {
|
|
3559
|
+
throw new Error(`canonical agent file not found at ${canonicalPath}`);
|
|
3560
|
+
}
|
|
3561
|
+
const canonical = readFileSync(canonicalPath, "utf8").replace(/^#[^\n]*\n+/, "").trimEnd();
|
|
3343
3562
|
return `# Aura3D Instructions For ${agent}
|
|
3344
3563
|
|
|
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.
|
|
3564
|
+
${skillsLine}${canonical}
|
|
3365
3565
|
`;
|
|
3366
3566
|
}
|
|
3367
3567
|
function escapeXml(value) {
|