@dreamboard-games/cli 0.1.30-alpha.29 → 0.1.30-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +2 -1
  2. package/dist/agent-verifier/agent-workspace-verifier.mjs +360 -17
  3. package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -1
  4. package/dist/agent-verifier/{chunk-IWB4L2HV.mjs → chunk-FNSHNMDY.mjs} +51 -5
  5. package/dist/agent-verifier/chunk-FNSHNMDY.mjs.map +1 -0
  6. package/dist/agent-verifier/{chunk-RDYXWXXC.mjs → chunk-LMW66VBH.mjs} +2 -11
  7. package/dist/agent-verifier/{chunk-RDYXWXXC.mjs.map → chunk-LMW66VBH.mjs.map} +1 -1
  8. package/dist/agent-verifier/{chunk-TIDX3YLW.mjs → chunk-M6YNQZCC.mjs} +2 -2
  9. package/dist/agent-verifier/{chunk-Z7UBAREF.mjs → chunk-QMOBTQ5G.mjs} +7 -9
  10. package/dist/agent-verifier/chunk-QMOBTQ5G.mjs.map +1 -0
  11. package/dist/agent-verifier/{chunk-F2DIOJJZ.mjs → chunk-XCQQIPCO.mjs} +5 -46
  12. package/dist/agent-verifier/chunk-XCQQIPCO.mjs.map +1 -0
  13. package/dist/agent-verifier/{global-config-IXZLY4BS.mjs → global-config-SWWR2LP4.mjs} +3 -4
  14. package/dist/agent-verifier/{materialize-workspace-XYYCQQGB.mjs → materialize-workspace-K4WYFG5E.mjs} +5 -5
  15. package/dist/agent-verifier/{reducer-native-test-harness-BY5SZ7XE.mjs → reducer-native-test-harness-UFMSNNDY.mjs} +49 -576
  16. package/dist/agent-verifier/reducer-native-test-harness-UFMSNNDY.mjs.map +1 -0
  17. package/dist/agent-verifier/{static-scaffold-M7QPX76Z.mjs → static-scaffold-MHVM63HU.mjs} +4 -4
  18. package/dist/authoring-compatibility-internal.js +1 -1
  19. package/dist/{chunk-QIVDPQME.js → chunk-I4SZ7FA4.js} +9 -64
  20. package/dist/{chunk-QIVDPQME.js.map → chunk-I4SZ7FA4.js.map} +1 -1
  21. package/dist/{chunk-NFCRMXEV.js → chunk-RTNKVNQA.js} +52 -624
  22. package/dist/chunk-RTNKVNQA.js.map +1 -0
  23. package/dist/index.js +318 -369
  24. package/dist/index.js.map +1 -1
  25. package/dist/internal.js +23 -3
  26. package/dist/internal.js.map +1 -1
  27. package/package.json +1 -1
  28. package/release/authoring-release-set.json +2 -2
  29. package/skills/dreamboard/SKILL.md +1 -1
  30. package/skills/dreamboard/references/cli.md +2 -3
  31. package/skills/dreamboard/references/quickstart.md +1 -1
  32. package/skills/dreamboard/references/testing.md +0 -7
  33. package/dist/agent-verifier/chunk-B7M2TJSP.mjs +0 -363
  34. package/dist/agent-verifier/chunk-B7M2TJSP.mjs.map +0 -1
  35. package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +0 -1
  36. package/dist/agent-verifier/chunk-IWB4L2HV.mjs.map +0 -1
  37. package/dist/agent-verifier/chunk-UXGTT25Q.mjs +0 -59
  38. package/dist/agent-verifier/chunk-UXGTT25Q.mjs.map +0 -1
  39. package/dist/agent-verifier/chunk-Z7UBAREF.mjs.map +0 -1
  40. package/dist/agent-verifier/reducer-native-test-harness-BY5SZ7XE.mjs.map +0 -1
  41. package/dist/chunk-NFCRMXEV.js.map +0 -1
  42. /package/dist/agent-verifier/{chunk-TIDX3YLW.mjs.map → chunk-M6YNQZCC.mjs.map} +0 -0
  43. /package/dist/agent-verifier/{global-config-IXZLY4BS.mjs.map → global-config-SWWR2LP4.mjs.map} +0 -0
  44. /package/dist/agent-verifier/{materialize-workspace-XYYCQQGB.mjs.map → materialize-workspace-K4WYFG5E.mjs.map} +0 -0
  45. /package/dist/agent-verifier/{static-scaffold-M7QPX76Z.mjs.map → static-scaffold-MHVM63HU.mjs.map} +0 -0
@@ -3,11 +3,6 @@ import {
3
3
  bundleTypeScriptModuleText,
4
4
  importTypeScriptModule
5
5
  } from "./chunk-QD4SQNUP.mjs";
6
- import {
7
- createUserTokenManager,
8
- resolveLocalHarnessAccessToken
9
- } from "./chunk-B7M2TJSP.mjs";
10
- import "./chunk-IWB4L2HV.mjs";
11
6
  import {
12
7
  loadManifest
13
8
  } from "./chunk-KDAQ4CZY.mjs";
@@ -15,12 +10,11 @@ import "./chunk-GWRZRWCF.mjs";
15
10
  import {
16
11
  REDUCER_TESTING_TYPES_WRAPPER_CONTENT,
17
12
  buildReducerTestingContractContent
18
- } from "./chunk-F2DIOJJZ.mjs";
13
+ } from "./chunk-XCQQIPCO.mjs";
19
14
  import {
20
15
  ensureDir,
21
- exists,
22
- writeJsonFile
23
- } from "./chunk-RDYXWXXC.mjs";
16
+ exists
17
+ } from "./chunk-LMW66VBH.mjs";
24
18
  import {
25
19
  CLIENT_PROBLEM_TYPES,
26
20
  SERVER_PROBLEM_TYPES,
@@ -50,10 +44,10 @@ import {
50
44
  import "./chunk-H6XDQJ3N.mjs";
51
45
 
52
46
  // src/services/testing/reducer-native-test-harness.ts
53
- import path3 from "path";
47
+ import path from "path";
54
48
  import { randomUUID as randomUUID2 } from "crypto";
55
- import { createRequire as createRequire2 } from "module";
56
- import { pathToFileURL as pathToFileURL2 } from "url";
49
+ import { createRequire } from "module";
50
+ import { pathToFileURL } from "url";
57
51
  import {
58
52
  existsSync,
59
53
  mkdirSync,
@@ -64,35 +58,6 @@ import {
64
58
  import { readdir } from "fs/promises";
65
59
  import { isDeepStrictEqual } from "util";
66
60
 
67
- // src/utils/dev-session.ts
68
- import { randomInt } from "crypto";
69
- var MIN_SAFE_SEED = BigInt(Number.MIN_SAFE_INTEGER);
70
- var MAX_SAFE_SEED = BigInt(Number.MAX_SAFE_INTEGER);
71
- function createPersistedDevSession(input) {
72
- return {
73
- sessionId: input.sessionId
74
- };
75
- }
76
-
77
- // src/utils/jwt.ts
78
- function extractUserIdFromJwt(token) {
79
- if (!token) {
80
- return null;
81
- }
82
- const parts = token.split(".");
83
- if (parts.length < 2) {
84
- return null;
85
- }
86
- try {
87
- const payload = JSON.parse(
88
- Buffer.from(parts[1], "base64url").toString("utf8")
89
- );
90
- return typeof payload.sub === "string" ? payload.sub : null;
91
- } catch {
92
- return null;
93
- }
94
- }
95
-
96
61
  // src/services/gameplay-authority-submit.ts
97
62
  import { randomUUID } from "crypto";
98
63
 
@@ -671,110 +636,6 @@ async function submitGameplayAuthorityAction(options) {
671
636
  }
672
637
  }
673
638
 
674
- // src/ui/playwright-runner.ts
675
- import os from "os";
676
- import path from "path";
677
- function configurePlaywrightBrowsersPath() {
678
- if (process.env.PLAYWRIGHT_BROWSERS_PATH) {
679
- return;
680
- }
681
- const runtimeHome = process.env.HOME;
682
- let realHome;
683
- try {
684
- realHome = os.userInfo().homedir;
685
- } catch {
686
- return;
687
- }
688
- if (!runtimeHome || path.resolve(runtimeHome) === path.resolve(realHome)) {
689
- return;
690
- }
691
- const browserCachePath = process.platform === "darwin" ? path.join(realHome, "Library", "Caches", "ms-playwright") : process.platform === "win32" ? path.join(realHome, "AppData", "Local", "ms-playwright") : path.join(realHome, ".cache", "ms-playwright");
692
- process.env.PLAYWRIGHT_BROWSERS_PATH = browserCachePath;
693
- }
694
- async function buildBrowserAuthInitScript(config) {
695
- const resolvedToken = resolveLocalHarnessAccessToken(config) ?? (await createUserTokenManager(config).resolveApiToken())?.token;
696
- if (!resolvedToken) return null;
697
- return `(function(){localStorage.setItem('dreamboard_auth_token',${JSON.stringify(resolvedToken)});})();`;
698
- }
699
- async function waitForGameReady(page, timeoutMs = 6e4) {
700
- await page.waitForSelector('iframe[title="Game UI Plugin"]', {
701
- timeout: timeoutMs
702
- });
703
- }
704
-
705
- // src/services/dev-host/loader.ts
706
- import path2 from "path";
707
- import { createRequire } from "module";
708
- import { pathToFileURL } from "url";
709
- async function loadProjectDevHost(projectRoot) {
710
- const requireFromProject = createRequire(path2.join(projectRoot, "package.json"));
711
- let packageJsonPath;
712
- let entryPath;
713
- try {
714
- packageJsonPath = requireFromProject.resolve(
715
- "@dreamboard-games/dev-host/package.json"
716
- );
717
- entryPath = requireFromProject.resolve("@dreamboard-games/dev-host");
718
- } catch (error) {
719
- throw new Error(
720
- "Install @dreamboard-games/dev-host in this workspace before running dreamboard dev or browser tests.",
721
- { cause: error }
722
- );
723
- }
724
- const packageRoot = path2.dirname(packageJsonPath);
725
- if (!isPathInside(packageRoot, entryPath)) {
726
- throw new Error(
727
- "@dreamboard-games/dev-host resolved outside its installed package."
728
- );
729
- }
730
- const packageJson = requireFromProject(packageJsonPath);
731
- if (packageJson.name !== "@dreamboard-games/dev-host" || typeof packageJson.version !== "string" || packageJson.version.length === 0) {
732
- throw new Error("Installed @dreamboard-games/dev-host metadata is invalid.");
733
- }
734
- const loaded = await import(pathToFileURL(entryPath).href);
735
- if (loaded.protocolVersion !== 1 || typeof loaded.start !== "function") {
736
- throw new Error(
737
- "Installed @dreamboard-games/dev-host does not expose DevHostModuleV1."
738
- );
739
- }
740
- return {
741
- packageRoot,
742
- packageVersion: packageJson.version,
743
- module: {
744
- protocolVersion: loaded.protocolVersion,
745
- start: loaded.start
746
- }
747
- };
748
- }
749
- function isPathInside(parent, candidate) {
750
- const relativePath = path2.relative(parent, candidate);
751
- return relativePath === "" || !relativePath.startsWith("..") && !path2.isAbsolute(relativePath);
752
- }
753
-
754
- // src/services/dev-host/platform.ts
755
- function createCliDevHostPlatform(config) {
756
- return {
757
- resolveBearer: () => resolveDevHostBearer(config)
758
- };
759
- }
760
- async function resolveDevHostBearer(config) {
761
- const localHarnessToken = resolveLocalHarnessAccessToken(config);
762
- if (localHarnessToken) {
763
- return { kind: "ok", token: localHarnessToken };
764
- }
765
- if (config.refreshTokenSource !== "global") {
766
- return { kind: "ok", token: config.authToken ?? null };
767
- }
768
- if (!config.refreshToken) {
769
- return {
770
- kind: "permanent_invalid",
771
- message: "Stored Dreamboard session is expired or invalid. Run `dreamboard auth login` to authenticate again."
772
- };
773
- }
774
- const resolved = await createUserTokenManager(config).resolveApiToken();
775
- return { kind: "ok", token: resolved?.token ?? null };
776
- }
777
-
778
639
  // src/services/workflows/resolve-setup-profile.ts
779
640
  function resolveSetupProfileSelection(options) {
780
641
  const setupProfiles = options.manifest.setupProfiles ?? [];
@@ -942,7 +803,6 @@ function projectIdFromSessionGameSource(source) {
942
803
  globalThis.__DREAMBOARD_AUTHORING_WARNINGS__ = true;
943
804
  var GENERATED_TESTING_TYPES_PREFIX = "// Generated by dreamboard";
944
805
  var TESTING_TYPES_STUB = "export function defineScenario(scenario) { return scenario; }\n";
945
- var DEFAULT_TIMEOUT_MS2 = 1e4;
946
806
  var BASE_SUFFIX = ".base.ts";
947
807
  var SCENARIO_SUFFIX = ".scenario.ts";
948
808
  var SDK_UI_RUNTIME_EXTERNALS = [
@@ -974,15 +834,15 @@ function findScenarioStackFrame(options) {
974
834
  if (!options.stack) {
975
835
  return null;
976
836
  }
977
- const absolutePath = path3.resolve(options.scenarioFilePath);
978
- const relativePath = path3.relative(options.projectRoot, absolutePath);
979
- const normalizedRelativePath = relativePath.split(path3.sep).join("/");
837
+ const absolutePath = path.resolve(options.scenarioFilePath);
838
+ const relativePath = path.relative(options.projectRoot, absolutePath);
839
+ const normalizedRelativePath = relativePath.split(path.sep).join("/");
980
840
  const escapedAbsolutePath = escapeRegExp(absolutePath);
981
841
  const escapedRelativePath = escapeRegExp(normalizedRelativePath);
982
842
  const absoluteFrame = new RegExp(`${escapedAbsolutePath}:(\\d+):(\\d+)`);
983
843
  const relativeFrame = new RegExp(`${escapedRelativePath}:(\\d+):(\\d+)`);
984
844
  for (const line of options.stack.split("\n")) {
985
- const normalizedLine = line.split(path3.sep).join("/");
845
+ const normalizedLine = line.split(path.sep).join("/");
986
846
  const match = normalizedLine.match(absoluteFrame) ?? normalizedLine.match(relativeFrame);
987
847
  if (match?.[1] && match?.[2]) {
988
848
  return `at ${normalizedRelativePath}:${match[1]}:${match[2]}`;
@@ -995,17 +855,17 @@ function escapeRegExp(value) {
995
855
  }
996
856
  var projectReducerNativeModules = /* @__PURE__ */ new Map();
997
857
  function resolveProjectSdkModule(projectRoot, specifier) {
998
- const requireFromProject = createRequire2(
999
- path3.join(projectRoot, "package.json")
858
+ const requireFromProject = createRequire(
859
+ path.join(projectRoot, "package.json")
1000
860
  );
1001
861
  return requireFromProject.resolve(specifier);
1002
862
  }
1003
863
  async function importProjectSdkModule(projectRoot, specifier) {
1004
864
  const modulePath = resolveProjectSdkModule(projectRoot, specifier);
1005
- return await import(pathToFileURL2(modulePath).href);
865
+ return await import(pathToFileURL(modulePath).href);
1006
866
  }
1007
867
  async function loadProjectReducerNativeModules(projectRoot) {
1008
- const cacheKey = path3.resolve(projectRoot);
868
+ const cacheKey = path.resolve(projectRoot);
1009
869
  const cached = projectReducerNativeModules.get(cacheKey);
1010
870
  if (cached) {
1011
871
  return cached;
@@ -1039,22 +899,9 @@ function createSubmissionError(errorCode, message, fallbackMessage) {
1039
899
  error.errorCode = errorCode;
1040
900
  return error;
1041
901
  }
1042
- function parseJsonValue(value) {
1043
- if (typeof value !== "string") {
1044
- return value;
1045
- }
1046
- try {
1047
- return JSON.parse(value);
1048
- } catch {
1049
- return value;
1050
- }
1051
- }
1052
902
  function deepEqual(left, right) {
1053
903
  return isDeepStrictEqual(left, right);
1054
904
  }
1055
- function normalizeScenarioRunners(runners) {
1056
- return runners && runners.length > 0 ? runners : ["reducer"];
1057
- }
1058
905
  function shouldRefreshReducerTestingTypes(existingContent) {
1059
906
  if (existingContent === null || existingContent.trim().length === 0 || existingContent === TESTING_TYPES_STUB || existingContent.startsWith(GENERATED_TESTING_TYPES_PREFIX)) {
1060
907
  return true;
@@ -1068,7 +915,7 @@ async function discoverFiles(root, suffix) {
1068
915
  const entries = await readdir(root, { withFileTypes: true });
1069
916
  const files = [];
1070
917
  for (const entry of entries) {
1071
- const entryPath = path3.join(root, entry.name);
918
+ const entryPath = path.join(root, entry.name);
1072
919
  if (entry.isDirectory()) {
1073
920
  files.push(...await discoverFiles(entryPath, suffix));
1074
921
  continue;
@@ -1117,8 +964,8 @@ function parseTypedScenarioDefinition(value) {
1117
964
  };
1118
965
  }
1119
966
  async function isReducerNativeTestingWorkspace(projectRoot) {
1120
- return await exists(path3.join(projectRoot, "app", "game.ts")) && await exists(
1121
- path3.join(projectRoot, "shared", "generated", "ui-contract.ts")
967
+ return await exists(path.join(projectRoot, "app", "game.ts")) && await exists(
968
+ path.join(projectRoot, "shared", "generated", "ui-contract.ts")
1122
969
  );
1123
970
  }
1124
971
  async function ensureReducerNativeTestingFiles(projectRoot) {
@@ -1210,7 +1057,7 @@ var DEFAULT_REJECTION_CODES = [
1210
1057
  ];
1211
1058
  async function collectKnownRejectionCodes(projectRoot) {
1212
1059
  const knownCodes = new Set(DEFAULT_REJECTION_CODES);
1213
- const gamePath = path3.join(projectRoot, "app", "game.ts");
1060
+ const gamePath = path.join(projectRoot, "app", "game.ts");
1214
1061
  if (!await exists(gamePath)) {
1215
1062
  return Array.from(knownCodes).sort(
1216
1063
  (left, right) => left.localeCompare(right)
@@ -1276,8 +1123,8 @@ async function loadTypedScenarios(projectRoot, options) {
1276
1123
  return loaded;
1277
1124
  }
1278
1125
  function reducerNativeTestHelperExternals(projectRoot, filePath) {
1279
- const testingTypesPath = path3.join(projectRoot, "test", "testing-types");
1280
- const relative = path3.relative(path3.dirname(filePath), testingTypesPath).replaceAll("\\", "/");
1126
+ const testingTypesPath = path.join(projectRoot, "test", "testing-types");
1127
+ const relative = path.relative(path.dirname(filePath), testingTypesPath).replaceAll("\\", "/");
1281
1128
  const specifier = relative.startsWith(".") ? relative : `./${relative}`;
1282
1129
  return [specifier, `${specifier}.ts`, ...SDK_UI_RUNTIME_EXTERNALS];
1283
1130
  }
@@ -1651,78 +1498,6 @@ function toReducerInput(input) {
1651
1498
  params: input.params
1652
1499
  };
1653
1500
  }
1654
- var RemoteGameplayTracker = class {
1655
- constructor(sessionId, playerId) {
1656
- this.sessionId = sessionId;
1657
- this.playerId = playerId;
1658
- this.state.playerId = playerId;
1659
- }
1660
- state = {
1661
- version: -1,
1662
- actionSetVersion: "",
1663
- currentPhase: null,
1664
- playerId: "player-1",
1665
- view: null,
1666
- availableInteractions: []
1667
- };
1668
- liveBootstrap = false;
1669
- async bootstrap() {
1670
- const { data, error, response } = await getSessionSnapshot({
1671
- path: { sessionId: this.sessionId },
1672
- query: { playerId: this.playerId }
1673
- });
1674
- if (error || !data || data.type !== "gameplay") {
1675
- throw toDreamboardApiError(
1676
- error ?? { detail: "Gameplay snapshot was unavailable." },
1677
- response,
1678
- "Failed to load the remote gameplay bootstrap snapshot"
1679
- );
1680
- }
1681
- if (data.gameplay.actionSetVersion === "authority") {
1682
- return;
1683
- }
1684
- this.liveBootstrap = true;
1685
- this.applyGameplay(data.gameplay);
1686
- }
1687
- hasLiveBootstrap() {
1688
- return this.liveBootstrap;
1689
- }
1690
- snapshot() {
1691
- return {
1692
- ...this.state,
1693
- availableInteractions: [...this.state.availableInteractions]
1694
- };
1695
- }
1696
- applyShadow(shadow) {
1697
- const projection = shadow.projectAllSeats();
1698
- const playerId = this.playerId;
1699
- const seat = projection.seats[playerId];
1700
- this.state.version = shadow.currentVersion();
1701
- this.state.actionSetVersion = "";
1702
- this.state.playerId = playerId;
1703
- this.state.currentPhase = shadow.phase();
1704
- this.state.view = seat?.view ?? null;
1705
- this.state.availableInteractions = shadow.availableInteractionsForPlayer(playerId);
1706
- }
1707
- applyGameplay(gameplay) {
1708
- const playerId = gameplay.perspectivePlayerId;
1709
- const seat = gameplay.seats[playerId];
1710
- this.state.version = gameplay.version;
1711
- this.state.actionSetVersion = gameplay.actionSetVersion;
1712
- this.state.playerId = playerId;
1713
- this.state.currentPhase = gameplay.shared.currentPhase;
1714
- this.state.view = parseSeatView(seat?.view ?? "null");
1715
- this.state.availableInteractions = (seat?.availableInteractionRefs ?? []).map((ref) => gameplay.interactionsByRef[ref]).filter(
1716
- (interaction) => Boolean(interaction)
1717
- ).map((interaction) => interaction.interactionId);
1718
- }
1719
- };
1720
- function parseSeatView(raw) {
1721
- return raw ? parseJsonValue(raw) : null;
1722
- }
1723
- function sleep(ms) {
1724
- return new Promise((resolve) => setTimeout(resolve, ms));
1725
- }
1726
1501
  function assertDispatchResultWireContract(result) {
1727
1502
  if (typeof result !== "object" || result === null) {
1728
1503
  throw new Error(
@@ -1731,98 +1506,6 @@ function assertDispatchResultWireContract(result) {
1731
1506
  }
1732
1507
  return result;
1733
1508
  }
1734
- async function createBrowserBridgeClient(page) {
1735
- const bridgeExists = async () => page.evaluate(
1736
- () => Boolean(
1737
- window.__dreamboardTestBridge__
1738
- )
1739
- );
1740
- const startedAt = Date.now();
1741
- while (!await bridgeExists()) {
1742
- if (Date.now() - startedAt > DEFAULT_TIMEOUT_MS2) {
1743
- const bodyText = await page.locator("body").innerText().catch(() => "");
1744
- const diagnostic = bodyText.trim().replace(/\s+/g, " ").slice(0, 400);
1745
- throw new Error(
1746
- diagnostic.length > 0 ? `Timed out waiting for browser test bridge. Page text: ${diagnostic}` : "Timed out waiting for browser test bridge."
1747
- );
1748
- }
1749
- await sleep(50);
1750
- }
1751
- return {
1752
- snapshot: () => page.evaluate(
1753
- () => window.__dreamboardTestBridge__.snapshot()
1754
- ),
1755
- submitInteraction: (playerId, interactionId, params) => page.evaluate(
1756
- ([nextPlayerId, nextInteractionId, nextParams]) => window.__dreamboardTestBridge__.submitInteraction(
1757
- nextPlayerId,
1758
- nextInteractionId,
1759
- nextParams
1760
- ),
1761
- [playerId, interactionId, params]
1762
- ),
1763
- waitForVersionChange: async (previousVersion, timeoutMs = DEFAULT_TIMEOUT_MS2) => {
1764
- const started = Date.now();
1765
- while (Date.now() - started < timeoutMs) {
1766
- const snapshot = await page.evaluate(
1767
- () => window.__dreamboardTestBridge__.snapshot()
1768
- );
1769
- if (snapshot.version > previousVersion) {
1770
- return snapshot;
1771
- }
1772
- await sleep(50);
1773
- }
1774
- throw new Error("Timed out waiting for browser gameplay version change.");
1775
- }
1776
- };
1777
- }
1778
- async function assertLiveMatchesShadow(runner, shadow, live) {
1779
- if (runner === "reducer") {
1780
- return;
1781
- }
1782
- const currentPhase = "currentPhase" in live ? live.currentPhase : shadow.phase();
1783
- if (currentPhase !== shadow.phase()) {
1784
- throw new Error(
1785
- `Live phase '${String(currentPhase)}' diverged from reducer phase '${shadow.phase()}'.`
1786
- );
1787
- }
1788
- const livePlayerId = "playerId" in live ? live.playerId : live.controllingPlayerId;
1789
- const liveView = "view" in live ? live.view : null;
1790
- if (livePlayerId && !deepEqual(liveView, await shadow.view(livePlayerId))) {
1791
- throw new Error("Live projected views diverged from reducer shadow views.");
1792
- }
1793
- const liveInteractions = "availableInteractions" in live ? live.availableInteractions : null;
1794
- if (livePlayerId && liveInteractions && !deepEqual(
1795
- liveInteractions,
1796
- shadow.availableInteractionsForPlayer(livePlayerId)
1797
- )) {
1798
- throw new Error(
1799
- "Live available-interactions metadata diverged from reducer shadow state."
1800
- );
1801
- }
1802
- }
1803
- async function loadBrowserDriver(projectRoot) {
1804
- const filePath = path3.join(projectRoot, "test", "browser-driver.ts");
1805
- if (!await exists(filePath)) {
1806
- return null;
1807
- }
1808
- const module = await importTypeScriptModule(filePath);
1809
- return module.default ?? module;
1810
- }
1811
- async function openBrowserPage(playUrl, config) {
1812
- configurePlaywrightBrowsersPath();
1813
- const { chromium } = await import("playwright");
1814
- const browser = await chromium.launch({ headless: true });
1815
- const context = await browser.newContext({
1816
- viewport: { width: 1440, height: 900 }
1817
- });
1818
- const initScript = await buildBrowserAuthInitScript(config);
1819
- if (initScript) {
1820
- await context.addInitScript({ content: initScript });
1821
- }
1822
- const page = await context.newPage();
1823
- await page.goto(playUrl, { waitUntil: "domcontentloaded" });
1824
- return { browser, page };
1825
- }
1826
1509
  function sanitizeSnapshotSegment(value) {
1827
1510
  return value.replace(/[^a-zA-Z0-9._-]+/g, "-");
1828
1511
  }
@@ -1838,7 +1521,7 @@ function createScenarioSnapshotMatcher(options) {
1838
1521
  };
1839
1522
  const serialized = `${JSON.stringify(wrappedValue, null, 2)}
1840
1523
  `;
1841
- mkdirSync(path3.dirname(snapshotPath), { recursive: true });
1524
+ mkdirSync(path.dirname(snapshotPath), { recursive: true });
1842
1525
  if (!existsSync(snapshotPath) || options.updateSnapshots) {
1843
1526
  writeFileSync(snapshotPath, serialized, "utf8");
1844
1527
  return;
@@ -1846,7 +1529,7 @@ function createScenarioSnapshotMatcher(options) {
1846
1529
  const previous = JSON.parse(readFileSync(snapshotPath, "utf8"));
1847
1530
  if (!deepEqual(previous.value, actual)) {
1848
1531
  throw new Error(
1849
- `Snapshot mismatch for scenario '${options.scenarioId}'. Re-run with --update-snapshots to refresh ${path3.relative(options.projectRoot, snapshotPath)}.`
1532
+ `Snapshot mismatch for scenario '${options.scenarioId}'. Re-run with --update-snapshots to refresh ${path.relative(options.projectRoot, snapshotPath)}.`
1850
1533
  );
1851
1534
  }
1852
1535
  };
@@ -1855,24 +1538,12 @@ async function createScenarioContext(options) {
1855
1538
  const api = {
1856
1539
  start: async () => {
1857
1540
  await options.shadow.start();
1858
- if (options.runner === "remote" && options.remote) {
1859
- if (options.remote.tracker.hasLiveBootstrap()) {
1860
- const live = options.remote.tracker.snapshot();
1861
- await assertLiveMatchesShadow("remote", options.shadow, live);
1862
- } else {
1863
- options.remote.tracker.applyShadow(options.shadow);
1864
- }
1865
- }
1866
- if (options.runner === "browser" && options.browser) {
1867
- const live = await options.browser.bridge.snapshot();
1868
- await assertLiveMatchesShadow("browser", options.shadow, live);
1869
- }
1870
1541
  },
1871
1542
  patchState: async (mutator) => {
1872
1543
  await api.start();
1873
- if (options.live || options.remote || options.browser || options.actionPlan) {
1544
+ if (options.live || options.actionPlan) {
1874
1545
  throw new Error(
1875
- "game.patchState is only supported for reducer snapshot scenarios. Use it to materialize a state before --from-scenario or reducer tests, not inside live replay/browser runners."
1546
+ "game.patchState is only supported for reducer snapshot scenarios. Use it to materialize a state before --from-scenario or reducer tests, not inside live replay."
1876
1547
  );
1877
1548
  }
1878
1549
  options.shadow.patchState(mutator);
@@ -1881,7 +1552,7 @@ async function createScenarioContext(options) {
1881
1552
  await api.start();
1882
1553
  const interactionParams = params ?? {};
1883
1554
  const normalizedInputs = interactionParams && typeof interactionParams === "object" && !Array.isArray(interactionParams) ? interactionParams : {};
1884
- const previousVersion = options.live ? options.live.version : options.actionPlan ? options.shadow.currentVersion() : options.runner === "remote" ? options.remote?.tracker.snapshot().version ?? 0 : options.runner === "browser" ? (await options.browser?.bridge.snapshot())?.version ?? 0 : 0;
1555
+ const previousVersion = options.live ? options.live.version : options.actionPlan ? options.shadow.currentVersion() : 0;
1885
1556
  if (options.live) {
1886
1557
  if (!options.live.actionSetVersion) {
1887
1558
  options.live.actionSetVersion = await fetchLiveActionSetVersion(
@@ -1948,20 +1619,6 @@ async function createScenarioContext(options) {
1948
1619
  }
1949
1620
  options.live.version = typeof data?.version === "number" ? data.version : previousVersion + 1;
1950
1621
  options.live.actionSetVersion = data?.actionSetVersion ?? options.live.actionSetVersion;
1951
- } else if (options.runner === "remote" && options.remote) {
1952
- } else if (options.runner === "browser" && options.browser) {
1953
- const handled = await options.browser.driver?.interaction?.(options.browser.bridge, {
1954
- playerId,
1955
- interactionId,
1956
- params: interactionParams
1957
- }) === true;
1958
- if (!handled) {
1959
- await options.browser.bridge.submitInteraction(
1960
- playerId,
1961
- interactionId,
1962
- interactionParams
1963
- );
1964
- }
1965
1622
  }
1966
1623
  await options.shadow.submitInteraction(
1967
1624
  playerId,
@@ -1981,18 +1638,6 @@ async function createScenarioContext(options) {
1981
1638
  });
1982
1639
  options.actionPlan.submitIndex = (options.actionPlan.submitIndex ?? 0) + 1;
1983
1640
  }
1984
- if (options.runner === "remote" && options.remote) {
1985
- options.remote.tracker.applyShadow(options.shadow);
1986
- await assertLiveMatchesShadow(
1987
- "remote",
1988
- options.shadow,
1989
- options.remote.tracker.snapshot()
1990
- );
1991
- }
1992
- if (options.runner === "browser" && options.browser) {
1993
- const live = await options.browser.bridge.waitForVersionChange(previousVersion);
1994
- await assertLiveMatchesShadow("browser", options.shadow, live);
1995
- }
1996
1641
  }
1997
1642
  };
1998
1643
  return {
@@ -2111,7 +1756,7 @@ async function readMaterializedScenarioCache(options) {
2111
1756
  }
2112
1757
  async function writeMaterializedScenarioCache(options) {
2113
1758
  const cachePath = materializedScenarioCacheFilePath(options);
2114
- await ensureDir(path3.dirname(cachePath));
1759
+ await ensureDir(path.dirname(cachePath));
2115
1760
  await writeWorkspaceJsonFile(
2116
1761
  options.projectRoot,
2117
1762
  materializedScenarioCachePath(options),
@@ -2212,10 +1857,10 @@ async function materializeScenarioReducerState(options) {
2212
1857
  }
2213
1858
  const [gameModule, manifestContractModule, modules] = await Promise.all([
2214
1859
  importTypeScriptModule(
2215
- path3.join(options.projectRoot, "app", "game.ts")
1860
+ path.join(options.projectRoot, "app", "game.ts")
2216
1861
  ),
2217
1862
  importTypeScriptModule(
2218
- path3.join(options.projectRoot, "shared", "manifest-contract.ts")
1863
+ path.join(options.projectRoot, "shared", "manifest-contract.ts")
2219
1864
  ),
2220
1865
  loadProjectReducerNativeModules(options.projectRoot)
2221
1866
  ]);
@@ -2238,7 +1883,6 @@ async function materializeScenarioReducerState(options) {
2238
1883
  );
2239
1884
  shadow.hydrate(generatedBase.snapshot, generatedBase.version);
2240
1885
  const context = await createScenarioContext({
2241
- runner: "reducer",
2242
1886
  shadow,
2243
1887
  expect: modules.createExpectApi()
2244
1888
  });
@@ -2300,10 +1944,10 @@ async function replayScenarioThroughBackend(options) {
2300
1944
  loadGeneratedBaseStates(options.projectRoot),
2301
1945
  loadManifest(options.projectRoot),
2302
1946
  importTypeScriptModule(
2303
- path3.join(options.projectRoot, "app", "game.ts")
1947
+ path.join(options.projectRoot, "app", "game.ts")
2304
1948
  ),
2305
1949
  importTypeScriptModule(
2306
- path3.join(options.projectRoot, "shared", "manifest-contract.ts")
1950
+ path.join(options.projectRoot, "shared", "manifest-contract.ts")
2307
1951
  ),
2308
1952
  loadProjectReducerNativeModules(options.projectRoot)
2309
1953
  ]);
@@ -2399,7 +2043,6 @@ async function replayScenarioThroughBackend(options) {
2399
2043
  }
2400
2044
  const diagnostics = [];
2401
2045
  const context = await createScenarioContext({
2402
- runner: "reducer",
2403
2046
  shadow,
2404
2047
  expect: (await loadProjectReducerNativeModules(options.projectRoot)).createExpectApi(),
2405
2048
  live: {
@@ -2458,10 +2101,10 @@ async function createScenarioActionPlan(options) {
2458
2101
  loadGeneratedBaseStates(options.projectRoot),
2459
2102
  loadManifest(options.projectRoot),
2460
2103
  importTypeScriptModule(
2461
- path3.join(options.projectRoot, "app", "game.ts")
2104
+ path.join(options.projectRoot, "app", "game.ts")
2462
2105
  ),
2463
2106
  importTypeScriptModule(
2464
- path3.join(options.projectRoot, "shared", "manifest-contract.ts")
2107
+ path.join(options.projectRoot, "shared", "manifest-contract.ts")
2465
2108
  ),
2466
2109
  loadProjectReducerNativeModules(options.projectRoot)
2467
2110
  ]);
@@ -2526,7 +2169,6 @@ async function createScenarioActionPlan(options) {
2526
2169
  }
2527
2170
  const diagnostics = [];
2528
2171
  const context = await createScenarioContext({
2529
- runner: "reducer",
2530
2172
  shadow,
2531
2173
  expect: (await loadProjectReducerNativeModules(options.projectRoot)).createExpectApi(),
2532
2174
  actionPlan: {
@@ -2782,7 +2424,7 @@ function writeProjectionSnapshots(options) {
2782
2424
  function validateTypedScenarioBases(scenarios, basesById) {
2783
2425
  const available = new Set(basesById.keys());
2784
2426
  const invalid = scenarios.filter((scenario) => !available.has(scenario.definition.from)).map(
2785
- (scenario) => path3.relative(process.cwd(), scenario.filePath) + ` -> '${scenario.definition.from}'`
2427
+ (scenario) => path.relative(process.cwd(), scenario.filePath) + ` -> '${scenario.definition.from}'`
2786
2428
  );
2787
2429
  if (invalid.length > 0) {
2788
2430
  throw new Error(
@@ -2796,12 +2438,12 @@ async function writeReducerNativeGeneratedFiles(options) {
2796
2438
  const manifestHash = hashContent(JSON.stringify(manifest));
2797
2439
  const appBundleHash = hashContent(
2798
2440
  await bundleTypeScriptModuleText(
2799
- path3.join(options.projectRoot, "app", "game.ts")
2441
+ path.join(options.projectRoot, "app", "game.ts")
2800
2442
  )
2801
2443
  );
2802
2444
  const uiContractHash = hashContent(
2803
2445
  await bundleTypeScriptModuleText(
2804
- path3.join(options.projectRoot, "shared", "generated", "ui-contract.ts"),
2446
+ path.join(options.projectRoot, "shared", "generated", "ui-contract.ts"),
2805
2447
  { external: SDK_UI_RUNTIME_EXTERNALS }
2806
2448
  )
2807
2449
  );
@@ -2813,10 +2455,10 @@ async function writeReducerNativeGeneratedFiles(options) {
2813
2455
  const baseStates = {};
2814
2456
  const [gameModule, manifestContractModule, modules] = await Promise.all([
2815
2457
  importTypeScriptModule(
2816
- path3.join(options.projectRoot, "app", "game.ts")
2458
+ path.join(options.projectRoot, "app", "game.ts")
2817
2459
  ),
2818
2460
  importTypeScriptModule(
2819
- path3.join(options.projectRoot, "shared", "manifest-contract.ts")
2461
+ path.join(options.projectRoot, "shared", "manifest-contract.ts")
2820
2462
  ),
2821
2463
  loadProjectReducerNativeModules(options.projectRoot)
2822
2464
  ]);
@@ -2871,7 +2513,6 @@ async function writeReducerNativeGeneratedFiles(options) {
2871
2513
  shadow.hydrate(parentArtifact.snapshot, parentArtifact.version);
2872
2514
  }
2873
2515
  const context = await createScenarioContext({
2874
- runner: "reducer",
2875
2516
  shadow,
2876
2517
  expect: modules.createExpectApi()
2877
2518
  });
@@ -2937,9 +2578,8 @@ export declare const BASE_STATES_CONTRACT_FINGERPRINT: string | undefined;
2937
2578
  `${header}export const SCENARIO_MANIFEST = ${JSON.stringify(
2938
2579
  options.scenarios.map((scenario) => ({
2939
2580
  id: scenario.definition.id,
2940
- filePath: path3.relative(generatedDir, scenario.filePath),
2941
- base: scenario.definition.from,
2942
- runners: normalizeScenarioRunners(scenario.definition.runners)
2581
+ filePath: path.relative(generatedDir, scenario.filePath),
2582
+ base: scenario.definition.from
2943
2583
  })),
2944
2584
  null,
2945
2585
  2
@@ -2958,7 +2598,7 @@ export declare const BASE_STATES_CONTRACT_FINGERPRINT: string | undefined;
2958
2598
  );
2959
2599
  }
2960
2600
  async function loadGeneratedBaseStates(projectRoot) {
2961
- const filePath = path3.join(
2601
+ const filePath = path.join(
2962
2602
  projectRoot,
2963
2603
  "test",
2964
2604
  "generated",
@@ -2971,7 +2611,7 @@ async function loadGeneratedBaseStates(projectRoot) {
2971
2611
  return module.BASE_STATES ?? null;
2972
2612
  }
2973
2613
  async function loadGeneratedScenarioManifest(projectRoot) {
2974
- const filePath = path3.join(
2614
+ const filePath = path.join(
2975
2615
  projectRoot,
2976
2616
  "test",
2977
2617
  "generated",
@@ -3035,7 +2675,7 @@ async function currentFingerprint(options) {
3035
2675
  const manifest = await loadManifest(options.projectRoot);
3036
2676
  const [gameModule, modules] = await Promise.all([
3037
2677
  importTypeScriptModule(
3038
- path3.join(options.projectRoot, "app", "game.ts")
2678
+ path.join(options.projectRoot, "app", "game.ts")
3039
2679
  ),
3040
2680
  loadProjectReducerNativeModules(options.projectRoot)
3041
2681
  ]);
@@ -3077,12 +2717,12 @@ async function currentFingerprint(options) {
3077
2717
  manifestHash: hashContent(JSON.stringify(manifest)),
3078
2718
  appBundleHash: hashContent(
3079
2719
  await bundleTypeScriptModuleText(
3080
- path3.join(options.projectRoot, "app", "game.ts")
2720
+ path.join(options.projectRoot, "app", "game.ts")
3081
2721
  )
3082
2722
  ),
3083
2723
  uiContractHash: hashContent(
3084
2724
  await bundleTypeScriptModuleText(
3085
- path3.join(options.projectRoot, "shared", "generated", "ui-contract.ts"),
2725
+ path.join(options.projectRoot, "shared", "generated", "ui-contract.ts"),
3086
2726
  { external: SDK_UI_RUNTIME_EXTERNALS }
3087
2727
  )
3088
2728
  ),
@@ -3132,10 +2772,10 @@ async function runReducerNativeScenarios(options) {
3132
2772
  loadGeneratedBaseStates(options.projectRoot),
3133
2773
  loadManifest(options.projectRoot),
3134
2774
  importTypeScriptModule(
3135
- path3.join(options.projectRoot, "app", "game.ts")
2775
+ path.join(options.projectRoot, "app", "game.ts")
3136
2776
  ),
3137
2777
  importTypeScriptModule(
3138
- path3.join(options.projectRoot, "shared", "manifest-contract.ts")
2778
+ path.join(options.projectRoot, "shared", "manifest-contract.ts")
3139
2779
  ),
3140
2780
  loadProjectReducerNativeModules(options.projectRoot)
3141
2781
  ]);
@@ -3154,25 +2794,10 @@ async function runReducerNativeScenarios(options) {
3154
2794
  });
3155
2795
  generatedBaseStates = await loadGeneratedBaseStates(options.projectRoot);
3156
2796
  }
3157
- const runnerScenarios = scenarios.filter(
3158
- (scenario) => normalizeScenarioRunners(scenario.definition.runners).includes(
3159
- options.runner
3160
- )
3161
- );
3162
- if (runnerScenarios.length === 0) {
3163
- throw new Error(
3164
- `No scenarios found for runner '${options.runner}'. Add runners: ["${options.runner}"] to at least one scenario in test/scenarios/*.scenario.ts.`
3165
- );
3166
- }
3167
- let browserBridge = null;
3168
- let browserDriver = null;
3169
- if (options.runner === "browser") {
3170
- browserDriver = await loadBrowserDriver(options.projectRoot);
3171
- }
3172
2797
  let passed = 0;
3173
2798
  let failed = 0;
3174
2799
  const results = [];
3175
- for (const scenario of runnerScenarios) {
2800
+ for (const scenario of scenarios) {
3176
2801
  const base = basesById.get(scenario.definition.from);
3177
2802
  if (!base) {
3178
2803
  throw new Error(
@@ -3190,13 +2815,7 @@ async function runReducerNativeScenarios(options) {
3190
2815
  gameId: options.gameId
3191
2816
  })
3192
2817
  });
3193
- } else if (options.runner !== "reducer") {
3194
- throw new Error(
3195
- "Missing reducer-native generated base artifacts. Run 'dreamboard test' first."
3196
- );
3197
2818
  }
3198
- let scenarioBrowser = null;
3199
- let scenarioDevHost = null;
3200
2819
  try {
3201
2820
  const resolvedBase = resolveBaseDefinition(base, basesById);
3202
2821
  const effectiveSetup = resolveEffectiveBaseSetup({
@@ -3223,141 +2842,7 @@ async function runReducerNativeScenarios(options) {
3223
2842
  }
3224
2843
  shadow.hydrate(parentArtifact.snapshot, parentArtifact.version);
3225
2844
  }
3226
- let remote;
3227
- if (options.runner === "remote") {
3228
- const compiledResultId = options.compiledResultId ?? options.projectConfig.compile?.latestSuccessful?.resultId;
3229
- if (!compiledResultId) {
3230
- throw new Error(
3231
- "Remote runner requires a compiled result. Compile the workspace first."
3232
- );
3233
- }
3234
- const {
3235
- data: session,
3236
- error: sessionError,
3237
- response: sessionResponse
3238
- } = await createProjectSession({
3239
- path: { projectId: options.projectConfig.projectId },
3240
- body: {
3241
- compiledResultId,
3242
- seed: resolvedBase.seed,
3243
- playerCount: resolvedBase.players,
3244
- autoAssignSeats: true,
3245
- setupProfileId: effectiveSetup.setupProfileId ?? void 0
3246
- }
3247
- });
3248
- if (!session || sessionError) {
3249
- throw toDreamboardApiError(
3250
- sessionError,
3251
- sessionResponse,
3252
- "Failed to create remote-runner session."
3253
- );
3254
- }
3255
- const tracker = new RemoteGameplayTracker(
3256
- session.sessionId,
3257
- "player-1"
3258
- );
3259
- const { error: startError, response: startResponse } = await startGame({
3260
- path: { sessionId: session.sessionId }
3261
- });
3262
- if (startError) {
3263
- throw toDreamboardApiError(
3264
- startError,
3265
- startResponse,
3266
- "Failed to start remote-runner session."
3267
- );
3268
- }
3269
- await tracker.bootstrap();
3270
- remote = {
3271
- sessionId: session.sessionId,
3272
- tracker
3273
- };
3274
- }
3275
- if (options.runner === "browser") {
3276
- const compiledResultId = options.compiledResultId ?? options.projectConfig.compile?.latestSuccessful?.resultId;
3277
- if (!compiledResultId) {
3278
- throw new Error(
3279
- "Browser runner requires a compiled result. Compile the workspace first."
3280
- );
3281
- }
3282
- const {
3283
- data: session,
3284
- error: sessionError,
3285
- response: sessionResponse
3286
- } = await createProjectSession({
3287
- path: { projectId: options.projectConfig.projectId },
3288
- body: {
3289
- compiledResultId,
3290
- seed: resolvedBase.seed,
3291
- playerCount: resolvedBase.players,
3292
- autoAssignSeats: true,
3293
- setupProfileId: effectiveSetup.setupProfileId ?? void 0
3294
- }
3295
- });
3296
- if (!session || sessionError) {
3297
- throw toDreamboardApiError(
3298
- sessionError,
3299
- sessionResponse,
3300
- "Failed to create browser-runner session."
3301
- );
3302
- }
3303
- const { error: startError, data: started } = await startGame({
3304
- path: { sessionId: session.sessionId }
3305
- });
3306
- if (startError || !started) {
3307
- throw new Error("Failed to start browser-runner session.");
3308
- }
3309
- const devDir = path3.join(options.projectRoot, PROJECT_DIR_NAME, "dev");
3310
- await ensureDir(devDir);
3311
- const sessionFilePath = path3.join(devDir, "session.json");
3312
- await writeJsonFile(
3313
- sessionFilePath,
3314
- createPersistedDevSession({ sessionId: session.sessionId })
3315
- );
3316
- const devHostPlatform = createCliDevHostPlatform(
3317
- options.resolvedConfig
3318
- );
3319
- const bearer = await devHostPlatform.resolveBearer();
3320
- if (bearer.kind === "permanent_invalid") {
3321
- throw new Error(bearer.message);
3322
- }
3323
- const loadedDevHost = await loadProjectDevHost(options.projectRoot);
3324
- scenarioDevHost = await loadedDevHost.module.start(
3325
- {
3326
- projectRoot: options.projectRoot,
3327
- sessionFilePath,
3328
- apiBaseUrl: options.resolvedConfig.apiBaseUrl,
3329
- runtimeConfig: {
3330
- apiBaseUrl: options.resolvedConfig.apiBaseUrl,
3331
- userId: extractUserIdFromJwt(bearer.token),
3332
- gameId: options.projectConfig.gameId,
3333
- compiledResultId,
3334
- setupProfileId: effectiveSetup.setupProfileId ?? null,
3335
- playerCount: resolvedBase.players,
3336
- debug: options.debug ?? false,
3337
- slug: options.projectConfig.slug,
3338
- autoStartGame: false,
3339
- initialSession: {
3340
- sessionId: session.sessionId,
3341
- shortCode: started.context.shortCode,
3342
- gameId: options.projectConfig.gameId,
3343
- seed: resolvedBase.seed
3344
- }
3345
- }
3346
- },
3347
- devHostPlatform
3348
- );
3349
- const opened = await openBrowserPage(
3350
- scenarioDevHost.url,
3351
- options.resolvedConfig
3352
- );
3353
- scenarioBrowser = opened.browser;
3354
- const page = opened.page;
3355
- await waitForGameReady(page);
3356
- browserBridge = await createBrowserBridgeClient(page);
3357
- await browserDriver?.onReady?.(browserBridge);
3358
- }
3359
2845
  const context = await createScenarioContext({
3360
- runner: options.runner,
3361
2846
  shadow,
3362
2847
  expect: modules.createExpectApi({
3363
2848
  matchSnapshot: createScenarioSnapshotMatcher({
@@ -3365,12 +2850,7 @@ async function runReducerNativeScenarios(options) {
3365
2850
  scenarioId: scenario.definition.id,
3366
2851
  updateSnapshots: options.updateSnapshots ?? false
3367
2852
  })
3368
- }),
3369
- remote,
3370
- browser: options.runner === "browser" && browserBridge ? {
3371
- bridge: browserBridge,
3372
- driver: browserDriver
3373
- } : void 0
2853
+ })
3374
2854
  });
3375
2855
  await context.game.start();
3376
2856
  await base.definition.setup({
@@ -3409,13 +2889,6 @@ async function runReducerNativeScenarios(options) {
3409
2889
  }) : `Scenario '${scenario.definition.id}' failed.`
3410
2890
  });
3411
2891
  } finally {
3412
- browserBridge = null;
3413
- if (scenarioBrowser) {
3414
- await scenarioBrowser.close();
3415
- }
3416
- if (scenarioDevHost) {
3417
- await scenarioDevHost.close();
3418
- }
3419
2892
  }
3420
2893
  }
3421
2894
  return { passed, failed, results };
@@ -3438,4 +2911,4 @@ export {
3438
2911
  runReducerNativeScenarios,
3439
2912
  writeReducerNativeGeneratedFiles
3440
2913
  };
3441
- //# sourceMappingURL=reducer-native-test-harness-BY5SZ7XE.mjs.map
2914
+ //# sourceMappingURL=reducer-native-test-harness-UFMSNNDY.mjs.map