@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.
- package/LICENSE +93 -0
- package/README.md +38 -2
- package/dist/bundling/logic-exports.d.ts +34 -0
- package/dist/bundling/node-builtins.d.ts +21 -0
- package/dist/bundling/transpiler.d.ts +7 -0
- package/dist/cli.js +27404 -0
- package/dist/client/dev-server.d.ts +59 -0
- package/dist/client/index.d.ts +28 -0
- package/dist/client/stub-services.d.ts +32 -0
- package/dist/client/test-session.d.ts +195 -0
- package/dist/client.js +16920 -0
- package/dist/core/asset-reference-translator.d.ts +46 -0
- package/dist/core/clock.d.ts +57 -0
- package/dist/core/faults.d.ts +65 -0
- package/dist/core/game-settings.d.ts +65 -0
- package/dist/core/history.d.ts +89 -0
- package/dist/core/listen-with-fallback.d.ts +30 -0
- package/dist/core/mutation-queue.d.ts +61 -0
- package/dist/core/package-scenario.d.ts +89 -0
- package/dist/core/participant-registry.d.ts +109 -0
- package/dist/core/pending-changes.d.ts +14 -0
- package/dist/core/protocol.d.ts +83 -0
- package/dist/core/scenario-drafts.d.ts +32 -0
- package/dist/core/session-endpoints.d.ts +108 -0
- package/dist/core/session-gates.d.ts +75 -0
- package/dist/core/session-host.d.ts +94 -0
- package/dist/core/session-refusals.d.ts +56 -0
- package/dist/core/session-rewind.d.ts +32 -0
- package/dist/core/session-roster.d.ts +128 -0
- package/dist/core/session-surfaces.d.ts +32 -0
- package/dist/core/session-ticks.d.ts +18 -0
- package/dist/core/session-timers.d.ts +84 -0
- package/dist/core/session-writes.d.ts +40 -0
- package/dist/core/session.d.ts +385 -0
- package/dist/core/settings-locks.d.ts +22 -0
- package/dist/core/team-names.d.ts +52 -0
- package/dist/core/team-state-store.d.ts +218 -0
- package/dist/core/tick-timer.d.ts +75 -0
- package/dist/dev/blob-links.d.ts +10 -0
- package/dist/dev/console/assets/index-DgFglsnA.js +204 -0
- package/dist/dev/console/index.html +12 -0
- package/dist/dev/console-path.d.ts +19 -0
- package/dist/dev/lockfile.d.ts +124 -0
- package/dist/dev/package-watcher.d.ts +21 -0
- package/dist/dev/routes.d.ts +67 -0
- package/dist/dev/shell.d.ts +260 -0
- package/dist/dev/surfaces.d.ts +41 -0
- package/dist/dev/tools-identity.d.ts +23 -0
- package/dist/dev/view/batch.d.ts +172 -0
- package/dist/dev/view/commands.d.ts +75 -0
- package/dist/dev/view/route.d.ts +58 -0
- package/dist/dev/view/view.d.ts +78 -0
- package/dist/dev/view/viewer.d.ts +32 -0
- package/dist/discovery/config.d.ts +9 -0
- package/dist/discovery/manifest-paths.d.ts +21 -0
- package/dist/discovery/removed-fields.d.ts +90 -0
- package/dist/docs/api/deck.md +386 -0
- package/dist/docs/api/index.md +67 -0
- package/dist/docs/api/sdk-commands.md +286 -0
- package/dist/docs/api/sdk-e2e.md +433 -0
- package/dist/docs/api/sdk-projection.md +207 -0
- package/dist/docs/api/sdk-testing.md +214 -0
- package/dist/docs/api/sdk-tools-client.md +560 -0
- package/dist/docs/api/sdk-ui-testing.md +231 -0
- package/dist/docs/api/sdk-ui.md +1269 -0
- package/dist/docs/api/sdk.md +2140 -0
- package/dist/docs/changelog-0.x.md +1156 -0
- package/dist/docs/changelog.md +241 -0
- package/dist/docs/cli-and-dev-server.md +217 -0
- package/dist/docs/cli-error-codes.md +156 -0
- package/dist/docs/cli-reference.md +2489 -0
- package/dist/docs/cli-simulation-testing.md +222 -0
- package/dist/docs/concepts/index.md +46 -0
- package/dist/docs/concepts/terminology.md +322 -0
- package/dist/docs/environment-variables.md +102 -0
- package/dist/docs/getting-started.md +145 -0
- package/dist/docs/guides/ai-facilitation.md +220 -0
- package/dist/docs/guides/capabilities.md +460 -0
- package/dist/docs/guides/endpoints.md +335 -0
- package/dist/docs/guides/engine-testing.md +477 -0
- package/dist/docs/guides/engine.md +527 -0
- package/dist/docs/guides/file-handling.md +405 -0
- package/dist/docs/guides/games.md +176 -0
- package/dist/docs/guides/global-settings.md +94 -0
- package/dist/docs/guides/guide.md +123 -0
- package/dist/docs/guides/hooks.md +183 -0
- package/dist/docs/guides/index.md +51 -0
- package/dist/docs/guides/internationalization.md +288 -0
- package/dist/docs/guides/llm-integration.md +635 -0
- package/dist/docs/guides/multi-team-games.md +586 -0
- package/dist/docs/guides/patterns.md +391 -0
- package/dist/docs/guides/presentation.md +196 -0
- package/dist/docs/guides/production-constraints.md +130 -0
- package/dist/docs/guides/scenario-editor.md +143 -0
- package/dist/docs/guides/scenarios.md +515 -0
- package/dist/docs/guides/session.md +972 -0
- package/dist/docs/guides/settings.md +458 -0
- package/dist/docs/guides/setup.md +193 -0
- package/dist/docs/guides/speech-generation.md +233 -0
- package/dist/docs/guides/starter-game.md +164 -0
- package/dist/docs/guides/testing.md +577 -0
- package/dist/docs/guides/tick-controller.md +569 -0
- package/dist/docs/guides/type-safety.md +516 -0
- package/dist/docs/guides/ui.md +1389 -0
- package/dist/docs/guides/upgrading.md +636 -0
- package/dist/docs/guides/validators.md +217 -0
- package/dist/docs/guides/waiting-room.md +244 -0
- package/dist/docs/index.md +41 -0
- package/dist/docs/recipes/act-on-the-session-from-an-endpoint.md +95 -0
- package/dist/docs/recipes/adapt-a-game-for-walkthroughs.md +133 -0
- package/dist/docs/recipes/adapt-ui-for-observers.md +74 -0
- package/dist/docs/recipes/call-endpoint-from-ui.md +109 -0
- package/dist/docs/recipes/check-a-package-from-a-script.md +117 -0
- package/dist/docs/recipes/create-capability.md +66 -0
- package/dist/docs/recipes/create-endpoint.md +127 -0
- package/dist/docs/recipes/create-engine.md +111 -0
- package/dist/docs/recipes/create-game.md +70 -0
- package/dist/docs/recipes/create-guide.md +75 -0
- package/dist/docs/recipes/create-hook.md +80 -0
- package/dist/docs/recipes/create-presentation.md +142 -0
- package/dist/docs/recipes/create-scenario-editor.md +102 -0
- package/dist/docs/recipes/create-scenario.md +98 -0
- package/dist/docs/recipes/create-session-ui.md +116 -0
- package/dist/docs/recipes/create-settings.md +88 -0
- package/dist/docs/recipes/create-setup.md +115 -0
- package/dist/docs/recipes/create-tick-controller.md +65 -0
- package/dist/docs/recipes/create-user-interface.md +96 -0
- package/dist/docs/recipes/create-validator.md +67 -0
- package/dist/docs/recipes/create-waiting-room-ui.md +109 -0
- package/dist/docs/recipes/declare-api-uses.md +67 -0
- package/dist/docs/recipes/design-state-for-concurrent-writes.md +96 -0
- package/dist/docs/recipes/distribute-package.md +80 -0
- package/dist/docs/recipes/e2e-testing.md +116 -0
- package/dist/docs/recipes/end-game-on-condition.md +154 -0
- package/dist/docs/recipes/fix-duplicate-packages.md +101 -0
- package/dist/docs/recipes/index.md +86 -0
- package/dist/docs/recipes/make-an-endpoint-external.md +101 -0
- package/dist/docs/recipes/negotiate-across-teams.md +164 -0
- package/dist/docs/recipes/observe-other-teams-state.md +119 -0
- package/dist/docs/recipes/publish-a-package.md +139 -0
- package/dist/docs/recipes/remember-a-viewers-choice.md +55 -0
- package/dist/docs/recipes/review-a-past-day.md +73 -0
- package/dist/docs/recipes/share-assets-across-scenarios.md +120 -0
- package/dist/docs/recipes/share-logic-between-engine-and-ui.md +130 -0
- package/dist/docs/recipes/show-all-teams-participants.md +109 -0
- package/dist/docs/recipes/start-from-an-empty-package.md +169 -0
- package/dist/docs/recipes/take-a-file-in-an-endpoint.md +82 -0
- package/dist/docs/recipes/test-a-multi-role-game.md +51 -0
- package/dist/docs/recipes/test-user-interface.md +95 -0
- package/dist/docs/recipes/test-with-engine.md +115 -0
- package/dist/docs/recipes/upload-and-display-files.md +148 -0
- package/dist/docs/recipes/use-request-play.md +65 -0
- package/dist/docs/recipes/use-request-tick.md +75 -0
- package/dist/docs/troubleshooting.md +816 -0
- package/dist/execution/blob-inputs.d.ts +57 -0
- package/dist/execution/bundle-reload.d.ts +42 -0
- package/dist/execution/config-resolver.d.ts +127 -0
- package/dist/execution/configuration-builder.d.ts +66 -0
- package/dist/execution/context-composition.d.ts +161 -0
- package/dist/execution/endpoint-actions.d.ts +9 -0
- package/dist/execution/endpoint-payloads.d.ts +32 -0
- package/dist/execution/endpoint-runner.d.ts +129 -0
- package/dist/execution/engine-state.d.ts +40 -0
- package/dist/execution/executor-callbacks.d.ts +56 -0
- package/dist/execution/executor.d.ts +436 -0
- package/dist/execution/gates.d.ts +45 -0
- package/dist/execution/hook-chain.d.ts +25 -0
- package/dist/execution/logic-calls.d.ts +190 -0
- package/dist/execution/logic-failure.d.ts +84 -0
- package/dist/execution/logic-loader.d.ts +54 -0
- package/dist/execution/logic-result.d.ts +76 -0
- package/dist/execution/tick-controller-call.d.ts +32 -0
- package/dist/execution/types.d.ts +48 -0
- package/dist/generation/ts-type.d.ts +39 -0
- package/dist/guide/locale.d.ts +12 -0
- package/dist/guide/video-registry.d.ts +42 -0
- package/dist/help-examples.d.ts +125 -0
- package/dist/host/adapter.d.ts +67 -0
- package/dist/host/host-channel.d.ts +222 -0
- package/dist/host/index.d.ts +20 -0
- package/dist/host/protocol.d.ts +783 -0
- package/dist/host/surfaces.d.ts +42 -0
- package/dist/host/theme.d.ts +55 -0
- package/dist/host.js +583 -0
- package/dist/prompts/index.d.ts +7 -0
- package/dist/prompts/schema-builder.d.ts +29 -0
- package/dist/prompts/types.d.ts +108 -0
- package/dist/prompts/validators.d.ts +32 -0
- package/dist/runtime/capability-scope.d.ts +6 -0
- package/dist/runtime/context-merge.d.ts +29 -0
- package/dist/runtime/context-projection.d.ts +41 -0
- package/dist/runtime/guarded-callbacks.d.ts +15 -0
- package/dist/runtime/index.d.ts +27 -0
- package/dist/runtime/manifest-version.d.ts +55 -0
- package/dist/runtime/tick-validation.d.ts +25 -0
- package/dist/runtime.js +346 -0
- package/dist/schema.json +1546 -0
- package/dist/server/vite-plugin.d.ts +46 -0
- package/dist/services/tts/client.d.ts +51 -0
- package/dist/services/tts/elevenlabs.d.ts +24 -0
- package/dist/services/tts/types.d.ts +44 -0
- package/dist/storage/asset-resolver.d.ts +49 -0
- package/dist/storage/blob-store.d.ts +41 -0
- package/dist/templates/endpoint/logic.test.ts.liquid +61 -0
- package/dist/templates/endpoint/logic.ts.liquid +25 -0
- package/dist/templates/engine/init.json.liquid +7 -0
- package/dist/templates/engine/logic-aggregate.test.ts.liquid +90 -0
- package/dist/templates/engine/logic-aggregate.ts.liquid +46 -0
- package/dist/templates/engine/logic.test.ts.liquid +61 -0
- package/dist/templates/engine/logic.ts.liquid +32 -0
- package/dist/templates/engine/run.json.liquid +7 -0
- package/dist/templates/guide/01-at-a-glance.md.liquid +19 -0
- package/dist/templates/guide/02-preparation.md.liquid +18 -0
- package/dist/templates/guide/03-running-the-session.md.liquid +37 -0
- package/dist/templates/hook/logic.test.ts.liquid +46 -0
- package/dist/templates/hook/logic.ts.liquid +12 -0
- package/dist/templates/package/CLAUDE.md.template +338 -0
- package/dist/templates/package/DESIGN.md.liquid +144 -0
- package/dist/templates/package/README.md.liquid +143 -0
- package/dist/templates/package/claude/rules/workflow-create-capability.md +26 -0
- package/dist/templates/package/claude/rules/workflow-create-endpoint.md +35 -0
- package/dist/templates/package/claude/rules/workflow-create-engine.md +35 -0
- package/dist/templates/package/claude/rules/workflow-create-guide.md +40 -0
- package/dist/templates/package/claude/rules/workflow-create-presentation.md +37 -0
- package/dist/templates/package/claude/rules/workflow-create-user-interface.md +31 -0
- package/dist/templates/package/claude/rules/workflow-publish-package.md +54 -0
- package/dist/templates/package/claude/rules/workflow-test-engine-or-ui.md +30 -0
- package/dist/templates/package/claude/rules/workflow-update-sdk-version.md +43 -0
- package/dist/templates/package/claude/settings.json.template +16 -0
- package/dist/templates/package/gitignore.template +15 -0
- package/dist/templates/package/global-setup.ts.template +21 -0
- package/dist/templates/package/globals.d.ts.template +2 -0
- package/dist/templates/package/oxfmtrc.json.template +14 -0
- package/dist/templates/package/oxlintrc.json.template +238 -0
- package/dist/templates/package/package.json.liquid +65 -0
- package/dist/templates/package/playwright.config.ts.liquid +19 -0
- package/dist/templates/package/pnpm-workspace.yaml.template +27 -0
- package/dist/templates/package/test-setup.ts.liquid +7 -0
- package/dist/templates/package/tsconfig.json.liquid +15 -0
- package/dist/templates/package/vite.config.ts.liquid +19 -0
- package/dist/templates/package/vitest.config.ts.liquid +25 -0
- package/dist/templates/package/vitest.engine.config.ts.liquid +12 -0
- package/dist/templates/presentation/index.html.liquid +20 -0
- package/dist/templates/presentation/src/App.tsx.liquid +49 -0
- package/dist/templates/presentation/src/Slides.tsx.liquid +81 -0
- package/dist/templates/presentation/src/i18n.ts.liquid +54 -0
- package/dist/templates/presentation/src/main.tsx.liquid +14 -0
- package/dist/templates/scenario_editor/src/App.test.tsx.liquid +30 -0
- package/dist/templates/scenario_editor/src/App.tsx.liquid +95 -0
- package/dist/templates/scenario_editor/src/i18n.ts.liquid +44 -0
- package/dist/templates/session/src/App.test.tsx.liquid +60 -0
- package/dist/templates/session/src/App.tsx.liquid +128 -0
- package/dist/templates/session/src/i18n.ts.liquid +53 -0
- package/dist/templates/session/src/main.tsx.liquid +48 -0
- package/dist/templates/session/src/theme.ts.liquid +46 -0
- package/dist/templates/settings-editor/index.html.liquid +12 -0
- package/dist/templates/settings-editor/src/main.tsx.liquid +48 -0
- package/dist/templates/settings-editor/src/theme.ts.liquid +24 -0
- package/dist/templates/setup/src/App.test.tsx.liquid +39 -0
- package/dist/templates/setup/src/App.tsx.liquid +102 -0
- package/dist/templates/setup/src/i18n.ts.liquid +47 -0
- package/dist/templates/starter-game/capabilities/briefing/capability.sdk.json +18 -0
- package/dist/templates/starter-game/capabilities/plan/capability.sdk.json +17 -0
- package/dist/templates/starter-game/capabilities/results/capability.sdk.json +61 -0
- package/dist/templates/starter-game/capabilities/roles/capability.sdk.json +17 -0
- package/dist/templates/starter-game/capabilities/weather/capability.sdk.json +23 -0
- package/dist/templates/starter-game/engine/defaults.ts +81 -0
- package/dist/templates/starter-game/engine/engine.sdk.json +12 -0
- package/dist/templates/starter-game/engine/logic.test.ts +221 -0
- package/dist/templates/starter-game/engine/logic.ts +149 -0
- package/dist/templates/starter-game/engine/test-helpers.ts +74 -0
- package/dist/templates/starter-game/engine/types.ts +139 -0
- package/dist/templates/starter-game/guide/content/en/01-at-a-glance.md +51 -0
- package/dist/templates/starter-game/guide/content/en/02-preparation.md +35 -0
- package/dist/templates/starter-game/guide/content/en/03-running-the-day.md +58 -0
- package/dist/templates/starter-game/guide/guide.sdk.json +10 -0
- package/dist/templates/starter-game/guide/guide.test.ts +108 -0
- package/dist/templates/starter-game/hooks/assignproducts/defaults.ts +37 -0
- package/dist/templates/starter-game/hooks/assignproducts/hook.sdk.json +13 -0
- package/dist/templates/starter-game/hooks/assignproducts/logic/logic.test.ts +77 -0
- package/dist/templates/starter-game/hooks/assignproducts/logic/logic.ts +47 -0
- package/dist/templates/starter-game/hooks/assignproducts/types.ts +55 -0
- package/dist/templates/starter-game/package.json +68 -0
- package/dist/templates/starter-game/playwright.config.ts +19 -0
- package/dist/templates/starter-game/scenarios/heatwave/scenario.sdk.json +20 -0
- package/dist/templates/starter-game/scenarios/ordinary_week/scenario.sdk.json +12 -0
- package/dist/templates/starter-game/seriousgaming.sdk.json +23 -0
- package/dist/templates/starter-game/session/defaults.ts +80 -0
- package/dist/templates/starter-game/session/index.html +12 -0
- package/dist/templates/starter-game/session/session.sdk.json +11 -0
- package/dist/templates/starter-game/session/src/App.test.tsx +307 -0
- package/dist/templates/starter-game/session/src/App.tsx +309 -0
- package/dist/templates/starter-game/session/src/Section.tsx +37 -0
- package/dist/templates/starter-game/session/src/TeamDoor.tsx +96 -0
- package/dist/templates/starter-game/session/src/format.ts +8 -0
- package/dist/templates/starter-game/session/src/i18n.ts +51 -0
- package/dist/templates/starter-game/session/src/main.tsx +48 -0
- package/dist/templates/starter-game/session/src/theme.ts +45 -0
- package/dist/templates/starter-game/session/types.ts +135 -0
- package/dist/templates/starter-game/settings/engine/settings.sdk.json +50 -0
- package/dist/templates/starter-game/settings/menu/settings.sdk.json +78 -0
- package/dist/templates/starter-game/settings/session/settings.sdk.json +23 -0
- package/dist/templates/starter-game/settings/ui/settings.sdk.json +25 -0
- package/dist/templates/starter-game/test-setup.ts +7 -0
- package/dist/templates/starter-game/testing/e2e/game.spec.ts +139 -0
- package/dist/templates/starter-game/testing/e2e/global-setup.ts +21 -0
- package/dist/templates/starter-game/testing/engine/game.engine.test.ts +171 -0
- package/dist/templates/starter-game/tsconfig.json +19 -0
- package/dist/templates/starter-game/ui/defaults.ts +60 -0
- package/dist/templates/starter-game/ui/index.html +12 -0
- package/dist/templates/starter-game/ui/src/App.test.tsx +138 -0
- package/dist/templates/starter-game/ui/src/App.tsx +175 -0
- package/dist/templates/starter-game/ui/src/DayBar.test.tsx +78 -0
- package/dist/templates/starter-game/ui/src/DayBar.tsx +72 -0
- package/dist/templates/starter-game/ui/src/HistoryPanel.test.tsx +74 -0
- package/dist/templates/starter-game/ui/src/HistoryPanel.tsx +120 -0
- package/dist/templates/starter-game/ui/src/MakeRow.tsx +129 -0
- package/dist/templates/starter-game/ui/src/Section.tsx +37 -0
- package/dist/templates/starter-game/ui/src/ThemeToggle.tsx +49 -0
- package/dist/templates/starter-game/ui/src/TodayPanel.test.tsx +179 -0
- package/dist/templates/starter-game/ui/src/TodayPanel.tsx +92 -0
- package/dist/templates/starter-game/ui/src/YesterdayPanel.tsx +142 -0
- package/dist/templates/starter-game/ui/src/format.ts +12 -0
- package/dist/templates/starter-game/ui/src/i18n.ts +95 -0
- package/dist/templates/starter-game/ui/src/main.tsx +48 -0
- package/dist/templates/starter-game/ui/src/menu.ts +18 -0
- package/dist/templates/starter-game/ui/src/test-helpers.ts +58 -0
- package/dist/templates/starter-game/ui/src/theme.ts +45 -0
- package/dist/templates/starter-game/ui/src/writes.ts +43 -0
- package/dist/templates/starter-game/ui/types.ts +137 -0
- package/dist/templates/starter-game/ui/ui.sdk.json +11 -0
- package/dist/templates/starter-game/validators/capacity/defaults.ts +37 -0
- package/dist/templates/starter-game/validators/capacity/logic/logic.test.ts +96 -0
- package/dist/templates/starter-game/validators/capacity/logic/logic.ts +45 -0
- package/dist/templates/starter-game/validators/capacity/types.ts +55 -0
- package/dist/templates/starter-game/validators/capacity/validator.sdk.json +11 -0
- package/dist/templates/starter-game/vite.config.ts +19 -0
- package/dist/templates/starter-game/vitest.config.ts +15 -0
- package/dist/templates/starter-game/vitest.engine.config.ts +19 -0
- package/dist/templates/starter-game/waiting_room/defaults.ts +40 -0
- package/dist/templates/starter-game/waiting_room/index.html +12 -0
- package/dist/templates/starter-game/waiting_room/src/App.test.tsx +102 -0
- package/dist/templates/starter-game/waiting_room/src/App.tsx +194 -0
- package/dist/templates/starter-game/waiting_room/src/i18n.ts +33 -0
- package/dist/templates/starter-game/waiting_room/src/main.tsx +48 -0
- package/dist/templates/starter-game/waiting_room/src/theme.ts +45 -0
- package/dist/templates/starter-game/waiting_room/types.ts +59 -0
- package/dist/templates/starter-game/waiting_room/waiting_room.sdk.json +10 -0
- package/dist/templates/tick-controller/logic.ts.liquid +8 -0
- package/dist/templates/ui/index.html.liquid +12 -0
- package/dist/templates/ui/src/App.test.tsx.liquid +41 -0
- package/dist/templates/ui/src/App.tsx.liquid +103 -0
- package/dist/templates/ui/src/i18n.ts.liquid +47 -0
- package/dist/templates/ui/src/main.tsx.liquid +48 -0
- package/dist/templates/ui/src/theme.ts.liquid +46 -0
- package/dist/templates/validator/logic.test.ts.liquid +42 -0
- package/dist/templates/validator/logic.ts.liquid +21 -0
- package/dist/templates/waiting-room/index.html.liquid +12 -0
- package/dist/templates/waiting-room/src/App.test.tsx.liquid +57 -0
- package/dist/templates/waiting-room/src/App.tsx.liquid +118 -0
- package/dist/templates/waiting-room/src/i18n.ts.liquid +44 -0
- package/dist/templates/waiting-room/src/main.tsx.liquid +48 -0
- package/dist/templates/waiting-room/src/theme.ts.liquid +46 -0
- package/dist/templating/resource-metadata.d.ts +131 -0
- package/dist/types.d.ts +14 -0
- package/dist/utils/atomic-write.d.ts +40 -0
- package/dist/utils/cli-error.d.ts +64 -0
- package/dist/utils/document-parser-client.d.ts +20 -0
- package/dist/utils/env-loader.d.ts +40 -0
- package/dist/utils/error-codes.d.ts +339 -0
- package/dist/utils/errors.d.ts +19 -0
- package/dist/utils/global-settings.d.ts +65 -0
- package/dist/utils/llm-client.d.ts +34 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/output.d.ts +109 -0
- package/dist/utils/platform.d.ts +14 -0
- package/dist/utils/prompt.d.ts +36 -0
- package/dist/utils/real-path.d.ts +6 -0
- package/dist/utils/schema-properties.d.ts +35 -0
- package/dist/validation/ajv.d.ts +17 -0
- package/dist/validation/facilitator-guide-validator.d.ts +27 -0
- package/dist/validation/findings.d.ts +40 -0
- package/dist/validation/game-constraints.d.ts +10 -0
- package/dist/validation/game-validator.d.ts +34 -0
- package/dist/validation/package-validation.d.ts +41 -0
- package/dist/validation/package-validator.d.ts +19 -0
- package/dist/validation/resource-validator.d.ts +79 -0
- package/dist/validation/schema-defaults-validator.d.ts +29 -0
- package/dist/validation/schema-validation.d.ts +115 -0
- package/dist/validation/semver.d.ts +9 -0
- package/package.json +123 -3
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# {{ name }}
|
|
2
|
+
|
|
3
|
+
A Serious Gaming game package created with the Serious Gaming SDK.
|
|
4
|
+
|
|
5
|
+
It starts as a complete, playable simulation rather than a blank page: a
|
|
6
|
+
lemonade stand, run for 10 days. Each morning a team decides how many
|
|
7
|
+
lemonades, iced teas, and cookies to make. Whatever they make they pay for,
|
|
8
|
+
whatever is left at closing is poured away, and anyone who wanted something
|
|
9
|
+
that ran out simply leaves. The whole game is the balance between making too
|
|
10
|
+
much and too little.
|
|
11
|
+
|
|
12
|
+
Keep it, change the numbers, or replace the model entirely. What is worth
|
|
13
|
+
keeping either way is the shape around it: state keyed so two people on one team
|
|
14
|
+
cannot overwrite each other, a validator on the one thing they share (the
|
|
15
|
+
stall's capacity), every write awaited so a refusal reaches the person who made
|
|
16
|
+
it, and teams that each open their stall when they are ready.
|
|
17
|
+
|
|
18
|
+
If the package was created with `--empty`, none of the game is here, only the
|
|
19
|
+
package files: `pnpm run sdk docs view recipes/start-from-an-empty-package.md`
|
|
20
|
+
picks up from there.
|
|
21
|
+
|
|
22
|
+
## Getting started
|
|
23
|
+
|
|
24
|
+
Dependencies are installed and types generated when the package is created. If
|
|
25
|
+
the install failed, run `pnpm install` once the cause is fixed.
|
|
26
|
+
|
|
27
|
+
### Play it
|
|
28
|
+
|
|
29
|
+
Start the development server:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm start
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
It opens the facilitator console at `http://localhost:3000`. Open
|
|
36
|
+
`http://localhost:3000/team/1/player/1` in another tab for the first
|
|
37
|
+
participant on team 1, then switch off **Waiting room** in the console to let
|
|
38
|
+
them in. Press the backtick key on any page for the dev drawer: tick, undo, and
|
|
39
|
+
reset controls, and the state as JSON.
|
|
40
|
+
|
|
41
|
+
Edits to logic, UIs, `*.sdk.json` bundles and `seriousgaming.sdk.json` reach
|
|
42
|
+
the running game without a restart. A settings change, which reaches the game
|
|
43
|
+
through `Init`, waits for you to re-initialise once a round has been played:
|
|
44
|
+
the console says so and offers a button.
|
|
45
|
+
|
|
46
|
+
### Drive it from the CLI
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pnpm run sdk tick --patch '[{"op":"replace","path":"/plan/Make/lemonade","value":70}]'
|
|
50
|
+
pnpm run sdk view
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Session commands act on the running dev server's session. With none running,
|
|
54
|
+
they start one in the background; `pnpm run sdk dev status` and
|
|
55
|
+
`pnpm run sdk dev stop` check on it and stop it. Add `--no-server` to run a
|
|
56
|
+
command in-process against a fresh session instead.
|
|
57
|
+
|
|
58
|
+
### Build your package
|
|
59
|
+
|
|
60
|
+
Validate, generate types, and bundle the game into `dist/`:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pnpm run build
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Project structure
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
.
|
|
70
|
+
├── seriousgaming.sdk.json # The package identifier, locales, maxTicks and teams
|
|
71
|
+
├── engine/ # THE engine: one day at the stall
|
|
72
|
+
├── ui/ # THE participant interface: plan, open, review
|
|
73
|
+
├── session/ # THE session interface: the facilitator's screen
|
|
74
|
+
├── waiting_room/ # THE holding screen, shown before and between
|
|
75
|
+
├── guide/ # THE facilitator guide, as markdown chapters
|
|
76
|
+
├── presentation/ # THE slide deck the facilitator projects (add with `new presentation`)
|
|
77
|
+
├── setup/ # THE form a facilitator fills in at session creation (`new setup`)
|
|
78
|
+
├── scenario_editor/ # THE editor for authoring lasting scenarios (`new scenario_editor`)
|
|
79
|
+
├── capabilities/ # The shape of the game's state
|
|
80
|
+
├── settings/ # Read-only parameters, each with a default
|
|
81
|
+
├── validators/ # Reject-only gates on what a surface may write
|
|
82
|
+
├── hooks/ # Lifecycle handlers, outside the tick
|
|
83
|
+
├── endpoints/ # Server-side functions a surface calls by name (`new endpoint`)
|
|
84
|
+
├── scenarios/ # Settings overrides (an ordinary week, a heatwave)
|
|
85
|
+
├── testing/ # Whole-game tests and Playwright specs
|
|
86
|
+
├── dist/ # Built output (generated)
|
|
87
|
+
├── package.json # Package manifest
|
|
88
|
+
└── tsconfig.json # TypeScript configuration
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Running the tests
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pnpm test:run # the engine's arithmetic, and every surface
|
|
95
|
+
pnpm test:engine # the whole game, day by day, in-process
|
|
96
|
+
pnpm test:e2e # the surfaces in a browser, against a dev server of its own
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`test:e2e` starts an isolated dev server of its own on free ports, so it runs
|
|
100
|
+
beside the one you are working in and leaves that session alone.
|
|
101
|
+
|
|
102
|
+
## Adding resources
|
|
103
|
+
|
|
104
|
+
### Create a capability
|
|
105
|
+
|
|
106
|
+
Capabilities define the data the engine and interfaces work with:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pnpm run sdk new capability
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Change the engine or an interface
|
|
113
|
+
|
|
114
|
+
A game holds one engine, one participant interface, one session interface, and
|
|
115
|
+
one waiting room, and the starter game already has each. Edit their code
|
|
116
|
+
directly, and change their bundles with `update`:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pnpm run sdk update engine --help
|
|
120
|
+
pnpm run sdk update ui --help
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### The rest
|
|
124
|
+
|
|
125
|
+
`pnpm run sdk new --help` lists every resource type, including validators,
|
|
126
|
+
hooks, endpoints, scenarios, tick controllers, setup, and the scenario editor.
|
|
127
|
+
|
|
128
|
+
A package is a game, so there is no `new game`: the game's locales, ticks and
|
|
129
|
+
teams live in `seriousgaming.sdk.json` beside the package identifier, its
|
|
130
|
+
parameters live in `settings/`, and every resource is discovered from the
|
|
131
|
+
directory it sits in.
|
|
132
|
+
|
|
133
|
+
## Learn more
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pnpm run sdk docs view getting-started.md
|
|
137
|
+
pnpm run sdk docs view guides/starter-game.md
|
|
138
|
+
pnpm run sdk docs view recipes/index.md
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The same documents are on disk in
|
|
142
|
+
`node_modules/@seriousgaming/sdk-tools/dist/docs/`, and
|
|
143
|
+
describe the SDK version you have installed.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/capabilities/**'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Create a capability
|
|
7
|
+
|
|
8
|
+
Capabilities are the data definitions the engine and UIs read from and write to. Use the SDK CLI rather than hand-editing `capability.sdk.json`.
|
|
9
|
+
|
|
10
|
+
## Order of operations
|
|
11
|
+
|
|
12
|
+
1. **Read the full recipe** before you start:
|
|
13
|
+
```bash
|
|
14
|
+
pnpm run --silent sdk docs view recipes/create-capability.md
|
|
15
|
+
```
|
|
16
|
+
2. **Create the capability** with `pnpm run sdk new capability '{ ... }'`. `definition.identifier` is a short lowercase name (`sales`), which becomes the directory `capabilities/sales/` and the key `context.sales`. The `variablesSchema` must be a full JSON Schema 7 object (`type: 'object'` + `properties` + `required` + `additionalProperties: false`), not a properties-only object. Set `scope` (`team` by default, or `team-readable`, `shared`, `private`) if the capability is not private to each team.
|
|
17
|
+
3. **Declare it** in the `reads` or `writes` of every resource that uses it (`pnpm run sdk update engine --patch '[...]'`, and so on). A resource is handed only the capabilities it declares.
|
|
18
|
+
4. **Verify**: `pnpm run build` should pass without type errors. `new` and `update` regenerate types; run `pnpm run generate` yourself only after editing a bundle by hand.
|
|
19
|
+
|
|
20
|
+
## Things that almost always go wrong
|
|
21
|
+
|
|
22
|
+
- Forgetting to add the capability to a resource's `reads` or `writes`: it is absent from that resource's `context` and generated `Context`
|
|
23
|
+
- Using a properties-only schema: the CLI assumes the full Draft 7 object shape everywhere
|
|
24
|
+
- Putting JSON in a `string`-typed field. Use `object` or `array` types so the generated types stay precise
|
|
25
|
+
- Using an array for something several participants add to at once: the last write wins. Key it by id instead (see `pnpm run --silent sdk docs view recipes/design-state-for-concurrent-writes.md`)
|
|
26
|
+
- A `default` that does not satisfy its own schema: `pnpm run sdk build --validate-only` fails it
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/endpoints/**'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Create an endpoint
|
|
7
|
+
|
|
8
|
+
Endpoints are named, server-side handlers that user interfaces (and, when its `visibility` is `external`, callers outside the game such as a facilitator's AI agent) invoke by identifier. The author owns the request and response schemas; the runtime validates both, builds a scoped context snapshot from the declared `reads` and `writes`, builds guarded callbacks for the declared `uses`, runs `Handle` (or `Plan` then `Respond`), and returns the response to the caller. An endpoint changes game state only if it declares `writes` or `actions`. Use the SDK CLI to scaffold it rather than hand-editing `endpoint.sdk.json`.
|
|
9
|
+
|
|
10
|
+
## Order of operations
|
|
11
|
+
|
|
12
|
+
1. **Read the full recipe** before you start:
|
|
13
|
+
```bash
|
|
14
|
+
pnpm run --silent sdk docs view recipes/create-endpoint.md
|
|
15
|
+
```
|
|
16
|
+
2. **Decide the request and response shapes.** Each is a full JSON Schema 7 object (`type: 'object'` + `properties` + `required` + `additionalProperties: false`).
|
|
17
|
+
3. **Decide what it touches**: which capabilities it `reads`, which it `writes` (if any), which settings resources it reads (`settings`), which runtime callbacks it `uses` (`generateText`, `extractText`, `generateSpeech`, `writeBlob`), which session `actions` it may return (such as advancing a tick or closing the waiting room), whether its `session` argument needs each team's participants (`roster: true`), and its `scope`: `team` (the default: it acts on the calling team's board) or `session` (for a session UI, setup screen, or scenario editor, which has no team of its own).
|
|
18
|
+
4. **Create the endpoint** with `pnpm run sdk new endpoint '{ ... }'`, declaring `identifier`, `requestSchema`, `responseSchema`, and whichever of `reads`, `writes`, `settings`, `uses`, `actions`, `roster`, `scope`, `visibility`, and `description` apply. An outside caller, such as an AI agent, reads `description` to decide whether to call an external endpoint, so write it for that reader. An external endpoint's `requestSchema` must be `"type": "object"` at the top (`EXTERNAL_REQUEST_NOT_OBJECT`); one taking no input declares an object with no properties.
|
|
19
|
+
5. **Implement `Handle`** in `endpoints/<name>/logic/logic.ts`. It takes `{ request, context, callbacks, caller, settings, meta, session }`, plus `team` (`{ teamId, index, name }`) on a team-scoped endpoint, which is how it identifies its own team. Without `writes` or `actions` it returns the response alone; otherwise it returns `{ response, capabilities, actions }`, where `capabilities` holds only the capabilities it changed and `actions` only those it declared. To remove a key (one entry of a map), add `deletes: [['orders', 'Open', id]]` beside `capabilities`; each path must sit under a capability in `writes`. The generated `Handler` type switches shape to match, so the compiler tells you which one you owe. An endpoint whose response must describe the state its effects leave (for example the tick it just advanced) exports `Plan` and `Respond` instead of `Handle`, typed with the generated `Planner` and `Responder`: `Plan` returns the effects alone, and `Respond` receives `plan` and `outcomes` after they have landed and returns the response.
|
|
20
|
+
6. **Allow the UI to call it.** Add the endpoint identifier to the `endpoints` array in the bundle of every UI that should be permitted to call it (`pnpm run sdk update ui --patch '[...]'`). Without this, the host rejects the call and TypeScript flags it. The UI then calls `callbacks.endpoints['<name>'](request)`.
|
|
21
|
+
7. **Add a unit test** in the scaffolded `endpoints/<name>/logic/logic.test.ts` covering the happy path and any branch in `Handle`.
|
|
22
|
+
8. **Verify**: `pnpm run sdk endpoint list` shows its scope and whether it writes; `pnpm run --silent sdk endpoint call <name> --no-server --team 1 --request '{...}'` runs it without a UI; then `pnpm run build` and `pnpm test:run`.
|
|
23
|
+
|
|
24
|
+
## Things that almost always go wrong
|
|
25
|
+
|
|
26
|
+
- Returning a value that does not match `responseSchema`: the runtime rejects it before delivery, and the UI's call rejects with an `EndpointError` of kind `invalid-response`
|
|
27
|
+
- Treating a failed call as one that changed nothing: an `EndpointError` whose `applied` is non-empty means the write and earlier actions landed before a later action failed. Tell the person so, and never retry the call automatically
|
|
28
|
+
- Using a capability not listed in `reads` or `writes`: it is not in `context`
|
|
29
|
+
- Calling a callback not listed in `uses`: the runtime throws
|
|
30
|
+
- Forgetting to add the endpoint identifier to the UI's `endpoints` array: the host rejects every call from that UI
|
|
31
|
+
- Returning a capability outside `writes` in `capabilities`: the whole call fails and none of the change is applied
|
|
32
|
+
- Returning a bare value from an endpoint that declares `writes` or `actions`, or `{ response, capabilities }` from one that declares neither
|
|
33
|
+
- Calling a team-scoped endpoint from a session UI, setup screen, or scenario editor: the build fails. Set `"scope": "session"`
|
|
34
|
+
- Listing an endpoint with `reads`, `writes` or `actions` in the scenario editor: the build fails (`EDITOR_ENDPOINT_STATEFUL`). The editor has no session, so its endpoints read their `settings`, resolved from the scenario being edited, and nothing else
|
|
35
|
+
- Returning binary data inline: declare `'writeBlob'` in `uses`, call `callbacks.writeBlob(bytes, { name, mimeType })`, and return the resulting `blob:<id>` reference in the JSON response
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/engine/**'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Create or change the engine
|
|
7
|
+
|
|
8
|
+
The engine runs each tick. It reads from capabilities and returns the ones it writes under `capabilities`. A game holds one engine, in the `engine/` slot, so its commands take no identifier. Use the SDK CLI to change its bundle rather than hand-editing `engine.sdk.json`.
|
|
9
|
+
|
|
10
|
+
## Order of operations
|
|
11
|
+
|
|
12
|
+
1. **Read the full recipe** before you start:
|
|
13
|
+
```bash
|
|
14
|
+
pnpm run --silent sdk docs view recipes/create-engine.md
|
|
15
|
+
```
|
|
16
|
+
2. **Confirm the capabilities exist.** An engine reads and writes capabilities by their short names (`plan`, `results`). Create any that are missing first (see the create-capability workflow).
|
|
17
|
+
3. **Change or create the bundle.** The starter game already has an engine, so change it with `pnpm run sdk update engine --patch '[...]'` (or a full `update engine '{ ... }'`); `new engine` refuses while `engine/` exists. In an empty package, `pnpm run sdk new engine '{ ... }'`. Declare every capability the engine reads or writes in `reads` / `writes`, and every settings resource it reads in `settings`. A tunable value belongs in a settings resource (`pnpm run sdk new settings`): a full JSON Schema 7 object, with a `default` on every property.
|
|
18
|
+
4. **Implement `Init` and `Run`** in `engine/logic.ts`. Both are async, both take `{ context, settings, callbacks, meta }`, and both return `{ capabilities: Context }`. Never mutate `context`: always spread. Optionally, return `state` beside `capabilities` for memory only the engine needs between ticks (it comes back as `state`; type it with `RunFunction`'s fourth parameter), and return `complete: true` from `Run` to end the game for that team. A simulation with several steps calls them as plain functions from its one `Run`: type each as `StepFunction<Context, Settings>`, pass the context along flat, and wrap only the final one.
|
|
19
|
+
5. **Check the types.** `new` and `update` regenerate `engine/types.ts`; run `pnpm run generate` yourself only after editing the bundle by hand.
|
|
20
|
+
6. **Test it.** Unit tests go in `engine/logic.test.ts`, covering at least the happy path and every branch in `Run`. Whole-game behaviour across several ticks goes in `testing/engine/` and runs with `pnpm test:engine`.
|
|
21
|
+
7. **Verify**: `pnpm run build`, `pnpm test:run`, `pnpm test:engine`, and `pnpm run --silent sdk tick --no-server`, which runs the logic in the restricted production runtime. A running dev server picks up the edit from its next tick, without a reset.
|
|
22
|
+
|
|
23
|
+
## Things that almost always go wrong
|
|
24
|
+
|
|
25
|
+
- Using a capability that is not declared in `reads` / `writes`: it is absent from `context` and from the generated `Context`
|
|
26
|
+
- Mutating `context` directly instead of returning a fresh object via spread
|
|
27
|
+
- Returning the capabilities flat (`{ ...context }`) instead of under `capabilities`: the runtime fails the call
|
|
28
|
+
- Trying to remove a map entry by leaving it out of `capabilities`: a key you leave out keeps its value. Return its path in `deletes` beside `capabilities` instead (`deletes: [['orders', 'Open', id]]`), under a capability in `writes`
|
|
29
|
+
- Using a host global (`structuredClone`, `setTimeout`, `fetch`, `crypto`): production logic runs in a bare V8 isolate. `pnpm run lint` catches most of them
|
|
30
|
+
- Importing a Node built-in (`node:fs`, `path`, `os`, and so on), directly or through a library: the build, `dev` and `tick` refuse it with `LOGIC_NODE_BUILTIN`
|
|
31
|
+
- Using `Math.random()` for anything you keep: derive it from `meta.seed` with `deriveSeed` and `seededRandom`, since a tick may run more than once
|
|
32
|
+
- Calling `Date.now()` or `new Date()`: read `meta.now`, the instant the operation started, which every team's `Run` in one tick and a re-run of it share
|
|
33
|
+
- Keeping a roster in context from `participantJoin` hooks: `Init`, `Run` and the tick controller receive `participants`, the team's roster as the tick started
|
|
34
|
+
- Expecting an edit to replay the ticks already played: a logic edit changes the next tick only. Undo and tick again, or reset to re-run `Init`
|
|
35
|
+
- Using `any` in engine signatures instead of the generated `Context` and `Settings` types
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/guide/**'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Create a facilitator guide
|
|
7
|
+
|
|
8
|
+
Facilitator guides are content, not code: per-locale markdown chapters plus shared images, rendered natively on the facilitator's page. A game holds one guide, in the `guide/` slot, so its commands take no identifier. Scaffold it with the SDK CLI rather than hand-creating the bundle file.
|
|
9
|
+
|
|
10
|
+
## Order of operations
|
|
11
|
+
|
|
12
|
+
1. **Read the full recipe** before you start:
|
|
13
|
+
```bash
|
|
14
|
+
pnpm run --silent sdk docs view recipes/create-guide.md
|
|
15
|
+
```
|
|
16
|
+
2. **Create or change the guide.** The starter game already has one, so edit its chapters directly and change its bundle with `pnpm run sdk update guide`; `new guide` refuses while `guide/` exists. In an empty package, `pnpm run sdk new guide '{ ... }'`. Declare every locale up front: the scaffold creates a chapter skeleton per declared locale, and the per-locale `name` is the title the host renders.
|
|
17
|
+
3. **Write the chapters** in `guide/content/<locale>/`. Chapters are ordered by file name (number them `01-`, `02-`, …) and file names must be identical across locales.
|
|
18
|
+
4. **Validate**: `pnpm run sdk build --validate-only`. This warns on missing translations and fails on malformed video blocks or image references that do not resolve. There is nothing to wire: a `guide/` directory beside `seriousgaming.sdk.json` is served.
|
|
19
|
+
|
|
20
|
+
## Content format
|
|
21
|
+
|
|
22
|
+
- Admonitions are container directives: `:::note`, `:::warning`, `:::tip`, plus the facilitation-specific `:::say`, `:::do`, and `:::timing`. Unknown types render as error blocks
|
|
23
|
+
- Headings build the table of contents (chapter H1 plus H2 to H3); end a heading with `{-}` to omit it
|
|
24
|
+
- Images go in the shared `assets/` directory, referenced relatively (`../../assets/diagram.png` from a chapter)
|
|
25
|
+
- Video embeds are fenced `video` blocks validated against a closed registry (YouTube only):
|
|
26
|
+
````markdown
|
|
27
|
+
```video
|
|
28
|
+
provider: youtube
|
|
29
|
+
id: dQw4w9WgXcQ
|
|
30
|
+
```
|
|
31
|
+
````
|
|
32
|
+
- Raw HTML never renders: it is escaped to visible text. Use markdown, admonitions, and video blocks only
|
|
33
|
+
|
|
34
|
+
## Things that almost always go wrong
|
|
35
|
+
|
|
36
|
+
- Chapter file names differing between locales: the runtime matches chapters by file name, so a renamed translation is treated as missing and falls back
|
|
37
|
+
- Invalid YouTube ids: the id must match the 11-character format exactly; anything else renders an inert error block
|
|
38
|
+
- Writing HTML for layout: it will appear as escaped text. Tables, admonitions, and images cover the supported layouts
|
|
39
|
+
- Breaking the structure `guide/guide.test.ts` checks (in the starter game): run `pnpm test:run` after editing chapters
|
|
40
|
+
- A guide a new facilitator could not run the session from alone: if a step lives only in the designer's head, write it down
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/presentation/**'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Create or change the presentation
|
|
7
|
+
|
|
8
|
+
The presentation is the facilitator's slide deck, shown on their screen and projected to the room. A game holds one, in the `presentation/` slot, so its commands take no identifier. It is read-only: it declares `reads` and `settings`, never `writes`, `uses` or `endpoints`. It is built with `@seriousgaming/deck` (`Deck`, `Slide`, `Step`, and the building blocks `Heading`, `Text`, `Bullets`, `Table`, `Image` and `Chart`).
|
|
9
|
+
|
|
10
|
+
## Order of operations
|
|
11
|
+
|
|
12
|
+
1. **Read the full recipe** before you start:
|
|
13
|
+
```bash
|
|
14
|
+
pnpm run --silent sdk docs view recipes/create-presentation.md
|
|
15
|
+
```
|
|
16
|
+
2. **Check the deck library is installed.** `package.json` must list `@seriousgaming/deck` at the same version as `@seriousgaming/sdk`. If it does not, add it at that version before anything else
|
|
17
|
+
3. **Create or change the bundle.** In a package without one, `pnpm run sdk new presentation '{ ... }'`. Otherwise change its `reads` and `settings` with `pnpm run sdk update presentation --patch '[...]'`, then `pnpm run sdk generate`
|
|
18
|
+
4. **Write the slides** in `presentation/src/`. Every element of the slides array is one slide; give each a stable `key`
|
|
19
|
+
5. **Check both ways it is shown**: `/presentation` during a session and `/presentation?preview` with none, once the user has started `pnpm run sdk dev`. Then `pnpm run build`
|
|
20
|
+
|
|
21
|
+
## Habits that keep an export faithful
|
|
22
|
+
|
|
23
|
+
A facilitator exports the deck and edits the PowerPoint, where words are editable and visuals are pictures. `pnpm run --silent sdk docs view guides/presentation.md` explains each habit; hold to them:
|
|
24
|
+
|
|
25
|
+
- **Use the building blocks** (`Heading`, `Text`, `Bullets`, `Table`) for anything a facilitator might edit
|
|
26
|
+
- **Render with `session === null`**, showing labelled sample figures where results would go
|
|
27
|
+
- **Branch on settings, not the scenario name**
|
|
28
|
+
- **Draw a custom animation's end state** when `useSlide().mode` is `'static'`
|
|
29
|
+
- **Route every word through i18n**, and keep one element per slide
|
|
30
|
+
|
|
31
|
+
## Things that almost always go wrong
|
|
32
|
+
|
|
33
|
+
- Reading `session.data` without checking `session` first: the no-session preview breaks
|
|
34
|
+
- A slide that comes and goes with a setting but has no `key`: the remembered position lands on the wrong slide
|
|
35
|
+
- Branching on `game.scenarioName`: the deck shows the wrong slides for a facilitator's saved scenario
|
|
36
|
+
- A chart or diagram drawn as text the facilitator expects to edit: it exports as a picture, so put the words they will change in a `Text` or `Table` beside it
|
|
37
|
+
- A word written straight into a slide rather than added to `src/i18n.ts`: it stays in English whatever the session's language
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/ui/**'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Create or change a user interface
|
|
7
|
+
|
|
8
|
+
A user interface is a React app that reads game state and (optionally) sends decisions back via `setData`. A game holds one participant interface, in the `ui/` slot, so its commands take no identifier; `session/` and `waiting_room/` are the facilitator's screen and the holding screen, and work the same way. Use the SDK CLI to change a bundle rather than hand-editing `ui.sdk.json`.
|
|
9
|
+
|
|
10
|
+
## Order of operations
|
|
11
|
+
|
|
12
|
+
1. **Read the full recipe** before you start:
|
|
13
|
+
```bash
|
|
14
|
+
pnpm run --silent sdk docs view recipes/create-user-interface.md
|
|
15
|
+
```
|
|
16
|
+
2. **Confirm the capabilities exist.** A UI reads (and optionally writes) capabilities by their short names. Create any that are missing first.
|
|
17
|
+
3. **Change or create the bundle.** The starter game already has a `ui/`, so change it with `pnpm run sdk update ui --patch '[...]'`; `new ui` refuses while `ui/` exists. In an empty package, `pnpm run sdk new ui '{ ... }'`. Declare every capability the UI shows in `reads`, and add `writes` only for the ones it sends back via `setData`. A UI receives exactly what it declares.
|
|
18
|
+
4. **Implement the components** under `ui/src/` (the entry component is `App.tsx`), with `useUserInterfaceData()` for `data`, `settings`, `setData` and `completedTicks`. Default to MUI; another library must integrate with `useUserInterfaceTheme` so dark mode and colour palettes work, and text on a theme colour uses that colour's `contrastText`. Remember a viewer's own choices with `useViewerStorage`, never `localStorage`. Put every string in `src/i18n.ts`. `pnpm run --silent sdk docs view guides/ui.md` is the reference for every hook.
|
|
19
|
+
5. **Await every write.** `setData` returns a promise that rejects when the host refuses the write. Route writes through `useMutationReporter`, as the starter game's `ui/src/writes.ts` does, so the participant sees the refusal. Never retry a write automatically: on a `conflict` the host has already retried and given up, so offer `failure.retry` behind a 'Try again' button instead.
|
|
20
|
+
6. **Add a test** beside the component (`App.test.tsx`), rendered with `renderUserInterface()` (or `renderSessionUserInterface<SessionData>()`, `renderSettingsEditor()`) from `@seriousgaming/sdk/ui/testing`, as the starter game's tests do. `pnpm run --silent sdk docs view guides/testing.md` has the harness.
|
|
21
|
+
7. **Verify**: `pnpm run build` and `pnpm test:run`. A running dev server hot-reloads the UI. The user starts the dev server (`pnpm run sdk dev`) when they want to see it; never start it yourself.
|
|
22
|
+
|
|
23
|
+
## Things that almost always go wrong
|
|
24
|
+
|
|
25
|
+
- Mocking the SDK contexts with `vi.mock`, or wiring a few providers by hand: the hand-wired version throws once the component uses callbacks or participants. Use `renderUserInterface()` instead, so the component renders as it does in production
|
|
26
|
+
- Forgetting `useUserInterfaceTheme` integration when using a non-MUI styling solution: the UI renders in the wrong colour scheme
|
|
27
|
+
- Writing a capability that is not declared in `writes`: `setData` for it is refused
|
|
28
|
+
- Calling `setData` without awaiting it: a refused write leaves the participant looking at a decision the game never received
|
|
29
|
+
- Expecting the engine's settings to reach the UI: a UI's `settings` holds only the settings resources the UI itself lists in `settings`, never those the engine lists, even for an engine whose capability it reads. List the settings resource in the UI's `settings` too, or write the value into context from the engine and read it via `data`
|
|
30
|
+
- Calling an LLM from the UI: a UI reaches external services only through an endpoint it lists in its `endpoints` array
|
|
31
|
+
- Using `userEvent.type` on controlled inputs in tests: the mock `setData` does not propagate, so the input value never updates between keystrokes. Use `fireEvent.change`
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- 'seriousgaming.sdk.json'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Publish this package
|
|
7
|
+
|
|
8
|
+
`pnpm run sdk package publish` builds (if needed), bundles, and uploads this package to the Serious Gaming platform. Uploads are scoped to a publisher, so the command needs both an API key and a publisher slug.
|
|
9
|
+
|
|
10
|
+
## Before you publish
|
|
11
|
+
|
|
12
|
+
You need:
|
|
13
|
+
|
|
14
|
+
- An API key (`sg_<lookupId>_<secret>`), issued from your organisation's settings page by an account with publishing access. Business Simulations grants that access; if the user's account lacks it, `publish` fails with a 403 and only they can ask for it
|
|
15
|
+
- The slug of the publisher you upload under
|
|
16
|
+
- A bumped version: the platform rejects re-uploads of a version that already exists
|
|
17
|
+
|
|
18
|
+
## Order of operations
|
|
19
|
+
|
|
20
|
+
1. **Configure the key and publisher once.** Either put them in `.env` in this directory (and keep `.env` git-ignored):
|
|
21
|
+
```bash
|
|
22
|
+
SERIOUSGAMING_API_KEY=sg_your_lookup_id_your_secret
|
|
23
|
+
SERIOUSGAMING_PUBLISHER=your-publisher-slug
|
|
24
|
+
```
|
|
25
|
+
Or have the user store them in the global settings file, so every project picks them up (this writes to their home directory, so leave it to them):
|
|
26
|
+
```bash
|
|
27
|
+
pnpm run sdk config set platform.apiKey sg_your_lookup_id_your_secret
|
|
28
|
+
pnpm run sdk config set platform.defaultPublisher your-publisher-slug
|
|
29
|
+
```
|
|
30
|
+
2. **Bump the version** (the platform rejects a duplicate):
|
|
31
|
+
```bash
|
|
32
|
+
pnpm run sdk package version patch
|
|
33
|
+
```
|
|
34
|
+
3. **Build and publish**:
|
|
35
|
+
```bash
|
|
36
|
+
pnpm run sdk build
|
|
37
|
+
pnpm run sdk package publish
|
|
38
|
+
```
|
|
39
|
+
The command runs `package bundle` itself when the zip is missing. On success it prints the hosted `PackageVersionResponse`.
|
|
40
|
+
4. **Capture the result in CI** with `--json`. The envelope's `data` is the `PackageVersionResponse`, and a failure carries a code: `PLATFORM_UNAUTHORISED` (exit 5), `VERSION_EXISTS` or `PLATFORM_REJECTED` (exit 3):
|
|
41
|
+
```bash
|
|
42
|
+
pnpm run --silent sdk package publish --json > publish.json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Resolution and overrides
|
|
46
|
+
|
|
47
|
+
The publisher slug resolves from (highest priority first): `--publisher <slug>`, the `SERIOUSGAMING_PUBLISHER` env var, then `platform.defaultPublisher` in global settings. The API key and the host follow the same order: the flag (`--api-key`, `--host`), then the environment (`SERIOUSGAMING_API_KEY`, `SERIOUSGAMING_API_HOST`, from the shell or `.env`), then global settings (`platform.apiKey`, `platform.apiHost`). The default host is `https://app.businesssimulations.com`; override it with `--host` or `SERIOUSGAMING_API_HOST` for a staging target.
|
|
48
|
+
|
|
49
|
+
## Things that almost always go wrong
|
|
50
|
+
|
|
51
|
+
- **No publisher configured.** The command fails rather than guessing. Set `SERIOUSGAMING_PUBLISHER`, pass `--publisher`, or set `platform.defaultPublisher`
|
|
52
|
+
- **Uploading under the wrong publisher.** The first upload binds this package to a publisher; later versions must use the same one or you get a 400 naming the registered publisher. Do not switch publishers to dodge the error
|
|
53
|
+
- **Version already exists (409).** Bump with `pnpm run sdk package version patch` and retry
|
|
54
|
+
- **Committing the API key.** Keep it in `.env` (git-ignored) or the global settings file, never in tracked source or shell history
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/*.test.ts'
|
|
4
|
+
- '**/*.test.tsx'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Workflow: Test an engine or user interface
|
|
8
|
+
|
|
9
|
+
Unit and component tests live next to the source they cover: the engine's `engine/logic.test.ts` beside `engine/logic.ts`, a hook's, validator's, or endpoint's `logic/logic.test.ts` beside its `logic.ts`, and a UI's `*.test.tsx` beside its components. `pnpm test:run` runs them all. Whole-game tests live in `testing/engine/` and run with `pnpm test:engine`; Playwright specs live in `testing/e2e/` and run with `pnpm test:e2e`.
|
|
10
|
+
|
|
11
|
+
## Order of operations
|
|
12
|
+
|
|
13
|
+
1. **Read the full recipe** that matches what you're testing:
|
|
14
|
+
```bash
|
|
15
|
+
pnpm run --silent sdk docs view recipes/test-user-interface.md # for UI components
|
|
16
|
+
pnpm run --silent sdk docs view recipes/test-with-engine.md # for whole games across several ticks
|
|
17
|
+
```
|
|
18
|
+
2. **For logic**, call `Init`, `Run`, a hook, an endpoint or a validator directly with arguments built by `logicArgs` from `@seriousgaming/sdk/testing` (`logicArgs.run({ context, settings: defaultSettings })`), and assert on the returned `capabilities`. For behaviour across several ticks, hooks, validators, endpoints, participants, undo or automatic ticks, use `createTestSession<Context, SharedContext>` in `testing/engine/`: it runs the session the dev server runs, in-process, with offline stubs for `generateText`, `generateSpeech` and `extractText`. The references are `pnpm run --silent sdk docs view guides/testing.md` and `guides/engine-testing.md`.
|
|
19
|
+
3. **For UI components**, render with `renderUserInterface()` (or `renderSessionUserInterface()`, or `renderSettingsEditor()` for setup and the scenario editor) from `@seriousgaming/sdk/ui/testing`, which supplies every provider the host does. Never `vi.mock` the SDK contexts, and never wire the providers by hand. For a session UI, pass the generated types: `renderSessionUserInterface<SessionData>()`, with fixtures from `createMockTeamState<TeamContext>()` and `createMockSharedState<SharedContext>()`, so a shared capability left on a team fixture fails to compile.
|
|
20
|
+
4. **Cover the branches.** One test per code path: the happy path plus each failure mode, each option flag, each conditional in `Run`.
|
|
21
|
+
5. **Run the tests**: `pnpm test:run` and `pnpm test:engine`. `pnpm test` is watch mode, so leave it to the user. `pnpm test:e2e` starts an isolated dev server of its own on free ports (`testing/e2e/global-setup.ts`), beside any the user has running.
|
|
22
|
+
|
|
23
|
+
## Things that almost always go wrong
|
|
24
|
+
|
|
25
|
+
- Mocking the SDK contexts with `vi.mock` instead of wrapping with the real providers: the test now exercises the mock, not the component
|
|
26
|
+
- Using `userEvent.type` on controlled inputs: the mock `setData` does not propagate, so subsequent keystrokes see the original value. Use `fireEvent.change`
|
|
27
|
+
- Asserting on internal implementation (props, state) instead of observable output (rendered text, `setData` arguments)
|
|
28
|
+
- Taking a green unit test as proof the logic runs in production: tests run in Node, where host globals exist. `pnpm run --silent sdk tick --no-server` runs a tick in the restricted runtime
|
|
29
|
+
- Casting arguments (`as never`, `{} as Callbacks`) or a session's context: `logicArgs` and the typed session make every cast unnecessary, and a cast hides the shape error the test exists to catch
|
|
30
|
+
- Skipping a test for a new resource: the scaffold creates the test file for a reason
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- 'package.json'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Update the SDK version
|
|
7
|
+
|
|
8
|
+
The SDK ships as three npm packages: `@seriousgaming/sdk` (runtime), `@seriousgaming/sdk-tools` (CLI and dev server), and `@seriousgaming/deck` (the presentation's deck library). Update them in lockstep and read the changelog before rebuilding.
|
|
9
|
+
|
|
10
|
+
## Order of operations
|
|
11
|
+
|
|
12
|
+
1. **Check the installed version**:
|
|
13
|
+
```bash
|
|
14
|
+
pnpm run --silent sdk version
|
|
15
|
+
```
|
|
16
|
+
2. **Read the changelog** for everything released since that version:
|
|
17
|
+
```bash
|
|
18
|
+
pnpm run sdk docs view changelog.md
|
|
19
|
+
```
|
|
20
|
+
Pay particular attention to any **Breaking Changes** section. If there are breaking changes, plan how to address them before bumping, and read `pnpm run sdk docs view guides/upgrading.md` too. The docs describe the installed version, so read the new changelog again after step 3.
|
|
21
|
+
3. **Bump all three packages** together. The SDK and its tools are dev dependencies, so keep `-D`; the deck library is a runtime dependency of the presentation and must stay at the same version as the SDK:
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add -D @seriousgaming/sdk@latest @seriousgaming/sdk-tools@latest
|
|
24
|
+
pnpm add @seriousgaming/deck@latest
|
|
25
|
+
```
|
|
26
|
+
The package also lists `@seriousgaming/sdk` under `peerDependencies`; move that range to match.
|
|
27
|
+
4. **Regenerate types**: `pnpm run generate`. New schema fields, renames, or removed fields all surface through the generated `types.ts` files.
|
|
28
|
+
5. **Build and address breakages**: `pnpm run build`. Work through type errors and address each Breaking Changes entry from step 2.
|
|
29
|
+
6. **Run the test suites**: `pnpm test:run` and `pnpm test:engine`.
|
|
30
|
+
7. **Adopt updated scaffold guidance**. New packages are scaffolded with the latest `CLAUDE.md` and `.claude/rules/`, but this package keeps whatever it was scaffolded with. The new version ships its templates inside the installed package, so both sides of the diff are on disk. Check three places and fold in anything relevant:
|
|
31
|
+
1. The changelog entries between the old and new version (from step 2): anything mentioning scaffold, guidance, rules, or `CLAUDE.md` is a candidate to adopt.
|
|
32
|
+
2. The shipped rules in `node_modules/@seriousgaming/sdk-tools/dist/templates/package/claude/rules/` against the local `.claude/rules/`: copy rule files that don't exist locally; for rules that do exist, diff the two and incorporate new guidance while keeping local edits.
|
|
33
|
+
3. The shipped `node_modules/@seriousgaming/sdk-tools/dist/templates/package/CLAUDE.md.template` against the local `CLAUDE.md`: incorporate new advice carefully.
|
|
34
|
+
|
|
35
|
+
The templates are the source of new guidance; the local files are the source of local truth. Propose the merge as a normal reviewable change, skip anything that isn't relevant to this package, and never overwrite local content wholesale. The goal is adoption, not a reset.
|
|
36
|
+
|
|
37
|
+
## Things that almost always go wrong
|
|
38
|
+
|
|
39
|
+
- Bumping only some of the three packages: the runtime and the CLI must agree on the schema, and the deck must match the SDK
|
|
40
|
+
- Skipping the changelog read: breaking changes silently corrupt resources or fail validation later
|
|
41
|
+
- Forgetting `pnpm run generate` after the upgrade: types stay stale and downstream code compiles against the old shape
|
|
42
|
+
- Leaving `package.json` scripts, `pnpm-workspace.yaml`, or the config files behind: the new version's `dist/templates/package/` holds the current copies to compare against
|
|
43
|
+
- Skipping the scaffold guidance check: the package quietly stays on outdated advice and never gains rules added after it was scaffolded
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(pnpm run generate)",
|
|
5
|
+
"Bash(pnpm run --silent sdk build --validate-only:*)",
|
|
6
|
+
"Bash(pnpm run --silent sdk view:*)",
|
|
7
|
+
"Bash(pnpm run --silent sdk tick:*)",
|
|
8
|
+
"Bash(pnpm run --silent sdk init:*)",
|
|
9
|
+
"Bash(pnpm run --silent sdk docs view:*)",
|
|
10
|
+
"Bash(pnpm test:run:*)",
|
|
11
|
+
"Bash(pnpm test:engine:*)",
|
|
12
|
+
"Bash(pnpm run typecheck)",
|
|
13
|
+
"Bash(pnpm run lint)"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build output
|
|
5
|
+
dist/
|
|
6
|
+
|
|
7
|
+
# The dev server's local state: settings overrides, session state and uploaded files
|
|
8
|
+
.seriousgaming-sdk/
|
|
9
|
+
|
|
10
|
+
# Playwright results and reports
|
|
11
|
+
test-results/
|
|
12
|
+
playwright-report/
|
|
13
|
+
|
|
14
|
+
# Local environment
|
|
15
|
+
.env
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { dirname } from 'path';
|
|
2
|
+
|
|
3
|
+
import type { FullConfig } from '@playwright/test';
|
|
4
|
+
import { startDevServer } from '@seriousgaming/sdk-tools/client';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Start the dev server the browser tests run against, and stop it after them.
|
|
8
|
+
*
|
|
9
|
+
* It is the server `sdk dev --isolated --port auto` runs: on free ports, with
|
|
10
|
+
* no lock file, and configured from the package alone, so it starts beside
|
|
11
|
+
* your own dev server and every run begins from the same place. Running it in
|
|
12
|
+
* this process rather than spawning `sdk dev` means stopping it is a call,
|
|
13
|
+
* which a run cannot hang on.
|
|
14
|
+
*/
|
|
15
|
+
export default async function globalSetup(config: FullConfig): Promise<() => Promise<void>> {
|
|
16
|
+
const server = await startDevServer({
|
|
17
|
+
packagePath: config.configFile ? dirname(config.configFile) : process.cwd(),
|
|
18
|
+
});
|
|
19
|
+
process.env.SERIOUSGAMING_DEV_URL = server.url;
|
|
20
|
+
return () => server.stop();
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
|
3
|
+
"ignorePatterns": ["**/*.sdk.json", "seriousgaming.sdk.json", "**/types.ts"],
|
|
4
|
+
"semi": true,
|
|
5
|
+
"trailingComma": "es5",
|
|
6
|
+
"singleQuote": true,
|
|
7
|
+
"printWidth": 100,
|
|
8
|
+
"tabWidth": 4,
|
|
9
|
+
"useTabs": false,
|
|
10
|
+
"experimentalSortImports": {
|
|
11
|
+
"ignoreCase": true
|
|
12
|
+
},
|
|
13
|
+
"experimentalSortPackageJson": true
|
|
14
|
+
}
|