@the-inclusionist/engine 9.0.0 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (532) hide show
  1. package/README.md +120 -78
  2. package/app/css/style.css +761 -377
  3. package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
  4. package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
  5. package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
  6. package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
  7. package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
  8. package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
  9. package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
  10. package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
  11. package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
  12. package/app/public/vendor/fonts.css +36 -84
  13. package/dist-pkg/boot/create-game.d.ts +499 -219
  14. package/dist-pkg/boot/create-game.js +3944 -562
  15. package/dist-pkg/core/a11y-sr.d.ts +25 -3
  16. package/dist-pkg/core/a11y-sr.js +38 -19
  17. package/dist-pkg/core/accessible-label.d.ts +17 -0
  18. package/dist-pkg/core/accessible-label.js +37 -0
  19. package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
  20. package/dist-pkg/core/accommodation-subjects.js +32 -0
  21. package/dist-pkg/core/accommodations.d.ts +125 -0
  22. package/dist-pkg/core/accommodations.js +195 -0
  23. package/dist-pkg/core/actions.d.ts +108 -55
  24. package/dist-pkg/core/actions.js +122 -71
  25. package/dist-pkg/core/calm-mode.d.ts +31 -0
  26. package/dist-pkg/core/calm-mode.js +47 -0
  27. package/dist-pkg/core/camera-cycle.d.ts +15 -0
  28. package/dist-pkg/core/camera-cycle.js +7 -0
  29. package/dist-pkg/core/caption-duration.d.ts +15 -0
  30. package/dist-pkg/core/caption-duration.js +19 -0
  31. package/dist-pkg/core/cartridge-problems.d.ts +34 -0
  32. package/dist-pkg/core/cartridge-problems.js +53 -0
  33. package/dist-pkg/core/constants.d.ts +0 -54
  34. package/dist-pkg/core/constants.js +9 -76
  35. package/dist-pkg/core/contract.d.ts +142 -164
  36. package/dist-pkg/core/contract.js +222 -208
  37. package/dist-pkg/core/dom-query.d.ts +4 -4
  38. package/dist-pkg/core/dom-query.js +12 -20
  39. package/dist-pkg/core/entity.d.ts +62 -77
  40. package/dist-pkg/core/entity.js +18 -32
  41. package/dist-pkg/core/escape-html.d.ts +9 -10
  42. package/dist-pkg/core/escape-html.js +16 -20
  43. package/dist-pkg/core/flash-threshold.d.ts +17 -0
  44. package/dist-pkg/core/flash-threshold.js +113 -0
  45. package/dist-pkg/core/game-speed.d.ts +11 -0
  46. package/dist-pkg/core/game-speed.js +16 -0
  47. package/dist-pkg/core/genres.d.ts +20 -0
  48. package/dist-pkg/core/genres.js +44 -0
  49. package/dist-pkg/core/i18n.d.ts +71 -60
  50. package/dist-pkg/core/i18n.js +186 -200
  51. package/dist-pkg/core/loop.d.ts +17 -6
  52. package/dist-pkg/core/loop.js +26 -26
  53. package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
  54. package/dist-pkg/core/pause-icon-catalogue.js +54 -0
  55. package/dist-pkg/core/ring.d.ts +17 -0
  56. package/dist-pkg/core/ring.js +29 -0
  57. package/dist-pkg/core/rng.d.ts +7 -12
  58. package/dist-pkg/core/rng.js +23 -53
  59. package/dist-pkg/core/route.d.ts +26 -26
  60. package/dist-pkg/core/route.js +126 -121
  61. package/dist-pkg/core/scenes.d.ts +37 -40
  62. package/dist-pkg/core/scenes.js +41 -43
  63. package/dist-pkg/core/screens.d.ts +4 -4
  64. package/dist-pkg/core/screens.js +11 -16
  65. package/dist-pkg/core/session-clock.d.ts +23 -0
  66. package/dist-pkg/core/session-clock.js +37 -0
  67. package/dist-pkg/core/setting-defaults.d.ts +61 -0
  68. package/dist-pkg/core/setting-defaults.js +66 -0
  69. package/dist-pkg/core/speech-rate.d.ts +29 -0
  70. package/dist-pkg/core/speech-rate.js +47 -0
  71. package/dist-pkg/core/state.d.ts +118 -118
  72. package/dist-pkg/core/state.js +322 -297
  73. package/dist-pkg/core/visual-cycles.d.ts +30 -0
  74. package/dist-pkg/core/visual-cycles.js +52 -0
  75. package/dist-pkg/core/visual-state.d.ts +13 -0
  76. package/dist-pkg/core/visual-state.js +6 -0
  77. package/dist-pkg/educational/activities-registry.d.ts +1 -1
  78. package/dist-pkg/educational/activities-registry.js +9 -8
  79. package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
  80. package/dist-pkg/educational/adaptive-engine.js +17 -17
  81. package/dist-pkg/educational/segment-bar.d.ts +12 -12
  82. package/dist-pkg/educational/segment-bar.js +9 -9
  83. package/dist-pkg/i18n/en.js +324 -223
  84. package/dist-pkg/i18n/es.js +323 -223
  85. package/dist-pkg/i18n/pt.js +348 -226
  86. package/dist-pkg/input/default-bindings.d.ts +37 -38
  87. package/dist-pkg/input/default-bindings.js +127 -144
  88. package/dist-pkg/input/devices.d.ts +7 -7
  89. package/dist-pkg/input/devices.js +17 -16
  90. package/dist-pkg/input/edges.d.ts +23 -32
  91. package/dist-pkg/input/edges.js +23 -28
  92. package/dist-pkg/input/empathy-filter.d.ts +22 -0
  93. package/dist-pkg/input/empathy-filter.js +34 -0
  94. package/dist-pkg/input/face-map.d.ts +96 -0
  95. package/dist-pkg/input/face-map.js +255 -0
  96. package/dist-pkg/input/face-signals.d.ts +40 -0
  97. package/dist-pkg/input/face-signals.js +48 -0
  98. package/dist-pkg/input/gamepad.d.ts +195 -145
  99. package/dist-pkg/input/gamepad.js +383 -556
  100. package/dist-pkg/input/gaze-cycle.d.ts +64 -0
  101. package/dist-pkg/input/gaze-cycle.js +133 -0
  102. package/dist-pkg/input/gaze-relative.d.ts +68 -0
  103. package/dist-pkg/input/gaze-relative.js +142 -0
  104. package/dist-pkg/input/hand-map.d.ts +28 -0
  105. package/dist-pkg/input/hand-map.js +142 -0
  106. package/dist-pkg/input/input-cooldown.d.ts +17 -0
  107. package/dist-pkg/input/input-cooldown.js +39 -0
  108. package/dist-pkg/input/key-default.d.ts +30 -0
  109. package/dist-pkg/input/key-default.js +60 -0
  110. package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
  111. package/dist-pkg/input/keyboard-runtime.js +23 -27
  112. package/dist-pkg/input/keyboard.d.ts +68 -63
  113. package/dist-pkg/input/keyboard.js +83 -105
  114. package/dist-pkg/input/keydown.d.ts +123 -137
  115. package/dist-pkg/input/keydown.js +284 -289
  116. package/dist-pkg/input/latch-edge.d.ts +33 -21
  117. package/dist-pkg/input/latch-edge.js +34 -35
  118. package/dist-pkg/input/latch-scope.d.ts +51 -50
  119. package/dist-pkg/input/latch-scope.js +61 -82
  120. package/dist-pkg/input/latch-store.d.ts +26 -30
  121. package/dist-pkg/input/latch-store.js +42 -50
  122. package/dist-pkg/input/latch-sync.d.ts +29 -29
  123. package/dist-pkg/input/latch-sync.js +25 -25
  124. package/dist-pkg/input/latch.d.ts +14 -17
  125. package/dist-pkg/input/latch.js +29 -37
  126. package/dist-pkg/input/pad-defaults.d.ts +13 -16
  127. package/dist-pkg/input/pad-defaults.js +21 -28
  128. package/dist-pkg/input/pad-reading.d.ts +76 -0
  129. package/dist-pkg/input/pad-reading.js +169 -0
  130. package/dist-pkg/input/pad-wizard.d.ts +99 -0
  131. package/dist-pkg/input/pad-wizard.js +256 -0
  132. package/dist-pkg/input/pointer-space.d.ts +19 -20
  133. package/dist-pkg/input/pointer-space.js +27 -32
  134. package/dist-pkg/input/pointer.d.ts +39 -40
  135. package/dist-pkg/input/pointer.js +42 -45
  136. package/dist-pkg/input/state.d.ts +101 -89
  137. package/dist-pkg/input/state.js +54 -134
  138. package/dist-pkg/input/switch-scan.d.ts +59 -0
  139. package/dist-pkg/input/switch-scan.js +67 -0
  140. package/dist-pkg/input/synthetic-source.d.ts +42 -0
  141. package/dist-pkg/input/synthetic-source.js +57 -0
  142. package/dist-pkg/input/touch-bindings.d.ts +127 -116
  143. package/dist-pkg/input/touch-bindings.js +158 -173
  144. package/dist-pkg/input/touch.d.ts +147 -72
  145. package/dist-pkg/input/touch.js +362 -126
  146. package/dist-pkg/input/transport-in-use.d.ts +107 -0
  147. package/dist-pkg/input/transport-in-use.js +130 -0
  148. package/dist-pkg/input/transports.d.ts +90 -117
  149. package/dist-pkg/input/transports.js +104 -106
  150. package/dist-pkg/input/virtual-controller.d.ts +82 -0
  151. package/dist-pkg/input/virtual-controller.js +69 -0
  152. package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
  153. package/dist-pkg/input/vocabulary-migration.js +80 -79
  154. package/dist-pkg/input/voice-map.d.ts +59 -0
  155. package/dist-pkg/input/voice-map.js +123 -0
  156. package/dist-pkg/platform/audio-ambient.d.ts +13 -2
  157. package/dist-pkg/platform/audio-ambient.js +14 -14
  158. package/dist-pkg/platform/audio-earcons.d.ts +20 -19
  159. package/dist-pkg/platform/audio-earcons.js +51 -42
  160. package/dist-pkg/platform/audio-jingles.js +9 -10
  161. package/dist-pkg/platform/audio-mixer.d.ts +14 -2
  162. package/dist-pkg/platform/audio-mixer.js +31 -39
  163. package/dist-pkg/platform/audio-sonar.d.ts +49 -152
  164. package/dist-pkg/platform/audio-sonar.js +124 -302
  165. package/dist-pkg/platform/audio.d.ts +62 -19
  166. package/dist-pkg/platform/audio.js +193 -168
  167. package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
  168. package/dist-pkg/platform/choose-by-voice.js +157 -0
  169. package/dist-pkg/platform/flash-sampler.d.ts +19 -0
  170. package/dist-pkg/platform/flash-sampler.js +79 -0
  171. package/dist-pkg/platform/font-library.d.ts +77 -0
  172. package/dist-pkg/platform/font-library.js +98 -0
  173. package/dist-pkg/platform/font-library.json +721 -0
  174. package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
  175. package/dist-pkg/platform/heavy-catalogue.js +256 -0
  176. package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
  177. package/dist-pkg/platform/heavy-mirror.js +73 -0
  178. package/dist-pkg/platform/heavy.d.ts +136 -0
  179. package/dist-pkg/platform/heavy.js +324 -0
  180. package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
  181. package/dist-pkg/platform/interruptible-speech.js +77 -54
  182. package/dist-pkg/platform/kokoro-port.d.ts +27 -0
  183. package/dist-pkg/platform/kokoro-port.js +50 -0
  184. package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
  185. package/dist-pkg/platform/kokoro-runtime.js +52 -0
  186. package/dist-pkg/platform/kokoro.d.ts +70 -0
  187. package/dist-pkg/platform/kokoro.js +133 -0
  188. package/dist-pkg/platform/listener-scope.d.ts +12 -0
  189. package/dist-pkg/platform/listener-scope.js +90 -0
  190. package/dist-pkg/platform/locale-host.d.ts +14 -0
  191. package/dist-pkg/platform/locale-host.js +45 -0
  192. package/dist-pkg/platform/microphone.d.ts +51 -0
  193. package/dist-pkg/platform/microphone.js +118 -0
  194. package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
  195. package/dist-pkg/platform/onnx-runtime.js +42 -0
  196. package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
  197. package/dist-pkg/platform/reading-in-worker.js +125 -0
  198. package/dist-pkg/platform/reading-model.d.ts +94 -0
  199. package/dist-pkg/platform/reading-model.js +272 -0
  200. package/dist-pkg/platform/reading-runtime.d.ts +24 -0
  201. package/dist-pkg/platform/reading-runtime.js +164 -0
  202. package/dist-pkg/platform/reading-worker.d.ts +41 -0
  203. package/dist-pkg/platform/reading-worker.js +58 -0
  204. package/dist-pkg/platform/reading.d.ts +80 -0
  205. package/dist-pkg/platform/reading.js +136 -0
  206. package/dist-pkg/platform/speech-recognition.d.ts +60 -0
  207. package/dist-pkg/platform/speech-recognition.js +104 -0
  208. package/dist-pkg/platform/speech.d.ts +23 -1
  209. package/dist-pkg/platform/speech.js +29 -18
  210. package/dist-pkg/platform/storage-keys.d.ts +96 -0
  211. package/dist-pkg/platform/storage-keys.js +106 -0
  212. package/dist-pkg/platform/storage.d.ts +46 -111
  213. package/dist-pkg/platform/storage.js +104 -169
  214. package/dist-pkg/platform/tts.d.ts +85 -39
  215. package/dist-pkg/platform/tts.js +447 -127
  216. package/dist-pkg/platform/vision-loop.d.ts +23 -0
  217. package/dist-pkg/platform/vision-loop.js +56 -0
  218. package/dist-pkg/platform/vision.d.ts +132 -0
  219. package/dist-pkg/platform/vision.js +117 -0
  220. package/dist-pkg/platform/voice-listener.d.ts +40 -0
  221. package/dist-pkg/platform/voice-listener.js +88 -0
  222. package/dist-pkg/platform/voice-plan.d.ts +15 -98
  223. package/dist-pkg/platform/voice-plan.js +56 -143
  224. package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
  225. package/dist-pkg/platform/vosk-runtime.js +151 -0
  226. package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
  227. package/dist-pkg/platform/vosk-vocabulary.js +178 -0
  228. package/dist-pkg/render/canvas.d.ts +13 -7
  229. package/dist-pkg/render/canvas.js +13 -13
  230. package/dist-pkg/render/crt.d.ts +48 -12
  231. package/dist-pkg/render/crt.js +78 -80
  232. package/dist-pkg/render/cvd-matrices.d.ts +22 -18
  233. package/dist-pkg/render/cvd-matrices.js +37 -38
  234. package/dist-pkg/render/hc-role-data.d.ts +7 -7
  235. package/dist-pkg/render/hc-role-data.js +14 -14
  236. package/dist-pkg/render/high-contrast.d.ts +67 -56
  237. package/dist-pkg/render/high-contrast.js +226 -217
  238. package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
  239. package/dist-pkg/render/low-vision-drawing.js +46 -0
  240. package/dist-pkg/render/lq-filter.d.ts +32 -20
  241. package/dist-pkg/render/lq-filter.js +59 -65
  242. package/dist-pkg/render/port.d.ts +86 -88
  243. package/dist-pkg/render/port.js +17 -23
  244. package/dist-pkg/render/screen-pipeline.d.ts +42 -42
  245. package/dist-pkg/render/screen-pipeline.js +80 -87
  246. package/dist-pkg/render/sprite-fx.d.ts +2 -1
  247. package/dist-pkg/render/sprite-fx.js +16 -14
  248. package/dist-pkg/render/viewports.d.ts +20 -15
  249. package/dist-pkg/render/viewports.js +83 -114
  250. package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
  251. package/dist-pkg/render/viz-axes-labels.js +88 -0
  252. package/dist-pkg/render/viz-axes.d.ts +89 -86
  253. package/dist-pkg/render/viz-axes.js +128 -116
  254. package/dist-pkg/render/viz-modes.d.ts +28 -29
  255. package/dist-pkg/render/viz-modes.js +40 -45
  256. package/dist-pkg/render/viz-refusal.d.ts +32 -0
  257. package/dist-pkg/render/viz-refusal.js +57 -0
  258. package/dist-pkg/render/viz-setters.d.ts +104 -66
  259. package/dist-pkg/render/viz-setters.js +182 -191
  260. package/dist-pkg/ui/aac-sets.d.ts +45 -0
  261. package/dist-pkg/ui/aac-sets.js +41 -0
  262. package/dist-pkg/ui/audio-choices.d.ts +68 -0
  263. package/dist-pkg/ui/audio-choices.js +98 -0
  264. package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
  265. package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
  266. package/dist-pkg/ui/camera-control.d.ts +53 -0
  267. package/dist-pkg/ui/camera-control.js +48 -0
  268. package/dist-pkg/ui/changed-mark.d.ts +9 -8
  269. package/dist-pkg/ui/changed-mark.js +22 -53
  270. package/dist-pkg/ui/control-choices.d.ts +37 -0
  271. package/dist-pkg/ui/control-choices.js +84 -0
  272. package/dist-pkg/ui/debug-panel.d.ts +59 -43
  273. package/dist-pkg/ui/debug-panel.js +68 -69
  274. package/dist-pkg/ui/declared-words.d.ts +21 -0
  275. package/dist-pkg/ui/declared-words.js +66 -0
  276. package/dist-pkg/ui/dom.d.ts +10 -14
  277. package/dist-pkg/ui/dom.js +10 -47
  278. package/dist-pkg/ui/drawing-problems.d.ts +25 -0
  279. package/dist-pkg/ui/drawing-problems.js +94 -0
  280. package/dist-pkg/ui/eye-control.d.ts +36 -0
  281. package/dist-pkg/ui/eye-control.js +178 -0
  282. package/dist-pkg/ui/face-control.d.ts +25 -0
  283. package/dist-pkg/ui/face-control.js +183 -0
  284. package/dist-pkg/ui/focus-trap.d.ts +39 -49
  285. package/dist-pkg/ui/focus-trap.js +56 -65
  286. package/dist-pkg/ui/fonts.d.ts +157 -68
  287. package/dist-pkg/ui/fonts.js +305 -115
  288. package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
  289. package/dist-pkg/ui/footer-scroll-driver.js +201 -0
  290. package/dist-pkg/ui/footer-scroll.d.ts +38 -0
  291. package/dist-pkg/ui/footer-scroll.js +55 -0
  292. package/dist-pkg/ui/game-options.d.ts +47 -0
  293. package/dist-pkg/ui/game-options.js +158 -0
  294. package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
  295. package/dist-pkg/ui/gaze-overlay.js +165 -0
  296. package/dist-pkg/ui/hand-control.d.ts +25 -0
  297. package/dist-pkg/ui/hand-control.js +143 -0
  298. package/dist-pkg/ui/help-panel.d.ts +87 -0
  299. package/dist-pkg/ui/help-panel.js +242 -0
  300. package/dist-pkg/ui/hud-bands.d.ts +62 -0
  301. package/dist-pkg/ui/hud-bands.js +146 -0
  302. package/dist-pkg/ui/hud-row.d.ts +34 -0
  303. package/dist-pkg/ui/hud-row.js +80 -0
  304. package/dist-pkg/ui/hud.d.ts +73 -73
  305. package/dist-pkg/ui/hud.js +94 -98
  306. package/dist-pkg/ui/item-announcement.d.ts +13 -12
  307. package/dist-pkg/ui/item-announcement.js +25 -26
  308. package/dist-pkg/ui/layout.d.ts +103 -28
  309. package/dist-pkg/ui/layout.js +117 -99
  310. package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
  311. package/dist-pkg/ui/libras-avatar-clip.js +86 -0
  312. package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
  313. package/dist-pkg/ui/libras-avatar-load.js +134 -0
  314. package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
  315. package/dist-pkg/ui/libras-avatar-plan.js +211 -0
  316. package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
  317. package/dist-pkg/ui/libras-avatar-player.js +226 -0
  318. package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
  319. package/dist-pkg/ui/libras-avatar-stage.js +208 -0
  320. package/dist-pkg/ui/libras-glosses.d.ts +28 -0
  321. package/dist-pkg/ui/libras-glosses.js +161 -0
  322. package/dist-pkg/ui/locale-flags.d.ts +16 -0
  323. package/dist-pkg/ui/locale-flags.js +30 -0
  324. package/dist-pkg/ui/loop-crash.d.ts +17 -17
  325. package/dist-pkg/ui/loop-crash.js +33 -62
  326. package/dist-pkg/ui/menu-intent.d.ts +61 -0
  327. package/dist-pkg/ui/menu-intent.js +88 -0
  328. package/dist-pkg/ui/menu-items.d.ts +20 -0
  329. package/dist-pkg/ui/menu-items.js +51 -0
  330. package/dist-pkg/ui/menu-nav.d.ts +98 -92
  331. package/dist-pkg/ui/menu-nav.js +398 -286
  332. package/dist-pkg/ui/mobility-choices.d.ts +26 -0
  333. package/dist-pkg/ui/mobility-choices.js +41 -0
  334. package/dist-pkg/ui/motion-choices.d.ts +31 -0
  335. package/dist-pkg/ui/motion-choices.js +68 -0
  336. package/dist-pkg/ui/motion-scene.d.ts +24 -19
  337. package/dist-pkg/ui/motion-scene.js +29 -61
  338. package/dist-pkg/ui/mount-panel.d.ts +81 -0
  339. package/dist-pkg/ui/mount-panel.js +61 -0
  340. package/dist-pkg/ui/panel-shell.d.ts +65 -31
  341. package/dist-pkg/ui/panel-shell.js +92 -66
  342. package/dist-pkg/ui/panel-widgets.d.ts +150 -0
  343. package/dist-pkg/ui/panel-widgets.js +294 -0
  344. package/dist-pkg/ui/pause-buttons.d.ts +35 -0
  345. package/dist-pkg/ui/pause-buttons.js +66 -0
  346. package/dist-pkg/ui/pause-icons.d.ts +261 -347
  347. package/dist-pkg/ui/pause-icons.js +671 -601
  348. package/dist-pkg/ui/pause-markup.d.ts +86 -0
  349. package/dist-pkg/ui/pause-markup.js +125 -0
  350. package/dist-pkg/ui/reach-notice.d.ts +22 -23
  351. package/dist-pkg/ui/reach-notice.js +55 -58
  352. package/dist-pkg/ui/scan-overlay.d.ts +23 -0
  353. package/dist-pkg/ui/scan-overlay.js +50 -0
  354. package/dist-pkg/ui/screen-text.d.ts +25 -0
  355. package/dist-pkg/ui/screen-text.js +152 -0
  356. package/dist-pkg/ui/session-clock.d.ts +32 -0
  357. package/dist-pkg/ui/session-clock.js +67 -0
  358. package/dist-pkg/ui/settings-aac.d.ts +70 -0
  359. package/dist-pkg/ui/settings-aac.js +208 -0
  360. package/dist-pkg/ui/settings-audio.d.ts +97 -114
  361. package/dist-pkg/ui/settings-audio.js +493 -425
  362. package/dist-pkg/ui/settings-controls.d.ts +53 -96
  363. package/dist-pkg/ui/settings-controls.js +143 -215
  364. package/dist-pkg/ui/settings-empathy.d.ts +39 -30
  365. package/dist-pkg/ui/settings-empathy.js +53 -60
  366. package/dist-pkg/ui/settings-mobility.d.ts +192 -0
  367. package/dist-pkg/ui/settings-mobility.js +332 -0
  368. package/dist-pkg/ui/settings-motion.d.ts +91 -70
  369. package/dist-pkg/ui/settings-motion.js +287 -198
  370. package/dist-pkg/ui/settings-panel.d.ts +58 -45
  371. package/dist-pkg/ui/settings-panel.js +189 -94
  372. package/dist-pkg/ui/settings-typo.d.ts +29 -78
  373. package/dist-pkg/ui/settings-typo.js +158 -129
  374. package/dist-pkg/ui/settings-visual.d.ts +29 -87
  375. package/dist-pkg/ui/settings-visual.js +240 -193
  376. package/dist-pkg/ui/shell.d.ts +112 -135
  377. package/dist-pkg/ui/shell.js +148 -217
  378. package/dist-pkg/ui/simulation-list.d.ts +27 -0
  379. package/dist-pkg/ui/simulation-list.js +76 -0
  380. package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
  381. package/dist-pkg/ui/simulation-over-the-world.js +131 -0
  382. package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
  383. package/dist-pkg/ui/simulation-refusal.js +8 -56
  384. package/dist-pkg/ui/switchable-control.d.ts +11 -0
  385. package/dist-pkg/ui/switchable-control.js +19 -0
  386. package/dist-pkg/ui/title.d.ts +3 -12
  387. package/dist-pkg/ui/title.js +49 -18
  388. package/dist-pkg/ui/top-band.d.ts +26 -0
  389. package/dist-pkg/ui/top-band.js +96 -0
  390. package/dist-pkg/ui/typo-choices.d.ts +71 -0
  391. package/dist-pkg/ui/typo-choices.js +85 -0
  392. package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
  393. package/dist-pkg/ui/visual-axes-panel.js +12 -94
  394. package/dist-pkg/ui/visual-choices.d.ts +77 -0
  395. package/dist-pkg/ui/visual-choices.js +107 -0
  396. package/dist-pkg/ui/vlibras.d.ts +77 -10
  397. package/dist-pkg/ui/vlibras.js +130 -81
  398. package/dist-pkg/ui/voice-control.d.ts +68 -0
  399. package/dist-pkg/ui/voice-control.js +276 -0
  400. package/dist-pkg/ui/voice-settings.d.ts +95 -0
  401. package/dist-pkg/ui/voice-settings.js +352 -0
  402. package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
  403. package/dist-pkg/ui/where-the-child-is.js +70 -0
  404. package/docs/CREDITS.md +300 -44
  405. package/docs/LICENSES.md +189 -145
  406. package/package.json +51 -27
  407. package/scripts/check-cartridge.mjs +78 -0
  408. package/scripts/game-build.d.mts +25 -0
  409. package/scripts/game-build.mjs +144 -0
  410. package/scripts/heavy-into-the-delivery.mjs +388 -0
  411. package/scripts/libras-avatar.json +680 -0
  412. package/scripts/libras-avatar.mjs +246 -0
  413. package/scripts/libras-glosses/gloss.py +95 -0
  414. package/scripts/libras-glosses/pyproject.toml +32 -0
  415. package/scripts/libras-glosses/uv.lock +781 -0
  416. package/scripts/libras-glosses.mjs +351 -0
  417. package/scripts/licences/Apache-2.0.txt +176 -0
  418. package/scripts/licences/GPL-3.0.txt +674 -0
  419. package/scripts/licences/MIT.txt +17 -0
  420. package/scripts/licences/OFL-1.1.txt +86 -0
  421. package/scripts/licences/UFL-1.0.txt +96 -0
  422. package/scripts/licences/fonts.mjs +389 -0
  423. package/scripts/licences/third-party.mjs +301 -0
  424. package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
  425. package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
  426. package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
  427. package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
  428. package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
  429. package/app/public/vendor/fonts/inter-400.woff2 +0 -0
  430. package/app/public/vendor/fonts/inter-700.woff2 +0 -0
  431. package/app/public/vendor/fonts/lato-400.woff2 +0 -0
  432. package/app/public/vendor/fonts/lato-700.woff2 +0 -0
  433. package/app/public/vendor/fonts/literata-400.woff2 +0 -0
  434. package/app/public/vendor/fonts/literata-700.woff2 +0 -0
  435. package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
  436. package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
  437. package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
  438. package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
  439. package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
  440. package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
  441. package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
  442. package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
  443. package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
  444. package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
  445. package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
  446. package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
  447. package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
  448. package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
  449. package/dist-pkg/core/anel.d.ts +0 -17
  450. package/dist-pkg/core/anel.js +0 -31
  451. package/dist-pkg/core/collision.d.ts +0 -21
  452. package/dist-pkg/core/collision.js +0 -62
  453. package/dist-pkg/core/layers.d.ts +0 -63
  454. package/dist-pkg/core/layers.js +0 -95
  455. package/dist-pkg/core/letter-grid.d.ts +0 -55
  456. package/dist-pkg/core/letter-grid.js +0 -116
  457. package/dist-pkg/core/password.d.ts +0 -34
  458. package/dist-pkg/core/password.js +0 -205
  459. package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
  460. package/dist-pkg/core/rotulo-acessivel.js +0 -41
  461. package/dist-pkg/core/run-state.d.ts +0 -115
  462. package/dist-pkg/core/run-state.js +0 -40
  463. package/dist-pkg/core/tiles.d.ts +0 -12
  464. package/dist-pkg/core/tiles.js +0 -61
  465. package/dist-pkg/core/world.d.ts +0 -4
  466. package/dist-pkg/core/world.js +0 -58
  467. package/dist-pkg/input/origem-sintetica.d.ts +0 -44
  468. package/dist-pkg/input/origem-sintetica.js +0 -60
  469. package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
  470. package/dist-pkg/input/transporte-em-uso.js +0 -130
  471. package/dist-pkg/platform/audio-nav.d.ts +0 -51
  472. package/dist-pkg/platform/audio-nav.js +0 -99
  473. package/dist-pkg/platform/guide-intensity.d.ts +0 -40
  474. package/dist-pkg/platform/guide-intensity.js +0 -73
  475. package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
  476. package/dist-pkg/platform/pesados-catalogo.js +0 -177
  477. package/dist-pkg/platform/pesados.d.ts +0 -31
  478. package/dist-pkg/platform/pesados.js +0 -75
  479. package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
  480. package/dist-pkg/platform/vozes-prontas.js +0 -61
  481. package/dist-pkg/render/camera.d.ts +0 -58
  482. package/dist-pkg/render/camera.js +0 -105
  483. package/dist-pkg/render/cenario-data.d.ts +0 -127
  484. package/dist-pkg/render/cenario-data.js +0 -145
  485. package/dist-pkg/render/city-tex.d.ts +0 -63
  486. package/dist-pkg/render/city-tex.js +0 -228
  487. package/dist-pkg/render/city-tiles.d.ts +0 -11
  488. package/dist-pkg/render/city-tiles.js +0 -140
  489. package/dist-pkg/render/draw.d.ts +0 -149
  490. package/dist-pkg/render/draw.js +0 -231
  491. package/dist-pkg/render/fx.d.ts +0 -63
  492. package/dist-pkg/render/fx.js +0 -123
  493. package/dist-pkg/render/minimap.d.ts +0 -11
  494. package/dist-pkg/render/minimap.js +0 -94
  495. package/dist-pkg/render/parallax.d.ts +0 -85
  496. package/dist-pkg/render/parallax.js +0 -158
  497. package/dist-pkg/render/player-anim.d.ts +0 -71
  498. package/dist-pkg/render/player-anim.js +0 -152
  499. package/dist-pkg/render/recycling-tex.d.ts +0 -48
  500. package/dist-pkg/render/recycling-tex.js +0 -164
  501. package/dist-pkg/render/scene-city.d.ts +0 -77
  502. package/dist-pkg/render/scene-city.js +0 -181
  503. package/dist-pkg/render/scene-parallax.d.ts +0 -72
  504. package/dist-pkg/render/scene-parallax.js +0 -426
  505. package/dist-pkg/render/scene-sky.d.ts +0 -126
  506. package/dist-pkg/render/scene-sky.js +0 -295
  507. package/dist-pkg/render/set-cenario.d.ts +0 -54
  508. package/dist-pkg/render/set-cenario.js +0 -103
  509. package/dist-pkg/render/textures.d.ts +0 -75
  510. package/dist-pkg/render/textures.js +0 -240
  511. package/dist-pkg/render/title-scene.d.ts +0 -46
  512. package/dist-pkg/render/title-scene.js +0 -75
  513. package/dist-pkg/render/weather.d.ts +0 -96
  514. package/dist-pkg/render/weather.js +0 -171
  515. package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
  516. package/dist-pkg/render/wheelchair-sprites.js +0 -69
  517. package/dist-pkg/render/world-tex.d.ts +0 -18
  518. package/dist-pkg/render/world-tex.js +0 -87
  519. package/dist-pkg/ui/activities-menu.d.ts +0 -258
  520. package/dist-pkg/ui/activities-menu.js +0 -648
  521. package/dist-pkg/ui/caa-sets.d.ts +0 -39
  522. package/dist-pkg/ui/caa-sets.js +0 -65
  523. package/dist-pkg/ui/latch-refusal.d.ts +0 -32
  524. package/dist-pkg/ui/latch-refusal.js +0 -60
  525. package/dist-pkg/ui/map-hub.d.ts +0 -56
  526. package/dist-pkg/ui/map-hub.js +0 -138
  527. package/dist-pkg/ui/settings-caa.d.ts +0 -45
  528. package/dist-pkg/ui/settings-caa.js +0 -137
  529. package/dist-pkg/ui/settings-motor.d.ts +0 -175
  530. package/dist-pkg/ui/settings-motor.js +0 -342
  531. package/dist-pkg/ui/webcam.d.ts +0 -7
  532. package/dist-pkg/ui/webcam.js +0 -93
@@ -0,0 +1,77 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /** A heavy thing the engine promises that does not fit in the package. */
3
+ export interface HeavyFile {
4
+ readonly id: string;
5
+ /** `null` = decided that it exists, but there is nowhere to fetch it from yet. See `whyNoSource`. */
6
+ readonly url: string | null;
7
+ /** Measured, not estimated — the number an honest sentence uses before the download starts. */
8
+ readonly bytes?: number;
9
+ /**
10
+ * The SHA-256 of the bytes, MEASURED (issue #168): what the fetcher compares before keeping anything. A pinned URL is
11
+ * not pinned content — a CDN or a mirror can serve other bytes at the same address, and these run in the child's page.
12
+ */
13
+ readonly sha256?: string;
14
+ /** Required when `url` is `null`: an absence without a written reason becomes a forgotten absence. */
15
+ readonly whyNoSource?: string;
16
+ }
17
+ /** The Cache Storage name. Versioned: changing the catalogue's content must not serve old bytes. */
18
+ export declare const CACHE_HEAVY = "incl-pesados-v2";
19
+ /** The language a reading id serves, or `null` where the id is not a reading model's. */
20
+ export declare function readingLanguageOf(id: string): string | null;
21
+ /**
22
+ * The language a command MODEL serves, or `null` for anything else — including the runtime, which serves every language.
23
+ * ⚠️ The middle word is read on purpose: `id.split(':')[1]` would call the runtime a language of its own and leave the three
24
+ * models behind it out of the start of every delivery.
25
+ */
26
+ export declare function commandsLanguageOf(id: string): string | null;
27
+ /**
28
+ * WHERE THE DELIVERY PUTS THE LIBRAS PLAYER'S FILES (ADR-0234, route B, the engine's interpreter since phase B3): the avatar, its
29
+ * clips, their manifest and the build-time glosses, beside the game's page (`inclusionist-heavy --libras`). Written here, below
30
+ * the player that reads it (`ui/libras-avatar-plan` re-exports it), because the delivery's list of those files names it too.
31
+ *
32
+ * 📌 THERE IS NO CATALOGUE ENTRY FOR IT: the avatar and the clips are this project's own export of LAViD-UFPB's GPL-3.0 sign
33
+ * sources, pinned by sha256 in `scripts/libras-avatar.json`, and each delivery lists what it wrote (`DELIVERY_LISTS`). Nothing
34
+ * closed and nothing patched is served for it.
35
+ */
36
+ export declare const LIBRAS_AVATAR_FOLDER = "libras/avatar/";
37
+ /**
38
+ * THE START OF THE FREE PLAYER'S STAGE CHUNK, under the page: `ui/libras-avatar-stage` and the three.js it carries, which the
39
+ * bundler emits as `assets/libras-avatar-stage-<content hash>.js`. The precache leaves it out on purpose (three.js is only a
40
+ * deaf-mode child's download), so the delivery finds the hashed name after the build and lists it; a NAME's start and not a
41
+ * folder, because the rest of `assets/` belongs to the precache.
42
+ */
43
+ export declare const LIBRAS_AVATAR_STAGE_CHUNK = "assets/libras-avatar-stage-";
44
+ /**
45
+ * A LIST THE DELIVERY WRITES OF ITS OWN FILES, each with its sha256 — for what no catalogue entry can pin because each delivery
46
+ * makes it: the Libras player's avatar, clips and manifest, the glosses of the engine's and the game's texts, and the build's
47
+ * stage chunk (ADR-0234, pillar 8). The device reads the list and keeps each file only if its bytes are the listed ones, in the
48
+ * checked cache, under the file's own address, where the service worker answers the player from offline.
49
+ *
50
+ * ⚠️ WHAT THE LIST PROVES, AND WHAT IT DOES NOT: it comes from the page's own origin, like the page's code, so it is exactly as
51
+ * trusted as the page — it is not a pin. What it guarantees is that what is kept is what this delivery wrote: never a truncated
52
+ * body, a fallback page served for a missing file, or a file of the previous delivery. The avatar's and the clips' hashes in it
53
+ * are the ones `scripts/libras-avatar.json` pins, checked when the delivery wrote them.
54
+ */
55
+ export interface DeliveryList {
56
+ readonly id: string;
57
+ /** Where the delivery writes the list, relative to the page. */
58
+ readonly path: string;
59
+ /**
60
+ * The only places the list may name, relative to the page: a listed file outside them is refused, never kept. Each is a
61
+ * folder (ending in `/`) or, for a file whose name the build hashes, the start of that name (`LIBRAS_AVATAR_STAGE_CHUNK`).
62
+ */
63
+ readonly folders: readonly string[];
64
+ }
65
+ /**
66
+ * The lists a device may read, each asked for with deaf mode (`heavyAtBoot`) — one per delivery step that writes files of its own:
67
+ * · `libras:avatar:delivery`, the Libras player's avatar, clips, manifest and glosses and the stage chunk with three.js, written by
68
+ * `--libras` (ADR-0234, phase B3). A delivery built without it has no such list: a quiet 404, and deaf mode says «signing
69
+ * unavailable» when the sonar is pressed.
70
+ * 📌 THE RULE IS «WHAT THE DELIVERY CARRIES, DEAF MODE KEEPS»: the files are kept whichever interpreter the host lends.
71
+ */
72
+ export declare const DELIVERY_LISTS: readonly DeliveryList[];
73
+ /**
74
+ * 📌 Every entry with an address needs its licence group in `scripts/licences/third-party.mjs`: the delivery writes that group's
75
+ * `LICENSE` and `NOTICE` beside the file, and refuses a file whose licence nobody recorded (ADR-0177).
76
+ */
77
+ export declare const HEAVY_FILES: readonly HeavyFile[];
@@ -0,0 +1,256 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // platform/heavy-catalogue.ts — WHAT IS HEAVY, WHERE IT COMES FROM, AND HOW MUCH IT WEIGHS.
3
+ //
4
+ // 📌 APART FROM THE FETCHER on purpose: the list is DATA and changes by recorded decision; the fetcher is a rule and
5
+ // changes by defect found. Together, every URL fix would touch the file that decides the download order, and every
6
+ // order fix would touch the list a record governs.
7
+ //
8
+ // 📌 Every address is written ONCE, where its module owns it: Kokoro's in `platform/kokoro`, the vision runtime's here.
9
+ import { KOKORO_VOICES, KOKORO_MODEL_URL, URL_DO_TOKENIZADOR_KOKORO, kokoroVoiceUrl, KOKORO_VOICES_SHA256, KOKORO_VOICE_BYTES, KOKORO_MODEL_SHA256, KOKORO_MODEL_BYTES, SHA256_DO_TOKENIZADOR_KOKORO, BYTES_DO_TOKENIZADOR_KOKORO, } from './kokoro.js';
10
+ /** The Cache Storage name. Versioned: changing the catalogue's content must not serve old bytes. */
11
+ // v2 since issue #168: what v1 kept was never checked against a hash, so it is not trusted — it is fetched again, checked.
12
+ export const CACHE_HEAVY = 'incl-pesados-v2';
13
+ /**
14
+ * THE VISION RUNTIME — **MediaPipe**, decided by the Dev (ADR-0124): «… mediapipe (webgazer não), e LPCP: devem
15
+ * acompanhar a engine». WebGazer, brought back by ADR-0132, left again (ADR-0214).
16
+ *
17
+ * 📏 MEASURED 2026-09-09: the three files answer 200 on jsDelivr with `Access-Control-Allow-Origin: *`, at the PINNED
18
+ * version — 155 439 + 323 377 + 11 756 954 bytes.
19
+ *
20
+ * ⚠️ A PINNED CDN IS ALLOWED AND ADR-0116 SAYS WHY: what pillar 8 forbids is depending on the network AFTER the first day.
21
+ * This comes down at INSTALL, with the rest. 📌 The version goes in the URL, which is what `check:precache` requires of
22
+ * any external entry: different bytes arrive by a different address, and a pinned entry never freezes.
23
+ *
24
+ * 🎯 IT IS THE THREE FILES AND NOT ONLY THE `.wasm`: `vision_bundle.mjs` is what loads it and `vision_wasm_internal.js` is
25
+ * the Emscripten glue. The wasm alone is a «downloaded» thing that does not run.
26
+ */
27
+ const MP = 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@1.0.1';
28
+ const MP_MODELS = 'https://storage.googleapis.com/mediapipe-models';
29
+ /**
30
+ * 🔴 THE MODELS, without which the runtime recognises nothing: 11.7 MB of WebAssembly without a `.task` is a download
31
+ * that does no work. The Dev caught the first version of this list, which carried the runtime and no model.
32
+ *
33
+ * 📏 MEASURED, all 200 with open CORS. `float16` and not `float32`: half the weight, and the precision lost is irrelevant
34
+ * to saying where an iris is on a 320×180 screen.
35
+ */
36
+ const MEDIAPIPE = Object.freeze([
37
+ { id: 'visao:runtime', url: `${MP}/vision_bundle.mjs`, bytes: 155_439,
38
+ sha256: 'd885630c297c0b20b1fe86096cb06291c4c8080876f27852e724f24ac603713f' },
39
+ { id: 'visao:runtime:cola', url: `${MP}/wasm/vision_wasm_internal.js`, bytes: 323_377,
40
+ sha256: 'e170ee67dd4e16c1a6fcd8840a206687e5a59b22c20e4a902bc445b095454d73' },
41
+ { id: 'visao:runtime:wasm', url: `${MP}/wasm/vision_wasm_internal.wasm`, bytes: 11_756_954,
42
+ sha256: '8da277a733926eacd0474b8704b36742d6ec3231c57a860c5b889dff8f1df886' },
43
+ { id: 'visao:modelo:rosto', url: `${MP_MODELS}/face_landmarker/face_landmarker/float16/1/face_landmarker.task`, bytes: 3_758_596,
44
+ sha256: '64184e229b263107bc2b804c6625db1341ff2bb731874b0bcc2fe6544e0bc9ff' },
45
+ { id: 'visao:modelo:gestos', url: `${MP_MODELS}/gesture_recognizer/gesture_recognizer/float16/1/gesture_recognizer.task`, bytes: 8_373_440,
46
+ sha256: '97952348cf6a6a4915c2ea1496b4b37ebabc50cbbf80571435643c455f2b0482' },
47
+ { id: 'visao:modelo:maos', url: `${MP_MODELS}/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task`, bytes: 7_819_105,
48
+ sha256: 'fbc2a30080c3c557093b5ddfc334698132eb341044ccee322ccf8bcf3607cde1' },
49
+ ]);
50
+ /**
51
+ * THE VOICE RUNTIME (ADR-0216 and its erratum; issue #200): what SPEAKS a neural voice, fetched like the vision runtime and for the
52
+ * same reason — the engine imports nothing from npm at run time, so a game that never asks for this voice carries none of it, and
53
+ * the published package stays free of a bundler-only import.
54
+ *
55
+ * · eSpeak NG turns a sentence into phonemes, in every language the project speaks. GPL-3.0-or-later, compatible with the engine's
56
+ * AGPL-3.0 (LICENSES.md). It is the PROJECT'S OWN BUILD (issue #192): the npm build named no source, so the engine compiles it
57
+ * from a pinned commit (`scripts/models/build-espeak-ng.ps1`), and that commit and that recipe travel beside the mirror's copy.
58
+ * Its address is the project's mirror because nothing upstream holds these bytes.
59
+ * · onnxruntime-web runs Kokoro's graph. The `jsep` pair is what its own threads load, which is why both are here: a worker that
60
+ * cannot find them answers nothing, and the child hears silence (measured in the quiz demo, #181).
61
+ *
62
+ * ⚠️ sha256 MEASURED on the files, not taken from a page: onnxruntime-web's on those the dev dependency put on the build machine,
63
+ * which the first delivery run proved jsDelivr serves; eSpeak NG's on two runs of its recipe, which wrote the same bytes.
64
+ */
65
+ const ESPEAK = 'https://lfs-oinclusionista.jrocha.dev.br/espeak-ng-530bf0a';
66
+ const ORT = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.27.0';
67
+ const VOICE_RUNTIME = Object.freeze([
68
+ { id: 'voz:runtime:fonemas', url: `${ESPEAK}/espeak-ng.js`, bytes: 70_951,
69
+ sha256: 'd2f7cea5ed29daed420a05271a48e5b7ab5315b1f4b33fa04ea54014c155889e' },
70
+ { id: 'voz:runtime:fonemas:wasm', url: `${ESPEAK}/espeak-ng.wasm`, bytes: 1_493_661,
71
+ sha256: '44e0cc6accb436880d1d52d2dd7b69a72f8f6a8c8f2cdb3dcf00e3914db4eb05' },
72
+ { id: 'voz:runtime:onnx', url: `${ORT}/dist/ort.webgpu.bundle.min.mjs`, bytes: 113_035,
73
+ sha256: '3a18c7f261e05d44a15b2eef18a28e5f53c044d5d140bcea6066baf1f09c8b53' },
74
+ { id: 'voz:runtime:onnx:cola', url: `${ORT}/dist/ort-wasm-simd-threaded.jsep.mjs`, bytes: 46_614,
75
+ sha256: '3ee381d20a80f51a788a1c4a5872f6f1d047538dd4342f4af00062de5f9ea4c6' },
76
+ { id: 'voz:runtime:onnx:wasm', url: `${ORT}/dist/ort-wasm-simd-threaded.jsep.wasm`, bytes: 26_827_543,
77
+ sha256: '78feeeb3d08f6bcee94d938ed322f69073bb8076b5f9d34697a574ffba8deb48' },
78
+ ]);
79
+ /**
80
+ * THE READING MODELS (ADR-0201 erratum, ADR-0203; issues #185, #200): what hears a child read aloud, ONE MODEL PER LANGUAGE —
81
+ * Whisper small for Portuguese, Moonshine streaming small for English and Spanish, the three the lab measured (pt 7.7 % WER,
82
+ * en 19.3 %, es 7.2 %).
83
+ *
84
+ * 🎯 THE ADDRESS IS THE PROJECT'S OWN, and it has to be: these two exports do not exist anywhere else. The Whisper one was made
85
+ * here (`scripts/models/export-whisper-small.py`) because the ready-made export states no licence, and the Spanish Moonshine was
86
+ * exported here from weights that ship no ONNX. The project mirrors them under ADR-0203 — «hospedar na Cloudflare do projeto» —
87
+ * with the licence of each beside it in `the-inclusionist-lfs`.
88
+ *
89
+ * ⚠️ AND THEY ARE BIG: 378 MiB for pt, 162 for en, 310 for es — and a device that reads keeps all three, because a child tries
90
+ * the three languages at once (ADR-0225 erratum, the Dev: «Negativo, baixar os três.»). The start asks for the child's language
91
+ * first and then each other whole (`heavyAtBoot`); a game that does not declare `uses: { reading: true }` asks for none of them.
92
+ *
93
+ * 📌 The ids are in English while their neighbours are not: what is here stays until the renaming of the whole catalogue (the
94
+ * English plan, phase 2, a single BREAKING release), and nothing new arrives in Portuguese meanwhile.
95
+ *
96
+ * ⚠️ sha256 MEASURED on the mirror's own files, each checked against the `SHA256SUMS` its folder publishes.
97
+ */
98
+ const READING_MIRROR = 'https://lfs-oinclusionista.jrocha.dev.br';
99
+ const READING = Object.freeze([
100
+ // pt — Whisper small, exported and quantized by this project
101
+ { id: 'reading:pt:encoder', url: `${READING_MIRROR}/whisper-small-onnx/onnx/encoder_model_quantized.onnx`, bytes: 95_131_296,
102
+ sha256: '25eae0fce49960d460d800c53a9df788afdf54baceee16ab6a6333869e2fc78f' },
103
+ { id: 'reading:pt:decoder', url: `${READING_MIRROR}/whisper-small-onnx/onnx/decoder_model_quantized.onnx`, bytes: 156_551_161,
104
+ sha256: '63e48cd0bef0f3367f4611728f38bf8f123af545212a2e744fe2ec28e0e887a3' },
105
+ { id: 'reading:pt:decoder:past', url: `${READING_MIRROR}/whisper-small-onnx/onnx/decoder_with_past_model_quantized.onnx`, bytes: 142_305_767,
106
+ sha256: '670b3e8b846f4e86dd3c26930bb671dec2df476b81c138c1864db37aa8bc92c0' },
107
+ { id: 'reading:pt:tokenizer', url: `${READING_MIRROR}/whisper-small-onnx/tokenizer.json`, bytes: 2_480_466,
108
+ sha256: '27fc476bfe7f17299480be2273fc0608e4d5a99aba2ab5dec5374b4482d1a566' },
109
+ { id: 'reading:pt:config', url: `${READING_MIRROR}/whisper-small-onnx/config.json`, bytes: 1_967,
110
+ sha256: 'e6a2b489da1b5aed65a8eb8d1e7466fa867ad5643a8bc138ba708bd56b2875c4' },
111
+ // what the reading must NOT invent: the tokens Whisper suppresses, and the mel filterbank its features are built with
112
+ { id: 'reading:pt:generation', url: `${READING_MIRROR}/whisper-small-onnx/generation_config.json`, bytes: 3_868,
113
+ sha256: '71565b8ef50d0bf7a1193ed4bbed195b94e70c18894d81bba2f1233dcec3ab53' },
114
+ { id: 'reading:pt:preprocessor', url: `${READING_MIRROR}/whisper-small-onnx/preprocessor_config.json`, bytes: 184_990,
115
+ sha256: '9b5cd03a36fbb8a627c64d98a5b5b126ead95a77720723944487311f0110b666' },
116
+ // en — Moonshine streaming small, the Workmind ONNX export, copied unchanged (MIT)
117
+ { id: 'reading:en:encoder', url: `${READING_MIRROR}/moonshine-streaming-small-onnx/onnx/encoder_model_quantized.onnx`, bytes: 74_923_158,
118
+ sha256: '69c786908794eb9e2e50d7137c4e755abdde7b4bdebffd68fe0c292eee5ffc55' },
119
+ { id: 'reading:en:decoder', url: `${READING_MIRROR}/moonshine-streaming-small-onnx/onnx/decoder_model_merged_quantized.onnx`, bytes: 90_830_447,
120
+ sha256: '3bd2e7a7e94c608b1988fa035be1f1b1f2acdbe059f7fe5cc70d85201c2835f5' },
121
+ { id: 'reading:en:tokenizer', url: `${READING_MIRROR}/moonshine-streaming-small-onnx/tokenizer.json`, bytes: 3_761_754,
122
+ sha256: '7b913404bdd039af4756783218af4440bc07fb7d6d8258d677e34f95b3ec416f' },
123
+ { id: 'reading:en:config', url: `${READING_MIRROR}/moonshine-streaming-small-onnx/config.json`, bytes: 1_745,
124
+ sha256: '849ca79b5af5603b1e7b8eeebf67265f931c70117434446fca6f35a26fc03df1' },
125
+ { id: 'reading:en:generation', url: `${READING_MIRROR}/moonshine-streaming-small-onnx/generation_config.json`, bytes: 163,
126
+ sha256: 'fd54ad15ad0a14f68db3c58a8d8e5e8f3791ef95e1ea92ee46cd71b4a5d7528c' },
127
+ // es — Moonshine streaming small, exported here from the upstream weights. ⚠️ Its encoder is fp32 and the biggest file of the
128
+ // three: quantized to q8 it drifted in the lab, and a reading that mis-hears a child is worse than a bigger download.
129
+ { id: 'reading:es:encoder', url: `${READING_MIRROR}/moonshine-streaming-small-es-onnx/onnx/encoder_model.onnx`, bytes: 205_951_994,
130
+ sha256: 'e675a5cf070ed40da516f1648bea62eb21f77421f1c490cedfe0d16bdc77a090' },
131
+ { id: 'reading:es:decoder', url: `${READING_MIRROR}/moonshine-streaming-small-es-onnx/onnx/decoder_model_quantized.onnx`, bytes: 63_639_862,
132
+ sha256: '6775c2b74f429ae202e5a11cc0db7e291a0e593641364ddf416613d130528fcf' },
133
+ { id: 'reading:es:decoder:past', url: `${READING_MIRROR}/moonshine-streaming-small-es-onnx/onnx/decoder_with_past_model_quantized.onnx`, bytes: 55_504_894,
134
+ sha256: '9cddfa057c8b5d65d3e5057b748b6f6b58753306846dd0fa4d0e8639cb22bfd9' },
135
+ { id: 'reading:es:tokenizer', url: `${READING_MIRROR}/moonshine-streaming-small-es-onnx/tokenizer.json`, bytes: 476_245,
136
+ sha256: 'e8dae7af9c2b6e5a1f413819db1eb70837ff4cf53b5a482a37f2ffc608b8b977' },
137
+ { id: 'reading:es:config', url: `${READING_MIRROR}/moonshine-streaming-small-es-onnx/config.json`, bytes: 1_653,
138
+ sha256: 'bfd932c804df9cde662468a8f933763cd5174bfed2c043b2440b4daaa702efbd' },
139
+ { id: 'reading:es:generation', url: `${READING_MIRROR}/moonshine-streaming-small-es-onnx/generation_config.json`, bytes: 246,
140
+ sha256: '3e5f0aa2b32615a4023d0a08cccb7c1ec292aba9a8d8f6f4886df2a769af31b0' },
141
+ ]);
142
+ /** The language a reading id serves, or `null` where the id is not a reading model's. */
143
+ export function readingLanguageOf(id) {
144
+ const parts = id.split(':');
145
+ return parts[0] === 'reading' && parts[1] ? parts[1] : null;
146
+ }
147
+ /**
148
+ * THE COMMAND MODELS (ADR-0189, ADR-0193, ADR-0194; issue #184): what hears a child SAY A WORD OF THE GAME. Not the same job as
149
+ * the reading above, and not the same tool: a command is heard against a CLOSED GRAMMAR — the names the menu is showing right
150
+ * now — which is why 32 MiB answer in 0.25 s what 378 MiB of Whisper answered in seconds and, on single words, wrongly (📏 lab:
151
+ * Vosk 7/7 commands, Whisper base 1/7).
152
+ *
153
+ * 🎯 THE RUNTIME IS THE PROJECT'S OWN BUILD, and that is the whole reason it exists: every published `vosk-browser` evaluates
154
+ * text as code, which this engine's Content-Security-Policy refuses (ADR-0193 — never `'unsafe-eval'`, never a patch). It was
155
+ * rebuilt from lichess-org/vosk-browser with `-s DYNAMIC_EXECUTION=0` and runs under the policy as it is (`models.md`).
156
+ * The models are alphacephei's small ones, repacked deterministically as the `.tar.gz` that build loads.
157
+ *
158
+ * ⚠️ ONE MODEL PER LANGUAGE, like the reading: pt 30.9 MiB, en 39.2, es 37.9. A delivery carries the three unless
159
+ * `inclusionist-heavy --commands` narrows it, and the start asks for every language the page can switch to, the child's first
160
+ * (ADR-0225 erratum: a language changed mid-game must find its model), as it does for the reading. 📌 But unlike the reading,
161
+ * NO GAME DECLARES THIS: a child who speaks instead of pressing is using a transport, and a cartridge does not get to deny her
162
+ * one (ADR-0111).
163
+ *
164
+ * ⚠️ sha256 MEASURED on the mirror's own files (2026-09-21), each checked against the `SHA256SUMS` its folder publishes.
165
+ */
166
+ const COMMANDS = Object.freeze([
167
+ { id: 'commands:runtime', url: `${READING_MIRROR}/vosk-browser-dynamic-execution-0/vosk.wasm.js`, bytes: 10_288,
168
+ sha256: 'a7ab48dcf72660ec79a493c37b9fd1d0b3c09c46968c6a1ebd06adb4d9a35ca6' },
169
+ { id: 'commands:runtime:worker', url: `${READING_MIRROR}/vosk-browser-dynamic-execution-0/vosk.worker.js`, bytes: 194_710,
170
+ sha256: 'cf84a33820a1634d6a8d11194f2bd04f871901bf630ba1423c24f6be13086b6a' },
171
+ { id: 'commands:runtime:wasm', url: `${READING_MIRROR}/vosk-browser-dynamic-execution-0/vosk.wasm`, bytes: 2_992_690,
172
+ sha256: 'e2a33196eacd6cd7d863392f877b9360664d7614ce97cddf9de5b5e637e2ccf9' },
173
+ { id: 'commands:model:pt', url: `${READING_MIRROR}/vosk-models/vosk-model-small-pt-0.3.tar.gz`, bytes: 32_358_733,
174
+ sha256: '4885a09d9cd3063bf991e2ae280f24eeee789410aaa05277a2e082cff0cf837d' },
175
+ { id: 'commands:model:en', url: `${READING_MIRROR}/vosk-models/vosk-model-small-en-us-0.15.tar.gz`, bytes: 41_116_539,
176
+ sha256: '61cf40721d255cccb9fe29bb059c6b3376b164c31f449d8143455ffbb86018cc' },
177
+ { id: 'commands:model:es', url: `${READING_MIRROR}/vosk-models/vosk-model-small-es-0.42.tar.gz`, bytes: 39_748_927,
178
+ sha256: '4ed16b681698db764ecb11996b1b4f74dd68f602213b36c17806a1398b26b162' },
179
+ ]);
180
+ /**
181
+ * The language a command MODEL serves, or `null` for anything else — including the runtime, which serves every language.
182
+ * ⚠️ The middle word is read on purpose: `id.split(':')[1]` would call the runtime a language of its own and leave the three
183
+ * models behind it out of the start of every delivery.
184
+ */
185
+ export function commandsLanguageOf(id) {
186
+ const parts = id.split(':');
187
+ return parts[0] === 'commands' && parts[1] === 'model' && parts[2] ? parts[2] : null;
188
+ }
189
+ /**
190
+ * WHERE THE DELIVERY PUTS THE LIBRAS PLAYER'S FILES (ADR-0234, route B, the engine's interpreter since phase B3): the avatar, its
191
+ * clips, their manifest and the build-time glosses, beside the game's page (`inclusionist-heavy --libras`). Written here, below
192
+ * the player that reads it (`ui/libras-avatar-plan` re-exports it), because the delivery's list of those files names it too.
193
+ *
194
+ * 📌 THERE IS NO CATALOGUE ENTRY FOR IT: the avatar and the clips are this project's own export of LAViD-UFPB's GPL-3.0 sign
195
+ * sources, pinned by sha256 in `scripts/libras-avatar.json`, and each delivery lists what it wrote (`DELIVERY_LISTS`). Nothing
196
+ * closed and nothing patched is served for it.
197
+ */
198
+ export const LIBRAS_AVATAR_FOLDER = 'libras/avatar/';
199
+ /**
200
+ * THE START OF THE FREE PLAYER'S STAGE CHUNK, under the page: `ui/libras-avatar-stage` and the three.js it carries, which the
201
+ * bundler emits as `assets/libras-avatar-stage-<content hash>.js`. The precache leaves it out on purpose (three.js is only a
202
+ * deaf-mode child's download), so the delivery finds the hashed name after the build and lists it; a NAME's start and not a
203
+ * folder, because the rest of `assets/` belongs to the precache.
204
+ */
205
+ export const LIBRAS_AVATAR_STAGE_CHUNK = 'assets/libras-avatar-stage-';
206
+ /**
207
+ * The lists a device may read, each asked for with deaf mode (`heavyAtBoot`) — one per delivery step that writes files of its own:
208
+ * · `libras:avatar:delivery`, the Libras player's avatar, clips, manifest and glosses and the stage chunk with three.js, written by
209
+ * `--libras` (ADR-0234, phase B3). A delivery built without it has no such list: a quiet 404, and deaf mode says «signing
210
+ * unavailable» when the sonar is pressed.
211
+ * 📌 THE RULE IS «WHAT THE DELIVERY CARRIES, DEAF MODE KEEPS»: the files are kept whichever interpreter the host lends.
212
+ */
213
+ export const DELIVERY_LISTS = Object.freeze([
214
+ Object.freeze({ id: 'libras:avatar:delivery', path: 'libras/offline-avatar.json',
215
+ folders: Object.freeze([LIBRAS_AVATAR_FOLDER, LIBRAS_AVATAR_STAGE_CHUNK]) }),
216
+ ]);
217
+ /**
218
+ * KOKORO (ADR-0186, ADR-0198; the Dev: «Faça»): the fp32 model, its tokenizer vocabulary and a style table per voice of the engine's
219
+ * languages. The engine loads them itself when a game declares `uses.neuralVoice` (ADR-0216); the phonemizer and the runtime that
220
+ * speak them are `VOICE_RUNTIME`, above.
221
+ */
222
+ const KOKORO = Object.freeze([
223
+ { id: 'voz:kokoro:modelo', url: KOKORO_MODEL_URL, bytes: KOKORO_MODEL_BYTES, sha256: KOKORO_MODEL_SHA256 },
224
+ { id: 'voz:kokoro:tokenizador', url: URL_DO_TOKENIZADOR_KOKORO, bytes: BYTES_DO_TOKENIZADOR_KOKORO, sha256: SHA256_DO_TOKENIZADOR_KOKORO },
225
+ ...KOKORO_VOICES.map((v) => ({ id: `voz:kokoro:${v.voice}`, url: kokoroVoiceUrl(v.voice), bytes: KOKORO_VOICE_BYTES, sha256: KOKORO_VOICES_SHA256[v.voice] })),
226
+ ]);
227
+ /**
228
+ * 📌 Every entry with an address needs its licence group in `scripts/licences/third-party.mjs`: the delivery writes that group's
229
+ * `LICENSE` and `NOTICE` beside the file, and refuses a file whose licence nobody recorded (ADR-0177).
230
+ */
231
+ export const HEAVY_FILES = Object.freeze([
232
+ ...VOICE_RUNTIME,
233
+ ...KOKORO,
234
+ // what hears a child read aloud, one model per language (ADR-0216 §2); the runtime that runs them is the voice's, above
235
+ ...READING,
236
+ // what hears a child SAY a word of the game, one model per language, with a runtime of its own (issue #184)
237
+ ...COMMANDS,
238
+ // the vision runtime and its models: eye control reads the face (ADR-0213); WebGazer left (ADR-0214)
239
+ ...MEDIAPIPE,
240
+ /*
241
+ * 🔴 THE ART COLLECTION — the fourth heavy thing of ADR-0119, and the only one WITHOUT A SOURCE. Measured: `art/` has
242
+ * TWO files — a README and a 40-byte `ATTRIBUTION.csv`, the header only. No art.
243
+ *
244
+ * 📌 The reason is simple: no collection has been chosen. Art enters under CC0, CC BY 3.0, CC BY 4.0 or OGA-BY, with a
245
+ * ledger line per asset and its source URL — and none of that is one URL a fetcher can ask for. (The Liberated Pixel
246
+ * Cup was refused by ADR-0133: both its arms are share-alike or GPL, outside the closed list of four licences.) This
247
+ * line's source is the day there is a collection.
248
+ */
249
+ {
250
+ id: 'arte:acervo',
251
+ url: null,
252
+ whyNoSource: 'não há acervo escolhido: `art/` tem só README e cabeçalho do CSV. O ADR-0133 fechou '
253
+ + 'a lista em CC0, CC BY 3.0/4.0 e OGA-BY, e a arte entra recurso a recurso com autoria e URL de '
254
+ + 'origem — não por uma URL solta que este buscador possa pedir.',
255
+ },
256
+ ]);
@@ -0,0 +1,20 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /** Upstream prefix → the path the mirror serves it under. Measured against the staging tree on 2026-09-21. */
3
+ export declare const MIRROR_FOLDERS: ReadonlyArray<readonly [string, string]>;
4
+ /**
5
+ * Addresses the project does NOT mirror, each with why — they go on being fetched upstream even when a base is set.
6
+ *
7
+ * 📌 EMPTY, and a line here is a written decision, never an omission. The last one was the npm build of eSpeak NG, kept upstream
8
+ * because the project could not name the source it was built from; the engine now pins its own build, whose folder carries that
9
+ * source (issue #192). ⚠️ Before adding a line, check what the bucket serves: the mirror answers 404 for a folder not uploaded.
10
+ */
11
+ export declare const NOT_MIRRORED: ReadonlyArray<readonly [string, string]>;
12
+ /** The path a mirror serves this upstream address under, or `null` when no mirror of this project holds it. */
13
+ export declare function mirrorPathOf(url: string): string | null;
14
+ /**
15
+ * Where to fetch this file from: the base's copy when there is a base and the file is mirrored, upstream otherwise.
16
+ * A base may be an address (`https://…`) or a folder on this machine — the caller knows how to open each.
17
+ */
18
+ export declare function heavySourceOf(url: string, base?: string | null): string;
19
+ /** Is this base an address, or a folder on the machine running the build? */
20
+ export declare const baseIsRemote: (base: string) => boolean;
@@ -0,0 +1,73 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // platform/heavy-mirror — WHERE A HEAVY FILE IS FETCHED FROM, WHEN IT IS NOT FETCHED FROM UPSTREAM.
3
+ //
4
+ // The Dev, 2026-09-21: «Precisamos de um .env que aponte para local quando estivermos testando em local e em
5
+ // <a conta R2> quando estivermos usando estes recursos na minha conta. Isso facilitaria quando tivermos que hospedar em
6
+ // outros servidores.»
7
+ //
8
+ // The catalogue pins an upstream address AND the sha256 of the bytes (ADR-0177, issue #168). A mirror serves those same
9
+ // bytes somewhere else — the project's Cloudflare, a school's own server, a folder on the build machine — so the only thing
10
+ // that changes is the BASE. Everything else, including the check, stays: a base that serves other bytes fails the sha256 and
11
+ // nothing is written. That is what makes pointing elsewhere safe, and it is why this module does not need to be trusted.
12
+ //
13
+ // The staging tree (`the-inclusionist-lfs`) lays each artefact out as its future Hugging Face repository, so the path under
14
+ // the base is NOT the upstream host and path — it is the folder the mirror uses. That mapping is here, once.
15
+ /** Upstream prefix → the path the mirror serves it under. Measured against the staging tree on 2026-09-21. */
16
+ // ⚠️ Written WITHOUT a trailing slash, exactly as the network inventory (`tests/nothing-comes-from-outside`) already declares each of
17
+ // them: an address that differs by one character reads as a new supplier entering without a decision.
18
+ export const MIRROR_FOLDERS = [
19
+ ['https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main', 'kokoro-82m-v1.0-onnx'],
20
+ ['https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@1.0.1', 'mediapipe-tasks-vision-1.0.1/tasks-vision@1.0.1'],
21
+ ['https://storage.googleapis.com/mediapipe-models', 'mediapipe-tasks-vision-1.0.1/models'],
22
+ // 📌 The reading models have NO upstream: both exports were made by this project (ADR-0201 erratum, ADR-0203), so the address
23
+ // the catalogue pins is already the mirror's. They are listed all the same, and that is what lets a build read them from the
24
+ // staging tree on disk — 850 MiB that nobody should download twice.
25
+ ['https://lfs-oinclusionista.jrocha.dev.br/whisper-small-onnx', 'whisper-small-onnx'],
26
+ ['https://lfs-oinclusionista.jrocha.dev.br/moonshine-streaming-small-onnx', 'moonshine-streaming-small-onnx'],
27
+ ['https://lfs-oinclusionista.jrocha.dev.br/moonshine-streaming-small-es-onnx', 'moonshine-streaming-small-es-onnx'],
28
+ // The command models and the runtime that loads them (issue #184). The runtime has no upstream either — every published
29
+ // `vosk-browser` evaluates text as code, so this one was rebuilt with `-s DYNAMIC_EXECUTION=0` to run under the policy.
30
+ ['https://lfs-oinclusionista.jrocha.dev.br/vosk-browser-dynamic-execution-0', 'vosk-browser-dynamic-execution-0'],
31
+ ['https://lfs-oinclusionista.jrocha.dev.br/vosk-models', 'vosk-models'],
32
+ // The neural voice's phonemizer, the project's own build of eSpeak NG (issue #192): it has no upstream either, and its folder
33
+ // carries the Corresponding Source the GPL asks for — the pinned commit and the recipe, in `corresponding-source/`. The commit is in the folder
34
+ // name on purpose: a mirror that drops it cannot serve two builds during an upgrade.
35
+ ['https://lfs-oinclusionista.jrocha.dev.br/espeak-ng-530bf0a', 'espeak-ng-530bf0a'],
36
+ // The graph runtime the neural voice shares with the reading models (the Dev on 2026-09-22).
37
+ ['https://cdn.jsdelivr.net/npm/onnxruntime-web@1.27.0', 'onnxruntime-web-1.27.0'],
38
+ // The font library (ADR-0255): one folder per family under `fonts/`, catalogued in `platform/font-library.json`. It has no
39
+ // upstream either — the library IS the project's copy, and the reserved-name families in it are their authors' originals.
40
+ ['https://lfs-oinclusionista.jrocha.dev.br/fonts', 'fonts'],
41
+ // 📌 The Libras player's avatar and clips are not catalogue files: `--libras` reads them from `<base>/vlibras-avatar-<commit>/`
42
+ // by their own pins (`scripts/libras-avatar.mjs`), so no mapping for them lives here.
43
+ ];
44
+ /**
45
+ * Addresses the project does NOT mirror, each with why — they go on being fetched upstream even when a base is set.
46
+ *
47
+ * 📌 EMPTY, and a line here is a written decision, never an omission. The last one was the npm build of eSpeak NG, kept upstream
48
+ * because the project could not name the source it was built from; the engine now pins its own build, whose folder carries that
49
+ * source (issue #192). ⚠️ Before adding a line, check what the bucket serves: the mirror answers 404 for a folder not uploaded.
50
+ */
51
+ export const NOT_MIRRORED = [];
52
+ /** The path a mirror serves this upstream address under, or `null` when no mirror of this project holds it. */
53
+ export function mirrorPathOf(url) {
54
+ if (NOT_MIRRORED.some(([prefix]) => url.startsWith(prefix)))
55
+ return null;
56
+ for (const [upstream, folder] of MIRROR_FOLDERS)
57
+ if (url.startsWith(`${upstream}/`))
58
+ return folder + url.slice(upstream.length);
59
+ return null;
60
+ }
61
+ /**
62
+ * Where to fetch this file from: the base's copy when there is a base and the file is mirrored, upstream otherwise.
63
+ * A base may be an address (`https://…`) or a folder on this machine — the caller knows how to open each.
64
+ */
65
+ export function heavySourceOf(url, base) {
66
+ const path = base ? mirrorPathOf(url) : null;
67
+ if (!path)
68
+ return url;
69
+ return `${base.replace(/[/\\]+$/, '')}/${path}`;
70
+ }
71
+ /** Is this base an address, or a folder on the machine running the build? */
72
+ // ⚠️ `\/{2}` and not `\/\/`: a gate reads the tree as text, and two slashes in a row are how a line comment starts.
73
+ export const baseIsRemote = (base) => /^https?:\/{2}/i.test(base);
@@ -0,0 +1,136 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { CACHE_HEAVY, HEAVY_FILES, type HeavyFile } from './heavy-catalogue.js';
3
+ export { CACHE_HEAVY, HEAVY_FILES };
4
+ /** What happened to each entry, so the caller can tell a person. */
5
+ export interface HeavyReport {
6
+ readonly id: string;
7
+ readonly outcome: 'ja-tinha' | 'baixado' | 'falhou' | 'sem-fonte';
8
+ readonly bytes?: number;
9
+ readonly error?: string;
10
+ }
11
+ /**
12
+ * 🔴 WHAT THE DOWNLOAD USES OF THE BROWSER, RECEIVED AND NEVER REACHED (ADR-0232 point 2): the root reads each from the host's
13
+ * window. Required, because a port that falls back to the global is a global reached one step later (ADR-0224/0227).
14
+ */
15
+ export interface HeavyOptions {
16
+ /**
17
+ * The host's `caches`, as its window answers it: `undefined` where it has none (an insecure context), and then every file
18
+ * is reported and none fetched. Required all the same — the key is the root's statement of what it lent.
19
+ */
20
+ readonly cacheStorage: CacheStorage | undefined;
21
+ /** The host's `fetch`, `undefined` where it has none, with the same answer. */
22
+ readonly fetch: typeof fetch | undefined;
23
+ /** Called on each resolved entry — what lets the interface say what is happening. */
24
+ readonly onProgress?: (r: HeavyReport) => void;
25
+ /**
26
+ * The SHA-256 of a body, as lowercase hex (issue #168) — `sha256With(crypto.subtle)`. `null` (a host without
27
+ * `crypto.subtle`, which is an insecure context) keeps NOTHING: unverifiable is not verified.
28
+ */
29
+ readonly digest: ((payload: ArrayBuffer) => Promise<string>) | null;
30
+ /**
31
+ * Only these ids, when given, and IN THIS ORDER — the download is one at a time, so the order is who waits (`heavyAtBoot`
32
+ * puts everything of the child's language first). For a consumer that wants the voices and not the rest.
33
+ */
34
+ readonly only?: readonly string[];
35
+ /**
36
+ * Files OUTSIDE the catalogue, kept by the same rules and FIRST: the font library's faces a cartridge declared
37
+ * (`platform/font-library`, ADR-0255) — a few hundred KB the child sees, which should not wait behind 850 MiB of models.
38
+ */
39
+ readonly also?: readonly HeavyFile[];
40
+ /** The page's address the delivery's `heavy/` folder is resolved against (`document.baseURI`). */
41
+ readonly base: string;
42
+ }
43
+ /**
44
+ * WHAT A GAME'S START FETCHES (ADR-0216 §3): the catalogue, less what this game did not ask for.
45
+ *
46
+ * · The neural voice — its model, its voices AND the runtime that speaks them: without that answer they are 372 MB taken from a
47
+ * school's link and a child's device for nothing.
48
+ * · The reading models, one per language (850 MiB for the three): `reading` is a language or a LIST of them, like `commands`, and
49
+ * the root asks for every language the page can switch to, the child's first (ADR-0225 erratum, the Dev: «Negativo, baixar os
50
+ * três. Toda criança vai experimentar as três línguas imediatamente.»). A language the delivery's `--reading` list left out is a
51
+ * quiet 404 here and, when she reads in it, a line of `problems` and a sentence to her. A game that never listens gets none.
52
+ * · 🔴 THE GRAPH RUNTIME IS NOT THE VOICE'S, and its `voz:` name said otherwise. `platform/onnx-runtime` runs Kokoro AND the
53
+ * reading models, so a game that only LISTENS needs it: without this line its delivery carried a 378 MiB model and nothing
54
+ * able to open it, and the first `listen()` asked for a file the build never wrote. Measured on 2026-09-21, building the
55
+ * very delivery this exists to serve. The PHONEMIZER (`voz:runtime:fonemas`, 18.7 MiB) stays the voice's — nothing else
56
+ * turns letters into sounds.
57
+ * · The command models (issue #184): one per language too, 108 MiB for the three, and the runtime that loads them. Nothing in
58
+ * the game decides this — speaking instead of pressing is a way INTO the controller, and a cartridge does not get to close
59
+ * one (ADR-0111). `commands` is a language or a LIST of them, and the models come in the list's order: the root asks for
60
+ * every language the page can switch to, the child's first, because a language changed mid-game must find its model already
61
+ * kept (ADR-0225 erratum, the Dev: «A entrega leva as três línguas.»). The delivery carries the three unless its
62
+ * `--commands` list narrows it; a language it did not carry is a quiet 404 here and a line of `problems` when she speaks.
63
+ * · The Libras player (ADR-0234): the delivery's list of its avatar, clips, glosses and three.js chunk (34.9 MB in the engine's
64
+ * delivery), only with `libras`: the root asks for it while deaf mode is on, so a device whose child never asks for signing
65
+ * never downloads it. No game declares it either — deaf mode is the person's (ADR-0111) — and a delivery built without
66
+ * `--libras` simply has none, the same quiet 404 as a missing command model. No catalogue file is the player's: it is all the
67
+ * delivery's own, kept by what the delivery carries.
68
+ * The ids are the catalogue's files, then the delivery lists (`DELIVERY_LISTS`), by one rule.
69
+ *
70
+ * 🔴 THE ORDER IS WHO WAITS, because the download is one file at a time (rule 1): a file of a language takes that language's
71
+ * position in the list it was asked by, a file of no language (the runtimes, vision) takes the first, and the sort is stable. So
72
+ * everything of the child's language comes first, then each other language whole — her command model never waits behind 470 MiB
73
+ * of another language's reading.
74
+ * 🔴 AND WITHIN A POSITION, THE WAYS IN COME FIRST (`waitsBehind`): the command models and the camera's reader are how a child
75
+ * who does not press reaches the game at all (ADR-0111), and they have nothing to fall back on; the reading is the game's own
76
+ * listening, with nothing either; the neural voice comes last, because the browser's voice speaks meanwhile (ADR-0200). 📏 In
77
+ * the catalogue's order a 👄 turned on in a fresh install waited behind 336 MiB of neural voice and 378 MiB of reading for a
78
+ * 34 MiB model — seven seconds from a local disk, minutes on a school's link (measured on 2026-09-27).
79
+ */
80
+ export declare function heavyAtBoot(declared: {
81
+ readonly kokoro: boolean;
82
+ readonly reading?: string | readonly string[] | null;
83
+ readonly commands?: string | readonly string[] | null;
84
+ readonly libras?: boolean;
85
+ }): readonly string[];
86
+ /**
87
+ * WHERE THE DELIVERY SERVES A HEAVY FILE (ADR-0177, issue #173): `heavy/<host><path>` beside the page. The child's device
88
+ * reads it from the game's own origin; the upstream address is only where the build fetched it from.
89
+ * 📌 The upstream address stays the CACHE KEY: it is what the voice and vision libraries ask for, and the service worker answers
90
+ * them from the checked cache without a network request.
91
+ *
92
+ * 🔴 THE FOLDER WAS CALLED «pesados» UNTIL 2026-09-21 (ADR-0219). 📏 What that costs a school was measured before it changed:
93
+ * the entries are kept under the UPSTREAM address, so nothing is re-downloaded — what breaks is a delivery built by the old
94
+ * `bin` under a new engine, which asks for `heavy/…` and gets a 404 until the delivery is built again.
95
+ */
96
+ export declare function deliveryPath(url: string): string;
97
+ /**
98
+ * The inverse, for the service worker: a request for `…/heavy/<host><path>` is answered from the entry kept under
99
+ * `https://<host><path>`; any other address has no key (`null`). It is the route's `cacheKeyWillBeUsed` itself, so it also
100
+ * takes Workbox's `{ request }`. Self-contained on purpose — the PWA plugin copies this function's SOURCE into `sw.js`, where
101
+ * nothing else from this module exists.
102
+ *
103
+ * ⚠️ THE OFFSET COMES FROM THE FOLDER'S OWN LENGTH, and it is written this way because of what a blind rename would have done
104
+ * here: the old code advanced by 9, the length of the old folder's name with its slashes, and `/heavy/` is 7 — a text
105
+ * replacement of the name alone would
106
+ * have left every cache key with two characters of the host eaten, and the only symptom would be a cache that never hits.
107
+ */
108
+ export declare function deliveryCacheKey(urlOrRequest: string | {
109
+ readonly request: {
110
+ readonly url: string;
111
+ };
112
+ }): string | null;
113
+ /**
114
+ * DOWNLOADS WHAT IS MISSING, ONE AT A TIME, AND RETURNS WHAT HAPPENED TO EACH.
115
+ *
116
+ * ⚠️ ENTRIES WITHOUT A `url` ARE NOT SKIPPED IN SILENCE — they return `sem-fonte`. It is the difference between "this
117
+ * subsystem has nowhere to come from yet" and "this subsystem is handled", exactly the distinction ADR-0119 measured as
118
+ * missing: the engine PROMISED four things and delivered one, with nothing saying so.
119
+ *
120
+ * The files handed in `also` come first (the declared library fonts), then the catalogue's, then the delivery's lists
121
+ * (`DELIVERY_LISTS`), each list ONE report for all its files.
122
+ */
123
+ export declare function downloadHeavy(options: HeavyOptions): Promise<HeavyReport[]>;
124
+ /**
125
+ * THE SHA-256 OF A BODY AS LOWERCASE HEX, by the `crypto.subtle` it is handed (issue #168) — or `null` when there is none,
126
+ * which is a host outside a secure context: the answer `HeavyOptions.digest` reads as «cannot hash, so keep nothing».
127
+ */
128
+ export declare function sha256With(subtle: Pick<SubtleCrypto, 'digest'> | null | undefined): ((payload: ArrayBuffer) => Promise<string>) | null;
129
+ /**
130
+ * WHETHER A CATALOGUE FILE IS IN THE CHECKED CACHE, by its upstream address — what `platform/vision` and
131
+ * `platform/vosk-runtime` ask before loading anything. The host's `caches` is handed in; `undefined` (an insecure context)
132
+ * holds nothing, so every file is missing and the loader names them.
133
+ */
134
+ export declare function checkedCacheHas(cacheStorage: CacheStorage | undefined): (upstreamUrl: string) => Promise<boolean>;
135
+ /** The size of what is still missing, in bytes — so a notice can say how much is left before it starts. */
136
+ export declare function bytesLeftToDownload(soFar: readonly HeavyReport[]): number;