@seriousgaming/sdk-tools 0.0.0-stage → 1.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +38 -2
  3. package/dist/bundling/logic-exports.d.ts +34 -0
  4. package/dist/bundling/node-builtins.d.ts +21 -0
  5. package/dist/bundling/transpiler.d.ts +7 -0
  6. package/dist/cli.js +27404 -0
  7. package/dist/client/dev-server.d.ts +59 -0
  8. package/dist/client/index.d.ts +28 -0
  9. package/dist/client/stub-services.d.ts +32 -0
  10. package/dist/client/test-session.d.ts +195 -0
  11. package/dist/client.js +16920 -0
  12. package/dist/core/asset-reference-translator.d.ts +46 -0
  13. package/dist/core/clock.d.ts +57 -0
  14. package/dist/core/faults.d.ts +65 -0
  15. package/dist/core/game-settings.d.ts +65 -0
  16. package/dist/core/history.d.ts +89 -0
  17. package/dist/core/listen-with-fallback.d.ts +30 -0
  18. package/dist/core/mutation-queue.d.ts +61 -0
  19. package/dist/core/package-scenario.d.ts +89 -0
  20. package/dist/core/participant-registry.d.ts +109 -0
  21. package/dist/core/pending-changes.d.ts +14 -0
  22. package/dist/core/protocol.d.ts +83 -0
  23. package/dist/core/scenario-drafts.d.ts +32 -0
  24. package/dist/core/session-endpoints.d.ts +108 -0
  25. package/dist/core/session-gates.d.ts +75 -0
  26. package/dist/core/session-host.d.ts +94 -0
  27. package/dist/core/session-refusals.d.ts +56 -0
  28. package/dist/core/session-rewind.d.ts +32 -0
  29. package/dist/core/session-roster.d.ts +128 -0
  30. package/dist/core/session-surfaces.d.ts +32 -0
  31. package/dist/core/session-ticks.d.ts +18 -0
  32. package/dist/core/session-timers.d.ts +84 -0
  33. package/dist/core/session-writes.d.ts +40 -0
  34. package/dist/core/session.d.ts +385 -0
  35. package/dist/core/settings-locks.d.ts +22 -0
  36. package/dist/core/team-names.d.ts +52 -0
  37. package/dist/core/team-state-store.d.ts +218 -0
  38. package/dist/core/tick-timer.d.ts +75 -0
  39. package/dist/dev/blob-links.d.ts +10 -0
  40. package/dist/dev/console/assets/index-DgFglsnA.js +204 -0
  41. package/dist/dev/console/index.html +12 -0
  42. package/dist/dev/console-path.d.ts +19 -0
  43. package/dist/dev/lockfile.d.ts +124 -0
  44. package/dist/dev/package-watcher.d.ts +21 -0
  45. package/dist/dev/routes.d.ts +67 -0
  46. package/dist/dev/shell.d.ts +260 -0
  47. package/dist/dev/surfaces.d.ts +41 -0
  48. package/dist/dev/tools-identity.d.ts +23 -0
  49. package/dist/dev/view/batch.d.ts +172 -0
  50. package/dist/dev/view/commands.d.ts +75 -0
  51. package/dist/dev/view/route.d.ts +58 -0
  52. package/dist/dev/view/view.d.ts +78 -0
  53. package/dist/dev/view/viewer.d.ts +32 -0
  54. package/dist/discovery/config.d.ts +9 -0
  55. package/dist/discovery/manifest-paths.d.ts +21 -0
  56. package/dist/discovery/removed-fields.d.ts +90 -0
  57. package/dist/docs/api/deck.md +386 -0
  58. package/dist/docs/api/index.md +67 -0
  59. package/dist/docs/api/sdk-commands.md +286 -0
  60. package/dist/docs/api/sdk-e2e.md +433 -0
  61. package/dist/docs/api/sdk-projection.md +207 -0
  62. package/dist/docs/api/sdk-testing.md +214 -0
  63. package/dist/docs/api/sdk-tools-client.md +560 -0
  64. package/dist/docs/api/sdk-ui-testing.md +231 -0
  65. package/dist/docs/api/sdk-ui.md +1269 -0
  66. package/dist/docs/api/sdk.md +2140 -0
  67. package/dist/docs/changelog-0.x.md +1156 -0
  68. package/dist/docs/changelog.md +241 -0
  69. package/dist/docs/cli-and-dev-server.md +217 -0
  70. package/dist/docs/cli-error-codes.md +156 -0
  71. package/dist/docs/cli-reference.md +2489 -0
  72. package/dist/docs/cli-simulation-testing.md +222 -0
  73. package/dist/docs/concepts/index.md +46 -0
  74. package/dist/docs/concepts/terminology.md +322 -0
  75. package/dist/docs/environment-variables.md +102 -0
  76. package/dist/docs/getting-started.md +145 -0
  77. package/dist/docs/guides/ai-facilitation.md +220 -0
  78. package/dist/docs/guides/capabilities.md +460 -0
  79. package/dist/docs/guides/endpoints.md +335 -0
  80. package/dist/docs/guides/engine-testing.md +477 -0
  81. package/dist/docs/guides/engine.md +527 -0
  82. package/dist/docs/guides/file-handling.md +405 -0
  83. package/dist/docs/guides/games.md +176 -0
  84. package/dist/docs/guides/global-settings.md +94 -0
  85. package/dist/docs/guides/guide.md +123 -0
  86. package/dist/docs/guides/hooks.md +183 -0
  87. package/dist/docs/guides/index.md +51 -0
  88. package/dist/docs/guides/internationalization.md +288 -0
  89. package/dist/docs/guides/llm-integration.md +635 -0
  90. package/dist/docs/guides/multi-team-games.md +586 -0
  91. package/dist/docs/guides/patterns.md +391 -0
  92. package/dist/docs/guides/presentation.md +196 -0
  93. package/dist/docs/guides/production-constraints.md +130 -0
  94. package/dist/docs/guides/scenario-editor.md +143 -0
  95. package/dist/docs/guides/scenarios.md +515 -0
  96. package/dist/docs/guides/session.md +972 -0
  97. package/dist/docs/guides/settings.md +458 -0
  98. package/dist/docs/guides/setup.md +193 -0
  99. package/dist/docs/guides/speech-generation.md +233 -0
  100. package/dist/docs/guides/starter-game.md +164 -0
  101. package/dist/docs/guides/testing.md +577 -0
  102. package/dist/docs/guides/tick-controller.md +569 -0
  103. package/dist/docs/guides/type-safety.md +516 -0
  104. package/dist/docs/guides/ui.md +1389 -0
  105. package/dist/docs/guides/upgrading.md +636 -0
  106. package/dist/docs/guides/validators.md +217 -0
  107. package/dist/docs/guides/waiting-room.md +244 -0
  108. package/dist/docs/index.md +41 -0
  109. package/dist/docs/recipes/act-on-the-session-from-an-endpoint.md +95 -0
  110. package/dist/docs/recipes/adapt-a-game-for-walkthroughs.md +133 -0
  111. package/dist/docs/recipes/adapt-ui-for-observers.md +74 -0
  112. package/dist/docs/recipes/call-endpoint-from-ui.md +109 -0
  113. package/dist/docs/recipes/check-a-package-from-a-script.md +117 -0
  114. package/dist/docs/recipes/create-capability.md +66 -0
  115. package/dist/docs/recipes/create-endpoint.md +127 -0
  116. package/dist/docs/recipes/create-engine.md +111 -0
  117. package/dist/docs/recipes/create-game.md +70 -0
  118. package/dist/docs/recipes/create-guide.md +75 -0
  119. package/dist/docs/recipes/create-hook.md +80 -0
  120. package/dist/docs/recipes/create-presentation.md +142 -0
  121. package/dist/docs/recipes/create-scenario-editor.md +102 -0
  122. package/dist/docs/recipes/create-scenario.md +98 -0
  123. package/dist/docs/recipes/create-session-ui.md +116 -0
  124. package/dist/docs/recipes/create-settings.md +88 -0
  125. package/dist/docs/recipes/create-setup.md +115 -0
  126. package/dist/docs/recipes/create-tick-controller.md +65 -0
  127. package/dist/docs/recipes/create-user-interface.md +96 -0
  128. package/dist/docs/recipes/create-validator.md +67 -0
  129. package/dist/docs/recipes/create-waiting-room-ui.md +109 -0
  130. package/dist/docs/recipes/declare-api-uses.md +67 -0
  131. package/dist/docs/recipes/design-state-for-concurrent-writes.md +96 -0
  132. package/dist/docs/recipes/distribute-package.md +80 -0
  133. package/dist/docs/recipes/e2e-testing.md +116 -0
  134. package/dist/docs/recipes/end-game-on-condition.md +154 -0
  135. package/dist/docs/recipes/fix-duplicate-packages.md +101 -0
  136. package/dist/docs/recipes/index.md +86 -0
  137. package/dist/docs/recipes/make-an-endpoint-external.md +101 -0
  138. package/dist/docs/recipes/negotiate-across-teams.md +164 -0
  139. package/dist/docs/recipes/observe-other-teams-state.md +119 -0
  140. package/dist/docs/recipes/publish-a-package.md +139 -0
  141. package/dist/docs/recipes/remember-a-viewers-choice.md +55 -0
  142. package/dist/docs/recipes/review-a-past-day.md +73 -0
  143. package/dist/docs/recipes/share-assets-across-scenarios.md +120 -0
  144. package/dist/docs/recipes/share-logic-between-engine-and-ui.md +130 -0
  145. package/dist/docs/recipes/show-all-teams-participants.md +109 -0
  146. package/dist/docs/recipes/start-from-an-empty-package.md +169 -0
  147. package/dist/docs/recipes/take-a-file-in-an-endpoint.md +82 -0
  148. package/dist/docs/recipes/test-a-multi-role-game.md +51 -0
  149. package/dist/docs/recipes/test-user-interface.md +95 -0
  150. package/dist/docs/recipes/test-with-engine.md +115 -0
  151. package/dist/docs/recipes/upload-and-display-files.md +148 -0
  152. package/dist/docs/recipes/use-request-play.md +65 -0
  153. package/dist/docs/recipes/use-request-tick.md +75 -0
  154. package/dist/docs/troubleshooting.md +816 -0
  155. package/dist/execution/blob-inputs.d.ts +57 -0
  156. package/dist/execution/bundle-reload.d.ts +42 -0
  157. package/dist/execution/config-resolver.d.ts +127 -0
  158. package/dist/execution/configuration-builder.d.ts +66 -0
  159. package/dist/execution/context-composition.d.ts +161 -0
  160. package/dist/execution/endpoint-actions.d.ts +9 -0
  161. package/dist/execution/endpoint-payloads.d.ts +32 -0
  162. package/dist/execution/endpoint-runner.d.ts +129 -0
  163. package/dist/execution/engine-state.d.ts +40 -0
  164. package/dist/execution/executor-callbacks.d.ts +56 -0
  165. package/dist/execution/executor.d.ts +436 -0
  166. package/dist/execution/gates.d.ts +45 -0
  167. package/dist/execution/hook-chain.d.ts +25 -0
  168. package/dist/execution/logic-calls.d.ts +190 -0
  169. package/dist/execution/logic-failure.d.ts +84 -0
  170. package/dist/execution/logic-loader.d.ts +54 -0
  171. package/dist/execution/logic-result.d.ts +76 -0
  172. package/dist/execution/tick-controller-call.d.ts +32 -0
  173. package/dist/execution/types.d.ts +48 -0
  174. package/dist/generation/ts-type.d.ts +39 -0
  175. package/dist/guide/locale.d.ts +12 -0
  176. package/dist/guide/video-registry.d.ts +42 -0
  177. package/dist/help-examples.d.ts +125 -0
  178. package/dist/host/adapter.d.ts +67 -0
  179. package/dist/host/host-channel.d.ts +222 -0
  180. package/dist/host/index.d.ts +20 -0
  181. package/dist/host/protocol.d.ts +783 -0
  182. package/dist/host/surfaces.d.ts +42 -0
  183. package/dist/host/theme.d.ts +55 -0
  184. package/dist/host.js +583 -0
  185. package/dist/prompts/index.d.ts +7 -0
  186. package/dist/prompts/schema-builder.d.ts +29 -0
  187. package/dist/prompts/types.d.ts +108 -0
  188. package/dist/prompts/validators.d.ts +32 -0
  189. package/dist/runtime/capability-scope.d.ts +6 -0
  190. package/dist/runtime/context-merge.d.ts +29 -0
  191. package/dist/runtime/context-projection.d.ts +41 -0
  192. package/dist/runtime/guarded-callbacks.d.ts +15 -0
  193. package/dist/runtime/index.d.ts +27 -0
  194. package/dist/runtime/manifest-version.d.ts +55 -0
  195. package/dist/runtime/tick-validation.d.ts +25 -0
  196. package/dist/runtime.js +346 -0
  197. package/dist/schema.json +1546 -0
  198. package/dist/server/vite-plugin.d.ts +46 -0
  199. package/dist/services/tts/client.d.ts +51 -0
  200. package/dist/services/tts/elevenlabs.d.ts +24 -0
  201. package/dist/services/tts/types.d.ts +44 -0
  202. package/dist/storage/asset-resolver.d.ts +49 -0
  203. package/dist/storage/blob-store.d.ts +41 -0
  204. package/dist/templates/endpoint/logic.test.ts.liquid +61 -0
  205. package/dist/templates/endpoint/logic.ts.liquid +25 -0
  206. package/dist/templates/engine/init.json.liquid +7 -0
  207. package/dist/templates/engine/logic-aggregate.test.ts.liquid +90 -0
  208. package/dist/templates/engine/logic-aggregate.ts.liquid +46 -0
  209. package/dist/templates/engine/logic.test.ts.liquid +61 -0
  210. package/dist/templates/engine/logic.ts.liquid +32 -0
  211. package/dist/templates/engine/run.json.liquid +7 -0
  212. package/dist/templates/guide/01-at-a-glance.md.liquid +19 -0
  213. package/dist/templates/guide/02-preparation.md.liquid +18 -0
  214. package/dist/templates/guide/03-running-the-session.md.liquid +37 -0
  215. package/dist/templates/hook/logic.test.ts.liquid +46 -0
  216. package/dist/templates/hook/logic.ts.liquid +12 -0
  217. package/dist/templates/package/CLAUDE.md.template +338 -0
  218. package/dist/templates/package/DESIGN.md.liquid +144 -0
  219. package/dist/templates/package/README.md.liquid +143 -0
  220. package/dist/templates/package/claude/rules/workflow-create-capability.md +26 -0
  221. package/dist/templates/package/claude/rules/workflow-create-endpoint.md +35 -0
  222. package/dist/templates/package/claude/rules/workflow-create-engine.md +35 -0
  223. package/dist/templates/package/claude/rules/workflow-create-guide.md +40 -0
  224. package/dist/templates/package/claude/rules/workflow-create-presentation.md +37 -0
  225. package/dist/templates/package/claude/rules/workflow-create-user-interface.md +31 -0
  226. package/dist/templates/package/claude/rules/workflow-publish-package.md +54 -0
  227. package/dist/templates/package/claude/rules/workflow-test-engine-or-ui.md +30 -0
  228. package/dist/templates/package/claude/rules/workflow-update-sdk-version.md +43 -0
  229. package/dist/templates/package/claude/settings.json.template +16 -0
  230. package/dist/templates/package/gitignore.template +15 -0
  231. package/dist/templates/package/global-setup.ts.template +21 -0
  232. package/dist/templates/package/globals.d.ts.template +2 -0
  233. package/dist/templates/package/oxfmtrc.json.template +14 -0
  234. package/dist/templates/package/oxlintrc.json.template +238 -0
  235. package/dist/templates/package/package.json.liquid +65 -0
  236. package/dist/templates/package/playwright.config.ts.liquid +19 -0
  237. package/dist/templates/package/pnpm-workspace.yaml.template +27 -0
  238. package/dist/templates/package/test-setup.ts.liquid +7 -0
  239. package/dist/templates/package/tsconfig.json.liquid +15 -0
  240. package/dist/templates/package/vite.config.ts.liquid +19 -0
  241. package/dist/templates/package/vitest.config.ts.liquid +25 -0
  242. package/dist/templates/package/vitest.engine.config.ts.liquid +12 -0
  243. package/dist/templates/presentation/index.html.liquid +20 -0
  244. package/dist/templates/presentation/src/App.tsx.liquid +49 -0
  245. package/dist/templates/presentation/src/Slides.tsx.liquid +81 -0
  246. package/dist/templates/presentation/src/i18n.ts.liquid +54 -0
  247. package/dist/templates/presentation/src/main.tsx.liquid +14 -0
  248. package/dist/templates/scenario_editor/src/App.test.tsx.liquid +30 -0
  249. package/dist/templates/scenario_editor/src/App.tsx.liquid +95 -0
  250. package/dist/templates/scenario_editor/src/i18n.ts.liquid +44 -0
  251. package/dist/templates/session/src/App.test.tsx.liquid +60 -0
  252. package/dist/templates/session/src/App.tsx.liquid +128 -0
  253. package/dist/templates/session/src/i18n.ts.liquid +53 -0
  254. package/dist/templates/session/src/main.tsx.liquid +48 -0
  255. package/dist/templates/session/src/theme.ts.liquid +46 -0
  256. package/dist/templates/settings-editor/index.html.liquid +12 -0
  257. package/dist/templates/settings-editor/src/main.tsx.liquid +48 -0
  258. package/dist/templates/settings-editor/src/theme.ts.liquid +24 -0
  259. package/dist/templates/setup/src/App.test.tsx.liquid +39 -0
  260. package/dist/templates/setup/src/App.tsx.liquid +102 -0
  261. package/dist/templates/setup/src/i18n.ts.liquid +47 -0
  262. package/dist/templates/starter-game/capabilities/briefing/capability.sdk.json +18 -0
  263. package/dist/templates/starter-game/capabilities/plan/capability.sdk.json +17 -0
  264. package/dist/templates/starter-game/capabilities/results/capability.sdk.json +61 -0
  265. package/dist/templates/starter-game/capabilities/roles/capability.sdk.json +17 -0
  266. package/dist/templates/starter-game/capabilities/weather/capability.sdk.json +23 -0
  267. package/dist/templates/starter-game/engine/defaults.ts +81 -0
  268. package/dist/templates/starter-game/engine/engine.sdk.json +12 -0
  269. package/dist/templates/starter-game/engine/logic.test.ts +221 -0
  270. package/dist/templates/starter-game/engine/logic.ts +149 -0
  271. package/dist/templates/starter-game/engine/test-helpers.ts +74 -0
  272. package/dist/templates/starter-game/engine/types.ts +139 -0
  273. package/dist/templates/starter-game/guide/content/en/01-at-a-glance.md +51 -0
  274. package/dist/templates/starter-game/guide/content/en/02-preparation.md +35 -0
  275. package/dist/templates/starter-game/guide/content/en/03-running-the-day.md +58 -0
  276. package/dist/templates/starter-game/guide/guide.sdk.json +10 -0
  277. package/dist/templates/starter-game/guide/guide.test.ts +108 -0
  278. package/dist/templates/starter-game/hooks/assignproducts/defaults.ts +37 -0
  279. package/dist/templates/starter-game/hooks/assignproducts/hook.sdk.json +13 -0
  280. package/dist/templates/starter-game/hooks/assignproducts/logic/logic.test.ts +77 -0
  281. package/dist/templates/starter-game/hooks/assignproducts/logic/logic.ts +47 -0
  282. package/dist/templates/starter-game/hooks/assignproducts/types.ts +55 -0
  283. package/dist/templates/starter-game/package.json +68 -0
  284. package/dist/templates/starter-game/playwright.config.ts +19 -0
  285. package/dist/templates/starter-game/scenarios/heatwave/scenario.sdk.json +20 -0
  286. package/dist/templates/starter-game/scenarios/ordinary_week/scenario.sdk.json +12 -0
  287. package/dist/templates/starter-game/seriousgaming.sdk.json +23 -0
  288. package/dist/templates/starter-game/session/defaults.ts +80 -0
  289. package/dist/templates/starter-game/session/index.html +12 -0
  290. package/dist/templates/starter-game/session/session.sdk.json +11 -0
  291. package/dist/templates/starter-game/session/src/App.test.tsx +307 -0
  292. package/dist/templates/starter-game/session/src/App.tsx +309 -0
  293. package/dist/templates/starter-game/session/src/Section.tsx +37 -0
  294. package/dist/templates/starter-game/session/src/TeamDoor.tsx +96 -0
  295. package/dist/templates/starter-game/session/src/format.ts +8 -0
  296. package/dist/templates/starter-game/session/src/i18n.ts +51 -0
  297. package/dist/templates/starter-game/session/src/main.tsx +48 -0
  298. package/dist/templates/starter-game/session/src/theme.ts +45 -0
  299. package/dist/templates/starter-game/session/types.ts +135 -0
  300. package/dist/templates/starter-game/settings/engine/settings.sdk.json +50 -0
  301. package/dist/templates/starter-game/settings/menu/settings.sdk.json +78 -0
  302. package/dist/templates/starter-game/settings/session/settings.sdk.json +23 -0
  303. package/dist/templates/starter-game/settings/ui/settings.sdk.json +25 -0
  304. package/dist/templates/starter-game/test-setup.ts +7 -0
  305. package/dist/templates/starter-game/testing/e2e/game.spec.ts +139 -0
  306. package/dist/templates/starter-game/testing/e2e/global-setup.ts +21 -0
  307. package/dist/templates/starter-game/testing/engine/game.engine.test.ts +171 -0
  308. package/dist/templates/starter-game/tsconfig.json +19 -0
  309. package/dist/templates/starter-game/ui/defaults.ts +60 -0
  310. package/dist/templates/starter-game/ui/index.html +12 -0
  311. package/dist/templates/starter-game/ui/src/App.test.tsx +138 -0
  312. package/dist/templates/starter-game/ui/src/App.tsx +175 -0
  313. package/dist/templates/starter-game/ui/src/DayBar.test.tsx +78 -0
  314. package/dist/templates/starter-game/ui/src/DayBar.tsx +72 -0
  315. package/dist/templates/starter-game/ui/src/HistoryPanel.test.tsx +74 -0
  316. package/dist/templates/starter-game/ui/src/HistoryPanel.tsx +120 -0
  317. package/dist/templates/starter-game/ui/src/MakeRow.tsx +129 -0
  318. package/dist/templates/starter-game/ui/src/Section.tsx +37 -0
  319. package/dist/templates/starter-game/ui/src/ThemeToggle.tsx +49 -0
  320. package/dist/templates/starter-game/ui/src/TodayPanel.test.tsx +179 -0
  321. package/dist/templates/starter-game/ui/src/TodayPanel.tsx +92 -0
  322. package/dist/templates/starter-game/ui/src/YesterdayPanel.tsx +142 -0
  323. package/dist/templates/starter-game/ui/src/format.ts +12 -0
  324. package/dist/templates/starter-game/ui/src/i18n.ts +95 -0
  325. package/dist/templates/starter-game/ui/src/main.tsx +48 -0
  326. package/dist/templates/starter-game/ui/src/menu.ts +18 -0
  327. package/dist/templates/starter-game/ui/src/test-helpers.ts +58 -0
  328. package/dist/templates/starter-game/ui/src/theme.ts +45 -0
  329. package/dist/templates/starter-game/ui/src/writes.ts +43 -0
  330. package/dist/templates/starter-game/ui/types.ts +137 -0
  331. package/dist/templates/starter-game/ui/ui.sdk.json +11 -0
  332. package/dist/templates/starter-game/validators/capacity/defaults.ts +37 -0
  333. package/dist/templates/starter-game/validators/capacity/logic/logic.test.ts +96 -0
  334. package/dist/templates/starter-game/validators/capacity/logic/logic.ts +45 -0
  335. package/dist/templates/starter-game/validators/capacity/types.ts +55 -0
  336. package/dist/templates/starter-game/validators/capacity/validator.sdk.json +11 -0
  337. package/dist/templates/starter-game/vite.config.ts +19 -0
  338. package/dist/templates/starter-game/vitest.config.ts +15 -0
  339. package/dist/templates/starter-game/vitest.engine.config.ts +19 -0
  340. package/dist/templates/starter-game/waiting_room/defaults.ts +40 -0
  341. package/dist/templates/starter-game/waiting_room/index.html +12 -0
  342. package/dist/templates/starter-game/waiting_room/src/App.test.tsx +102 -0
  343. package/dist/templates/starter-game/waiting_room/src/App.tsx +194 -0
  344. package/dist/templates/starter-game/waiting_room/src/i18n.ts +33 -0
  345. package/dist/templates/starter-game/waiting_room/src/main.tsx +48 -0
  346. package/dist/templates/starter-game/waiting_room/src/theme.ts +45 -0
  347. package/dist/templates/starter-game/waiting_room/types.ts +59 -0
  348. package/dist/templates/starter-game/waiting_room/waiting_room.sdk.json +10 -0
  349. package/dist/templates/tick-controller/logic.ts.liquid +8 -0
  350. package/dist/templates/ui/index.html.liquid +12 -0
  351. package/dist/templates/ui/src/App.test.tsx.liquid +41 -0
  352. package/dist/templates/ui/src/App.tsx.liquid +103 -0
  353. package/dist/templates/ui/src/i18n.ts.liquid +47 -0
  354. package/dist/templates/ui/src/main.tsx.liquid +48 -0
  355. package/dist/templates/ui/src/theme.ts.liquid +46 -0
  356. package/dist/templates/validator/logic.test.ts.liquid +42 -0
  357. package/dist/templates/validator/logic.ts.liquid +21 -0
  358. package/dist/templates/waiting-room/index.html.liquid +12 -0
  359. package/dist/templates/waiting-room/src/App.test.tsx.liquid +57 -0
  360. package/dist/templates/waiting-room/src/App.tsx.liquid +118 -0
  361. package/dist/templates/waiting-room/src/i18n.ts.liquid +44 -0
  362. package/dist/templates/waiting-room/src/main.tsx.liquid +48 -0
  363. package/dist/templates/waiting-room/src/theme.ts.liquid +46 -0
  364. package/dist/templating/resource-metadata.d.ts +131 -0
  365. package/dist/types.d.ts +14 -0
  366. package/dist/utils/atomic-write.d.ts +40 -0
  367. package/dist/utils/cli-error.d.ts +64 -0
  368. package/dist/utils/document-parser-client.d.ts +20 -0
  369. package/dist/utils/env-loader.d.ts +40 -0
  370. package/dist/utils/error-codes.d.ts +339 -0
  371. package/dist/utils/errors.d.ts +19 -0
  372. package/dist/utils/global-settings.d.ts +65 -0
  373. package/dist/utils/llm-client.d.ts +34 -0
  374. package/dist/utils/logger.d.ts +36 -0
  375. package/dist/utils/output.d.ts +109 -0
  376. package/dist/utils/platform.d.ts +14 -0
  377. package/dist/utils/prompt.d.ts +36 -0
  378. package/dist/utils/real-path.d.ts +6 -0
  379. package/dist/utils/schema-properties.d.ts +35 -0
  380. package/dist/validation/ajv.d.ts +17 -0
  381. package/dist/validation/facilitator-guide-validator.d.ts +27 -0
  382. package/dist/validation/findings.d.ts +40 -0
  383. package/dist/validation/game-constraints.d.ts +10 -0
  384. package/dist/validation/game-validator.d.ts +34 -0
  385. package/dist/validation/package-validation.d.ts +41 -0
  386. package/dist/validation/package-validator.d.ts +19 -0
  387. package/dist/validation/resource-validator.d.ts +79 -0
  388. package/dist/validation/schema-defaults-validator.d.ts +29 -0
  389. package/dist/validation/schema-validation.d.ts +115 -0
  390. package/dist/validation/semver.d.ts +9 -0
  391. package/package.json +123 -3
@@ -0,0 +1,1546 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$defs": {
4
+ "PackageDefinition": {
5
+ "type": "object",
6
+ "description": "Definition of a package",
7
+ "properties": {
8
+ "identifier": {
9
+ "type": "string",
10
+ "description": "Namespace-style identifier for the package",
11
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
12
+ },
13
+ "name": {
14
+ "type": "string",
15
+ "description": "Name of the package"
16
+ },
17
+ "version": {
18
+ "type": "string",
19
+ "description": "Semantic version of the package",
20
+ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$"
21
+ }
22
+ },
23
+ "required": ["identifier", "name", "version"],
24
+ "additionalProperties": false
25
+ },
26
+ "EndpointActionType": {
27
+ "type": "string",
28
+ "description": "A session action an endpoint may return for the runtime to carry out after its write. Each is the operation a facilitator's session surface can perform, held to the same rules; an endpoint may return only the actions it declares.",
29
+ "enum": [
30
+ "tick",
31
+ "setWaitingRoom",
32
+ "pauseTimer",
33
+ "resumeTimer",
34
+ "extendTick",
35
+ "renameTeam",
36
+ "moveParticipant",
37
+ "addTeam",
38
+ "setLocale"
39
+ ]
40
+ },
41
+ "RequiredFeatures": {
42
+ "type": "array",
43
+ "description": "Optional runtime features the game depends on, by name. A runtime that does not support every listed feature refuses the package at load, naming the feature, rather than running it half-working. This is how a feature arrives within a manifest version without a new one. Absent or empty means the game needs nothing beyond its manifest version.",
44
+ "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
45
+ "uniqueItems": true
46
+ },
47
+ "ScenarioFormat": {
48
+ "type": "integer",
49
+ "minimum": 1,
50
+ "default": 1,
51
+ "description": "The format of the game's scenarios, which the author bumps whenever a custom scenario saved against an earlier value may no longer be correct: a setting removed, renamed or reshaped, a change in what a value means, or a change in how the game loads scenario assets. A purely additive change, such as a new setting with a default, needs no bump. A runtime stores it with each custom scenario it persists and refuses to apply a saved scenario whose format differs from the package's. Absent means 1."
52
+ },
53
+ "ApiUse": {
54
+ "type": "string",
55
+ "description": "Runtime callback API (a service) a logic-bearing resource is permitted to invoke. A declared API is always present for that resource, and a runtime that cannot provide one a package declares refuses the package at load. Calling an undeclared API throws at runtime, in both dev and production. Resources that omit `uses` (or declare an empty array) cannot call any callbacks.",
56
+ "enum": ["generateText", "extractText", "generateSpeech", "writeBlob"]
57
+ },
58
+ "GlobalSettings": {
59
+ "type": "object",
60
+ "description": "User-owned global settings file (~/.seriousgaming-sdk/config.json). Stores API keys and defaults once so every project picks them up. This is the lowest-priority configuration source: .env files, environment variables, and CLI flags all override it. The file is plaintext and must not be committed to git.",
61
+ "properties": {
62
+ "elevenLabs": {
63
+ "type": "object",
64
+ "description": "ElevenLabs integration settings.",
65
+ "properties": {
66
+ "apiKey": {
67
+ "type": "string",
68
+ "description": "ElevenLabs API key."
69
+ }
70
+ },
71
+ "additionalProperties": false
72
+ },
73
+ "platform": {
74
+ "type": "object",
75
+ "description": "Serious Gaming platform settings used by `package publish` and LLM text generation.",
76
+ "properties": {
77
+ "apiHost": {
78
+ "type": "string",
79
+ "description": "Serious Gaming platform API host."
80
+ },
81
+ "apiKey": {
82
+ "type": "string",
83
+ "description": "Serious Gaming platform API key."
84
+ },
85
+ "defaultPublisher": {
86
+ "type": "string",
87
+ "description": "Default publisher identifier used when publishing packages."
88
+ }
89
+ },
90
+ "additionalProperties": false
91
+ }
92
+ },
93
+ "additionalProperties": false
94
+ },
95
+ "EngineDefinition": {
96
+ "type": "object",
97
+ "description": "Definition of a game's engine: the logic that computes each tick",
98
+ "properties": {
99
+ "identifier": {
100
+ "type": "string",
101
+ "description": "Identifier for the engine. A game holds one, in the `engine` slot, and the slot is the identifier.",
102
+ "pattern": "^[a-z][a-z0-9_]*$"
103
+ },
104
+ "reads": {
105
+ "type": "array",
106
+ "description": "Identifiers of the capabilities this engine reads",
107
+ "items": {
108
+ "type": "string",
109
+ "pattern": "^[a-z][a-z0-9_]*$"
110
+ },
111
+ "uniqueItems": true
112
+ },
113
+ "writes": {
114
+ "type": "array",
115
+ "description": "Identifiers of the capabilities this engine writes",
116
+ "items": {
117
+ "type": "string",
118
+ "pattern": "^[a-z][a-z0-9_]*$"
119
+ },
120
+ "uniqueItems": true
121
+ },
122
+ "uses": {
123
+ "type": "array",
124
+ "description": "Runtime callback APIs this engine is permitted to invoke. The runtime throws when this engine calls a callback whose name is not listed here.",
125
+ "items": { "$ref": "#/$defs/ApiUse" },
126
+ "uniqueItems": true,
127
+ "default": []
128
+ },
129
+ "settings": {
130
+ "type": "array",
131
+ "description": "Identifiers of the settings resources this engine reads. It receives exactly these, read-only, as settings.<identifier>",
132
+ "items": {
133
+ "type": "string",
134
+ "pattern": "^[a-z][a-z0-9_]*$"
135
+ },
136
+ "uniqueItems": true
137
+ },
138
+ "aggregate": {
139
+ "type": "boolean",
140
+ "description": "Generated, not authored. True when the engine's logic exports InitAggregate and RunAggregate, in which case it runs once across all teams rather than per-team via Run, and may write to shared capabilities. The build derives this from the exports and writes it into the bundled manifest; authoring it in engine.sdk.json is an error.",
141
+ "default": false
142
+ }
143
+ },
144
+ "required": ["identifier"],
145
+ "additionalProperties": false
146
+ },
147
+ "CapabilityDefinition": {
148
+ "type": "object",
149
+ "description": "Definition of a capability",
150
+ "properties": {
151
+ "identifier": {
152
+ "type": "string",
153
+ "description": "Namespace-style identifier for the capability",
154
+ "pattern": "^[a-z][a-z0-9_]*$"
155
+ },
156
+ "variablesSchema": {
157
+ "type": "object",
158
+ "description": "JSON Schema describing the variables provided by this capability",
159
+ "$comment": "This should be a valid JSON Schema object defining properties, types, required fields, etc."
160
+ },
161
+ "scope": {
162
+ "type": "string",
163
+ "enum": ["team", "team-readable", "shared", "private"],
164
+ "description": "Visibility of this capability's state. 'team' (default): per team, delivered to that team's surfaces. 'team-readable': each team writes only its own copy, but user interfaces on other teams may observe every team's value live in shared-state games. 'shared': one value for all teams, written by an aggregate engine, a facilitator's shared write or a session-scoped endpoint, and synchronised between teams by the production coordinator. 'private': per team like 'team', but never delivered to any user interface, never included in session data or cross-team data; for engine bookkeeping no surface should depend on. A user interface declaring one in reads or writes fails the build."
165
+ },
166
+ "lifetime": {
167
+ "type": "string",
168
+ "enum": ["tick", "session"],
169
+ "description": "How long a value lasts. 'tick' (default): part of each tick snapshot, so undo and reset rewind it with the round. 'session': kept out of tick snapshots, so neither undo nor reset touches it; seeded from its defaults once, when the session (or a team added later) is created, and persisted across restarts. For facilitator state such as setup completed, pacing gates, or an announcement. Read and written by surfaces, endpoints, hooks and validators; the build refuses one in the engine's reads or writes, because a tick must be replayable from its snapshot"
170
+ }
171
+ },
172
+ "required": ["identifier", "variablesSchema"],
173
+ "additionalProperties": false
174
+ },
175
+ "SettingsDefinition": {
176
+ "type": "object",
177
+ "description": "Definition of a settings resource: named, read-only parameters a game declares once and any resource may read by listing it in its settings. Overridden only by the active scenario and by the session's setup step, and fixed when play starts.",
178
+ "properties": {
179
+ "identifier": {
180
+ "type": "string",
181
+ "description": "Namespace-style identifier for the settings resource",
182
+ "pattern": "^[a-z][a-z0-9_]*$"
183
+ },
184
+ "settingsSchema": {
185
+ "type": "object",
186
+ "description": "JSON Schema describing these settings. A full object schema, and every property MUST declare a default. `readOnly: true` on a property, at any depth, fixes it and everything under it at the default: no scenario or session may change it",
187
+ "$comment": "This should be a valid JSON Schema object defining properties, types, and a default for each."
188
+ }
189
+ },
190
+ "required": ["identifier", "settingsSchema"],
191
+ "additionalProperties": false
192
+ },
193
+ "SDKSettings": {
194
+ "type": "object",
195
+ "description": "Bundle containing a settings definition",
196
+ "properties": {
197
+ "definition": {
198
+ "$ref": "#/$defs/SettingsDefinition"
199
+ }
200
+ },
201
+ "required": ["definition"],
202
+ "additionalProperties": false
203
+ },
204
+ "UserInterfaceDefinition": {
205
+ "type": "object",
206
+ "description": "Definition of a user interface with internationalization support",
207
+ "properties": {
208
+ "identifier": {
209
+ "type": "string",
210
+ "description": "Namespace-style identifier for the user interface",
211
+ "pattern": "^[a-z][a-z0-9_]*$"
212
+ },
213
+ "reads": {
214
+ "type": "array",
215
+ "description": "Identifiers of the capabilities this user interface reads",
216
+ "items": {
217
+ "type": "string",
218
+ "pattern": "^[a-z][a-z0-9_]*$"
219
+ },
220
+ "uniqueItems": true
221
+ },
222
+ "crossTeamReads": {
223
+ "type": "array",
224
+ "description": "Identifiers of the capabilities this user interface receives every team's value of, live, rather than its own team's alone. Every entry MUST also appear in `reads`, and MUST name a capability with scope 'team-readable'. Only meaningful in shared-state games.",
225
+ "items": {
226
+ "type": "string",
227
+ "pattern": "^[a-z][a-z0-9_]*$"
228
+ },
229
+ "uniqueItems": true,
230
+ "default": []
231
+ },
232
+ "writes": {
233
+ "type": "array",
234
+ "description": "Identifiers of the capabilities this user interface writes",
235
+ "items": {
236
+ "type": "string",
237
+ "pattern": "^[a-z][a-z0-9_]*$"
238
+ },
239
+ "uniqueItems": true
240
+ },
241
+ "endpoints": {
242
+ "type": "array",
243
+ "description": "Endpoint identifiers this user interface is permitted to call via `callbacks.endpoints[<identifier>]`. The host throws when this UI requests an endpoint whose identifier is not listed here.",
244
+ "items": {
245
+ "type": "string",
246
+ "pattern": "^[a-z][a-z0-9_]*$"
247
+ },
248
+ "uniqueItems": true,
249
+ "default": []
250
+ },
251
+ "crossTeamParticipants": {
252
+ "type": "boolean",
253
+ "description": "If true, this user interface may read the participant roster of every team via `callbacks.getAllTeamsParticipants()`, not just its own team. Only meaningful in shared-state games; a game that is not shared-state and references a UI declaring this MUST fail the build.",
254
+ "default": false
255
+ },
256
+ "settings": {
257
+ "type": "array",
258
+ "description": "Identifiers of the settings resources this user interface reads. It receives exactly these, read-only, as settings.<identifier>",
259
+ "items": {
260
+ "type": "string",
261
+ "pattern": "^[a-z][a-z0-9_]*$"
262
+ },
263
+ "uniqueItems": true
264
+ }
265
+ },
266
+ "required": ["identifier"],
267
+ "additionalProperties": false
268
+ },
269
+ "SessionUserInterfaceDefinition": {
270
+ "type": "object",
271
+ "description": "Definition of a session user interface with internationalization support",
272
+ "properties": {
273
+ "identifier": {
274
+ "type": "string",
275
+ "description": "Namespace-style identifier for the session user interface",
276
+ "pattern": "^[a-z][a-z0-9_]*$"
277
+ },
278
+ "reads": {
279
+ "type": "array",
280
+ "description": "Identifiers of the capabilities this session user interface reads",
281
+ "items": {
282
+ "type": "string",
283
+ "pattern": "^[a-z][a-z0-9_]*$"
284
+ },
285
+ "uniqueItems": true
286
+ },
287
+ "writes": {
288
+ "type": "array",
289
+ "description": "Identifiers of the capabilities this session user interface writes",
290
+ "items": {
291
+ "type": "string",
292
+ "pattern": "^[a-z][a-z0-9_]*$"
293
+ },
294
+ "uniqueItems": true
295
+ },
296
+ "endpoints": {
297
+ "type": "array",
298
+ "description": "Endpoint identifiers this session user interface is permitted to call via `callbacks.endpoints[<identifier>]`. The host throws when this UI requests an endpoint whose identifier is not listed here.",
299
+ "items": {
300
+ "type": "string",
301
+ "pattern": "^[a-z][a-z0-9_]*$"
302
+ },
303
+ "uniqueItems": true,
304
+ "default": []
305
+ },
306
+ "settings": {
307
+ "type": "array",
308
+ "description": "Identifiers of the settings resources this session user interface reads. It receives exactly these, read-only, as settings.<identifier>",
309
+ "items": {
310
+ "type": "string",
311
+ "pattern": "^[a-z][a-z0-9_]*$"
312
+ },
313
+ "uniqueItems": true
314
+ }
315
+ },
316
+ "required": ["identifier"],
317
+ "additionalProperties": false
318
+ },
319
+ "WaitingRoomUserInterfaceDefinition": {
320
+ "type": "object",
321
+ "description": "Definition of a waiting room user interface (the holding screen shown to players while the session's waiting room is open)",
322
+ "properties": {
323
+ "identifier": {
324
+ "type": "string",
325
+ "description": "Namespace-style identifier for the waiting room user interface",
326
+ "pattern": "^[a-z][a-z0-9_]*$"
327
+ },
328
+ "reads": {
329
+ "type": "array",
330
+ "description": "Identifiers of the capabilities this waiting room user interface reads",
331
+ "items": {
332
+ "type": "string",
333
+ "pattern": "^[a-z][a-z0-9_]*$"
334
+ },
335
+ "uniqueItems": true
336
+ },
337
+ "crossTeamReads": {
338
+ "type": "array",
339
+ "description": "Identifiers of the capabilities this waiting room user interface receives every team's value of, live, rather than its own team's alone. Every entry MUST also appear in `reads`, and MUST name a capability with scope 'team-readable'. Only meaningful in shared-state games.",
340
+ "items": {
341
+ "type": "string",
342
+ "pattern": "^[a-z][a-z0-9_]*$"
343
+ },
344
+ "uniqueItems": true,
345
+ "default": []
346
+ },
347
+ "writes": {
348
+ "type": "array",
349
+ "description": "Identifiers of the capabilities this waiting room user interface writes",
350
+ "items": {
351
+ "type": "string",
352
+ "pattern": "^[a-z][a-z0-9_]*$"
353
+ },
354
+ "uniqueItems": true
355
+ },
356
+ "endpoints": {
357
+ "type": "array",
358
+ "description": "Endpoint identifiers this waiting room user interface is permitted to call via `callbacks.endpoints[<identifier>]`. The host throws when this UI requests an endpoint whose identifier is not listed here.",
359
+ "items": {
360
+ "type": "string",
361
+ "pattern": "^[a-z][a-z0-9_]*$"
362
+ },
363
+ "uniqueItems": true,
364
+ "default": []
365
+ },
366
+ "crossTeamParticipants": {
367
+ "type": "boolean",
368
+ "description": "If true, this waiting room user interface may read the participant roster of every team via `callbacks.getAllTeamsParticipants()`, not just its own team. Only meaningful in shared-state games; a game that is not shared-state and references a UI declaring this MUST fail the build.",
369
+ "default": false
370
+ },
371
+ "settings": {
372
+ "type": "array",
373
+ "description": "Identifiers of the settings resources this waiting room user interface reads. It receives exactly these, read-only, as settings.<identifier>",
374
+ "items": {
375
+ "type": "string",
376
+ "pattern": "^[a-z][a-z0-9_]*$"
377
+ },
378
+ "uniqueItems": true
379
+ }
380
+ },
381
+ "required": ["identifier"],
382
+ "additionalProperties": false
383
+ },
384
+ "SetupDefinition": {
385
+ "type": "object",
386
+ "description": "Definition of the game's setup user interface: a small form shown at session creation, whose changes become session overrides for that session only (§8.2, §8.3). Its presence is what gives a session its configuration step",
387
+ "properties": {
388
+ "identifier": {
389
+ "type": "string",
390
+ "description": "The slot, `setup`. A game holds one setup user interface, so it carries no name of its own",
391
+ "pattern": "^[a-z][a-z0-9_]*$"
392
+ },
393
+ "configures": {
394
+ "type": "array",
395
+ "description": "Identifiers of the settings resources this setup user interface edits, the built-in `game` included. It is sent their resolved values through `setSettings`, keyed by identifier, and writes changes to them through `updateSettings`",
396
+ "items": {
397
+ "type": "string",
398
+ "pattern": "^[a-z][a-z0-9_]*$"
399
+ },
400
+ "uniqueItems": true,
401
+ "default": []
402
+ },
403
+ "endpoints": {
404
+ "type": "array",
405
+ "description": "Endpoint identifiers this setup user interface is permitted to call via `callbacks.endpoints[<identifier>]`. The host throws when this UI requests an endpoint whose identifier is not listed here.",
406
+ "items": {
407
+ "type": "string",
408
+ "pattern": "^[a-z][a-z0-9_]*$"
409
+ },
410
+ "uniqueItems": true,
411
+ "default": []
412
+ }
413
+ },
414
+ "required": ["identifier"],
415
+ "additionalProperties": false
416
+ },
417
+ "ScenarioEditorDefinition": {
418
+ "type": "object",
419
+ "description": "Definition of the game's scenario editor: an authoring screen, used at any time and with no session, whose output is a lasting scenario (§6.7.1). Optional: `customScenarios.supported` is what switches custom scenarios on",
420
+ "properties": {
421
+ "identifier": {
422
+ "type": "string",
423
+ "description": "The slot, `scenario_editor`. A game holds one scenario editor, so it carries no name of its own",
424
+ "pattern": "^[a-z][a-z0-9_]*$"
425
+ },
426
+ "configures": {
427
+ "type": "array",
428
+ "description": "Identifiers of the settings resources this scenario editor edits, the built-in `game` included. It is sent their resolved values through `setSettings`, keyed by identifier, and writes changes to them through `updateSettings`",
429
+ "items": {
430
+ "type": "string",
431
+ "pattern": "^[a-z][a-z0-9_]*$"
432
+ },
433
+ "uniqueItems": true,
434
+ "default": []
435
+ },
436
+ "endpoints": {
437
+ "type": "array",
438
+ "description": "Endpoint identifiers this scenario editor is permitted to call via `callbacks.endpoints[<identifier>]`. The host throws when this UI requests an endpoint whose identifier is not listed here.",
439
+ "items": {
440
+ "type": "string",
441
+ "pattern": "^[a-z][a-z0-9_]*$"
442
+ },
443
+ "uniqueItems": true,
444
+ "default": []
445
+ }
446
+ },
447
+ "required": ["identifier"],
448
+ "additionalProperties": false
449
+ },
450
+ "ScenarioDefinition": {
451
+ "type": "object",
452
+ "description": "Definition of a scenario — a named flavour of a game bundling settings overrides and static assets",
453
+ "properties": {
454
+ "identifier": {
455
+ "type": "string",
456
+ "description": "Namespace-style identifier for the scenario",
457
+ "pattern": "^[a-z][a-z0-9_]*$"
458
+ },
459
+ "locales": {
460
+ "type": "object",
461
+ "description": "Localized scenario fields with one entry per supported locale",
462
+ "patternProperties": {
463
+ "^[a-z]{2}(-[A-Z]{2})?$": {
464
+ "type": "object",
465
+ "description": "Localized fields for this locale",
466
+ "properties": {
467
+ "name": {
468
+ "type": "string",
469
+ "description": "Display name for this locale"
470
+ },
471
+ "description": {
472
+ "type": "string",
473
+ "description": "Short description for this locale"
474
+ }
475
+ },
476
+ "required": ["name"],
477
+ "additionalProperties": false
478
+ }
479
+ },
480
+ "minProperties": 1,
481
+ "additionalProperties": false
482
+ },
483
+ "default": {
484
+ "type": "boolean",
485
+ "description": "If true, this scenario is selected when no explicit scenario is chosen at init time. At most one scenario per package should set it.",
486
+ "default": false
487
+ },
488
+ "restricted": {
489
+ "type": "boolean",
490
+ "description": "If true, this scenario is built for a particular audience and a runtime must not offer, list, resolve or serve it to a caller it has not granted it to. The package never names that audience. Cannot be combined with `default`.",
491
+ "default": false
492
+ },
493
+ "settings": {
494
+ "type": "object",
495
+ "description": "Settings overrides applied when this scenario is selected, keyed by settings identifier. Each value is a partial object of that settings resource's properties. The game-level settings (the number of rounds, the team bounds and names, and whether the waiting room opens with the session) are the built-in `game` settings resource, overridden here under `game` like any other.",
496
+ "additionalProperties": {
497
+ "type": "object"
498
+ }
499
+ }
500
+ },
501
+ "required": ["identifier", "locales"],
502
+ "additionalProperties": false
503
+ },
504
+ "FacilitatorGuideDefinition": {
505
+ "type": "object",
506
+ "description": "Definition of a facilitator guide — bundled markdown content rendered natively by the host on the facilitator's page",
507
+ "properties": {
508
+ "identifier": {
509
+ "type": "string",
510
+ "description": "Namespace-style identifier for the facilitator guide",
511
+ "pattern": "^[a-z][a-z0-9_]*$"
512
+ },
513
+ "locales": {
514
+ "type": "object",
515
+ "description": "Localized facilitator guide fields with one entry per supported locale. Each declared locale must have a matching content/<locale>/ directory.",
516
+ "patternProperties": {
517
+ "^[a-z]{2}(-[A-Z]{2})?$": {
518
+ "type": "object",
519
+ "description": "Localized fields for this locale",
520
+ "properties": {
521
+ "name": {
522
+ "type": "string",
523
+ "description": "Display name for this locale, shown as the guide's title"
524
+ }
525
+ },
526
+ "required": ["name"],
527
+ "additionalProperties": false
528
+ }
529
+ },
530
+ "minProperties": 1,
531
+ "additionalProperties": false
532
+ }
533
+ },
534
+ "required": ["identifier", "locales"],
535
+ "additionalProperties": false
536
+ },
537
+ "GameDefinition": {
538
+ "type": "object",
539
+ "description": "Definition of a game with internationalization support",
540
+ "properties": {
541
+ "identifier": {
542
+ "type": "string",
543
+ "description": "Namespace-style identifier for the game",
544
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
545
+ },
546
+ "supportedLocales": { "$ref": "#/$defs/GameSupportedLocales" },
547
+ "locales": { "$ref": "#/$defs/GameLocales" },
548
+ "customScenarios": { "$ref": "#/$defs/GameCustomScenarios" },
549
+ "teams": {
550
+ "type": "object",
551
+ "description": "The game's interaction mode, fixed at authoring time. The team bounds, participant guidance and default names are game settings, in the built-in `game` settings resource.",
552
+ "properties": {
553
+ "mode": { "$ref": "#/$defs/GameTeamMode" }
554
+ },
555
+ "additionalProperties": false
556
+ }
557
+ },
558
+ "required": ["identifier", "supportedLocales", "locales"],
559
+ "additionalProperties": false
560
+ },
561
+ "GameSupportedLocales": {
562
+ "type": "array",
563
+ "description": "List of locales supported by this game (e.g., ['en', 'es', 'fr'])",
564
+ "items": {
565
+ "type": "string",
566
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
567
+ },
568
+ "minItems": 1,
569
+ "uniqueItems": true
570
+ },
571
+ "GameLocales": {
572
+ "type": "object",
573
+ "description": "Localized game fields with one entry per supported locale",
574
+ "patternProperties": {
575
+ "^[a-z]{2}(-[A-Z]{2})?$": {
576
+ "type": "object",
577
+ "description": "Localized fields for this locale",
578
+ "properties": {
579
+ "name": {
580
+ "type": "string",
581
+ "description": "Display name for this locale"
582
+ }
583
+ },
584
+ "required": ["name"],
585
+ "additionalProperties": false
586
+ }
587
+ },
588
+ "minProperties": 1,
589
+ "additionalProperties": false
590
+ },
591
+ "GameCustomScenarios": {
592
+ "type": "object",
593
+ "description": "Production-policy signal opting in to facilitator-authored, runtime-persisted scenarios. When supported is true, runtime hosts offer 'save as scenario' from the game's scenario editor, or through whatever other authoring route they provide, such as an agent editing the settings schemas directly, and list the resulting scenarios alongside built-in ones at init time. The scenario editor is optional: this flag, not the editor, is what switches custom scenarios on. Author-time hosts (e.g. the SDK dev server) surface their own save affordance regardless.",
594
+ "properties": {
595
+ "supported": {
596
+ "type": "boolean",
597
+ "description": "If true, the runtime MAY persist scenarios authored at session time."
598
+ }
599
+ },
600
+ "required": ["supported"],
601
+ "additionalProperties": false
602
+ },
603
+ "GameTeams": {
604
+ "type": "object",
605
+ "description": "Team configuration: the interaction mode, fixed at authoring time, and the game's own values for the team settings, which are the defaults of the built-in `game` settings resource. All fields are optional.",
606
+ "properties": {
607
+ "mode": { "$ref": "#/$defs/GameTeamMode" },
608
+ "min": {
609
+ "type": "integer",
610
+ "description": "Minimum number of teams this game is designed for. The default for the `game` settings' `teams.min`",
611
+ "minimum": 1
612
+ },
613
+ "max": {
614
+ "type": "integer",
615
+ "description": "Maximum number of teams this game is designed for. The default for the `game` settings' `teams.max`",
616
+ "minimum": 1
617
+ },
618
+ "perTeam": {
619
+ "type": "object",
620
+ "description": "Per-team participant guidance. The default for the `game` settings' `teams.perTeam`",
621
+ "properties": {
622
+ "minParticipants": {
623
+ "type": "integer",
624
+ "description": "Minimum participants per team",
625
+ "minimum": 1
626
+ },
627
+ "maxParticipants": {
628
+ "type": "integer",
629
+ "description": "Maximum participants per team",
630
+ "minimum": 1
631
+ }
632
+ },
633
+ "additionalProperties": false
634
+ },
635
+ "defaultNames": {
636
+ "type": "array",
637
+ "description": "Ordered, localised default names for teams. Entry N seeds the default name for the Nth team (team-1, team-2, …). Advisory: operators may rename teams at session setup, and teams beyond the list fall back to the runtime default. The default for the `game` settings' `teams.defaultNames`",
638
+ "items": {
639
+ "type": "object",
640
+ "description": "Localised default name for one team, with one entry per supported locale",
641
+ "patternProperties": {
642
+ "^[a-z]{2}(-[A-Z]{2})?$": {
643
+ "type": "object",
644
+ "description": "Localised fields for this locale",
645
+ "properties": {
646
+ "name": {
647
+ "type": "string",
648
+ "description": "Display name for this locale"
649
+ }
650
+ },
651
+ "required": ["name"],
652
+ "additionalProperties": false
653
+ }
654
+ },
655
+ "minProperties": 1,
656
+ "additionalProperties": false
657
+ }
658
+ }
659
+ },
660
+ "additionalProperties": false
661
+ },
662
+ "GameTeamMode": {
663
+ "type": "string",
664
+ "description": "Interaction mode this game runs in. 'independent' = teams are isolated with independent tick progression. 'shared-state' = teams interact via shared capabilities with synchronized ticks. If omitted, defaults to 'independent'. Fixed at authoring time: no scenario or session varies it.",
665
+ "enum": ["independent", "shared-state"]
666
+ },
667
+ "GameSettingConstraint": {
668
+ "type": "object",
669
+ "description": "How a game narrows one of its `game` settings. Each keyword may only narrow the SDK's schema: a `minimum` or `maximum` applies to a number and also rules out null, an `enum` lists values the SDK's schema accepts, and `readOnly` fixes the value at the game's own, so no scenario or session may change it.",
670
+ "properties": {
671
+ "minimum": {
672
+ "type": "number",
673
+ "description": "The smallest value a scenario or session may set. At or above the SDK's own minimum"
674
+ },
675
+ "maximum": {
676
+ "type": "number",
677
+ "description": "The largest value a scenario or session may set. At or below the SDK's own maximum"
678
+ },
679
+ "enum": {
680
+ "type": "array",
681
+ "minItems": 1,
682
+ "description": "The only values a scenario or session may set, each one the SDK's schema accepts"
683
+ },
684
+ "readOnly": {
685
+ "type": "boolean",
686
+ "description": "True fixes the value at the game's own: a scenario or session that sets it is refused"
687
+ }
688
+ },
689
+ "minProperties": 1,
690
+ "additionalProperties": false
691
+ },
692
+ "GameSettingsConstraints": {
693
+ "type": "object",
694
+ "description": "Narrowing for the built-in `game` settings, in their shape. The build merges each constraint into the `game` settings schema it emits, so a runtime sees one ordinary schema. Adding a constraint is a scenario-format change.",
695
+ "properties": {
696
+ "maxTicks": { "$ref": "#/$defs/GameSettingConstraint" },
697
+ "teams": {
698
+ "type": "object",
699
+ "properties": {
700
+ "min": { "$ref": "#/$defs/GameSettingConstraint" },
701
+ "max": { "$ref": "#/$defs/GameSettingConstraint" },
702
+ "perTeam": {
703
+ "type": "object",
704
+ "properties": {
705
+ "minParticipants": { "$ref": "#/$defs/GameSettingConstraint" },
706
+ "maxParticipants": { "$ref": "#/$defs/GameSettingConstraint" }
707
+ },
708
+ "additionalProperties": false
709
+ },
710
+ "defaultNames": { "$ref": "#/$defs/GameSettingConstraint" }
711
+ },
712
+ "additionalProperties": false
713
+ },
714
+ "waitingRoom": {
715
+ "type": "object",
716
+ "properties": {
717
+ "openOnStart": { "$ref": "#/$defs/GameSettingConstraint" }
718
+ },
719
+ "additionalProperties": false
720
+ }
721
+ },
722
+ "additionalProperties": false
723
+ },
724
+ "GameSettings": {
725
+ "type": "object",
726
+ "description": "The values of the built-in `game` settings resource: the game-level settings every game has. Its schema is the SDK's, not the game's: a game sets its own values in its manifest, which become this resource's defaults, and a scenario or a session overrides them under the identifier `game` like any other settings resource. Null means 'no limit' or 'no guidance'. A new game-level setting joins as a new optional property with a default.",
727
+ "properties": {
728
+ "maxTicks": {
729
+ "type": ["integer", "null"],
730
+ "minimum": 1,
731
+ "description": "The number of ticks the game plays before it is complete. Null means no fixed limit: the game ends by its tick controller or its engine"
732
+ },
733
+ "teams": {
734
+ "type": "object",
735
+ "description": "How many teams a session may hold, how many participants each is meant for, and what the teams are called to begin with",
736
+ "properties": {
737
+ "min": {
738
+ "type": ["integer", "null"],
739
+ "minimum": 1,
740
+ "description": "The fewest teams a session may start play with. Null means no minimum"
741
+ },
742
+ "max": {
743
+ "type": ["integer", "null"],
744
+ "minimum": 1,
745
+ "description": "The most teams a session may hold at any point. Null means no maximum beyond the runtime's own ceiling"
746
+ },
747
+ "perTeam": {
748
+ "type": "object",
749
+ "description": "Advisory guidance on how many participants each team is meant for, shown to the facilitator. Never a gate on joining",
750
+ "properties": {
751
+ "minParticipants": {
752
+ "type": ["integer", "null"],
753
+ "minimum": 1,
754
+ "description": "The fewest participants a team is meant for. Null means no guidance"
755
+ },
756
+ "maxParticipants": {
757
+ "type": ["integer", "null"],
758
+ "minimum": 1,
759
+ "description": "The most participants a team is meant for. Null means no guidance"
760
+ }
761
+ },
762
+ "additionalProperties": false
763
+ },
764
+ "defaultNames": {
765
+ "type": "array",
766
+ "description": "Ordered, localised default names for teams. Entry N names the team whose index is N; a team beyond the list is named by position. A facilitator or the team's players may rename it",
767
+ "items": {
768
+ "type": "object",
769
+ "description": "Localised default name for one team, with one entry per supported locale",
770
+ "patternProperties": {
771
+ "^[a-z]{2}(-[A-Z]{2})?$": {
772
+ "type": "object",
773
+ "description": "Localised fields for this locale",
774
+ "properties": {
775
+ "name": {
776
+ "type": "string",
777
+ "description": "Display name for this locale"
778
+ }
779
+ },
780
+ "required": ["name"],
781
+ "additionalProperties": false
782
+ }
783
+ },
784
+ "minProperties": 1,
785
+ "additionalProperties": false
786
+ }
787
+ }
788
+ },
789
+ "additionalProperties": false
790
+ },
791
+ "waitingRoom": {
792
+ "type": "object",
793
+ "description": "How the waiting room starts",
794
+ "properties": {
795
+ "openOnStart": {
796
+ "type": "boolean",
797
+ "description": "Whether a new session starts with the waiting room open. Seeds the session flag at creation, before any setup step, so only the game and its scenarios set it"
798
+ }
799
+ },
800
+ "additionalProperties": false
801
+ }
802
+ },
803
+ "additionalProperties": false
804
+ },
805
+ "GameWaitingRoomOpenOnStart": {
806
+ "type": "boolean",
807
+ "description": "Whether a new session starts with the waiting room open, holding participants on this screen until the facilitator closes it. Seeds the session flag at creation only: the facilitator owns it from then on, and neither a reset nor a restart reapplies it.",
808
+ "default": false
809
+ },
810
+ "GameWaitingRoomSettings": {
811
+ "type": "object",
812
+ "description": "Waiting room settings. Which user interface fills the waiting room is the package's waiting room user interface; only its settings are authored.",
813
+ "properties": {
814
+ "openOnStart": { "$ref": "#/$defs/GameWaitingRoomOpenOnStart" }
815
+ },
816
+ "additionalProperties": false
817
+ },
818
+ "HookSignal": {
819
+ "type": "string",
820
+ "description": "Lifecycle signal a hook subscribes to. Hooks fire on out-of-tick events emitted by the runtime, after the runtime applies the change.",
821
+ "enum": ["participantJoin", "participantMove"]
822
+ },
823
+ "HookDefinition": {
824
+ "type": "object",
825
+ "description": "Definition of a hook — a single-signal handler that runs in response to an out-of-tick lifecycle event",
826
+ "properties": {
827
+ "identifier": {
828
+ "type": "string",
829
+ "description": "Namespace-style identifier for the hook",
830
+ "pattern": "^[a-z][a-z0-9_]*$"
831
+ },
832
+ "signal": {
833
+ "$ref": "#/$defs/HookSignal",
834
+ "description": "Lifecycle signal this hook fires on"
835
+ },
836
+ "reads": {
837
+ "type": "array",
838
+ "description": "Identifiers of the capabilities this hook reads",
839
+ "items": {
840
+ "type": "string",
841
+ "pattern": "^[a-z][a-z0-9_]*$"
842
+ },
843
+ "uniqueItems": true
844
+ },
845
+ "writes": {
846
+ "type": "array",
847
+ "description": "Identifiers of the capabilities this hook writes",
848
+ "items": {
849
+ "type": "string",
850
+ "pattern": "^[a-z][a-z0-9_]*$"
851
+ },
852
+ "uniqueItems": true
853
+ },
854
+ "uses": {
855
+ "type": "array",
856
+ "description": "Runtime callback APIs this hook is permitted to invoke. The runtime throws when this hook calls a callback whose name is not listed here.",
857
+ "items": { "$ref": "#/$defs/ApiUse" },
858
+ "uniqueItems": true,
859
+ "default": []
860
+ },
861
+ "settings": {
862
+ "type": "array",
863
+ "description": "Identifiers of the settings resources this hook reads. It receives exactly these, read-only, as settings.<identifier>",
864
+ "items": {
865
+ "type": "string",
866
+ "pattern": "^[a-z][a-z0-9_]*$"
867
+ },
868
+ "uniqueItems": true
869
+ }
870
+ },
871
+ "required": ["identifier", "signal"],
872
+ "additionalProperties": false
873
+ },
874
+ "TickControllerDefinition": {
875
+ "type": "object",
876
+ "description": "Definition of a tick controller that determines automatic tick timing",
877
+ "properties": {
878
+ "identifier": {
879
+ "type": "string",
880
+ "description": "Namespace-style identifier for the tick controller",
881
+ "pattern": "^[a-z][a-z0-9_]*$"
882
+ },
883
+ "reads": {
884
+ "type": "array",
885
+ "description": "Identifiers of the capabilities this tick controller reads",
886
+ "items": {
887
+ "type": "string",
888
+ "pattern": "^[a-z][a-z0-9_]*$"
889
+ },
890
+ "uniqueItems": true
891
+ },
892
+ "uses": {
893
+ "type": "array",
894
+ "description": "Runtime callback APIs this tick controller is permitted to invoke. The runtime throws when this tick controller calls a callback whose name is not listed here.",
895
+ "items": { "$ref": "#/$defs/ApiUse" },
896
+ "uniqueItems": true,
897
+ "default": []
898
+ },
899
+ "settings": {
900
+ "type": "array",
901
+ "description": "Identifiers of the settings resources this tick controller reads. It receives exactly these, read-only, as settings.<identifier>",
902
+ "items": {
903
+ "type": "string",
904
+ "pattern": "^[a-z][a-z0-9_]*$"
905
+ },
906
+ "uniqueItems": true
907
+ }
908
+ },
909
+ "required": ["identifier"],
910
+ "additionalProperties": false
911
+ },
912
+ "SDKTickController": {
913
+ "type": "object",
914
+ "description": "Bundle containing a tick controller definition and its logic layout",
915
+ "properties": {
916
+ "definition": { "$ref": "#/$defs/TickControllerDefinition" },
917
+ "logic": { "$ref": "#/$defs/LogicLayout" },
918
+ "rootDirectory": {
919
+ "type": "string",
920
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
921
+ "pattern": "^[^\\\\]+$"
922
+ }
923
+ },
924
+ "required": ["definition", "logic", "rootDirectory"],
925
+ "additionalProperties": false
926
+ },
927
+ "SDKHook": {
928
+ "type": "object",
929
+ "description": "Bundle containing a hook definition and its logic layout",
930
+ "properties": {
931
+ "definition": { "$ref": "#/$defs/HookDefinition" },
932
+ "logic": { "$ref": "#/$defs/LogicLayout" },
933
+ "rootDirectory": {
934
+ "type": "string",
935
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
936
+ "pattern": "^[^\\\\]+$"
937
+ }
938
+ },
939
+ "required": ["definition", "logic", "rootDirectory"],
940
+ "additionalProperties": false
941
+ },
942
+ "ValidatorGate": {
943
+ "type": "string",
944
+ "description": "A participant action a validator can gate, named after the surface message it gates: a context write, or a request for the next tick",
945
+ "enum": ["updateData", "requestTick"]
946
+ },
947
+ "ValidatorDefinition": {
948
+ "type": "object",
949
+ "description": "Definition of a validator — a standalone, read-only gate on what a participant does from a player surface: a context write, or a request for the next tick. Reject-only; never modifies state.",
950
+ "properties": {
951
+ "identifier": {
952
+ "type": "string",
953
+ "description": "Namespace-style identifier for the validator",
954
+ "pattern": "^[a-z][a-z0-9_]*$"
955
+ },
956
+ "reads": {
957
+ "type": "array",
958
+ "description": "Identifiers of the capabilities this validator reads. Also its trigger set: a validator runs when a mutation changes one of them, and one declaring none runs on every mutation",
959
+ "items": {
960
+ "type": "string",
961
+ "pattern": "^[a-z][a-z0-9_]*$"
962
+ },
963
+ "uniqueItems": true
964
+ },
965
+ "gates": {
966
+ "type": "array",
967
+ "description": "Generated, not authored. The participant actions this validator gates, one per gate function its logic exports: 'updateData' for an UpdateData export (a context write), 'requestTick' for a RequestTick export (a request for the next tick). The build derives this from the exports and writes it into the bundled manifest, and a runtime calls only these; authoring it in validator.sdk.json is an error",
968
+ "items": { "$ref": "#/$defs/ValidatorGate" },
969
+ "uniqueItems": true
970
+ },
971
+ "settings": {
972
+ "type": "array",
973
+ "description": "Identifiers of the settings resources this validator reads. It receives exactly these, read-only, as settings.<identifier>",
974
+ "items": {
975
+ "type": "string",
976
+ "pattern": "^[a-z][a-z0-9_]*$"
977
+ },
978
+ "uniqueItems": true
979
+ }
980
+ },
981
+ "required": ["identifier"],
982
+ "additionalProperties": false
983
+ },
984
+ "SDKValidator": {
985
+ "type": "object",
986
+ "description": "Bundle containing a validator definition and its logic layout",
987
+ "properties": {
988
+ "definition": { "$ref": "#/$defs/ValidatorDefinition" },
989
+ "logic": { "$ref": "#/$defs/LogicLayout" },
990
+ "rootDirectory": {
991
+ "type": "string",
992
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
993
+ "pattern": "^[^\\\\]+$"
994
+ }
995
+ },
996
+ "required": ["definition", "logic", "rootDirectory"],
997
+ "additionalProperties": false
998
+ },
999
+ "EndpointDefinition": {
1000
+ "type": "object",
1001
+ "description": "Definition of an endpoint — a named, server-side handler that user interfaces, and callers outside the game when its visibility is external, invoke by identifier. Endpoints validate structured requests and responses against declared schemas, and operate strictly within the bounds of their declared `reads`, `writes` and `uses`.",
1002
+ "properties": {
1003
+ "identifier": {
1004
+ "type": "string",
1005
+ "description": "Namespace-style identifier for the endpoint",
1006
+ "pattern": "^[a-z][a-z0-9_]*$"
1007
+ },
1008
+ "displayName": {
1009
+ "type": "string",
1010
+ "description": "Human-readable name for author-time tools"
1011
+ },
1012
+ "description": {
1013
+ "type": "string",
1014
+ "description": "Short description of what this endpoint does, surfaced in author-time tools. Required when `visibility` is `external`, where it is also the text an outside caller, such as a facilitator's AI agent, reads to decide whether to call this endpoint."
1015
+ },
1016
+ "scope": {
1017
+ "type": "string",
1018
+ "enum": ["session", "team"],
1019
+ "description": "Whether this endpoint acts on one team or on the session as a whole. A team-scoped endpoint receives that team's context and a `team` naming it, whoever calls it; a session-scoped one has neither. Absent means `team`.",
1020
+ "default": "team"
1021
+ },
1022
+ "requestSchema": {
1023
+ "type": "object",
1024
+ "description": "JSON Schema describing the request payload accepted by this endpoint",
1025
+ "$comment": "This should be a valid JSON Schema object defining properties, types, required fields, etc."
1026
+ },
1027
+ "responseSchema": {
1028
+ "type": "object",
1029
+ "description": "JSON Schema describing the response payload returned by this endpoint",
1030
+ "$comment": "This should be a valid JSON Schema object defining properties, types, required fields, etc."
1031
+ },
1032
+ "reads": {
1033
+ "type": "array",
1034
+ "description": "Identifiers of the capabilities this endpoint reads. The handler receives a scoped snapshot of these capabilities under `context`.",
1035
+ "items": {
1036
+ "type": "string",
1037
+ "pattern": "^[a-z][a-z0-9_]*$"
1038
+ },
1039
+ "uniqueItems": true
1040
+ },
1041
+ "settings": {
1042
+ "type": "array",
1043
+ "description": "Identifiers of the settings resources this endpoint reads. It receives exactly these, read-only, as settings.<identifier>",
1044
+ "items": {
1045
+ "type": "string",
1046
+ "pattern": "^[a-z][a-z0-9_]*$"
1047
+ },
1048
+ "uniqueItems": true
1049
+ },
1050
+ "writes": {
1051
+ "type": "array",
1052
+ "description": "Identifiers of the capabilities this endpoint may change. The context patch a handler returns is held to this list, and an endpoint declaring none cannot change state at all.",
1053
+ "items": {
1054
+ "type": "string",
1055
+ "pattern": "^[a-z][a-z0-9_]*$"
1056
+ },
1057
+ "uniqueItems": true
1058
+ },
1059
+ "uses": {
1060
+ "type": "array",
1061
+ "description": "Runtime callback APIs this endpoint is permitted to invoke. The runtime throws when this endpoint calls a callback whose name is not listed here.",
1062
+ "items": { "$ref": "#/$defs/ApiUse" },
1063
+ "uniqueItems": true,
1064
+ "default": []
1065
+ },
1066
+ "actions": {
1067
+ "type": "array",
1068
+ "description": "Session actions this endpoint may return beside its response, such as closing the waiting room or advancing a tick. The runtime carries them out, in order, after the endpoint's write.",
1069
+ "items": { "$ref": "#/$defs/EndpointActionType" },
1070
+ "uniqueItems": true
1071
+ },
1072
+ "responds": {
1073
+ "type": "boolean",
1074
+ "description": "Generated, not authored. Whether the endpoint answers in two phases: its logic exports `Plan`, which returns the effects alone, and `Respond`, which the runtime calls once they have been applied to write the response from the state they left. An endpoint that answers in one exports `Handle`. The build derives this from the exports and writes it into the bundled manifest; authoring it in endpoint.sdk.json is an error"
1075
+ },
1076
+ "roster": {
1077
+ "type": "boolean",
1078
+ "description": "Whether the handler's `session` argument lists each team's participants. Off by default, because the list grows with the cohort and most endpoints do not need it.",
1079
+ "default": false
1080
+ },
1081
+ "visibility": {
1082
+ "type": "string",
1083
+ "enum": ["internal", "external"],
1084
+ "description": "Who may invoke this endpoint. `internal` endpoints are reached only by the game's own user interfaces; `external` ones may also be invoked by callers outside the game, such as a facilitator's AI agent or a platform API, subject to the platform's own authorisation. Absent means `internal`, so an endpoint written for a game's own screens is never published unless its author says so.",
1085
+ "default": "internal"
1086
+ }
1087
+ },
1088
+ "required": ["identifier", "requestSchema", "responseSchema"],
1089
+ "additionalProperties": false
1090
+ },
1091
+ "SDKEndpoint": {
1092
+ "type": "object",
1093
+ "description": "Bundle containing an endpoint definition and its logic layout",
1094
+ "properties": {
1095
+ "definition": { "$ref": "#/$defs/EndpointDefinition" },
1096
+ "logic": { "$ref": "#/$defs/LogicLayout" },
1097
+ "rootDirectory": {
1098
+ "type": "string",
1099
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1100
+ "pattern": "^[^\\\\]+$"
1101
+ }
1102
+ },
1103
+ "required": ["definition", "logic", "rootDirectory"],
1104
+ "additionalProperties": false
1105
+ },
1106
+ "ResolvedPackageManifest": {
1107
+ "type": "object",
1108
+ "description": "Every resource a package holds: the shape the loader builds from disk and the shape the build writes to seriousgaming.json. A game holds one of nine kinds, each in its own field; everything a package may hold more than one of is an array.",
1109
+ "properties": {
1110
+ "manifestVersion": {
1111
+ "type": "integer",
1112
+ "minimum": 1,
1113
+ "description": "Format version of this manifest. Absent means 1. Runtimes MUST treat an absent value as 1 and MUST reject a version they do not implement."
1114
+ },
1115
+ "requires": { "$ref": "#/$defs/RequiredFeatures" },
1116
+ "scenarioFormat": { "$ref": "#/$defs/ScenarioFormat" },
1117
+ "package": { "$ref": "#/$defs/SDKPackage" },
1118
+ "game": { "$ref": "#/$defs/SDKGame" },
1119
+ "engine": { "$ref": "#/$defs/SDKEngine" },
1120
+ "ui": { "$ref": "#/$defs/SDKUserInterface" },
1121
+ "session": { "$ref": "#/$defs/SDKSessionUserInterface" },
1122
+ "waiting_room": { "$ref": "#/$defs/SDKWaitingRoomUserInterface" },
1123
+ "presentation": { "$ref": "#/$defs/SDKPresentation" },
1124
+ "setup": {
1125
+ "$ref": "#/$defs/SDKSetup"
1126
+ },
1127
+ "scenario_editor": {
1128
+ "$ref": "#/$defs/SDKScenarioEditor"
1129
+ },
1130
+ "tick_controller": { "$ref": "#/$defs/SDKTickController" },
1131
+ "guide": { "$ref": "#/$defs/SDKFacilitatorGuide" },
1132
+ "capabilities": {
1133
+ "type": "array",
1134
+ "items": { "$ref": "#/$defs/SDKCapability" }
1135
+ },
1136
+ "settings": {
1137
+ "type": "array",
1138
+ "items": { "$ref": "#/$defs/SDKSettings" }
1139
+ },
1140
+ "scenarios": {
1141
+ "type": "array",
1142
+ "items": { "$ref": "#/$defs/SDKScenario" }
1143
+ },
1144
+ "hooks": {
1145
+ "type": "array",
1146
+ "items": { "$ref": "#/$defs/SDKHook" }
1147
+ },
1148
+ "validators": {
1149
+ "type": "array",
1150
+ "items": { "$ref": "#/$defs/SDKValidator" }
1151
+ },
1152
+ "endpoints": {
1153
+ "type": "array",
1154
+ "items": { "$ref": "#/$defs/SDKEndpoint" }
1155
+ }
1156
+ },
1157
+ "required": ["package", "game"],
1158
+ "additionalProperties": false
1159
+ },
1160
+ "LogicLayout": {
1161
+ "type": "object",
1162
+ "description": "Where a logic-bearing resource keeps its code, and what its entrypoint is called",
1163
+ "properties": {
1164
+ "directory": {
1165
+ "type": "string",
1166
+ "description": "Subdirectory containing logic files"
1167
+ },
1168
+ "entrypoint": {
1169
+ "type": "string",
1170
+ "description": "Path to the TypeScript entrypoint file (e.g., logic.ts)"
1171
+ }
1172
+ },
1173
+ "required": ["directory", "entrypoint"],
1174
+ "additionalProperties": false
1175
+ },
1176
+ "SDKPackage": {
1177
+ "type": "object",
1178
+ "description": "Bundle containing a package definition",
1179
+ "properties": {
1180
+ "definition": { "$ref": "#/$defs/PackageDefinition" }
1181
+ },
1182
+ "required": ["definition"],
1183
+ "additionalProperties": false
1184
+ },
1185
+ "SDKEngine": {
1186
+ "type": "object",
1187
+ "description": "Bundle containing an engine definition and its logic layout",
1188
+ "properties": {
1189
+ "definition": { "$ref": "#/$defs/EngineDefinition" },
1190
+ "logic": { "$ref": "#/$defs/LogicLayout" },
1191
+ "rootDirectory": {
1192
+ "type": "string",
1193
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1194
+ "pattern": "^[^\\\\]+$"
1195
+ }
1196
+ },
1197
+ "required": ["definition", "logic", "rootDirectory"],
1198
+ "additionalProperties": false
1199
+ },
1200
+ "SDKCapability": {
1201
+ "type": "object",
1202
+ "description": "Bundle containing a capability definition",
1203
+ "properties": {
1204
+ "definition": { "$ref": "#/$defs/CapabilityDefinition" }
1205
+ },
1206
+ "required": ["definition"],
1207
+ "additionalProperties": false
1208
+ },
1209
+ "SDKScenario": {
1210
+ "type": "object",
1211
+ "description": "Bundle containing a scenario definition and root directory for assets",
1212
+ "properties": {
1213
+ "definition": { "$ref": "#/$defs/ScenarioDefinition" },
1214
+ "rootDirectory": {
1215
+ "type": "string",
1216
+ "description": "Root directory where scenario assets are located. Must use forward slashes, not Windows separators",
1217
+ "pattern": "^[^\\\\]+$"
1218
+ }
1219
+ },
1220
+ "required": ["definition", "rootDirectory"],
1221
+ "additionalProperties": false
1222
+ },
1223
+ "SDKFacilitatorGuide": {
1224
+ "type": "object",
1225
+ "description": "Bundle containing a facilitator guide definition and root directory for content and assets",
1226
+ "properties": {
1227
+ "definition": { "$ref": "#/$defs/FacilitatorGuideDefinition" },
1228
+ "rootDirectory": {
1229
+ "type": "string",
1230
+ "description": "Root directory where guide content and assets are located. Must use forward slashes, not Windows separators",
1231
+ "pattern": "^[^\\\\]+$"
1232
+ }
1233
+ },
1234
+ "required": ["definition", "rootDirectory"],
1235
+ "additionalProperties": false
1236
+ },
1237
+ "SDKUserInterface": {
1238
+ "type": "object",
1239
+ "description": "Bundle containing a user interface definition and entrypoint",
1240
+ "properties": {
1241
+ "definition": { "$ref": "#/$defs/UserInterfaceDefinition" },
1242
+ "rootDirectory": {
1243
+ "type": "string",
1244
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1245
+ "pattern": "^[^\\\\]+$"
1246
+ },
1247
+ "ui": {
1248
+ "type": "object",
1249
+ "description": "Where this surface's entrypoint is. A UI's web files sit in the resource's own directory, so only the entrypoint's name varies",
1250
+ "properties": {
1251
+ "entrypoint": {
1252
+ "type": "string",
1253
+ "description": "Entrypoint file, in the resource's own directory (e.g., 'index.html')"
1254
+ }
1255
+ },
1256
+ "required": ["entrypoint"],
1257
+ "additionalProperties": false
1258
+ }
1259
+ },
1260
+ "required": ["definition", "rootDirectory", "ui"],
1261
+ "additionalProperties": false
1262
+ },
1263
+ "SDKSessionUserInterface": {
1264
+ "type": "object",
1265
+ "description": "Bundle containing a session user interface definition and entrypoint",
1266
+ "properties": {
1267
+ "definition": { "$ref": "#/$defs/SessionUserInterfaceDefinition" },
1268
+ "rootDirectory": {
1269
+ "type": "string",
1270
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1271
+ "pattern": "^[^\\\\]+$"
1272
+ },
1273
+ "ui": {
1274
+ "type": "object",
1275
+ "description": "Where this surface's entrypoint is. A UI's web files sit in the resource's own directory, so only the entrypoint's name varies",
1276
+ "properties": {
1277
+ "entrypoint": {
1278
+ "type": "string",
1279
+ "description": "Entrypoint file, in the resource's own directory (e.g., 'index.html')"
1280
+ }
1281
+ },
1282
+ "required": ["entrypoint"],
1283
+ "additionalProperties": false
1284
+ }
1285
+ },
1286
+ "required": ["definition", "rootDirectory", "ui"],
1287
+ "additionalProperties": false
1288
+ },
1289
+ "SDKSetup": {
1290
+ "type": "object",
1291
+ "description": "Bundle containing the setup user interface definition and entrypoint",
1292
+ "properties": {
1293
+ "definition": {
1294
+ "$ref": "#/$defs/SetupDefinition"
1295
+ },
1296
+ "rootDirectory": {
1297
+ "type": "string",
1298
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1299
+ "pattern": "^[^\\\\]+$"
1300
+ },
1301
+ "ui": {
1302
+ "type": "object",
1303
+ "description": "Where this surface's entrypoint is. A UI's web files sit in the resource's own directory, so only the entrypoint's name varies",
1304
+ "properties": {
1305
+ "entrypoint": {
1306
+ "type": "string",
1307
+ "description": "Entrypoint file, in the resource's own directory (e.g., 'index.html')"
1308
+ }
1309
+ },
1310
+ "required": ["entrypoint"],
1311
+ "additionalProperties": false
1312
+ }
1313
+ },
1314
+ "required": ["definition", "rootDirectory", "ui"],
1315
+ "additionalProperties": false
1316
+ },
1317
+ "SDKScenarioEditor": {
1318
+ "type": "object",
1319
+ "description": "Bundle containing the scenario editor definition and entrypoint",
1320
+ "properties": {
1321
+ "definition": {
1322
+ "$ref": "#/$defs/ScenarioEditorDefinition"
1323
+ },
1324
+ "rootDirectory": {
1325
+ "type": "string",
1326
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1327
+ "pattern": "^[^\\\\]+$"
1328
+ },
1329
+ "ui": {
1330
+ "type": "object",
1331
+ "description": "Where this surface's entrypoint is. A UI's web files sit in the resource's own directory, so only the entrypoint's name varies",
1332
+ "properties": {
1333
+ "entrypoint": {
1334
+ "type": "string",
1335
+ "description": "Entrypoint file, in the resource's own directory (e.g., 'index.html')"
1336
+ }
1337
+ },
1338
+ "required": ["entrypoint"],
1339
+ "additionalProperties": false
1340
+ }
1341
+ },
1342
+ "required": ["definition", "rootDirectory", "ui"],
1343
+ "additionalProperties": false
1344
+ },
1345
+ "PresentationDefinition": {
1346
+ "type": "object",
1347
+ "description": "Definition of a presentation: the slides a facilitator shows the room, rendered from a UI bundle of the game's own. Read-only by construction: it declares no writes, no endpoints and no callback uses, and it may be shown with no session at all",
1348
+ "properties": {
1349
+ "identifier": {
1350
+ "type": "string",
1351
+ "description": "Namespace-style identifier for the presentation",
1352
+ "pattern": "^[a-z][a-z0-9_]*$"
1353
+ },
1354
+ "locales": {
1355
+ "type": "object",
1356
+ "description": "Display name per locale, for the host to label the presentation with",
1357
+ "additionalProperties": {
1358
+ "type": "object",
1359
+ "properties": {
1360
+ "name": { "type": "string" }
1361
+ },
1362
+ "required": ["name"],
1363
+ "additionalProperties": false
1364
+ }
1365
+ },
1366
+ "reads": {
1367
+ "type": "array",
1368
+ "description": "Identifiers of the capabilities this presentation reads, from every team and the shared store, when it is shown during a session",
1369
+ "items": {
1370
+ "type": "string",
1371
+ "pattern": "^[a-z][a-z0-9_]*$"
1372
+ },
1373
+ "uniqueItems": true
1374
+ },
1375
+ "settings": {
1376
+ "type": "array",
1377
+ "description": "Identifiers of the settings resources this presentation reads. It receives exactly these, read-only, as settings.<identifier>, with or without a session",
1378
+ "items": {
1379
+ "type": "string",
1380
+ "pattern": "^[a-z][a-z0-9_]*$"
1381
+ },
1382
+ "uniqueItems": true
1383
+ }
1384
+ },
1385
+ "required": ["identifier"],
1386
+ "additionalProperties": false
1387
+ },
1388
+ "SDKPresentation": {
1389
+ "type": "object",
1390
+ "description": "Bundle containing a presentation definition and entrypoint",
1391
+ "properties": {
1392
+ "definition": { "$ref": "#/$defs/PresentationDefinition" },
1393
+ "rootDirectory": {
1394
+ "type": "string",
1395
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1396
+ "pattern": "^[^\\\\]+$"
1397
+ },
1398
+ "ui": {
1399
+ "type": "object",
1400
+ "description": "Where this surface's entrypoint is. A UI's web files sit in the resource's own directory, so only the entrypoint's name varies",
1401
+ "properties": {
1402
+ "entrypoint": {
1403
+ "type": "string",
1404
+ "description": "Entrypoint file, in the resource's own directory (e.g., 'index.html')"
1405
+ }
1406
+ },
1407
+ "required": ["entrypoint"],
1408
+ "additionalProperties": false
1409
+ }
1410
+ },
1411
+ "required": ["definition", "rootDirectory", "ui"],
1412
+ "additionalProperties": false
1413
+ },
1414
+ "SDKWaitingRoomUserInterface": {
1415
+ "type": "object",
1416
+ "description": "Bundle containing a waiting room user interface definition and entrypoint",
1417
+ "properties": {
1418
+ "definition": { "$ref": "#/$defs/WaitingRoomUserInterfaceDefinition" },
1419
+ "rootDirectory": {
1420
+ "type": "string",
1421
+ "description": "Directory containing this resource's files, relative to the bundle file. Must use forward slashes, not Windows separators",
1422
+ "pattern": "^[^\\\\]+$"
1423
+ },
1424
+ "ui": {
1425
+ "type": "object",
1426
+ "description": "Where this surface's entrypoint is. A UI's web files sit in the resource's own directory, so only the entrypoint's name varies",
1427
+ "properties": {
1428
+ "entrypoint": {
1429
+ "type": "string",
1430
+ "description": "Entrypoint file, in the resource's own directory (e.g., 'index.html')"
1431
+ }
1432
+ },
1433
+ "required": ["entrypoint"],
1434
+ "additionalProperties": false
1435
+ }
1436
+ },
1437
+ "required": ["definition", "rootDirectory", "ui"],
1438
+ "additionalProperties": false
1439
+ },
1440
+ "SDKGame": {
1441
+ "type": "object",
1442
+ "description": "Bundle containing a game definition",
1443
+ "properties": {
1444
+ "definition": { "$ref": "#/$defs/GameDefinition" },
1445
+ "rootDirectory": {
1446
+ "type": "string",
1447
+ "description": "Root directory where game files are located (e.g., '.'). Must use forward slashes, not Windows separators",
1448
+ "pattern": "^[^\\\\]+$"
1449
+ }
1450
+ },
1451
+ "required": ["definition", "rootDirectory"],
1452
+ "additionalProperties": false
1453
+ },
1454
+ "PackageManifest": {
1455
+ "type": "object",
1456
+ "description": "A package, which is a game: its identifier and the game's settings. What it declares are the resources on disk under the conventional directories beside this file. The version comes from package.json, and the game's identifier is the package identifier with `.game` appended.",
1457
+ "properties": {
1458
+ "identifier": {
1459
+ "type": "string",
1460
+ "description": "Namespace-style identifier for the package. Every resource identifier sits under it, and the game's identifier is it with `.game` appended.",
1461
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
1462
+ },
1463
+ "requires": { "$ref": "#/$defs/RequiredFeatures" },
1464
+ "scenarioFormat": { "$ref": "#/$defs/ScenarioFormat" },
1465
+ "supportedLocales": { "$ref": "#/$defs/GameSupportedLocales" },
1466
+ "locales": { "$ref": "#/$defs/GameLocales" },
1467
+ "maxTicks": {
1468
+ "type": "integer",
1469
+ "minimum": 1,
1470
+ "description": "The number of ticks (rounds) the game plays before it is complete. A tick can stand for an hour, a day, a week, or something more abstract. Omit it when the game ends by its tick controller or its engine instead. The default for the `game` settings' `maxTicks`, which a scenario or a session may override"
1471
+ },
1472
+ "teams": { "$ref": "#/$defs/GameTeams" },
1473
+ "waitingRoom": { "$ref": "#/$defs/GameWaitingRoomSettings" },
1474
+ "gameSettingsConstraints": { "$ref": "#/$defs/GameSettingsConstraints" },
1475
+ "customScenarios": { "$ref": "#/$defs/GameCustomScenarios" }
1476
+ },
1477
+ "required": ["identifier", "supportedLocales", "locales"],
1478
+ "additionalProperties": false
1479
+ }
1480
+ },
1481
+ "type": "object",
1482
+ "properties": {
1483
+ "PackageDefinition": { "$ref": "#/$defs/PackageDefinition" },
1484
+ "EngineDefinition": { "$ref": "#/$defs/EngineDefinition" },
1485
+ "CapabilityDefinition": { "$ref": "#/$defs/CapabilityDefinition" },
1486
+ "SettingsDefinition": { "$ref": "#/$defs/SettingsDefinition" },
1487
+ "SDKSettings": { "$ref": "#/$defs/SDKSettings" },
1488
+ "SetupDefinition": {
1489
+ "$ref": "#/$defs/SetupDefinition"
1490
+ },
1491
+ "ScenarioEditorDefinition": {
1492
+ "$ref": "#/$defs/ScenarioEditorDefinition"
1493
+ },
1494
+ "ScenarioDefinition": { "$ref": "#/$defs/ScenarioDefinition" },
1495
+ "UserInterfaceDefinition": { "$ref": "#/$defs/UserInterfaceDefinition" },
1496
+ "GameDefinition": { "$ref": "#/$defs/GameDefinition" },
1497
+ "SessionUserInterfaceDefinition": { "$ref": "#/$defs/SessionUserInterfaceDefinition" },
1498
+ "SDKSessionUserInterface": { "$ref": "#/$defs/SDKSessionUserInterface" },
1499
+ "WaitingRoomUserInterfaceDefinition": {
1500
+ "$ref": "#/$defs/WaitingRoomUserInterfaceDefinition"
1501
+ },
1502
+ "SDKWaitingRoomUserInterface": { "$ref": "#/$defs/SDKWaitingRoomUserInterface" },
1503
+ "PresentationDefinition": { "$ref": "#/$defs/PresentationDefinition" },
1504
+ "SDKPresentation": { "$ref": "#/$defs/SDKPresentation" },
1505
+ "GameSupportedLocales": { "$ref": "#/$defs/GameSupportedLocales" },
1506
+ "GameLocales": { "$ref": "#/$defs/GameLocales" },
1507
+ "GameCustomScenarios": { "$ref": "#/$defs/GameCustomScenarios" },
1508
+ "GameTeams": { "$ref": "#/$defs/GameTeams" },
1509
+ "GameTeamMode": { "$ref": "#/$defs/GameTeamMode" },
1510
+ "GameSettings": { "$ref": "#/$defs/GameSettings" },
1511
+ "GameSettingConstraint": { "$ref": "#/$defs/GameSettingConstraint" },
1512
+ "GameSettingsConstraints": { "$ref": "#/$defs/GameSettingsConstraints" },
1513
+ "GameWaitingRoomOpenOnStart": { "$ref": "#/$defs/GameWaitingRoomOpenOnStart" },
1514
+ "GameWaitingRoomSettings": { "$ref": "#/$defs/GameWaitingRoomSettings" },
1515
+ "FacilitatorGuideDefinition": { "$ref": "#/$defs/FacilitatorGuideDefinition" },
1516
+ "SDKFacilitatorGuide": { "$ref": "#/$defs/SDKFacilitatorGuide" },
1517
+ "ResolvedPackageManifest": { "$ref": "#/$defs/ResolvedPackageManifest" },
1518
+ "LogicLayout": { "$ref": "#/$defs/LogicLayout" },
1519
+ "SDKPackage": { "$ref": "#/$defs/SDKPackage" },
1520
+ "SDKEngine": { "$ref": "#/$defs/SDKEngine" },
1521
+ "SDKCapability": { "$ref": "#/$defs/SDKCapability" },
1522
+ "SDKScenario": { "$ref": "#/$defs/SDKScenario" },
1523
+ "SDKUserInterface": { "$ref": "#/$defs/SDKUserInterface" },
1524
+ "SDKSetup": {
1525
+ "$ref": "#/$defs/SDKSetup"
1526
+ },
1527
+ "SDKScenarioEditor": {
1528
+ "$ref": "#/$defs/SDKScenarioEditor"
1529
+ },
1530
+ "SDKGame": { "$ref": "#/$defs/SDKGame" },
1531
+ "PackageManifest": { "$ref": "#/$defs/PackageManifest" },
1532
+ "TickControllerDefinition": { "$ref": "#/$defs/TickControllerDefinition" },
1533
+ "SDKTickController": { "$ref": "#/$defs/SDKTickController" },
1534
+ "ApiUse": { "$ref": "#/$defs/ApiUse" },
1535
+ "EndpointActionType": { "$ref": "#/$defs/EndpointActionType" },
1536
+ "GlobalSettings": { "$ref": "#/$defs/GlobalSettings" },
1537
+ "HookSignal": { "$ref": "#/$defs/HookSignal" },
1538
+ "HookDefinition": { "$ref": "#/$defs/HookDefinition" },
1539
+ "SDKHook": { "$ref": "#/$defs/SDKHook" },
1540
+ "ValidatorDefinition": { "$ref": "#/$defs/ValidatorDefinition" },
1541
+ "SDKValidator": { "$ref": "#/$defs/SDKValidator" },
1542
+ "EndpointDefinition": { "$ref": "#/$defs/EndpointDefinition" },
1543
+ "SDKEndpoint": { "$ref": "#/$defs/SDKEndpoint" }
1544
+ },
1545
+ "additionalProperties": false
1546
+ }