@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
package/dist/index.js CHANGED
@@ -8,28 +8,22 @@ import {
8
8
  STALE_CONTRACT_ARTIFACT_EXIT_CODE,
9
9
  buildClerkAuthorizationUrl,
10
10
  configureClient,
11
- createCliDevHostPlatform,
12
- createPersistedDevSession,
13
11
  createPkcePair,
14
12
  createSessionFromScenario,
15
13
  createUserTokenManager,
16
14
  didLocalMaintainerSnapshotChange,
17
15
  exchangeClerkOAuthCode,
18
16
  exchangeDreamboardUserToken,
19
- extractUserIdFromJwt,
20
- findProjectCompiledResultsForRevision,
21
17
  formatCliError,
22
18
  generateReducerNativeArtifacts,
23
19
  getAuthTokenExpiry,
24
20
  getCliErrorExitCode,
25
- getProjectCompiledResultSdk,
26
21
  importTypeScriptModule,
27
22
  isDreamboardApiError,
28
23
  isLocalMaintainerRegistryEnabled,
29
24
  isReducerNativeTestingWorkspace,
30
25
  isStaleContractArtifactError,
31
26
  isStaleContractArtifactMessage,
32
- loadProjectDevHost,
33
27
  normalizeSlug,
34
28
  parseAuthCommandArgs,
35
29
  parseBuildCommandArgs,
@@ -37,7 +31,6 @@ import {
37
31
  parseCommitScopedCommandArgs,
38
32
  parseConfigFlags,
39
33
  parseDevCommandArgs,
40
- parseDevSeed,
41
34
  parseNewCommandArgs,
42
35
  parsePlayerCountFlags,
43
36
  parsePositiveInt,
@@ -56,7 +49,7 @@ import {
56
49
  titleFromSlug,
57
50
  toDreamboardApiError,
58
51
  waitForCompiledResultJobSdk
59
- } from "./chunk-NFCRMXEV.js";
52
+ } from "./chunk-RTNKVNQA.js";
60
53
  import {
61
54
  applyWorkspaceCodegen,
62
55
  collectLocalFiles,
@@ -71,12 +64,9 @@ import {
71
64
  getApiVersion,
72
65
  getCurrentAuthUser,
73
66
  getCurrentProjectRelease,
74
- getProjectAuthoringState,
75
67
  getProjectBySlug,
76
68
  getProjectCommitStatus,
77
- getProjectCompileState,
78
69
  getProjectLocalMaintainerRegistry,
79
- getProjectPendingAuthoringSync,
80
70
  getProjectRepository,
81
71
  getSessionSnapshot,
82
72
  installFrozenWorkspaceDependencies,
@@ -94,7 +84,7 @@ import {
94
84
  updateProjectLocalMaintainerRegistry,
95
85
  updateProjectState,
96
86
  writeSnapshot
97
- } from "./chunk-QIVDPQME.js";
87
+ } from "./chunk-I4SZ7FA4.js";
98
88
  import {
99
89
  clearCredentials,
100
90
  getActiveCredentialBackendName,
@@ -1940,7 +1930,7 @@ password=${response.password}
1940
1930
  async function resolveGitCredential(input) {
1941
1931
  const protocol = input.request.protocol?.toLowerCase();
1942
1932
  const host = input.request.host?.toLowerCase();
1943
- const path10 = normalizeCredentialPath(input.request.path);
1933
+ const path11 = normalizeCredentialPath(input.request.path);
1944
1934
  const allowedHosts = new Set(
1945
1935
  input.policy.allowedHosts.map((value) => value.toLowerCase())
1946
1936
  );
@@ -1952,7 +1942,7 @@ async function resolveGitCredential(input) {
1952
1942
  if (!secureProtocol) {
1953
1943
  return null;
1954
1944
  }
1955
- if (!path10 || !pathPattern.test(path10)) {
1945
+ if (!path11 || !pathPattern.test(path11)) {
1956
1946
  return null;
1957
1947
  }
1958
1948
  const token = await input.tokenManager.resolveGitToken();
@@ -2957,9 +2947,63 @@ var build_default = defineCommand({
2957
2947
  });
2958
2948
 
2959
2949
  // src/commands/dev.ts
2960
- import path6 from "path";
2950
+ import path7 from "path";
2961
2951
  import { createHash } from "crypto";
2962
2952
 
2953
+ // src/utils/dev-session.ts
2954
+ import { randomInt } from "crypto";
2955
+ var DEFAULT_DEV_SEED = 1337;
2956
+ var MIN_KOTLIN_LONG = -9223372036854775808n;
2957
+ var MAX_KOTLIN_LONG = 9223372036854775807n;
2958
+ var MIN_SAFE_SEED = BigInt(Number.MIN_SAFE_INTEGER);
2959
+ var MAX_SAFE_SEED = BigInt(Number.MAX_SAFE_INTEGER);
2960
+ function createPersistedDevSession(input) {
2961
+ return {
2962
+ sessionId: input.sessionId
2963
+ };
2964
+ }
2965
+ function parseDevSeed(rawSeed) {
2966
+ return parseOptionalDevSeed(rawSeed) ?? DEFAULT_DEV_SEED;
2967
+ }
2968
+ function parseOptionalDevSeed(rawSeed) {
2969
+ const value = rawSeed?.trim();
2970
+ if (!value) {
2971
+ return void 0;
2972
+ }
2973
+ if (!/^-?\d+$/.test(value)) {
2974
+ throw new Error("seed must be an integer");
2975
+ }
2976
+ const parsed = BigInt(value);
2977
+ if (parsed < MIN_KOTLIN_LONG || parsed > MAX_KOTLIN_LONG) {
2978
+ throw new Error("seed must be within signed 64-bit integer range");
2979
+ }
2980
+ if (parsed < MIN_SAFE_SEED || parsed > MAX_SAFE_SEED) {
2981
+ throw new Error(
2982
+ `seed must be within JavaScript safe integer range (${Number.MIN_SAFE_INTEGER}..${Number.MAX_SAFE_INTEGER})`
2983
+ );
2984
+ }
2985
+ return Number(parsed);
2986
+ }
2987
+
2988
+ // src/utils/jwt.ts
2989
+ function extractUserIdFromJwt(token) {
2990
+ if (!token) {
2991
+ return null;
2992
+ }
2993
+ const parts = token.split(".");
2994
+ if (parts.length < 2) {
2995
+ return null;
2996
+ }
2997
+ try {
2998
+ const payload = JSON.parse(
2999
+ Buffer.from(parts[1], "base64url").toString("utf8")
3000
+ );
3001
+ return typeof payload.sub === "string" ? payload.sub : null;
3002
+ } catch {
3003
+ return null;
3004
+ }
3005
+ }
3006
+
2963
3007
  // src/utils/player-count.ts
2964
3008
  async function resolvePlayerCount(projectRoot, flags) {
2965
3009
  const rawPlayers = flags.players ?? flags["player-count"];
@@ -2976,6 +3020,79 @@ async function resolvePlayerCount(projectRoot, flags) {
2976
3020
  return Math.max(1, Math.floor(minPlayers));
2977
3021
  }
2978
3022
 
3023
+ // src/services/dev-host/loader.ts
3024
+ import path from "path";
3025
+ import { createRequire } from "module";
3026
+ import { pathToFileURL } from "url";
3027
+ async function loadProjectDevHost(projectRoot) {
3028
+ const requireFromProject = createRequire(path.join(projectRoot, "package.json"));
3029
+ let packageJsonPath;
3030
+ let entryPath;
3031
+ try {
3032
+ packageJsonPath = requireFromProject.resolve(
3033
+ "@dreamboard-games/dev-host/package.json"
3034
+ );
3035
+ entryPath = requireFromProject.resolve("@dreamboard-games/dev-host");
3036
+ } catch (error) {
3037
+ throw new Error(
3038
+ "Install @dreamboard-games/dev-host in this workspace before running dreamboard dev or browser tests.",
3039
+ { cause: error }
3040
+ );
3041
+ }
3042
+ const packageRoot = path.dirname(packageJsonPath);
3043
+ if (!isPathInside(packageRoot, entryPath)) {
3044
+ throw new Error(
3045
+ "@dreamboard-games/dev-host resolved outside its installed package."
3046
+ );
3047
+ }
3048
+ const packageJson = requireFromProject(packageJsonPath);
3049
+ if (packageJson.name !== "@dreamboard-games/dev-host" || typeof packageJson.version !== "string" || packageJson.version.length === 0) {
3050
+ throw new Error("Installed @dreamboard-games/dev-host metadata is invalid.");
3051
+ }
3052
+ const loaded = await import(pathToFileURL(entryPath).href);
3053
+ if (loaded.protocolVersion !== 1 || typeof loaded.start !== "function") {
3054
+ throw new Error(
3055
+ "Installed @dreamboard-games/dev-host does not expose DevHostModuleV1."
3056
+ );
3057
+ }
3058
+ return {
3059
+ packageRoot,
3060
+ packageVersion: packageJson.version,
3061
+ module: {
3062
+ protocolVersion: loaded.protocolVersion,
3063
+ start: loaded.start
3064
+ }
3065
+ };
3066
+ }
3067
+ function isPathInside(parent, candidate) {
3068
+ const relativePath = path.relative(parent, candidate);
3069
+ return relativePath === "" || !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
3070
+ }
3071
+
3072
+ // src/services/dev-host/platform.ts
3073
+ function createCliDevHostPlatform(config) {
3074
+ return {
3075
+ resolveBearer: () => resolveDevHostBearer(config)
3076
+ };
3077
+ }
3078
+ async function resolveDevHostBearer(config) {
3079
+ const localHarnessToken = resolveLocalHarnessAccessToken(config);
3080
+ if (localHarnessToken) {
3081
+ return { kind: "ok", token: localHarnessToken };
3082
+ }
3083
+ if (config.refreshTokenSource !== "global") {
3084
+ return { kind: "ok", token: config.authToken ?? null };
3085
+ }
3086
+ if (!config.refreshToken) {
3087
+ return {
3088
+ kind: "permanent_invalid",
3089
+ message: "Stored Dreamboard session is expired or invalid. Run `dreamboard auth login` to authenticate again."
3090
+ };
3091
+ }
3092
+ const resolved = await createUserTokenManager(config).resolveApiToken();
3093
+ return { kind: "ok", token: resolved?.token ?? null };
3094
+ }
3095
+
2979
3096
  // src/services/project/remote-project.ts
2980
3097
  async function resolveRemoteProject(options) {
2981
3098
  const identity = await loadRemoteProjectIdentity();
@@ -3005,8 +3122,8 @@ async function resolveRemoteProject(options) {
3005
3122
  // src/services/project/local-typecheck.ts
3006
3123
  import { spawn as spawn2 } from "child_process";
3007
3124
  import { lstat } from "fs/promises";
3008
- import { createRequire } from "module";
3009
- import path from "path";
3125
+ import { createRequire as createRequire2 } from "module";
3126
+ import path2 from "path";
3010
3127
  var TYPESCRIPT_BIN_PATH_SEGMENTS = [
3011
3128
  "node_modules",
3012
3129
  "typescript",
@@ -3016,17 +3133,17 @@ var TYPESCRIPT_BIN_PATH_SEGMENTS = [
3016
3133
  var CLI_PACKAGE_TYPESCRIPT_CLI = resolveCliPackageTypescriptCli();
3017
3134
  function resolveCliPackageTypescriptCli() {
3018
3135
  try {
3019
- const require2 = createRequire(import.meta.url);
3136
+ const require2 = createRequire2(import.meta.url);
3020
3137
  return require2.resolve("typescript/bin/tsc");
3021
3138
  } catch {
3022
3139
  return null;
3023
3140
  }
3024
3141
  }
3025
3142
  function getProjectNodeModules(projectRoot) {
3026
- return path.join(projectRoot, "node_modules");
3143
+ return path2.join(projectRoot, "node_modules");
3027
3144
  }
3028
3145
  function getProjectTypescriptCli(projectRoot) {
3029
- return path.join(projectRoot, ...TYPESCRIPT_BIN_PATH_SEGMENTS);
3146
+ return path2.join(projectRoot, ...TYPESCRIPT_BIN_PATH_SEGMENTS);
3030
3147
  }
3031
3148
  async function pathExists(targetPath) {
3032
3149
  try {
@@ -3146,12 +3263,12 @@ async function runLocalTypecheck(projectRoot) {
3146
3263
  // src/services/project/local-maintainer-registry.ts
3147
3264
  import { spawn as spawn3 } from "child_process";
3148
3265
  import { existsSync, readFileSync } from "fs";
3149
- import path2 from "path";
3266
+ import path3 from "path";
3150
3267
  import { fileURLToPath } from "url";
3151
- var MODULE_DIR = path2.dirname(fileURLToPath(import.meta.url));
3268
+ var MODULE_DIR = path3.dirname(fileURLToPath(import.meta.url));
3152
3269
  function getCliPackageRoot() {
3153
3270
  try {
3154
- return path2.join(
3271
+ return path3.join(
3155
3272
  resolveCliRepoRoot(import.meta.url),
3156
3273
  "apps",
3157
3274
  "dreamboard-cli"
@@ -3163,7 +3280,7 @@ function getCliPackageRoot() {
3163
3280
  function resolveInstalledCliPackageRoot(moduleDir) {
3164
3281
  let current = moduleDir;
3165
3282
  while (true) {
3166
- const packageJsonPath = path2.join(current, "package.json");
3283
+ const packageJsonPath = path3.join(current, "package.json");
3167
3284
  if (existsSync(packageJsonPath)) {
3168
3285
  try {
3169
3286
  const packageJson = JSON.parse(
@@ -3175,7 +3292,7 @@ function resolveInstalledCliPackageRoot(moduleDir) {
3175
3292
  } catch {
3176
3293
  }
3177
3294
  }
3178
- const parent = path2.dirname(current);
3295
+ const parent = path3.dirname(current);
3179
3296
  if (parent === current) {
3180
3297
  return moduleDir;
3181
3298
  }
@@ -3203,10 +3320,10 @@ function getScriptInvocation() {
3203
3320
  };
3204
3321
  }
3205
3322
  function getLocalMaintainerScriptPath(cliPackageRoot) {
3206
- return path2.join(cliPackageRoot, "scripts", "local-maintainer-registry.ts");
3323
+ return path3.join(cliPackageRoot, "scripts", "local-maintainer-registry.ts");
3207
3324
  }
3208
3325
  function isInstalledCliPackageRoot(cliPackageRoot) {
3209
- return cliPackageRoot.split(path2.sep).includes("node_modules");
3326
+ return cliPackageRoot.split(path3.sep).includes("node_modules");
3210
3327
  }
3211
3328
  function shouldSkipLocalMaintainerHelper() {
3212
3329
  const cliPackageRoot = getCliPackageRoot();
@@ -3233,7 +3350,7 @@ function readInstalledCliLocalMaintainerSnapshot() {
3233
3350
  if (!isInstalledCliPackageRoot(cliPackageRoot)) {
3234
3351
  return null;
3235
3352
  }
3236
- const packageJsonPath = path2.join(cliPackageRoot, "package.json");
3353
+ const packageJsonPath = path3.join(cliPackageRoot, "package.json");
3237
3354
  if (!existsSync(packageJsonPath)) {
3238
3355
  return null;
3239
3356
  }
@@ -3341,7 +3458,7 @@ async function ensureLocalMaintainerSnapshot(apiBaseUrl) {
3341
3458
  }
3342
3459
 
3343
3460
  // src/services/project/dependency-portability.ts
3344
- import path3 from "path";
3461
+ import path4 from "path";
3345
3462
  var DEPENDENCY_FIELDS = [
3346
3463
  "dependencies",
3347
3464
  "devDependencies",
@@ -3424,7 +3541,7 @@ async function assertReleaseEnvironmentPortableDependencies(options) {
3424
3541
  }
3425
3542
  async function readProjectPackageJson(projectRoot) {
3426
3543
  return readJsonFile(
3427
- path3.join(projectRoot, "package.json")
3544
+ path4.join(projectRoot, "package.json")
3428
3545
  );
3429
3546
  }
3430
3547
  function collectDreamboardPackageSpecifiers(packageJson) {
@@ -3523,7 +3640,7 @@ function isLocalRegistryUrl(rawUrl) {
3523
3640
  }
3524
3641
  }
3525
3642
  async function readDreamboardRegistryFromNpmrc(projectRoot) {
3526
- const npmrc = await readTextFileIfExists(path3.join(projectRoot, ".npmrc"));
3643
+ const npmrc = await readTextFileIfExists(path4.join(projectRoot, ".npmrc"));
3527
3644
  if (!npmrc) return void 0;
3528
3645
  for (const line of npmrc.split(/\r?\n/)) {
3529
3646
  const trimmed = line.trim();
@@ -3534,8 +3651,8 @@ async function readDreamboardRegistryFromNpmrc(projectRoot) {
3534
3651
  }
3535
3652
 
3536
3653
  // src/services/project/reducer-contract-preflight.ts
3537
- import path4 from "path";
3538
- var GAME_CONTRACT_ENTRY_PATH = path4.join("app", "game-contract.ts");
3654
+ import path5 from "path";
3655
+ var GAME_CONTRACT_ENTRY_PATH = path5.join("app", "game-contract.ts");
3539
3656
  function normalizeErrorMessage(error) {
3540
3657
  const rawMessage = error instanceof Error ? error.message : String(error ?? "Unknown error");
3541
3658
  return rawMessage.split("\n").map((line) => line.trim()).find(Boolean)?.replace(/^Error:\s*/u, "") ?? "Unknown error";
@@ -3544,7 +3661,7 @@ function isManifestScopedIdBrandingError(message) {
3544
3661
  return message.includes("defineGameContract:") && message.includes("manifest-scoped") && (message.includes("uses a raw z.string()") || message.includes("uses z.array(z.string())"));
3545
3662
  }
3546
3663
  async function assertReducerContractPreflight(projectRoot) {
3547
- const entryPath = path4.join(projectRoot, GAME_CONTRACT_ENTRY_PATH);
3664
+ const entryPath = path5.join(projectRoot, GAME_CONTRACT_ENTRY_PATH);
3548
3665
  try {
3549
3666
  await importTypeScriptModule(entryPath);
3550
3667
  } catch (error) {
@@ -3570,11 +3687,11 @@ async function assertReducerContractPreflight(projectRoot) {
3570
3687
  }
3571
3688
 
3572
3689
  // src/services/project/reducer-bundle-preflight.ts
3573
- import path5 from "path";
3574
- import { createRequire as createRequire2 } from "module";
3575
- import { pathToFileURL } from "url";
3690
+ import path6 from "path";
3691
+ import { createRequire as createRequire3 } from "module";
3692
+ import { pathToFileURL as pathToFileURL2 } from "url";
3576
3693
  globalThis.__DREAMBOARD_AUTHORING_WARNINGS__ = true;
3577
- var REDUCER_BUNDLE_ENTRY_PATH = path5.join("app", "index.ts");
3694
+ var REDUCER_BUNDLE_ENTRY_PATH = path6.join("app", "index.ts");
3578
3695
  var PREFLIGHT_RNG_SEED = 1337;
3579
3696
  function isStructuralPerPlayer(value) {
3580
3697
  return typeof value === "object" && value !== null && value.__perPlayer === true && Array.isArray(value.entries);
@@ -3587,8 +3704,8 @@ function fallbackPerPlayerSchema(valueSchema, options) {
3587
3704
  }).strict();
3588
3705
  }
3589
3706
  async function loadProjectReducerPreflightModules(projectRoot) {
3590
- const requireFromProject = createRequire2(
3591
- path5.join(projectRoot, "package.json")
3707
+ const requireFromProject = createRequire3(
3708
+ path6.join(projectRoot, "package.json")
3592
3709
  );
3593
3710
  const reducerPath = requireFromProject.resolve(
3594
3711
  "@dreamboard-games/sdk/reducer"
@@ -3597,8 +3714,8 @@ async function loadProjectReducerPreflightModules(projectRoot) {
3597
3714
  "@dreamboard-games/sdk/reducer-contract"
3598
3715
  );
3599
3716
  const [reducerModule, reducerContractModule] = await Promise.all([
3600
- import(pathToFileURL(reducerPath).href),
3601
- import(pathToFileURL(reducerContractPath).href)
3717
+ import(pathToFileURL2(reducerPath).href),
3718
+ import(pathToFileURL2(reducerContractPath).href)
3602
3719
  ]);
3603
3720
  if (typeof reducerModule.isPerPlayer !== "function" || typeof reducerModule.perPlayerSchema !== "function" || typeof reducerContractModule.materializeManifestTable !== "function") {
3604
3721
  throw new Error(
@@ -3811,7 +3928,7 @@ async function runReducerBundleSmoke(options) {
3811
3928
  if (scenarios.length === 0) {
3812
3929
  return [];
3813
3930
  }
3814
- const entryPath = path5.join(projectRoot, REDUCER_BUNDLE_ENTRY_PATH);
3931
+ const entryPath = path6.join(projectRoot, REDUCER_BUNDLE_ENTRY_PATH);
3815
3932
  let module;
3816
3933
  try {
3817
3934
  module = await importTypeScriptModule(
@@ -4063,9 +4180,9 @@ var dev_default = defineCommand({
4063
4180
  env: parsedArgs.env ?? "local",
4064
4181
  debug: parsedArgs.debug
4065
4182
  });
4066
- const devDir = path6.join(projectRoot, PROJECT_DIR_NAME, "dev");
4183
+ const devDir = path7.join(projectRoot, PROJECT_DIR_NAME, "dev");
4067
4184
  await ensureDir(devDir);
4068
- const sessionFilePath = path6.join(devDir, "session.json");
4185
+ const sessionFilePath = path7.join(devDir, "session.json");
4069
4186
  const requestedResumeSessionId = parsedArgs.resume?.trim() || null;
4070
4187
  const requestedScenarioId = parsedArgs["from-scenario"]?.trim() || null;
4071
4188
  if (requestedResumeSessionId && parsedArgs["new-session"]) {
@@ -4446,7 +4563,7 @@ async function resolveBackendVersionMetadata() {
4446
4563
  }
4447
4564
  async function readWorkspacePackageJson(projectRoot) {
4448
4565
  try {
4449
- const raw = await readTextFile(path6.join(projectRoot, "package.json"));
4566
+ const raw = await readTextFile(path7.join(projectRoot, "package.json"));
4450
4567
  const parsed = JSON.parse(raw);
4451
4568
  return {
4452
4569
  dependencies: Object.fromEntries(
@@ -4607,7 +4724,7 @@ var preview_default = defineCommand({
4607
4724
  });
4608
4725
 
4609
4726
  // src/commands/project-create.ts
4610
- import path7 from "path";
4727
+ import path8 from "path";
4611
4728
 
4612
4729
  // src/services/git/workspace-origin.ts
4613
4730
  var DREAMBOARD_GIT_CREDENTIAL_HELPER = "!dreamboard auth git-credential";
@@ -4777,7 +4894,7 @@ var project_create_default = defineCommand({
4777
4894
  setupProfiles: []
4778
4895
  };
4779
4896
  consola.start("Scaffolding local workspace...");
4780
- const targetDir = path7.resolve(process.cwd(), project.slug);
4897
+ const targetDir = path8.resolve(process.cwd(), project.slug);
4781
4898
  await materializeWorkspaceProject({
4782
4899
  targetDir,
4783
4900
  projectId,
@@ -4806,7 +4923,7 @@ var project_create_default = defineCommand({
4806
4923
 
4807
4924
  // src/commands/project-clone.ts
4808
4925
  import { mkdtemp, rename, rm } from "fs/promises";
4809
- import path8 from "path";
4926
+ import path9 from "path";
4810
4927
  var DEFAULT_REPOSITORY_WAIT_TIMEOUT_MS2 = 12e4;
4811
4928
  var DEFAULT_REPOSITORY_POLL_INTERVAL_MS2 = 1e3;
4812
4929
  function parsePositiveIntegerFlag2(value, flagName, defaultValue) {
@@ -4872,7 +4989,7 @@ var project_clone_default = defineCommand({
4872
4989
  requireAuth(config);
4873
4990
  await configureClient(config);
4874
4991
  const identity = await loadRemoteProjectIdentity();
4875
- const targetDir = path8.resolve(process.cwd(), targetSlug);
4992
+ const targetDir = path9.resolve(process.cwd(), targetSlug);
4876
4993
  if (await exists(targetDir)) {
4877
4994
  throw new Error(`Target directory already exists: ${targetDir}`);
4878
4995
  }
@@ -4896,9 +5013,9 @@ var project_clone_default = defineCommand({
4896
5013
  error.name = "PROJECT_UNINITIALIZED";
4897
5014
  throw error;
4898
5015
  }
4899
- const parentDir = path8.dirname(targetDir);
5016
+ const parentDir = path9.dirname(targetDir);
4900
5017
  const tempDir = await mkdtemp(
4901
- path8.join(parentDir, `.${path8.basename(targetDir)}.dreamboard-clone-`)
5018
+ path9.join(parentDir, `.${path9.basename(targetDir)}.dreamboard-clone-`)
4902
5019
  );
4903
5020
  let renamed = false;
4904
5021
  try {
@@ -5336,56 +5453,148 @@ var release_default = defineCommand({
5336
5453
  }
5337
5454
  });
5338
5455
 
5339
- // src/services/testing/runtime-mode.ts
5340
- function isRemoteTestEnvironment(environment) {
5341
- return environment === "staging" || environment === "prod";
5342
- }
5343
- function shouldUseRemoteTestRuntime(environment) {
5344
- return IS_PUBLISHED_BUILD || isRemoteTestEnvironment(environment);
5456
+ // src/commands/test.ts
5457
+ var REDUCER_NATIVE_TEST_WORKSPACE_ERROR = "dreamboard test now requires a reducer-native workspace with app/game.ts, shared/generated/ui-contract.ts, test/bases/*.base.ts, and test/scenarios/*.scenario.ts. Legacy test/base-scenarios.json workspaces are no longer supported.";
5458
+ var NO_REDUCER_NATIVE_BASES_FOUND_ERROR = "No bases found under test/bases/*.base.ts";
5459
+ var NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR = "No scenarios found under test/scenarios/*.scenario.ts";
5460
+ function resolveTestCommandPlan(args) {
5461
+ const updateSnapshots = Boolean(args["update-snapshots"]);
5462
+ return {
5463
+ updateSnapshots
5464
+ };
5345
5465
  }
5346
-
5347
- // src/services/workflows/resolve-latest-compiled-result.ts
5348
- async function resolveLatestCompiledResult(projectRoot, projectConfig) {
5349
- void projectRoot;
5350
- const authoring = getProjectAuthoringState(projectConfig);
5351
- if (getProjectPendingAuthoringSync(projectConfig)) {
5352
- throw new Error(
5353
- "Previous source preparation did not finish updating local scaffold files. Recreate or reclone the project workspace first."
5354
- );
5355
- }
5356
- if (authoring.revisionDigest) {
5357
- const compile = getProjectCompileState(projectConfig);
5358
- const latestSuccess = (await findProjectCompiledResultsForRevision({
5359
- projectId: projectConfig.projectId,
5360
- revisionDigest: authoring.revisionDigest
5361
- })).find((result) => result.success);
5362
- const matchingLocalSuccess = compile.latestSuccessful?.revisionDigest === authoring.revisionDigest ? compile.latestSuccessful : void 0;
5363
- const resolvedSuccess = latestSuccess ?? (matchingLocalSuccess?.resultId ? await getProjectCompiledResultSdk(
5364
- projectConfig.projectId,
5365
- matchingLocalSuccess.resultId
5366
- ) : void 0);
5367
- if (!resolvedSuccess?.success) {
5466
+ function assertNoRemovedTestFlags(argv2) {
5467
+ for (let index = 0; index < argv2.length; index += 1) {
5468
+ const arg = argv2[index];
5469
+ if (arg === void 0) {
5470
+ continue;
5471
+ }
5472
+ if (arg === "--runner" || arg.startsWith("--runner=")) {
5368
5473
  throw new Error(
5369
- "No successful compile exists for the current authored revision. Build the exact commit with dreamboard build --commit <rev>, or run remote tests with --commit."
5474
+ "dreamboard test no longer supports --runner. The public CLI runs offline reducer tests only."
5370
5475
  );
5371
5476
  }
5372
- const resultRevisionDigest = resolvedSuccess.revisionDigest;
5373
- if (resultRevisionDigest && resultRevisionDigest !== authoring.revisionDigest) {
5374
- consola.warn(
5375
- `Latest successful compile ${resolvedSuccess.id} belongs to ${resultRevisionDigest}, not ${authoring.revisionDigest}.`
5477
+ if (arg === "--commit" || arg.startsWith("--commit=")) {
5478
+ throw new Error(
5479
+ "dreamboard test no longer supports --commit. Use dreamboard verify/build/preview/release with --commit for pushed-commit workflows."
5376
5480
  );
5377
5481
  }
5378
- consola.info(
5379
- `Project summary:
5380
- compiledResultId: ${resolvedSuccess.id}
5381
- revisionDigest: ${authoring.revisionDigest}`
5382
- );
5383
- return resolvedSuccess;
5384
5482
  }
5385
- throw new Error(
5386
- "This workspace does not know its project revision yet. Use an exact pushed commit with --commit."
5483
+ }
5484
+ function isStaleContractArtifactResult(result) {
5485
+ return result.errorCode === STALE_CONTRACT_ARTIFACT_CODE || (result.error ? isStaleContractArtifactMessage(result.error) : false);
5486
+ }
5487
+ function resolveTestRunExitCode(summary) {
5488
+ if (summary.failed === 0) {
5489
+ return 0;
5490
+ }
5491
+ return summary.results.some(
5492
+ (result) => !result.success && isStaleContractArtifactResult(result)
5493
+ ) ? STALE_CONTRACT_ARTIFACT_EXIT_CODE : 1;
5494
+ }
5495
+ async function assertReducerNativeTestingWorkspace(projectRoot) {
5496
+ if (await isReducerNativeTestingWorkspace(projectRoot)) {
5497
+ return;
5498
+ }
5499
+ throw new Error(REDUCER_NATIVE_TEST_WORKSPACE_ERROR);
5500
+ }
5501
+ async function runTestCommand(args, deps = {}) {
5502
+ const parsedFlags = parseConfigFlags(args);
5503
+ const plan = resolveTestCommandPlan(args);
5504
+ const { projectRoot, projectConfig, config } = await (deps.resolveProjectContext ?? resolveProjectContext)(parsedFlags, {
5505
+ requireAuth: false
5506
+ });
5507
+ await (deps.assertPortableDependencies ?? assertReleaseEnvironmentPortableDependencies)({
5508
+ projectRoot,
5509
+ projectConfig,
5510
+ environment: config.environment
5511
+ });
5512
+ await (deps.assertTestingWorkspace ?? assertReducerNativeTestingWorkspace)(
5513
+ projectRoot
5387
5514
  );
5515
+ const generated = await (deps.generateArtifacts ?? generateReducerNativeArtifacts)({
5516
+ projectRoot,
5517
+ scenarioPath: args.scenario,
5518
+ compiledResultId: projectConfig.compile?.latestSuccessful?.resultId,
5519
+ gameId: projectConfig.gameId,
5520
+ debug: Boolean(args.debug)
5521
+ });
5522
+ if (generated.bases.length === 0) {
5523
+ throw new Error(NO_REDUCER_NATIVE_BASES_FOUND_ERROR);
5524
+ }
5525
+ if (generated.scenarios.length === 0) {
5526
+ throw new Error(NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR);
5527
+ }
5528
+ const summary = await (deps.runScenarios ?? runReducerNativeScenarios)({
5529
+ projectRoot,
5530
+ projectConfig,
5531
+ resolvedConfig: config,
5532
+ scenarioPath: args.scenario,
5533
+ compiledResultId: projectConfig.compile?.latestSuccessful?.resultId,
5534
+ gameId: projectConfig.gameId,
5535
+ debug: Boolean(args.debug),
5536
+ updateSnapshots: plan.updateSnapshots
5537
+ });
5538
+ printTestSummary(summary);
5388
5539
  }
5540
+ function printTestSummary(summary) {
5541
+ for (const result of summary.results) {
5542
+ if (result.success) {
5543
+ consola.success(`PASS ${result.id}`);
5544
+ } else if (result.errorCode === STALE_CONTRACT_ARTIFACT_CODE && result.error) {
5545
+ consola.error(result.error);
5546
+ } else {
5547
+ consola.error(`FAIL ${result.id}: ${result.error ?? "Scenario failed"}`);
5548
+ }
5549
+ }
5550
+ consola.info(
5551
+ `Test summary: ${summary.passed} passed, ${summary.failed} failed.`
5552
+ );
5553
+ if (summary.failed > 0) {
5554
+ process.exitCode = resolveTestRunExitCode(summary);
5555
+ }
5556
+ }
5557
+ var runCommand2 = defineCommand({
5558
+ meta: {
5559
+ name: "run",
5560
+ description: "Run reducer-native scenarios from test/scenarios"
5561
+ },
5562
+ args: {
5563
+ scenario: {
5564
+ type: "string",
5565
+ description: "Optional scenario file path under test/scenarios"
5566
+ },
5567
+ debug: {
5568
+ type: "boolean",
5569
+ description: "Print full reducer-native validation details",
5570
+ default: false
5571
+ },
5572
+ "update-snapshots": {
5573
+ type: "boolean",
5574
+ description: "Refresh generated projection and scenario snapshots",
5575
+ default: false
5576
+ },
5577
+ ...CONFIG_FLAG_ARGS
5578
+ },
5579
+ async run({ args }) {
5580
+ assertNoRemovedTestFlags(process.argv.slice(2));
5581
+ await runTestCommand(args);
5582
+ }
5583
+ });
5584
+ var test_default = defineCommand({
5585
+ meta: {
5586
+ name: "test",
5587
+ description: "Reducer-native test runner with typed bases and scenarios"
5588
+ },
5589
+ args: runCommand2.args,
5590
+ async run(context) {
5591
+ await runCommand2.run?.(context);
5592
+ }
5593
+ });
5594
+
5595
+ // src/commands/verify.ts
5596
+ import { execFile as execFile2 } from "child_process";
5597
+ import { promisify as promisify2 } from "util";
5389
5598
 
5390
5599
  // src/services/verification/exact-commit-verifier.ts
5391
5600
  import { spawn as spawn4 } from "child_process";
@@ -5393,7 +5602,7 @@ import { createHash as createHash2 } from "crypto";
5393
5602
  import { existsSync as existsSync2 } from "fs";
5394
5603
  import { mkdtemp as mkdtemp2, readFile, rm as rm2 } from "fs/promises";
5395
5604
  import os from "os";
5396
- import path9 from "path";
5605
+ import path10 from "path";
5397
5606
  var ALLOWED_DREAMBOARD_TRACKED_PATHS = /* @__PURE__ */ new Set([".dreamboard/project.json"]);
5398
5607
  var CREDENTIAL_BASENAMES = /* @__PURE__ */ new Set([
5399
5608
  ".env",
@@ -5476,7 +5685,6 @@ async function runExactCommitVerification(options, deps = {}) {
5476
5685
  projectRoot: worktreeRoot,
5477
5686
  projectConfig,
5478
5687
  resolvedConfig: options.config,
5479
- runner: "reducer",
5480
5688
  gameId: runtimeIdentity.gameId,
5481
5689
  compiledResultId: runtimeIdentity.compiledResultId
5482
5690
  });
@@ -5508,8 +5716,8 @@ async function runExactCommitVerification(options, deps = {}) {
5508
5716
  }
5509
5717
  async function withExactCommitWorktree(options, run, deps = {}) {
5510
5718
  const git = deps.git ?? new SystemGit();
5511
- const tempRoot = await deps.makeTempDir?.() ?? await mkdtemp2(path9.join(os.tmpdir(), "dreamboard-verify-"));
5512
- const worktreeRoot = path9.join(tempRoot, "worktree");
5719
+ const tempRoot = await deps.makeTempDir?.() ?? await mkdtemp2(path10.join(os.tmpdir(), "dreamboard-verify-"));
5720
+ const worktreeRoot = path10.join(tempRoot, "worktree");
5513
5721
  let worktreeCreated = false;
5514
5722
  try {
5515
5723
  await git.createDetachedWorktree(
@@ -5625,7 +5833,7 @@ async function assertExactCommitSourcePolicy(options) {
5625
5833
  }
5626
5834
  }
5627
5835
  async function readGitTree(root, commitOid) {
5628
- const { stdout } = await runCommand2(
5836
+ const { stdout } = await runCommand3(
5629
5837
  "git",
5630
5838
  ["ls-tree", "-r", "-z", "--full-tree", commitOid],
5631
5839
  root
@@ -5647,7 +5855,7 @@ function parseGitTree(output) {
5647
5855
  });
5648
5856
  }
5649
5857
  async function runFrozenNoScriptsInstall(root) {
5650
- await runCommand2(
5858
+ await runCommand3(
5651
5859
  resolvePnpmCommand(),
5652
5860
  [
5653
5861
  "install",
@@ -5660,11 +5868,11 @@ async function runFrozenNoScriptsInstall(root) {
5660
5868
  );
5661
5869
  }
5662
5870
  function resolvePnpmCommand() {
5663
- const corepackPath = path9.join(path9.dirname(process.execPath), "corepack");
5871
+ const corepackPath = path10.join(path10.dirname(process.execPath), "corepack");
5664
5872
  return existsSync2(corepackPath) ? corepackPath : "pnpm";
5665
5873
  }
5666
- async function runCommand2(command, args, cwd) {
5667
- const finalArgs = path9.basename(command) === "corepack" ? ["pnpm", ...args] : [...args];
5874
+ async function runCommand3(command, args, cwd) {
5875
+ const finalArgs = path10.basename(command) === "corepack" ? ["pnpm", ...args] : [...args];
5668
5876
  return new Promise((resolve, reject) => {
5669
5877
  const child = spawn4(command, finalArgs, {
5670
5878
  cwd,
@@ -5698,12 +5906,12 @@ async function runCommand2(command, args, cwd) {
5698
5906
  });
5699
5907
  }
5700
5908
  async function readPolicyFileFromDisk(root, relativePath) {
5701
- return readFile(path9.join(root, relativePath));
5909
+ return readFile(path10.join(root, relativePath));
5702
5910
  }
5703
5911
  function normalizeTreePath(filePath) {
5704
5912
  if (filePath.includes("\\")) return null;
5705
- const normalized = path9.posix.normalize(filePath);
5706
- if (normalized === "." || normalized.startsWith("../") || path9.posix.isAbsolute(normalized)) {
5913
+ const normalized = path10.posix.normalize(filePath);
5914
+ if (normalized === "." || normalized.startsWith("../") || path10.posix.isAbsolute(normalized)) {
5707
5915
  return null;
5708
5916
  }
5709
5917
  return normalized;
@@ -5715,275 +5923,16 @@ function isForbiddenDreamboardStatePath(filePath) {
5715
5923
  return filePath.startsWith(".dreamboard/") && !ALLOWED_DREAMBOARD_TRACKED_PATHS.has(filePath);
5716
5924
  }
5717
5925
  function isCredentialLikePath(filePath) {
5718
- const basename = path9.posix.basename(filePath);
5926
+ const basename = path10.posix.basename(filePath);
5719
5927
  if (CREDENTIAL_BASENAMES.has(basename)) return true;
5720
- if (CREDENTIAL_EXTENSIONS.has(path9.posix.extname(basename))) return true;
5928
+ if (CREDENTIAL_EXTENSIONS.has(path10.posix.extname(basename))) return true;
5721
5929
  return filePath.startsWith(".dreamboard-dev/deploy-secrets/");
5722
5930
  }
5723
5931
  function hasCredentialLikeContent(prefix) {
5724
5932
  return /-----BEGIN [A-Z ]*PRIVATE KEY-----/.test(prefix) || /_authToken\s*=/i.test(prefix) || /(?:^|\n)\s*(?:npm_token|authToken|password|secret)\s*=/i.test(prefix);
5725
5933
  }
5726
5934
 
5727
- // src/commands/test.ts
5728
- var REDUCER_NATIVE_TEST_WORKSPACE_ERROR = "dreamboard test now requires a reducer-native workspace with app/game.ts, shared/generated/ui-contract.ts, test/bases/*.base.ts, and test/scenarios/*.scenario.ts. Legacy test/base-scenarios.json workspaces are no longer supported.";
5729
- var NO_REDUCER_NATIVE_BASES_FOUND_ERROR = "No bases found under test/bases/*.base.ts";
5730
- var NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR = "No scenarios found under test/scenarios/*.scenario.ts";
5731
- function resolveRequestedRunner(value) {
5732
- if (value == null || value === "") {
5733
- return void 0;
5734
- }
5735
- if (value === "reducer" || value === "remote" || value === "browser") {
5736
- return value;
5737
- }
5738
- throw new Error(
5739
- `Unsupported test runner '${String(value)}'. Expected one of reducer, remote, browser.`
5740
- );
5741
- }
5742
- function resolveTestCommandPlan(args) {
5743
- const runner = resolveRequestedRunner(args.runner) ?? "reducer";
5744
- const commit = typeof args.commit === "string" && args.commit.trim().length > 0 ? args.commit : void 0;
5745
- const updateSnapshots = Boolean(args["update-snapshots"]);
5746
- if (runner === "remote" && !commit) {
5747
- throw new Error("dreamboard test --runner remote requires --commit <rev>.");
5748
- }
5749
- if (commit && runner !== "remote" && runner !== "browser") {
5750
- throw new Error(
5751
- "dreamboard test --commit is only valid with --runner remote or --runner browser."
5752
- );
5753
- }
5754
- if (updateSnapshots && (runner === "remote" || commit)) {
5755
- throw new Error(
5756
- "dreamboard test --update-snapshots is only valid for current-worktree reducer or browser tests."
5757
- );
5758
- }
5759
- return {
5760
- runner,
5761
- commit,
5762
- updateSnapshots
5763
- };
5764
- }
5765
- function isStaleContractArtifactResult(result) {
5766
- return result.errorCode === STALE_CONTRACT_ARTIFACT_CODE || (result.error ? isStaleContractArtifactMessage(result.error) : false);
5767
- }
5768
- function resolveTestRunExitCode(summary) {
5769
- if (summary.failed === 0) {
5770
- return 0;
5771
- }
5772
- return summary.results.some(
5773
- (result) => !result.success && isStaleContractArtifactResult(result)
5774
- ) ? STALE_CONTRACT_ARTIFACT_EXIT_CODE : 1;
5775
- }
5776
- async function assertReducerNativeTestingWorkspace(projectRoot) {
5777
- if (await isReducerNativeTestingWorkspace(projectRoot)) {
5778
- return;
5779
- }
5780
- throw new Error(REDUCER_NATIVE_TEST_WORKSPACE_ERROR);
5781
- }
5782
- function assertRemoteCommitReady(status) {
5783
- if (!status.source.observed) {
5784
- throw new Error(
5785
- `Remote commit tests require pushed commit ${status.commitOid}. Push the commit, then run dreamboard project status --commit ${status.commitOid} --wait.`
5786
- );
5787
- }
5788
- if (status.source.validationStatus !== "SUCCEEDED") {
5789
- throw new Error(
5790
- `Remote commit tests require source validation to succeed for ${status.commitOid}; current status is ${status.source.validationStatus ?? "UNKNOWN"}.`
5791
- );
5792
- }
5793
- const revisionDigest = status.gameRevision.revisionDigest;
5794
- if (!revisionDigest) {
5795
- throw new Error(
5796
- `Remote commit tests require a materialized game revision for ${status.commitOid}. Run dreamboard project status --commit ${status.commitOid} --wait and retry after validation completes.`
5797
- );
5798
- }
5799
- return revisionDigest;
5800
- }
5801
- async function resolveRemoteCommitCompiledResult(options) {
5802
- const revisionDigest = assertRemoteCommitReady(options.status);
5803
- const previewBuild = options.status.builds.find(
5804
- (build) => build.targetProfile === "preview" && build.compiledArtifactStatus === "SUCCEEDED" && typeof build.compiledArtifactId === "string" && build.compiledArtifactId.length > 0
5805
- );
5806
- if (previewBuild?.compiledArtifactId) {
5807
- return { id: previewBuild.compiledArtifactId };
5808
- }
5809
- const compiledResults = await (options.findCompiledResultsForRevision ?? findProjectCompiledResultsForRevision)({
5810
- projectId: options.projectId,
5811
- revisionDigest
5812
- });
5813
- const compiledResult = compiledResults.find((result) => result.success);
5814
- if (!compiledResult) {
5815
- throw new Error(
5816
- `Remote commit tests require a successful compiled result for commit ${options.status.commitOid} (revision ${revisionDigest}). Run dreamboard build --commit ${options.status.commitOid}, wait for it to succeed, and retry.`
5817
- );
5818
- }
5819
- return compiledResult;
5820
- }
5821
- async function resolveReducerNativeRuntimeIdentity(options) {
5822
- if (options.useRemoteRuntime || options.runner === "remote") {
5823
- const latestCompiledResult = await resolveLatestCompiledResult(
5824
- options.projectRoot,
5825
- options.projectConfig
5826
- );
5827
- return {
5828
- gameId: options.projectConfig.gameId,
5829
- compiledResultId: latestCompiledResult.id
5830
- };
5831
- }
5832
- return {
5833
- gameId: options.projectConfig.gameId,
5834
- compiledResultId: options.projectConfig.compile?.latestSuccessful?.resultId
5835
- };
5836
- }
5837
- async function runTestCommand(args, deps = {}) {
5838
- const parsedFlags = parseConfigFlags(args);
5839
- const plan = resolveTestCommandPlan(args);
5840
- const useRemoteRuntime = shouldUseRemoteTestRuntime(parsedFlags.env);
5841
- if (plan.commit) {
5842
- const { projectRoot: projectRoot2, config: config2, commitOid } = await (deps.resolveCommitScopedProjectContext ?? resolveCommitScopedProjectContext)(parsedFlags, plan.commit, { requireAuth: true });
5843
- await (deps.withExactCommitWorktree ?? withExactCommitWorktree)(
5844
- {
5845
- projectRoot: projectRoot2,
5846
- commitOid
5847
- },
5848
- async (worktreeRoot) => {
5849
- const prepared = await (deps.prepareExactCommitWorkspace ?? prepareExactCommitWorkspace)({
5850
- worktreeRoot
5851
- });
5852
- const status = await (deps.getProjectCommitStatus ?? getProjectCommitStatusSdk)({
5853
- projectId: prepared.projectConfig.projectId,
5854
- commitOid
5855
- });
5856
- const compiledResult = await resolveRemoteCommitCompiledResult({
5857
- projectId: prepared.projectConfig.projectId,
5858
- status,
5859
- findCompiledResultsForRevision: deps.findCompiledResultsForRevision
5860
- });
5861
- await (deps.assertTestingWorkspace ?? assertReducerNativeTestingWorkspace)(worktreeRoot);
5862
- const generated = await (deps.generateArtifacts ?? generateReducerNativeArtifacts)({
5863
- projectRoot: worktreeRoot,
5864
- scenarioPath: args.scenario,
5865
- compiledResultId: compiledResult.id,
5866
- gameId: prepared.projectConfig.gameId,
5867
- debug: Boolean(args.debug)
5868
- });
5869
- if (generated.bases.length === 0) {
5870
- throw new Error(NO_REDUCER_NATIVE_BASES_FOUND_ERROR);
5871
- }
5872
- if (generated.scenarios.length === 0) {
5873
- throw new Error(NO_REDUCER_NATIVE_SCENARIOS_FOUND_ERROR);
5874
- }
5875
- const summary2 = await (deps.runScenarios ?? runReducerNativeScenarios)({
5876
- projectRoot: worktreeRoot,
5877
- projectConfig: prepared.projectConfig,
5878
- resolvedConfig: config2,
5879
- runner: plan.runner,
5880
- scenarioPath: args.scenario,
5881
- compiledResultId: compiledResult.id,
5882
- gameId: prepared.projectConfig.gameId,
5883
- debug: Boolean(args.debug),
5884
- updateSnapshots: false
5885
- });
5886
- printTestSummary(summary2);
5887
- }
5888
- );
5889
- return;
5890
- }
5891
- const { projectRoot, projectConfig, config } = await (deps.resolveProjectContext ?? resolveProjectContext)(parsedFlags, {
5892
- requireAuth: useRemoteRuntime || plan.runner === "remote"
5893
- });
5894
- await (deps.assertPortableDependencies ?? assertReleaseEnvironmentPortableDependencies)({
5895
- projectRoot,
5896
- projectConfig,
5897
- environment: config.environment
5898
- });
5899
- await (deps.assertTestingWorkspace ?? assertReducerNativeTestingWorkspace)(
5900
- projectRoot
5901
- );
5902
- const runtimeIdentity = await (deps.resolveRuntimeIdentity ?? resolveReducerNativeRuntimeIdentity)({
5903
- projectRoot,
5904
- projectConfig,
5905
- useRemoteRuntime,
5906
- runner: plan.runner
5907
- });
5908
- const summary = await (deps.runScenarios ?? runReducerNativeScenarios)({
5909
- projectRoot,
5910
- projectConfig,
5911
- resolvedConfig: config,
5912
- runner: plan.runner,
5913
- scenarioPath: args.scenario,
5914
- compiledResultId: runtimeIdentity.compiledResultId,
5915
- gameId: runtimeIdentity.gameId,
5916
- debug: Boolean(args.debug),
5917
- updateSnapshots: plan.updateSnapshots
5918
- });
5919
- printTestSummary(summary);
5920
- }
5921
- function printTestSummary(summary) {
5922
- for (const result of summary.results) {
5923
- if (result.success) {
5924
- consola.success(`PASS ${result.id}`);
5925
- } else if (result.errorCode === STALE_CONTRACT_ARTIFACT_CODE && result.error) {
5926
- consola.error(result.error);
5927
- } else {
5928
- consola.error(`FAIL ${result.id}: ${result.error ?? "Scenario failed"}`);
5929
- }
5930
- }
5931
- consola.info(
5932
- `Test summary: ${summary.passed} passed, ${summary.failed} failed.`
5933
- );
5934
- if (summary.failed > 0) {
5935
- process.exitCode = resolveTestRunExitCode(summary);
5936
- }
5937
- }
5938
- var runCommand3 = defineCommand({
5939
- meta: {
5940
- name: "run",
5941
- description: "Run reducer-native scenarios from test/scenarios"
5942
- },
5943
- args: {
5944
- scenario: {
5945
- type: "string",
5946
- description: "Optional scenario file path under test/scenarios"
5947
- },
5948
- debug: {
5949
- type: "boolean",
5950
- description: "Print full reducer-native validation details",
5951
- default: false
5952
- },
5953
- "update-snapshots": {
5954
- type: "boolean",
5955
- description: "Refresh generated projection and scenario snapshots",
5956
- default: false
5957
- },
5958
- runner: {
5959
- type: "string",
5960
- valueHint: "reducer|remote|browser",
5961
- description: "Scenario runner: reducer (in-process, default), remote (live sessions against the configured backend), or browser (real dev-host browser flow)."
5962
- },
5963
- commit: {
5964
- type: "string",
5965
- description: "Git revision to resolve once before remote testing"
5966
- },
5967
- ...CONFIG_FLAG_ARGS
5968
- },
5969
- async run({ args }) {
5970
- await runTestCommand(args);
5971
- }
5972
- });
5973
- var test_default = defineCommand({
5974
- meta: {
5975
- name: "test",
5976
- description: "Reducer-native test runner with typed bases and scenarios"
5977
- },
5978
- args: runCommand3.args,
5979
- async run(context) {
5980
- await runCommand3.run?.(context);
5981
- }
5982
- });
5983
-
5984
5935
  // src/commands/verify.ts
5985
- import { execFile as execFile2 } from "child_process";
5986
- import { promisify as promisify2 } from "util";
5987
5936
  var execFileAsync2 = promisify2(execFile2);
5988
5937
  async function findGitRoot() {
5989
5938
  const { stdout } = await execFileAsync2(
@@ -6067,8 +6016,8 @@ function consumeMachineOutputMode(argv2) {
6067
6016
  runId: crypto3.randomUUID()
6068
6017
  } : null;
6069
6018
  }
6070
- function commandPathToId(path10) {
6071
- const [first, second] = path10;
6019
+ function commandPathToId(path11) {
6020
+ const [first, second] = path11;
6072
6021
  if (first === "auth") {
6073
6022
  if (second === "git-credential") return "auth.git_credential";
6074
6023
  if (second === "status") return "auth.status";
@@ -6333,7 +6282,7 @@ function runDreamboardCli(internalSubCommands = {}) {
6333
6282
  const main = defineCommand({
6334
6283
  meta: {
6335
6284
  name: "dreamboard",
6336
- version: "0.1.30-alpha.29",
6285
+ version: "0.1.30-alpha.30",
6337
6286
  description: "Dreamboard CLI \u2014 game development platform"
6338
6287
  },
6339
6288
  subCommands