dreamboard 0.1.21 → 0.1.22

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 (186) hide show
  1. package/dist/{chunk-EYYWGWTO.js → chunk-2RCUHMGL.js} +343 -1911
  2. package/dist/chunk-2RCUHMGL.js.map +1 -0
  3. package/dist/{chunk-MOVHYB6E.js → chunk-AQ5UUNJS.js} +1018 -692
  4. package/dist/chunk-AQ5UUNJS.js.map +1 -0
  5. package/dist/{chunk-BMYC6772.js → chunk-H3O43F5P.js} +9765 -3068
  6. package/dist/chunk-H3O43F5P.js.map +1 -0
  7. package/dist/dev-host/dev-api-proxy-plugin.ts +330 -0
  8. package/dist/dev-host/dev-diagnostics.ts +62 -0
  9. package/dist/dev-host/dev-fallback-stylesheet.ts +50 -0
  10. package/dist/dev-host/dev-host-controller.ts +686 -0
  11. package/dist/dev-host/dev-host-player-query.ts +17 -0
  12. package/dist/dev-host/dev-host-session-transport.ts +52 -0
  13. package/dist/dev-host/dev-host-storage.ts +56 -0
  14. package/dist/dev-host/dev-log-relay-plugin.ts +469 -0
  15. package/dist/dev-host/dev-runtime-config.ts +14 -0
  16. package/dist/dev-host/dev-runtime-platform.ts +419 -0
  17. package/dist/dev-host/dev-virtual-modules-plugin.ts +63 -0
  18. package/dist/dev-host/host-main.css +182 -0
  19. package/dist/dev-host/host-main.tsx +754 -0
  20. package/dist/dev-host/index.html +56 -0
  21. package/dist/dev-host/plugin-main.ts +55 -0
  22. package/dist/dev-host/plugin.html +24 -0
  23. package/dist/dev-host/start-dev-server.ts +138 -0
  24. package/dist/dev-host/virtual-modules.d.ts +27 -0
  25. package/dist/dist-FEPN3BDN.js +16543 -0
  26. package/dist/dist-FEPN3BDN.js.map +1 -0
  27. package/dist/{dist-WJRJNFLI.js → dist-FRURQI7Q.js} +4 -2
  28. package/dist/index.js +3 -3
  29. package/dist/internal.js +159 -124
  30. package/dist/internal.js.map +1 -1
  31. package/dist/runtime-packages/tailwind-config/shared-styles.css +146 -0
  32. package/dist/runtime-packages/ui/src/components/.gitkeep +0 -0
  33. package/dist/runtime-packages/ui/src/components/accordion.tsx +66 -0
  34. package/dist/runtime-packages/ui/src/components/ai-elements/actions.tsx +65 -0
  35. package/dist/runtime-packages/ui/src/components/ai-elements/artifact.tsx +147 -0
  36. package/dist/runtime-packages/ui/src/components/ai-elements/branch.tsx +215 -0
  37. package/dist/runtime-packages/ui/src/components/ai-elements/canvas.tsx +22 -0
  38. package/dist/runtime-packages/ui/src/components/ai-elements/chain-of-thought.tsx +228 -0
  39. package/dist/runtime-packages/ui/src/components/ai-elements/code-block.tsx +179 -0
  40. package/dist/runtime-packages/ui/src/components/ai-elements/confirmation.tsx +158 -0
  41. package/dist/runtime-packages/ui/src/components/ai-elements/connection.tsx +28 -0
  42. package/dist/runtime-packages/ui/src/components/ai-elements/context.tsx +408 -0
  43. package/dist/runtime-packages/ui/src/components/ai-elements/controls.tsx +18 -0
  44. package/dist/runtime-packages/ui/src/components/ai-elements/conversation.tsx +97 -0
  45. package/dist/runtime-packages/ui/src/components/ai-elements/edge.tsx +140 -0
  46. package/dist/runtime-packages/ui/src/components/ai-elements/image.tsx +24 -0
  47. package/dist/runtime-packages/ui/src/components/ai-elements/inline-citation.tsx +287 -0
  48. package/dist/runtime-packages/ui/src/components/ai-elements/loader.tsx +96 -0
  49. package/dist/runtime-packages/ui/src/components/ai-elements/message.tsx +463 -0
  50. package/dist/runtime-packages/ui/src/components/ai-elements/node.tsx +71 -0
  51. package/dist/runtime-packages/ui/src/components/ai-elements/open-in-chat.tsx +365 -0
  52. package/dist/runtime-packages/ui/src/components/ai-elements/panel.tsx +15 -0
  53. package/dist/runtime-packages/ui/src/components/ai-elements/plan.tsx +142 -0
  54. package/dist/runtime-packages/ui/src/components/ai-elements/prompt-input.tsx +1380 -0
  55. package/dist/runtime-packages/ui/src/components/ai-elements/queue.tsx +274 -0
  56. package/dist/runtime-packages/ui/src/components/ai-elements/reasoning.tsx +182 -0
  57. package/dist/runtime-packages/ui/src/components/ai-elements/response.tsx +22 -0
  58. package/dist/runtime-packages/ui/src/components/ai-elements/shimmer.tsx +64 -0
  59. package/dist/runtime-packages/ui/src/components/ai-elements/sources.tsx +77 -0
  60. package/dist/runtime-packages/ui/src/components/ai-elements/suggestion.tsx +53 -0
  61. package/dist/runtime-packages/ui/src/components/ai-elements/task.tsx +87 -0
  62. package/dist/runtime-packages/ui/src/components/ai-elements/tool.tsx +165 -0
  63. package/dist/runtime-packages/ui/src/components/ai-elements/toolbar.tsx +16 -0
  64. package/dist/runtime-packages/ui/src/components/ai-elements/web-preview.tsx +263 -0
  65. package/dist/runtime-packages/ui/src/components/alert-dialog.tsx +157 -0
  66. package/dist/runtime-packages/ui/src/components/alert.tsx +66 -0
  67. package/dist/runtime-packages/ui/src/components/avatar.tsx +53 -0
  68. package/dist/runtime-packages/ui/src/components/badge.tsx +46 -0
  69. package/dist/runtime-packages/ui/src/components/button-group.tsx +83 -0
  70. package/dist/runtime-packages/ui/src/components/button.tsx +65 -0
  71. package/dist/runtime-packages/ui/src/components/card.tsx +92 -0
  72. package/dist/runtime-packages/ui/src/components/carousel.tsx +241 -0
  73. package/dist/runtime-packages/ui/src/components/collapsible.tsx +33 -0
  74. package/dist/runtime-packages/ui/src/components/command.tsx +184 -0
  75. package/dist/runtime-packages/ui/src/components/context-menu.tsx +252 -0
  76. package/dist/runtime-packages/ui/src/components/counter.tsx +11 -0
  77. package/dist/runtime-packages/ui/src/components/dialog.tsx +146 -0
  78. package/dist/runtime-packages/ui/src/components/drawer.tsx +132 -0
  79. package/dist/runtime-packages/ui/src/components/dropdown-menu.tsx +257 -0
  80. package/dist/runtime-packages/ui/src/components/form.tsx +168 -0
  81. package/dist/runtime-packages/ui/src/components/header.tsx +13 -0
  82. package/dist/runtime-packages/ui/src/components/hover-card.tsx +44 -0
  83. package/dist/runtime-packages/ui/src/components/input-group.tsx +178 -0
  84. package/dist/runtime-packages/ui/src/components/input.tsx +21 -0
  85. package/dist/runtime-packages/ui/src/components/item.tsx +193 -0
  86. package/dist/runtime-packages/ui/src/components/label.tsx +24 -0
  87. package/dist/runtime-packages/ui/src/components/navigation-menu.tsx +168 -0
  88. package/dist/runtime-packages/ui/src/components/popover.tsx +55 -0
  89. package/dist/runtime-packages/ui/src/components/progress.tsx +31 -0
  90. package/dist/runtime-packages/ui/src/components/radio-group.tsx +45 -0
  91. package/dist/runtime-packages/ui/src/components/resizable.tsx +56 -0
  92. package/dist/runtime-packages/ui/src/components/scroll-area.tsx +58 -0
  93. package/dist/runtime-packages/ui/src/components/select.tsx +187 -0
  94. package/dist/runtime-packages/ui/src/components/separator.tsx +28 -0
  95. package/dist/runtime-packages/ui/src/components/skeleton.tsx +13 -0
  96. package/dist/runtime-packages/ui/src/components/sonner.tsx +25 -0
  97. package/dist/runtime-packages/ui/src/components/spinner.tsx +16 -0
  98. package/dist/runtime-packages/ui/src/components/switch.tsx +31 -0
  99. package/dist/runtime-packages/ui/src/components/table.tsx +137 -0
  100. package/dist/runtime-packages/ui/src/components/tabs.tsx +74 -0
  101. package/dist/runtime-packages/ui/src/components/textarea.tsx +23 -0
  102. package/dist/runtime-packages/ui/src/components/theme-provider.tsx +73 -0
  103. package/dist/runtime-packages/ui/src/components/tooltip.tsx +61 -0
  104. package/dist/runtime-packages/ui/src/components/ui/file-upload.tsx +195 -0
  105. package/dist/runtime-packages/ui/src/hooks/.gitkeep +0 -0
  106. package/dist/runtime-packages/ui/src/index.ts +68 -0
  107. package/dist/runtime-packages/ui/src/lib/utils.ts +6 -0
  108. package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +68 -0
  109. package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +359 -0
  110. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +274 -0
  111. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +214 -0
  112. package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +135 -0
  113. package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +5 -0
  114. package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +194 -0
  115. package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +1 -0
  116. package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +1 -0
  117. package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +162 -0
  118. package/dist/runtime-packages/ui-host-runtime/src/index.ts +2 -0
  119. package/dist/runtime-packages/ui-host-runtime/src/logger.ts +11 -0
  120. package/dist/runtime-packages/ui-host-runtime/src/perf.ts +253 -0
  121. package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +195 -0
  122. package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +138 -0
  123. package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +159 -0
  124. package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +524 -0
  125. package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +12 -0
  126. package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +122 -0
  127. package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +26 -0
  128. package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +477 -0
  129. package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +209 -0
  130. package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +112 -0
  131. package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +318 -0
  132. package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +211 -0
  133. package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +814 -0
  134. package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +334 -0
  135. package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +180 -0
  136. package/dist/scaffold/assets/static/app/tsconfig.framework.json +3 -1
  137. package/dist/scaffold/assets/static/ui/tsconfig.framework.json +7 -19
  138. package/package.json +52 -17
  139. package/skills/dreamboard/SKILL.md +41 -75
  140. package/LICENSE +0 -89
  141. package/NOTICE +0 -1
  142. package/dist/chunk-BMYC6772.js.map +0 -1
  143. package/dist/chunk-EYYWGWTO.js.map +0 -1
  144. package/dist/chunk-MOVHYB6E.js.map +0 -1
  145. package/dist/scaffold/assets/static/ui/App.tsx +0 -22
  146. package/dist/src-CUL7EGGG.js +0 -634
  147. package/dist/src-CUL7EGGG.js.map +0 -1
  148. package/skills/dreamboard/references/authoring-lifecycle.md +0 -102
  149. package/skills/dreamboard/references/board-surfaces.md +0 -36
  150. package/skills/dreamboard/references/board-topology.md +0 -443
  151. package/skills/dreamboard/references/boards-and-topology.md +0 -100
  152. package/skills/dreamboard/references/card-actions.md +0 -107
  153. package/skills/dreamboard/references/cli.md +0 -120
  154. package/skills/dreamboard/references/core-concepts.md +0 -514
  155. package/skills/dreamboard/references/custom-renderers.md +0 -26
  156. package/skills/dreamboard/references/derived-values.md +0 -55
  157. package/skills/dreamboard/references/effects.md +0 -111
  158. package/skills/dreamboard/references/game-contract.md +0 -89
  159. package/skills/dreamboard/references/game-definition.md +0 -89
  160. package/skills/dreamboard/references/game-shell.md +0 -80
  161. package/skills/dreamboard/references/hand-surfaces.md +0 -33
  162. package/skills/dreamboard/references/index.md +0 -112
  163. package/skills/dreamboard/references/inputs-and-targets.md +0 -160
  164. package/skills/dreamboard/references/interactions.md +0 -158
  165. package/skills/dreamboard/references/manifest-fields.md +0 -137
  166. package/skills/dreamboard/references/manifest.md +0 -81
  167. package/skills/dreamboard/references/package-surfaces.md +0 -69
  168. package/skills/dreamboard/references/phases.md +0 -145
  169. package/skills/dreamboard/references/prompts-and-choices.md +0 -55
  170. package/skills/dreamboard/references/quickstart.md +0 -71
  171. package/skills/dreamboard/references/rule-authoring.md +0 -144
  172. package/skills/dreamboard/references/setup-bootstrap.md +0 -78
  173. package/skills/dreamboard/references/stages-and-zones.md +0 -59
  174. package/skills/dreamboard/references/static-views.md +0 -67
  175. package/skills/dreamboard/references/table-queries-and-ops.md +0 -103
  176. package/skills/dreamboard/references/testing-bases.md +0 -147
  177. package/skills/dreamboard/references/testing-generated-contracts.md +0 -142
  178. package/skills/dreamboard/references/testing-runtime-assertions.md +0 -124
  179. package/skills/dreamboard/references/testing-scenarios.md +0 -148
  180. package/skills/dreamboard/references/testing-ui-tests.md +0 -174
  181. package/skills/dreamboard/references/testing.md +0 -161
  182. package/skills/dreamboard/references/ui-architecture.md +0 -137
  183. package/skills/dreamboard/references/ui-components.md +0 -34
  184. package/skills/dreamboard/references/views.md +0 -72
  185. package/skills/dreamboard/references/workspace-layout.md +0 -136
  186. /package/dist/{dist-WJRJNFLI.js.map → dist-FRURQI7Q.js.map} +0 -0
@@ -1,71 +0,0 @@
1
- # Quickstart
2
-
3
- Install Dreamboard, create a workspace, sync generated contracts, compile, and run locally.
4
-
5
- ## Requirements
6
-
7
- - Node 20 or newer
8
-
9
- ## Install
10
-
11
- ```bash
12
- npm install -g dreamboard
13
- dreamboard login
14
- ```
15
-
16
- `dreamboard login` opens a browser for authentication.
17
-
18
- ## Create a workspace
19
-
20
- ```bash
21
- dreamboard new my-deck-builder --description "An exciting deck builder for 4 players"
22
- cd my-deck-builder
23
- ```
24
-
25
- The generated workspace contains generated contracts, a React UI, and reducer-native tests. Read [Workspace layout](./workspace-layout.md) before changing generated files.
26
-
27
- ## Sync generated files
28
-
29
- Run sync after changing `manifest.ts`, reducer definitions, testing contracts, or scaffold-owned files:
30
-
31
- ```bash
32
- dreamboard sync
33
- ```
34
-
35
- `sync` regenerates local contracts from authored source and upload the source files to Dreamboard server for compilation.
36
-
37
- ```bash
38
- pnpm install
39
- ```
40
-
41
- ## Compile
42
-
43
- ```bash
44
- dreamboard compile
45
- ```
46
-
47
- Compile runs local checks, builds the reducer bundle, and uploads the compiled artifact to Dreamboard server.
48
-
49
- ## Run locally
50
-
51
- ```bash
52
- dreamboard dev
53
- ```
54
-
55
- Starts a local Vite server for playtesting the game. It runs the UI locally but connects to Dreamboard server for streaming game state. Open the printed URL to play the current compiled game.
56
-
57
- ## Add test coverage
58
-
59
- ```bash
60
- dreamboard test generate
61
- dreamboard test run
62
- ```
63
-
64
- `test generate` writes workspace-specific testing wrappers and generated contracts. `test run` replays scenario files under `test/scenarios`.
65
-
66
- ## Next steps
67
-
68
- - [Manifest](./manifest.md) explains the static table model.
69
- - [Game contract](./game-contract.md) explains state and phase names.
70
- - [Interactions](./interactions.md) explains player commands and prompts.
71
- - [CLI](./cli.md) is the command reference.
@@ -1,144 +0,0 @@
1
- # Rule authoring
2
-
3
- Reference for authoring Dreamboard rule.md files.
4
-
5
- `rule.md` is the game-design source of intent for a Dreamboard project. Use it
6
- to describe the rules in plain language before you commit to reducer state,
7
- manifest, or UI details.
8
-
9
- ## What `rule.md` is for
10
-
11
- Use `rule.md` for:
12
-
13
- - the game objective and match shape
14
- - setup, turn flow, scoring, and victory rules
15
- - player actions and their legality constraints
16
- - visibility rules and information flow
17
- - edge cases and deterministic tie-break rules
18
-
19
- ## Recommended structure
20
-
21
- Use the same section order for every `rule.md`.
22
-
23
- ### `Overview`
24
-
25
- State the core promise of the game in one short section.
26
-
27
- - supported player count
28
- - objective
29
- - expected match length
30
- - one-paragraph summary of how a turn feels
31
-
32
- ### `Components`
33
-
34
- List the components the rules assume exist.
35
-
36
- - cards, zones, boards, pieces, dice, and resources
37
- - public versus hidden information
38
- - per-player versus shared components
39
- - hard limits such as hand size, stock limits, or caps
40
-
41
- ### `Setup`
42
-
43
- Describe the initial state in ordered steps.
44
-
45
- - how players are seated
46
- - which player acts first
47
- - which components start in which locations
48
- - any setup options or setup-profile differences
49
-
50
- ### `Gameplay`
51
-
52
- Describe the game loop in the order the reducer should implement it.
53
-
54
- For each phase, name:
55
-
56
- - who is allowed to act
57
- - which actions are legal
58
- - what input each action requires
59
- - what ends the phase
60
- - which phase follows next
61
-
62
- When a game has repeated rounds, document the round loop explicitly instead of
63
- implying it.
64
-
65
- ### `Scoring and progression`
66
-
67
- Describe how players gain or lose progress.
68
-
69
- - points, tracks, resources, or thresholds
70
- - when scoring happens
71
- - round-end or trick-end resolution
72
- - tie-breakers for intermediate rankings
73
-
74
- ### `Winning conditions`
75
-
76
- State the exact end trigger and winner resolution rule.
77
-
78
- - when the game ends
79
- - how the winner is chosen
80
- - how ties are broken
81
- - what happens if multiple end conditions become true at once
82
-
83
- ### `Special rules and edge cases`
84
-
85
- List rules that are easy to miss during implementation.
86
-
87
- - simultaneous actions
88
- - empty-deck or empty-pool behavior
89
- - no-op or invalid actions
90
- - forced actions versus optional actions
91
- - what happens when a player cannot act
92
-
93
- ## Example template
94
-
95
- ```markdown
96
- # <Game name>
97
-
98
- ## Overview
99
-
100
- - Players: <min-max> (optimal: <n>)
101
- - Objective: <how a player wins>
102
- - Duration: <target minutes>
103
-
104
- ## Components
105
-
106
- - Shared components:
107
- - Per-player components:
108
- - Public information:
109
- - Hidden information:
110
-
111
- ## Setup
112
-
113
- 1. ...
114
- 2. ...
115
- 3. ...
116
-
117
- ## Gameplay
118
-
119
- ### Phase 1: <name>
120
-
121
- - Acting player(s):
122
- - Allowed actions:
123
- - Validation:
124
- - Completion:
125
- - Next phase:
126
-
127
- ### Phase 2: <name>
128
-
129
- - ...
130
-
131
- ## Scoring and progression
132
-
133
- - ...
134
-
135
- ## Winning conditions
136
-
137
- - End trigger:
138
- - Winner determination:
139
- - Tie-breaker:
140
-
141
- ## Special rules and edge cases
142
-
143
- - ...
144
- ```
@@ -1,78 +0,0 @@
1
- # Setup bootstrap
2
-
3
- Seed initial table state from setup profiles with typed shuffle, deal, and move steps.
4
-
5
- Setup bootstrap steps move components into their starting runtime locations before normal phases run. Use them for deterministic setup work that belongs to a setup profile rather than to turn logic.
6
-
7
- Setup profiles are usually authored through the generated `setupProfiles` helper:
8
-
9
- ```ts
10
- import {
11
- dealToPlayerZone,
12
- setupProfiles,
13
- shuffle,
14
- } from "../shared/manifest-contract";
15
-
16
- export default setupProfiles({
17
- "default-setup": {
18
- initialPhase: "playerTurn",
19
- bootstrap: [
20
- shuffle({ type: "sharedZone", zoneId: "draw" }),
21
- dealToPlayerZone({
22
- from: { type: "sharedZone", zoneId: "draw" },
23
- zoneId: "hand",
24
- count: 5,
25
- }),
26
- ],
27
- },
28
- });
29
- ```
30
-
31
- ## Step types
32
-
33
- | Step | Use for |
34
- | --- | --- |
35
- | `shuffle` | Shuffle a shared zone or board container during setup. |
36
- | `deal` | Deal from a shared zone/container to a per-player zone/container. |
37
- | `move` | Move specific or counted components into zones, board spaces, or board containers. |
38
-
39
- Generated helpers include:
40
-
41
- - `shuffle`
42
- - `dealToPlayerZone`
43
- - `dealToPlayerBoardContainer`
44
- - `seedSharedBoardContainer`
45
- - `seedSharedBoardSpace`
46
-
47
- These helpers are typed against the manifest, so invalid zone, board, space, container, card, piece, or die ids fail at author time.
48
-
49
- ## Bootstrap vs phase enter
50
-
51
- Use bootstrap for static setup:
52
-
53
- - shuffle starting decks
54
- - deal opening hands
55
- - place fixed pieces
56
- - seed shared board spaces or containers
57
-
58
- Use phase `enter` for dynamic setup:
59
-
60
- - choose first player from runtime state
61
- - branch by setup selection
62
- - compute state fields from player count
63
- - run setup that depends on reducer logic
64
-
65
- It is normal to combine both: bootstrap seeds the table, then the first phase initializes active players or public state.
66
-
67
- ## Initial phase
68
-
69
- A setup profile may override the game definition's `initialPhase`:
70
-
71
- ```ts
72
- "short-game": {
73
- initialPhase: "playerTurn",
74
- bootstrap: [...],
75
- }
76
- ```
77
-
78
- Keep `initialPhase` values aligned with `gameContract.phaseNames`.
@@ -1,59 +0,0 @@
1
- # Stages and zones
2
-
3
- Use stages for phase sub-states and zones for declarative hand rendering.
4
-
5
- Stages and zones are optional phase-level primitives. Use them when they simplify a phase without creating extra phase names.
6
-
7
- ## Stages
8
-
9
- Stages are first-match sub-state selectors inside a phase. Declaration order is priority: the first `when` predicate that returns `true` becomes the current stage.
10
-
11
- ```ts
12
- stages: {
13
- discard: definePhaseStage<GameContract, typeof phaseState>()({
14
- when: ({ state }) => state.phase.step === "discard",
15
- allow: ["discardCards"],
16
- }),
17
- main: definePhaseStage<GameContract, typeof phaseState>()({
18
- when: ({ state }) => state.phase.step === "main",
19
- allow: ["buildPath", "tradeWithBank", "endTurn"],
20
- }),
21
- }
22
- ```
23
-
24
- `allow` gates which interaction ids are available in that stage.
25
-
26
- Stages can also use `onEnter` and `onExit` hooks:
27
-
28
- ```ts
29
- onEnter({ state, accept, ops }) {
30
- return accept(pipe(state, ops.patchPhaseState({ enteredMain: true })));
31
- }
32
- ```
33
-
34
- Use stages when one phase has clear internal steps but the surrounding flow is still one conceptual phase.
35
-
36
- ## Zones
37
-
38
- Zones declare which manifest player card zones are projected for generated
39
- `Zone` primitives.
40
-
41
- ```ts
42
- zones: [zones.actionHand],
43
- cardActions: {
44
- playBoost,
45
- playDrawCards,
46
- playBuildPath,
47
- },
48
- ```
49
-
50
- Each entry is a manifest player zone id that stores cards. Import `zones` from the generated manifest contract and use handles such as `zones.actionHand` instead of raw string ids. The runtime reads cards from listed zones and derives playable actions from phase `cardActions` whose `playFrom` matches the zone id.
51
-
52
- The runtime dry-runs each derived card action's validation to determine per-card
53
- playability for UI primitives.
54
-
55
- ## Zone keys
56
-
57
- Manifest zone ids often use kebab case, such as `action-hand`. Generated UI contracts expose JS-friendly zone keys such as `actionHand` for surface configuration while preserving the manifest zone id at runtime.
58
-
59
- Keep the manifest zone id as the source of truth. Do not maintain a parallel UI-only zone id list.
@@ -1,67 +0,0 @@
1
- # Static views
2
-
3
- Use defineStaticView for immutable session-scoped projection such as decorated board topology.
4
-
5
- Static views project immutable data once per reducer session. They receive only the manifest and static queries, so they cannot accidentally include per-player or per-turn state.
6
-
7
- ```ts
8
- export const boardStatic = defineStaticView<GameContract>()({
9
- project: ({ q }) => {
10
- const board = q.board.hex("island");
11
- return {
12
- ...board,
13
- portsByVertexId: computePorts(board),
14
- };
15
- },
16
- });
17
- ```
18
-
19
- Register it in `defineGame`:
20
-
21
- ```ts
22
- export default defineGame({
23
- contract: gameContract,
24
- phases,
25
- views: { player: playerView },
26
- staticView: boardStatic,
27
- });
28
- ```
29
-
30
- ## What belongs in static views
31
-
32
- Good static-view data:
33
-
34
- - board topology
35
- - precomputed board decoration
36
- - labels and ids derived from manifest literals
37
- - fixed layout data for UI components
38
- - static adjacency lookup tables
39
-
40
- Bad static-view data:
41
-
42
- - current pieces on spaces
43
- - active player
44
- - card locations
45
- - resource balances
46
- - prompts or available actions
47
- - anything dependent on `state`, `playerId`, or `runtime`
48
-
49
- Those belong in [Views](./views.md), interactions, or table queries.
50
-
51
- ## Static query surface
52
-
53
- Static views use manifest-backed static queries:
54
-
55
- ```ts
56
- const board = q.board.get("map");
57
- const hex = q.board.hex("island");
58
- const square = q.board.square("grid");
59
- ```
60
-
61
- Use this instead of rebuilding board topology manually in the workspace.
62
-
63
- ## Why static views matter
64
-
65
- Large board topology can dominate runtime update payloads if it is projected on every action. Static views move that data into a once-per-session payload and let dynamic views focus on changing state.
66
-
67
- Keep game-specific decoration local. If the access pattern is broadly reusable, it should become an SDK query instead of repeated workspace code.
@@ -1,103 +0,0 @@
1
- # Table queries and ops
2
-
3
- Read runtime table state with q, write with ops, and compose deterministic state transitions with pipe.
4
-
5
- Reducer callbacks receive two canonical table helpers:
6
-
7
- - `q` for reads
8
- - `ops` for writes
9
-
10
- Use them instead of reading or mutating `state.table` directly.
11
-
12
- ## Read with q
13
-
14
- `q` is a typed query namespace over the runtime table:
15
-
16
- ```ts
17
- const playerIds = q.player.order();
18
- const hand = q.zone.playerCards(playerId, "things-hand");
19
- const card = q.card.get(cardId);
20
- const board = q.board.hex("island");
21
- const vertices = q.board.incidentVertices("island", edgeId);
22
- const resources = q.player.resources(playerId);
23
- ```
24
-
25
- Common groups:
26
-
27
- | Namespace | Reads |
28
- | --- | --- |
29
- | `q.board.*` | Boards, spaces, containers, edges, vertices, adjacency, occupants. |
30
- | `q.zone.*` | Shared zones, per-player zones, card collections. |
31
- | `q.card.*` | Runtime card data, owner, visibility. |
32
- | `q.component.*` | Component locations. |
33
- | `q.slot.*` | Slot occupants and slot occupants by host. |
34
- | `q.player.*` | Player order, next player, resources, affordability. |
35
-
36
- Prefer `q.card.get(cardId)` over parsing card ids. Runtime card data already includes `cardType`, name, text, and properties.
37
-
38
- ## Write with ops
39
-
40
- `ops` is a typed namespace of curried state writers. Compose ops with `pipe`:
41
-
42
- ```ts
43
- return accept(
44
- pipe(
45
- state,
46
- ops.spendResources({ playerId, amounts: { coin: 2 } }),
47
- ops.dealCardsToPlayerZone({
48
- fromZoneId: "market",
49
- playerId,
50
- toZoneId: "hand",
51
- count: 1,
52
- }),
53
- ops.patchPhaseState({ step: "main" }),
54
- ),
55
- );
56
- ```
57
-
58
- Common groups:
59
-
60
- | Operation family | Examples |
61
- | --- | --- |
62
- | Flow | `setActivePlayers`, `advanceActivePlayer`. |
63
- | Authored state | `patchPublicState`, `patchHiddenState`, `patchPlayerPrivateState`, `patchPhaseState`. |
64
- | Zones/cards | `addCardToSharedZone`, `moveCardBetweenSharedZones`, `moveCardFromPlayerZoneToSharedZone`, `dealCardsToPlayerZone`. |
65
- | Board/components | `moveComponentToSpace`, `moveComponentToContainer`, `moveComponentToEdge`, `moveComponentToVertex`. |
66
- | Resources | `addResources`, `spendResources`, `transferResources`, `setResource`. |
67
-
68
- Ops preserve the narrowed phase-state type through `pipe`.
69
-
70
- ## Author helper pattern
71
-
72
- Game-specific helpers should accept `ops` or `q` as arguments:
73
-
74
- ```ts
75
- export function incrementScore(ops: Ops, playerId: PlayerId): Op<GameState> {
76
- return ops.patchPublicState((prev) => ({
77
- ...prev,
78
- scores: {
79
- ...prev.scores,
80
- [playerId]: (prev.scores[playerId] ?? 0) + 1,
81
- },
82
- }));
83
- }
84
- ```
85
-
86
- This keeps helper code testable and tied to the same injected runtime surface as reducer callbacks.
87
-
88
- ## Validation before writes
89
-
90
- Some ops throw if the write is invalid. For example, `ops.spendResources` requires the player to afford the full cost.
91
-
92
- Check business rules in `validate`:
93
-
94
- ```ts
95
- validate({ input, q }) {
96
- if (!q.player.canAfford(input.playerId, COST)) {
97
- return { errorCode: "INSUFFICIENT_RESOURCES" };
98
- }
99
- return null;
100
- }
101
- ```
102
-
103
- Then apply the write in `reduce`.
@@ -1,147 +0,0 @@
1
- # Bases
2
-
3
- Define reusable starting states for scenario tests.
4
-
5
- A base is a deterministic starting state for scenarios. It chooses the seed,
6
- player count, optional setup profile, and setup actions that produce a reusable
7
- checkpoint.
8
-
9
- Bases live under `test/bases/*.base.ts` and are generated into
10
- `test/generated/base-states.generated.ts` by `dreamboard test generate`.
11
-
12
- ## Basic base
13
-
14
- ```ts
15
- import { defineBase } from "../testing-types";
16
-
17
- export default defineBase({
18
- id: "initial-turn",
19
- seed: 1337,
20
- players: 4,
21
- setup: async () => undefined,
22
- });
23
- ```
24
-
25
- Fields:
26
-
27
- | Field | Required | Meaning |
28
- | --- | --- | --- |
29
- | `id` | Yes | Stable base id used by scenarios. |
30
- | `seed` | Yes unless inherited | Reducer seed for deterministic randomness. |
31
- | `players` | Yes unless inherited | Number of seats in the generated base. |
32
- | `setupProfileId` | No | Manifest setup profile to use before setup actions. |
33
- | `extends` | No | Parent base id to hydrate before this setup runs. |
34
- | `setup` | Yes | Async function that prepares the checkpoint. |
35
-
36
- A base without `extends` must declare both `seed` and `players`.
37
-
38
- ## Setup actions
39
-
40
- Use `game.submit` with generated interaction ids and typed params:
41
-
42
- ```ts
43
- export default defineBase({
44
- id: "after-first-placement",
45
- extends: "initial-turn",
46
- setup: async ({ game, seat }) => {
47
- await game.submit(seat(1), "placeThingCard", {
48
- cardId: "a-diamond",
49
- ringId: "ring-1",
50
- });
51
- },
52
- });
53
- ```
54
-
55
- `game.submit` runs the same validation and reducer dispatch path as a scenario
56
- action. If setup fails, generation fails.
57
-
58
- ## Seat helpers
59
-
60
- Use `seat(index)` for stable player references:
61
-
62
- ```ts
63
- const firstPlayer = seat(0);
64
- const secondPlayer = seat(1);
65
- ```
66
-
67
- `seat(index)` throws if the base has fewer players than requested. Prefer it to
68
- literal ids because player id literals are generated from the workspace
69
- manifest and player count.
70
-
71
- ## Setup profiles
72
-
73
- Use `setupProfileId` when the manifest has named setup profiles:
74
-
75
- ```ts
76
- export default defineBase({
77
- id: "standard-opening",
78
- seed: 2026,
79
- players: 4,
80
- setupProfileId: "standard",
81
- setup: async () => undefined,
82
- });
83
- ```
84
-
85
- When a base extends another base, the setup profile is inherited unless the
86
- child declares one. A child base cannot change the effective seed, player count,
87
- or setup profile from its generated parent artifact. If it does, the fingerprint
88
- check fails and you should model that as a separate root base.
89
-
90
- ## Inherited bases
91
-
92
- Use `extends` to avoid rebuilding expensive checkpoints in every scenario:
93
-
94
- ```ts
95
- export default defineBase({
96
- id: "after-setup",
97
- seed: 1337,
98
- players: 4,
99
- setup: async ({ game, seat }) => {
100
- for (const step of SETUP_ORDER) {
101
- await game.submit(seat(step.seat), "placeSetupMarker", {
102
- vertexId: step.vertex,
103
- });
104
- await game.submit(seat(step.seat), "placeSetupPath", {
105
- edgeId: step.edge,
106
- });
107
- }
108
- },
109
- });
110
- ```
111
-
112
- ```ts
113
- export default defineBase({
114
- id: "pending-trade",
115
- extends: "after-setup",
116
- setup: async ({ game, seat }) => {
117
- await game.submit(seat(0), "rollDice");
118
- await game.submit(seat(0), "offerTrade", {
119
- targetPlayerId: seat(1),
120
- give: { brick: 1 },
121
- receive: { wool: 1 },
122
- });
123
- },
124
- });
125
- ```
126
-
127
- Generation hydrates the parent snapshot, runs the child setup, and fingerprints
128
- the parent. If the parent changes, children become stale and must be
129
- regenerated.
130
-
131
- ## What belongs in a base
132
-
133
- Good base setup:
134
-
135
- - opening state
136
- - post-setup state
137
- - pending prompt state shared by several scenarios
138
- - late-game state that would be noisy to replay inline
139
-
140
- Poor base setup:
141
-
142
- - a one-off action used by only one scenario
143
- - assertions
144
- - full playthroughs that hide the rule being tested
145
- - local mutation of generated state files
146
-
147
- Assertions belong in scenarios. Bases create state; scenarios prove behavior.