@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,222 @@
1
+ # Drive a game from the CLI
2
+
3
+ Play a game from the terminal: configure it, start a session, make decisions, advance ticks, and read the state back as JSON. This is how you check engine behaviour quickly, and how an agent or a script plays a game without a browser.
4
+
5
+ **Keywords:** cli testing, drive game, tick, patch, view, configure, init, automated testing, json output, simulate decisions
6
+
7
+ Every flag used here is listed in the [CLI reference](./cli-reference.md#session-commands).
8
+
9
+ ## Prerequisites
10
+
11
+ - A package with an engine. The commands below use the starter game `new package` scaffolds; for your own game, swap in its settings and capability paths
12
+ - `seriousgaming.sdk.json` in your working directory
13
+ - `jq`, if you want to pick values out of the output
14
+
15
+ ## Steps
16
+
17
+ ### 1. Configure the game (optional)
18
+
19
+ Skip this step and the game plays with its settings' defaults (or its scenario's values). To try other values, set them keyed by settings identifier, the directory name under `settings/`:
20
+
21
+ ```bash
22
+ pnpm run sdk configure '{"menu":{"Capacity":80},"engine":{"Variation":0}}'
23
+
24
+ # Or from a file
25
+ pnpm run sdk configure -f config.json
26
+ ```
27
+
28
+ The values are validated against each settings resource's `settingsSchema` and kept in `.seriousgaming-sdk/configuration.json`, so every later session starts from them. A session that is already running is started again on them, at tick 0, keeping its team count, scenario and locale.
29
+
30
+ ### 2. Start a session (optional)
31
+
32
+ ```bash
33
+ pnpm run sdk init
34
+ ```
35
+
36
+ This prints the game at tick 0:
37
+
38
+ ```json
39
+ {
40
+ "gameId": "com.example.lemonade.game",
41
+ "completedTicks": 0,
42
+ "maxTicks": 10,
43
+ "complete": false,
44
+ "context": {
45
+ "plan": { "Make": { "lemonade": 28, "icedtea": 15, "cookies": 10 } },
46
+ "weather": {
47
+ "Today": "cloudy",
48
+ "Expected": { "lemonade": 55, "icedtea": 30, "cookies": 20 }
49
+ },
50
+ "results": {
51
+ "Day": 0,
52
+ "Weather": "cloudy",
53
+ "Lines": {},
54
+ "Takings": 0,
55
+ "Spent": 0,
56
+ "Profit": 0,
57
+ "Purse": 0
58
+ },
59
+ "roles": { "LooksAfter": {} }
60
+ },
61
+ "sharedContext": { "briefing": { "Message": "" } }
62
+ }
63
+ ```
64
+
65
+ `gameId` is your package identifier with `.game` appended. The weather, and so the forecast in `Expected`, comes from the session's seed, so yours may differ. `sharedContext` appears because the starter game has a shared capability, `briefing`.
66
+
67
+ You can skip `init` too: any session command starts a session when none is running. Reach for `init` when you want to start over with a different team count, scenario, or locale (`pnpm run sdk init --teams 3`).
68
+
69
+ A session started this way runs in a background dev server, and the command says so on stderr. The session lives in that server's memory, so it carries across commands until the server stops. See [Where the session lives](./cli-reference.md#where-the-session-lives).
70
+
71
+ ### 3. Advance a tick
72
+
73
+ ```bash
74
+ pnpm run sdk tick
75
+ ```
76
+
77
+ With no decisions, the engine runs on the current context: the game advances as if nobody touched a control.
78
+
79
+ ### 4. Make decisions, then advance
80
+
81
+ A participant makes a decision by writing to a capability through a UI. From the CLI, `--patch` does the same thing: it applies an RFC 6902 JSON Patch to the context and then runs the engine.
82
+
83
+ ```bash
84
+ pnpm run sdk tick --patch '[{"op":"replace","path":"/plan/Make/lemonade","value":40}]'
85
+ ```
86
+
87
+ Several decisions go in one patch, applied in order:
88
+
89
+ ```bash
90
+ pnpm run sdk tick --patch '[
91
+ {"op":"replace","path":"/plan/Make/icedtea","value":20},
92
+ {"op":"replace","path":"/plan/Make/cookies","value":15}
93
+ ]'
94
+ ```
95
+
96
+ Paths start at the capability identifier, then the variable, then any key inside it (`/plan/Make/lemonade`). The CLI reference covers [every operation and path rule](./cli-reference.md#partial-update-with-json-patch).
97
+
98
+ ### 5. Change the context without ticking
99
+
100
+ To set state up, or correct it, without running the engine, use `patch`:
101
+
102
+ ```bash
103
+ pnpm run sdk patch '[{"op":"replace","path":"/plan/Make/cookies","value":0}]'
104
+ ```
105
+
106
+ The game stays on the current tick, and the next tick runs from the patched context.
107
+
108
+ ### 6. Read the state
109
+
110
+ ```bash
111
+ pnpm run sdk view
112
+ ```
113
+
114
+ To parse the output, add `--silent` to `pnpm run` so pnpm's own banner stays out of it (see [Parsing JSON output](./cli-reference.md#parsing-json-through-pnpm)):
115
+
116
+ ```bash
117
+ pnpm run --silent sdk view | jq '.context'
118
+ pnpm run --silent sdk view | jq '.maxTicks'
119
+ ```
120
+
121
+ `view --full` prints the whole state projection: every team's context and roster, the shared store, the resolved settings, and the timer. It is what the console renders from, so what you read is what the browser shows.
122
+
123
+ ```bash
124
+ pnpm run --silent sdk view --full | jq '.teams[] | {team: .index, completedTicks, context}'
125
+ ```
126
+
127
+ ### 7. Start again
128
+
129
+ ```bash
130
+ pnpm run sdk reset # back to tick 0, keeping the scenario and roster
131
+ pnpm run sdk init # rebuild from the package, re-resolving everything
132
+ ```
133
+
134
+ ## Scripting a run
135
+
136
+ Each command prints JSON, so a script can drive a game and check the result. Always use `pnpm run --silent` so `JSON.parse` sees JSON alone.
137
+
138
+ Run several ticks and check the end state:
139
+
140
+ ```typescript
141
+ // 1. Initialize game (--silent strips the pnpm banner so JSON.parse succeeds)
142
+ const initResult = await exec('pnpm run --silent sdk init');
143
+ const initialState = JSON.parse(initResult.stdout);
144
+
145
+ // Verify initial context
146
+ assert(initialState.context.plan.Make.lemonade === 28);
147
+ assert(initialState.completedTicks === 0);
148
+
149
+ // 2. Execute multiple ticks
150
+ for (let i = 0; i < 5; i++) {
151
+ const tickResult = await exec('pnpm run --silent sdk tick');
152
+ const state = JSON.parse(tickResult.stdout);
153
+
154
+ // Verify state updates are as expected
155
+ console.log(`Day ${state.completedTicks}: Profit = ${state.context.results.Profit}`);
156
+ }
157
+
158
+ // 3. View final state
159
+ const viewResult = await exec('pnpm run --silent sdk view');
160
+ const finalState = JSON.parse(viewResult.stdout);
161
+
162
+ // Verify end conditions
163
+ assert(finalState.completedTicks === 5);
164
+ assert(finalState.context.results.Day === 5);
165
+ ```
166
+
167
+ Try the engine against several sets of decisions:
168
+
169
+ ```typescript
170
+ // Test how the engine reacts to different input values
171
+ const testCases = [{ lemonade: 20 }, { lemonade: 40 }, { lemonade: 60 }];
172
+
173
+ for (const testCase of testCases) {
174
+ // Reset game
175
+ await exec('pnpm run --silent sdk init');
176
+
177
+ // Create patch to set input values
178
+ const patch = [{ op: 'replace', path: '/plan/Make/lemonade', value: testCase.lemonade }];
179
+
180
+ // Tick with modified context
181
+ const tickResult = await exec(`pnpm run --silent sdk tick --patch '${JSON.stringify(patch)}'`);
182
+ const state = JSON.parse(tickResult.stdout);
183
+
184
+ // Verify the engine played the day on the patched plan
185
+ const line = state.context.results.Lines.lemonade;
186
+ assert(line.Made === testCase.lemonade);
187
+ assert(line.Sold + line.PouredAway === line.Made);
188
+
189
+ console.log(`Test case (lemonade=${testCase.lemonade}): passed`);
190
+ }
191
+ ```
192
+
193
+ For a multi-tick run in CI, prefer [`createTestSession`](./guides/engine-testing.md), which plays a whole run in one process with no server and no port. `--no-server` is no substitute: each command is then a fresh session, so two ticks both report `completedTicks: 1`.
194
+
195
+ For a game with several teams, pass `--team N` to `tick`, `patch`, and `view`; the [multi-team games guide](./guides/multi-team-games.md) explains how shared-state and independent games advance. For letting an agent play while you watch the browser, see [Working alongside an agent](./cli-and-dev-server.md#working-alongside-an-agent).
196
+
197
+ ## Verify
198
+
199
+ - `pnpm run --silent sdk view | jq '.completedTicks'` reports the tick you expect after each `tick`
200
+ - A value you patched appears in the `context` that `view` prints
201
+ - `pnpm run sdk dev status` shows the background server the commands are talking to
202
+
203
+ ## Troubleshooting
204
+
205
+ | Problem | Solution |
206
+ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
207
+ | `Error: The game is complete` | The last tick has run. Raise `maxTicks` in `seriousgaming.sdk.json`, or start again with `pnpm run sdk reset` or `pnpm run sdk init` |
208
+ | `Team is already complete` | A `--team N` tick on a team that has finished. Tick another team, or reset |
209
+ | `Tick limit reached` | The game has played its `maxTicks`. Raise `maxTicks`, or start again with `pnpm run sdk reset` |
210
+ | `JSON.parse` fails or `jq` errors on the first line | Use `pnpm run --silent` so the pnpm banner stays out of stdout |
211
+ | `Path does not exist` | The patch path does not match the context. Check it with `pnpm run --silent sdk view \| jq '.context'` |
212
+ | `--team` errors | See [Team addressing errors](./cli-reference.md#team-addressing-errors) |
213
+ | The engine cannot be found | Build the game with `pnpm run build` |
214
+ | The context does not change between ticks | The engine must return a new object built with spreads (`{ capabilities: { ...context, capability: { ...context.capability, Variable: newValue } } }`), not mutate `context` in place |
215
+ | The session is in a state you cannot explain | Stop the server with `pnpm run sdk dev stop`, then run `pnpm run sdk tick`. The session is the process, so nothing carries the problem forward |
216
+
217
+ ## Related
218
+
219
+ - [CLI reference](./cli-reference.md): every command and flag
220
+ - [The CLI and the dev server](./cli-and-dev-server.md): how commands reach the session
221
+ - [Engine testing](./guides/engine-testing.md): `createTestSession` for automated playthroughs
222
+ - [Test with the engine](./recipes/test-with-engine.md)
@@ -0,0 +1,46 @@
1
+ # Core concepts
2
+
3
+ The model behind the SDK on one page. Each resource kind has one guide that explains it in full and is its reference; this page says how they fit together. For the words these docs use, each with one meaning, see the [terminology](./terminology.md).
4
+
5
+ ## A package is a game
6
+
7
+ A game is a package: a directory with a `seriousgaming.sdk.json` (the game's identifier, locales, ticks, teams and waiting room) and one directory per resource. The CLI finds resources by scanning the directories beside the manifest, so there is no list to keep in step.
8
+
9
+ A game holds exactly one of some kinds, each in a fixed **slot** named for it, and any number of the others, each under a plural directory and named by its directory:
10
+
11
+ | Kind | Where | What it is |
12
+ | ------------------------------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------------- |
13
+ | [Capability](../guides/capabilities.md) | `capabilities/<name>/` | A named slice of state, with a schema and no logic |
14
+ | [Settings](../guides/settings.md) | `settings/<name>/` | Read-only parameters, each with a default, fixed when play starts |
15
+ | [Engine](../guides/engine.md) | `engine/` | The tick logic: `Init` and `Run` |
16
+ | [Tick controller](../guides/tick-controller.md) | `tick_controller/` | Automatic tick timing, and when the game is over |
17
+ | [Hook](../guides/hooks.md) | `hooks/<name>/` | Logic run on a lifecycle signal, such as a participant joining |
18
+ | [Validator](../guides/validators.md) | `validators/<name>/` | A read-only check that can reject what a player surface submits |
19
+ | [Endpoint](../guides/endpoints.md) | `endpoints/<name>/` | A server-side handler a surface or an agent calls by identifier |
20
+ | [Game UI](../guides/ui.md) | `ui/` | What each participant plays |
21
+ | [Waiting room UI](../guides/waiting-room.md) | `waiting_room/` | What participants see while the session is held |
22
+ | [Session UI](../guides/session.md) | `session/` | The facilitator's whole-session screen |
23
+ | [Setup](../guides/setup.md) and [scenario editor](../guides/scenario-editor.md) | `setup/`, `scenario_editor/` | The screens that edit settings: per session, and as lasting scenarios |
24
+ | [Presentation](../guides/presentation.md) | `presentation/` | The facilitator's slide deck |
25
+ | [Facilitator guide](../guides/guide.md) | `guide/` | Markdown chapters for whoever runs the session |
26
+ | [Scenario](../guides/scenarios.md) | `scenarios/<name>/` | A variant of the game: settings overrides and static assets |
27
+
28
+ ## How a session runs
29
+
30
+ 1. A facilitator creates a session, choosing a scenario and, if the game has a setup screen, filling it in. The session's settings are resolved and fixed
31
+ 2. The engine's `Init` runs once per team, and the teams' surfaces mount
32
+ 3. In each round, participants make decisions: each is a write to their team's state, checked by the game's validators
33
+ 4. A tick, requested by hand or by the tick controller, runs the engine's `Run` on what the teams submitted and records the round as a snapshot
34
+ 5. When the last tick has run, or the tick controller says so, the game is complete
35
+
36
+ The [CLI and the dev server](../cli-and-dev-server.md) run the same session on your machine.
37
+
38
+ ## Key ideas
39
+
40
+ 1. **Scoped context**: state is organised under capability identifiers, so names cannot collide (`context.sales.Revenue`)
41
+ 2. **Immutable updates**: logic returns what it writes under `capabilities`, built with spreads, and removes paths with `deletes`. It never changes the context it was given
42
+ 3. **Declared data flow**: every resource declares the capabilities it reads and writes, the settings it reads, and the services it uses, so the SDK can generate exact types and deliver exactly that, and nothing else
43
+ 4. **One engine, composed from functions**: a game has one engine, and a simulation with several steps calls them as plain functions from its `Run`, in the order it wants them
44
+ 5. **Logic runs anywhere**: logic uses the JavaScript language alone, with no Node.js or browser APIs, and reaches the outside world only through the callbacks it declares, so the same code runs in the dev server and in production
45
+
46
+ Start with [Capabilities](../guides/capabilities.md) for the data model, then [Engine](../guides/engine.md).
@@ -0,0 +1,322 @@
1
+ # Terminology
2
+
3
+ Definitions of the terms used across the SDK, the CLI, the dev server, and these docs. Each concept has one preferred name. Where older pages use another, the entry lists it under **Also called**, so you can recognise it, and says which word to use.
4
+
5
+ **Keywords:** glossary, terminology, definitions, vocabulary, naming conventions, synonyms, preferred terms
6
+
7
+ ## Sessions, teams, and participants
8
+
9
+ ### Session
10
+
11
+ A single facilitated run of a game. A facilitator starts a session, and it groups one or more **teams**. Every team plays the same game with the same resolved settings, and each has its own context; shared capabilities are the one thing teams hold in common.
12
+
13
+ In the dev server, the session lives in the server's memory. It starts when the server does, whether you ran `sdk dev` or a session command started one in the background, and it ends when the server stops. `sdk init` puts it back at tick 0.
14
+
15
+ ### Team
16
+
17
+ The unit of game state. Every participant on a team sees the same context and makes decisions against the same data. A team has a stable `teamId` (`team-1`, `team-2`, and so on) and a stable zero-based index that never changes for the life of the session.
18
+
19
+ A game that declares `teams.max: 1` and locks it with `gameSettingsConstraints` is single-team. Any other game can run with several teams: the facilitator chooses how many, within `teams.min` and `teams.max`. How teams relate is the game's **interaction mode**.
20
+
21
+ ### Participant
22
+
23
+ A browser session connected to a team. Each participant has:
24
+
25
+ | Field | Meaning |
26
+ | ----------- | ------------------------------------------------------- |
27
+ | `id` | Stable within a session; assigned on first visit |
28
+ | `name` | Display name (defaults to 'Participant N') |
29
+ | `index` | Zero-based join order within the team |
30
+ | `connected` | Whether the participant has a live connection right now |
31
+ | `teamId` | The team this participant belongs to (e.g. `"team-1"`) |
32
+
33
+ A participant is **not** the same as a person. Someone who opens two browser tabs against the same team is two participants. Someone who clears their cookies and comes back is a new participant, and the original stays as disconnected.
34
+
35
+ A game UI reads its own participant with `useUserInterfaceParticipant()` and the team roster with `useUserInterfaceParticipants()`. The session UI reads every team's participants with `useSessionUserInterfaceParticipants()`.
36
+
37
+ **Also called** 'player' in older pages. Use participant. A game's own copy can call them whatever suits it.
38
+
39
+ ### Facilitator
40
+
41
+ The person running the session, from the session UI. 'Facilitator' is a human role, not an SDK type: there is no `facilitator` identifier, and anyone with the session UI's address can use it.
42
+
43
+ ### Author
44
+
45
+ The person creating a scenario, in the scenario editor. On the platform an author may be an end user rather than a facilitator, so an endpoint the editor calls sees `caller.role` as `'author'`, never `'facilitator'`.
46
+
47
+ ### Observer
48
+
49
+ A facilitator watching one team's game UI without joining as a participant, to see how a team is playing, to help with a problem, or to run a debrief. An observer is a behavioural role, not a record: no participant entry, no presence, and absent from the roster. They see the same game UI a participant sees. A UI tells the two apart with `useUserInterfaceViewerRole()`, and while observing, `useUserInterfaceParticipant()` returns `null`. See [Adapt a UI for observers](../recipes/adapt-ui-for-observers.md).
50
+
51
+ ### Viewer role
52
+
53
+ Which viewer a game UI is rendered for: `participant` or `observer`. Read it with `useUserInterfaceViewerRole()`.
54
+
55
+ ### Interaction mode
56
+
57
+ How teams relate within a session, declared as `teams.mode` in `seriousgaming.sdk.json` and fixed by the game:
58
+
59
+ - **`independent`**: teams are isolated from each other, and each team ticks on its own schedule. A shared capability exists, but only the facilitator writes it. **A game that omits `teams.mode` is independent**
60
+ - **`shared-state`**: teams interact through shared capabilities that an aggregate engine computes from every team's state, so all teams tick together
61
+
62
+ The facilitator cannot change the mode when creating a session. See [Multi-team games](../guides/multi-team-games.md).
63
+
64
+ ### Walkthrough
65
+
66
+ A disposable second run of the same game, owned by a session, used to demonstrate the game before it is played for real. It has one team, starts at tick 0, resolves its settings exactly as the session does, and nothing it does reaches the session. It never shows the waiting room, and it is left out of every report.
67
+
68
+ ### Run kind
69
+
70
+ Which run a call belongs to: `'session'` or `'walkthrough'`. Every call into logic carries it as `meta.runKind`, and every UI is told the same value. A game uses it to fill in what a solo demonstration lacks, such as rival teams on a leaderboard, and to keep outward side effects out of it. See [Adapt a game for walkthroughs](../recipes/adapt-a-game-for-walkthroughs.md).
71
+
72
+ ## Game structure
73
+
74
+ ### Game
75
+
76
+ The playable simulation a package is: its engine, capabilities, and UIs, plus how long it runs and how it is configured. Authored as `seriousgaming.sdk.json` itself, one flat object. A game is a blueprint, describing what to run rather than the state of any run.
77
+
78
+ ### Resource
79
+
80
+ One of the things a game is built from: an engine, a capability, a settings resource, a UI (the game UI, the waiting room UI, the session UI, setup, the scenario editor, or the presentation), a hook, a validator, an endpoint, a scenario, a tick controller, or a facilitator guide. Each is a directory holding a `*.sdk.json` bundle. A package declares whatever is on disk; there is no list to keep in step.
81
+
82
+ ### Slot
83
+
84
+ The fixed directory for a resource a game holds exactly one of: `engine`, `ui` (the game UI), `session` (the session UI), `waiting_room`, `setup`, `scenario_editor`, `presentation` (the facilitator's slide deck), `tick_controller`, and `guide` (the facilitator guide). The slot is the resource's identifier, so it is never renamed. Resources a game can hold several of live under a plural directory instead, such as `capabilities/sales/`.
85
+
86
+ ### Identifier
87
+
88
+ The name of a resource inside its package, taken from its directory: `sales`, or the slot, such as `session`. Lowercase letters, digits, and underscores, starting with a letter. A resource never authors its own identifier.
89
+
90
+ A package is named globally, so it keeps a reverse-domain identifier (`com.example.retailgame`), and its game is that identifier with `.game` appended.
91
+
92
+ ### Scenario
93
+
94
+ A named variant of a game: overrides of its settings, the built-in `game` settings such as `maxTicks` among them, and an `assets/` directory of static files. Scenarios carry no logic. A game's scenarios are whatever sits under `scenarios/`; the facilitator picks one when the session starts (`--scenario` in the dev server), and it stays for the session. See [Scenarios](../guides/scenarios.md).
95
+
96
+ ### Capability
97
+
98
+ A named slice of the game's state, with a `variablesSchema` (JSON Schema) describing what it holds. A capability is named by its directory (for example `sales`). Capabilities hold no logic.
99
+
100
+ A capability's **scope** says who else sees it: `team` (the default: each team has its own), `team-readable` (each team writes its own copy, and in a shared-state game a UI that asks can read every team's), `shared` (one value for the whole session), or `private` (hidden from every UI).
101
+
102
+ ### Engine
103
+
104
+ The game's tick logic, in the `engine` slot. It declares which capabilities it `reads` and `writes`, and exports `Init` (set up tick 0) and `Run` (play one tick). A simulation with several steps calls them as functions from `Run`, in the order it wants them. See [Engines](../guides/engine.md).
105
+
106
+ ### Hook
107
+
108
+ Logic that runs when the runtime emits a lifecycle **signal**, outside the tick loop: `participantJoin` when a participant joins a team, and `participantMove` when one moves between teams. A hook subscribes to one signal, runs after the runtime has applied the change, and can write the capabilities it declares. It cannot prevent the change. See [Hooks](../guides/hooks.md).
109
+
110
+ ### Validator
111
+
112
+ A read-only check on every mutation a UI submits, run before the mutation is applied. It sees the state before and after, and either accepts it or rejects it with a message; it never changes state and receives no callbacks. See [Validators](../guides/validators.md).
113
+
114
+ ### Endpoint
115
+
116
+ A server-side handler, exported as `Handle`, that a UI calls by identifier with `callEndpoint`. It validates its request and response against schemas. An endpoint is **team**-scoped (the default: it acts on the calling team's context) or **session**-scoped (it acts on the session as a whole), and one that declares `writes` can change state. An endpoint is also how a UI reaches callbacks such as `generateText`, and one whose `visibility` is `external` can be called from outside the game, for example by a facilitator's AI agent or a platform API. See [Endpoints](../guides/endpoints.md).
117
+
118
+ ### Context
119
+
120
+ The whole game state at a point in time, as an object keyed by capability identifier:
121
+
122
+ ```typescript
123
+ {
124
+ "sales": { Revenue: 100, Units: 50 },
125
+ "costs": { FixedCosts: 200 }
126
+ }
127
+ ```
128
+
129
+ The engine reads it and returns an updated copy. UIs display it and write back to it with `setData`.
130
+
131
+ ### Scoped context
132
+
133
+ Nesting each variable under its capability's identifier, so names cannot collide: `context.sales.Revenue` and `context.costs.Revenue` are different values.
134
+
135
+ ### Shared store
136
+
137
+ The one copy of every `shared` capability in a session. Teams never own shared values: wherever code receives a team's context, the runtime composes a **view** of the team's own capabilities with the store. Only an aggregate engine (in shared-state mode), the facilitator, and session-scoped endpoints write it.
138
+
139
+ ### Board
140
+
141
+ One team's state as a surface or an endpoint sees it: that team's context at a given tick. A write to a board changes that team only. A shared value is read through a board but lives in the shared store, so a team-addressed write cannot change it.
142
+
143
+ ### Aggregate engine
144
+
145
+ An engine that runs once per tick across all teams rather than once per team, receiving every team's context. In shared-state mode it is the only engine that may write shared capabilities.
146
+
147
+ ## Ticks
148
+
149
+ ### Tick
150
+
151
+ One iteration of the game loop: the engine runs on the board the teams submitted, and that board is recorded as a snapshot. Tick N closes round N. The facilitator or a UI triggers a tick by hand (the dev drawer's **Tick**, or `requestTick`), or a tick controller triggers it automatically.
152
+
153
+ **Also called** 'day' or 'turn' in older pages. Use tick for the runtime concept. A game's own copy calls its ticks whatever fits the story: the starter game calls them days.
154
+
155
+ ### Round
156
+
157
+ The play between two ticks. Round N opens when tick N - 1 commits (or when the game is initialised, for round 1) and is closed by tick N. Participants enter its decisions on the board their team holds live.
158
+
159
+ ### Engine tick
160
+
161
+ `meta.tick` on a call into the engine or the tick controller: the tick being run. It is `0` during `Init`, `1` on the first `Run`, and `N` on the `Run` that closes round N. A game with `maxTicks: N` sees `N` on its last `Run`.
162
+
163
+ ### Completed ticks
164
+
165
+ `completedTicks`, wherever it appears: on a surface (`useUserInterfaceData().completedTicks`), on each team in the session UI, in an endpoint's `session`, and in `sdk view --json`. It is the number of ticks that team has completed: `0` until the first tick commits, and `N - 1` during round N. It is always one behind the engine tick of the tick in progress, so the first `Run` of a session sees `meta.tick` of `1` while every surface still shows `0`. A surface names the round in play as `completedTicks + 1`.
166
+
167
+ **Also called** the head tick in older pages. Use completed ticks.
168
+
169
+ ### Snapshot N
170
+
171
+ The record of a closed round, read back with `getPastState` or `usePastState`: the state after tick N (after `Init`, for snapshot 0) together with the decisions made against it. It is captured when tick N + 1 is submitted and recorded once that tick has run, so a team that has completed N ticks holds snapshots 0 to N - 1. The board straight after `Init` is kept as the reset target, not as a snapshot.
172
+
173
+ The first round of one team, in the order things happen (every later round repeats the last three rows with each number one higher):
174
+
175
+ | Moment | Engine tick (`meta.tick`) | Surface `completedTicks` | Snapshots held |
176
+ | ------------------------------------------------------ | ------------------------- | ------------------------------------- | ---------------------------------------------------------- |
177
+ | `Init` runs | `0` | (not yet mounted) | None |
178
+ | Round 1 is played: participants enter decisions | (no engine call) | `0` | None |
179
+ | Tick 1 is requested; the board is captured, `Run` runs | `1` | `0`, with a round shown as processing | None yet |
180
+ | Tick 1 commits; snapshot 0 is recorded | (no engine call) | `1` | Snapshot 0: the post-`Init` state with round 1's decisions |
181
+ | Round 2 is played | (no engine call) | `1` | Snapshot 0 |
182
+
183
+ ### Decision
184
+
185
+ A change a participant or the facilitator makes to the context between ticks. A UI makes one with `setData`. From the CLI, `tick --patch` applies a JSON Patch (RFC 6902) to the context and then runs the tick:
186
+
187
+ ```json
188
+ [{ "op": "replace", "path": "/price/Price", "value": 25 }]
189
+ ```
190
+
191
+ ### Mutation
192
+
193
+ Any state-changing request a UI sends: a context write (`setData`), a tick, an undo or a reset, a settings change, a roster change, or opening the waiting room. Every mutation returns a promise that resolves once the change has taken effect and rejects with a `MutationError` when it is refused. The error's `outcome.kind` says why: `validation-rejected` (a validator said no), `denied` (not permitted), `conflict` (lost a race with a tick, worth retrying), `superseded` (someone else already did it), `tick-failed`, or `error`. Await every mutation, so a refusal reaches the person who made it.
194
+
195
+ ### Tick controller
196
+
197
+ Logic in the `tick_controller` slot that decides automatic tick timing and when the game is over. It exports `GetTickController`, which returns `{ enabled, intervalMs, complete }`: with `enabled` true, the runtime ticks every `intervalMs` milliseconds, and `complete: true` ends the game for good. See [Tick controllers](../guides/tick-controller.md).
198
+
199
+ ## User interfaces
200
+
201
+ A game has up to six UIs, each in its own slot: the game UI, the waiting room UI, the session UI, setup, the scenario editor, and the presentation. Each is a React app the host mounts in a sandboxed iframe and talks to over a message channel. **Surface** is the umbrella word for any of them as mounted by the host; name a particular one by its UI name below.
202
+
203
+ ### Player surface
204
+
205
+ The game UI or the waiting room UI: a surface rendered for one team, for a participant or an observer. Everything a player surface submits is put to the game's validators. Where these docs mean the `ui` slot alone, they say game UI.
206
+
207
+ ### Facilitator surface
208
+
209
+ The session UI, setup, the scenario editor, or the presentation. A facilitator surface is never mounted on a participant's device, and what it submits is never put to validators.
210
+
211
+ ### Game UI
212
+
213
+ What each participant sees and plays with during the game, in the `ui` slot. It reads and writes its team's context, can request ticks, calls endpoints, and uploads files. It also sees the team roster (`useUserInterfaceParticipants()`) and basic facts about every team (`useUserInterfaceTeams()`). The resource type is `ui`, and the SDK API keeps the `UserInterface` names (`UserInterfaceWrapper`, `useUserInterfaceData`). See [Building user interfaces](../guides/ui.md).
214
+
215
+ **Also called** 'play surface', 'player UI', 'player user interface', 'participant interface' and 'game user interface' in older pages. Use game UI, or player surface when the waiting room UI is meant too.
216
+
217
+ ### Session UI
218
+
219
+ The facilitator's whole-session screen, in the `session` slot. It reads and writes every team's context, controls ticks for one team or all of them, manages the roster, writes shared capabilities it declares, and reads the session's join links. Its game-flow callbacks take an optional `teamId` to target one team. In the dev server it is the page at `/`. See [Building session UIs](../guides/session.md).
220
+
221
+ **Also called** 'session surface', 'facilitator UI' and 'session user interface' in older pages. Use session UI, or facilitator surface when setup, the scenario editor and the presentation are meant too.
222
+
223
+ ### Setup
224
+
225
+ The short form a facilitator fills in at session creation, in the `setup` slot. It edits the settings it lists in `configures` and writes that session's overrides only, never context. A game with a setup slot opens at its **configuration step**, which closes when the facilitator presses **Play** (or the form sends `requestPlay`). See [Building a setup screen](../guides/setup.md).
226
+
227
+ **Also called** 'quick config' and 'configuration UI' in older pages. Use setup.
228
+
229
+ ### Scenario editor
230
+
231
+ The screen for authoring lasting scenarios, in the `scenario_editor` slot. It works at any time, with no session, and its output is a saved scenario; the host offers save-as-scenario from it and never from setup. It is optional: `customScenarios.supported` switches custom scenarios on, and an agent can author one from well-described settings schemas alone. See [Building a scenario editor](../guides/scenario-editor.md).
232
+
233
+ **Also called** 'scenario builder' and 'configuration UI' in older pages. Use scenario editor.
234
+
235
+ ### Settings editor
236
+
237
+ Setup and the scenario editor together: the two slots that edit settings rather than context. They share one wrapper, `SettingsEditorWrapper`, and one hook, `useSettingsEditor()`.
238
+
239
+ ### Waiting room UI
240
+
241
+ The holding screen participants see in place of the game UI while the session's waiting room is open, in the `waiting_room` slot. The facilitator opens and closes the room for every team at once, and `waitingRoom.openOnStart` starts a session with it open. Without one, the host shows its own built-in panel. See [Building waiting room UIs](../guides/waiting-room.md).
242
+
243
+ **Also called** 'waiting room user interface' in older pages. Use waiting room UI.
244
+
245
+ ### Presentation
246
+
247
+ The facilitator's slide deck, in the `presentation` slot, shown on a projector during the session. It reads the capabilities it declares, never writes, and is built from `@seriousgaming/deck`. See [Building presentations](../guides/presentation.md).
248
+
249
+ ### Wrapper
250
+
251
+ The SDK component around each kind of UI (`UserInterfaceWrapper`, which the waiting room UI uses too, `SessionUserInterfaceWrapper`, `SettingsEditorWrapper`, `PresentationWrapper`). A wrapper handles the handshake with the host, provides the data, and exposes the hooks the UI code calls.
252
+
253
+ ## Settings
254
+
255
+ ### Settings resource
256
+
257
+ A named, read-only set of parameters: a price, a difficulty, a round length, an answer key. Authored at `settings/<name>/settings.sdk.json` as a `settingsSchema` (JSON Schema) whose every property declares a default. A package may hold any number. A resource (the engine, a UI, the session UI, the waiting room UI, the tick controller, a hook, a validator, or an endpoint) lists the ones it reads in its `settings`, exactly as `reads` names capabilities, and receives exactly those, keyed by identifier: `settings.engine.BaseDemand`. No logic or surface writes one, and settings are not part of the context. See [Settings](../guides/settings.md).
258
+
259
+ **Not to be confused with** the global settings file, `~/.seriousgaming-sdk/config.json`, which holds your API keys (see [Global settings](../guides/global-settings.md)).
260
+
261
+ ### Resolved settings
262
+
263
+ The values a session's settings take: every settings resource, resolved through the settings layers and keyed by settings identifier. A scenario's `settings`, `sdk configure`, and a settings editor's `configures` all use the same keys. Resolved settings are fixed when play starts: at session creation on the platform, and once the configuration step completes in the dev server.
264
+
265
+ ### Settings layers
266
+
267
+ The three layers each settings resource is resolved from, each later one winning: the settings defaults, the active scenario's overrides, and the **session overrides**. There is no game-level layer. The full order, and how each layer is set, is in [Overriding settings](../guides/settings.md#overriding-settings).
268
+
269
+ A running session resolved its settings when it started, so `sdk configure` restarts it on the new values itself, back at tick 0, keeping its team count, scenario, and locale. With no session running, the next one starts on them. Either way, there is no need to run `sdk init` afterwards.
270
+
271
+ ### Session overrides
272
+
273
+ What was changed for this session and nothing else: the top settings layer. The game's setup screen writes it in production. In the dev server, `sdk configure` writes it to `.seriousgaming-sdk/configuration.json`. The layer is sparse: it holds only the keys somebody supplied, never a resolved copy of the layers beneath, so choosing another scenario still takes effect. See [Settings](../guides/settings.md#overriding-settings).
274
+
275
+ ## LLM integration
276
+
277
+ ### generateText
278
+
279
+ A callback for generating text through the Serious Gaming platform's LLM API, available to the engine, hooks, tick controllers, and endpoints once the resource declares it in `uses`. A UI reaches it through an endpoint. It takes one of three tiers:
280
+
281
+ | Tier | Use case |
282
+ | ---------- | ------------------------- |
283
+ | `quick` | Fast, cheap calls |
284
+ | `standard` | Balanced quality and cost |
285
+ | `expert` | Complex reasoning |
286
+
287
+ ### Tier
288
+
289
+ The quality and cost level of an LLM call. The platform maps each tier to a model; a raw model name is not accepted.
290
+
291
+ ## File handling
292
+
293
+ ### Asset reference
294
+
295
+ A string naming a file the SDK can read: `asset:<path>` for a file in the active scenario's `assets/` directory, or `blob:<id>` for a file uploaded at run time. Every callback that takes a file takes one: `getAssetUrl`, `readAsset`, `extractText`. See [Asset references](../guides/file-handling.md).
296
+
297
+ ### Blob
298
+
299
+ A file (an image, a PDF, a spreadsheet) uploaded during a session and stored by the platform. `callbacks.uploadBlob(file)` returns a `blob:` asset reference, which `callbacks.getAssetUrl(reference)` or `callbacks.readAsset(reference)` resolves.
300
+
301
+ ### Blob scope
302
+
303
+ How long a blob lasts:
304
+
305
+ | Scope | Survives a game reset? | Cleared when? |
306
+ | ---------- | ---------------------- | ---------------------------------- |
307
+ | `game` | No | On a game reset or a re-initialise |
308
+ | `settings` | Yes | On a re-initialise |
309
+
310
+ ## Development
311
+
312
+ ### Dev server
313
+
314
+ The local runtime started by `sdk dev`, or in the background by any session command. It holds the session in memory and is the only thing that runs the game's logic. Its page at `/` is the console: the session UI, with a dev drawer (press the backtick key) for ticks, undo, reset, the waiting room, the state as JSON, and errors. Every surface has its own address, such as `/team/1/player/1`. It watches the package, so logic and bundle edits reach the next tick without a reset. See [The CLI and the dev server](../cli-and-dev-server.md).
315
+
316
+ ### CLI
317
+
318
+ The `seriousgaming-sdk` command, run as `pnpm run sdk` in a package. It creates and updates resources, builds and publishes packages, and drives sessions. Session commands print JSON, so a script or an AI agent can play a game. See the [CLI reference](../cli-reference.md).
319
+
320
+ ### Lock file
321
+
322
+ `.seriousgaming-sdk/session.json`, which names the running dev server (its pid, port and instance id, and the tools that started it), or a directory named by `SERIOUSGAMING_DEV_STATE_DIR`. A CLI command reads it to find the session. It holds no session state: the session is never written to disk, and when the server stops, the session is gone. The same directory holds the session overrides (`configuration.json`) and the scenario they were saved under (`configuration-scenario`).