deepline 0.2.30 → 0.2.32

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.
@@ -512,6 +512,55 @@ type RuntimeApiActionRequest =
512
512
  input: Parameters<typeof releaseRuntimeWorkReceipts>[1];
513
513
  };
514
514
 
515
+ /**
516
+ * The Runtime Sheet persistence lane is temporarily full. This is an
517
+ * admission signal, not a failed transport attempt: the runner must park the
518
+ * same idempotent write and retry it after capacity becomes available.
519
+ */
520
+ export class RuntimeApiCapacityError extends Error {
521
+ readonly status: number;
522
+ readonly code: 'runtime_postgres_admission_backpressure';
523
+ readonly action: RuntimeApiActionRequest['action'];
524
+ readonly requestId: string | null;
525
+ readonly retryAfterMs: number;
526
+
527
+ constructor(input: {
528
+ status: number;
529
+ action: RuntimeApiActionRequest['action'];
530
+ requestId?: string | null;
531
+ retryAfterMs: number;
532
+ detail: string;
533
+ }) {
534
+ super(
535
+ `Runtime API ${input.action} delayed by persistence capacity` +
536
+ `${input.requestId ? ` request_id=${input.requestId}` : ''}: ${input.detail}`,
537
+ );
538
+ this.name = 'RuntimeApiCapacityError';
539
+ this.status = input.status;
540
+ this.code = 'runtime_postgres_admission_backpressure';
541
+ this.action = input.action;
542
+ this.requestId = input.requestId?.trim() || null;
543
+ this.retryAfterMs = Math.max(0, Math.floor(input.retryAfterMs));
544
+ }
545
+ }
546
+
547
+ export function isRuntimeApiCapacityError(
548
+ error: unknown,
549
+ ): error is RuntimeApiCapacityError {
550
+ if (error instanceof RuntimeApiCapacityError) return true;
551
+ if (!error || typeof error !== 'object') return false;
552
+ const candidate = error as {
553
+ name?: unknown;
554
+ code?: unknown;
555
+ retryAfterMs?: unknown;
556
+ };
557
+ return (
558
+ candidate.name === 'RuntimeApiCapacityError' &&
559
+ candidate.code === 'runtime_postgres_admission_backpressure' &&
560
+ typeof candidate.retryAfterMs === 'number'
561
+ );
562
+ }
563
+
515
564
  export type RuntimeApiRowRecord = MapRowOutcome & {
516
565
  inputIndex?: number | null;
517
566
  };
@@ -588,13 +637,17 @@ async function postRuntimeApi<TResponse>(
588
637
  method: 'POST',
589
638
  headers: resolveRuntimeApiHeaders(context, vercelHeaders),
590
639
  body: JSON.stringify(body),
591
- signal: abortController.signal,
640
+ signal: context.abortSignal
641
+ ? AbortSignal.any([context.abortSignal, abortController.signal])
642
+ : abortController.signal,
592
643
  });
593
644
  let parsedValue: unknown;
594
645
  try {
595
646
  parsedValue = await response.json();
596
647
  } catch (error) {
597
- if (abortController.signal.aborted) throw error;
648
+ if (abortController.signal.aborted || context.abortSignal?.aborted) {
649
+ throw error;
650
+ }
598
651
  parsedValue = null;
599
652
  }
600
653
  parsed =
@@ -605,6 +658,9 @@ async function postRuntimeApi<TResponse>(
605
658
  : null;
606
659
  } catch (error) {
607
660
  clearTimeout(timeout);
661
+ if (context.abortSignal?.aborted) {
662
+ throw context.abortSignal.reason ?? error;
663
+ }
608
664
  if (attempt < maxAttempts) {
609
665
  await sleepRuntimeApiRetry(body.action, attempt);
610
666
  continue;
@@ -654,6 +710,23 @@ async function postRuntimeApi<TResponse>(
654
710
  : typeof parsed?.debug_error === 'string'
655
711
  ? parsed.debug_error
656
712
  : null;
713
+ if (
714
+ response.status === 503 &&
715
+ parsed?.code === 'runtime_postgres_admission_backpressure'
716
+ ) {
717
+ const requestId = response.headers.get('x-deepline-request-id');
718
+ const errorMessage =
719
+ typeof parsed.error === 'string'
720
+ ? parsed.error
721
+ : 'Runtime Postgres admission delayed.';
722
+ throw new RuntimeApiCapacityError({
723
+ status: response.status,
724
+ action: body.action,
725
+ requestId,
726
+ retryAfterMs,
727
+ detail: details ? `${errorMessage}: ${details}` : errorMessage,
728
+ });
729
+ }
657
730
  const shouldRetryRuntimeResponse =
658
731
  (response.status === 503 &&
659
732
  parsed?.code === 'ingestion_plane_not_ready') ||
@@ -713,7 +786,8 @@ function runtimeApiRetryDelayMs(
713
786
  function runtimeApiRequestTimeoutMs(
714
787
  action: RuntimeApiActionRequest['action'],
715
788
  ): number {
716
- return action === 'runtime_sheet_start'
789
+ return action === 'runtime_sheet_start' ||
790
+ action === 'runtime_sheet_complete_map_rows'
717
791
  ? RUNTIME_SHEET_ADMISSION_REQUEST_TIMEOUT_MS
718
792
  : RUNTIME_API_REQUEST_TIMEOUT_MS;
719
793
  }
@@ -7896,6 +7970,29 @@ export async function completeRuntimeMapRows(
7896
7970
  );
7897
7971
  }
7898
7972
 
7973
+ /**
7974
+ * Freeze the transport-ready completion payload before a higher-level
7975
+ * capacity retry loop starts. In particular, completedAt must remain stable:
7976
+ * a retry is the same idempotent write, not a newly authored row transition.
7977
+ */
7978
+ export function createCompleteRuntimeMapRowsOperation(
7979
+ context: RuntimeApiContext & { playName: string },
7980
+ input: Parameters<typeof completeRuntimeMapRows>[1],
7981
+ ): () => Promise<RuntimeMapRowsWriteResult> {
7982
+ if (context.dbSessionStrategy !== 'gateway_only') {
7983
+ return () => completeRuntimeMapRows(context, input);
7984
+ }
7985
+ const frozenInput = {
7986
+ ...input,
7987
+ rows: prepareRuntimeSheetRowsForJsonTransport({
7988
+ rows: input.rows,
7989
+ runId: input.runId,
7990
+ outputFields: input.outputFields ?? [],
7991
+ }),
7992
+ };
7993
+ return () => completeRuntimeMapRows(context, frozenInput);
7994
+ }
7995
+
7899
7996
  export async function readRuntimeSheetDatasetRows(
7900
7997
  context: RuntimeApiContext & { playName: string },
7901
7998
  input: {
package/dist/cli/index.js CHANGED
@@ -1044,7 +1044,7 @@ var SDK_RELEASE = {
1044
1044
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
1045
1045
  // exposed storage-dependent synchronous access. This deliberate minor
1046
1046
  // release keeps lazy paging semantics independent of row residency.
1047
- version: "0.2.30",
1047
+ version: "0.2.32",
1048
1048
  contracts: {
1049
1049
  api: {
1050
1050
  name: "sdk-http-api",
@@ -4204,6 +4204,7 @@ var DeeplineClient = class {
4204
4204
  // defaults to absurd; callers normally omit this field.
4205
4205
  ...request.profile ? { profile: request.profile } : {},
4206
4206
  ...integrationMode ? { integrationMode } : {},
4207
+ ...request.fixtureBehavior ? { fixtureBehavior: request.fixtureBehavior } : {},
4207
4208
  ...runtime ? { runtime } : {},
4208
4209
  ...testPolicyOverrides ? { testPolicyOverrides } : {}
4209
4210
  },
@@ -4253,6 +4254,7 @@ var DeeplineClient = class {
4253
4254
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
4254
4255
  ...request.profile ? { profile: request.profile } : {},
4255
4256
  ...integrationMode ? { integrationMode } : {},
4257
+ ...request.fixtureBehavior ? { fixtureBehavior: request.fixtureBehavior } : {},
4256
4258
  ...runtime ? { runtime } : {},
4257
4259
  ...testPolicyOverrides ? { testPolicyOverrides } : {}
4258
4260
  };
@@ -17018,6 +17020,188 @@ function isInternalGlueStepId(stepId) {
17018
17020
  return typeof stepId === "string" && stepId.startsWith(INTERNAL_GLUE_NODE_ID_PREFIX);
17019
17021
  }
17020
17022
 
17023
+ // ../shared_libs/play-runtime/fixture-behavior.ts
17024
+ var FIXTURE_BEHAVIOR_VERSION = 1;
17025
+ var FIXTURE_BEHAVIOR_RESPONSE_VERSION = 2;
17026
+ var MAX_FIXTURE_RESPONSE_DELAY_SAMPLES = 256;
17027
+ var MAX_FIXTURE_RESPONSE_DELAY_MS = 8 * 6e4;
17028
+ var MAX_FIXTURE_RESPONSE_ERROR_MESSAGE_LENGTH = 500;
17029
+ function validateFixtureBehavior(value) {
17030
+ if (value === void 0 || value === null) {
17031
+ return { ok: true, behavior: null };
17032
+ }
17033
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
17034
+ return { ok: false, error: "fixtureBehavior must be a JSON object." };
17035
+ }
17036
+ const record = value;
17037
+ const supportedKeys = record.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION ? /* @__PURE__ */ new Set(["version", "responseSamples"]) : /* @__PURE__ */ new Set(["version", "responseDelaySamplesMs"]);
17038
+ const unknownKeys = Object.keys(record).filter(
17039
+ (key) => !supportedKeys.has(key)
17040
+ );
17041
+ if (unknownKeys.length > 0) {
17042
+ return {
17043
+ ok: false,
17044
+ error: `Unsupported fixtureBehavior field "${unknownKeys[0]}".`
17045
+ };
17046
+ }
17047
+ if (record.version !== FIXTURE_BEHAVIOR_VERSION && record.version !== FIXTURE_BEHAVIOR_RESPONSE_VERSION) {
17048
+ return {
17049
+ ok: false,
17050
+ error: `fixtureBehavior.version must be ${FIXTURE_BEHAVIOR_VERSION} or ${FIXTURE_BEHAVIOR_RESPONSE_VERSION}.`
17051
+ };
17052
+ }
17053
+ if (record.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION) {
17054
+ if (!Array.isArray(record.responseSamples) || record.responseSamples.length === 0 || record.responseSamples.length > MAX_FIXTURE_RESPONSE_DELAY_SAMPLES) {
17055
+ return {
17056
+ ok: false,
17057
+ error: `fixtureBehavior.responseSamples must contain between 1 and ${MAX_FIXTURE_RESPONSE_DELAY_SAMPLES} values.`
17058
+ };
17059
+ }
17060
+ const samples2 = [];
17061
+ for (let index = 0; index < record.responseSamples.length; index += 1) {
17062
+ const value2 = record.responseSamples[index];
17063
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
17064
+ return {
17065
+ ok: false,
17066
+ error: `fixtureBehavior.responseSamples[${index}] must be an object.`
17067
+ };
17068
+ }
17069
+ const sample = value2;
17070
+ const sampleUnknownKeys = Object.keys(sample).filter(
17071
+ (key) => key !== "delayMs" && key !== "when" && key !== "httpError"
17072
+ );
17073
+ if (sampleUnknownKeys.length > 0) {
17074
+ return {
17075
+ ok: false,
17076
+ error: `Unsupported fixtureBehavior.responseSamples[${index}] field "${sampleUnknownKeys[0]}".`
17077
+ };
17078
+ }
17079
+ if (typeof sample.delayMs !== "number" || !Number.isSafeInteger(sample.delayMs) || sample.delayMs < 0 || sample.delayMs > MAX_FIXTURE_RESPONSE_DELAY_MS) {
17080
+ return {
17081
+ ok: false,
17082
+ error: `fixtureBehavior.responseSamples[${index}].delayMs must be an integer between 0 and ${MAX_FIXTURE_RESPONSE_DELAY_MS}.`
17083
+ };
17084
+ }
17085
+ let when;
17086
+ if (sample.when !== void 0) {
17087
+ if (!sample.when || typeof sample.when !== "object" || Array.isArray(sample.when)) {
17088
+ return {
17089
+ ok: false,
17090
+ error: `fixtureBehavior.responseSamples[${index}].when must be an object.`
17091
+ };
17092
+ }
17093
+ const condition = sample.when;
17094
+ const conditionUnknownKeys = Object.keys(condition).filter(
17095
+ (key) => key !== "provider" && key !== "operation"
17096
+ );
17097
+ if (conditionUnknownKeys.length > 0) {
17098
+ return {
17099
+ ok: false,
17100
+ error: `Unsupported fixtureBehavior.responseSamples[${index}].when field "${conditionUnknownKeys[0]}".`
17101
+ };
17102
+ }
17103
+ const provider = normalizeFixtureScopeValue(condition.provider, 100);
17104
+ const operation = normalizeFixtureScopeValue(condition.operation, 200);
17105
+ if (provider.error || operation.error) {
17106
+ return {
17107
+ ok: false,
17108
+ error: `fixtureBehavior.responseSamples[${index}].when ` + (provider.error ?? operation.error)
17109
+ };
17110
+ }
17111
+ if (!provider.value && !operation.value) {
17112
+ return {
17113
+ ok: false,
17114
+ error: `fixtureBehavior.responseSamples[${index}].when must select a provider or operation.`
17115
+ };
17116
+ }
17117
+ when = {
17118
+ ...provider.value ? { provider: provider.value } : {},
17119
+ ...operation.value ? { operation: operation.value } : {}
17120
+ };
17121
+ }
17122
+ let httpError;
17123
+ if (sample.httpError !== void 0) {
17124
+ if (!sample.httpError || typeof sample.httpError !== "object" || Array.isArray(sample.httpError)) {
17125
+ return {
17126
+ ok: false,
17127
+ error: `fixtureBehavior.responseSamples[${index}].httpError must be an object.`
17128
+ };
17129
+ }
17130
+ const error = sample.httpError;
17131
+ const errorUnknownKeys = Object.keys(error).filter(
17132
+ (key) => key !== "status" && key !== "message"
17133
+ );
17134
+ if (errorUnknownKeys.length > 0) {
17135
+ return {
17136
+ ok: false,
17137
+ error: `Unsupported fixtureBehavior.responseSamples[${index}].httpError field "${errorUnknownKeys[0]}".`
17138
+ };
17139
+ }
17140
+ if (typeof error.status !== "number" || !Number.isSafeInteger(error.status) || error.status < 400 || error.status > 599) {
17141
+ return {
17142
+ ok: false,
17143
+ error: `fixtureBehavior.responseSamples[${index}].httpError.status must be an integer between 400 and 599.`
17144
+ };
17145
+ }
17146
+ if (typeof error.message !== "string" || !error.message.trim() || error.message.length > MAX_FIXTURE_RESPONSE_ERROR_MESSAGE_LENGTH) {
17147
+ return {
17148
+ ok: false,
17149
+ error: `fixtureBehavior.responseSamples[${index}].httpError.message must contain 1-${MAX_FIXTURE_RESPONSE_ERROR_MESSAGE_LENGTH} characters.`
17150
+ };
17151
+ }
17152
+ httpError = { status: error.status, message: error.message.trim() };
17153
+ }
17154
+ samples2.push({
17155
+ delayMs: sample.delayMs,
17156
+ ...when ? { when } : {},
17157
+ ...httpError ? { httpError } : {}
17158
+ });
17159
+ }
17160
+ return {
17161
+ ok: true,
17162
+ behavior: {
17163
+ version: FIXTURE_BEHAVIOR_RESPONSE_VERSION,
17164
+ responseSamples: samples2
17165
+ }
17166
+ };
17167
+ }
17168
+ if (!Array.isArray(record.responseDelaySamplesMs) || record.responseDelaySamplesMs.length === 0 || record.responseDelaySamplesMs.length > MAX_FIXTURE_RESPONSE_DELAY_SAMPLES) {
17169
+ return {
17170
+ ok: false,
17171
+ error: `fixtureBehavior.responseDelaySamplesMs must contain between 1 and ${MAX_FIXTURE_RESPONSE_DELAY_SAMPLES} values.`
17172
+ };
17173
+ }
17174
+ const samples = [];
17175
+ for (let index = 0; index < record.responseDelaySamplesMs.length; index += 1) {
17176
+ const value2 = record.responseDelaySamplesMs[index];
17177
+ if (typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < 0 || value2 > MAX_FIXTURE_RESPONSE_DELAY_MS) {
17178
+ return {
17179
+ ok: false,
17180
+ error: `fixtureBehavior.responseDelaySamplesMs[${index}] must be an integer between 0 and ${MAX_FIXTURE_RESPONSE_DELAY_MS}.`
17181
+ };
17182
+ }
17183
+ samples.push(value2);
17184
+ }
17185
+ return {
17186
+ ok: true,
17187
+ behavior: {
17188
+ version: FIXTURE_BEHAVIOR_VERSION,
17189
+ responseDelaySamplesMs: samples
17190
+ }
17191
+ };
17192
+ }
17193
+ function normalizeFixtureScopeValue(value, maxLength) {
17194
+ if (value === void 0) return {};
17195
+ if (typeof value !== "string" || !value.trim()) {
17196
+ return { error: "values must be non-empty strings." };
17197
+ }
17198
+ const normalized = value.trim().toLowerCase();
17199
+ if (normalized.length > maxLength) {
17200
+ return { error: `values must be at most ${maxLength} characters.` };
17201
+ }
17202
+ return { value: normalized };
17203
+ }
17204
+
17021
17205
  // src/cli/commands/play.ts
17022
17206
  var PLAY_BUNDLER_MODULE_PATHS = [
17023
17207
  // Built CLI bundle: dist/cli/index.mjs -> dist/plays/bundle-play-file.mjs.
@@ -17062,7 +17246,8 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
17062
17246
  "--full",
17063
17247
  "--force",
17064
17248
  "--open",
17065
- "--debug-map-latency"
17249
+ "--debug-map-latency",
17250
+ "--debug-fixture-provider-pacing"
17066
17251
  ]);
17067
17252
  function traceCliSync(phase, fields, run) {
17068
17253
  const startedAt = Date.now();
@@ -20904,8 +21089,12 @@ function parsePlayRunOptions(args) {
20904
21089
  const force = args.includes("--force");
20905
21090
  const open = args.includes("--open");
20906
21091
  const debugMapLatency = args.includes("--debug-map-latency");
21092
+ const debugFixtureProviderPacing = args.includes(
21093
+ "--debug-fixture-provider-pacing"
21094
+ );
20907
21095
  let waitTimeoutMs = null;
20908
21096
  let profile = null;
21097
+ let fixtureBehavior = null;
20909
21098
  for (let index = 0; index < args.length; index += 1) {
20910
21099
  const arg = args[index];
20911
21100
  if (arg === "--file" && args[index + 1]) {
@@ -20934,6 +21123,23 @@ function parsePlayRunOptions(args) {
20934
21123
  index += 1;
20935
21124
  continue;
20936
21125
  }
21126
+ if (arg === "--fixture-behavior") {
21127
+ const value = args[index + 1];
21128
+ if (!value) {
21129
+ throw new Error(
21130
+ "--fixture-behavior requires a JSON object or @file path."
21131
+ );
21132
+ }
21133
+ const parsed = validateFixtureBehavior(parseJsonInput(value));
21134
+ if (!parsed.ok || !parsed.behavior) {
21135
+ throw new Error(
21136
+ parsed.ok ? "--fixture-behavior is required." : parsed.error
21137
+ );
21138
+ }
21139
+ fixtureBehavior = parsed.behavior;
21140
+ index += 1;
21141
+ continue;
21142
+ }
20937
21143
  if (arg === "--live") {
20938
21144
  revisionSelector = "live";
20939
21145
  continue;
@@ -21028,7 +21234,9 @@ function parsePlayRunOptions(args) {
21028
21234
  force,
21029
21235
  open,
21030
21236
  profile,
21031
- debugMapLatency
21237
+ debugMapLatency,
21238
+ debugFixtureProviderPacing,
21239
+ fixtureBehavior
21032
21240
  };
21033
21241
  }
21034
21242
  function parsePlayCheckOptions(args) {
@@ -21586,6 +21794,20 @@ async function handleFileBackedRun(options, hooks) {
21586
21794
  })
21587
21795
  );
21588
21796
  const integrationMode = resolveEvalIntegrationMode();
21797
+ if (options.fixtureBehavior && integrationMode !== "fixture") {
21798
+ throw new Error(
21799
+ "--fixture-behavior requires DEEPLINE_EVAL_INTEGRATION_MODE=fixture."
21800
+ );
21801
+ }
21802
+ if (options.debugFixtureProviderPacing && integrationMode !== "fixture") {
21803
+ throw new Error(
21804
+ "--debug-fixture-provider-pacing requires DEEPLINE_EVAL_INTEGRATION_MODE=fixture."
21805
+ );
21806
+ }
21807
+ const testPolicyOverrides = {
21808
+ ...options.debugMapLatency ? { mapLatencyProfile: true } : {},
21809
+ ...options.debugFixtureProviderPacing ? { enforceFixtureProviderPacing: true } : {}
21810
+ };
21589
21811
  const startRequest = {
21590
21812
  name: playName,
21591
21813
  sourceCode: bundleResult.sourceCode,
@@ -21599,8 +21821,9 @@ async function handleFileBackedRun(options, hooks) {
21599
21821
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
21600
21822
  ...options.force ? { force: true } : {},
21601
21823
  ...options.profile ? { profile: options.profile } : {},
21602
- ...options.debugMapLatency ? { testPolicyOverrides: { mapLatencyProfile: true } } : {},
21603
- ...integrationMode ? { integrationMode } : {}
21824
+ ...Object.keys(testPolicyOverrides).length > 0 ? { testPolicyOverrides } : {},
21825
+ ...integrationMode ? { integrationMode } : {},
21826
+ ...options.fixtureBehavior ? { fixtureBehavior: options.fixtureBehavior } : {}
21604
21827
  };
21605
21828
  if (options.watch) {
21606
21829
  progress.phase("starting run");
@@ -21755,6 +21978,20 @@ async function handleNamedRun(options, hooks) {
21755
21978
  })
21756
21979
  );
21757
21980
  const integrationMode = resolveEvalIntegrationMode();
21981
+ if (options.fixtureBehavior && integrationMode !== "fixture") {
21982
+ throw new Error(
21983
+ "--fixture-behavior requires DEEPLINE_EVAL_INTEGRATION_MODE=fixture."
21984
+ );
21985
+ }
21986
+ if (options.debugFixtureProviderPacing && integrationMode !== "fixture") {
21987
+ throw new Error(
21988
+ "--debug-fixture-provider-pacing requires DEEPLINE_EVAL_INTEGRATION_MODE=fixture."
21989
+ );
21990
+ }
21991
+ const testPolicyOverrides = {
21992
+ ...options.debugMapLatency ? { mapLatencyProfile: true } : {},
21993
+ ...options.debugFixtureProviderPacing ? { enforceFixtureProviderPacing: true } : {}
21994
+ };
21758
21995
  const startRequest = {
21759
21996
  name: playName,
21760
21997
  ...selectedRevisionId ? { revisionId: selectedRevisionId } : {},
@@ -21763,8 +22000,9 @@ async function handleNamedRun(options, hooks) {
21763
22000
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
21764
22001
  ...options.force ? { force: true } : {},
21765
22002
  ...options.profile ? { profile: options.profile } : {},
21766
- ...options.debugMapLatency ? { testPolicyOverrides: { mapLatencyProfile: true } } : {},
21767
- ...integrationMode ? { integrationMode } : {}
22003
+ ...Object.keys(testPolicyOverrides).length > 0 ? { testPolicyOverrides } : {},
22004
+ ...integrationMode ? { integrationMode } : {},
22005
+ ...options.fixtureBehavior ? { fixtureBehavior: options.fixtureBehavior } : {}
21768
22006
  };
21769
22007
  if (options.watch) {
21770
22008
  progress.phase("starting run");
@@ -23230,12 +23468,18 @@ Examples:
23230
23468
  ).option(
23231
23469
  "--profile <id>",
23232
23470
  "Internal/testing: override the execution profile for this run"
23471
+ ).option(
23472
+ "--fixture-behavior <json>",
23473
+ "Internal/testing: fixture response behavior JSON object or @file path"
23233
23474
  ).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
23234
23475
  "--logs",
23235
23476
  "When output is non-interactive, stream play logs to stderr while waiting"
23236
23477
  ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option("--open", "Open the play page in a browser after the run starts").option(
23237
23478
  "--debug-map-latency",
23238
23479
  "Internal diagnostics: emit one aggregate latency profile per dataset map"
23480
+ ).option(
23481
+ "--debug-fixture-provider-pacing",
23482
+ "Internal diagnostics: retain provider pacing while fixture mode is active"
23239
23483
  ).option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
23240
23484
  "afterAll",
23241
23485
  `
@@ -23267,6 +23511,7 @@ Pass-through input flags:
23267
23511
  ...options.latest ? ["--latest"] : [],
23268
23512
  ...options.revisionId ? ["--revision-id", options.revisionId] : [],
23269
23513
  ...options.profile ? ["--profile", options.profile] : [],
23514
+ ...options.fixtureBehavior ? ["--fixture-behavior", options.fixtureBehavior] : [],
23270
23515
  ...options.wait === false ? ["--no-wait"] : [],
23271
23516
  ...options.watch || options.wait ? ["--watch"] : [],
23272
23517
  ...options.logs ? ["--logs"] : [],
@@ -23274,6 +23519,7 @@ Pass-through input flags:
23274
23519
  ...options.force ? ["--force"] : [],
23275
23520
  ...options.open ? ["--open"] : [],
23276
23521
  ...options.debugMapLatency ? ["--debug-map-latency"] : [],
23522
+ ...options.debugFixtureProviderPacing ? ["--debug-fixture-provider-pacing"] : [],
23277
23523
  ...options.json ? ["--json"] : [],
23278
23524
  ...options.full ? ["--full"] : [],
23279
23525
  ...passthroughArgs