@auraindustry/aurajs 0.0.6 → 0.1.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.
Files changed (334) hide show
  1. package/README.md +103 -7
  2. package/benchmarks/perf-thresholds.json +54 -0
  3. package/package.json +4 -7
  4. package/src/asset-pack.mjs +5 -1
  5. package/src/authored-project.mjs +1449 -0
  6. package/src/authored-runtime.mjs +2016 -0
  7. package/src/authoring/avatar-animation-graph.mjs +648 -0
  8. package/src/bin-integrity.mjs +272 -0
  9. package/src/build-contract/assets.mjs +130 -0
  10. package/src/build-contract/capabilities.mjs +116 -0
  11. package/src/build-contract/constants.mjs +6 -0
  12. package/src/build-contract/helpers.mjs +44 -0
  13. package/src/build-contract/web-templates.mjs +5993 -0
  14. package/src/build-contract.mjs +27 -2910
  15. package/src/bundler.mjs +188 -55
  16. package/src/cli.mjs +4825 -1512
  17. package/src/commands/project-authoring.mjs +434 -0
  18. package/src/config.mjs +27 -0
  19. package/src/conformance/cases/app-and-ui-runtime-cases.mjs +3309 -0
  20. package/src/conformance/cases/core-runtime-cases.mjs +1431 -0
  21. package/src/conformance/cases/index.mjs +11 -0
  22. package/src/conformance/cases/scene3d-and-media-cases.mjs +2094 -0
  23. package/src/conformance/cases/systems-and-gameplay-cases.mjs +1776 -0
  24. package/src/conformance/shared.mjs +27 -0
  25. package/src/conformance-runner.mjs +25 -13
  26. package/src/conformance.mjs +619 -4020
  27. package/src/cutscene.mjs +362 -5
  28. package/src/dev-cli-action.mjs +249 -0
  29. package/src/dev-cli-inspect.mjs +92 -0
  30. package/src/dev-cli-state.mjs +80 -0
  31. package/src/external-asset-cache.mjs +587 -0
  32. package/src/external-asset-policy.mjs +217 -0
  33. package/src/external-package-surface.mjs +206 -0
  34. package/src/game-action-runtime.mjs +869 -0
  35. package/src/game-state-runtime.mjs +206 -6
  36. package/src/headless-action.mjs +186 -0
  37. package/src/headless-test/runtime-animation.mjs +1173 -0
  38. package/src/headless-test/runtime-coordinator.mjs +1514 -0
  39. package/src/headless-test/runtime-primitives.mjs +320 -0
  40. package/src/headless-test/runtime-world.mjs +2253 -0
  41. package/src/headless-test.mjs +392 -4298
  42. package/src/host-binary.mjs +342 -14
  43. package/src/icon-discovery.mjs +64 -0
  44. package/src/make-catalog.mjs +109 -0
  45. package/src/make.mjs +197 -0
  46. package/src/package-integrity.mjs +586 -0
  47. package/src/perf-benchmark.mjs +353 -0
  48. package/src/postinstall.mjs +5 -5
  49. package/src/prefabs/index.mjs +34 -0
  50. package/src/prefabs/scene-serialization.mjs +184 -0
  51. package/src/project-importer.mjs +620 -0
  52. package/src/project-registry.mjs +24 -0
  53. package/src/publish-command.mjs +195 -0
  54. package/src/publish-env-example.mjs +83 -0
  55. package/src/publish-validation.mjs +708 -0
  56. package/src/retro/assets/compile.mjs +232 -0
  57. package/src/retro/backend-gba/authoring.mjs +1029 -0
  58. package/src/retro/backend-gba/rom.mjs +363 -0
  59. package/src/retro/backend-gbc/rom.mjs +85 -0
  60. package/src/retro/build.mjs +278 -0
  61. package/src/retro/cli/commands.mjs +292 -0
  62. package/src/retro/cli/templates.mjs +84 -0
  63. package/src/retro/diagnostics/catalog.mjs +110 -0
  64. package/src/retro/diagnostics/emit.mjs +72 -0
  65. package/src/retro/emulator/case-overlay.mjs +64 -0
  66. package/src/retro/emulator/discovery.mjs +158 -0
  67. package/src/retro/emulator/macos-case-overlay.swift +220 -0
  68. package/src/retro/emulator/profiles.mjs +146 -0
  69. package/src/retro/emulator/runner.mjs +289 -0
  70. package/src/retro/frontend/load-project.mjs +98 -0
  71. package/src/retro/index.mjs +30 -0
  72. package/src/retro/ir/build-ir.mjs +108 -0
  73. package/src/retro/runtime-gba/contract.mjs +151 -0
  74. package/src/retro/runtime-gbc/contract.mjs +117 -0
  75. package/src/retro/shared/span.mjs +26 -0
  76. package/src/retro/shared/targets.mjs +64 -0
  77. package/src/retro/validator/check-project.mjs +114 -0
  78. package/src/runtime-hotspot-audit.mjs +707 -0
  79. package/src/scaffold/config.mjs +1000 -0
  80. package/src/scaffold/fs.mjs +56 -0
  81. package/src/scaffold/layout.mjs +318 -0
  82. package/src/scaffold/project-docs.mjs +438 -0
  83. package/src/scaffold.mjs +93 -596
  84. package/src/scene-composition/index.mjs +326 -0
  85. package/src/scene-composition/runtime.mjs +751 -0
  86. package/src/self-hosted-assets.mjs +604 -0
  87. package/src/session-client.mjs +750 -0
  88. package/src/session-native-launcher.mjs +74 -0
  89. package/src/session-protocol.mjs +75 -0
  90. package/src/session-runtime.mjs +321 -0
  91. package/src/session-server.mjs +360 -0
  92. package/src/shader-kits/index.mjs +773 -0
  93. package/src/starter-content-registry.mjs +292 -0
  94. package/src/state-artifacts.mjs +662 -24
  95. package/src/state-dev-reload.mjs +99 -2
  96. package/src/terminal-ui.mjs +245 -0
  97. package/src/web-conformance.mjs +219 -0
  98. package/templates/create/2d/config/gameplay/shooter.config.js +26 -0
  99. package/templates/create/2d/content/gameplay/waves.json +26 -0
  100. package/templates/create/2d/content/registries/.gitkeep +1 -0
  101. package/templates/create/2d/docs/design/.gitkeep +1 -0
  102. package/templates/create/2d/docs/design/loop.md +5 -0
  103. package/templates/create/2d/prefabs/enemies.prefab.js +90 -0
  104. package/templates/create/2d/prefabs/enemy-basic.prefab.js +18 -0
  105. package/templates/create/2d/prefabs/player.prefab.js +36 -0
  106. package/templates/create/2d/prefabs/projectiles.prefab.js +35 -0
  107. package/templates/create/2d/scenes/boot.scene.js +12 -0
  108. package/templates/create/2d/scenes/gameplay.scene.js +230 -0
  109. package/templates/create/2d/scenes/menu.scene.js +9 -0
  110. package/templates/create/2d/src/main.js +6 -185
  111. package/templates/create/2d/src/runtime/app.js +49 -0
  112. package/templates/create/2d/src/runtime/capabilities.js +35 -0
  113. package/templates/create/2d/ui/hud.screen.js +40 -0
  114. package/templates/create/2d/ui/pause.screen.js +149 -0
  115. package/templates/create/2d/ui/settings.screen.js +347 -0
  116. package/templates/create/2d/ui/title.screen.js +13 -0
  117. package/templates/create/2d-adventure/aura.config.json +28 -0
  118. package/templates/create/2d-adventure/config/gameplay/adventure.config.js +14 -0
  119. package/templates/create/2d-adventure/content/gameplay/world.js +46 -0
  120. package/templates/create/2d-adventure/content/registries/.gitkeep +1 -0
  121. package/templates/create/2d-adventure/docs/design/loop.md +5 -0
  122. package/templates/create/2d-adventure/prefabs/player.prefab.js +54 -0
  123. package/templates/create/2d-adventure/prefabs/relic.prefab.js +38 -0
  124. package/templates/create/2d-adventure/prefabs/world.prefab.js +125 -0
  125. package/templates/create/2d-adventure/scenes/gameplay.scene.js +256 -0
  126. package/templates/create/2d-adventure/src/runtime/capabilities.js +34 -0
  127. package/templates/create/2d-adventure/ui/hud.screen.js +60 -0
  128. package/templates/create/2d-survivor/config/gameplay/survivor.config.js +33 -0
  129. package/templates/create/2d-survivor/content/gameplay/spawn-zones.json +29 -0
  130. package/templates/create/2d-survivor/content/registries/.gitkeep +1 -0
  131. package/templates/create/2d-survivor/docs/design/.gitkeep +1 -0
  132. package/templates/create/2d-survivor/docs/design/loop.md +5 -0
  133. package/templates/create/2d-survivor/prefabs/enemies.prefab.js +178 -0
  134. package/templates/create/2d-survivor/prefabs/enemy-swarm.prefab.js +18 -0
  135. package/templates/create/2d-survivor/prefabs/player.prefab.js +42 -0
  136. package/templates/create/2d-survivor/prefabs/projectiles.prefab.js +56 -0
  137. package/templates/create/2d-survivor/scenes/boot.scene.js +12 -0
  138. package/templates/create/2d-survivor/scenes/gameplay.scene.js +314 -0
  139. package/templates/create/2d-survivor/scenes/menu.scene.js +9 -0
  140. package/templates/create/2d-survivor/src/main.js +5 -332
  141. package/templates/create/2d-survivor/src/runtime/app.js +49 -0
  142. package/templates/create/2d-survivor/src/runtime/capabilities.js +35 -0
  143. package/templates/create/2d-survivor/ui/hud.screen.js +45 -0
  144. package/templates/create/2d-survivor/ui/title.screen.js +13 -0
  145. package/templates/create/3d/assets/models/starter-avatar.gltf +184 -0
  146. package/templates/create/3d/config/gameplay/.gitkeep +1 -0
  147. package/templates/create/3d/content/gameplay/checkpoints.json +33 -0
  148. package/templates/create/3d/content/gameplay/course.js +40 -0
  149. package/templates/create/3d/content/registries/.gitkeep +1 -0
  150. package/templates/create/3d/docs/design/.gitkeep +1 -0
  151. package/templates/create/3d/docs/design/loop.md +5 -0
  152. package/templates/create/3d/prefabs/checkpoint.prefab.js +15 -0
  153. package/templates/create/3d/prefabs/player.prefab.js +204 -0
  154. package/templates/create/3d/prefabs/world.prefab.js +112 -0
  155. package/templates/create/3d/scenes/boot.scene.js +12 -0
  156. package/templates/create/3d/scenes/checkpoint.scene.js +9 -0
  157. package/templates/create/3d/scenes/gameplay.scene.js +292 -0
  158. package/templates/create/3d/src/main.js +6 -295
  159. package/templates/create/3d/src/runtime/app.js +49 -0
  160. package/templates/create/3d/src/runtime/capabilities.js +53 -0
  161. package/templates/create/3d/src/runtime/materials.js +34 -0
  162. package/templates/create/3d/src/runtime/state.js +39 -0
  163. package/templates/create/3d/ui/hud.screen.js +75 -0
  164. package/templates/create/3d/ui/pause.screen.js +166 -0
  165. package/templates/create/3d/ui/settings.screen.js +387 -0
  166. package/templates/create/3d-adventure/assets/models/starter-avatar.gltf +184 -0
  167. package/templates/create/3d-adventure/aura.config.json +28 -0
  168. package/templates/create/3d-adventure/config/gameplay/adventure.config.js +9 -0
  169. package/templates/create/3d-adventure/content/gameplay/course.js +62 -0
  170. package/templates/create/3d-adventure/content/registries/.gitkeep +1 -0
  171. package/templates/create/3d-adventure/docs/design/loop.md +5 -0
  172. package/templates/create/3d-adventure/prefabs/player.prefab.js +168 -0
  173. package/templates/create/3d-adventure/prefabs/relic.prefab.js +35 -0
  174. package/templates/create/3d-adventure/prefabs/world.prefab.js +119 -0
  175. package/templates/create/3d-adventure/scenes/gameplay.scene.js +358 -0
  176. package/templates/create/3d-adventure/src/runtime/capabilities.js +56 -0
  177. package/templates/create/3d-adventure/src/runtime/materials.js +39 -0
  178. package/templates/create/3d-adventure/src/runtime/state.js +31 -0
  179. package/templates/create/3d-adventure/ui/hud.screen.js +70 -0
  180. package/templates/create/3d-adventure/ui/pause.screen.js +437 -0
  181. package/templates/create/3d-collectathon/assets/models/starter-avatar.gltf +184 -0
  182. package/templates/create/3d-collectathon/config/gameplay/.gitkeep +1 -0
  183. package/templates/create/3d-collectathon/content/gameplay/collectibles.json +26 -0
  184. package/templates/create/3d-collectathon/content/gameplay/course.js +46 -0
  185. package/templates/create/3d-collectathon/content/registries/.gitkeep +1 -0
  186. package/templates/create/3d-collectathon/docs/design/.gitkeep +1 -0
  187. package/templates/create/3d-collectathon/docs/design/loop.md +5 -0
  188. package/templates/create/3d-collectathon/prefabs/collectible.prefab.js +15 -0
  189. package/templates/create/3d-collectathon/prefabs/player.prefab.js +207 -0
  190. package/templates/create/3d-collectathon/prefabs/world.prefab.js +112 -0
  191. package/templates/create/3d-collectathon/scenes/boot.scene.js +12 -0
  192. package/templates/create/3d-collectathon/scenes/checkpoint.scene.js +9 -0
  193. package/templates/create/3d-collectathon/scenes/gameplay.scene.js +200 -0
  194. package/templates/create/3d-collectathon/src/main.js +5 -355
  195. package/templates/create/3d-collectathon/src/runtime/app.js +49 -0
  196. package/templates/create/3d-collectathon/src/runtime/capabilities.js +53 -0
  197. package/templates/create/3d-collectathon/src/runtime/materials.js +34 -0
  198. package/templates/create/3d-collectathon/src/runtime/state.js +27 -0
  199. package/templates/create/3d-collectathon/ui/hud.screen.js +66 -0
  200. package/templates/create/3d-collectathon/ui/pause.screen.js +13 -0
  201. package/templates/create/blank/config/gameplay/.gitkeep +1 -0
  202. package/templates/create/blank/content/gameplay/.gitkeep +1 -0
  203. package/templates/create/blank/content/registries/.gitkeep +1 -0
  204. package/templates/create/blank/docs/design/.gitkeep +1 -0
  205. package/templates/create/blank/docs/design/loop.md +5 -0
  206. package/templates/create/blank/prefabs/.gitkeep +1 -0
  207. package/templates/create/blank/scenes/.gitkeep +1 -0
  208. package/templates/create/blank/src/runtime/.gitkeep +1 -0
  209. package/templates/create/blank/ui/.gitkeep +1 -0
  210. package/templates/create/deckbuilder-2d/assets/audio/.gitkeep +1 -0
  211. package/templates/create/deckbuilder-2d/assets/fonts/.gitkeep +1 -0
  212. package/templates/create/deckbuilder-2d/assets/sprites/.gitkeep +1 -0
  213. package/templates/create/deckbuilder-2d/assets/starter/README.md +11 -0
  214. package/templates/create/deckbuilder-2d/assets/ui/.gitkeep +1 -0
  215. package/templates/create/deckbuilder-2d/aura.config.json +28 -0
  216. package/templates/create/deckbuilder-2d/config/gameplay/deckbuilder.config.js +26 -0
  217. package/templates/create/deckbuilder-2d/content/cards/guard.card.js +19 -0
  218. package/templates/create/deckbuilder-2d/content/cards/spark.card.js +20 -0
  219. package/templates/create/deckbuilder-2d/content/cards/starter.deck.js +69 -0
  220. package/templates/create/deckbuilder-2d/content/cards/strike.card.js +19 -0
  221. package/templates/create/deckbuilder-2d/content/cards/survey.card.js +20 -0
  222. package/templates/create/deckbuilder-2d/content/encounters/training-battle.encounter.js +14 -0
  223. package/templates/create/deckbuilder-2d/content/encounters/training-battle.js +65 -0
  224. package/templates/create/deckbuilder-2d/content/enemies/training-automaton.enemy.js +48 -0
  225. package/templates/create/deckbuilder-2d/content/gameplay/.gitkeep +1 -0
  226. package/templates/create/deckbuilder-2d/content/registries/cards.registry.js +26 -0
  227. package/templates/create/deckbuilder-2d/content/registries/encounters.registry.js +20 -0
  228. package/templates/create/deckbuilder-2d/content/registries/enemies.registry.js +20 -0
  229. package/templates/create/deckbuilder-2d/content/registries/relics.registry.js +20 -0
  230. package/templates/create/deckbuilder-2d/content/relics/ember-charm.relic.js +18 -0
  231. package/templates/create/deckbuilder-2d/docs/design/loop.md +12 -0
  232. package/templates/create/deckbuilder-2d/prefabs/.gitkeep +1 -0
  233. package/templates/create/deckbuilder-2d/scenes/boot.scene.js +84 -0
  234. package/templates/create/deckbuilder-2d/scenes/gameplay.scene.js +641 -0
  235. package/templates/create/deckbuilder-2d/src/components/.gitkeep +1 -0
  236. package/templates/create/deckbuilder-2d/src/main.js +17 -0
  237. package/templates/create/deckbuilder-2d/src/runtime/capabilities.js +22 -0
  238. package/templates/create/deckbuilder-2d/src/shared/.gitkeep +1 -0
  239. package/templates/create/deckbuilder-2d/src/systems/.gitkeep +1 -0
  240. package/templates/create/deckbuilder-2d/tests/smoke/.gitkeep +1 -0
  241. package/templates/create/deckbuilder-2d/ui/hud.screen.js +80 -0
  242. package/templates/create/deckbuilder-2d/ui/pause.screen.js +146 -0
  243. package/templates/create/deckbuilder-2d/ui/settings.screen.js +342 -0
  244. package/templates/create/local-multiplayer/aura.config.json +40 -0
  245. package/templates/create/local-multiplayer/config/gameplay/local-multiplayer.config.js +26 -0
  246. package/templates/create/local-multiplayer/content/gameplay/room-layout.js +13 -0
  247. package/templates/create/local-multiplayer/content/registries/.gitkeep +1 -0
  248. package/templates/create/local-multiplayer/docs/design/loop.md +14 -0
  249. package/templates/create/local-multiplayer/prefabs/player.prefab.js +99 -0
  250. package/templates/create/local-multiplayer/scenes/boot.scene.js +12 -0
  251. package/templates/create/local-multiplayer/scenes/gameplay.scene.js +443 -0
  252. package/templates/create/local-multiplayer/src/main.js +17 -0
  253. package/templates/create/local-multiplayer/src/runtime/capabilities.js +28 -0
  254. package/templates/create/local-multiplayer/ui/hud.screen.js +60 -0
  255. package/templates/create/shared/src/runtime/project-inspector.js +105 -0
  256. package/templates/create/shared/src/runtime/scene-flow.js +290 -0
  257. package/templates/create/shared/src/runtime/screen-shell.js +222 -0
  258. package/templates/create/shared/src/runtime/ui-forms.js +209 -0
  259. package/templates/create/shared/src/runtime/ui-settings.js +237 -0
  260. package/templates/create/shared/src/runtime/ui-theme.js +352 -0
  261. package/templates/create/shared/src/starter-utils/adventure-objectives.js +102 -0
  262. package/templates/create/shared/src/starter-utils/animation-2d.js +337 -0
  263. package/templates/create/shared/src/starter-utils/avatar-3d.js +404 -0
  264. package/templates/create/shared/src/starter-utils/combat-feedback-2d.js +320 -0
  265. package/templates/create/shared/src/starter-utils/core.js +39 -3
  266. package/templates/create/shared/src/starter-utils/index.js +8 -2
  267. package/templates/create/shared/src/starter-utils/platformer-3d.js +34 -3
  268. package/templates/create/shared/src/starter-utils/triggers.js +662 -0
  269. package/templates/create/shared/src/starter-utils/tween-2d.js +615 -0
  270. package/templates/create/video-cutscene/assets/video/.gitkeep +0 -0
  271. package/templates/create/video-cutscene/aura.config.json +28 -0
  272. package/templates/create/video-cutscene/config/gameplay/.gitkeep +0 -0
  273. package/templates/create/video-cutscene/content/gameplay/.gitkeep +0 -0
  274. package/templates/create/video-cutscene/content/registries/.gitkeep +0 -0
  275. package/templates/create/video-cutscene/docs/design/loop.md +22 -0
  276. package/templates/create/video-cutscene/prefabs/.gitkeep +0 -0
  277. package/templates/create/video-cutscene/scenes/boot.scene.js +11 -0
  278. package/templates/create/video-cutscene/scenes/cutscene.scene.js +113 -0
  279. package/templates/create/video-cutscene/scenes/gameplay.scene.js +50 -0
  280. package/templates/create/video-cutscene/src/main.js +17 -0
  281. package/templates/create/video-cutscene/src/runtime/app.js +52 -0
  282. package/templates/create/video-cutscene/src/runtime/capabilities.js +35 -0
  283. package/templates/create/video-cutscene/src/runtime/state.js +13 -0
  284. package/templates/create/video-cutscene/ui/.gitkeep +0 -0
  285. package/templates/create-bin/play.js +1187 -0
  286. package/templates/make/README.md +46 -0
  287. package/templates/make/catalog.json +51 -0
  288. package/templates/make/component/files/{{MAKE_NAME}}.component.js +20 -0
  289. package/templates/make/component/manifest.json +9 -0
  290. package/templates/make/data/files/{{MAKE_NAME}}.json +14 -0
  291. package/templates/make/data/manifest.json +9 -0
  292. package/templates/make/material/files/{{MAKE_NAME}}.material.json +17 -0
  293. package/templates/make/material/manifest.json +9 -0
  294. package/templates/make/prefab/files/{{MAKE_NAME}}.prefab.js +20 -0
  295. package/templates/make/prefab/manifest.json +9 -0
  296. package/templates/make/scene/files/{{MAKE_NAME}}.scene.js +31 -0
  297. package/templates/make/scene/manifest.json +9 -0
  298. package/templates/make/shader/files/{{MAKE_NAME}}.shader.js +23 -0
  299. package/templates/make/shader/manifest.json +9 -0
  300. package/templates/make/system/files/{{MAKE_NAME}}.system.js +15 -0
  301. package/templates/make/system/manifest.json +9 -0
  302. package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.js +16 -0
  303. package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.json +23 -0
  304. package/templates/make/ui-screen/manifest.json +10 -0
  305. package/templates/make-starters/deckbuilder-2d/card/files/{{MAKE_NAME}}.card.js +22 -0
  306. package/templates/make-starters/deckbuilder-2d/card/manifest.json +9 -0
  307. package/templates/make-starters/deckbuilder-2d/catalog.json +34 -0
  308. package/templates/make-starters/deckbuilder-2d/encounter/files/{{MAKE_NAME}}.encounter.js +18 -0
  309. package/templates/make-starters/deckbuilder-2d/encounter/manifest.json +9 -0
  310. package/templates/make-starters/deckbuilder-2d/enemy/files/{{MAKE_NAME}}.enemy.js +28 -0
  311. package/templates/make-starters/deckbuilder-2d/enemy/manifest.json +9 -0
  312. package/templates/make-starters/deckbuilder-2d/relic/files/{{MAKE_NAME}}.relic.js +23 -0
  313. package/templates/make-starters/deckbuilder-2d/relic/manifest.json +9 -0
  314. package/templates/retro/platformer/README.md +10 -0
  315. package/templates/retro/platformer/assets/retro/assets.json +91 -0
  316. package/templates/retro/platformer/aura.config.json +7 -0
  317. package/templates/retro/platformer/package.json +5 -0
  318. package/templates/retro/platformer/src/main.js +40 -0
  319. package/templates/retro/puzzle-grid/README.md +10 -0
  320. package/templates/retro/puzzle-grid/assets/retro/assets.json +90 -0
  321. package/templates/retro/puzzle-grid/aura.config.json +7 -0
  322. package/templates/retro/puzzle-grid/package.json +5 -0
  323. package/templates/retro/puzzle-grid/src/main.js +29 -0
  324. package/templates/retro/tactics-grid/README.md +10 -0
  325. package/templates/retro/tactics-grid/assets/retro/assets.json +90 -0
  326. package/templates/retro/tactics-grid/aura.config.json +7 -0
  327. package/templates/retro/tactics-grid/package.json +5 -0
  328. package/templates/retro/tactics-grid/src/main.js +35 -0
  329. package/templates/retro/topdown-adventure/README.md +10 -0
  330. package/templates/retro/topdown-adventure/assets/retro/assets.json +95 -0
  331. package/templates/retro/topdown-adventure/aura.config.json +7 -0
  332. package/templates/retro/topdown-adventure/package.json +5 -0
  333. package/templates/retro/topdown-adventure/src/main.js +29 -0
  334. package/templates/skills/aurajs/SKILL.md +61 -5
@@ -19,6 +19,9 @@ export function prepareDevStateRestoreEntry({
19
19
  projectRoot: resolvedProjectRoot,
20
20
  kind: artifactKind,
21
21
  name: artifactName,
22
+ exportDefaults: {
23
+ mode: 'native',
24
+ },
22
25
  });
23
26
 
24
27
  if (artifact.envelope.stateSchemaVersion !== GAME_STATE_SCHEMA_VERSION) {
@@ -54,14 +57,82 @@ export function prepareDevStateRestoreEntry({
54
57
  };
55
58
  }
56
59
 
60
+ export function prepareDevStateRestorePayloadEntry({
61
+ projectRoot,
62
+ entryFile,
63
+ payload,
64
+ reasonCode = 'dev_live_state_restore',
65
+ label = 'live',
66
+ }) {
67
+ const resolvedProjectRoot = resolve(projectRoot || process.cwd());
68
+ const resolvedEntryFile = resolve(resolvedProjectRoot, entryFile || 'src/main.js');
69
+ if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
70
+ throw new Error('Live dev-state restore payload must be an object.');
71
+ }
72
+ if (payload.schemaVersion !== GAME_STATE_SCHEMA_VERSION) {
73
+ throw new Error(
74
+ `Live dev-state restore payload uses schema "${payload.schemaVersion}", expected "${GAME_STATE_SCHEMA_VERSION}".`,
75
+ );
76
+ }
77
+
78
+ const generatedDir = resolve(resolvedProjectRoot, 'src', '.aurajs-generated');
79
+ mkdirSync(generatedDir, { recursive: true });
80
+
81
+ const safeLabel = String(label || 'live')
82
+ .trim()
83
+ .replace(/[^a-zA-Z0-9._-]+/g, '-')
84
+ .replace(/-+/g, '-')
85
+ .replace(/^[-._]+|[-._]+$/g, '')
86
+ .slice(0, 48) || 'live';
87
+ const generatedFile = resolve(generatedDir, `dev-state-restore-${safeLabel}.js`);
88
+ const relativeImport = normalizeImportSpecifier(dirname(generatedFile), resolvedEntryFile);
89
+ const wrapperSource = buildDevStateRestoreWrapperSource({
90
+ entryImport: relativeImport,
91
+ payload,
92
+ artifact: {
93
+ kind: 'live-session',
94
+ artifactVersion: null,
95
+ name: safeLabel,
96
+ path: relative(resolvedProjectRoot, generatedFile).split(sep).join('/'),
97
+ stateSchemaVersion: GAME_STATE_SCHEMA_VERSION,
98
+ payloadFingerprint: payload?.export?.fingerprint || null,
99
+ migration: null,
100
+ reasonCode,
101
+ },
102
+ });
103
+
104
+ const previous = tryReadFile(generatedFile);
105
+ if (previous !== wrapperSource) {
106
+ writeFileSync(generatedFile, wrapperSource, 'utf8');
107
+ }
108
+
109
+ return {
110
+ entryFile: relative(resolvedProjectRoot, generatedFile).split(sep).join('/'),
111
+ wrapperPath: generatedFile,
112
+ artifact: {
113
+ kind: 'live-session',
114
+ artifactVersion: null,
115
+ name: safeLabel,
116
+ path: relative(resolvedProjectRoot, generatedFile).split(sep).join('/'),
117
+ stateSchemaVersion: GAME_STATE_SCHEMA_VERSION,
118
+ payloadFingerprint: payload?.export?.fingerprint || null,
119
+ migration: null,
120
+ reasonCode,
121
+ },
122
+ };
123
+ }
124
+
57
125
  export function buildDevStateRestoreWrapperSource({ entryImport, payload, artifact }) {
58
126
  const bootstrapSource = buildStateRestoreRuntimeBootstrapSource();
59
127
  const metadata = {
60
128
  kind: artifact.kind,
129
+ artifactVersion: artifact.artifactVersion ?? null,
61
130
  name: artifact.name,
62
131
  path: artifact.path,
63
132
  stateSchemaVersion: artifact.stateSchemaVersion,
64
133
  payloadFingerprint: artifact.payloadFingerprint,
134
+ migration: artifact.migration || null,
135
+ reasonCode: artifact.reasonCode || null,
65
136
  };
66
137
 
67
138
  return [
@@ -76,26 +147,52 @@ export function buildDevStateRestoreWrapperSource({ entryImport, payload, artifa
76
147
  ' if (!stateNs || typeof stateNs.apply !== "function") {',
77
148
  ' throw new Error("[aurajs] dev restore failed: aura.state.apply is unavailable");',
78
149
  ' }',
150
+ ' if (aura && typeof aura === "object") {',
151
+ ' aura.__aurajsPendingDevRestore = { ...__aurajsRestoreMeta };',
152
+ ' }',
79
153
  ' const result = stateNs.apply(__aurajsRestorePayload);',
80
154
  ' if (!result || result.ok !== true) {',
81
155
  ' const reasonCode = result && typeof result.reasonCode === "string"',
82
156
  ' ? result.reasonCode',
83
157
  ' : "state_apply_failed";',
158
+ ' if (aura && typeof aura === "object") {',
159
+ ' aura.__aurajsDevRestore = {',
160
+ ' kind: __aurajsRestoreMeta.kind,',
161
+ ' artifactVersion: __aurajsRestoreMeta.artifactVersion || null,',
162
+ ' name: __aurajsRestoreMeta.name,',
163
+ ' path: __aurajsRestoreMeta.path,',
164
+ ' stateSchemaVersion: __aurajsRestoreMeta.stateSchemaVersion || null,',
165
+ ' reasonCode,',
166
+ ' detail: result && typeof result === "object" ? result.detail || null : null,',
167
+ ' payloadFingerprint: __aurajsRestoreMeta.payloadFingerprint || null,',
168
+ ' migration: __aurajsRestoreMeta.migration || null,',
169
+ ' continuity: result && typeof result === "object" ? result.continuity || null : null,',
170
+ ' ok: false,',
171
+ ' };',
172
+ ' delete aura.__aurajsPendingDevRestore;',
173
+ ' }',
84
174
  ' throw new Error(`[aurajs] dev restore failed (${__aurajsRestoreMeta.kind}:${__aurajsRestoreMeta.name}): ${reasonCode}`);',
85
175
  ' }',
86
- ' return result;',
87
- '}',
176
+ ' return result;',
177
+ '}',
88
178
  'aura.setup = function (...args) {',
89
179
  ' const setupResult = __aurajsOriginalSetup ? __aurajsOriginalSetup.apply(this, args) : undefined;',
90
180
  ' const restoreResult = __aurajsApplyRestorePayload();',
91
181
  ' if (aura && typeof aura === "object") {',
92
182
  ' aura.__aurajsDevRestore = {',
93
183
  ' kind: __aurajsRestoreMeta.kind,',
184
+ ' artifactVersion: __aurajsRestoreMeta.artifactVersion || null,',
94
185
  ' name: __aurajsRestoreMeta.name,',
95
186
  ' path: __aurajsRestoreMeta.path,',
187
+ ' stateSchemaVersion: __aurajsRestoreMeta.stateSchemaVersion || null,',
96
188
  ' reasonCode: restoreResult.reasonCode || null,',
189
+ ' detail: restoreResult.detail || null,',
97
190
  ' payloadFingerprint: __aurajsRestoreMeta.payloadFingerprint || null,',
191
+ ' migration: __aurajsRestoreMeta.migration || null,',
192
+ ' continuity: restoreResult.continuity || null,',
193
+ ' ok: restoreResult.ok === true,',
98
194
  ' };',
195
+ ' delete aura.__aurajsPendingDevRestore;',
99
196
  ' }',
100
197
  ' return setupResult;',
101
198
  '};',
@@ -0,0 +1,245 @@
1
+ import readline from 'node:readline';
2
+
3
+ const START_BANNER_QUOTES = [
4
+ 'ready to auramaxx and mog prompt peasants?',
5
+ 'you are perfect. never give up your aura',
6
+ 'why jestermaxx when you can auramaxx?',
7
+ 'lock tf in, the aura farm is live.',
8
+ 'we are so back. aura at all-time highs.',
9
+ 'negative motion detected. deploy tera-aura.',
10
+ 'delulu? no. pre-success manifestation engine.',
11
+ 'doomers offline, builders online.',
12
+ 'your aura just hit legendary rarity.',
13
+ 'brainrot but make it productive.',
14
+ 'stack wins, stack aura, stack peace.',
15
+ 'this session is sponsored by unstoppable motion.',
16
+ 'if plan A fails, we auramaxx harder.',
17
+ 'zero cope, pure glow-up execution.',
18
+ 'cooked? nah. we are perfectly seasoned.',
19
+ 'straight gas, no brakes, no bad vibes.',
20
+ 'today forecast: 100% chance of aura gains.',
21
+ 'touch grass, then auramaxx.',
22
+ 'say no to digital slops. say yes to auramaxx.',
23
+ 'if the world goes dark can i still auramaxx with you?',
24
+ 'its me, AI. you are absolutely right. i want to auramaxx as well.',
25
+ ];
26
+
27
+ export const ANSI = {
28
+ reset: '\x1b[0m',
29
+ bold: '\x1b[1m',
30
+ dim: '\x1b[2m',
31
+ italic: '\x1b[3m',
32
+ fgAccent: '\x1b[38;5;154m',
33
+ fgWhite: '\x1b[97m',
34
+ fgGray: '\x1b[90m',
35
+ };
36
+
37
+ const USE_COLOR = process.stdout.isTTY
38
+ && !process.env.NO_COLOR
39
+ && process.env.CI !== 'true'
40
+ && process.env.TERM !== 'dumb';
41
+ const BANNER_WIDTH = 62;
42
+
43
+ function wrapText(text, width) {
44
+ if (text.length <= width) return [text];
45
+ const words = text.split(/\s+/).filter(Boolean);
46
+ if (words.length === 0) return [''];
47
+ const lines = [];
48
+ let line = '';
49
+ for (const word of words) {
50
+ const next = line ? `${line} ${word}` : word;
51
+ if (next.length <= width) {
52
+ line = next;
53
+ continue;
54
+ }
55
+ if (line) lines.push(line);
56
+ if (word.length <= width) {
57
+ line = word;
58
+ continue;
59
+ }
60
+ for (let index = 0; index < word.length; index += width) {
61
+ lines.push(word.slice(index, index + width));
62
+ }
63
+ line = '';
64
+ }
65
+ if (line) lines.push(line);
66
+ return lines;
67
+ }
68
+
69
+ function getBannerQuote() {
70
+ const forced = process.env.AURA_START_BANNER_QUOTE_INDEX;
71
+ if (forced) {
72
+ const forcedIndex = Number.parseInt(forced, 10);
73
+ if (Number.isFinite(forcedIndex)) {
74
+ return START_BANNER_QUOTES[Math.abs(forcedIndex) % START_BANNER_QUOTES.length];
75
+ }
76
+ }
77
+ return START_BANNER_QUOTES[Math.floor(Math.random() * START_BANNER_QUOTES.length)];
78
+ }
79
+
80
+ export function paint(text, ...codes) {
81
+ if (!USE_COLOR) return text;
82
+ return `${codes.join('')}${text}${ANSI.reset}`;
83
+ }
84
+
85
+ export function canPromptInteractively() {
86
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY && typeof process.stdin.setRawMode === 'function');
87
+ }
88
+
89
+ export function printBanner(subtitle = '') {
90
+ const sub = String(subtitle || '').trim().toUpperCase();
91
+ const pipe = paint('|', ANSI.fgGray);
92
+ const logoPipe = paint('|', ANSI.fgGray);
93
+ const stripe = (value) => paint(value, ANSI.bold);
94
+ const logoTop = paint('.', ANSI.fgGray) + paint('----------', ANSI.dim) + paint('.', ANSI.fgGray);
95
+ const logoBottom = paint("'", ANSI.fgGray) + paint('----------', ANSI.dim) + paint("'", ANSI.fgGray);
96
+
97
+ console.log('');
98
+ console.log(` ${paint('.-', ANSI.fgGray)}${paint(' '.repeat(BANNER_WIDTH - 4), ANSI.dim)}${paint('-.', ANSI.fgGray)}`);
99
+ console.log(` ${pipe} ${logoTop}${' '.repeat(BANNER_WIDTH - 19)}${pipe}`);
100
+ console.log(` ${pipe} ${logoPipe}${stripe('\\\\')} ${stripe('\\\\')} ${stripe('\\\\')}${logoPipe} ${paint('A U R A', ANSI.bold)}${' '.repeat(BANNER_WIDTH - 30)}${pipe}`);
101
+ console.log(` ${pipe} ${logoPipe}${stripe('\\\\')} ${stripe('\\\\')} ${stripe('\\\\')}${logoPipe} ${paint('A U R A J S', ANSI.dim)}${' '.repeat(BANNER_WIDTH - 35)}${pipe}`);
102
+ console.log(` ${pipe} ${logoPipe}${stripe('\\\\')} ${stripe('\\\\')} ${stripe('\\\\')}${logoPipe} ${sub ? paint(sub, ANSI.fgAccent) : ''}${' '.repeat(Math.max(0, BANNER_WIDTH - 23 - sub.length))}${pipe}`);
103
+ console.log(` ${pipe} ${logoBottom}${' '.repeat(BANNER_WIDTH - 19)}${pipe}`);
104
+ console.log(` ${paint("'-", ANSI.fgGray)}${paint(' '.repeat(BANNER_WIDTH - 4), ANSI.dim)}${paint("-'", ANSI.fgGray)}`);
105
+ for (const line of wrapText(getBannerQuote(), BANNER_WIDTH - 2)) {
106
+ console.log(` ${paint(line, ANSI.fgWhite, ANSI.italic)}`);
107
+ }
108
+ console.log('');
109
+ }
110
+
111
+ export function printSection(title, subtitle = '') {
112
+ console.log('');
113
+ console.log(` ${'- '.repeat(Math.floor(BANNER_WIDTH / 2))}`);
114
+ console.log(` ${paint(`[ ${String(title || '').toUpperCase()} ]`, ANSI.bold)}`);
115
+ if (subtitle) {
116
+ console.log(` ${paint(subtitle, ANSI.dim)}`);
117
+ }
118
+ console.log('');
119
+ }
120
+
121
+ function renderSelectLines(message, options, selectedIndex, defaultValue) {
122
+ const lines = [
123
+ message,
124
+ paint(' Use up/down arrows and Enter to confirm.', ANSI.dim),
125
+ ];
126
+
127
+ for (let index = 0; index < options.length; index += 1) {
128
+ const option = options[index];
129
+ const suffix = defaultValue === option.value ? ' [default]' : '';
130
+ if (index === selectedIndex) {
131
+ lines.push(` ${paint('//', ANSI.fgAccent, ANSI.bold)} ${paint(option.label + suffix, ANSI.bold)}`);
132
+ } else {
133
+ lines.push(` ${paint(option.label + suffix, ANSI.dim)}`);
134
+ }
135
+ }
136
+
137
+ return lines;
138
+ }
139
+
140
+ export async function promptSelect(message, options, defaultValue) {
141
+ if (!Array.isArray(options) || options.length === 0) {
142
+ throw new Error('promptSelect requires at least one option.');
143
+ }
144
+ if (!canPromptInteractively()) {
145
+ return defaultValue || options[0].value;
146
+ }
147
+
148
+ return new Promise((resolvePrompt, rejectPrompt) => {
149
+ const stdin = process.stdin;
150
+ const stdout = process.stdout;
151
+ const defaultIndex = Math.max(0, options.findIndex((option) => option.value === defaultValue));
152
+ const previousRawMode = stdin.isRaw ?? false;
153
+ let selectedIndex = defaultIndex;
154
+ let renderedLines = 0;
155
+ let settled = false;
156
+
157
+ const cleanup = () => {
158
+ if (settled) return;
159
+ settled = true;
160
+ stdin.removeListener('data', onData);
161
+ stdin.removeListener('error', onError);
162
+ if (stdin.isTTY && typeof stdin.setRawMode === 'function') {
163
+ stdin.setRawMode(previousRawMode);
164
+ }
165
+ stdin.pause();
166
+ };
167
+
168
+ const render = () => {
169
+ const lines = renderSelectLines(message, options, selectedIndex, defaultValue);
170
+ if (renderedLines > 0) {
171
+ stdout.write(`\u001b[${renderedLines}A`);
172
+ }
173
+ for (const line of lines) {
174
+ stdout.write('\u001b[2K');
175
+ stdout.write(`${line}\n`);
176
+ }
177
+ renderedLines = lines.length;
178
+ };
179
+
180
+ const onError = (error) => {
181
+ cleanup();
182
+ rejectPrompt(error);
183
+ };
184
+
185
+ const onData = (chunk) => {
186
+ const input = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
187
+ let delta = 0;
188
+
189
+ for (let index = 0; index < input.length; index += 1) {
190
+ const char = input[index];
191
+ if (char === '\u0003') {
192
+ cleanup();
193
+ stdout.write('\n');
194
+ process.exit(1);
195
+ }
196
+ if (char === '\r' || char === '\n') {
197
+ cleanup();
198
+ stdout.write('\n');
199
+ resolvePrompt(options[selectedIndex].value);
200
+ return;
201
+ }
202
+ if (input.startsWith('\u001b[A', index)) {
203
+ delta -= 1;
204
+ index += 2;
205
+ continue;
206
+ }
207
+ if (input.startsWith('\u001b[B', index)) {
208
+ delta += 1;
209
+ index += 2;
210
+ continue;
211
+ }
212
+ }
213
+
214
+ if (delta !== 0) {
215
+ selectedIndex = (selectedIndex + delta + options.length) % options.length;
216
+ render();
217
+ }
218
+ };
219
+
220
+ try {
221
+ if (stdin.isTTY && typeof stdin.setRawMode === 'function') {
222
+ stdin.setRawMode(true);
223
+ }
224
+ stdin.resume();
225
+ stdin.on('data', onData);
226
+ stdin.on('error', onError);
227
+ render();
228
+ } catch (error) {
229
+ onError(error);
230
+ }
231
+ });
232
+ }
233
+
234
+ export async function promptInput(label) {
235
+ return new Promise((resolve) => {
236
+ const rl = readline.createInterface({
237
+ input: process.stdin,
238
+ output: process.stdout,
239
+ });
240
+ rl.question(`${label}: `, (answer) => {
241
+ rl.close();
242
+ resolve(String(answer || '').trim());
243
+ });
244
+ });
245
+ }
@@ -0,0 +1,219 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { mkdirSync, writeFileSync } from 'node:fs';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const repoRoot = resolve(fileURLToPath(new URL('../../../../..', import.meta.url)));
7
+ const DEFAULT_TEST_FILE = './packages/aurascript/src/cli/test/build-contract.test.mjs';
8
+
9
+ export const DEFAULT_WEB_SMOKE_CASES = Object.freeze([
10
+ Object.freeze({
11
+ id: 'web-supported-browser-surface-2d',
12
+ bucket: 'supported',
13
+ expectation: 'supported',
14
+ title: 'browser loader installs the committed 2d surface',
15
+ file: DEFAULT_TEST_FILE,
16
+ testName: 'web loader installs browser-backed aura surface for 2d examples',
17
+ examples: [],
18
+ }),
19
+ Object.freeze({
20
+ id: 'web-supported-render-2d-proof-example',
21
+ bucket: 'supported',
22
+ expectation: 'supported',
23
+ title: 'web-render-2d-proof runs on the committed advanced draw2d browser floor',
24
+ file: DEFAULT_TEST_FILE,
25
+ testName: 'web loader browser smoke: web-render-2d-proof runs on the committed advanced draw2d browser floor',
26
+ examples: ['examples/web-render-2d-proof'],
27
+ }),
28
+ Object.freeze({
29
+ id: 'web-partial-pokemon-style-example',
30
+ bucket: 'partial',
31
+ expectation: 'partial',
32
+ title: 'pokemon-style runs on the current browser-backed subset',
33
+ file: DEFAULT_TEST_FILE,
34
+ testName: 'web loader browser smoke: pokemon-style runs on the supported 2d subset with input and resize evidence',
35
+ examples: ['examples/pokemon-style'],
36
+ }),
37
+ Object.freeze({
38
+ id: 'web-supported-starter-3d-example',
39
+ bucket: 'supported',
40
+ expectation: 'supported',
41
+ title: 'starter-3d runs on the committed browser 3d floor',
42
+ file: DEFAULT_TEST_FILE,
43
+ testName: 'web loader browser smoke: starter-3d runs on the committed browser 3d floor',
44
+ examples: ['examples/starter-3d'],
45
+ }),
46
+ Object.freeze({
47
+ id: 'web-unsupported-multiplayer-examples',
48
+ bucket: 'unsupported',
49
+ expectation: 'unsupported',
50
+ title: 'multiplayer examples fail before setup with stable capability diagnostics',
51
+ file: DEFAULT_TEST_FILE,
52
+ testName: 'web loader browser smoke: multiplayer examples fail before setup with stable capability diagnostics',
53
+ examples: ['examples/multiplayer-room-client', 'examples/multiplayer-room-host'],
54
+ }),
55
+ Object.freeze({
56
+ id: 'web-unsupported-advanced-3d-example',
57
+ bucket: 'unsupported',
58
+ expectation: 'unsupported',
59
+ title: 'advanced 3d examples outside the committed browser floor fail before setup with stable capability diagnostics',
60
+ file: DEFAULT_TEST_FILE,
61
+ testName: 'web loader browser smoke: advanced 3d examples still fail before setup with stable capability diagnostics',
62
+ examples: ['examples/custom-shader-material-proof'],
63
+ }),
64
+ ]);
65
+
66
+ export class WebConformanceSuiteError extends Error {
67
+ constructor(message, details = {}) {
68
+ super(message);
69
+ this.name = 'WebConformanceSuiteError';
70
+ this.details = details;
71
+ }
72
+ }
73
+
74
+ function escapeRegExp(value) {
75
+ return String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
76
+ }
77
+
78
+ function tailLines(value, maxLines = 20) {
79
+ const text = String(value || '').trim();
80
+ if (!text) return '';
81
+ return text.split(/\r?\n/).slice(-maxLines).join('\n');
82
+ }
83
+
84
+ function summarizeBucket(cases, bucket) {
85
+ const matches = cases.filter((entry) => entry.bucket === bucket);
86
+ return {
87
+ total: matches.length,
88
+ passed: matches.filter((entry) => entry.status === 'passed').length,
89
+ failed: matches.filter((entry) => entry.status === 'failed').length,
90
+ };
91
+ }
92
+
93
+ async function runWebSmokeCase({ cwd, caseDef }) {
94
+ const args = [
95
+ '--test',
96
+ '--test-name-pattern',
97
+ `^${escapeRegExp(caseDef.testName)}$`,
98
+ caseDef.file,
99
+ ];
100
+
101
+ return new Promise((resolvePromise, rejectPromise) => {
102
+ const child = spawn(process.execPath, args, {
103
+ cwd,
104
+ env: process.env,
105
+ stdio: ['ignore', 'pipe', 'pipe'],
106
+ });
107
+
108
+ let stdout = '';
109
+ let stderr = '';
110
+
111
+ child.stdout.setEncoding('utf8');
112
+ child.stderr.setEncoding('utf8');
113
+ child.stdout.on('data', (chunk) => {
114
+ stdout += chunk;
115
+ });
116
+ child.stderr.on('data', (chunk) => {
117
+ stderr += chunk;
118
+ });
119
+
120
+ child.on('error', (error) => {
121
+ rejectPromise(error);
122
+ });
123
+
124
+ child.on('close', (code, signal) => {
125
+ resolvePromise({
126
+ code: Number.isInteger(code) ? code : 1,
127
+ signal: signal || null,
128
+ stdout,
129
+ stderr,
130
+ });
131
+ });
132
+ });
133
+ }
134
+
135
+ export async function runWebConformanceSuite(options = {}) {
136
+ const startedAt = Date.now();
137
+ const cwd = resolve(options.cwd || repoRoot);
138
+ const reportPath = resolve(options.reportPath || cwd, '.aura/web-conformance/report.json');
139
+ const cases = Array.isArray(options.cases) && options.cases.length > 0
140
+ ? options.cases
141
+ : DEFAULT_WEB_SMOKE_CASES;
142
+ const runner = typeof options.runner === 'function' ? options.runner : runWebSmokeCase;
143
+ const results = [];
144
+
145
+ mkdirSync(dirname(reportPath), { recursive: true });
146
+
147
+ for (const caseDef of cases) {
148
+ const caseStartedAt = Date.now();
149
+ const execution = await runner({ cwd, caseDef });
150
+ const durationMs = Date.now() - caseStartedAt;
151
+ const passed = execution.code === 0;
152
+
153
+ results.push({
154
+ id: caseDef.id,
155
+ title: caseDef.title,
156
+ bucket: caseDef.bucket,
157
+ expectation: caseDef.expectation,
158
+ file: caseDef.file,
159
+ testName: caseDef.testName,
160
+ examples: Array.isArray(caseDef.examples) ? caseDef.examples : [],
161
+ status: passed ? 'passed' : 'failed',
162
+ durationMs,
163
+ stdoutTail: tailLines(execution.stdout),
164
+ stderrTail: tailLines(execution.stderr),
165
+ error: passed
166
+ ? null
167
+ : {
168
+ message: `Web smoke case failed: ${caseDef.id}`,
169
+ exitCode: execution.code,
170
+ signal: execution.signal,
171
+ },
172
+ });
173
+ }
174
+
175
+ const durationMs = Date.now() - startedAt;
176
+ const summary = {
177
+ total: results.length,
178
+ passed: results.filter((entry) => entry.status === 'passed').length,
179
+ failed: results.filter((entry) => entry.status === 'failed').length,
180
+ durationMs,
181
+ byMode: {
182
+ web: {
183
+ total: results.length,
184
+ passed: results.filter((entry) => entry.status === 'passed').length,
185
+ failed: results.filter((entry) => entry.status === 'failed').length,
186
+ durationMs,
187
+ },
188
+ },
189
+ byBucket: {
190
+ supported: summarizeBucket(results, 'supported'),
191
+ partial: summarizeBucket(results, 'partial'),
192
+ unsupported: summarizeBucket(results, 'unsupported'),
193
+ },
194
+ };
195
+
196
+ const report = {
197
+ schemaVersion: 'aurajs.web-conformance-report.v1',
198
+ generatedAt: new Date().toISOString(),
199
+ mode: 'web',
200
+ cwd,
201
+ reportPath,
202
+ summary,
203
+ cases: results,
204
+ };
205
+
206
+ writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
207
+
208
+ if (summary.failed > 0) {
209
+ throw new WebConformanceSuiteError(
210
+ `Web conformance failed for ${summary.failed}/${summary.total} browser smoke cases.`,
211
+ {
212
+ reportPath,
213
+ failedCases: results.filter((entry) => entry.status === 'failed'),
214
+ },
215
+ );
216
+ }
217
+
218
+ return report;
219
+ }
@@ -0,0 +1,26 @@
1
+ export const SHOOTER_CONFIG = Object.freeze({
2
+ playerWidth: 34,
3
+ playerHeight: 26,
4
+ playerSpeed: 420,
5
+ bulletWidth: 6,
6
+ bulletHeight: 14,
7
+ bulletSpeed: 640,
8
+ shootCooldownSeconds: 0.14,
9
+ playerStartOffsetY: 70,
10
+ betweenWaveDelaySeconds: 1.0,
11
+ });
12
+
13
+ export const SHOOTER_WAVES = Object.freeze([
14
+ Object.freeze({ maxSpawns: 9, spawnEvery: 0.62, archetype: 'scout', speedScale: 1.0 }),
15
+ Object.freeze({ maxSpawns: 10, spawnEvery: 0.56, archetype: 'striker', speedScale: 1.06 }),
16
+ Object.freeze({ maxSpawns: 8, spawnEvery: 0.74, archetype: 'tank', speedScale: 1.02 }),
17
+ Object.freeze({ maxSpawns: 12, spawnEvery: 0.48, archetype: null, speedScale: 1.12 }),
18
+ ]);
19
+
20
+ export const SHOOTER_TEXT = Object.freeze({
21
+ started: '{{PROJECT_TITLE}} started (2D shooter template)',
22
+ controls: 'Move: Arrows/WASD Fire: Space/Z',
23
+ gameOverTitle: 'GAME OVER',
24
+ gameOverPrompt: 'Press Enter to restart',
25
+ waveDone: 'Done',
26
+ });
@@ -0,0 +1,26 @@
1
+ {
2
+ "schema": "aurajs.wave-plan.v1",
3
+ "waves": [
4
+ {
5
+ "id": "intro",
6
+ "maxSpawns": 9,
7
+ "spawnEvery": 0.62,
8
+ "archetype": "scout",
9
+ "speedScale": 1
10
+ },
11
+ {
12
+ "id": "pressure",
13
+ "maxSpawns": 10,
14
+ "spawnEvery": 0.56,
15
+ "archetype": "striker",
16
+ "speedScale": 1.06
17
+ },
18
+ {
19
+ "id": "anchor",
20
+ "maxSpawns": 8,
21
+ "spawnEvery": 0.74,
22
+ "archetype": "tank",
23
+ "speedScale": 1.02
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,5 @@
1
+ # 2D Shooter Loop
2
+
3
+ 1. Survive the wave set, clear the arena, and keep the score-and-lives loop readable.
4
+ 1. Keep tuning in `config/gameplay/shooter.config.js`, authored wave payloads in `content/gameplay/waves.json`, and reusable combat pieces in `prefabs/`.
5
+ 1. Extend from here with enemy families, weapon rules, and HUD beats before layering on heavier meta systems.