deepline 0.3.145 → 0.3.147

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 (28) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +1 -1
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +40 -4
  4. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +259 -7
  5. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +10 -0
  6. package/dist/bundling-sources/shared_libs/play-runtime/fullenrich-batching.ts +2 -2
  7. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +10 -0
  8. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +58 -19
  9. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +17 -11
  10. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +57 -2
  11. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +14 -2
  12. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +73 -16
  13. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +22 -1
  14. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +84 -10
  15. package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +7 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +6 -2
  17. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +1 -0
  18. package/dist/cli/index.js +57 -17
  19. package/dist/cli/index.mjs +57 -17
  20. package/dist/index.d.mts +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +25 -9
  23. package/dist/index.mjs +25 -9
  24. package/dist/release.d.mts +1 -1
  25. package/dist/release.d.ts +1 -1
  26. package/dist/release.js +1 -1
  27. package/dist/release.mjs +1 -1
  28. package/package.json +1 -1
@@ -264,7 +264,9 @@ const POSTGRES_SCHEDULER_SCHEMA_INIT_STATEMENT_TIMEOUT_MS = 60_000;
264
264
  // v44 moves the v39-v43 shared-schema expansion onto the online, statement-
265
265
  // scoped migration path. The reader contract is unchanged; the marker ensures
266
266
  // deployment retries do not re-enter the old cross-table DDL transaction.
267
- export const POSTGRES_SCHEDULER_SCHEMA_VERSION = 44;
267
+ // v45 adds the bucket-leading expiration index used by rate-reservation
268
+ // cleanup. Shared schemas build it concurrently through the deploy migrator.
269
+ export const POSTGRES_SCHEDULER_SCHEMA_VERSION = 45;
268
270
  const POSTGRES_SCHEDULER_SCHEMA_MIGRATIONS_TABLE =
269
271
  'scheduler_schema_migrations';
270
272
  export const POSTGRES_SCHEDULER_OPEN_RECOVERY_INDEX =
@@ -1829,6 +1831,15 @@ export async function hasCurrentPostgresSchedulerSchemaShape(
1829
1831
  AND index_class.relname = 'runtime_scheduler_runs_terminal_finished_idx'
1830
1832
  AND index_row.indrelid = to_regclass($4)
1831
1833
  AND index_row.indisready AND index_row.indisvalid
1834
+ )
1835
+ AND EXISTS (
1836
+ SELECT 1 FROM pg_index AS index_row
1837
+ JOIN pg_class AS index_class ON index_class.oid = index_row.indexrelid
1838
+ JOIN pg_namespace AS index_namespace ON index_namespace.oid = index_class.relnamespace
1839
+ WHERE index_namespace.nspname = $1
1840
+ AND index_class.relname = 'runtime_scheduler_rate_reservation_bucket_expiry_idx'
1841
+ AND index_row.indrelid = to_regclass($9)
1842
+ AND index_row.indisready AND index_row.indisvalid
1832
1843
  ) AS ready
1833
1844
  `,
1834
1845
  [
@@ -1840,6 +1851,7 @@ export async function hasCurrentPostgresSchedulerSchemaShape(
1840
1851
  requirements.blockedOutboxIndex !== false,
1841
1852
  `${quotedSchema}.${quoteIdent('sandbox_cleanup_jobs_v2')}`,
1842
1853
  `${quotedSchema}.${quoteIdent('compute_billing_jobs_v2')}`,
1854
+ `${quotedSchema}.${quoteIdent('rate_reservations')}`,
1843
1855
  ],
1844
1856
  );
1845
1857
  return runtimeAdminIndexes.rows[0]?.ready === true;
@@ -3434,7 +3446,10 @@ export async function ensurePostgresSchedulerSchema(
3434
3446
  END
3435
3447
  $$
3436
3448
  `);
3437
- await ensurePostgresRateStateSchema(client, options);
3449
+ await ensurePostgresRateStateSchema(client, {
3450
+ schema,
3451
+ deferReservationBucketExpiryIndex: options?.deferRuntimeAdminIndexes,
3452
+ });
3438
3453
  await ensurePostgresBudgetStateSchema(client, {
3439
3454
  schedulerSchema: schemaName(options),
3440
3455
  });
@@ -3792,6 +3807,11 @@ const POSTGRES_SCHEDULER_RUNTIME_ADMIN_INDEXES = [
3792
3807
  WHERE status IN ('completed', 'failed', 'cancelled')
3793
3808
  AND started_at IS NOT NULL`,
3794
3809
  },
3810
+ {
3811
+ name: 'runtime_scheduler_rate_reservation_bucket_expiry_idx',
3812
+ table: 'rate_reservations',
3813
+ definition: `(bucket_id, expires_at_ms)`,
3814
+ },
3795
3815
  ] as const;
3796
3816
 
3797
3817
  async function readPostgresSchedulerIndexState(
@@ -3824,7 +3844,7 @@ async function readPostgresSchedulerIndexState(
3824
3844
  }
3825
3845
 
3826
3846
  /**
3827
- * Remove interrupted dashboard index builds from a quiesced run-scoped
3847
+ * Remove interrupted deploy-owned index builds from a quiesced run-scoped
3828
3848
  * schema so transactional CREATE INDEX IF NOT EXISTS can recreate them.
3829
3849
  * Shared schemas must use the concurrent repair path below.
3830
3850
  */
@@ -3848,9 +3868,9 @@ export async function repairInvalidRunScopedRuntimeAdminIndexes(
3848
3868
  }
3849
3869
 
3850
3870
  /**
3851
- * The Runtime Workers dashboard and bounded delivered-outbox retention rely on
3852
- * these indexes. Deploy owns the builds because the live scheduler tables are
3853
- * too large for request or worker startup to run blocking DDL.
3871
+ * Runtime health surfaces, bounded retention, and hot-path cleanup rely on
3872
+ * these indexes. Deploy owns the builds because live scheduler tables are too
3873
+ * large for request or worker startup to run blocking DDL.
3854
3874
  */
3855
3875
  export async function ensurePostgresSchedulerRuntimeAdminIndexesConcurrently(
3856
3876
  client: PostgresSchedulerQueryClient,
@@ -3882,7 +3902,7 @@ export async function ensurePostgresSchedulerRuntimeAdminIndexesConcurrently(
3882
3902
  );
3883
3903
  if (installed.kind !== 'ready') {
3884
3904
  throw new Error(
3885
- `Runtime scheduler dashboard index ${schema}.${index.name} is not valid and ready after concurrent creation.`,
3905
+ `Runtime scheduler index ${schema}.${index.name} is not valid and ready after concurrent creation.`,
3886
3906
  );
3887
3907
  }
3888
3908
  }
@@ -9099,6 +9119,9 @@ export async function directCompletePostgresSchedulerRunnerTerminal(
9099
9119
  input.result,
9100
9120
  { logMetadata: input.completionLogMetadata ?? 'attach' },
9101
9121
  );
9122
+ const resultSummary = terminalRowOutcomesSummary(
9123
+ (input.result as { rowOutcomes?: unknown }).rowOutcomes,
9124
+ );
9102
9125
  const terminalResult = assertTerminalRunResultWithinLimit(terminalOutput);
9103
9126
  const ledgerTerminalResult = terminalRunResultForLedger(terminalResult, {
9104
9127
  content: 'full',
@@ -9352,7 +9375,8 @@ export async function directCompletePostgresSchedulerRunnerTerminal(
9352
9375
  jsonb_build_object(
9353
9376
  'output', $6::jsonb,
9354
9377
  'terminalLogLines', $7::jsonb,
9355
- 'terminalProgressEvents', $8::jsonb
9378
+ 'terminalProgressEvents', $8::jsonb,
9379
+ 'resultSummary', $16::jsonb
9356
9380
  ),
9357
9381
  ${causalOutboxCreatedAt('run_terminal.run_id', options)}
9358
9382
  FROM run_terminal
@@ -9386,6 +9410,7 @@ export async function directCompletePostgresSchedulerRunnerTerminal(
9386
9410
  input.engineWake.eventName,
9387
9411
  input.engineWake.wakeChannel,
9388
9412
  input.allowCappedCompletion === true,
9413
+ stringifyPostgresJson(resultSummary),
9389
9414
  ],
9390
9415
  );
9391
9416
  if (completed.rows.length > 0) return 'completed';
@@ -11271,6 +11296,7 @@ export async function completePostgresSchedulerAttempt(
11271
11296
  attempt: number;
11272
11297
  leaseToken: string;
11273
11298
  output: unknown;
11299
+ rowOutcomes?: unknown;
11274
11300
  runtimeTiming?: PlayRunnerRuntimeTiming | null;
11275
11301
  terminalLogLines?: readonly string[] | null;
11276
11302
  },
@@ -11280,6 +11306,7 @@ export async function completePostgresSchedulerAttempt(
11280
11306
  const ledgerTerminalResult = terminalRunResultForLedger(terminalResult, {
11281
11307
  content: 'full',
11282
11308
  });
11309
+ const resultSummary = terminalRowOutcomesSummary(input.rowOutcomes);
11283
11310
  const terminalLogLines = (input.terminalLogLines ?? [])
11284
11311
  .map((line) => line.trim())
11285
11312
  .filter(Boolean)
@@ -11458,7 +11485,8 @@ export async function completePostgresSchedulerAttempt(
11458
11485
  'run.completed',
11459
11486
  jsonb_build_object(
11460
11487
  'output', $9::jsonb,
11461
- 'terminalLogLines', $8::jsonb
11488
+ 'terminalLogLines', $8::jsonb,
11489
+ 'resultSummary', $10::jsonb
11462
11490
  ),
11463
11491
  ${causalOutboxCreatedAt('run_terminal.run_id', options)}
11464
11492
  FROM run_terminal
@@ -11479,6 +11507,7 @@ export async function completePostgresSchedulerAttempt(
11479
11507
  JSON.stringify({ runId: input.runId, status: 'completed' }),
11480
11508
  JSON.stringify(terminalLogLines),
11481
11509
  stringifyPostgresJson(ledgerTerminalResult ?? null),
11510
+ stringifyPostgresJson(resultSummary),
11482
11511
  ],
11483
11512
  );
11484
11513
  if (completed.rows.length === 0) {
@@ -11522,6 +11551,9 @@ export async function failPostgresSchedulerAttempt(
11522
11551
  terminalResult === undefined ? (input.result ?? null) : terminalResult,
11523
11552
  terminalResult === undefined ? {} : { content: 'full' },
11524
11553
  );
11554
+ const resultSummary = terminalRowOutcomesSummary(
11555
+ (input.result as { rowOutcomes?: unknown } | null)?.rowOutcomes,
11556
+ );
11525
11557
  // Keep the recovery tail separate from result: large failures are represented
11526
11558
  // by a result reference, but their customer guidance must still be logged.
11527
11559
  const terminalLogLines = (input.terminalLogLines ?? [])
@@ -11762,7 +11794,8 @@ export async function failPostgresSchedulerAttempt(
11762
11794
  jsonb_build_object(
11763
11795
  'error', $4::jsonb ->> 'message',
11764
11796
  'result', $8::jsonb,
11765
- 'terminalLogLines', $12::jsonb
11797
+ 'terminalLogLines', $12::jsonb,
11798
+ 'resultSummary', $13::jsonb
11766
11799
  ),
11767
11800
  ${causalOutboxCreatedAt('run_terminal.run_id', options)}
11768
11801
  FROM run_terminal
@@ -11786,6 +11819,7 @@ export async function failPostgresSchedulerAttempt(
11786
11819
  stringifyPostgresJson(input.sandboxCrashDiagnostic ?? null),
11787
11820
  input.preserveRunnerTerminal === true,
11788
11821
  JSON.stringify(terminalLogLines),
11822
+ stringifyPostgresJson(resultSummary),
11789
11823
  ],
11790
11824
  );
11791
11825
  return failed.rows.length > 0;
@@ -12265,6 +12299,23 @@ function finiteRunnerNumber(value: unknown): number | null {
12265
12299
  : null;
12266
12300
  }
12267
12301
 
12302
+ function terminalRowOutcomesSummary(value: unknown): {
12303
+ rowOutcomes: Record<string, number>;
12304
+ } | null {
12305
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
12306
+ const record = value as Record<string, unknown>;
12307
+ const completedRows = finiteRunnerNumber(record.completedRows);
12308
+ const failedRows = finiteRunnerNumber(record.failedRows);
12309
+ const totalRows = finiteRunnerNumber(record.totalRows);
12310
+ const supersededRows = finiteRunnerNumber(record.supersededRows);
12311
+ const rowOutcomes: Record<string, number> = {};
12312
+ if (completedRows !== null) rowOutcomes.completedRows = completedRows;
12313
+ if (failedRows !== null) rowOutcomes.failedRows = failedRows;
12314
+ if (totalRows !== null) rowOutcomes.totalRows = totalRows;
12315
+ if (supersededRows !== null) rowOutcomes.supersededRows = supersededRows;
12316
+ return Object.keys(rowOutcomes).length > 0 ? { rowOutcomes } : null;
12317
+ }
12318
+
12268
12319
  function readPlayRunnerRuntimeTiming(
12269
12320
  value: unknown,
12270
12321
  ): PlayRunnerRuntimeTiming | null {
@@ -12425,6 +12476,18 @@ function attachRunnerWorkProgressMetadata(
12425
12476
  const skipped = finiteRunnerNumber(
12426
12477
  (runnerResult as { skipped?: unknown }).skipped,
12427
12478
  );
12479
+ const runnerRowOutcomes = terminalRowOutcomesSummary(
12480
+ (runnerResult as { rowOutcomes?: unknown }).rowOutcomes,
12481
+ )?.rowOutcomes;
12482
+ const existingRowOutcomes =
12483
+ metadata?.rowOutcomes &&
12484
+ typeof metadata.rowOutcomes === 'object' &&
12485
+ !Array.isArray(metadata.rowOutcomes)
12486
+ ? (metadata.rowOutcomes as Record<string, unknown>)
12487
+ : null;
12488
+ const rowOutcomes = runnerRowOutcomes
12489
+ ? { ...(existingRowOutcomes ?? {}), ...runnerRowOutcomes }
12490
+ : null;
12428
12491
  const logs = Array.isArray((runnerResult as { logs?: unknown }).logs)
12429
12492
  ? (runnerResult as { logs: unknown[] }).logs.filter(
12430
12493
  (line): line is string =>
@@ -12480,6 +12543,7 @@ function attachRunnerWorkProgressMetadata(
12480
12543
  (total === null || skipped === null || metadata?.workProgress) &&
12481
12544
  !runLogTail &&
12482
12545
  !runtimeResources &&
12546
+ !rowOutcomes &&
12483
12547
  mergedOutputWarnings.length === 0
12484
12548
  ) {
12485
12549
  return output;
@@ -12511,6 +12575,7 @@ function attachRunnerWorkProgressMetadata(
12511
12575
  _metadata: {
12512
12576
  ...(metadata ?? {}),
12513
12577
  ...(workProgress ? { workProgress } : {}),
12578
+ ...(rowOutcomes ? { rowOutcomes } : {}),
12514
12579
  ...(runLogTail ? { runLogTail } : {}),
12515
12580
  ...(runtimeResources ? { runtimeResources } : {}),
12516
12581
  ...(mergedOutputWarnings.length > 0
@@ -12608,6 +12673,7 @@ export async function executePostgresSchedulerClaim(
12608
12673
  attempt: claim.attempt,
12609
12674
  leaseToken: claim.leaseToken,
12610
12675
  output: terminalOutput,
12676
+ rowOutcomes: (output as { rowOutcomes?: unknown } | null)?.rowOutcomes,
12611
12677
  runtimeTiming: extractRunnerRuntimeTiming(output),
12612
12678
  terminalLogLines: terminalLogLinesForOutbox(
12613
12679
  output,
@@ -15736,6 +15802,7 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
15736
15802
  event.runId,
15737
15803
  );
15738
15804
  const lines = stringArrayPayloadField(event.payload, 'terminalLogLines');
15805
+ const resultSummary = payloadField(event.payload, 'resultSummary');
15739
15806
  return [
15740
15807
  ...progressEvents,
15741
15808
  ...(lines.length === 0
@@ -15757,6 +15824,9 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
15757
15824
  result: terminalRunResultForLedger(
15758
15825
  payloadField(event.payload, 'output'),
15759
15826
  ),
15827
+ ...(resultSummary === undefined || resultSummary === null
15828
+ ? {}
15829
+ : { resultSummary }),
15760
15830
  },
15761
15831
  ];
15762
15832
  }
@@ -15770,6 +15840,7 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
15770
15840
  const result = terminalRunResultForLedger(
15771
15841
  payloadField(event.payload, 'result'),
15772
15842
  );
15843
+ const resultSummary = payloadField(event.payload, 'resultSummary');
15773
15844
  return [
15774
15845
  ...progressEvents,
15775
15846
  ...(lines.length === 0
@@ -15790,6 +15861,9 @@ export function buildRunLedgerEventsFromPostgresSchedulerOutbox(
15790
15861
  source: 'system',
15791
15862
  error: stringPayloadField(event.payload, 'error'),
15792
15863
  ...(result === null || result === undefined ? {} : { result }),
15864
+ ...(resultSummary === undefined || resultSummary === null
15865
+ ? {}
15866
+ : { resultSummary }),
15793
15867
  },
15794
15868
  ];
15795
15869
  }
@@ -25,6 +25,7 @@ export type PlayVisualNodeProgress = {
25
25
  activeRows?: number;
26
26
  waitingRows?: number;
27
27
  completedRows?: number;
28
+ supersededRows?: number;
28
29
  message?: string;
29
30
  updatedAt?: number | null;
30
31
  startedAt?: number | null;
@@ -129,6 +130,11 @@ export function normalizePlayVisualNodeProgressMap(
129
130
  Number.isFinite(rawProgress.completedRows)
130
131
  ? rawProgress.completedRows
131
132
  : undefined;
133
+ const supersededRows =
134
+ typeof rawProgress.supersededRows === 'number' &&
135
+ Number.isFinite(rawProgress.supersededRows)
136
+ ? rawProgress.supersededRows
137
+ : undefined;
132
138
  const updatedAt =
133
139
  typeof rawProgress.updatedAt === 'number' &&
134
140
  Number.isFinite(rawProgress.updatedAt)
@@ -165,6 +171,7 @@ export function normalizePlayVisualNodeProgressMap(
165
171
  ...(activeRows !== undefined ? { activeRows } : {}),
166
172
  ...(waitingRows !== undefined ? { waitingRows } : {}),
167
173
  ...(completedRows !== undefined ? { completedRows } : {}),
174
+ ...(supersededRows !== undefined ? { supersededRows } : {}),
168
175
  ...(updatedAt !== undefined ? { updatedAt } : {}),
169
176
  ...(startedAt !== undefined ? { startedAt } : {}),
170
177
  ...(completedAt !== undefined ? { completedAt } : {}),
@@ -202,11 +202,15 @@ export function runtimeSheetPageTailWriteMarkerEvent(
202
202
  ) {
203
203
  return null;
204
204
  }
205
+ const at = new Date().toISOString();
205
206
  return {
206
207
  type: 'log',
207
- at: new Date().toISOString(),
208
+ at,
208
209
  source: 'play',
209
- line: `[runtime.sheet-page-tail-write] phase=start table=${tableNamespace} rows=${rows.length}`,
210
+ // The status projection currently exposes the durable log line without
211
+ // the event envelope's `at`. Keep the emission time in the line so the
212
+ // runtime-preview proof can measure delayed projection accurately.
213
+ line: `[${at}] [runtime.sheet-page-tail-write] phase=start table=${tableNamespace} rows=${rows.length}`,
210
214
  };
211
215
  }
212
216
 
@@ -18,6 +18,7 @@ export type PlayVisualNodeProgress = {
18
18
  activeRows?: number;
19
19
  waitingRows?: number;
20
20
  completedRows?: number;
21
+ supersededRows?: number;
21
22
  message?: string;
22
23
  updatedAt?: number;
23
24
  startedAt?: number;
package/dist/cli/index.js CHANGED
@@ -3068,7 +3068,7 @@ var SDK_RELEASE = {
3068
3068
  // getters keep their established compatibility behavior.
3069
3069
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3070
3070
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3071
- version: "0.3.145",
3071
+ version: "0.3.147",
3072
3072
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3073
3073
  packageCapabilities: {
3074
3074
  updatePreferences: 1
@@ -5313,19 +5313,32 @@ function summarizeRunRowOutcomes(snapshot) {
5313
5313
  let completedRows = 0;
5314
5314
  let failedRows = 0;
5315
5315
  let totalRows = 0;
5316
+ let supersededRows = 0;
5316
5317
  for (const step of Object.values(snapshot.stepsById)) {
5317
5318
  const progress = step.progress;
5318
5319
  if (!progress) continue;
5319
5320
  completedRows += Math.max(0, finiteNumber(progress.completed) ?? 0);
5320
5321
  failedRows += Math.max(0, finiteNumber(progress.failed) ?? 0);
5322
+ supersededRows += Math.max(0, finiteNumber(progress.supersededRows) ?? 0);
5321
5323
  const stepTotal = finiteNumber(progress.total);
5322
- totalRows += stepTotal !== null && stepTotal >= 0 ? stepTotal : Math.max(0, finiteNumber(progress.completed) ?? 0) + Math.max(0, finiteNumber(progress.failed) ?? 0);
5323
- }
5324
+ totalRows += stepTotal !== null && stepTotal >= 0 ? stepTotal : Math.max(0, finiteNumber(progress.completed) ?? 0) + Math.max(0, finiteNumber(progress.failed) ?? 0) + Math.max(0, finiteNumber(progress.supersededRows) ?? 0);
5325
+ }
5326
+ const resultSummary = isRecord5(snapshot.resultSummary) ? snapshot.resultSummary : null;
5327
+ const resultRowOutcomes = isRecord5(resultSummary?.rowOutcomes) ? resultSummary.rowOutcomes : null;
5328
+ const terminalCompletedRows = finiteNumber(resultRowOutcomes?.completedRows);
5329
+ const terminalFailedRows = finiteNumber(resultRowOutcomes?.failedRows);
5330
+ const terminalTotalRows = finiteNumber(resultRowOutcomes?.totalRows);
5331
+ const terminalSupersededRows = finiteNumber(
5332
+ resultRowOutcomes?.supersededRows
5333
+ );
5334
+ const settledCompletedRows = terminalCompletedRows ?? completedRows;
5335
+ const settledFailedRows = terminalFailedRows ?? failedRows;
5324
5336
  return {
5325
- completedRows,
5326
- failedRows,
5327
- totalRows,
5328
- hasRowFailures: failedRows > 0
5337
+ completedRows: settledCompletedRows,
5338
+ failedRows: settledFailedRows,
5339
+ totalRows: terminalTotalRows ?? totalRows,
5340
+ hasRowFailures: settledFailedRows > 0,
5341
+ ...(terminalSupersededRows ?? supersededRows) > 0 ? { supersededRows: terminalSupersededRows ?? supersededRows } : {}
5329
5342
  };
5330
5343
  }
5331
5344
  function createEmptyPlayRunLedgerSnapshot(input2) {
@@ -5483,6 +5496,7 @@ function normalizeStepProgress(value) {
5483
5496
  ...optionalFiniteNumber(value.activeRows) !== void 0 ? { activeRows: optionalFiniteNumber(value.activeRows) } : {},
5484
5497
  ...optionalFiniteNumber(value.waitingRows) !== void 0 ? { waitingRows: optionalFiniteNumber(value.waitingRows) } : {},
5485
5498
  ...optionalFiniteNumber(value.completedRows) !== void 0 ? { completedRows: optionalFiniteNumber(value.completedRows) } : {},
5499
+ ...optionalFiniteNumber(value.supersededRows) !== void 0 ? { supersededRows: optionalFiniteNumber(value.supersededRows) } : {},
5486
5500
  ...optionalString(value.message) ? { message: optionalString(value.message) } : {},
5487
5501
  ...optionalNullableString(value.artifactTableNamespace) !== void 0 ? {
5488
5502
  artifactTableNamespace: optionalNullableString(
@@ -5734,6 +5748,7 @@ function buildSnapshotFromLedger(snapshot) {
5734
5748
  activeRows: step.progress.activeRows,
5735
5749
  waitingRows: step.progress.waitingRows,
5736
5750
  completedRows: step.progress.completedRows,
5751
+ supersededRows: step.progress.supersededRows,
5737
5752
  message: step.progress.message,
5738
5753
  artifactTableNamespace: step.progress.artifactTableNamespace ?? step.artifactTableNamespace ?? null,
5739
5754
  startedAt: step.startedAt ?? null,
@@ -5747,7 +5762,8 @@ function buildSnapshotFromLedger(snapshot) {
5747
5762
  ...step.progress?.nodeIo ? { nodeIo: step.progress.nodeIo } : {}
5748
5763
  }));
5749
5764
  const liveStatus = normalizePlayRunLiveStatus(snapshot.status);
5750
- const rowOutcomes = isTerminalPlayRunLiveStatus(liveStatus) && Object.keys(snapshot.stepsById).length > 0 ? summarizeRunRowOutcomes(snapshot) : null;
5765
+ const terminalRowOutcomes = isTerminalPlayRunLiveStatus(liveStatus) ? summarizeRunRowOutcomes(snapshot) : null;
5766
+ const rowOutcomes = terminalRowOutcomes && (Object.keys(snapshot.stepsById).length > 0 || terminalRowOutcomes.totalRows > 0 || (terminalRowOutcomes.supersededRows ?? 0) > 0) ? terminalRowOutcomes : null;
5751
5767
  return {
5752
5768
  runId: snapshot.runId,
5753
5769
  status: liveStatus,
@@ -7435,7 +7451,7 @@ var DeeplineClient = class _DeeplineClient {
7435
7451
  * guaranteed support for every model. Runtime AI SDK/Gateway errors remain
7436
7452
  * authoritative for model-gated values.
7437
7453
  *
7438
- * @param model - Gateway model id such as `"openai/gpt-5.5"`
7454
+ * @param model - Exact-case Gateway model id such as `"openai/gpt-5.6-luna"`
7439
7455
  * @returns Model metadata, provider option shapes, and runnable examples
7440
7456
  */
7441
7457
  async describeModel(model) {
@@ -23656,14 +23672,18 @@ function getProgressLinesFromLiveEvent(event) {
23656
23672
  const rowOutcomes = readRowOutcomeSummary({
23657
23673
  rowOutcomes: payload.rowOutcomes
23658
23674
  });
23659
- if (rowOutcomes?.hasRowFailures) {
23675
+ if (rowOutcomes && (rowOutcomes.hasRowFailures || (rowOutcomes.supersededRows ?? 0) > 0)) {
23660
23676
  const counts = formatProgressCounts({
23661
23677
  completed: rowOutcomes.completedRows,
23662
23678
  total: rowOutcomes.totalRows,
23663
23679
  failed: rowOutcomes.failedRows
23664
23680
  });
23665
- if (counts) {
23666
- lines.push(`progress run outcomes: ${counts}`);
23681
+ const outcomeParts = [
23682
+ counts,
23683
+ ...rowOutcomes && (rowOutcomes.supersededRows ?? 0) > 0 ? [formatSupersededRowsNotice(rowOutcomes.supersededRows)] : []
23684
+ ].filter((part) => Boolean(part));
23685
+ if (outcomeParts.length > 0) {
23686
+ lines.push(`progress run outcomes: ${outcomeParts.join(", ")}`);
23667
23687
  }
23668
23688
  }
23669
23689
  return lines;
@@ -24542,9 +24562,13 @@ function buildRunWarnings(status, rowsInfo) {
24542
24562
  const rowOutcomeWarnings = rowOutcomes?.hasRowFailures ? [
24543
24563
  `${status.status === "completed" ? "Run completed" : "Run ended"} with ${formatInteger(rowOutcomes.failedRows)} failed row(s); inspect the persisted failed rows before treating the output as complete.`
24544
24564
  ] : [];
24565
+ const supersededRowNotices = (rowOutcomes?.supersededRows ?? 0) > 0 ? [
24566
+ `Latest-write-wins: ${formatSupersededRowsNotice(rowOutcomes.supersededRows ?? 0)}; the newer write still owns that Runtime Sheet row.`
24567
+ ] : [];
24545
24568
  if (status.status === "completed" && rowsInfo?.totalRows === 0) {
24546
24569
  return [
24547
24570
  ...rowOutcomeWarnings,
24571
+ ...supersededRowNotices,
24548
24572
  "Run completed with 0 output rows.",
24549
24573
  ...outputWarnings
24550
24574
  ];
@@ -24552,11 +24576,12 @@ function buildRunWarnings(status, rowsInfo) {
24552
24576
  if (rowsInfo && !rowsInfo.complete) {
24553
24577
  return [
24554
24578
  ...rowOutcomeWarnings,
24579
+ ...supersededRowNotices,
24555
24580
  `Run output is partial: showing ${rowsInfo.rows.length} preview row(s) of ${rowsInfo.totalRows}.`,
24556
24581
  ...outputWarnings
24557
24582
  ];
24558
24583
  }
24559
- return [...rowOutcomeWarnings, ...outputWarnings];
24584
+ return [...rowOutcomeWarnings, ...supersededRowNotices, ...outputWarnings];
24560
24585
  }
24561
24586
  function buildRunNextCommands(status) {
24562
24587
  const runId = status.runId?.trim();
@@ -24592,6 +24617,9 @@ function getNumericField(value, key) {
24592
24617
  const field = getRecordField(value, key);
24593
24618
  return typeof field === "number" && Number.isFinite(field) ? field : null;
24594
24619
  }
24620
+ function formatSupersededRowsNotice(count) {
24621
+ return `${formatInteger(count)} row${count === 1 ? "" : "s"} skipped because a newer Runtime Sheet write took precedence`;
24622
+ }
24595
24623
  function readRowOutcomeSummary(value) {
24596
24624
  const record3 = getRecordField(value, "rowOutcomes");
24597
24625
  if (!record3) return null;
@@ -24602,11 +24630,13 @@ function readRowOutcomeSummary(value) {
24602
24630
  return null;
24603
24631
  }
24604
24632
  const explicitHasFailures = getRecordField(record3, "hasRowFailures");
24633
+ const supersededRows = getNumericField(record3, "supersededRows");
24605
24634
  return {
24606
24635
  completedRows,
24607
24636
  failedRows,
24608
24637
  totalRows,
24609
- hasRowFailures: typeof explicitHasFailures === "boolean" ? explicitHasFailures : failedRows > 0
24638
+ hasRowFailures: typeof explicitHasFailures === "boolean" ? explicitHasFailures : failedRows > 0,
24639
+ ...supersededRows !== null ? { supersededRows: Math.max(0, supersededRows) } : {}
24610
24640
  };
24611
24641
  }
24612
24642
  function getStringField(value, key) {
@@ -24849,12 +24879,16 @@ function normalizeProgressForEnvelope(status, rowsInfo) {
24849
24879
  const total = rowOutcomes?.totalRows ?? getNumericField(progress, "totalRows") ?? getNumericField(progress, "total") ?? rowsInfo?.totalRows ?? null;
24850
24880
  const failed = rowOutcomes?.failedRows ?? getNumericField(progress, "failed") ?? getNumericField(progress, "failedRows") ?? null;
24851
24881
  const completed = rowOutcomes?.completedRows ?? getNumericField(progress, "completed") ?? getNumericField(progress, "completedRows") ?? (status.status === "completed" ? total : null);
24852
- const pending = getNumericField(progress, "pending") ?? (typeof total === "number" && typeof completed === "number" && typeof failed === "number" ? Math.max(0, total - completed - failed) : null);
24882
+ const supersededRows = rowOutcomes?.supersededRows ?? getNumericField(progress, "supersededRows");
24883
+ const supersededOffset = supersededRows ?? 0;
24884
+ const progressPending = getNumericField(progress, "pending");
24885
+ const pending = (progressPending !== null ? Math.max(0, progressPending - supersededOffset) : null) ?? (typeof total === "number" && typeof completed === "number" && typeof failed === "number" ? Math.max(0, total - completed - failed - supersededOffset) : null);
24853
24886
  return {
24854
24887
  total,
24855
24888
  totalRows: total,
24856
24889
  completed,
24857
24890
  completedRows: completed,
24891
+ ...supersededRows !== null ? { supersededRows: Math.max(0, supersededRows) } : {},
24858
24892
  pending,
24859
24893
  failed,
24860
24894
  executed: getNumericField(progress, "executed"),
@@ -24985,6 +25019,9 @@ function compactPlayStatus(status) {
24985
25019
  ) : [],
24986
25020
  ...rowOutcomes2.hasRowFailures ? [
24987
25021
  `${status.status === "completed" ? "Run completed" : "Run ended"} with ${formatInteger(rowOutcomes2.failedRows)} failed row(s); inspect the persisted failed rows before treating the output as complete.`
25022
+ ] : [],
25023
+ ...(rowOutcomes2.supersededRows ?? 0) > 0 ? [
25024
+ `Latest-write-wins: ${formatSupersededRowsNotice(rowOutcomes2.supersededRows ?? 0)}; the newer write still owns that Runtime Sheet row.`
24988
25025
  ] : []
24989
25026
  ]
24990
25027
  } : packaged;
@@ -47939,7 +47976,7 @@ Examples:
47939
47976
  deepline tools describe hunter_email_verifier --schema-only
47940
47977
  deepline tools describe hunter_email_verifier --examples-only
47941
47978
  deepline tools describe hunter_email_verifier --json
47942
- deepline tools describe deeplineagent --model openai/gpt-5.5 --json
47979
+ deepline tools describe deeplineagent --model openai/gpt-5.6-luna --json
47943
47980
  deepline tools describe ai_inference --estimate-payload @payload.json --json
47944
47981
  deepline tools describe ai_evaluate --estimate-payload @payload.json --json
47945
47982
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
@@ -47985,9 +48022,11 @@ Notes:
47985
48022
  waterfalls, row maps, checkpoints, and retries.
47986
48023
  Calling a provider-backed tool can spend Deepline credits. Use --json for the
47987
48024
  stable result payload plus output preview and debugging helpers.
48025
+ --timeout sets this CLI request's HTTP deadline; it does not cancel provider work.
47988
48026
 
47989
48027
  Examples:
47990
48028
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
48029
+ deepline tools execute bounceban_verify_bulk --input @batch.json --timeout 10m --json
47991
48030
  deepline tools execute hunter_email_verifier -p email=a@b.com
47992
48031
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --timeout 90s --json
47993
48032
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --json | jq '.status'
@@ -48012,7 +48051,7 @@ Examples:
48012
48051
  "Merge a JSON object or @file path into the tool params"
48013
48052
  ).option(
48014
48053
  "--timeout <duration>",
48015
- "Execution HTTP deadline (for example 90s, 5m, or 1h; bare numbers are seconds)"
48054
+ "Client-side HTTP deadline (for example 90s, 5m, or 1h; bare numbers are seconds); it does not cancel provider work"
48016
48055
  ).option(
48017
48056
  "--output-format <format>",
48018
48057
  "Output format: auto, csv, csv_file, json, or json_file"
@@ -49637,6 +49676,7 @@ async function executeTool(args) {
49637
49676
  return 2;
49638
49677
  }
49639
49678
  const rawResponse = await client2.executeTool(parsed.toolId, parsed.params, {
49679
+ ...parsed.timeoutMs !== void 0 ? { timeout: parsed.timeoutMs } : {},
49640
49680
  responseIntent: parsed.outPath || parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file" ? "row_artifact" : "raw",
49641
49681
  ...parsed.timeoutMs !== void 0 ? { timeout: parsed.timeoutMs } : {}
49642
49682
  });