deepline 0.3.145 → 0.3.146

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.
@@ -59,16 +59,16 @@ export type PlayRunLedgerEventSource =
59
59
  * these; they re-execute on the next run).
60
60
  * - `total` is the settled-row denominator. In-flight it is the row-count
61
61
  * estimate (`rowCountHint`); at map finalize it is reconciled to
62
- * `completed + failed` and CAN SHRINK from the initial estimate when rows are
63
- * filtered/skipped. So `total` is monotonic-up during flight but is corrected
64
- * down to the settled count at terminal.
62
+ * `completed + failed + supersededRows` and CAN SHRINK from the initial
63
+ * estimate when rows are filtered/skipped. So `total` is monotonic-up during
64
+ * flight but is corrected down to the settled count at terminal.
65
65
  *
66
- * Terminal invariant: once the step is settled, `completed + failed === total`.
67
- * Because `completed` is successes-only (NOT all-settled), readers must NOT
68
- * assume `completed === total` at terminal a truthful terminal render is
69
- * `{total} rows` when `failed === 0`, else a `completed`/`failed`/`total`
70
- * breakdown. See `settleRunningStepsOnTerminal` for why the reducer does not
71
- * force `completed = total`.
66
+ * Terminal invariant: once the step is settled,
67
+ * `completed + failed + supersededRows === total` when supersededRows is
68
+ * present; older producers without that field use `completed + failed ===
69
+ * total`. Because `completed` is successes-only (NOT all-settled), readers
70
+ * must not assume `completed === total`. Superseded rows are omitted because a
71
+ * newer Runtime Sheet write won, not because this step failed.
72
72
  */
73
73
  export type PlayRunLedgerStepProgress = {
74
74
  completed?: number;
@@ -78,6 +78,7 @@ export type PlayRunLedgerStepProgress = {
78
78
  activeRows?: number;
79
79
  waitingRows?: number;
80
80
  completedRows?: number;
81
+ supersededRows?: number;
81
82
  message?: string;
82
83
  artifactTableNamespace?: string | null;
83
84
  startedAt?: number | null;
@@ -209,6 +210,7 @@ export type PlayRunLedgerEvent =
209
210
  type: 'run.failed';
210
211
  error?: string | null;
211
212
  result?: unknown;
213
+ resultSummary?: unknown;
212
214
  })
213
215
  | (PlayRunLedgerBaseEvent & {
214
216
  type: 'run.cancelled';
@@ -463,14 +465,17 @@ export type PlayRunRowOutcomeSummary = {
463
465
  failedRows: number;
464
466
  totalRows: number;
465
467
  hasRowFailures: boolean;
468
+ supersededRows?: number;
466
469
  };
467
470
 
468
471
  export function summarizeRunRowOutcomes(
469
- snapshot: Pick<PlayRunLedgerSnapshot, 'stepsById'>,
472
+ snapshot: Pick<PlayRunLedgerSnapshot, 'stepsById'> &
473
+ Partial<Pick<PlayRunLedgerSnapshot, 'resultSummary'>>,
470
474
  ): PlayRunRowOutcomeSummary {
471
475
  let completedRows = 0;
472
476
  let failedRows = 0;
473
477
  let totalRows = 0;
478
+ let supersededRows = 0;
474
479
  for (const step of Object.values(snapshot.stepsById)) {
475
480
  const progress = step.progress;
476
481
  if (!progress) continue;
@@ -479,20 +484,39 @@ export function summarizeRunRowOutcomes(
479
484
  // row outcome, not just the last step.
480
485
  completedRows += Math.max(0, finiteNumber(progress.completed) ?? 0);
481
486
  failedRows += Math.max(0, finiteNumber(progress.failed) ?? 0);
482
- // Prefer the settled denominator; fall back to completed+failed when a
483
- // producer never stamped `total` (per the terminal invariant those agree).
487
+ supersededRows += Math.max(0, finiteNumber(progress.supersededRows) ?? 0);
488
+ // Prefer the settled denominator; fall back to completed+failed+superseded
489
+ // when a producer never stamped `total`.
484
490
  const stepTotal = finiteNumber(progress.total);
485
491
  totalRows +=
486
492
  stepTotal !== null && stepTotal >= 0
487
493
  ? stepTotal
488
494
  : Math.max(0, finiteNumber(progress.completed) ?? 0) +
489
- Math.max(0, finiteNumber(progress.failed) ?? 0);
495
+ Math.max(0, finiteNumber(progress.failed) ?? 0) +
496
+ Math.max(0, finiteNumber(progress.supersededRows) ?? 0);
490
497
  }
498
+ const resultSummary = isRecord(snapshot.resultSummary)
499
+ ? snapshot.resultSummary
500
+ : null;
501
+ const resultRowOutcomes = isRecord(resultSummary?.rowOutcomes)
502
+ ? resultSummary.rowOutcomes
503
+ : null;
504
+ const terminalCompletedRows = finiteNumber(resultRowOutcomes?.completedRows);
505
+ const terminalFailedRows = finiteNumber(resultRowOutcomes?.failedRows);
506
+ const terminalTotalRows = finiteNumber(resultRowOutcomes?.totalRows);
507
+ const terminalSupersededRows = finiteNumber(
508
+ resultRowOutcomes?.supersededRows,
509
+ );
510
+ const settledCompletedRows = terminalCompletedRows ?? completedRows;
511
+ const settledFailedRows = terminalFailedRows ?? failedRows;
491
512
  return {
492
- completedRows,
493
- failedRows,
494
- totalRows,
495
- hasRowFailures: failedRows > 0,
513
+ completedRows: settledCompletedRows,
514
+ failedRows: settledFailedRows,
515
+ totalRows: terminalTotalRows ?? totalRows,
516
+ hasRowFailures: settledFailedRows > 0,
517
+ ...((terminalSupersededRows ?? supersededRows) > 0
518
+ ? { supersededRows: terminalSupersededRows ?? supersededRows }
519
+ : {}),
496
520
  };
497
521
  }
498
522
 
@@ -762,6 +786,11 @@ function mergeMonotonicStepProgress(input: {
762
786
  ),
763
787
  }
764
788
  : {}),
789
+ ...(next.supersededRows !== undefined
790
+ ? { supersededRows: Math.max(0, next.supersededRows) }
791
+ : current.supersededRows !== undefined
792
+ ? { supersededRows: current.supersededRows }
793
+ : {}),
765
794
  };
766
795
  }
767
796
 
@@ -771,8 +800,8 @@ function mergeMonotonicStepProgress(input: {
771
800
  * live-only counters: once a step is terminal nothing is in flight or waiting,
772
801
  * so leaving the last observed values renders a contradiction like
773
802
  * "status: completed · 1 in flight · waiting 29". This preserves the settled
774
- * counts (completed/failed/total/completedRows/startedRows) and only clears the
775
- * two live accumulators. Idempotent: dropping already-absent fields is a no-op.
803
+ * counts (including supersededRows) and only clears the two live accumulators.
804
+ * Idempotent: dropping already-absent fields is a no-op.
776
805
  */
777
806
  function clearInFlightProgressOnTerminal(
778
807
  progress: PlayRunLedgerStepProgress | null | undefined,
@@ -831,6 +860,9 @@ function normalizeStepProgress(
831
860
  ...(optionalFiniteNumber(value.completedRows) !== undefined
832
861
  ? { completedRows: optionalFiniteNumber(value.completedRows) }
833
862
  : {}),
863
+ ...(optionalFiniteNumber(value.supersededRows) !== undefined
864
+ ? { supersededRows: optionalFiniteNumber(value.supersededRows) }
865
+ : {}),
834
866
  ...(optionalString(value.message)
835
867
  ? { message: optionalString(value.message) }
836
868
  : {}),
@@ -1309,6 +1341,8 @@ export function reducePlayRunLedgerEvent(
1309
1341
  allowStaleSameStatusPayloadMerge:
1310
1342
  (base.error == null && event.error != null) ||
1311
1343
  (base.result === undefined && event.result !== undefined) ||
1344
+ (base.resultSummary === undefined &&
1345
+ event.resultSummary !== undefined) ||
1312
1346
  canPromoteTerminalResultReference(base.result, event.result),
1313
1347
  }) ??
1314
1348
  withTiming({
@@ -1327,6 +1361,7 @@ export function reducePlayRunLedgerEvent(
1327
1361
  current: base.result,
1328
1362
  next: event.result,
1329
1363
  }),
1364
+ resultSummary: event.resultSummary ?? base.resultSummary,
1330
1365
  terminalSource: nextTerminalSource(base, event.source),
1331
1366
  })
1332
1367
  );
@@ -1657,6 +1692,7 @@ function progressSignature(
1657
1692
  activeRows: progress?.activeRows ?? null,
1658
1693
  waitingRows: progress?.waitingRows ?? null,
1659
1694
  completedRows: progress?.completedRows ?? null,
1695
+ supersededRows: progress?.supersededRows ?? null,
1660
1696
  message: progress?.message ?? null,
1661
1697
  artifactTableNamespace: progress?.artifactTableNamespace ?? null,
1662
1698
  startedAt: progress?.startedAt ?? null,
@@ -1913,6 +1949,9 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
1913
1949
  ...(progress.completedRows !== undefined
1914
1950
  ? { completedRows: progress.completedRows }
1915
1951
  : {}),
1952
+ ...(progress.supersededRows !== undefined
1953
+ ? { supersededRows: progress.supersededRows }
1954
+ : {}),
1916
1955
  ...(progress.message !== undefined ? { message: progress.message } : {}),
1917
1956
  ...(progress.artifactTableNamespace !== undefined
1918
1957
  ? { artifactTableNamespace: progress.artifactTableNamespace }
@@ -103,11 +103,11 @@ export type PlayRunLiveSnapshot = {
103
103
  nodeStates: PlayRunStreamNodeState[];
104
104
  activeNodeId: string | null;
105
105
  /**
106
- * Additive, terminal-only aggregate of row outcomes across all steps. Present
107
- * once the run is terminal so readers can render a truthful "completed with
108
- * failures" surface (row-failure isolation persists failed rows for retry, so
109
- * a run legitimately reports `status: 'completed'` with `rowOutcomes.failedRows
110
- * > 0`). Absent on non-terminal snapshots and on runs with no row/map steps.
106
+ * Additive, terminal-only aggregate of row outcomes across all steps. It lets
107
+ * readers distinguish successful, failed, and superseded rows. Superseded
108
+ * rows were omitted because a newer Runtime Sheet write won; they are neither
109
+ * failures nor pending work. Absent on non-terminal snapshots and runs
110
+ * without row outcomes.
111
111
  */
112
112
  rowOutcomes?: PlayRunRowOutcomeSummary;
113
113
  };
@@ -205,6 +205,7 @@ function buildSnapshotFromLedger(
205
205
  activeRows: step.progress.activeRows,
206
206
  waitingRows: step.progress.waitingRows,
207
207
  completedRows: step.progress.completedRows,
208
+ supersededRows: step.progress.supersededRows,
208
209
  message: step.progress.message,
209
210
  artifactTableNamespace:
210
211
  step.progress.artifactTableNamespace ??
@@ -222,13 +223,18 @@ function buildSnapshotFromLedger(
222
223
  ...(step.progress?.nodeIo ? { nodeIo: step.progress.nodeIo } : {}),
223
224
  }));
224
225
  const liveStatus = normalizePlayRunLiveStatus(snapshot.status);
225
- // Only surface the row-outcome aggregate once the run is terminal and it
226
- // actually observed row/map steps mid-flight `failed` counts churn, and a
227
- // no-map play has no meaningful row outcome to report.
226
+ // Only surface the aggregate once terminal: live `failed` counts churn.
227
+ // Prefer the runner's terminal summary when available (it survives detached
228
+ // checkpoint omission), falling back to the reconciled step progress.
229
+ const terminalRowOutcomes = isTerminalPlayRunLiveStatus(liveStatus)
230
+ ? summarizeRunRowOutcomes(snapshot)
231
+ : null;
228
232
  const rowOutcomes =
229
- isTerminalPlayRunLiveStatus(liveStatus) &&
230
- Object.keys(snapshot.stepsById).length > 0
231
- ? summarizeRunRowOutcomes(snapshot)
233
+ terminalRowOutcomes &&
234
+ (Object.keys(snapshot.stepsById).length > 0 ||
235
+ terminalRowOutcomes.totalRows > 0 ||
236
+ (terminalRowOutcomes.supersededRows ?? 0) > 0)
237
+ ? terminalRowOutcomes
232
238
  : null;
233
239
  return {
234
240
  runId: snapshot.runId,
@@ -1831,6 +1831,55 @@ function terminalLogsWithPhaseSummary(ctx: {
1831
1831
  ];
1832
1832
  }
1833
1833
 
1834
+ function rowOutcomesFromCheckpoint(checkpoint: {
1835
+ mapFrames?: Record<
1836
+ string,
1837
+ {
1838
+ completedRowsCount?: number;
1839
+ completedRowKeys?: string[];
1840
+ failedRowsCount?: number;
1841
+ totalRows?: number;
1842
+ supersededRows?: number;
1843
+ }
1844
+ >;
1845
+ }): {
1846
+ completedRows: number;
1847
+ failedRows: number;
1848
+ totalRows: number;
1849
+ supersededRows?: number;
1850
+ } | null {
1851
+ const frames = Object.values(checkpoint.mapFrames ?? {});
1852
+ if (frames.length === 0) return null;
1853
+ let completedRows = 0;
1854
+ let failedRows = 0;
1855
+ let totalRows = 0;
1856
+ let supersededRows = 0;
1857
+ for (const frame of frames) {
1858
+ const completed = Number.isFinite(frame.completedRowsCount)
1859
+ ? Math.max(0, Math.floor(frame.completedRowsCount ?? 0))
1860
+ : Math.max(0, frame.completedRowKeys?.length ?? 0);
1861
+ const failed = Number.isFinite(frame.failedRowsCount)
1862
+ ? Math.max(0, Math.floor(frame.failedRowsCount ?? 0))
1863
+ : 0;
1864
+ const superseded = Number.isFinite(frame.supersededRows)
1865
+ ? Math.max(0, Math.floor(frame.supersededRows ?? 0))
1866
+ : 0;
1867
+ completedRows += completed;
1868
+ failedRows += failed;
1869
+ supersededRows += superseded;
1870
+ totalRows +=
1871
+ Number.isFinite(frame.totalRows) && (frame.totalRows ?? 0) >= 0
1872
+ ? Math.floor(frame.totalRows ?? 0)
1873
+ : completed + failed + superseded;
1874
+ }
1875
+ return {
1876
+ completedRows,
1877
+ failedRows,
1878
+ totalRows,
1879
+ supersededRows,
1880
+ };
1881
+ }
1882
+
1834
1883
  async function run(
1835
1884
  config: PlayRunnerExecutionConfig,
1836
1885
  options?: ExecutePlayRunnerOptions,
@@ -3125,6 +3174,8 @@ async function run(
3125
3174
  ]),
3126
3175
  ).values(),
3127
3176
  ).slice(0, 16);
3177
+ const checkpoint = ctx.getCheckpoint();
3178
+ const rowOutcomes = rowOutcomesFromCheckpoint(checkpoint);
3128
3179
 
3129
3180
  return {
3130
3181
  status: 'completed' as const,
@@ -3135,9 +3186,10 @@ async function run(
3135
3186
  outputRowCount,
3136
3187
  logs,
3137
3188
  ...(runtimeDiagnostics.length > 0 ? { runtimeDiagnostics } : {}),
3189
+ ...(rowOutcomes ? { rowOutcomes } : {}),
3138
3190
  stats: ctx.getStats(),
3139
3191
  steps: ctx.getSteps(),
3140
- checkpoint: ctx.getCheckpoint(),
3192
+ checkpoint,
3141
3193
  tableNamespace: resultTableNamespace,
3142
3194
  totalRows,
3143
3195
  inserted,
@@ -3215,14 +3267,17 @@ async function run(
3215
3267
  ensureSourceMapSupport();
3216
3268
  const failure = normalizePlayRunFailure(error);
3217
3269
  logRecovery();
3270
+ const checkpoint = ctx.getCheckpoint();
3271
+ const rowOutcomes = rowOutcomesFromCheckpoint(checkpoint);
3218
3272
  return {
3219
3273
  status: 'failed',
3220
3274
  error: formatRunnerFailure(error),
3221
3275
  errors: [failure],
3222
3276
  logs: terminalLogsWithPhaseSummary(ctx),
3277
+ ...(rowOutcomes ? { rowOutcomes } : {}),
3223
3278
  stats: ctx.getStats(),
3224
3279
  steps: ctx.getSteps(),
3225
- checkpoint: ctx.getCheckpoint(),
3280
+ checkpoint,
3226
3281
  tableNamespace: null,
3227
3282
  totalRows,
3228
3283
  inserted,
@@ -159,10 +159,14 @@ function resolveDatasetNodeRefFromTableNamespace(
159
159
  function rowsProcessedMessage(
160
160
  completed: number,
161
161
  total: number | undefined,
162
+ supersededRows = 0,
162
163
  ): string | undefined {
163
- return total !== undefined && total > 0
164
- ? `${Math.max(0, completed).toLocaleString()} / ${total.toLocaleString()} rows processed`
165
- : undefined;
164
+ if (total === undefined || total <= 0) return undefined;
165
+ const skipped = Math.max(0, supersededRows);
166
+ const base = `${Math.max(0, completed).toLocaleString()} / ${total.toLocaleString()} rows processed`;
167
+ return skipped > 0
168
+ ? `${base}; ${skipped.toLocaleString()} skipped because a newer Runtime Sheet write took precedence`
169
+ : base;
166
170
  }
167
171
 
168
172
  function callsInFlightMessage(input: {
@@ -597,6 +601,9 @@ export function createPostgresSchedulerProgressReporter(input: {
597
601
  ...(current.completedRows !== undefined
598
602
  ? { completedRows: current.completedRows }
599
603
  : {}),
604
+ ...(current.supersededRows !== undefined
605
+ ? { supersededRows: current.supersededRows }
606
+ : {}),
600
607
  ...(current.message !== undefined ? { message: current.message } : {}),
601
608
  ...(current.artifactTableNamespace !== undefined
602
609
  ? { artifactTableNamespace: current.artifactTableNamespace }
@@ -625,6 +632,9 @@ export function createPostgresSchedulerProgressReporter(input: {
625
632
  ...(patch.completedRows !== undefined
626
633
  ? { completedRows: patch.completedRows }
627
634
  : {}),
635
+ ...(patch.supersededRows !== undefined
636
+ ? { supersededRows: patch.supersededRows }
637
+ : {}),
628
638
  ...(patch.message !== undefined ? { message: patch.message } : {}),
629
639
  ...(patch.artifactTableNamespace !== undefined
630
640
  ? { artifactTableNamespace: patch.artifactTableNamespace }
@@ -926,25 +936,40 @@ export function createPostgresSchedulerProgressReporter(input: {
926
936
  completed: event.completedRows,
927
937
  failed: 0,
928
938
  total: eventTotalRows,
929
- startedRows: event.completedRows,
939
+ startedRows: event.completedRows + (event.supersededRows ?? 0),
930
940
  activeRows: 0,
931
941
  waitingRows:
932
942
  typeof eventTotalRows === 'number'
933
- ? Math.max(0, eventTotalRows - event.completedRows)
943
+ ? Math.max(
944
+ 0,
945
+ eventTotalRows -
946
+ event.completedRows -
947
+ (event.supersededRows ?? 0),
948
+ )
934
949
  : undefined,
935
950
  completedRows: event.completedRows,
951
+ ...(event.supersededRows !== undefined
952
+ ? { supersededRows: event.supersededRows }
953
+ : {}),
936
954
  artifactTableNamespace: event.artifactTableNamespace,
937
955
  startedAt: Date.now(),
938
956
  message:
939
957
  event.type === 'map.preparing'
940
958
  ? 'Preparing durable table...'
941
- : rowsProcessedMessage(event.completedRows, eventTotalRows ?? 0),
959
+ : rowsProcessedMessage(
960
+ event.completedRows,
961
+ eventTotalRows ?? 0,
962
+ event.supersededRows,
963
+ ),
942
964
  });
943
965
  return;
944
966
  }
945
967
  if (event.type === 'map.progress') {
946
968
  const current = liveNodeProgress[nodeId] ?? {};
947
- const settled = Math.max(0, event.completedRows + event.failedRows);
969
+ const settled = Math.max(
970
+ 0,
971
+ event.completedRows + event.failedRows + (event.supersededRows ?? 0),
972
+ );
948
973
  const progressTotalRows = Math.max(
949
974
  typeof event.totalRows === 'number' && Number.isFinite(event.totalRows)
950
975
  ? event.totalRows
@@ -964,8 +989,15 @@ export function createPostgresSchedulerProgressReporter(input: {
964
989
  ? Math.max(0, progressTotalRows - startedRows)
965
990
  : undefined,
966
991
  completedRows: event.completedRows,
992
+ ...(event.supersededRows !== undefined
993
+ ? { supersededRows: event.supersededRows }
994
+ : {}),
967
995
  artifactTableNamespace: event.artifactTableNamespace,
968
- message: rowsProcessedMessage(event.completedRows, progressTotalRows),
996
+ message: rowsProcessedMessage(
997
+ event.completedRows,
998
+ progressTotalRows,
999
+ event.supersededRows,
1000
+ ),
969
1001
  });
970
1002
  return;
971
1003
  }
@@ -975,7 +1007,10 @@ export function createPostgresSchedulerProgressReporter(input: {
975
1007
  } else {
976
1008
  stepLifecycle.onMapCompleted(nodeId);
977
1009
  }
978
- const processedRows = Math.max(0, event.completedRows + event.failedRows);
1010
+ const processedRows = Math.max(
1011
+ 0,
1012
+ event.completedRows + event.failedRows + (event.supersededRows ?? 0),
1013
+ );
979
1014
  const terminalTotal =
980
1015
  typeof event.totalRows === 'number' && Number.isFinite(event.totalRows)
981
1016
  ? event.totalRows
@@ -991,9 +1026,16 @@ export function createPostgresSchedulerProgressReporter(input: {
991
1026
  activeRows: 0,
992
1027
  waitingRows: 0,
993
1028
  completedRows: event.completedRows,
1029
+ ...(event.supersededRows !== undefined
1030
+ ? { supersededRows: event.supersededRows }
1031
+ : {}),
994
1032
  artifactTableNamespace: event.artifactTableNamespace,
995
1033
  completedAt: Date.now(),
996
- message: rowsProcessedMessage(event.completedRows, event.totalRows),
1034
+ message: rowsProcessedMessage(
1035
+ event.completedRows,
1036
+ event.totalRows,
1037
+ event.supersededRows,
1038
+ ),
997
1039
  });
998
1040
  activeMapNodeId = null;
999
1041
  return;
@@ -1151,12 +1193,19 @@ export function createPostgresSchedulerProgressReporter(input: {
1151
1193
  activeRows: 0,
1152
1194
  waitingRows: 0,
1153
1195
  completedRows: completed,
1196
+ ...(frame.supersededRows !== undefined
1197
+ ? { supersededRows: Math.max(0, frame.supersededRows) }
1198
+ : {}),
1154
1199
  artifactTableNamespace:
1155
1200
  frame.artifactTableNamespace ||
1156
1201
  existing.artifactTableNamespace ||
1157
1202
  undefined,
1158
1203
  completedAt: existing.completedAt ?? Date.now(),
1159
- message: rowsProcessedMessage(completed, total > 0 ? total : undefined),
1204
+ message: rowsProcessedMessage(
1205
+ completed,
1206
+ total > 0 ? total : undefined,
1207
+ frame.supersededRows ?? existing.supersededRows ?? 0,
1208
+ ),
1160
1209
  });
1161
1210
  }
1162
1211
  liveNodeProgressDirty = true;
@@ -1199,18 +1248,22 @@ export function createPostgresSchedulerProgressReporter(input: {
1199
1248
  if (!nodeRef) continue;
1200
1249
  const completed = Math.max(0, Math.floor(outcome.completed) || 0);
1201
1250
  const failed = Math.max(0, Math.floor(outcome.failed) || 0);
1202
- const total =
1251
+ const existing = liveNodeProgress[nodeRef.nodeId] ?? {};
1252
+ const supersededRows = Math.max(0, existing.supersededRows ?? 0);
1253
+ const sheetTotal =
1203
1254
  Number.isFinite(outcome.total) && outcome.total > 0
1204
1255
  ? Math.floor(outcome.total)
1205
1256
  : completed + failed;
1206
- if (total <= 0 && completed <= 0 && failed <= 0) continue;
1207
- const existing = liveNodeProgress[nodeRef.nodeId] ?? {};
1257
+ const total = Math.max(sheetTotal, completed + failed + supersededRows);
1258
+ if (total <= 0 && completed <= 0 && failed <= 0 && supersededRows <= 0) {
1259
+ continue;
1260
+ }
1208
1261
  const now = Date.now();
1209
1262
  setNodeProgress(nodeRef.nodeId, {
1210
1263
  completed,
1211
1264
  failed,
1212
1265
  total: total > 0 ? total : undefined,
1213
- startedRows: total > 0 ? total : completed + failed,
1266
+ startedRows: total > 0 ? total : completed + failed + supersededRows,
1214
1267
  activeRows: 0,
1215
1268
  waitingRows: 0,
1216
1269
  completedRows: completed,
@@ -1218,7 +1271,11 @@ export function createPostgresSchedulerProgressReporter(input: {
1218
1271
  existing.artifactTableNamespace ?? nodeRef.artifactTableNamespace,
1219
1272
  startedAt: existing.startedAt ?? now,
1220
1273
  completedAt: existing.completedAt ?? now,
1221
- message: rowsProcessedMessage(completed, total > 0 ? total : undefined),
1274
+ message: rowsProcessedMessage(
1275
+ completed,
1276
+ total > 0 ? total : undefined,
1277
+ existing.supersededRows ?? 0,
1278
+ ),
1222
1279
  });
1223
1280
  }
1224
1281
  liveNodeProgressDirty = true;