@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.
Files changed (379) hide show
  1. package/README.md +16 -15
  2. package/dist/admission/artDirection.d.ts +28 -0
  3. package/dist/admission/artDirection.d.ts.map +1 -0
  4. package/dist/admission/artDirection.js +47 -0
  5. package/dist/admission/artDirection.js.map +1 -0
  6. package/dist/admission/audio.d.ts +19 -0
  7. package/dist/admission/audio.d.ts.map +1 -0
  8. package/dist/admission/audio.js +31 -0
  9. package/dist/admission/audio.js.map +1 -0
  10. package/dist/admission/builder-patterns.d.ts +25 -0
  11. package/dist/admission/builder-patterns.d.ts.map +1 -0
  12. package/dist/admission/builder-patterns.js +40 -0
  13. package/dist/admission/builder-patterns.js.map +1 -0
  14. package/dist/admission/gates.d.ts +136 -0
  15. package/dist/admission/gates.d.ts.map +1 -0
  16. package/dist/admission/gates.js +335 -0
  17. package/dist/admission/gates.js.map +1 -0
  18. package/dist/admission/glb.d.ts +64 -0
  19. package/dist/admission/glb.d.ts.map +1 -0
  20. package/dist/admission/glb.js +128 -0
  21. package/dist/admission/glb.js.map +1 -0
  22. package/dist/admission/index.d.ts +8 -0
  23. package/dist/admission/index.d.ts.map +1 -0
  24. package/dist/admission/index.js +8 -0
  25. package/dist/admission/index.js.map +1 -0
  26. package/dist/admission/profiles.d.ts +52 -0
  27. package/dist/admission/profiles.d.ts.map +1 -0
  28. package/dist/admission/profiles.js +91 -0
  29. package/dist/admission/profiles.js.map +1 -0
  30. package/dist/admission/qrFlags.d.ts +12 -0
  31. package/dist/admission/qrFlags.d.ts.map +1 -0
  32. package/dist/admission/qrFlags.js +48 -0
  33. package/dist/admission/qrFlags.js.map +1 -0
  34. package/dist/admission/routeGates.d.ts +36 -0
  35. package/dist/admission/routeGates.d.ts.map +1 -0
  36. package/dist/admission/routeGates.js +144 -0
  37. package/dist/admission/routeGates.js.map +1 -0
  38. package/dist/admission/texel.d.ts +50 -0
  39. package/dist/admission/texel.d.ts.map +1 -0
  40. package/dist/admission/texel.js +177 -0
  41. package/dist/admission/texel.js.map +1 -0
  42. package/dist/admission/textureStats.d.ts +45 -0
  43. package/dist/admission/textureStats.d.ts.map +1 -0
  44. package/dist/admission/textureStats.js +201 -0
  45. package/dist/admission/textureStats.js.map +1 -0
  46. package/dist/animation-asset-validator.d.ts +44 -0
  47. package/dist/animation-asset-validator.d.ts.map +1 -1
  48. package/dist/animation-asset-validator.js +80 -1
  49. package/dist/animation-asset-validator.js.map +1 -1
  50. package/dist/asset-core-types.d.ts +100 -4
  51. package/dist/asset-core-types.d.ts.map +1 -1
  52. package/dist/asset-inspection-types.d.ts +9 -0
  53. package/dist/asset-inspection-types.d.ts.map +1 -1
  54. package/dist/asset-manifest.d.ts +1 -0
  55. package/dist/asset-manifest.d.ts.map +1 -1
  56. package/dist/asset-manifest.js +17 -5
  57. package/dist/asset-manifest.js.map +1 -1
  58. package/dist/asset-route-typegen.d.ts +37 -0
  59. package/dist/asset-route-typegen.d.ts.map +1 -0
  60. package/dist/asset-route-typegen.js +179 -0
  61. package/dist/asset-route-typegen.js.map +1 -0
  62. package/dist/cli-help.d.ts +1 -1
  63. package/dist/cli-help.d.ts.map +1 -1
  64. package/dist/cli-help.js +9 -4
  65. package/dist/cli-help.js.map +1 -1
  66. package/dist/cli-options.d.ts +7 -0
  67. package/dist/cli-options.d.ts.map +1 -1
  68. package/dist/cli-options.js +33 -2
  69. package/dist/cli-options.js.map +1 -1
  70. package/dist/cli.d.ts +1 -1
  71. package/dist/cli.d.ts.map +1 -1
  72. package/dist/cli.js +126 -11
  73. package/dist/cli.js.map +1 -1
  74. package/dist/codemods/engine-entry-imports.d.ts +22 -0
  75. package/dist/codemods/engine-entry-imports.d.ts.map +1 -0
  76. package/dist/codemods/engine-entry-imports.js +159 -0
  77. package/dist/codemods/engine-entry-imports.js.map +1 -0
  78. package/dist/codemods/lean-imports.d.ts +40 -0
  79. package/dist/codemods/lean-imports.d.ts.map +1 -0
  80. package/dist/codemods/lean-imports.js +175 -0
  81. package/dist/codemods/lean-imports.js.map +1 -0
  82. package/dist/codemods/renderer-imports.d.ts +36 -0
  83. package/dist/codemods/renderer-imports.d.ts.map +1 -0
  84. package/dist/codemods/renderer-imports.js +364 -0
  85. package/dist/codemods/renderer-imports.js.map +1 -0
  86. package/dist/codemods/renderer-mode.d.ts +38 -0
  87. package/dist/codemods/renderer-mode.d.ts.map +1 -0
  88. package/dist/codemods/renderer-mode.js +130 -0
  89. package/dist/codemods/renderer-mode.js.map +1 -0
  90. package/dist/commands/prd01/index.d.ts +8 -0
  91. package/dist/commands/prd01/index.d.ts.map +1 -0
  92. package/dist/commands/prd01/index.js +39 -0
  93. package/dist/commands/prd01/index.js.map +1 -0
  94. package/dist/commands/prd02/environmentsBake.d.ts +6 -0
  95. package/dist/commands/prd02/environmentsBake.d.ts.map +1 -0
  96. package/dist/commands/prd02/environmentsBake.js +174 -0
  97. package/dist/commands/prd02/environmentsBake.js.map +1 -0
  98. package/dist/commands/prd02/index.d.ts +2 -0
  99. package/dist/commands/prd02/index.d.ts.map +1 -0
  100. package/dist/commands/prd02/index.js +26 -0
  101. package/dist/commands/prd02/index.js.map +1 -0
  102. package/dist/commands/prd02/migrateLighting.d.ts +17 -0
  103. package/dist/commands/prd02/migrateLighting.d.ts.map +1 -0
  104. package/dist/commands/prd02/migrateLighting.js +86 -0
  105. package/dist/commands/prd02/migrateLighting.js.map +1 -0
  106. package/dist/commands/prd02/migrateLightingSweep.d.ts +20 -0
  107. package/dist/commands/prd02/migrateLightingSweep.d.ts.map +1 -0
  108. package/dist/commands/prd02/migrateLightingSweep.js +105 -0
  109. package/dist/commands/prd02/migrateLightingSweep.js.map +1 -0
  110. package/dist/commands/prd03/index.d.ts +7 -0
  111. package/dist/commands/prd03/index.d.ts.map +1 -0
  112. package/dist/commands/prd03/index.js +9 -0
  113. package/dist/commands/prd03/index.js.map +1 -0
  114. package/dist/commands/prd04/index.d.ts +10 -0
  115. package/dist/commands/prd04/index.d.ts.map +1 -0
  116. package/dist/commands/prd04/index.js +10 -0
  117. package/dist/commands/prd04/index.js.map +1 -0
  118. package/dist/commands/prd04/modelTintReport.d.ts +16 -0
  119. package/dist/commands/prd04/modelTintReport.d.ts.map +1 -0
  120. package/dist/commands/prd04/modelTintReport.js +114 -0
  121. package/dist/commands/prd04/modelTintReport.js.map +1 -0
  122. package/dist/commands/prd04/pinEmissiveDefaults.d.ts +3 -0
  123. package/dist/commands/prd04/pinEmissiveDefaults.d.ts.map +1 -0
  124. package/dist/commands/prd04/pinEmissiveDefaults.js +36 -0
  125. package/dist/commands/prd04/pinEmissiveDefaults.js.map +1 -0
  126. package/dist/commands/prd05/admit.d.ts +54 -0
  127. package/dist/commands/prd05/admit.d.ts.map +1 -0
  128. package/dist/commands/prd05/admit.js +153 -0
  129. package/dist/commands/prd05/admit.js.map +1 -0
  130. package/dist/commands/prd05/codemods/assetsRouteModules.d.ts +3 -0
  131. package/dist/commands/prd05/codemods/assetsRouteModules.d.ts.map +1 -0
  132. package/dist/commands/prd05/codemods/assetsRouteModules.js +92 -0
  133. package/dist/commands/prd05/codemods/assetsRouteModules.js.map +1 -0
  134. package/dist/commands/prd05/index.d.ts +9 -0
  135. package/dist/commands/prd05/index.d.ts.map +1 -0
  136. package/dist/commands/prd05/index.js +171 -0
  137. package/dist/commands/prd05/index.js.map +1 -0
  138. package/dist/commands/prd05/library.d.ts +23 -0
  139. package/dist/commands/prd05/library.d.ts.map +1 -0
  140. package/dist/commands/prd05/library.js +245 -0
  141. package/dist/commands/prd05/library.js.map +1 -0
  142. package/dist/commands/prd05/lookdev.d.ts +14 -0
  143. package/dist/commands/prd05/lookdev.d.ts.map +1 -0
  144. package/dist/commands/prd05/lookdev.js +68 -0
  145. package/dist/commands/prd05/lookdev.js.map +1 -0
  146. package/dist/commands/prd05/optimize.d.ts +16 -0
  147. package/dist/commands/prd05/optimize.d.ts.map +1 -0
  148. package/dist/commands/prd05/optimize.js +55 -0
  149. package/dist/commands/prd05/optimize.js.map +1 -0
  150. package/dist/commands/prd05/prune.d.ts +26 -0
  151. package/dist/commands/prd05/prune.d.ts.map +1 -0
  152. package/dist/commands/prd05/prune.js +104 -0
  153. package/dist/commands/prd05/prune.js.map +1 -0
  154. package/dist/commands/prd05/review.d.ts +24 -0
  155. package/dist/commands/prd05/review.d.ts.map +1 -0
  156. package/dist/commands/prd05/review.js +40 -0
  157. package/dist/commands/prd05/review.js.map +1 -0
  158. package/dist/commands/prd06/index.d.ts +6 -0
  159. package/dist/commands/prd06/index.d.ts.map +1 -0
  160. package/dist/commands/prd06/index.js +86 -0
  161. package/dist/commands/prd06/index.js.map +1 -0
  162. package/dist/commands/prd06/inspectAnimationClips.d.ts +86 -0
  163. package/dist/commands/prd06/inspectAnimationClips.d.ts.map +1 -0
  164. package/dist/commands/prd06/inspectAnimationClips.js +168 -0
  165. package/dist/commands/prd06/inspectAnimationClips.js.map +1 -0
  166. package/dist/commands/prd06/validateHero.d.ts +18 -0
  167. package/dist/commands/prd06/validateHero.d.ts.map +1 -0
  168. package/dist/commands/prd06/validateHero.js +91 -0
  169. package/dist/commands/prd06/validateHero.js.map +1 -0
  170. package/dist/commands/prd07/codemods.d.ts +28 -0
  171. package/dist/commands/prd07/codemods.d.ts.map +1 -0
  172. package/dist/commands/prd07/codemods.js +155 -0
  173. package/dist/commands/prd07/codemods.js.map +1 -0
  174. package/dist/commands/prd07/index.d.ts +2 -0
  175. package/dist/commands/prd07/index.d.ts.map +1 -0
  176. package/dist/commands/prd07/index.js +151 -0
  177. package/dist/commands/prd07/index.js.map +1 -0
  178. package/dist/commands/prd08/feelLint.d.ts +13 -0
  179. package/dist/commands/prd08/feelLint.d.ts.map +1 -0
  180. package/dist/commands/prd08/feelLint.js +32 -0
  181. package/dist/commands/prd08/feelLint.js.map +1 -0
  182. package/dist/commands/prd08/index.d.ts +2 -0
  183. package/dist/commands/prd08/index.d.ts.map +1 -0
  184. package/dist/commands/prd08/index.js +16 -0
  185. package/dist/commands/prd08/index.js.map +1 -0
  186. package/dist/commands/prd08/motionReport.d.ts +94 -0
  187. package/dist/commands/prd08/motionReport.d.ts.map +1 -0
  188. package/dist/commands/prd08/motionReport.js +197 -0
  189. package/dist/commands/prd08/motionReport.js.map +1 -0
  190. package/dist/commands/prd09/codemods/audio-wrapper.d.ts +9 -0
  191. package/dist/commands/prd09/codemods/audio-wrapper.d.ts.map +1 -0
  192. package/dist/commands/prd09/codemods/audio-wrapper.js +30 -0
  193. package/dist/commands/prd09/codemods/audio-wrapper.js.map +1 -0
  194. package/dist/commands/prd09/codemods/capture-branches.d.ts +10 -0
  195. package/dist/commands/prd09/codemods/capture-branches.d.ts.map +1 -0
  196. package/dist/commands/prd09/codemods/capture-branches.js +54 -0
  197. package/dist/commands/prd09/codemods/capture-branches.js.map +1 -0
  198. package/dist/commands/prd09/codemods/evidence-globals.d.ts +8 -0
  199. package/dist/commands/prd09/codemods/evidence-globals.d.ts.map +1 -0
  200. package/dist/commands/prd09/codemods/evidence-globals.js +19 -0
  201. package/dist/commands/prd09/codemods/evidence-globals.js.map +1 -0
  202. package/dist/commands/prd09/codemods/perf-script.d.ts +8 -0
  203. package/dist/commands/prd09/codemods/perf-script.d.ts.map +1 -0
  204. package/dist/commands/prd09/codemods/perf-script.js +24 -0
  205. package/dist/commands/prd09/codemods/perf-script.js.map +1 -0
  206. package/dist/commands/prd09/index.d.ts +8 -0
  207. package/dist/commands/prd09/index.d.ts.map +1 -0
  208. package/dist/commands/prd09/index.js +19 -0
  209. package/dist/commands/prd09/index.js.map +1 -0
  210. package/dist/commands/prd09/perf-report.d.ts +56 -0
  211. package/dist/commands/prd09/perf-report.d.ts.map +1 -0
  212. package/dist/commands/prd09/perf-report.js +118 -0
  213. package/dist/commands/prd09/perf-report.js.map +1 -0
  214. package/dist/commands/prd09/sfx-admit.d.ts +18 -0
  215. package/dist/commands/prd09/sfx-admit.d.ts.map +1 -0
  216. package/dist/commands/prd09/sfx-admit.js +120 -0
  217. package/dist/commands/prd09/sfx-admit.js.map +1 -0
  218. package/dist/commands/prd10/index.d.ts +2 -0
  219. package/dist/commands/prd10/index.d.ts.map +1 -0
  220. package/dist/commands/prd10/index.js +109 -0
  221. package/dist/commands/prd10/index.js.map +1 -0
  222. package/dist/commands/prd11/batchOptout.d.ts +35 -0
  223. package/dist/commands/prd11/batchOptout.d.ts.map +1 -0
  224. package/dist/commands/prd11/batchOptout.js +155 -0
  225. package/dist/commands/prd11/batchOptout.js.map +1 -0
  226. package/dist/commands/prd11/index.d.ts +2 -0
  227. package/dist/commands/prd11/index.d.ts.map +1 -0
  228. package/dist/commands/prd11/index.js +13 -0
  229. package/dist/commands/prd11/index.js.map +1 -0
  230. package/dist/commands/prd11/perfGate.d.ts +15 -0
  231. package/dist/commands/prd11/perfGate.d.ts.map +1 -0
  232. package/dist/commands/prd11/perfGate.js +98 -0
  233. package/dist/commands/prd11/perfGate.js.map +1 -0
  234. package/dist/commands/prd13/index.d.ts +15 -0
  235. package/dist/commands/prd13/index.d.ts.map +1 -0
  236. package/dist/commands/prd13/index.js +26 -0
  237. package/dist/commands/prd13/index.js.map +1 -0
  238. package/dist/commands/prd13/run.d.ts +10 -0
  239. package/dist/commands/prd13/run.d.ts.map +1 -0
  240. package/dist/commands/prd13/run.js +29 -0
  241. package/dist/commands/prd13/run.js.map +1 -0
  242. package/dist/commands/prd14/index.d.ts +6 -0
  243. package/dist/commands/prd14/index.d.ts.map +1 -0
  244. package/dist/commands/prd14/index.js +6 -0
  245. package/dist/commands/prd14/index.js.map +1 -0
  246. package/dist/commands/prd15/index.d.ts +8 -0
  247. package/dist/commands/prd15/index.d.ts.map +1 -0
  248. package/dist/commands/prd15/index.js +152 -0
  249. package/dist/commands/prd15/index.js.map +1 -0
  250. package/dist/commands/registry.d.ts +19 -0
  251. package/dist/commands/registry.d.ts.map +1 -0
  252. package/dist/commands/registry.js +19 -0
  253. package/dist/commands/registry.js.map +1 -0
  254. package/dist/contracts/assetManifest.d.ts +80 -0
  255. package/dist/contracts/assetManifest.d.ts.map +1 -0
  256. package/dist/contracts/assetManifest.js +9 -0
  257. package/dist/contracts/assetManifest.js.map +1 -0
  258. package/dist/contracts/commands.d.ts +53 -0
  259. package/dist/contracts/commands.d.ts.map +1 -0
  260. package/dist/contracts/commands.js +37 -0
  261. package/dist/contracts/commands.js.map +1 -0
  262. package/dist/index.d.ts +17 -1
  263. package/dist/index.d.ts.map +1 -1
  264. package/dist/index.js +297 -73
  265. package/dist/index.js.map +1 -1
  266. package/dist/library-manifest.d.ts +86 -0
  267. package/dist/library-manifest.d.ts.map +1 -0
  268. package/dist/library-manifest.js +95 -0
  269. package/dist/library-manifest.js.map +1 -0
  270. package/dist/look/capture.d.ts +51 -0
  271. package/dist/look/capture.d.ts.map +1 -0
  272. package/dist/look/capture.js +229 -0
  273. package/dist/look/capture.js.map +1 -0
  274. package/dist/look/judge.d.ts +24 -0
  275. package/dist/look/judge.d.ts.map +1 -0
  276. package/dist/look/judge.js +151 -0
  277. package/dist/look/judge.js.map +1 -0
  278. package/dist/look/lint-static.d.ts +45 -0
  279. package/dist/look/lint-static.d.ts.map +1 -0
  280. package/dist/look/lint-static.js +241 -0
  281. package/dist/look/lint-static.js.map +1 -0
  282. package/dist/look/rubric.d.ts +70 -0
  283. package/dist/look/rubric.d.ts.map +1 -0
  284. package/dist/look/rubric.js +169 -0
  285. package/dist/look/rubric.js.map +1 -0
  286. package/dist/meshy/admission.d.ts.map +1 -1
  287. package/dist/meshy/admission.js +32 -7
  288. package/dist/meshy/admission.js.map +1 -1
  289. package/dist/meshy/import.d.ts +7 -1
  290. package/dist/meshy/import.d.ts.map +1 -1
  291. package/dist/meshy/import.js +84 -6
  292. package/dist/meshy/import.js.map +1 -1
  293. package/dist/migrate-three/CompatibilityWarnings.d.ts +6 -0
  294. package/dist/migrate-three/CompatibilityWarnings.d.ts.map +1 -0
  295. package/dist/migrate-three/CompatibilityWarnings.js +24 -0
  296. package/dist/migrate-three/CompatibilityWarnings.js.map +1 -0
  297. package/dist/migrate-three/ImportMap.d.ts +19 -0
  298. package/dist/migrate-three/ImportMap.d.ts.map +1 -0
  299. package/dist/migrate-three/ImportMap.js +35 -0
  300. package/dist/migrate-three/ImportMap.js.map +1 -0
  301. package/dist/migrate-three/R3fMigration.d.ts +32 -0
  302. package/dist/migrate-three/R3fMigration.d.ts.map +1 -0
  303. package/dist/migrate-three/R3fMigration.js +70 -0
  304. package/dist/migrate-three/R3fMigration.js.map +1 -0
  305. package/dist/migrate-three/ThreeToA3DAdapter.d.ts +8 -0
  306. package/dist/migrate-three/ThreeToA3DAdapter.d.ts.map +1 -0
  307. package/dist/migrate-three/ThreeToA3DAdapter.js +20 -0
  308. package/dist/migrate-three/ThreeToA3DAdapter.js.map +1 -0
  309. package/dist/migrate-three/emit.d.ts +21 -0
  310. package/dist/migrate-three/emit.d.ts.map +1 -0
  311. package/dist/migrate-three/emit.js +117 -0
  312. package/dist/migrate-three/emit.js.map +1 -0
  313. package/dist/migrate-three/mappings.d.ts +21 -0
  314. package/dist/migrate-three/mappings.d.ts.map +1 -0
  315. package/dist/migrate-three/mappings.js +42 -0
  316. package/dist/migrate-three/mappings.js.map +1 -0
  317. package/dist/migrate-three/parse.d.ts +20 -0
  318. package/dist/migrate-three/parse.d.ts.map +1 -0
  319. package/dist/migrate-three/parse.js +56 -0
  320. package/dist/migrate-three/parse.js.map +1 -0
  321. package/dist/migrate-three/report.d.ts +18 -0
  322. package/dist/migrate-three/report.d.ts.map +1 -0
  323. package/dist/migrate-three/report.js +16 -0
  324. package/dist/migrate-three/report.js.map +1 -0
  325. package/dist/pull-bridge/adapters.d.ts +1 -1
  326. package/dist/pull-bridge/adapters.d.ts.map +1 -1
  327. package/dist/pull-bridge/adapters.js +17 -4
  328. package/dist/pull-bridge/adapters.js.map +1 -1
  329. package/dist/pull-bridge/provenance.d.ts.map +1 -1
  330. package/dist/pull-bridge/provenance.js +3 -2
  331. package/dist/pull-bridge/provenance.js.map +1 -1
  332. package/dist/pull-bridge/pullable.d.ts.map +1 -1
  333. package/dist/pull-bridge/pullable.js +14 -3
  334. package/dist/pull-bridge/pullable.js.map +1 -1
  335. package/dist/pull-bridge/scoring.d.ts +36 -8
  336. package/dist/pull-bridge/scoring.d.ts.map +1 -1
  337. package/dist/pull-bridge/scoring.js +143 -47
  338. package/dist/pull-bridge/scoring.js.map +1 -1
  339. package/dist/pull-bridge/search.d.ts +2 -0
  340. package/dist/pull-bridge/search.d.ts.map +1 -1
  341. package/dist/pull-bridge/search.js +17 -10
  342. package/dist/pull-bridge/search.js.map +1 -1
  343. package/dist/pull-bridge.d.ts +2 -2
  344. package/dist/pull-bridge.d.ts.map +1 -1
  345. package/dist/pull-bridge.js +24 -8
  346. package/dist/pull-bridge.js.map +1 -1
  347. package/package.json +6 -3
  348. package/skills/agent-files/AGENTS.md +3 -0
  349. package/skills/aura3d-animation-studio/SKILL.md +153 -0
  350. package/skills/aura3d-animation-studio/references/shot-looks.md +26 -0
  351. package/skills/aura3d-art-direction/SKILL.md +84 -0
  352. package/skills/aura3d-art-direction/references/failure-gallery.md +64 -0
  353. package/skills/aura3d-art-direction/references/framing-and-shots.md +45 -0
  354. package/skills/aura3d-art-direction/references/look-recipes.md +32 -0
  355. package/skills/aura3d-art-direction/references/quality-bar.md +103 -0
  356. package/skills/aura3d-art-direction/references/reference-frames.md +82 -0
  357. package/skills/aura3d-assets/SKILL.md +151 -0
  358. package/skills/aura3d-assets/references/preview-under-look.md +26 -0
  359. package/skills/aura3d-browser-game/SKILL.md +149 -0
  360. package/skills/aura3d-browser-game/references/genre-looks.md +52 -0
  361. package/skills/aura3d-character-animation/SKILL.md +129 -0
  362. package/skills/aura3d-character-animation/references/stage-and-lighting.md +31 -0
  363. package/skills/aura3d-core/SKILL.md +143 -0
  364. package/skills/aura3d-core/references/boundaries.md +91 -0
  365. package/skills/aura3d-evidence-review/SKILL.md +106 -0
  366. package/skills/aura3d-game-art/SKILL.md +118 -0
  367. package/skills/aura3d-game-art/references/sheet-check.mjs +58 -0
  368. package/skills/aura3d-game-art/references/sprite-palettes.md +25 -0
  369. package/skills/aura3d-materials-environments/SKILL.md +139 -0
  370. package/skills/aura3d-performance/SKILL.md +97 -0
  371. package/skills/aura3d-retexture/SKILL.md +115 -0
  372. package/skills/aura3d-retexture/references/geometry-hash.mjs +89 -0
  373. package/skills/aura3d-scene-authoring/SKILL.md +132 -0
  374. package/skills/aura3d-scene-authoring/references/look-by-family.md +28 -0
  375. package/skills/aura3d-threejs-migration/SKILL.md +125 -0
  376. package/skills/aura3d-threejs-migration/references/look-mapping.md +27 -0
  377. package/skills/llms.txt +147 -0
  378. package/skills/manifest.json +163 -0
  379. 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 { dirname, extname, join, relative, resolve } from "node:path";
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
- schema: "aura3d.assets/1.0",
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
- return written;
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
- return inspectGltf(json, baseDir);
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
- function inspectGltfAnimations(json) {
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: animation.name ?? `clip-${index}`,
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
- if (!inspection.bounds)
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(extname(path).slice(1).toLowerCase()))
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(extname(path).slice(1).toLowerCase()))
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 && !hasHashBoundFlatColorMaterialEvidence(asset)) {
2692
- warnings.push(`${asset.id}: release primary model has no texture references; use only with explicit material/readability evidence.`);
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
- if (hasHashBoundFlatColorMaterialEvidence(asset)) {
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
- if (requiresTextureEvidence(role, suitabilityReason) && !hasTextureEvidence) {
2945
- warnings.push(`${asset.id}: role-aware release ${role} validation requires texture evidence or explicit stylized-material rationale.`);
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
- Read ./llms.txt first, then ./docs/agents/README.md.
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) {