@dreamboard-games/sdk 0.4.0-alpha.8 → 0.4.0-alpha.9
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/REFERENCE.md +1067 -164
- package/dist/authoring/index.d.ts +4 -9
- package/dist/authoring/index.js +11 -547
- package/dist/authoring/index.js.map +1 -1
- package/dist/authoring-compiler.d.ts +27 -0
- package/dist/authoring-compiler.js +12 -0
- package/dist/authoring-compiler.js.map +1 -0
- package/dist/authoring-materialize-cli.d.ts +1 -0
- package/dist/authoring-materialize-cli.js +46 -0
- package/dist/authoring-materialize-cli.js.map +1 -0
- package/dist/browser-interaction.d.ts +1 -1
- package/dist/{chunk-3BLN5POZ.js → chunk-3PFDHTR7.js} +16 -6
- package/dist/chunk-3PFDHTR7.js.map +1 -0
- package/dist/chunk-45P5CEGH.js +176 -0
- package/dist/chunk-45P5CEGH.js.map +1 -0
- package/dist/chunk-5XTAQ4EQ.js +32 -0
- package/dist/chunk-5XTAQ4EQ.js.map +1 -0
- package/dist/chunk-7ADPYKFT.js +532 -0
- package/dist/chunk-7ADPYKFT.js.map +1 -0
- package/dist/{chunk-44N3T2A5.js → chunk-BUOODBVO.js} +2 -2
- package/dist/{chunk-ZYONCTZ2.js → chunk-GMOBG7Y7.js} +4 -4
- package/dist/{chunk-VTK4TIXC.js → chunk-JRGP6W4V.js} +3 -3
- package/dist/chunk-L3W2FPRQ.js +1793 -0
- package/dist/chunk-L3W2FPRQ.js.map +1 -0
- package/dist/{chunk-XV27IQHA.js → chunk-NGYFBNBP.js} +3 -3
- package/dist/chunk-P6IJ5YVY.js +154 -0
- package/dist/chunk-P6IJ5YVY.js.map +1 -0
- package/dist/{chunk-IYX5OO2K.js → chunk-QQNL4WTX.js} +15 -2
- package/dist/chunk-QQNL4WTX.js.map +1 -0
- package/dist/{chunk-2TAKLJJD.js → chunk-SACZWUA6.js} +139 -46
- package/dist/chunk-SACZWUA6.js.map +1 -0
- package/dist/{chunk-VTNEWMWJ.js → chunk-SFOAY5H4.js} +2 -2
- package/dist/{chunk-VTNEWMWJ.js.map → chunk-SFOAY5H4.js.map} +1 -1
- package/dist/chunk-UNVCT5Z7.js +73 -0
- package/dist/chunk-UNVCT5Z7.js.map +1 -0
- package/dist/{chunk-YGQTL63W.js → chunk-WDR7SKBM.js} +2 -2
- package/dist/chunk-XDGRC6OR.js +7039 -0
- package/dist/chunk-XDGRC6OR.js.map +1 -0
- package/dist/chunk-XLHLFTLI.js +399 -0
- package/dist/chunk-XLHLFTLI.js.map +1 -0
- package/dist/{chunk-B2YBS3SG.js → chunk-YNW3KBDE.js} +41 -13
- package/dist/chunk-YNW3KBDE.js.map +1 -0
- package/dist/codegen.js +1 -1
- package/dist/{components-BTwSIjXj.d.ts → components-BPzsSRs8.d.ts} +1 -1
- package/dist/definitions-0kjPV9wh.d.ts +294 -0
- package/dist/{diagnostics-1BWjRo6-.d.ts → diagnostics-DIi3ina7.d.ts} +2 -1
- package/dist/{index-CFTjJIXd.d.ts → index-CWzWpQzM.d.ts} +1 -1
- package/dist/{index.d-C0PKOVbh.d.ts → index.d-C7Ztirg6.d.ts} +211 -3
- package/dist/index.js +2 -2
- package/dist/package-set.d.ts +2 -2
- package/dist/package-set.js +2 -2
- package/dist/{protocol-nS2ojsGr.d.ts → protocol-B2LWcqB4.d.ts} +9 -0
- package/dist/reducer/advanced.d.ts +4 -4
- package/dist/reducer/advanced.js +7 -26
- package/dist/reducer/advanced.js.map +1 -1
- package/dist/reducer-contract.d.ts +1 -1
- package/dist/reducer-contract.js +2 -2
- package/dist/reducer.d.ts +17 -11
- package/dist/reducer.js +28 -6050
- package/dist/reducer.js.map +1 -1
- package/dist/reference-game-compiler.d.ts +45 -0
- package/dist/reference-game-compiler.js +25 -0
- package/dist/reference-game-compiler.js.map +1 -0
- package/dist/reference-game-source-manifest-cli.d.ts +1 -0
- package/dist/reference-game-source-manifest-cli.js +84 -0
- package/dist/reference-game-source-manifest-cli.js.map +1 -0
- package/dist/reference-games/index.d.ts +7 -217
- package/dist/reference-games/index.js +28 -208
- package/dist/reference-games/index.js.map +1 -1
- package/dist/runtime/primitives.d.ts +3 -3
- package/dist/runtime/primitives.js +3 -3
- package/dist/runtime/runtime-api.d.ts +1 -1
- package/dist/runtime/workspace-contract.d.ts +4 -4
- package/dist/runtime/workspace-contract.js +4 -4
- package/dist/{runtime-Dkfm1x2r.d.ts → runtime-B_w9AO2n.d.ts} +60 -5
- package/dist/{runtime-api-C6aWo9c0.d.ts → runtime-api-xCWLMQRT.d.ts} +2 -0
- package/dist/runtime.d.ts +7 -7
- package/dist/runtime.js +12 -12
- package/dist/schema-9jZzlEWZ.d.ts +220 -0
- package/dist/{stale-contract-artifact-error-C5AaZPJ8.d.ts → stale-contract-artifact-error-XLaweZtF.d.ts} +1 -1
- package/dist/testing-compiler.d.ts +36 -0
- package/dist/testing-compiler.js +236 -0
- package/dist/testing-compiler.js.map +1 -0
- package/dist/testing-runtime.d.ts +97 -21
- package/dist/testing-runtime.js +154 -95
- package/dist/testing-runtime.js.map +1 -1
- package/dist/testing.d.ts +178 -60
- package/dist/testing.js +641 -26
- package/dist/testing.js.map +1 -1
- package/dist/types-Bvptkukh.d.ts +122 -0
- package/dist/{types-CTeN_QAk.d.ts → types-_zfC_7CD.d.ts} +1 -1
- package/dist/ui/components.d.ts +2 -2
- package/dist/ui/plugin-styles.css +1 -1
- package/dist/{ui-contract-Ue6SywvO.d.ts → ui-contract-CUC7Lyoc.d.ts} +1 -1
- package/dist/ui.d.ts +3 -3
- package/dist/{views-Qx-EHBP8.d.ts → views-DE2eZxPz.d.ts} +15 -3
- package/package.json +22 -2
- package/dist/chunk-2TAKLJJD.js.map +0 -1
- package/dist/chunk-3BLN5POZ.js.map +0 -1
- package/dist/chunk-3OZMHZK3.js +0 -40
- package/dist/chunk-3OZMHZK3.js.map +0 -1
- package/dist/chunk-5CQIJHGF.js +0 -663
- package/dist/chunk-5CQIJHGF.js.map +0 -1
- package/dist/chunk-B2YBS3SG.js.map +0 -1
- package/dist/chunk-IYX5OO2K.js.map +0 -1
- package/dist/types-B_3pObUV.d.ts +0 -192
- /package/dist/{chunk-44N3T2A5.js.map → chunk-BUOODBVO.js.map} +0 -0
- /package/dist/{chunk-ZYONCTZ2.js.map → chunk-GMOBG7Y7.js.map} +0 -0
- /package/dist/{chunk-VTK4TIXC.js.map → chunk-JRGP6W4V.js.map} +0 -0
- /package/dist/{chunk-XV27IQHA.js.map → chunk-NGYFBNBP.js.map} +0 -0
- /package/dist/{chunk-YGQTL63W.js.map → chunk-WDR7SKBM.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/testing/scenario-schema.ts","../src/testing/scenario-definition-validation.ts","../src/testing/definitions.ts","../src/testing/scenario-assertion-error.ts","../src/testing/create-expect-api.ts","../src/testing/scenario-player-refs.ts","../src/testing/scenario-replay.ts","../src/testing/canonical.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { manifestSchemaFamily } from \"../reducer/model/manifest.js\";\n\nexport class ScenarioSchemaValueError extends Error {\n readonly path: string;\n\n constructor(path: string, message: string) {\n super(message);\n this.name = \"ScenarioSchemaValueError\";\n this.path = path;\n }\n}\n\nexport function appendScenarioPath(path: string, key: PropertyKey): string {\n if (typeof key === \"number\") {\n return `${path}[${key}]`;\n }\n if (typeof key === \"symbol\") {\n return `${path}[${String(key)}]`;\n }\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)\n ? `${path}.${key}`\n : `${path}[${JSON.stringify(key)}]`;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction resolvePlayerSeatReference(options: {\n readonly value: unknown;\n readonly playerIds: readonly string[];\n readonly path: string;\n}): string {\n if (!isPlainObject(options.value)) {\n throw new ScenarioSchemaValueError(\n options.path,\n \"expected a seat reference shaped as { seat: number }\",\n );\n }\n const keys = Object.keys(options.value);\n if (keys.length !== 1 || keys[0] !== \"seat\") {\n throw new ScenarioSchemaValueError(\n options.path,\n \"expected a seat reference with only the 'seat' field\",\n );\n }\n const seat = options.value.seat;\n const seatPath = appendScenarioPath(options.path, \"seat\");\n if (typeof seat !== \"number\" || !Number.isSafeInteger(seat)) {\n throw new ScenarioSchemaValueError(\n seatPath,\n \"expected a finite safe integer\",\n );\n }\n if (seat < 0 || seat >= options.playerIds.length) {\n throw new ScenarioSchemaValueError(\n seatPath,\n `expected a seat from 0 through ${Math.max(0, options.playerIds.length - 1)}`,\n );\n }\n const playerId = options.playerIds[seat];\n if (playerId === undefined) {\n throw new ScenarioSchemaValueError(\n seatPath,\n `could not resolve seat ${seat}`,\n );\n }\n return playerId;\n}\n\nfunction projectPlayerSeatReference(options: {\n readonly value: unknown;\n readonly playerIds: readonly string[];\n readonly path: string;\n}): { readonly seat: number } {\n if (typeof options.value !== \"string\") {\n throw new ScenarioSchemaValueError(\n options.path,\n \"expected a runtime player id string\",\n );\n }\n const seat = options.playerIds.indexOf(options.value);\n if (seat < 0) {\n throw new ScenarioSchemaValueError(\n options.path,\n `runtime player id '${options.value}' is not assigned to a scenario seat`,\n );\n }\n return { seat };\n}\n\ntype TupleDefinition = {\n readonly items?: readonly z.core.SomeType[];\n readonly rest?: z.core.SomeType | null;\n};\n\ntype IntersectionDefinition = {\n readonly left: z.core.SomeType;\n readonly right: z.core.SomeType;\n};\n\nfunction tupleDefinition(schema: z.ZodTuple): TupleDefinition {\n return schema._zod.def as unknown as TupleDefinition;\n}\n\nfunction intersectionDefinition(\n schema: z.ZodIntersection,\n): IntersectionDefinition {\n return schema._zod.def as unknown as IntersectionDefinition;\n}\n\nfunction asClassicSchema(schema: z.core.SomeType): z.ZodTypeAny {\n return schema as unknown as z.ZodTypeAny;\n}\n\ntype ScenarioSchemaTransformOptions = {\n readonly schema: z.core.SomeType;\n readonly value: unknown;\n readonly playerIds: readonly string[];\n readonly path: string;\n};\n\n/**\n * Resolve only schemas carrying the semantic `playerId` manifest family.\n * Ordinary strings and objects with a coincidental `seat` key are untouched.\n */\nexport function resolveScenarioSeatReferences(\n options: ScenarioSchemaTransformOptions,\n): unknown {\n return transformScenarioSchemaValue({ ...options, direction: \"resolve\" });\n}\n\n/**\n * Convert runtime player ids back to pasteable scenario seat references using\n * the same semantic schema walker as command replay.\n */\nexport function projectScenarioSeatReferences(\n options: ScenarioSchemaTransformOptions,\n): unknown {\n return transformScenarioSchemaValue({ ...options, direction: \"project\" });\n}\n\nfunction transformScenarioSchemaValue(\n options: ScenarioSchemaTransformOptions & {\n readonly direction: \"resolve\" | \"project\";\n },\n): unknown {\n const { schema, value, playerIds, path } = options;\n\n if (manifestSchemaFamily(schema) === \"playerId\") {\n return options.direction === \"resolve\"\n ? resolvePlayerSeatReference({ value, playerIds, path })\n : projectPlayerSeatReference({ value, playerIds, path });\n }\n\n if (schema instanceof z.ZodOptional || schema instanceof z.ZodExactOptional) {\n return value === undefined\n ? value\n : transformScenarioSchemaValue({\n schema: asClassicSchema(schema.unwrap()),\n value,\n playerIds,\n path,\n direction: options.direction,\n });\n }\n if (schema instanceof z.ZodNullable) {\n return value === null\n ? value\n : transformScenarioSchemaValue({\n schema: asClassicSchema(schema.unwrap()),\n value,\n playerIds,\n path,\n direction: options.direction,\n });\n }\n if (\n schema instanceof z.ZodDefault ||\n schema instanceof z.ZodPrefault ||\n schema instanceof z.ZodCatch ||\n schema instanceof z.ZodReadonly ||\n schema instanceof z.ZodNonOptional\n ) {\n return transformScenarioSchemaValue({\n schema: asClassicSchema(schema.unwrap()),\n value,\n playerIds,\n path,\n direction: options.direction,\n });\n }\n if (schema instanceof z.ZodArray) {\n if (!Array.isArray(value)) return value;\n return value.map((item, index) =>\n transformScenarioSchemaValue({\n schema: asClassicSchema(schema.element),\n value: item,\n playerIds,\n path: appendScenarioPath(path, index),\n direction: options.direction,\n }),\n );\n }\n if (schema instanceof z.ZodTuple) {\n if (!Array.isArray(value)) return value;\n const definition = tupleDefinition(schema);\n const items = definition.items ?? [];\n return value.map((item, index) => {\n const itemSchema = items[index] ?? definition.rest;\n return itemSchema\n ? transformScenarioSchemaValue({\n schema: asClassicSchema(itemSchema),\n value: item,\n playerIds,\n path: appendScenarioPath(path, index),\n direction: options.direction,\n })\n : item;\n });\n }\n if (schema instanceof z.ZodObject) {\n if (!isPlainObject(value)) return value;\n const output: Record<string, unknown> = { ...value };\n for (const [key, childSchema] of Object.entries(schema.shape)) {\n if (!Object.prototype.hasOwnProperty.call(value, key)) continue;\n output[key] = transformScenarioSchemaValue({\n schema: asClassicSchema(childSchema),\n value: value[key],\n playerIds,\n path: appendScenarioPath(path, key),\n direction: options.direction,\n });\n }\n return output;\n }\n if (schema instanceof z.ZodRecord) {\n if (!isPlainObject(value)) return value;\n if (manifestSchemaFamily(schema.keyType) === \"playerId\") {\n throw new ScenarioSchemaValueError(\n path,\n \"player-valued record keys cannot be represented by scenario seat references\",\n );\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [\n key,\n transformScenarioSchemaValue({\n schema: asClassicSchema(schema.valueType),\n value: item,\n playerIds,\n path: appendScenarioPath(path, key),\n direction: options.direction,\n }),\n ]),\n );\n }\n if (schema instanceof z.ZodUnion) {\n let firstSeatError: ScenarioSchemaValueError | undefined;\n for (const option of schema.options) {\n try {\n if (\n options.direction === \"project\" &&\n !asClassicSchema(option).safeParse(value).success\n ) {\n continue;\n }\n const resolved = transformScenarioSchemaValue({\n schema: asClassicSchema(option),\n value,\n playerIds,\n path,\n direction: options.direction,\n });\n if (\n options.direction === \"project\" ||\n asClassicSchema(option).safeParse(resolved).success\n ) {\n return resolved;\n }\n } catch (error) {\n if (\n firstSeatError === undefined &&\n error instanceof ScenarioSchemaValueError\n ) {\n firstSeatError = error;\n }\n }\n }\n if (firstSeatError) throw firstSeatError;\n return value;\n }\n if (schema instanceof z.ZodIntersection) {\n const definition = intersectionDefinition(schema);\n const leftResolved = transformScenarioSchemaValue({\n schema: asClassicSchema(definition.left),\n value,\n playerIds,\n path,\n direction: options.direction,\n });\n return transformScenarioSchemaValue({\n schema: asClassicSchema(definition.right),\n value: leftResolved,\n playerIds,\n path,\n direction: options.direction,\n });\n }\n if (schema instanceof z.ZodPipe) {\n return transformScenarioSchemaValue({\n schema: asClassicSchema(schema.in),\n value,\n playerIds,\n path,\n direction: options.direction,\n });\n }\n if (schema instanceof z.ZodLazy) {\n return transformScenarioSchemaValue({\n schema: asClassicSchema(schema.unwrap()),\n value,\n playerIds,\n path,\n direction: options.direction,\n });\n }\n\n return value;\n}\n","import { z } from \"zod\";\nimport { createClientParamSchemasByPhase } from \"../reducer/client-param-schemas.js\";\nimport {\n appendScenarioPath,\n resolveScenarioSeatReferences,\n} from \"./scenario-schema.js\";\nimport { ScenarioSchemaValueError } from \"./scenario-schema.js\";\n\nexport type ScenarioDefinitionValidationCode =\n | \"INVALID_TYPE\"\n | \"UNKNOWN_FIELD\"\n | \"INVALID_VALUE\"\n | \"UNSAFE_INTEGER\"\n | \"OUT_OF_RANGE\"\n | \"UNKNOWN_SETUP_PROFILE\"\n | \"UNKNOWN_INTERACTION\"\n | \"INVALID_COMMAND_PARAMS\"\n | \"NON_SERIALIZABLE\"\n | \"NORMAL_SETUP_UNAVAILABLE\";\n\nexport class ScenarioDefinitionValidationError extends Error {\n readonly code: ScenarioDefinitionValidationCode;\n readonly path: string;\n\n constructor(options: {\n readonly code: ScenarioDefinitionValidationCode;\n readonly path: string;\n readonly reason: string;\n }) {\n super(\n `Invalid scenario definition at '${options.path}': ${options.reason}.`,\n );\n this.name = \"ScenarioDefinitionValidationError\";\n this.code = options.code;\n this.path = options.path;\n }\n}\n\ntype NormalSetupLike = {\n readonly minPlayers: number;\n readonly maxPlayers: number;\n readonly createInitialTable: (options: {\n readonly playerIds: readonly string[];\n }) => unknown;\n};\n\nexport type ScenarioDefinitionGameLike = {\n readonly contract: {\n readonly manifest: {\n readonly normalSetup?: NormalSetupLike;\n readonly literals: { readonly playerIds: readonly string[] };\n readonly setupProfilesById: Readonly<Record<string, unknown>>;\n };\n };\n readonly phases: Readonly<Record<string, unknown>>;\n};\n\ntype ScenarioDefinitionLike = {\n readonly id: string;\n readonly description?: string;\n readonly setup: {\n readonly players: number;\n readonly seed: number;\n readonly setupProfileId?: string | null;\n };\n readonly given: readonly unknown[];\n readonly when: readonly unknown[];\n readonly then: (...args: never[]) => unknown;\n};\n\nfunction fail(options: {\n readonly code: ScenarioDefinitionValidationCode;\n readonly path: string;\n readonly reason: string;\n}): never {\n throw new ScenarioDefinitionValidationError(options);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction requireObject(value: unknown, path: string): Record<string, unknown> {\n if (!isPlainObject(value)) {\n fail({ code: \"INVALID_TYPE\", path, reason: \"expected a plain object\" });\n }\n return value;\n}\n\nfunction assertExactKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n path: string,\n): void {\n const allowedSet = new Set(allowed);\n for (const key of Object.keys(value)) {\n if (!allowedSet.has(key)) {\n fail({\n code: \"UNKNOWN_FIELD\",\n path: appendScenarioPath(path, key),\n reason: \"field is not part of the scenario contract\",\n });\n }\n }\n}\n\nfunction assertOwn(\n value: Record<string, unknown>,\n key: string,\n path: string,\n): void {\n if (!Object.prototype.hasOwnProperty.call(value, key)) {\n fail({\n code: \"INVALID_TYPE\",\n path: appendScenarioPath(path, key),\n reason: \"required field is missing\",\n });\n }\n}\n\nfunction assertSafeInteger(value: unknown, path: string): number {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value)) {\n fail({\n code: \"UNSAFE_INTEGER\",\n path,\n reason: \"expected a finite safe integer\",\n });\n }\n return value;\n}\n\nfunction assertJsonSerializable(\n value: unknown,\n path: string,\n ancestors: Set<object> = new Set(),\n): void {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\"\n ) {\n return;\n }\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) {\n fail({\n code: \"NON_SERIALIZABLE\",\n path,\n reason: \"non-finite numbers are not JSON-serializable\",\n });\n }\n return;\n }\n if (typeof value !== \"object\") {\n fail({\n code: \"NON_SERIALIZABLE\",\n path,\n reason: `${typeof value} values are not JSON-serializable`,\n });\n }\n if (ancestors.has(value)) {\n fail({\n code: \"NON_SERIALIZABLE\",\n path,\n reason: \"cyclic values are not JSON-serializable\",\n });\n }\n\n if (!Array.isArray(value) && !isPlainObject(value)) {\n fail({\n code: \"NON_SERIALIZABLE\",\n path,\n reason: \"class instances are not JSON-serializable scenario data\",\n });\n }\n\n ancestors.add(value);\n if (Array.isArray(value)) {\n for (let index = 0; index < value.length; index += 1) {\n if (!Object.prototype.hasOwnProperty.call(value, index)) {\n fail({\n code: \"NON_SERIALIZABLE\",\n path: appendScenarioPath(path, index),\n reason: \"sparse array entries are not allowed\",\n });\n }\n assertJsonSerializable(\n value[index],\n appendScenarioPath(path, index),\n ancestors,\n );\n }\n const extraKeys = Reflect.ownKeys(value).filter((key) => {\n if (key === \"length\") return false;\n return typeof key !== \"string\" || !/^(0|[1-9][0-9]*)$/.test(key);\n });\n if (extraKeys.length > 0) {\n const key = extraKeys[0] as PropertyKey;\n fail({\n code: \"NON_SERIALIZABLE\",\n path: appendScenarioPath(path, key),\n reason: \"array metadata is not JSON-serializable\",\n });\n }\n ancestors.delete(value);\n return;\n }\n\n const descriptors = Object.getOwnPropertyDescriptors(value);\n for (const key of Reflect.ownKeys(value)) {\n if (typeof key === \"symbol\") {\n fail({\n code: \"NON_SERIALIZABLE\",\n path: appendScenarioPath(path, key),\n reason: \"symbol keys are not JSON-serializable\",\n });\n }\n const descriptor = descriptors[key];\n if (\n descriptor === undefined ||\n !descriptor.enumerable ||\n !(\"value\" in descriptor)\n ) {\n fail({\n code: \"NON_SERIALIZABLE\",\n path: appendScenarioPath(path, key),\n reason: \"only enumerable data properties are allowed\",\n });\n }\n assertJsonSerializable(\n descriptor.value,\n appendScenarioPath(path, key),\n ancestors,\n );\n }\n ancestors.delete(value);\n}\n\nfunction playerIdsForDefinition(\n game: ScenarioDefinitionGameLike,\n players: number,\n): readonly string[] {\n const declared = game.contract.manifest.literals.playerIds;\n return Array.from(\n { length: players },\n (_, index) => declared[index] ?? `player-${index + 1}`,\n );\n}\n\nfunction commandSchemas(\n game: ScenarioDefinitionGameLike,\n interactionId: string,\n): readonly z.ZodTypeAny[] {\n const schemasByPhase = createClientParamSchemasByPhase(\n game as Parameters<typeof createClientParamSchemasByPhase>[0],\n );\n return Object.values(schemasByPhase).flatMap((schemas) => {\n const schema = schemas[interactionId];\n return schema ? [schema as z.ZodTypeAny] : [];\n });\n}\n\nfunction issuePath(\n path: string,\n issue: { readonly path: PropertyKey[] },\n): string {\n return issue.path.reduce(appendScenarioPath, path);\n}\n\nfunction validateCommand(options: {\n readonly game: ScenarioDefinitionGameLike;\n readonly command: unknown;\n readonly path: string;\n readonly playerIds: readonly string[];\n}): void {\n const command = requireObject(options.command, options.path);\n assertJsonSerializable(command, options.path);\n assertExactKeys(command, [\"actor\", \"interactionId\", \"params\"], options.path);\n for (const field of [\"actor\", \"interactionId\", \"params\"] as const) {\n assertOwn(command, field, options.path);\n }\n\n const actorPath = appendScenarioPath(options.path, \"actor\");\n const actor = requireObject(command.actor, actorPath);\n assertExactKeys(actor, [\"seat\"], actorPath);\n assertOwn(actor, \"seat\", actorPath);\n const actorSeat = assertSafeInteger(\n actor.seat,\n appendScenarioPath(actorPath, \"seat\"),\n );\n if (actorSeat < 0 || actorSeat >= options.playerIds.length) {\n fail({\n code: \"OUT_OF_RANGE\",\n path: appendScenarioPath(actorPath, \"seat\"),\n reason: `expected a seat from 0 through ${Math.max(0, options.playerIds.length - 1)}`,\n });\n }\n\n const interactionPath = appendScenarioPath(options.path, \"interactionId\");\n if (\n typeof command.interactionId !== \"string\" ||\n command.interactionId === \"\"\n ) {\n fail({\n code: \"INVALID_TYPE\",\n path: interactionPath,\n reason: \"expected a non-empty string\",\n });\n }\n\n const paramsPath = appendScenarioPath(options.path, \"params\");\n const schemas = commandSchemas(options.game, command.interactionId);\n if (schemas.length === 0) {\n fail({\n code: \"UNKNOWN_INTERACTION\",\n path: interactionPath,\n reason: `interaction '${command.interactionId}' is not declared by the game`,\n });\n }\n\n let firstSeatError: ScenarioSchemaValueError | undefined;\n let firstIssue:\n | { readonly path: PropertyKey[]; readonly message: string }\n | undefined;\n for (const schema of schemas) {\n try {\n const resolved = resolveScenarioSeatReferences({\n schema,\n value: command.params,\n playerIds: options.playerIds,\n path: paramsPath,\n });\n const parsed = schema.safeParse(resolved);\n if (parsed.success) return;\n firstIssue ??= parsed.error.issues[0];\n } catch (error) {\n if (error instanceof ScenarioSchemaValueError) {\n firstSeatError ??= error;\n continue;\n }\n throw error;\n }\n }\n\n if (firstSeatError) {\n fail({\n code: firstSeatError.message.includes(\"seat from\")\n ? \"OUT_OF_RANGE\"\n : \"INVALID_COMMAND_PARAMS\",\n path: firstSeatError.path,\n reason: firstSeatError.message,\n });\n }\n fail({\n code: \"INVALID_COMMAND_PARAMS\",\n path: firstIssue ? issuePath(paramsPath, firstIssue) : paramsPath,\n reason:\n firstIssue?.message ?? \"parameters do not match the interaction contract\",\n });\n}\n\nexport function validateScenarioDefinition(\n game: ScenarioDefinitionGameLike,\n value: unknown,\n): asserts value is ScenarioDefinitionLike {\n const definition = requireObject(value, \"scenario\");\n assertExactKeys(\n definition,\n [\"id\", \"description\", \"setup\", \"given\", \"when\", \"then\"],\n \"scenario\",\n );\n for (const field of [\"id\", \"setup\", \"given\", \"when\", \"then\"] as const) {\n assertOwn(definition, field, \"scenario\");\n }\n if (typeof definition.id !== \"string\" || definition.id === \"\") {\n fail({\n code: \"INVALID_TYPE\",\n path: \"scenario.id\",\n reason: \"expected a non-empty string\",\n });\n }\n if (\n Object.prototype.hasOwnProperty.call(definition, \"description\") &&\n typeof definition.description !== \"string\"\n ) {\n fail({\n code: \"INVALID_TYPE\",\n path: \"scenario.description\",\n reason: \"expected a string when provided\",\n });\n }\n\n const setup = requireObject(definition.setup, \"scenario.setup\");\n assertExactKeys(\n setup,\n [\"players\", \"seed\", \"setupProfileId\"],\n \"scenario.setup\",\n );\n assertOwn(setup, \"players\", \"scenario.setup\");\n assertOwn(setup, \"seed\", \"scenario.setup\");\n const players = assertSafeInteger(setup.players, \"scenario.setup.players\");\n const normalSetup = game.contract.manifest.normalSetup;\n if (\n normalSetup === undefined ||\n !Number.isSafeInteger(normalSetup.minPlayers) ||\n !Number.isSafeInteger(normalSetup.maxPlayers) ||\n normalSetup.minPlayers <= 0 ||\n normalSetup.maxPlayers < normalSetup.minPlayers\n ) {\n fail({\n code: \"NORMAL_SETUP_UNAVAILABLE\",\n path: \"scenario.setup.players\",\n reason: \"the game manifest does not provide valid normal setup bounds\",\n });\n }\n if (players < normalSetup.minPlayers || players > normalSetup.maxPlayers) {\n fail({\n code: \"OUT_OF_RANGE\",\n path: \"scenario.setup.players\",\n reason: `expected ${normalSetup.minPlayers} through ${normalSetup.maxPlayers} players`,\n });\n }\n assertSafeInteger(setup.seed, \"scenario.setup.seed\");\n\n if (Object.prototype.hasOwnProperty.call(setup, \"setupProfileId\")) {\n if (\n setup.setupProfileId !== null &&\n typeof setup.setupProfileId !== \"string\"\n ) {\n fail({\n code: \"INVALID_TYPE\",\n path: \"scenario.setup.setupProfileId\",\n reason: \"expected a declared setup profile id or null\",\n });\n }\n if (\n typeof setup.setupProfileId === \"string\" &&\n !Object.prototype.hasOwnProperty.call(\n game.contract.manifest.setupProfilesById,\n setup.setupProfileId,\n )\n ) {\n fail({\n code: \"UNKNOWN_SETUP_PROFILE\",\n path: \"scenario.setup.setupProfileId\",\n reason: `setup profile '${setup.setupProfileId}' is not declared by the manifest`,\n });\n }\n }\n\n assertJsonSerializable(definition.id, \"scenario.id\");\n if (Object.prototype.hasOwnProperty.call(definition, \"description\")) {\n assertJsonSerializable(definition.description, \"scenario.description\");\n }\n assertJsonSerializable(setup, \"scenario.setup\");\n if (!Array.isArray(definition.given)) {\n fail({\n code: \"INVALID_TYPE\",\n path: \"scenario.given\",\n reason: \"expected an array\",\n });\n }\n if (!Array.isArray(definition.when)) {\n fail({\n code: \"INVALID_TYPE\",\n path: \"scenario.when\",\n reason: \"expected an array\",\n });\n }\n if (typeof definition.then !== \"function\") {\n fail({\n code: \"INVALID_TYPE\",\n path: \"scenario.then\",\n reason: \"expected an assertion function\",\n });\n }\n\n const playerIds = playerIdsForDefinition(game, players);\n definition.given.forEach((command, index) =>\n validateCommand({\n game,\n command,\n path: `scenario.given[${index}]`,\n playerIds,\n }),\n );\n definition.when.forEach((command, index) =>\n validateCommand({\n game,\n command,\n path: `scenario.when[${index}]`,\n playerIds,\n }),\n );\n}\n","import type { z } from \"zod\";\nimport type {\n ClientParamsOfInteractionOfDefinition,\n GameStateOf,\n InteractionIdOfDefinitionPhase,\n InteractionSpecByNameOfDefinitionPhase,\n PhaseNamesOfDefinition,\n ViewNamesOfDefinition,\n ViewOfDefinition,\n} from \"../reducer/model/definition.js\";\nimport type { ManifestIdSchema } from \"../reducer/model/manifest.js\";\nimport type {\n DispatchTraceSummaryEntry,\n ReducerDiagnosticEvent,\n} from \"../reducer/diagnostics.js\";\nimport {\n validateScenarioDefinition,\n type ScenarioDefinitionGameLike,\n} from \"./scenario-definition-validation.js\";\n\nexport {\n ScenarioDefinitionValidationError,\n type ScenarioDefinitionValidationCode,\n} from \"./scenario-definition-validation.js\";\n\nexport type InteractionDescriptorLike = {\n interactionId?: string;\n surface?: string;\n kind?: string;\n availability?: InteractionAvailabilityLike;\n context?: {\n to?: string;\n };\n} & Record<string, unknown>;\n\nexport type InteractionAvailabilityLike =\n | { status: \"available\" }\n | { status: \"notYourTurn\"; reason: string }\n | {\n status: \"insufficientResources\";\n reason: string;\n missingResources?: Record<string, unknown>;\n }\n | { status: \"blocked\"; reason: string; code?: string };\n\nexport type InteractionExplanationLike = {\n interactionId: string;\n phase: string;\n step: string | null;\n availability:\n | \"available\"\n | \"notYourTurn\"\n | \"wrongPhase\"\n | \"wrongStep\"\n | \"blocked\";\n rules: ReadonlyArray<{\n ruleId: string;\n outcome: \"passed\" | \"failed\" | \"notEvaluated\";\n errorCode?: string;\n message?: string;\n }>;\n actor: { required: readonly string[]; playerIsActor: boolean };\n inputs: ReadonlyArray<{\n key: string;\n kind: string;\n eligibleCount: number | \"lazy\";\n }>;\n};\n\nexport type SnapshotMatcherHandler = (\n name: string | undefined,\n actual: unknown,\n) => void;\n\nexport type RejectionExpectation = {\n errorCode?: string;\n message?: string | RegExp;\n};\n\nexport type ExpectMatchers = {\n toBe: (expected: unknown) => void;\n toEqual: (expected: unknown) => void;\n toMatchObject: (expected: Record<string, unknown>) => void;\n toBeDefined: () => void;\n toBeUndefined: () => void;\n toBeNull: () => void;\n toContain: (expected: unknown) => void;\n toContainEqual: (expected: unknown) => void;\n toHaveLength: (expected: number) => void;\n toBeGreaterThan: (expected: number) => void;\n toBeGreaterThanOrEqual: (expected: number) => void;\n toThrow: (predicate?: string | RegExp | ((error: Error) => boolean)) => void;\n toMatchSnapshot: (filename?: string) => void;\n toRejectWith: (expected: RejectionExpectation) => Promise<void>;\n toHaveInteraction: (\n interactionId: string,\n opts?: Partial<InteractionDescriptorLike>,\n ) => void;\n toBeGatedBy: (reason: string, opts?: { interactionId?: string }) => void;\n toBeAvailable: (explanation?: InteractionExplanationLike) => void;\n toBeActiveFor: (playerId: string, opts?: { interactionId?: string }) => void;\n not: {\n toHaveInteraction: (interactionId: string) => void;\n };\n};\n\nexport type ExpectFn = (actual: unknown) => ExpectMatchers;\n\nexport type ScenarioSeatRef = {\n readonly seat: number;\n};\n\nexport type ScenarioActor = ScenarioSeatRef;\n\nexport type ScenarioSetup = {\n readonly players: number;\n readonly seed: number;\n readonly setupProfileId?: string | null;\n};\n\ntype ScenarioTupleOutput<\n Items extends readonly z.core.SomeType[],\n Rest extends z.core.SomeType | null,\n> = Rest extends z.core.SomeType\n ? readonly [\n ...{ [Index in keyof Items]: ScenarioSchemaOutput<Items[Index]> },\n ...ScenarioSchemaOutput<Rest>[],\n ]\n : readonly [\n ...{ [Index in keyof Items]: ScenarioSchemaOutput<Items[Index]> },\n ];\n\ntype OptionalScenarioObjectKeys<Shape extends z.core.$ZodShape> = {\n [Key in keyof Shape]: undefined extends z.output<Shape[Key]> ? Key : never;\n}[keyof Shape];\n\ntype ScenarioObjectOutput<Shape extends z.core.$ZodShape> = {\n readonly [Key in Exclude<\n keyof Shape,\n OptionalScenarioObjectKeys<Shape>\n >]: ScenarioSchemaOutput<Shape[Key]>;\n} & {\n readonly [Key in OptionalScenarioObjectKeys<Shape>]?: ScenarioSchemaOutput<\n Shape[Key]\n >;\n};\n\n/**\n * Authoring projection of an input schema. Only semantic player-id leaves are\n * replaced; ordinary strings retain their original type.\n */\nexport type ScenarioSchemaOutput<Schema extends z.core.SomeType> =\n Schema extends ManifestIdSchema<unknown, \"playerId\">\n ? ScenarioSeatRef\n : Schema extends z.ZodOptional<infer Inner>\n ? ScenarioSchemaOutput<Inner> | undefined\n : Schema extends z.ZodExactOptional<infer Inner>\n ? ScenarioSchemaOutput<Inner> | undefined\n : Schema extends z.ZodNullable<infer Inner>\n ? ScenarioSchemaOutput<Inner> | null\n : Schema extends z.ZodDefault<infer Inner>\n ? ScenarioSchemaOutput<Inner>\n : Schema extends z.ZodPrefault<infer Inner>\n ? ScenarioSchemaOutput<Inner>\n : Schema extends z.ZodCatch<infer Inner>\n ? ScenarioSchemaOutput<Inner>\n : Schema extends z.ZodReadonly<infer Inner>\n ? Readonly<ScenarioSchemaOutput<Inner>>\n : Schema extends z.ZodNonOptional<infer Inner>\n ? Exclude<ScenarioSchemaOutput<Inner>, undefined>\n : Schema extends z.ZodArray<infer Element>\n ? readonly ScenarioSchemaOutput<Element>[]\n : Schema extends z.ZodTuple<infer Items, infer Rest>\n ? ScenarioTupleOutput<Items, Rest>\n : Schema extends z.ZodObject<infer Shape>\n ? ScenarioObjectOutput<Shape>\n : Schema extends z.ZodRecord<infer Key, infer Value>\n ? Key extends ManifestIdSchema<unknown, \"playerId\">\n ? never\n : Readonly<\n Record<\n Extract<\n z.output<Key>,\n string | number | symbol\n >,\n ScenarioSchemaOutput<Value>\n >\n >\n : Schema extends z.ZodIntersection<\n infer Left,\n infer Right\n >\n ? ScenarioSchemaOutput<Left> &\n ScenarioSchemaOutput<Right>\n : Schema extends z.ZodPipe<infer Input, z.ZodType>\n ? ScenarioSchemaOutput<Input>\n : Schema extends z.ZodLazy<infer Inner>\n ? ScenarioSchemaOutput<Inner>\n : Schema extends z.ZodUnion<infer Options>\n ? ScenarioSchemaOutput<Options[number]>\n : z.output<Schema>;\n\ntype InputCollectorsOfInteraction<Interaction> = Interaction extends {\n readonly inputs?: infer Collectors;\n}\n ? NonNullable<Collectors> extends Readonly<Record<string, unknown>>\n ? NonNullable<Collectors>\n : Record<string, never>\n : Record<string, never>;\n\ntype ScenarioParamsOfCollectors<\n Collectors extends Readonly<Record<string, unknown>>,\n> = {\n readonly [Key in keyof Collectors as Collectors[Key] extends {\n readonly kind: \"rng\";\n }\n ? never\n : Key]: Collectors[Key] extends {\n readonly schema: infer Schema extends z.core.SomeType;\n }\n ? ScenarioSchemaOutput<Schema>\n : never;\n};\n\ntype ScenarioParamsOfInteraction<Interaction> = Interaction extends {\n readonly cardType: unknown;\n readonly playFrom: unknown;\n}\n ? { readonly cardId: string } & ScenarioParamsOfCollectors<\n InputCollectorsOfInteraction<Interaction>\n >\n : ScenarioParamsOfCollectors<InputCollectorsOfInteraction<Interaction>>;\n\nexport type ScenarioCommand<\n InteractionId extends string = string,\n Params = Record<string, unknown>,\n> = {\n readonly actor: ScenarioActor;\n readonly interactionId: InteractionId;\n readonly params: Params;\n};\n\ntype ScenarioCommandForPhase<\n Game,\n Phase extends PhaseNamesOfDefinition<Game>,\n> = {\n [InteractionId in InteractionIdOfDefinitionPhase<\n Game,\n Phase\n >]: ScenarioCommand<\n InteractionId,\n ScenarioParamsOfInteraction<\n InteractionSpecByNameOfDefinitionPhase<Game, Phase, InteractionId>\n >\n >;\n}[InteractionIdOfDefinitionPhase<Game, Phase>];\n\nexport type ScenarioCommandOf<Game> = {\n [Phase in PhaseNamesOfDefinition<Game>]: ScenarioCommandForPhase<Game, Phase>;\n}[PhaseNamesOfDefinition<Game>];\n\n/** Production params remain available for runtime implementors and diagnostics. */\nexport type RuntimeParamsOfScenarioCommand<\n Game,\n Phase extends PhaseNamesOfDefinition<Game>,\n InteractionId extends InteractionIdOfDefinitionPhase<Game, Phase>,\n> = ClientParamsOfInteractionOfDefinition<Game, Phase, InteractionId>;\n\nexport type ScenarioReplayDefinition<Game> = {\n readonly id: string;\n readonly description?: string;\n readonly setup: ScenarioSetup;\n readonly given: readonly ScenarioCommandOf<Game>[];\n readonly when: readonly ScenarioCommandOf<Game>[];\n};\n\ntype DeepReadonly<Value> = Value extends (...args: never[]) => unknown\n ? Value\n : Value extends readonly (infer Item)[]\n ? readonly DeepReadonly<Item>[]\n : Value extends object\n ? { readonly [Key in keyof Value]: DeepReadonly<Value[Key]> }\n : Value;\n\ntype ScenarioPlayerView<Game> =\n Extract<\"player\", ViewNamesOfDefinition<Game>> extends infer ViewName\n ? ViewName extends ViewNamesOfDefinition<Game>\n ? ViewOfDefinition<Game, ViewName>\n : unknown\n : unknown;\n\nexport type ScenarioFlowDiagnostics = {\n readonly currentPhase: string | null;\n readonly currentStage: string | null;\n readonly activeSeats: readonly ScenarioSeatRef[];\n};\n\nexport type ScenarioDiagnostics = {\n readonly events: readonly ReducerDiagnosticEvent[];\n readonly lastDispatch: {\n readonly submissionId: string;\n readonly trace: readonly DispatchTraceSummaryEntry[];\n } | null;\n readonly flow: ScenarioFlowDiagnostics;\n};\n\nexport type ScenarioProbeAccepted<Game> = {\n readonly kind: \"accepted\";\n readonly command: ScenarioCommandOf<Game>;\n readonly checkpointDigest: string;\n readonly trace: readonly DispatchTraceSummaryEntry[];\n toBeAccepted(): void;\n toRejectWith(expected: RejectionExpectation): never;\n};\n\nexport type ScenarioProbeRejected<Game> = {\n readonly kind: \"rejected\";\n readonly command: ScenarioCommandOf<Game>;\n readonly errorCode: string;\n readonly message?: string;\n readonly trace: readonly DispatchTraceSummaryEntry[];\n toBeAccepted(): never;\n toRejectWith(expected: RejectionExpectation): void;\n};\n\nexport type ScenarioProbeResult<Game> =\n | ScenarioProbeAccepted<Game>\n | ScenarioProbeRejected<Game>;\n\nexport type ScenarioAssertionContext<Game> = {\n readonly expect: ExpectFn;\n state(): DeepReadonly<GameStateOf<Game>>;\n view(seat: ScenarioSeatRef): DeepReadonly<ScenarioPlayerView<Game>>;\n interactions(seat: ScenarioSeatRef): readonly InteractionDescriptorLike[];\n explain(\n seat: ScenarioSeatRef,\n interactionId: string,\n ): InteractionExplanationLike;\n readonly diagnostics: ScenarioDiagnostics;\n probe(command: ScenarioCommandOf<Game>): Promise<ScenarioProbeResult<Game>>;\n};\n\nexport type ScenarioDefinition<Game> = ScenarioReplayDefinition<Game> & {\n readonly then: (\n context: ScenarioAssertionContext<Game>,\n ) => void | Promise<void>;\n};\n\nexport type ScenarioCheckpoint =\n | { readonly segment: \"setup\"; readonly completed: 0 }\n | { readonly segment: \"given\"; readonly completed: number }\n | { readonly segment: \"when\"; readonly completed: number };\n\nexport type ScenarioReplaySegment = \"given\" | \"when\";\n\nexport type ScenarioCommandTraceEntry<Game> = {\n readonly segment: ScenarioReplaySegment;\n readonly index: number;\n readonly command: ScenarioCommandOf<Game>;\n readonly trace: readonly DispatchTraceSummaryEntry[];\n};\n\nexport type ScenarioReplay<Game> = {\n readonly scenarioId: string;\n readonly checkpoint: ScenarioCheckpoint;\n readonly checkpointDigest: string;\n readonly complete: boolean;\n readonly trace: readonly ScenarioCommandTraceEntry<Game>[];\n state(): DeepReadonly<GameStateOf<Game>>;\n view(seat: ScenarioSeatRef): DeepReadonly<ScenarioPlayerView<Game>>;\n interactions(seat: ScenarioSeatRef): readonly InteractionDescriptorLike[];\n explain(\n seat: ScenarioSeatRef,\n interactionId: string,\n ): InteractionExplanationLike;\n readonly diagnostics: ScenarioDiagnostics;\n clone(): ScenarioReplay<Game>;\n};\n\nexport type ReplayScenarioOptions<Game> = {\n readonly game: Game;\n readonly scenario: ScenarioReplayDefinition<Game>;\n readonly at?: ScenarioCheckpoint;\n};\n\nexport type AssertScenarioOptions<Game> = {\n readonly replay: ScenarioReplay<Game>;\n readonly assertion: ScenarioDefinition<Game>[\"then\"];\n};\n\nexport type ScenarioReplayErrorOptions = {\n readonly scenarioId: string;\n readonly segment: ScenarioReplaySegment;\n readonly index: number;\n readonly interactionId: string;\n readonly errorCode: string;\n readonly reducerMessage?: string;\n readonly trace?: readonly DispatchTraceSummaryEntry[];\n};\n\nexport class ScenarioReplayError extends Error {\n readonly scenarioId: string;\n readonly segment: ScenarioReplaySegment;\n readonly index: number;\n readonly interactionId: string;\n readonly errorCode: string;\n readonly reducerMessage?: string;\n readonly trace: readonly DispatchTraceSummaryEntry[];\n\n constructor(options: ScenarioReplayErrorOptions) {\n super(\n `Scenario '${options.scenarioId}' rejected ${options.segment}[${options.index}] ` +\n `interaction '${options.interactionId}' with ${options.errorCode}` +\n (options.reducerMessage ? `: ${options.reducerMessage}` : \".\"),\n );\n this.name = \"ScenarioReplayError\";\n this.scenarioId = options.scenarioId;\n this.segment = options.segment;\n this.index = options.index;\n this.interactionId = options.interactionId;\n this.errorCode = options.errorCode;\n this.reducerMessage = options.reducerMessage;\n this.trace = options.trace ?? [];\n }\n}\n\ntype NoExtraScenarioFields<Actual, Expected> = Record<\n Exclude<keyof Actual, keyof Expected>,\n never\n>;\n\nexport type ScenarioAuthoring<Game> = {\n defineScenario<const Definition extends ScenarioDefinition<Game>>(\n definition: Definition &\n NoExtraScenarioFields<Definition, ScenarioDefinition<Game>>,\n ): Definition;\n};\n\nexport function createScenarioAuthoring<\n const Game extends ScenarioDefinitionGameLike,\n>(game: Game): ScenarioAuthoring<Game> {\n return {\n defineScenario<const Definition extends ScenarioDefinition<Game>>(\n definition: Definition &\n NoExtraScenarioFields<Definition, ScenarioDefinition<Game>>,\n ): Definition {\n validateScenarioDefinition(game, definition);\n return definition;\n },\n };\n}\n\n/** Select and clone the only serializable portion of a loaded scenario. */\nexport function toScenarioReplayDefinition<Game>(\n definition: ScenarioDefinition<Game>,\n): ScenarioReplayDefinition<Game> {\n const replay = {\n id: definition.id,\n ...(definition.description === undefined\n ? {}\n : { description: definition.description }),\n setup: definition.setup,\n given: definition.given,\n when: definition.when,\n } satisfies ScenarioReplayDefinition<Game>;\n return structuredClone(replay);\n}\n","export const SCENARIO_ASSERTION_ERROR_CODE =\n \"SCENARIO_ASSERTION_FAILED\" as const;\n\n/** A failed SDK matcher or probe expectation authored in `scenario.then`. */\nexport class ScenarioAssertionError extends Error {\n readonly code = SCENARIO_ASSERTION_ERROR_CODE;\n\n constructor(message: string) {\n super(message);\n this.name = \"ScenarioAssertionError\";\n }\n}\n\nexport function scenarioAssertionFailure(message: string): never {\n throw new ScenarioAssertionError(message);\n}\n","import type {\n ExpectFn,\n ExpectMatchers,\n InteractionDescriptorLike,\n RejectionExpectation,\n InteractionExplanationLike,\n SnapshotMatcherHandler,\n} from \"./definitions.js\";\nimport type { ReducerDiagnosticEvent } from \"../reducer/diagnostics.js\";\nimport { scenarioAssertionFailure } from \"./scenario-assertion-error.js\";\n\ntype CreateExpectApiOptions = {\n matchSnapshot?: SnapshotMatcherHandler;\n lastDiagnosticRejection?: () =>\n | Extract<ReducerDiagnosticEvent, { type: \"submitRejected\" }>\n | null\n | undefined;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isDeepStrictEqual(actual: unknown, expected: unknown): boolean {\n if (Object.is(actual, expected)) return true;\n if (typeof actual !== typeof expected) return false;\n if (actual === null || expected === null) return false;\n if (typeof actual !== \"object\" || typeof expected !== \"object\") return false;\n\n if (actual instanceof Date || expected instanceof Date) {\n return (\n actual instanceof Date &&\n expected instanceof Date &&\n Object.is(actual.getTime(), expected.getTime())\n );\n }\n if (actual instanceof RegExp || expected instanceof RegExp) {\n return (\n actual instanceof RegExp &&\n expected instanceof RegExp &&\n actual.source === expected.source &&\n actual.flags === expected.flags\n );\n }\n if (Array.isArray(actual) || Array.isArray(expected)) {\n return (\n Array.isArray(actual) &&\n Array.isArray(expected) &&\n actual.length === expected.length &&\n actual.every((value, index) => isDeepStrictEqual(value, expected[index]))\n );\n }\n\n const actualPrototype = Object.getPrototypeOf(actual);\n const expectedPrototype = Object.getPrototypeOf(expected);\n if (actualPrototype !== expectedPrototype) return false;\n\n const actualRecord = actual as Record<string, unknown>;\n const expectedRecord = expected as Record<string, unknown>;\n const actualKeys = Object.keys(actualRecord);\n const expectedKeys = Object.keys(expectedRecord);\n return (\n actualKeys.length === expectedKeys.length &&\n actualKeys.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(expectedRecord, key) &&\n isDeepStrictEqual(actualRecord[key], expectedRecord[key]),\n )\n );\n}\n\nfunction matchPartial(\n actual: unknown,\n expected: unknown,\n path: string = \"value\",\n): string | null {\n if (!isRecord(expected)) {\n return isDeepStrictEqual(actual, expected)\n ? null\n : `${path} does not match`;\n }\n if (!isRecord(actual)) {\n return `${path} is not an object`;\n }\n for (const [key, expectedValue] of Object.entries(expected)) {\n const actualValue = actual[key];\n if (!(key in actual)) {\n return `${path}.${key} is missing`;\n }\n const mismatch = matchPartial(actualValue, expectedValue, `${path}.${key}`);\n if (mismatch) {\n return mismatch;\n }\n }\n return null;\n}\n\nfunction asDescriptorList(actual: unknown): InteractionDescriptorLike[] {\n if (!Array.isArray(actual)) {\n scenarioAssertionFailure(\"Expected interaction descriptor array.\");\n }\n return actual as InteractionDescriptorLike[];\n}\n\nfunction findInteraction(\n descriptors: readonly InteractionDescriptorLike[],\n interactionId: string,\n): InteractionDescriptorLike | null {\n return (\n descriptors.find(\n (descriptor) => descriptor.interactionId === interactionId,\n ) ?? null\n );\n}\n\nfunction assertDescriptorMatches(\n descriptor: InteractionDescriptorLike,\n opts: Partial<InteractionDescriptorLike> | undefined,\n): void {\n if (!opts) {\n return;\n }\n const mismatch = matchPartial(descriptor, opts, \"interaction\");\n if (mismatch) {\n scenarioAssertionFailure(mismatch);\n }\n}\n\nfunction createSubmissionErrorMatcher(\n actual: unknown,\n expected: RejectionExpectation,\n options: CreateExpectApiOptions,\n): Promise<void> {\n if (\n isRecord(actual) &&\n (actual.kind === \"accepted\" || actual.kind === \"rejected\")\n ) {\n if (actual.kind === \"accepted\") {\n scenarioAssertionFailure(\n \"Expected probe command to reject, but it was accepted.\",\n );\n }\n const errorCode =\n typeof actual.errorCode === \"string\" ? actual.errorCode : undefined;\n const message = typeof actual.message === \"string\" ? actual.message : \"\";\n if (expected.errorCode !== undefined && errorCode !== expected.errorCode) {\n scenarioAssertionFailure(\n `Expected rejection errorCode '${expected.errorCode}', received '${errorCode ?? \"undefined\"}'.`,\n );\n }\n if (typeof expected.message === \"string\" && message !== expected.message) {\n scenarioAssertionFailure(\n `Expected rejection message '${expected.message}', received '${message}'.`,\n );\n }\n if (expected.message instanceof RegExp && !expected.message.test(message)) {\n scenarioAssertionFailure(\n `Expected rejection message '${message}' to match ${String(expected.message)}.`,\n );\n }\n return Promise.resolve();\n }\n\n const resolvePromise = (): Promise<unknown> => {\n if (typeof actual === \"function\") {\n return Promise.resolve().then(() => (actual as () => unknown)());\n }\n return Promise.resolve(actual);\n };\n\n return resolvePromise().then(\n () => scenarioAssertionFailure(\"Expected promise to reject.\"),\n (error: unknown) => {\n if (!(error instanceof Error)) {\n scenarioAssertionFailure(\"Expected rejection to be an Error.\");\n }\n if (\n expected.errorCode !== undefined &&\n (error as Error & { errorCode?: string }).errorCode !==\n expected.errorCode\n ) {\n scenarioAssertionFailure(\n `Expected rejection errorCode '${expected.errorCode}', received '${\n (error as Error & { errorCode?: string }).errorCode ?? \"undefined\"\n }'.${formatLastDiagnosticRejection(options)}`,\n );\n }\n if (\n typeof expected.message === \"string\" &&\n error.message !== expected.message\n ) {\n scenarioAssertionFailure(\n `Expected rejection message '${expected.message}', received '${error.message}'.${formatLastDiagnosticRejection(\n options,\n )}`,\n );\n }\n if (\n expected.message instanceof RegExp &&\n !expected.message.test(error.message)\n ) {\n scenarioAssertionFailure(\n `Expected rejection message '${error.message}' to match ${String(\n expected.message,\n )}.${formatLastDiagnosticRejection(options)}`,\n );\n }\n },\n );\n}\n\nfunction formatLastDiagnosticRejection(\n options: CreateExpectApiOptions,\n): string {\n const rejection = options.lastDiagnosticRejection?.();\n if (!rejection) return \"\";\n const rule = rejection.ruleId ? ` ruleId=${rejection.ruleId}` : \"\";\n const message = rejection.message ? ` message=${rejection.message}` : \"\";\n return `\\nlast rejection: errorCode=${rejection.errorCode}${rule}${message}`;\n}\n\nfunction assertLength(actual: unknown, expected: number): void {\n if (\n actual === null ||\n actual === undefined ||\n typeof (actual as { length?: unknown }).length !== \"number\"\n ) {\n scenarioAssertionFailure(\n \"toHaveLength expects a value with a numeric length.\",\n );\n }\n const length = (actual as { length: number }).length;\n if (length !== expected) {\n scenarioAssertionFailure(\n `Expected length ${expected}, received ${length}.`,\n );\n }\n}\n\nfunction formatInteractionExplanation(\n explanation: InteractionExplanationLike | undefined,\n): string {\n if (!explanation) {\n return \"\";\n }\n const lines = [\n `availability: ${explanation.availability}`,\n ...explanation.rules.map((rule) => {\n const code = rule.errorCode ? ` (${rule.errorCode})` : \"\";\n const message = rule.message ? `: ${rule.message}` : \"\";\n return `rule ${rule.ruleId} ${rule.outcome}${code}${message}`;\n }),\n ...explanation.inputs.map(\n (input) => `input ${input.key} eligibleCount=${input.eligibleCount}`,\n ),\n ];\n return `\\n${lines.join(\"\\n\")}`;\n}\n\nfunction assertThrown(\n actual: unknown,\n predicate?: string | RegExp | ((error: Error) => boolean),\n): void {\n if (typeof actual !== \"function\") {\n scenarioAssertionFailure(\"toThrow expects a function.\");\n }\n try {\n (actual as () => unknown)();\n } catch (error) {\n if (!(error instanceof Error)) {\n scenarioAssertionFailure(\"Thrown value is not an Error.\");\n }\n if (predicate === undefined) {\n return;\n }\n if (typeof predicate === \"string\" && error.message !== predicate) {\n scenarioAssertionFailure(\n `Expected thrown message '${predicate}', received '${error.message}'.`,\n );\n }\n if (predicate instanceof RegExp && !predicate.test(error.message)) {\n scenarioAssertionFailure(\n `Expected thrown message '${error.message}' to match ${String(predicate)}.`,\n );\n }\n if (typeof predicate === \"function\" && !predicate(error)) {\n scenarioAssertionFailure(\"Thrown error did not satisfy predicate.\");\n }\n return;\n }\n scenarioAssertionFailure(\"Expected function to throw.\");\n}\n\nexport function createExpectApi(\n options: CreateExpectApiOptions = {},\n): ExpectFn {\n const buildMatchers = (actual: unknown): ExpectMatchers => ({\n toBe: (expected: unknown) => {\n if (actual !== expected) {\n scenarioAssertionFailure(\n `Expected '${String(actual)}' to be '${String(expected)}'.`,\n );\n }\n },\n toEqual: (expected: unknown) => {\n if (!isDeepStrictEqual(actual, expected)) {\n scenarioAssertionFailure(\"Expected values to be deeply equal.\");\n }\n },\n toMatchObject: (expected: Record<string, unknown>) => {\n const mismatch = matchPartial(actual, expected);\n if (mismatch) {\n scenarioAssertionFailure(mismatch);\n }\n },\n toBeDefined: () => {\n if (actual === undefined) {\n scenarioAssertionFailure(\"Expected value to be defined.\");\n }\n },\n toBeUndefined: () => {\n if (actual !== undefined) {\n scenarioAssertionFailure(\n `Expected value to be undefined, but received '${String(actual)}'.`,\n );\n }\n },\n toBeNull: () => {\n if (actual !== null) {\n scenarioAssertionFailure(\n `Expected value to be null, but received '${String(actual)}'.`,\n );\n }\n },\n toContain: (expected: unknown) => {\n if (Array.isArray(actual)) {\n if (!actual.includes(expected)) {\n scenarioAssertionFailure(\"Expected array to contain value.\");\n }\n return;\n }\n if (typeof actual === \"string\") {\n if (!actual.includes(String(expected))) {\n scenarioAssertionFailure(\"Expected string to contain value.\");\n }\n return;\n }\n scenarioAssertionFailure(\n \"toContain expects an array or string actual value.\",\n );\n },\n toContainEqual: (expected: unknown) => {\n if (!Array.isArray(actual)) {\n scenarioAssertionFailure(\n \"toContainEqual expects an array actual value.\",\n );\n }\n if (!actual.some((value) => isDeepStrictEqual(value, expected))) {\n scenarioAssertionFailure(\"Expected array to contain an equal value.\");\n }\n },\n toHaveLength: (expected: number) => {\n assertLength(actual, expected);\n },\n toBeGreaterThan: (expected: number) => {\n if (typeof actual !== \"number\") {\n scenarioAssertionFailure(\n \"toBeGreaterThan expects a number actual value.\",\n );\n }\n if (actual <= expected) {\n scenarioAssertionFailure(`Expected ${actual} to be > ${expected}.`);\n }\n },\n toBeGreaterThanOrEqual: (expected: number) => {\n if (typeof actual !== \"number\") {\n scenarioAssertionFailure(\n \"toBeGreaterThanOrEqual expects a number actual value.\",\n );\n }\n if (actual < expected) {\n scenarioAssertionFailure(`Expected ${actual} to be >= ${expected}.`);\n }\n },\n toThrow: (predicate) => {\n assertThrown(actual, predicate);\n },\n toMatchSnapshot: (filename) => {\n if (!options.matchSnapshot) {\n scenarioAssertionFailure(\n \"Snapshot matching is not configured for this expect API.\",\n );\n }\n options.matchSnapshot(filename, actual);\n },\n toRejectWith: (expected) =>\n createSubmissionErrorMatcher(actual, expected, options),\n toHaveInteraction: (interactionId, opts) => {\n const descriptors = asDescriptorList(actual);\n const descriptor = findInteraction(descriptors, interactionId);\n if (!descriptor) {\n scenarioAssertionFailure(\n `Expected interaction '${interactionId}' to exist.`,\n );\n }\n assertDescriptorMatches(descriptor, opts);\n },\n toBeGatedBy: (reason, opts) => {\n const descriptor = Array.isArray(actual)\n ? (() => {\n if (!opts?.interactionId) {\n scenarioAssertionFailure(\n \"toBeGatedBy on a descriptor array requires opts.interactionId.\",\n );\n }\n return findInteraction(\n asDescriptorList(actual),\n opts.interactionId,\n );\n })()\n : (actual as InteractionDescriptorLike | null);\n if (!descriptor) {\n scenarioAssertionFailure(\"Expected interaction descriptor to exist.\");\n }\n if (descriptor.availability?.status === \"available\") {\n scenarioAssertionFailure(\"Expected interaction to be unavailable.\");\n }\n const actualReason =\n descriptor.availability?.status === \"notYourTurn\" ||\n descriptor.availability?.status === \"insufficientResources\" ||\n descriptor.availability?.status === \"blocked\"\n ? descriptor.availability.reason\n : undefined;\n if (actualReason !== reason) {\n scenarioAssertionFailure(\n `Expected unavailable reason '${reason}', received '${\n actualReason ?? \"undefined\"\n }'.`,\n );\n }\n },\n toBeAvailable: (explanation) => {\n const descriptor = Array.isArray(actual)\n ? (() => {\n if (!explanation?.interactionId) {\n scenarioAssertionFailure(\n \"toBeAvailable on a descriptor array requires an explanation.\",\n );\n }\n return findInteraction(\n asDescriptorList(actual),\n explanation.interactionId,\n );\n })()\n : (actual as InteractionDescriptorLike | null);\n if (!descriptor) {\n scenarioAssertionFailure(\n `Expected interaction descriptor to exist.${formatInteractionExplanation(\n explanation,\n )}`,\n );\n }\n if (descriptor.availability?.status !== \"available\") {\n scenarioAssertionFailure(\n `Expected interaction '${descriptor.interactionId ?? \"unknown\"}' to be available.${formatInteractionExplanation(\n explanation,\n )}`,\n );\n }\n },\n toBeActiveFor: (playerId, opts) => {\n const descriptor = Array.isArray(actual)\n ? (() => {\n if (!opts?.interactionId) {\n scenarioAssertionFailure(\n \"toBeActiveFor on a descriptor array requires opts.interactionId.\",\n );\n }\n return findInteraction(\n asDescriptorList(actual),\n opts.interactionId,\n );\n })()\n : (actual as InteractionDescriptorLike | null);\n if (!descriptor) {\n scenarioAssertionFailure(\"Expected interaction descriptor to exist.\");\n }\n if (descriptor.context?.to !== playerId) {\n scenarioAssertionFailure(\n `Expected interaction to target '${playerId}', received '${\n descriptor.context?.to ?? \"undefined\"\n }'.`,\n );\n }\n if (descriptor.availability?.status !== \"available\") {\n scenarioAssertionFailure(\"Expected interaction to be available.\");\n }\n },\n not: {\n toHaveInteraction: (interactionId) => {\n const descriptors = asDescriptorList(actual);\n if (findInteraction(descriptors, interactionId)) {\n scenarioAssertionFailure(\n `Expected interaction '${interactionId}' to be absent.`,\n );\n }\n },\n },\n });\n\n return (actual: unknown) => buildMatchers(actual);\n}\n","import type { z } from \"zod\";\nimport { createClientParamSchemasByPhase } from \"../reducer/client-param-schemas.js\";\nimport type { ScenarioSeatRef } from \"./definitions.js\";\nimport {\n projectScenarioSeatReferences,\n resolveScenarioSeatReferences,\n ScenarioSchemaValueError,\n} from \"./scenario-schema.js\";\n\ntype GameLike = {\n readonly phases: Readonly<Record<string, unknown>>;\n};\n\nexport class ScenarioCommandParamsError extends Error {\n readonly path: string;\n\n constructor(path: string, message: string) {\n super(`${path}: ${message}`);\n this.name = \"ScenarioCommandParamsError\";\n this.path = path;\n }\n}\n\nexport function isScenarioSeatRef(value: unknown): value is ScenarioSeatRef {\n if (!isPlainRecord(value)) return false;\n const keys = Object.keys(value);\n return (\n keys.length === 1 &&\n keys[0] === \"seat\" &&\n Number.isSafeInteger(value.seat) &&\n (value.seat as number) >= 0\n );\n}\n\nexport function resolveScenarioSeatRef(options: {\n readonly ref: ScenarioSeatRef;\n readonly playerIds: readonly string[];\n readonly path: string;\n}): string {\n if (!isScenarioSeatRef(options.ref)) {\n throw new ScenarioCommandParamsError(\n options.path,\n \"expected a scenario seat reference\",\n );\n }\n const playerId = options.playerIds[options.ref.seat];\n if (playerId === undefined) {\n throw new ScenarioCommandParamsError(\n `${options.path}.seat`,\n `seat ${options.ref.seat} is out of range for ${options.playerIds.length} player(s)`,\n );\n }\n return playerId;\n}\n\nexport function resolveScenarioCommandParams(options: {\n readonly game: GameLike;\n readonly phase: string;\n readonly interactionId: string;\n readonly params: unknown;\n readonly playerIds: readonly string[];\n readonly path: string;\n}): Record<string, unknown> {\n const candidateSchemas = clientParamSchemaCandidates(options);\n let firstSeatError: ScenarioSchemaValueError | undefined;\n let firstIssue:\n | { readonly path: PropertyKey[]; readonly message: string }\n | undefined;\n for (const schema of candidateSchemas) {\n try {\n const resolved = resolveScenarioSeatReferences({\n schema,\n value: options.params,\n playerIds: options.playerIds,\n path: `${options.path}.params`,\n });\n const parsed = schema.safeParse(resolved);\n if (parsed.success) {\n return parsed.data as Record<string, unknown>;\n }\n firstIssue ??= parsed.error.issues[0];\n } catch (error) {\n if (error instanceof ScenarioSchemaValueError) {\n firstSeatError ??= error;\n continue;\n }\n throw error;\n }\n }\n\n if (firstSeatError) {\n throw new ScenarioCommandParamsError(\n firstSeatError.path,\n firstSeatError.message,\n );\n }\n const suffix =\n firstIssue?.path\n .map((part) =>\n typeof part === \"number\" ? `[${part}]` : `.${String(part)}`,\n )\n .join(\"\") ?? \"\";\n throw new ScenarioCommandParamsError(\n `${options.path}.params${suffix}`,\n firstIssue?.message ?? \"invalid interaction parameters\",\n );\n}\n\n/** Convert runtime command params into the semantic, pasteable scenario form. */\nexport function projectScenarioCommandParams(options: {\n readonly game: GameLike;\n readonly phase: string;\n readonly interactionId: string;\n readonly params: unknown;\n readonly playerIds: readonly string[];\n readonly path: string;\n}): Record<string, unknown> {\n const candidateSchemas = clientParamSchemaCandidates(options);\n let firstSeatError: ScenarioSchemaValueError | undefined;\n for (const schema of candidateSchemas) {\n if (!schema.safeParse(options.params).success) continue;\n try {\n const projected = projectScenarioSeatReferences({\n schema,\n value: options.params,\n playerIds: options.playerIds,\n path: `${options.path}.params`,\n });\n if (isPlainRecord(projected)) return projected;\n } catch (error) {\n if (error instanceof ScenarioSchemaValueError) {\n firstSeatError ??= error;\n continue;\n }\n throw error;\n }\n }\n if (firstSeatError) {\n throw new ScenarioCommandParamsError(\n firstSeatError.path,\n firstSeatError.message,\n );\n }\n throw new ScenarioCommandParamsError(\n `${options.path}.params`,\n \"runtime interaction parameters do not match a client parameter schema\",\n );\n}\n\nfunction clientParamSchemaCandidates(options: {\n readonly game: GameLike;\n readonly phase: string;\n readonly interactionId: string;\n readonly path: string;\n}): z.ZodTypeAny[] {\n const schemas = createClientParamSchemasByPhase(options.game as never);\n const currentPhaseSchema = schemas[options.phase]?.[options.interactionId] as\n | z.ZodTypeAny\n | undefined;\n const candidateSchemas = [\n ...(currentPhaseSchema ? [currentPhaseSchema] : []),\n ...Object.entries(schemas).flatMap(([phase, schemasForPhase]) => {\n if (phase === options.phase) return [];\n const schema = schemasForPhase[options.interactionId] as\n | z.ZodTypeAny\n | undefined;\n return schema ? [schema] : [];\n }),\n ];\n if (candidateSchemas.length === 0) {\n throw new ScenarioCommandParamsError(\n `${options.path}.interactionId`,\n `interaction '${options.interactionId}' has no client parameter schema`,\n );\n }\n return candidateSchemas;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n","import type { Wire } from \"@dreamboard-games/reducer-contract\";\nimport { digestPluginRuntimeJson } from \"@dreamboard-games/plugin-runtime-contract\";\nimport { createReducerBundle } from \"../reducer/bundle.js\";\nimport type { ReducerBundleTestingRuntime } from \"../reducer/bundle/types.js\";\nimport type {\n InteractionActionabilityResult,\n InteractionInputEnumerationResult,\n} from \"../reducer/bundle/trusted/interaction-types.js\";\nimport type {\n DispatchTraceSummaryEntry,\n ReducerDiagnosticEvent,\n} from \"../reducer/diagnostics.js\";\nimport { createExpectApi } from \"./create-expect-api.js\";\nimport { scenarioAssertionFailure } from \"./scenario-assertion-error.js\";\nimport {\n ScenarioDefinitionValidationError,\n ScenarioReplayError,\n type AssertScenarioOptions,\n type InteractionDescriptorLike,\n type InteractionExplanationLike,\n type ReplayScenarioOptions,\n type RejectionExpectation,\n type ScenarioAssertionContext,\n type ScenarioCheckpoint,\n type ScenarioCommandOf,\n type ScenarioCommandTraceEntry,\n type ScenarioDiagnostics,\n type ScenarioProbeResult,\n type ScenarioReplay,\n type ScenarioReplayDefinition,\n type ScenarioReplaySegment,\n type ScenarioSeatRef,\n} from \"./definitions.js\";\nimport {\n validateScenarioDefinition,\n type ScenarioDefinitionGameLike,\n} from \"./scenario-definition-validation.js\";\nimport {\n resolveScenarioCommandParams,\n resolveScenarioSeatRef,\n} from \"./scenario-player-refs.js\";\n\ntype ScenarioBundle = ReducerBundleTestingRuntime;\n\ntype ScenarioReplayState<Game> = {\n readonly game: Game;\n readonly scenario: ScenarioReplayDefinition<Game>;\n readonly playerIds: readonly string[];\n readonly reducerState: Wire.ReducerSessionState;\n readonly checkpoint: ScenarioCheckpoint;\n readonly trace: readonly ScenarioCommandTraceEntry<Game>[];\n readonly events: readonly ReducerDiagnosticEvent[];\n};\n\nexport type ScenarioReplayPerspective =\n | { readonly kind: \"player\"; readonly seat: number }\n | { readonly kind: \"spectator\" };\n\nexport type ScenarioReplayInspectionAuthority<Game> = {\n readonly game: Game;\n readonly scenario: ScenarioReplayDefinition<Game>;\n readonly playerIds: readonly string[];\n readonly checkpoint: ScenarioCheckpoint;\n readonly checkpointDigest: string;\n readonly publicState: unknown;\n readonly view: unknown;\n readonly scheduler: {\n readonly phase: string;\n readonly step: string | null;\n readonly activePlayerIds: readonly string[];\n readonly pendingPlayerIds: readonly string[];\n readonly continuationDependencies: readonly {\n readonly waiterPlayerId: string;\n readonly blockerPlayerIds: readonly string[];\n }[];\n };\n readonly interactions: readonly {\n readonly descriptor: InteractionDescriptorLike;\n readonly explanation: InteractionExplanationLike;\n readonly actionability: InteractionActionabilityResult;\n }[];\n readonly entropy: {\n readonly seed: number | null;\n readonly draws: readonly Wire.RngDraw[];\n };\n readonly commandTrace: readonly ScenarioCommandTraceEntry<Game>[];\n};\n\nexport type ScenarioReplayAdvanceResult<Game> =\n | {\n readonly kind: \"accepted\";\n readonly replay: ScenarioReplay<Game>;\n readonly trace: readonly DispatchTraceSummaryEntry[];\n }\n | {\n readonly kind: \"rejected\";\n readonly errorCode: string;\n readonly message?: string;\n readonly trace: readonly DispatchTraceSummaryEntry[];\n };\n\nexport async function replayScenario<\n const Game extends ScenarioDefinitionGameLike,\n>(options: ReplayScenarioOptions<Game>): Promise<ScenarioReplay<Game>> {\n validateReplayDefinition(options.game, options.scenario);\n const scenario = cloneReplayDefinition(options.scenario);\n const checkpoint = normalizeCheckpoint(scenario, options.at);\n const playerIds = resolvePlayerIds(options.game, scenario.setup.players);\n const events: ReducerDiagnosticEvent[] = [];\n const bundle = createScenarioBundle(options.game, events);\n const normalSetup = options.game.contract.manifest.normalSetup;\n if (!normalSetup) {\n throw new ScenarioDefinitionValidationError({\n code: \"NORMAL_SETUP_UNAVAILABLE\",\n path: \"scenario.setup.players\",\n reason: \"the game manifest does not expose normal setup\",\n });\n }\n const table = normalSetup.createInitialTable({ playerIds });\n const reducerState = await bundle.initialize({\n table: table as Wire.JsonValue,\n playerIds: [...playerIds],\n rngSeed: scenario.setup.seed,\n setup:\n typeof scenario.setup.setupProfileId === \"string\"\n ? {\n profileId: scenario.setup.setupProfileId,\n optionValues: {},\n }\n : null,\n });\n\n const runtime = new ScenarioReplayImplementation<Game>({\n game: options.game,\n scenario,\n playerIds,\n reducerState,\n checkpoint: { segment: \"setup\", completed: 0 },\n trace: [],\n events,\n });\n await runtime.replayTo(checkpoint);\n return runtime;\n}\n\nexport type ScenarioRuntimeCheckpointMaterialization = {\n readonly checkpoint: ScenarioCheckpoint;\n readonly checkpointDigest: string;\n readonly playerIds: readonly string[];\n readonly state: Wire.ReducerSessionState;\n};\n\n/**\n * Trusted tool-side materialization for CLI, Workbench, and backend adapters.\n * The returned reducer snapshot must never cross a player/browser boundary.\n */\nexport async function materializeScenarioRuntimeCheckpoint<\n const Game extends ScenarioDefinitionGameLike,\n>(\n options: ReplayScenarioOptions<Game>,\n): Promise<ScenarioRuntimeCheckpointMaterialization> {\n const replay = requireScenarioReplayImplementation(\n await replayScenario(options),\n );\n return {\n checkpoint: structuredClone(replay.checkpoint),\n checkpointDigest: replay.checkpointDigest,\n playerIds: [...replay.playerIds],\n state: structuredClone(replay.reducerState),\n };\n}\n\nfunction cloneReplayDefinition<Game>(\n scenario: ScenarioReplayDefinition<Game>,\n): ScenarioReplayDefinition<Game> {\n return structuredClone({\n id: scenario.id,\n ...(scenario.description === undefined\n ? {}\n : { description: scenario.description }),\n setup: scenario.setup,\n given: scenario.given,\n when: scenario.when,\n });\n}\n\nexport async function assertScenario<Game>(\n options: AssertScenarioOptions<Game>,\n): Promise<void> {\n const replay = requireScenarioReplayImplementation(options.replay);\n if (!replay.complete) {\n throw new Error(\n `Scenario '${replay.scenarioId}' assertions require a full replay; checkpoint is ${replay.checkpoint.segment}:${replay.checkpoint.completed}.`,\n );\n }\n const context: ScenarioAssertionContext<Game> = {\n expect: createExpectApi({\n lastDiagnosticRejection: () => lastRejectedEvent(replay.diagnostics),\n }),\n state: replay.state,\n view: replay.view,\n interactions: replay.interactions,\n explain: replay.explain,\n get diagnostics() {\n return replay.diagnostics;\n },\n probe: (command) => replay.probe(command),\n };\n await options.assertion(context);\n}\n\nexport async function probeScenarioCommand<Game>(options: {\n readonly replay: ScenarioReplay<Game>;\n readonly command: ScenarioCommandOf<Game>;\n}): Promise<ScenarioProbeResult<Game>> {\n return requireScenarioReplayImplementation(options.replay).probe(\n options.command,\n );\n}\n\nclass ScenarioReplayImplementation<Game> implements ScenarioReplay<Game> {\n readonly scenarioId: string;\n readonly scenario: ScenarioReplayDefinition<Game>;\n readonly game: Game;\n readonly playerIds: readonly string[];\n readonly bundle: ScenarioBundle;\n readonly events: ReducerDiagnosticEvent[];\n checkpoint: ScenarioCheckpoint;\n reducerState: Wire.ReducerSessionState;\n trace: ScenarioCommandTraceEntry<Game>[];\n\n constructor(state: ScenarioReplayState<Game>) {\n this.scenarioId = state.scenario.id;\n this.scenario = state.scenario;\n this.game = state.game;\n this.playerIds = [...state.playerIds];\n this.reducerState = structuredClone(state.reducerState);\n this.checkpoint = structuredClone(state.checkpoint);\n this.trace = structuredClone(\n state.trace,\n ) as ScenarioCommandTraceEntry<Game>[];\n this.events = structuredClone(state.events) as ReducerDiagnosticEvent[];\n this.bundle = createScenarioBundle(state.game as never, this.events);\n\n this.state = this.state.bind(this);\n this.view = this.view.bind(this);\n this.interactions = this.interactions.bind(this);\n this.explain = this.explain.bind(this);\n }\n\n get checkpointDigest(): string {\n return digestPluginRuntimeJson({\n digestVersion: \"scenario-checkpoint@1\",\n scenarioId: this.scenarioId,\n checkpoint: this.checkpoint,\n reducerState: this.reducerState,\n trace: this.trace,\n });\n }\n\n get complete(): boolean {\n return (\n this.checkpoint.segment === \"when\" &&\n this.checkpoint.completed === this.scenario.when.length\n );\n }\n\n get diagnostics(): ScenarioDiagnostics {\n const flow = readFlowState(this.reducerState);\n const projection = this.project(this.playerIds[0]!);\n return {\n events: structuredClone(this.events),\n lastDispatch: lastAcceptedDispatch(this.events),\n flow: {\n currentPhase: flow.currentPhase,\n currentStage: projection.currentStage ?? null,\n activeSeats: flow.activePlayers.flatMap((playerId) => {\n const seat = this.playerIds.indexOf(playerId);\n return seat < 0 ? [] : [{ seat }];\n }),\n },\n };\n }\n\n state(): never {\n return structuredClone(this.reducerState.domain) as never;\n }\n\n view(seat: ScenarioSeatRef): never {\n const playerId = this.playerId(seat, \"seat\");\n const projection = this.project(playerId);\n return structuredClone(projection.seats?.[playerId]?.view ?? null) as never;\n }\n\n interactions(seat: ScenarioSeatRef): readonly InteractionDescriptorLike[] {\n const playerId = this.playerId(seat, \"seat\");\n const projection = this.project(playerId);\n const refs =\n (projection.seats?.[playerId]?.availableInteractionRefs as\n | readonly string[]\n | undefined) ?? [];\n const interactionsByRef =\n (projection.interactionsByRef as\n | Readonly<Record<string, InteractionDescriptorLike>>\n | undefined) ?? {};\n return structuredClone(\n refs.flatMap((ref) => {\n const descriptor = interactionsByRef[ref];\n return descriptor ? [descriptor] : [];\n }),\n );\n }\n\n explain(\n seat: ScenarioSeatRef,\n interactionId: string,\n ): InteractionExplanationLike {\n return structuredClone(\n this.bundle.explainInteraction({\n state: this.reducerState,\n playerId: this.playerId(seat, \"seat\"),\n interactionId,\n }),\n ) as InteractionExplanationLike;\n }\n\n clone(): ScenarioReplay<Game> {\n return new ScenarioReplayImplementation<Game>({\n game: this.game,\n scenario: this.scenario,\n playerIds: this.playerIds,\n reducerState: this.reducerState,\n checkpoint: this.checkpoint,\n trace: this.trace,\n events: this.events,\n });\n }\n\n inspectionAuthority(\n perspective: ScenarioReplayPerspective,\n ): ScenarioReplayInspectionAuthority<Game> {\n const selectedPlayerId =\n perspective.kind === \"player\"\n ? this.playerId({ seat: perspective.seat }, \"perspective.seat\")\n : null;\n const projection = this.bundle.projectSeatsDynamic({\n state: this.reducerState,\n playerIds: selectedPlayerId ? [selectedPlayerId] : [],\n });\n const descriptors = selectedPlayerId\n ? descriptorsForPlayer(projection, selectedPlayerId)\n : [];\n const flow = readFlowState(this.reducerState);\n return {\n game: this.game,\n scenario: structuredClone(this.scenario),\n playerIds: [...this.playerIds],\n checkpoint: structuredClone(this.checkpoint),\n checkpointDigest: this.checkpointDigest,\n publicState: structuredClone(this.reducerState.domain.publicState),\n view: structuredClone(\n selectedPlayerId\n ? (projection.seats[selectedPlayerId]?.view ?? null)\n : (projection.sharedView ?? null),\n ),\n scheduler: {\n phase: flow.currentPhase ?? \"\",\n step: readPhaseStep(this.reducerState.domain.phase),\n activePlayerIds: [\n ...(projection.schedulerFlow?.activePlayerIds ??\n projection.stageSeats ??\n []),\n ],\n pendingPlayerIds: [\n ...(projection.schedulerFlow?.pendingPlayerIds ??\n projection.simultaneousPhase?.pendingPlayerIds ??\n []),\n ],\n continuationDependencies: structuredClone(\n projection.schedulerFlow?.continuationDependencies ?? [],\n ),\n },\n interactions: descriptors.map((descriptor) => ({\n descriptor: structuredClone(descriptor),\n explanation: structuredClone(\n this.bundle.explainInteraction({\n state: this.reducerState,\n playerId: selectedPlayerId!,\n interactionId: String(descriptor.interactionId ?? \"\"),\n }),\n ) as InteractionExplanationLike,\n actionability: structuredClone(\n this.bundle.resolveInteractionActionability({\n state: this.reducerState,\n playerId: selectedPlayerId!,\n interactionId: String(descriptor.interactionId ?? \"\"),\n }),\n ),\n })),\n entropy: {\n seed: this.reducerState.runtime.rng.seed,\n draws: structuredClone(this.reducerState.runtime.rng.draws ?? []),\n },\n commandTrace: structuredClone(this.trace),\n };\n }\n\n enumerateInteractionParams(options: {\n readonly seat: number;\n readonly interactionId: string;\n readonly maxEvaluations: number;\n }): InteractionInputEnumerationResult {\n return structuredClone(\n this.bundle.enumerateInteractionParams({\n state: this.reducerState,\n playerId: this.playerId({ seat: options.seat }, \"perspective.seat\"),\n interactionId: options.interactionId,\n maxEvaluations: options.maxEvaluations,\n }),\n );\n }\n\n async advance(\n command: ScenarioCommandOf<Game>,\n ): Promise<ScenarioReplayAdvanceResult<Game>> {\n const clone = new ScenarioReplayImplementation<Game>({\n game: this.game,\n scenario: this.scenario,\n playerIds: this.playerIds,\n reducerState: this.reducerState,\n checkpoint: this.checkpoint,\n trace: this.trace,\n events: this.events,\n });\n const result = await clone.dispatch(command, \"probe\", 0);\n if (result.kind === \"accept\") {\n clone.trace.push({\n segment: this.checkpoint.segment === \"when\" ? \"when\" : \"given\",\n index: this.checkpoint.completed,\n command: structuredClone(command),\n trace: structuredClone(result.trace),\n });\n return {\n kind: \"accepted\",\n replay: clone,\n trace: structuredClone(result.trace),\n };\n }\n return {\n kind: \"rejected\",\n errorCode: result.errorCode,\n ...(result.message === undefined ? {} : { message: result.message }),\n trace: structuredClone(result.trace),\n };\n }\n\n async replayTo(target: ScenarioCheckpoint): Promise<void> {\n const givenCount =\n target.segment === \"setup\"\n ? 0\n : target.segment === \"given\"\n ? target.completed\n : this.scenario.given.length;\n const whenCount = target.segment === \"when\" ? target.completed : 0;\n for (let index = 0; index < givenCount; index += 1) {\n await this.dispatchRequired(\"given\", index, this.scenario.given[index]!);\n }\n this.checkpoint = { segment: \"given\", completed: givenCount };\n for (let index = 0; index < whenCount; index += 1) {\n await this.dispatchRequired(\"when\", index, this.scenario.when[index]!);\n }\n this.checkpoint = structuredClone(target);\n }\n\n async probe(\n command: ScenarioCommandOf<Game>,\n ): Promise<ScenarioProbeResult<Game>> {\n const clone = requireScenarioReplayImplementation(this.clone());\n const result = await clone.dispatch(command, \"probe\", 0);\n if (result.kind === \"accept\") {\n const accepted = {\n kind: \"accepted\" as const,\n command,\n checkpointDigest: digestPluginRuntimeJson({\n digestVersion: \"scenario-probe@1\",\n from: this.checkpointDigest,\n command,\n reducerState: clone.reducerState,\n trace: result.trace,\n }),\n trace: result.trace,\n toBeAccepted() {},\n toRejectWith(expected: RejectionExpectation): never {\n scenarioAssertionFailure(\n `Expected probe to reject${expected.errorCode ? ` with ${expected.errorCode}` : \"\"}, but it was accepted.`,\n );\n },\n } satisfies ScenarioProbeResult<Game>;\n return accepted;\n }\n const rejected = {\n kind: \"rejected\" as const,\n command,\n errorCode: result.errorCode,\n ...(result.message === undefined ? {} : { message: result.message }),\n trace: result.trace,\n toBeAccepted(): never {\n scenarioAssertionFailure(\n `Expected probe to be accepted, but it rejected with ${result.errorCode}.`,\n );\n },\n toRejectWith(expected: RejectionExpectation): void {\n assertRejectionMatches(result, expected);\n },\n } satisfies ScenarioProbeResult<Game>;\n return rejected;\n }\n\n private async dispatchRequired(\n segment: ScenarioReplaySegment,\n index: number,\n command: ScenarioCommandOf<Game>,\n ): Promise<void> {\n const result = await this.dispatch(command, segment, index);\n if (result.kind === \"reject\") {\n throw new ScenarioReplayError({\n scenarioId: this.scenarioId,\n segment,\n index,\n interactionId: command.interactionId,\n errorCode: result.errorCode,\n reducerMessage: result.message,\n trace: result.trace,\n });\n }\n this.trace.push({\n segment,\n index,\n command: structuredClone(command),\n trace: result.trace,\n });\n }\n\n private async dispatch(\n command: ScenarioCommandOf<Game>,\n segment: ScenarioReplaySegment | \"probe\",\n index: number,\n ): Promise<\n | { readonly kind: \"accept\"; readonly trace: DispatchTraceSummaryEntry[] }\n | {\n readonly kind: \"reject\";\n readonly errorCode: string;\n readonly message?: string;\n readonly trace: DispatchTraceSummaryEntry[];\n }\n > {\n const phase = readFlowState(this.reducerState).currentPhase ?? \"\";\n const playerId = resolveScenarioSeatRef({\n ref: command.actor,\n playerIds: this.playerIds,\n path: `scenario.${segment}[${index}].actor`,\n });\n const params = resolveScenarioCommandParams({\n game: this.game as never,\n phase,\n interactionId: command.interactionId,\n params: command.params,\n playerIds: this.playerIds,\n path: `scenario.${segment}[${index}]`,\n });\n const result = await this.bundle.dispatch({\n state: this.reducerState,\n input: {\n kind: \"interaction\",\n playerId,\n interactionId: command.interactionId,\n params: params as Wire.JsonValue,\n },\n });\n if (result.kind === \"reject\") {\n return {\n kind: \"reject\",\n errorCode: result.errorCode,\n ...(result.message === undefined ? {} : { message: result.message }),\n trace: [],\n };\n }\n this.reducerState = structuredClone(result.state);\n return {\n kind: \"accept\",\n trace: summarizeWireTrace(result.trace),\n };\n }\n\n private playerId(seat: ScenarioSeatRef, path: string): string {\n return resolveScenarioSeatRef({\n ref: seat,\n playerIds: this.playerIds,\n path,\n });\n }\n\n private project(playerId: string): Wire.SeatProjectionBundle {\n return this.bundle.projectSeatsDynamic({\n state: this.reducerState,\n playerIds: [playerId],\n });\n }\n}\n\nexport function inspectScenarioReplayAuthority<Game>(options: {\n readonly replay: ScenarioReplay<Game>;\n readonly perspective: ScenarioReplayPerspective;\n}): ScenarioReplayInspectionAuthority<Game> {\n return requireScenarioReplayImplementation(\n options.replay,\n ).inspectionAuthority(options.perspective);\n}\n\nexport function enumerateScenarioInteractionParams<Game>(options: {\n readonly replay: ScenarioReplay<Game>;\n readonly seat: number;\n readonly interactionId: string;\n readonly maxEvaluations: number;\n}): InteractionInputEnumerationResult {\n return requireScenarioReplayImplementation(\n options.replay,\n ).enumerateInteractionParams(options);\n}\n\nexport function advanceScenarioReplay<Game>(options: {\n readonly replay: ScenarioReplay<Game>;\n readonly command: ScenarioCommandOf<Game>;\n}): Promise<ScenarioReplayAdvanceResult<Game>> {\n return requireScenarioReplayImplementation(options.replay).advance(\n options.command,\n );\n}\n\nfunction descriptorsForPlayer(\n projection: Wire.SeatProjectionBundle,\n playerId: string,\n): InteractionDescriptorLike[] {\n const refs =\n (projection.seats[playerId]?.availableInteractionRefs as\n | readonly string[]\n | undefined) ?? [];\n const interactionsByRef =\n (projection.interactionsByRef as\n | Readonly<Record<string, InteractionDescriptorLike>>\n | undefined) ?? {};\n return refs.flatMap((ref) => {\n const descriptor = interactionsByRef[ref];\n return descriptor ? [descriptor] : [];\n });\n}\n\nfunction createScenarioBundle(\n game: ScenarioDefinitionGameLike,\n events: ReducerDiagnosticEvent[],\n): ScenarioBundle {\n return createReducerBundle(game as never, {\n diagnostics: {\n event(event) {\n events.push(structuredClone(event));\n },\n },\n }) as ScenarioBundle;\n}\n\nfunction validateReplayDefinition<Game>(\n game: ScenarioDefinitionGameLike,\n replay: ScenarioReplayDefinition<Game>,\n): void {\n validateScenarioDefinition(game, {\n ...replay,\n then: () => undefined,\n });\n}\n\nfunction resolvePlayerIds(\n game: ScenarioDefinitionGameLike,\n count: number,\n): string[] {\n const declared = game.contract.manifest.literals.playerIds;\n return Array.from(\n { length: count },\n (_, index) => declared[index] ?? `player-${index + 1}`,\n );\n}\n\nfunction normalizeCheckpoint<Game>(\n scenario: ScenarioReplayDefinition<Game>,\n checkpoint: ScenarioCheckpoint | undefined,\n): ScenarioCheckpoint {\n if (checkpoint === undefined) {\n return { segment: \"when\", completed: scenario.when.length };\n }\n const maximum =\n checkpoint.segment === \"setup\"\n ? 0\n : checkpoint.segment === \"given\"\n ? scenario.given.length\n : scenario.when.length;\n if (\n !Number.isSafeInteger(checkpoint.completed) ||\n checkpoint.completed < 0 ||\n checkpoint.completed > maximum ||\n (checkpoint.segment === \"setup\" && checkpoint.completed !== 0)\n ) {\n throw new ScenarioDefinitionValidationError({\n code: \"OUT_OF_RANGE\",\n path: \"at.completed\",\n reason: `expected 0 through ${maximum} for ${checkpoint.segment}`,\n });\n }\n return structuredClone(checkpoint);\n}\n\nfunction readFlowState(state: Wire.ReducerSessionState): {\n readonly currentPhase: string | null;\n readonly activePlayers: readonly string[];\n} {\n const flow = (state.domain as { flow?: unknown } | undefined)?.flow;\n if (typeof flow !== \"object\" || flow === null) {\n return { currentPhase: null, activePlayers: [] };\n }\n const record = flow as {\n readonly currentPhase?: unknown;\n readonly activePlayers?: unknown;\n };\n return {\n currentPhase:\n typeof record.currentPhase === \"string\" ? record.currentPhase : null,\n activePlayers: Array.isArray(record.activePlayers)\n ? record.activePlayers.filter(\n (playerId): playerId is string => typeof playerId === \"string\",\n )\n : [],\n };\n}\n\nfunction readPhaseStep(phase: unknown): string | null {\n if (!phase || typeof phase !== \"object\") return null;\n const step = (phase as { readonly step?: unknown }).step;\n return typeof step === \"string\" ? step : null;\n}\n\nfunction summarizeWireTrace(\n trace: readonly Wire.DispatchTrace[],\n): DispatchTraceSummaryEntry[] {\n return trace.flatMap((entry): DispatchTraceSummaryEntry[] => {\n switch (entry.kind) {\n case \"acceptedClientInput\":\n return [\n {\n kind: \"acceptedClientInput\",\n interactionId: entry.input.interactionId,\n playerId: entry.input.playerId,\n },\n ];\n case \"appliedEffect\":\n return [\n {\n kind: \"appliedInstruction\",\n instruction: String(\n (\n entry.effect as {\n readonly kind?: string;\n readonly type?: string;\n }\n ).kind ??\n (entry.effect as { readonly type?: string }).type ??\n \"effect\",\n ),\n },\n ];\n case \"rngConsumption\":\n return [\n {\n kind: \"rngConsumption\",\n version: entry.version,\n operation: entry.operation,\n drawIndex: entry.drawIndex,\n },\n ];\n }\n });\n}\n\nfunction lastAcceptedDispatch(\n events: readonly ReducerDiagnosticEvent[],\n): ScenarioDiagnostics[\"lastDispatch\"] {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event?.type === \"submitAccepted\") {\n return {\n submissionId: event.submissionId,\n trace: structuredClone(event.trace),\n };\n }\n }\n return null;\n}\n\nfunction lastRejectedEvent(\n diagnostics: ScenarioDiagnostics,\n): Extract<ReducerDiagnosticEvent, { type: \"submitRejected\" }> | null {\n for (let index = diagnostics.events.length - 1; index >= 0; index -= 1) {\n const event = diagnostics.events[index];\n if (event?.type === \"submitRejected\") return event;\n }\n return null;\n}\n\nfunction assertRejectionMatches(\n rejection: { readonly errorCode: string; readonly message?: string },\n expected: RejectionExpectation,\n): void {\n if (\n expected.errorCode !== undefined &&\n rejection.errorCode !== expected.errorCode\n ) {\n scenarioAssertionFailure(\n `Expected rejection errorCode '${expected.errorCode}', received '${rejection.errorCode}'.`,\n );\n }\n if (\n typeof expected.message === \"string\" &&\n rejection.message !== expected.message\n ) {\n scenarioAssertionFailure(\n `Expected rejection message '${expected.message}', received '${rejection.message ?? \"undefined\"}'.`,\n );\n }\n if (\n expected.message instanceof RegExp &&\n !expected.message.test(rejection.message ?? \"\")\n ) {\n scenarioAssertionFailure(\n `Expected rejection message '${rejection.message ?? \"\"}' to match ${String(expected.message)}.`,\n );\n }\n}\n\nfunction requireScenarioReplayImplementation<Game>(\n replay: ScenarioReplay<Game>,\n): ScenarioReplayImplementation<Game> {\n if (!(replay instanceof ScenarioReplayImplementation)) {\n throw new Error(\n \"Scenario replay was not created by replayScenario(); alternate replay implementations are not supported.\",\n );\n }\n return replay;\n}\n","import {\n digestPluginRuntimeJson,\n encodeCanonicalPluginRuntimeJson,\n} from \"@dreamboard-games/plugin-runtime-contract\";\nimport type { Sha256Digest } from \"./inspection/types.js\";\n\nexport function canonicalScenarioJson(value: unknown): string {\n return encodeCanonicalPluginRuntimeJson(value);\n}\n\nexport function digestScenarioJson(value: unknown): Sha256Digest {\n return digestPluginRuntimeJson(value) as Sha256Digest;\n}\n\nexport function compareCanonicalScenarioJson(\n left: unknown,\n right: unknown,\n): number {\n const leftJson = canonicalScenarioJson(left);\n const rightJson = canonicalScenarioJson(right);\n return leftJson === rightJson ? 0 : leftJson < rightJson ? -1 : 1;\n}\n"],"mappings":"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","names":["isPlainObject"]}
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
PluginSessionProvider,
|
|
5
5
|
RuntimeContext,
|
|
6
6
|
usePluginSession
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GMOBG7Y7.js";
|
|
8
8
|
import {
|
|
9
9
|
HostToPluginEnvelopeSchema,
|
|
10
10
|
RuntimeJsonSchema
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QQNL4WTX.js";
|
|
12
12
|
|
|
13
13
|
// src/runtime/core/create-plugin-runtime-client.ts
|
|
14
14
|
var defaultClock = {
|
|
@@ -330,4 +330,4 @@ export {
|
|
|
330
330
|
createPluginRuntimeClient,
|
|
331
331
|
PluginRuntimeBoundary
|
|
332
332
|
};
|
|
333
|
-
//# sourceMappingURL=chunk-
|
|
333
|
+
//# sourceMappingURL=chunk-NGYFBNBP.js.map
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateWorkspaceArtifacts
|
|
3
|
+
} from "./chunk-7ADPYKFT.js";
|
|
4
|
+
import {
|
|
5
|
+
compareReferenceGameCanonicalStrings
|
|
6
|
+
} from "./chunk-UNVCT5Z7.js";
|
|
7
|
+
import {
|
|
8
|
+
WORKSPACE_CODEGEN_OWNERSHIP
|
|
9
|
+
} from "./chunk-SACZWUA6.js";
|
|
10
|
+
|
|
11
|
+
// src/authoring/materialize-workspace.ts
|
|
12
|
+
import { createHash, randomUUID } from "crypto";
|
|
13
|
+
import { mkdir, readFile, rename, rm, stat, writeFile } from "fs/promises";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { pathToFileURL } from "url";
|
|
16
|
+
import { build } from "esbuild";
|
|
17
|
+
var authoritativePaths = new Set(
|
|
18
|
+
WORKSPACE_CODEGEN_OWNERSHIP.dynamic.generatedFiles
|
|
19
|
+
);
|
|
20
|
+
async function materializeWorkspace(options) {
|
|
21
|
+
const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
|
|
22
|
+
const manifestPath = resolveProjectPath(projectRoot, options.manifestPath);
|
|
23
|
+
if (!await isFile(manifestPath)) {
|
|
24
|
+
throw new Error(`Manifest source does not exist: ${manifestPath}.`);
|
|
25
|
+
}
|
|
26
|
+
const manifest = await loadManifest({ manifestPath, projectRoot });
|
|
27
|
+
const artifacts = generateWorkspaceArtifacts(manifest);
|
|
28
|
+
const emittedAuthoritative = new Set(
|
|
29
|
+
artifacts.filter(({ ownership }) => ownership === "authoritative").map(({ path: artifactPath }) => artifactPath)
|
|
30
|
+
);
|
|
31
|
+
assertExactAuthoritativeInventory(emittedAuthoritative);
|
|
32
|
+
let seededFiles = 0;
|
|
33
|
+
const records = [];
|
|
34
|
+
for (const artifact of artifacts) {
|
|
35
|
+
const destination = resolveProjectPath(projectRoot, artifact.path);
|
|
36
|
+
if (artifact.ownership === "seed") {
|
|
37
|
+
if (!options.writeMissingSeeds || await isFile(destination)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
42
|
+
if (artifact.ownership === "authoritative") {
|
|
43
|
+
await writeAuthoritativeFile(destination, artifact.content);
|
|
44
|
+
} else {
|
|
45
|
+
await writeFile(destination, artifact.content);
|
|
46
|
+
}
|
|
47
|
+
if (artifact.ownership === "seed") {
|
|
48
|
+
seededFiles += 1;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const bytes = await readFile(destination);
|
|
52
|
+
const actual = createHash("sha256").update(bytes).digest("hex");
|
|
53
|
+
if (actual !== artifact.contentSha256) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`Generated ${artifact.path} digest does not match its SDK receipt.`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
records.push({
|
|
59
|
+
path: artifact.path,
|
|
60
|
+
ownership: "authoritative",
|
|
61
|
+
sha256: `sha256:${actual}`
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
records.sort(
|
|
65
|
+
(left, right) => compareReferenceGameCanonicalStrings(left.path, right.path)
|
|
66
|
+
);
|
|
67
|
+
return {
|
|
68
|
+
schemaVersion: 1,
|
|
69
|
+
projectRoot,
|
|
70
|
+
authoritativeFiles: records.length,
|
|
71
|
+
seededFiles,
|
|
72
|
+
artifacts: records,
|
|
73
|
+
digest: `sha256:${createHash("sha256").update(JSON.stringify(records)).digest("hex")}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function loadManifest(options) {
|
|
77
|
+
const entryPath = path.join(
|
|
78
|
+
options.projectRoot,
|
|
79
|
+
"node_modules/.cache/dreamboard-workspace-compiler",
|
|
80
|
+
`manifest-${process.pid}-${randomUUID()}.mjs`
|
|
81
|
+
);
|
|
82
|
+
await mkdir(path.dirname(entryPath), { recursive: true });
|
|
83
|
+
try {
|
|
84
|
+
const result = await build({
|
|
85
|
+
entryPoints: [options.manifestPath],
|
|
86
|
+
outfile: entryPath,
|
|
87
|
+
absWorkingDir: options.projectRoot,
|
|
88
|
+
bundle: true,
|
|
89
|
+
format: "esm",
|
|
90
|
+
platform: "node",
|
|
91
|
+
target: "node24",
|
|
92
|
+
packages: "external",
|
|
93
|
+
sourcemap: "inline",
|
|
94
|
+
logLevel: "silent"
|
|
95
|
+
});
|
|
96
|
+
void result;
|
|
97
|
+
const loaded = await import(pathToFileURL(entryPath).href);
|
|
98
|
+
const manifest = loaded.manifest ?? loaded.default;
|
|
99
|
+
if (!manifest || typeof manifest !== "object") {
|
|
100
|
+
throw new Error("Manifest source must export a manifest object.");
|
|
101
|
+
}
|
|
102
|
+
return manifest;
|
|
103
|
+
} finally {
|
|
104
|
+
await rm(entryPath, { force: true });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function writeAuthoritativeFile(destination, content) {
|
|
108
|
+
const temporaryPath = path.join(
|
|
109
|
+
path.dirname(destination),
|
|
110
|
+
`.${path.basename(destination)}.${process.pid}.${randomUUID()}.tmp`
|
|
111
|
+
);
|
|
112
|
+
try {
|
|
113
|
+
await writeFile(temporaryPath, content);
|
|
114
|
+
await rename(temporaryPath, destination);
|
|
115
|
+
} finally {
|
|
116
|
+
await rm(temporaryPath, { force: true });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function assertExactAuthoritativeInventory(emitted) {
|
|
120
|
+
const missing = [...authoritativePaths].filter(
|
|
121
|
+
(value) => !emitted.has(value)
|
|
122
|
+
);
|
|
123
|
+
const unexpected = [...emitted].filter(
|
|
124
|
+
(value) => !authoritativePaths.has(value)
|
|
125
|
+
);
|
|
126
|
+
if (missing.length > 0 || unexpected.length > 0) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`SDK workspace ownership mismatch (missing: ${missing.join(", ") || "none"}; unexpected: ${unexpected.join(", ") || "none"}).`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function resolveProjectPath(projectRoot, value) {
|
|
133
|
+
if (typeof value !== "string" || value.length === 0 || path.isAbsolute(value) || value.split(/[\\/]+/).some((segment) => segment === "..")) {
|
|
134
|
+
throw new Error(`Workspace path must be project-relative: ${value}.`);
|
|
135
|
+
}
|
|
136
|
+
const resolved = path.resolve(projectRoot, value);
|
|
137
|
+
if (!resolved.startsWith(`${projectRoot}${path.sep}`)) {
|
|
138
|
+
throw new Error(`Workspace path escapes the project root: ${value}.`);
|
|
139
|
+
}
|
|
140
|
+
return resolved;
|
|
141
|
+
}
|
|
142
|
+
async function isFile(filePath) {
|
|
143
|
+
return stat(filePath).then((value) => value.isFile()).catch((error) => {
|
|
144
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export {
|
|
152
|
+
materializeWorkspace
|
|
153
|
+
};
|
|
154
|
+
//# sourceMappingURL=chunk-P6IJ5YVY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/authoring/materialize-workspace.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { WORKSPACE_CODEGEN_OWNERSHIP } from \"@dreamboard-games/workspace-codegen\";\nimport { build } from \"esbuild\";\nimport { compareReferenceGameCanonicalStrings } from \"../reference-games/canonical.js\";\nimport { generateWorkspaceArtifacts } from \"./adapter.js\";\n\nexport type MaterializeWorkspaceOptions = {\n readonly manifestPath: string;\n readonly projectRoot?: string;\n /** Scaffolding-only. Existing build/test paths leave seed files untouched. */\n readonly writeMissingSeeds?: boolean;\n};\n\nexport type MaterializedWorkspaceReceipt = {\n readonly schemaVersion: 1;\n readonly projectRoot: string;\n readonly authoritativeFiles: number;\n readonly seededFiles: number;\n readonly artifacts: readonly {\n readonly path: string;\n readonly ownership: \"authoritative\";\n readonly sha256: `sha256:${string}`;\n }[];\n readonly digest: `sha256:${string}`;\n};\n\ntype ManifestModule = {\n readonly default?: unknown;\n readonly manifest?: unknown;\n};\n\nconst authoritativePaths = new Set(\n WORKSPACE_CODEGEN_OWNERSHIP.dynamic.generatedFiles,\n);\n\n/**\n * Materialize SDK-owned workspace contracts from authored manifest source.\n * Authoritative files are always replaced. Seed files are untouched unless a\n * scaffolding caller explicitly opts in. No test state or projection artifact\n * is emitted.\n */\nexport async function materializeWorkspace(\n options: MaterializeWorkspaceOptions,\n): Promise<MaterializedWorkspaceReceipt> {\n const projectRoot = path.resolve(options.projectRoot ?? process.cwd());\n const manifestPath = resolveProjectPath(projectRoot, options.manifestPath);\n if (!(await isFile(manifestPath))) {\n throw new Error(`Manifest source does not exist: ${manifestPath}.`);\n }\n const manifest = await loadManifest({ manifestPath, projectRoot });\n const artifacts = generateWorkspaceArtifacts(manifest);\n const emittedAuthoritative = new Set(\n artifacts\n .filter(({ ownership }) => ownership === \"authoritative\")\n .map(({ path: artifactPath }) => artifactPath),\n );\n assertExactAuthoritativeInventory(emittedAuthoritative);\n\n let seededFiles = 0;\n const records: Array<{\n readonly path: string;\n readonly ownership: \"authoritative\";\n readonly sha256: `sha256:${string}`;\n }> = [];\n for (const artifact of artifacts) {\n const destination = resolveProjectPath(projectRoot, artifact.path);\n if (artifact.ownership === \"seed\") {\n if (!options.writeMissingSeeds || (await isFile(destination))) {\n continue;\n }\n }\n await mkdir(path.dirname(destination), { recursive: true });\n if (artifact.ownership === \"authoritative\") {\n await writeAuthoritativeFile(destination, artifact.content);\n } else {\n await writeFile(destination, artifact.content);\n }\n if (artifact.ownership === \"seed\") {\n seededFiles += 1;\n continue;\n }\n const bytes = await readFile(destination);\n const actual = createHash(\"sha256\").update(bytes).digest(\"hex\");\n if (actual !== artifact.contentSha256) {\n throw new Error(\n `Generated ${artifact.path} digest does not match its SDK receipt.`,\n );\n }\n records.push({\n path: artifact.path,\n ownership: \"authoritative\",\n sha256: `sha256:${actual}`,\n });\n }\n records.sort((left, right) =>\n compareReferenceGameCanonicalStrings(left.path, right.path),\n );\n return {\n schemaVersion: 1,\n projectRoot,\n authoritativeFiles: records.length,\n seededFiles,\n artifacts: records,\n digest: `sha256:${createHash(\"sha256\")\n .update(JSON.stringify(records))\n .digest(\"hex\")}`,\n };\n}\n\nasync function loadManifest(options: {\n readonly manifestPath: string;\n readonly projectRoot: string;\n}): Promise<unknown> {\n const entryPath = path.join(\n options.projectRoot,\n \"node_modules/.cache/dreamboard-workspace-compiler\",\n `manifest-${process.pid}-${randomUUID()}.mjs`,\n );\n await mkdir(path.dirname(entryPath), { recursive: true });\n try {\n const result = await build({\n entryPoints: [options.manifestPath],\n outfile: entryPath,\n absWorkingDir: options.projectRoot,\n bundle: true,\n format: \"esm\",\n platform: \"node\",\n target: \"node24\",\n packages: \"external\",\n sourcemap: \"inline\",\n logLevel: \"silent\",\n });\n void result;\n const loaded = (await import(\n pathToFileURL(entryPath).href\n )) as ManifestModule;\n const manifest = loaded.manifest ?? loaded.default;\n if (!manifest || typeof manifest !== \"object\") {\n throw new Error(\"Manifest source must export a manifest object.\");\n }\n return manifest;\n } finally {\n await rm(entryPath, { force: true });\n }\n}\n\nasync function writeAuthoritativeFile(\n destination: string,\n content: string,\n): Promise<void> {\n const temporaryPath = path.join(\n path.dirname(destination),\n `.${path.basename(destination)}.${process.pid}.${randomUUID()}.tmp`,\n );\n try {\n await writeFile(temporaryPath, content);\n await rename(temporaryPath, destination);\n } finally {\n await rm(temporaryPath, { force: true });\n }\n}\n\nfunction assertExactAuthoritativeInventory(emitted: ReadonlySet<string>): void {\n const missing = [...authoritativePaths].filter(\n (value) => !emitted.has(value),\n );\n const unexpected = [...emitted].filter(\n (value) => !authoritativePaths.has(value),\n );\n if (missing.length > 0 || unexpected.length > 0) {\n throw new Error(\n `SDK workspace ownership mismatch (missing: ${missing.join(\", \") || \"none\"}; unexpected: ${unexpected.join(\", \") || \"none\"}).`,\n );\n }\n}\n\nfunction resolveProjectPath(projectRoot: string, value: string): string {\n if (\n typeof value !== \"string\" ||\n value.length === 0 ||\n path.isAbsolute(value) ||\n value.split(/[\\\\/]+/).some((segment) => segment === \"..\")\n ) {\n throw new Error(`Workspace path must be project-relative: ${value}.`);\n }\n const resolved = path.resolve(projectRoot, value);\n if (!resolved.startsWith(`${projectRoot}${path.sep}`)) {\n throw new Error(`Workspace path escapes the project root: ${value}.`);\n }\n return resolved;\n}\n\nasync function isFile(filePath: string): Promise<boolean> {\n return stat(filePath)\n .then((value) => value.isFile())\n .catch((error: unknown) => {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return false;\n }\n throw error;\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -69,7 +69,7 @@ function digestPluginGameplayFrame(frame) {
|
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
// ../plugin-runtime-contract/dist/chunk-
|
|
72
|
+
// ../plugin-runtime-contract/dist/chunk-X6IFFMYH.js
|
|
73
73
|
import { z } from "zod";
|
|
74
74
|
var DREAMBOARD_PLUGIN_PROTOCOL = "dreamboard-plugin";
|
|
75
75
|
var DREAMBOARD_PLUGIN_PROTOCOL_VERSION = 3;
|
|
@@ -131,6 +131,17 @@ var SeatProjectionBundleSchema = z.object({
|
|
|
131
131
|
currentStage: z.string().nullable().optional(),
|
|
132
132
|
stageSeats: z.array(z.string()).optional(),
|
|
133
133
|
simultaneousPhase: z.unknown().nullable().optional(),
|
|
134
|
+
schedulerFlow: z.object({
|
|
135
|
+
version: z.literal(1),
|
|
136
|
+
activePlayerIds: z.array(z.string()),
|
|
137
|
+
pendingPlayerIds: z.array(z.string()),
|
|
138
|
+
continuationDependencies: z.array(
|
|
139
|
+
z.object({
|
|
140
|
+
waiterPlayerId: z.string(),
|
|
141
|
+
blockerPlayerIds: z.array(z.string())
|
|
142
|
+
}).strict()
|
|
143
|
+
)
|
|
144
|
+
}).strict().optional(),
|
|
134
145
|
guidance: GameGuidanceProjectionSchema.nullable().optional(),
|
|
135
146
|
recentEvents: z.array(ProjectedGameEventSchema).optional(),
|
|
136
147
|
sharedView: z.unknown().optional(),
|
|
@@ -551,6 +562,8 @@ function isRecord(value) {
|
|
|
551
562
|
}
|
|
552
563
|
|
|
553
564
|
export {
|
|
565
|
+
encodeCanonicalPluginRuntimeJson,
|
|
566
|
+
digestPluginRuntimeJson,
|
|
554
567
|
computePluginActionSetVersion,
|
|
555
568
|
digestPluginGameplayFrame,
|
|
556
569
|
DREAMBOARD_PLUGIN_PROTOCOL,
|
|
@@ -562,4 +575,4 @@ export {
|
|
|
562
575
|
PluginProtocolTapeSchema,
|
|
563
576
|
materializePluginGameplayFrame
|
|
564
577
|
};
|
|
565
|
-
//# sourceMappingURL=chunk-
|
|
578
|
+
//# sourceMappingURL=chunk-QQNL4WTX.js.map
|