deepline 0.3.270 → 0.3.272

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 (29) hide show
  1. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  2. package/dist/bundling-sources/shared_libs/play-runtime/activity-observation.ts +3 -2
  3. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +11 -9
  4. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5 -4
  5. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +2 -1
  6. package/dist/bundling-sources/shared_libs/play-runtime/run-event-catalog.ts +610 -0
  7. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +3 -1
  8. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-projection-diagnostics.ts +3 -2
  9. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +80 -67
  10. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +5 -4
  11. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +59 -20
  12. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +3 -2
  13. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +19 -9
  14. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +205 -107
  15. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +125 -81
  16. package/dist/cli/getting-started.d.mts +13 -9
  17. package/dist/cli/getting-started.d.ts +13 -9
  18. package/dist/cli/getting-started.js +15 -3
  19. package/dist/cli/getting-started.mjs +13 -3
  20. package/dist/cli/index.js +447 -11
  21. package/dist/cli/index.mjs +447 -11
  22. package/dist/index.js +420 -1
  23. package/dist/index.mjs +420 -1
  24. package/dist/install-integrity.json +1 -0
  25. package/dist/release.d.mts +1 -1
  26. package/dist/release.d.ts +1 -1
  27. package/dist/release.js +1 -1
  28. package/dist/release.mjs +1 -1
  29. package/package.json +1 -1
@@ -23,6 +23,7 @@ import {
23
23
  } from './cell-provenance';
24
24
  import { isLedgerTerminalResultRef } from './output-size-limits';
25
25
  import type { PlayLogContext } from './log-context';
26
+ import { RUN_EVENT_KIND, type RunEventSource } from './run-event-catalog';
26
27
 
27
28
  export type PlayRunLedgerStatus =
28
29
  | 'queued'
@@ -41,11 +42,7 @@ export type PlayRunLedgerStepStatus =
41
42
  | 'failed'
42
43
  | 'skipped';
43
44
 
44
- export type PlayRunLedgerEventSource =
45
- | 'worker'
46
- | 'convex'
47
- | 'coordinator'
48
- | 'system';
45
+ export type PlayRunLedgerEventSource = RunEventSource;
49
46
 
50
47
  /**
51
48
  * Live progress for a single step/node.
@@ -228,51 +225,51 @@ type PlayRunLedgerBaseEvent = {
228
225
 
229
226
  export type PlayRunLedgerEvent =
230
227
  | (PlayRunLedgerBaseEvent & {
231
- type: 'run.created';
228
+ type: typeof RUN_EVENT_KIND.runCreated;
232
229
  playName?: string | null;
233
230
  status?: PlayRunLedgerStatus;
234
231
  runtimeBackend?: string | null;
235
232
  })
236
233
  | (PlayRunLedgerBaseEvent & {
237
- type: 'run.started';
234
+ type: typeof RUN_EVENT_KIND.runStarted;
238
235
  playName?: string | null;
239
236
  runtimeBackend?: string | null;
240
237
  })
241
238
  | (PlayRunLedgerBaseEvent & {
242
- type: 'run.waiting';
239
+ type: typeof RUN_EVENT_KIND.runWaiting;
243
240
  waitKind?: string | null;
244
241
  waitUntil?: number | null;
245
242
  })
246
243
  | (PlayRunLedgerBaseEvent & {
247
- type: 'run.resumed';
244
+ type: typeof RUN_EVENT_KIND.runResumed;
248
245
  })
249
246
  | (PlayRunLedgerBaseEvent & {
250
- type: 'run.completed';
247
+ type: typeof RUN_EVENT_KIND.runCompleted;
251
248
  result?: unknown;
252
249
  resultSummary?: unknown;
253
250
  terminalWorkCounterSegment?: PlayRunLedgerTerminalWorkCounterSegment;
254
251
  })
255
252
  | (PlayRunLedgerBaseEvent & {
256
- type: 'run.failed';
253
+ type: typeof RUN_EVENT_KIND.runFailed;
257
254
  error?: string | null;
258
255
  result?: unknown;
259
256
  resultSummary?: unknown;
260
257
  terminalWorkCounterSegment?: PlayRunLedgerTerminalWorkCounterSegment;
261
258
  })
262
259
  | (PlayRunLedgerBaseEvent & {
263
- type: 'run.cancelled';
260
+ type: typeof RUN_EVENT_KIND.runCancelled;
264
261
  error?: string | null;
265
262
  result?: unknown;
266
263
  })
267
264
  | (PlayRunLedgerBaseEvent & {
268
- type: 'step.started';
265
+ type: typeof RUN_EVENT_KIND.stepStarted;
269
266
  stepId: string;
270
267
  label?: string;
271
268
  kind?: string;
272
269
  artifactTableNamespace?: string | null;
273
270
  })
274
271
  | (PlayRunLedgerBaseEvent & {
275
- type: 'step.progress';
272
+ type: typeof RUN_EVENT_KIND.stepProgress;
276
273
  stepId: string;
277
274
  label?: string;
278
275
  kind?: string;
@@ -280,14 +277,14 @@ export type PlayRunLedgerEvent =
280
277
  progress: PlayRunLedgerStepProgress;
281
278
  })
282
279
  | (PlayRunLedgerBaseEvent & {
283
- type: 'step.completed';
280
+ type: typeof RUN_EVENT_KIND.stepCompleted;
284
281
  stepId: string;
285
282
  label?: string;
286
283
  kind?: string;
287
284
  artifactTableNamespace?: string | null;
288
285
  })
289
286
  | (PlayRunLedgerBaseEvent & {
290
- type: 'step.failed';
287
+ type: typeof RUN_EVENT_KIND.stepFailed;
291
288
  stepId: string;
292
289
  label?: string;
293
290
  kind?: string;
@@ -295,14 +292,14 @@ export type PlayRunLedgerEvent =
295
292
  artifactTableNamespace?: string | null;
296
293
  })
297
294
  | (PlayRunLedgerBaseEvent & {
298
- type: 'step.skipped';
295
+ type: typeof RUN_EVENT_KIND.stepSkipped;
299
296
  stepId: string;
300
297
  label?: string;
301
298
  kind?: string;
302
299
  artifactTableNamespace?: string | null;
303
300
  })
304
301
  | (PlayRunLedgerBaseEvent & {
305
- type: 'log.appended';
302
+ type: typeof RUN_EVENT_KIND.logAppended;
306
303
  lines: string[];
307
304
  /** Search-only context aligned to `lines`; stripped before Convex. */
308
305
  lineContexts?: Array<PlayLogContext | null>;
@@ -330,7 +327,7 @@ export type PlayRunLedgerEvent =
330
327
  logsTruncated?: boolean;
331
328
  })
332
329
  | (PlayRunLedgerBaseEvent & {
333
- type: 'dataset.lifecycle';
330
+ type: typeof RUN_EVENT_KIND.datasetLifecycle;
334
331
  datasetId: string;
335
332
  path: string;
336
333
  tableNamespace: string;
@@ -343,11 +340,11 @@ export type PlayRunLedgerEvent =
343
340
  bornFrom?: PlayDatasetBornFrom;
344
341
  })
345
342
  | (PlayRunLedgerBaseEvent & {
346
- type: 'activity.observed';
343
+ type: typeof RUN_EVENT_KIND.activityObserved;
347
344
  observation: PlayActivityObservation;
348
345
  })
349
346
  | (PlayRunLedgerBaseEvent & {
350
- type: 'work.counters';
347
+ type: typeof RUN_EVENT_KIND.workCounters;
351
348
  attempt: number;
352
349
  invocationSeq: number;
353
350
  segmentId: string;
@@ -548,7 +545,10 @@ function normalizeWorkCounters(
548
545
 
549
546
  function advanceNextWorkCounterSegment(
550
547
  current: PlayRunLedgerWorkCounters,
551
- event: Extract<PlayRunLedgerEvent, { type: 'work.counters' }>,
548
+ event: Extract<
549
+ PlayRunLedgerEvent,
550
+ { type: typeof RUN_EVENT_KIND.workCounters }
551
+ >,
552
552
  ): PlayRunLedgerWorkCounters {
553
553
  const completedLogicalCalls =
554
554
  current.completedLogicalCalls + current.logicalCalls;
@@ -594,7 +594,10 @@ function advanceNextWorkCounterSegment(
594
594
 
595
595
  function advanceWorkCounters(
596
596
  current: PlayRunLedgerWorkCounters | undefined,
597
- event: Extract<PlayRunLedgerEvent, { type: 'work.counters' }>,
597
+ event: Extract<
598
+ PlayRunLedgerEvent,
599
+ { type: typeof RUN_EVENT_KIND.workCounters }
600
+ >,
598
601
  ): PlayRunLedgerWorkCounters | undefined {
599
602
  if (
600
603
  !nonnegativeSafeInteger(event.attempt) ||
@@ -1307,9 +1310,9 @@ function withTiming(snapshot: PlayRunLedgerSnapshot): PlayRunLedgerSnapshot {
1307
1310
  }
1308
1311
 
1309
1312
  const TERMINAL_STATUS_BY_EVENT_TYPE = {
1310
- 'run.completed': 'completed',
1311
- 'run.failed': 'failed',
1312
- 'run.cancelled': 'cancelled',
1313
+ [RUN_EVENT_KIND.runCompleted]: 'completed',
1314
+ [RUN_EVENT_KIND.runFailed]: 'failed',
1315
+ [RUN_EVENT_KIND.runCancelled]: 'cancelled',
1313
1316
  } as const satisfies Partial<Record<string, PlayRunLedgerStatus>>;
1314
1317
 
1315
1318
  function isRawPlatformDeployResetText(
@@ -1387,7 +1390,7 @@ function conflictingTerminalSnapshot(
1387
1390
  const terminalAt = base.finishedAt ?? base.updatedAt ?? 0;
1388
1391
  if (
1389
1392
  base.status === 'completed' &&
1390
- eventType === 'run.failed' &&
1393
+ eventType === RUN_EVENT_KIND.runFailed &&
1391
1394
  isPlatformDeployFailureText(eventError)
1392
1395
  ) {
1393
1396
  return withTiming(
@@ -1398,7 +1401,7 @@ function conflictingTerminalSnapshot(
1398
1401
  }
1399
1402
  if (
1400
1403
  base.status === 'failed' &&
1401
- eventType === 'run.failed' &&
1404
+ eventType === RUN_EVENT_KIND.runFailed &&
1402
1405
  isPlatformDeployFailureText(eventError)
1403
1406
  ) {
1404
1407
  return withTiming(base);
@@ -1538,11 +1541,11 @@ function terminalFinishedAt(
1538
1541
 
1539
1542
  function isStepLifecycleEvent(event: PlayRunLedgerEvent): boolean {
1540
1543
  return (
1541
- event.type === 'step.started' ||
1542
- event.type === 'step.progress' ||
1543
- event.type === 'step.completed' ||
1544
- event.type === 'step.failed' ||
1545
- event.type === 'step.skipped'
1544
+ event.type === RUN_EVENT_KIND.stepStarted ||
1545
+ event.type === RUN_EVENT_KIND.stepProgress ||
1546
+ event.type === RUN_EVENT_KIND.stepCompleted ||
1547
+ event.type === RUN_EVENT_KIND.stepFailed ||
1548
+ event.type === RUN_EVENT_KIND.stepSkipped
1546
1549
  );
1547
1550
  }
1548
1551
 
@@ -1557,7 +1560,10 @@ function isStepLifecycleEvent(event: PlayRunLedgerEvent): boolean {
1557
1560
  */
1558
1561
  function refineTerminalSyntheticStepStart(
1559
1562
  snapshot: PlayRunLedgerSnapshot,
1560
- event: Extract<PlayRunLedgerEvent, { type: 'step.progress' }>,
1563
+ event: Extract<
1564
+ PlayRunLedgerEvent,
1565
+ { type: typeof RUN_EVENT_KIND.stepProgress }
1566
+ >,
1561
1567
  ): PlayRunLedgerSnapshot | null {
1562
1568
  const current = snapshot.stepsById[event.stepId];
1563
1569
  const startedAt = event.progress.startedAt;
@@ -1607,7 +1613,7 @@ export function reducePlayRunLedgerEvent(
1607
1613
  // `step.*` facts must be a true no-op here rather than relying on a gateway
1608
1614
  // process to remember terminal state.
1609
1615
  if (isTerminalPlayRunLedgerStatus(snapshot.status)) {
1610
- if (event.type === 'step.progress') {
1616
+ if (event.type === RUN_EVENT_KIND.stepProgress) {
1611
1617
  return refineTerminalSyntheticStepStart(snapshot, event) ?? snapshot;
1612
1618
  }
1613
1619
  if (isStepLifecycleEvent(event)) return snapshot;
@@ -1617,7 +1623,8 @@ export function reducePlayRunLedgerEvent(
1617
1623
  // must be byte-for-byte inert: even advancing `updatedAt` would re-publish
1618
1624
  // a stale terminal snapshot to every observer.
1619
1625
  if (
1620
- (event.type === 'run.waiting' || event.type === 'run.resumed') &&
1626
+ (event.type === RUN_EVENT_KIND.runWaiting ||
1627
+ event.type === RUN_EVENT_KIND.runResumed) &&
1621
1628
  shouldIgnoreNonTerminalAfterStickyTerminal(snapshot)
1622
1629
  ) {
1623
1630
  return snapshot;
@@ -1628,16 +1635,17 @@ export function reducePlayRunLedgerEvent(
1628
1635
  updatedAt: Math.max(snapshot.updatedAt ?? 0, occurredAt),
1629
1636
  };
1630
1637
  const ignoreNonTerminalAfterStickyTerminal =
1631
- (event.type === 'run.created' || event.type === 'run.started') &&
1638
+ (event.type === RUN_EVENT_KIND.runCreated ||
1639
+ event.type === RUN_EVENT_KIND.runStarted) &&
1632
1640
  shouldIgnoreNonTerminalAfterStickyTerminal(base);
1633
1641
 
1634
1642
  switch (event.type) {
1635
- case 'work.counters': {
1643
+ case RUN_EVENT_KIND.workCounters: {
1636
1644
  const workCounters = advanceWorkCounters(base.workCounters, event);
1637
1645
  if (workCounters === base.workCounters) return snapshot;
1638
1646
  return withTiming({ ...base, workCounters });
1639
1647
  }
1640
- case 'run.created': {
1648
+ case RUN_EVENT_KIND.runCreated: {
1641
1649
  if (ignoreNonTerminalAfterStickyTerminal) {
1642
1650
  return withTiming(base);
1643
1651
  }
@@ -1657,7 +1665,7 @@ export function reducePlayRunLedgerEvent(
1657
1665
  (createdStatus === 'running' ? occurredAt : base.startedAt),
1658
1666
  });
1659
1667
  }
1660
- case 'run.started':
1668
+ case RUN_EVENT_KIND.runStarted:
1661
1669
  if (ignoreNonTerminalAfterStickyTerminal) {
1662
1670
  return withTiming(base);
1663
1671
  }
@@ -1671,7 +1679,7 @@ export function reducePlayRunLedgerEvent(
1671
1679
  : 'running',
1672
1680
  startedAt: base.startedAt ?? occurredAt,
1673
1681
  });
1674
- case 'run.waiting':
1682
+ case RUN_EVENT_KIND.runWaiting:
1675
1683
  return withTiming({
1676
1684
  ...base,
1677
1685
  status: 'waiting',
@@ -1679,7 +1687,7 @@ export function reducePlayRunLedgerEvent(
1679
1687
  waitUntil: event.waitUntil ?? null,
1680
1688
  activeActivityId: null,
1681
1689
  });
1682
- case 'run.resumed':
1690
+ case RUN_EVENT_KIND.runResumed:
1683
1691
  return withTiming({
1684
1692
  ...base,
1685
1693
  status: 'running',
@@ -1687,7 +1695,7 @@ export function reducePlayRunLedgerEvent(
1687
1695
  waitUntil: null,
1688
1696
  activeActivityId: null,
1689
1697
  });
1690
- case 'run.completed': {
1698
+ case RUN_EVENT_KIND.runCompleted: {
1691
1699
  const terminalWorkCounterSegment =
1692
1700
  (event.source === 'worker' || event.source === 'system') &&
1693
1701
  (!isTerminalPlayRunLedgerStatus(base.status) ||
@@ -1732,7 +1740,7 @@ export function reducePlayRunLedgerEvent(
1732
1740
  })
1733
1741
  );
1734
1742
  }
1735
- case 'run.failed': {
1743
+ case RUN_EVENT_KIND.runFailed: {
1736
1744
  const terminalWorkCounterSegment =
1737
1745
  (event.source === 'worker' || event.source === 'system') &&
1738
1746
  (!isTerminalPlayRunLedgerStatus(base.status) ||
@@ -1782,7 +1790,7 @@ export function reducePlayRunLedgerEvent(
1782
1790
  })
1783
1791
  );
1784
1792
  }
1785
- case 'run.cancelled':
1793
+ case RUN_EVENT_KIND.runCancelled:
1786
1794
  return (
1787
1795
  conflictingTerminalSnapshot(base, event.type, occurredAt, event.error, {
1788
1796
  allowStaleSameStatusPayloadMerge:
@@ -1815,7 +1823,7 @@ export function reducePlayRunLedgerEvent(
1815
1823
  terminalSource: nextTerminalSource(base, event.source),
1816
1824
  })
1817
1825
  );
1818
- case 'log.appended':
1826
+ case RUN_EVENT_KIND.logAppended:
1819
1827
  return withTiming(
1820
1828
  appendLogLines(base, event.lines, {
1821
1829
  ...(typeof event.firstSeq === 'number'
@@ -1824,7 +1832,7 @@ export function reducePlayRunLedgerEvent(
1824
1832
  ...(event.logsTruncated === true ? { logsTruncated: true } : {}),
1825
1833
  }),
1826
1834
  );
1827
- case 'step.started': {
1835
+ case RUN_EVENT_KIND.stepStarted: {
1828
1836
  const current = base.stepsById[event.stepId];
1829
1837
  const runTerminal = isTerminalPlayRunLedgerStatus(base.status);
1830
1838
  const shouldRefineSyntheticStart =
@@ -1872,7 +1880,7 @@ export function reducePlayRunLedgerEvent(
1872
1880
  : (base.activeArtifactTableNamespace ?? null),
1873
1881
  });
1874
1882
  }
1875
- case 'step.progress': {
1883
+ case RUN_EVENT_KIND.stepProgress: {
1876
1884
  const current = base.stepsById[event.stepId];
1877
1885
  const runTerminal = isTerminalPlayRunLedgerStatus(base.status);
1878
1886
  const mergedProgress = {
@@ -1969,18 +1977,19 @@ export function reducePlayRunLedgerEvent(
1969
1977
  : (base.activeArtifactTableNamespace ?? null),
1970
1978
  });
1971
1979
  }
1972
- case 'step.completed':
1973
- case 'step.failed':
1974
- case 'step.skipped': {
1980
+ case RUN_EVENT_KIND.stepCompleted:
1981
+ case RUN_EVENT_KIND.stepFailed:
1982
+ case RUN_EVENT_KIND.stepSkipped: {
1975
1983
  const current = base.stepsById[event.stepId];
1976
1984
  const runTerminal = isTerminalPlayRunLedgerStatus(base.status);
1977
1985
  const preserveFailedStatus =
1978
- current?.status === 'failed' && event.type !== 'step.failed';
1986
+ current?.status === 'failed' &&
1987
+ event.type !== RUN_EVENT_KIND.stepFailed;
1979
1988
  const status = preserveFailedStatus
1980
1989
  ? 'failed'
1981
- : event.type === 'step.completed'
1990
+ : event.type === RUN_EVENT_KIND.stepCompleted
1982
1991
  ? 'completed'
1983
- : event.type === 'step.failed'
1992
+ : event.type === RUN_EVENT_KIND.stepFailed
1984
1993
  ? 'failed'
1985
1994
  : 'skipped';
1986
1995
  const completedAt =
@@ -1994,7 +2003,7 @@ export function reducePlayRunLedgerEvent(
1994
2003
  kind: event.kind ?? current?.kind,
1995
2004
  status,
1996
2005
  error:
1997
- event.type === 'step.failed'
2006
+ event.type === RUN_EVENT_KIND.stepFailed
1998
2007
  ? (event.error ?? current?.error ?? null)
1999
2008
  : preserveFailedStatus
2000
2009
  ? (current?.error ?? null)
@@ -2032,7 +2041,7 @@ export function reducePlayRunLedgerEvent(
2032
2041
  : null,
2033
2042
  });
2034
2043
  }
2035
- case 'dataset.lifecycle': {
2044
+ case RUN_EVENT_KIND.datasetLifecycle: {
2036
2045
  const current = base.datasetsById[event.datasetId];
2037
2046
  const persistedRows = optionalFiniteNumber(event.persistedRows);
2038
2047
  const succeededRows = optionalFiniteNumber(event.succeededRows);
@@ -2082,7 +2091,7 @@ export function reducePlayRunLedgerEvent(
2082
2091
  resultTableNamespace: base.resultTableNamespace ?? event.tableNamespace,
2083
2092
  });
2084
2093
  }
2085
- case 'activity.observed': {
2094
+ case RUN_EVENT_KIND.activityObserved: {
2086
2095
  const current = base.activitiesById[event.observation.activityId];
2087
2096
  if (current && current.observedAt >= event.observation.observedAt) {
2088
2097
  return withTiming(base);
@@ -2142,16 +2151,20 @@ function progressSignature(
2142
2151
 
2143
2152
  function terminalEventTypeForStatus(
2144
2153
  status: PlayRunLedgerStatus,
2145
- ): 'run.completed' | 'run.failed' | 'run.cancelled' | null {
2146
- if (status === 'completed') return 'run.completed';
2154
+ ):
2155
+ | typeof RUN_EVENT_KIND.runCompleted
2156
+ | typeof RUN_EVENT_KIND.runFailed
2157
+ | typeof RUN_EVENT_KIND.runCancelled
2158
+ | null {
2159
+ if (status === 'completed') return RUN_EVENT_KIND.runCompleted;
2147
2160
  if (
2148
2161
  status === 'failed' ||
2149
2162
  status === 'terminated' ||
2150
2163
  status === 'timed_out'
2151
2164
  ) {
2152
- return 'run.failed';
2165
+ return RUN_EVENT_KIND.runFailed;
2153
2166
  }
2154
- if (status === 'cancelled') return 'run.cancelled';
2167
+ if (status === 'cancelled') return RUN_EVENT_KIND.runCancelled;
2155
2168
  return null;
2156
2169
  }
2157
2170
 
@@ -2266,7 +2279,7 @@ export function buildPlayRunLedgerEventsFromLogLines(input: {
2266
2279
  index += MAX_LEDGER_LOG_LINES_PER_EVENT
2267
2280
  ) {
2268
2281
  events.push({
2269
- type: 'log.appended',
2282
+ type: RUN_EVENT_KIND.logAppended,
2270
2283
  runId: input.runId,
2271
2284
  source,
2272
2285
  occurredAt,
@@ -2386,7 +2399,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
2386
2399
  isTerminalPlayRunLedgerStatus(status))
2387
2400
  ) {
2388
2401
  events.push({
2389
- type: 'run.started',
2402
+ type: RUN_EVENT_KIND.runStarted,
2390
2403
  runId: patch.runId,
2391
2404
  playName: patch.playName ?? input.previousSnapshot.playName ?? null,
2392
2405
  source,
@@ -2401,7 +2414,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
2401
2414
  const previousStep = input.previousSnapshot.stepsById[stepId];
2402
2415
  if (progress.startedAt && !previousStep?.startedAt) {
2403
2416
  events.push({
2404
- type: 'step.started',
2417
+ type: RUN_EVENT_KIND.stepStarted,
2405
2418
  runId: patch.runId,
2406
2419
  source,
2407
2420
  occurredAt: progress.startedAt,
@@ -2449,7 +2462,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
2449
2462
  progressSignature(previousStep?.progress)
2450
2463
  ) {
2451
2464
  events.push({
2452
- type: 'step.progress',
2465
+ type: RUN_EVENT_KIND.stepProgress,
2453
2466
  runId: patch.runId,
2454
2467
  source,
2455
2468
  occurredAt: progress.updatedAt ?? checkpointAt,
@@ -2468,7 +2481,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
2468
2481
 
2469
2482
  if (progress.completedAt && !previousStep?.completedAt) {
2470
2483
  events.push({
2471
- type: 'step.completed',
2484
+ type: RUN_EVENT_KIND.stepCompleted,
2472
2485
  runId: patch.runId,
2473
2486
  source,
2474
2487
  occurredAt: progress.completedAt,
@@ -2484,7 +2497,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
2484
2497
  !isTerminalPlayRunLedgerStatus(input.previousSnapshot.status)
2485
2498
  ) {
2486
2499
  const occurredAt = latestCompletedAt ?? checkpointAt;
2487
- if (terminalType === 'run.completed') {
2500
+ if (terminalType === RUN_EVENT_KIND.runCompleted) {
2488
2501
  events.push({
2489
2502
  type: terminalType,
2490
2503
  runId: patch.runId,
@@ -1,3 +1,4 @@
1
+ import { RUN_EVENT_KIND } from '../run-event-catalog';
1
2
  import { hydratePlayRunnerConfig } from '../protocol';
2
3
  import { appendFileSync, createReadStream, writeFileSync } from 'node:fs';
3
4
  import { readFile } from 'node:fs/promises';
@@ -2404,7 +2405,7 @@ async function run(
2404
2405
  {
2405
2406
  type: 'execution_event',
2406
2407
  event: {
2407
- type: 'dataset.lifecycle',
2408
+ type: RUN_EVENT_KIND.datasetLifecycle,
2408
2409
  datasetId,
2409
2410
  path: settlement.path,
2410
2411
  tableNamespace: settlement.tableNamespace,
@@ -2620,7 +2621,7 @@ async function run(
2620
2621
  {
2621
2622
  type: 'execution_event',
2622
2623
  event: {
2623
- type: 'dataset.lifecycle',
2624
+ type: RUN_EVENT_KIND.datasetLifecycle,
2624
2625
  datasetId,
2625
2626
  path: datasetPath,
2626
2627
  tableNamespace,
@@ -3193,7 +3194,7 @@ async function run(
3193
3194
  {
3194
3195
  type: 'execution_event',
3195
3196
  event: {
3196
- type: 'dataset.lifecycle',
3197
+ type: RUN_EVENT_KIND.datasetLifecycle,
3197
3198
  datasetId: settlement.datasetId,
3198
3199
  path: settlement.path,
3199
3200
  tableNamespace: settlement.tableNamespace,
@@ -3281,7 +3282,7 @@ async function run(
3281
3282
  {
3282
3283
  type: 'execution_event',
3283
3284
  event: {
3284
- type: 'dataset.lifecycle',
3285
+ type: RUN_EVENT_KIND.datasetLifecycle,
3285
3286
  datasetId: createRuntimeDatasetId(
3286
3287
  config.context.playName!,
3287
3288
  csvDataset.tableNamespace,
@@ -151,6 +151,7 @@ import {
151
151
  markPostgresSchedulerAttemptWaiting,
152
152
  materializePostgresSchedulerFiles,
153
153
  listPostgresSchedulerCompletedRunnerTerminals,
154
+ type PostgresSchedulerCompletedRunnerTerminal,
154
155
  listPostgresSchedulerAmbiguousModalCreateIntents,
155
156
  recordPostgresSchedulerAttemptRuntimeResource,
156
157
  recordPostgresSchedulerAmbiguousModalCreateIntent,
@@ -1939,7 +1940,12 @@ async function readTerminalSheetRowOutcomes(input: {
1939
1940
  runId: string;
1940
1941
  attempt: number;
1941
1942
  }): Promise<
1942
- Array<{ tableNamespace: string; completed: number; failed: number; total: number }>
1943
+ Array<{
1944
+ tableNamespace: string;
1945
+ completed: number;
1946
+ failed: number;
1947
+ total: number;
1948
+ }>
1943
1949
  > {
1944
1950
  const sheetNamespaces = [
1945
1951
  ...new Set(
@@ -2014,11 +2020,14 @@ async function collectFailedTerminalSettledProgressEvents(input: {
2014
2020
  occurredAt: Date.now(),
2015
2021
  });
2016
2022
  } catch (error) {
2017
- console.warn('[absurd-runtime.worker] failed_terminal_settled_counts_failed', {
2018
- runId: input.runId,
2019
- attempt: input.attempt,
2020
- error: error instanceof Error ? error.message : String(error),
2021
- });
2023
+ console.warn(
2024
+ '[absurd-runtime.worker] failed_terminal_settled_counts_failed',
2025
+ {
2026
+ runId: input.runId,
2027
+ attempt: input.attempt,
2028
+ error: error instanceof Error ? error.message : String(error),
2029
+ },
2030
+ );
2022
2031
  return [];
2023
2032
  }
2024
2033
  }
@@ -2073,7 +2082,11 @@ function requestTerminalOutboxProjection(input: {
2073
2082
  attempted: projection?.attempted ?? null,
2074
2083
  projected: projection?.projected ?? null,
2075
2084
  });
2076
- if (projection && projection.attempted === 0 && !projection.targetDelivered) {
2085
+ if (
2086
+ projection &&
2087
+ projection.attempted === 0 &&
2088
+ !projection.targetDelivered
2089
+ ) {
2077
2090
  // Nothing was claimable for this run: another dispatcher holds its
2078
2091
  // outbox lease or a predecessor is not yet due. Delivery now depends
2079
2092
  // on that holder or the projector's next wave.
@@ -5748,17 +5761,21 @@ export async function recoverAbsurdRuntimeCompletedRunnerTerminals(input: {
5748
5761
  schedulerOptions?: Pick<PostgresSchedulerOptions, 'schema'>;
5749
5762
  absurdReleaseId?: string | null;
5750
5763
  limit?: number;
5764
+ /** Preselected by the fixed controller's one-query cross-lane scan. */
5765
+ terminals?: readonly PostgresSchedulerCompletedRunnerTerminal[];
5751
5766
  }): Promise<{ recovered: number; skipped: number }> {
5752
5767
  const options = input.schedulerOptions ?? {};
5753
- const terminals = await listPostgresSchedulerCompletedRunnerTerminals(
5754
- input.client,
5755
- {
5756
- limit: input.limit,
5757
- absurdReleaseId: input.absurdReleaseId,
5758
- includeFailed: true,
5759
- },
5760
- options,
5761
- );
5768
+ const terminals =
5769
+ input.terminals ??
5770
+ (await listPostgresSchedulerCompletedRunnerTerminals(
5771
+ input.client,
5772
+ {
5773
+ limit: input.limit,
5774
+ absurdReleaseId: input.absurdReleaseId,
5775
+ includeFailed: true,
5776
+ },
5777
+ options,
5778
+ ));
5762
5779
  let recovered = 0;
5763
5780
  let skipped = 0;
5764
5781
 
@@ -5955,18 +5972,40 @@ export async function recoverAbsurdRuntimeCompletedRunnerTerminalsAcrossLanes(in
5955
5972
  schedulerOptions?: Pick<PostgresSchedulerOptions, 'schema'>;
5956
5973
  limitPerLane?: number;
5957
5974
  }): Promise<{ recovered: number; skipped: number }> {
5975
+ const releaseIds = [
5976
+ ...new Set(input.releaseIds.map((id) => id.trim()).filter(Boolean)),
5977
+ ];
5978
+ if (releaseIds.length === 0) return { recovered: 0, skipped: 0 };
5979
+ const terminals = await listPostgresSchedulerCompletedRunnerTerminals(
5980
+ input.client,
5981
+ {
5982
+ absurdReleaseIds: releaseIds,
5983
+ includeFailed: true,
5984
+ limit: input.limitPerLane,
5985
+ },
5986
+ input.schedulerOptions,
5987
+ );
5988
+ const terminalsByReleaseId = new Map<
5989
+ string,
5990
+ PostgresSchedulerCompletedRunnerTerminal[]
5991
+ >();
5992
+ for (const terminal of terminals) {
5993
+ if (!terminal.releaseId) continue;
5994
+ const laneTerminals = terminalsByReleaseId.get(terminal.releaseId) ?? [];
5995
+ laneTerminals.push(terminal);
5996
+ terminalsByReleaseId.set(terminal.releaseId, laneTerminals);
5997
+ }
5998
+
5958
5999
  let recovered = 0;
5959
6000
  let skipped = 0;
5960
- for (const releaseId of [
5961
- ...new Set(input.releaseIds.map((id) => id.trim())),
5962
- ]) {
5963
- if (!releaseId) continue;
6001
+ for (const releaseId of releaseIds) {
5964
6002
  const outcome = await recoverAbsurdRuntimeCompletedRunnerTerminals({
5965
6003
  client: input.client,
5966
6004
  queue: absurdQueueNameForRelease(releaseId),
5967
6005
  absurdReleaseId: releaseId,
5968
6006
  schedulerOptions: input.schedulerOptions,
5969
6007
  limit: input.limitPerLane,
6008
+ terminals: terminalsByReleaseId.get(releaseId) ?? [],
5970
6009
  });
5971
6010
  recovered += outcome.recovered;
5972
6011
  skipped += outcome.skipped;
@@ -1,3 +1,4 @@
1
+ import { RUN_EVENT_KIND } from '../run-event-catalog';
1
2
  /**
2
3
  * Shared constants and pure helpers for the `absurd` play-runtime scheduler
3
4
  * profile — imported by both the scheduler backend (`absurd.ts`, submit side)
@@ -823,7 +824,7 @@ export function absurdTerminalLedgerEvent(
823
824
  const occurredAt = Date.now();
824
825
  if (result.status === 'completed') {
825
826
  return {
826
- type: 'run.completed',
827
+ type: RUN_EVENT_KIND.runCompleted,
827
828
  runId: result.runId,
828
829
  occurredAt,
829
830
  source: 'worker',
@@ -832,7 +833,7 @@ export function absurdTerminalLedgerEvent(
832
833
  }
833
834
  if (result.status === 'failed') {
834
835
  return {
835
- type: 'run.failed',
836
+ type: RUN_EVENT_KIND.runFailed,
836
837
  runId: result.runId,
837
838
  occurredAt,
838
839
  source: 'worker',