deepline 0.1.199 → 0.1.201

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 (72) hide show
  1. package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +5 -1
  2. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +67 -18
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/README.md +1 -1
  4. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +16 -0
  5. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/receipts.ts +40 -9
  6. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-dispatch.ts +108 -39
  7. package/dist/bundling-sources/sdk/src/http.ts +5 -2
  8. package/dist/bundling-sources/sdk/src/play.ts +1 -1
  9. package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +7 -0
  10. package/dist/bundling-sources/sdk/src/release.ts +2 -2
  11. package/dist/bundling-sources/sdk/src/worker-play-entry.ts +11 -55
  12. package/dist/bundling-sources/shared_libs/play-runtime/adaptive-tool-dispatcher.ts +355 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +172 -73
  14. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +1794 -377
  15. package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +3 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +67 -4
  17. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +161 -39
  18. package/dist/bundling-sources/shared_libs/play-runtime/governor/adaptive-admission.ts +218 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +1 -1
  20. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +115 -25
  21. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +17 -17
  22. package/dist/bundling-sources/shared_libs/play-runtime/lease-policy.ts +22 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +2 -1
  24. package/dist/bundling-sources/shared_libs/play-runtime/live-events.ts +0 -1
  25. package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +265 -0
  26. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +135 -0
  27. package/dist/bundling-sources/shared_libs/play-runtime/play-input.ts +17 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +0 -3
  29. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +10 -1
  30. package/dist/bundling-sources/shared_libs/play-runtime/providers.ts +9 -15
  31. package/dist/bundling-sources/shared_libs/play-runtime/receipt-completion-sink.ts +262 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/receipt-heartbeat-supervisor.ts +64 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/receipt-sql.ts +76 -8
  34. package/dist/bundling-sources/shared_libs/play-runtime/receipt-state-sink.ts +59 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +3 -2
  36. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +269 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +45 -3
  38. package/dist/bundling-sources/shared_libs/play-runtime/run-terminal-source.ts +0 -1
  39. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +433 -0
  40. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +227 -0
  41. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +882 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +573 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/bundle.ts +264 -0
  44. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/index.ts +33 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runner-events.ts +35 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +53 -0
  47. package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +0 -1
  48. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +561 -105
  49. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +12 -0
  50. package/dist/bundling-sources/shared_libs/play-runtime/runtime-infra-mode.ts +23 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-attempt-state-machine.ts +23 -2
  52. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +16 -24
  53. package/dist/bundling-sources/shared_libs/play-runtime/serial-task-queue.ts +26 -0
  54. package/dist/bundling-sources/shared_libs/play-runtime/submit-limits.ts +1 -1
  55. package/dist/bundling-sources/shared_libs/play-runtime/vercel-protection.ts +81 -0
  56. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-state-machine.ts +54 -9
  57. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +17 -3
  58. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +0 -20
  59. package/dist/bundling-sources/shared_libs/plays/dataset.ts +105 -4
  60. package/dist/bundling-sources/shared_libs/plays/row-identity.ts +4 -11
  61. package/dist/cli/index.js +167 -54
  62. package/dist/cli/index.mjs +167 -54
  63. package/dist/index.d.mts +1 -1
  64. package/dist/index.d.ts +1 -1
  65. package/dist/index.js +8 -8
  66. package/dist/index.mjs +8 -8
  67. package/dist/plays/bundle-play-file.mjs +15 -20
  68. package/package.json +1 -1
  69. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-diagnosis.ts +0 -321
  70. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-target.ts +0 -158
  71. package/dist/bundling-sources/shared_libs/temporal/constants.ts +0 -39
  72. package/dist/bundling-sources/shared_libs/temporal/preview-config.ts +0 -150
@@ -143,17 +143,12 @@ function validateIdentifierPart(
143
143
  ): string {
144
144
  const sanitized = sanitizeIdentifierPart(rawValue);
145
145
  if (!sanitized) {
146
- throw new Error(
147
- `${label} must contain at least one letter or number after normalization. ` +
148
- `Use only letters, numbers, underscores, or hyphens.`,
149
- );
146
+ throw new Error(`${label} must contain a letter or number.`);
150
147
  }
151
148
 
152
149
  if (sanitized.length > maxLength) {
153
150
  throw new Error(
154
- `${label} is too long after normalization (${sanitized.length}/${maxLength}). ` +
155
- `Shorten it to ${maxLength} characters or fewer. ` +
156
- `Normalized value: "${sanitized}".`,
151
+ `${label} is too long after normalization (${sanitized.length}/${maxLength}): "${sanitized}".`,
157
152
  );
158
153
  }
159
154
 
@@ -163,7 +158,7 @@ function validateIdentifierPart(
163
158
  export function normalizePlayName(value: string): string {
164
159
  if (value.includes('/')) {
165
160
  throw new Error(
166
- 'Play name cannot contain "/". Slash is reserved for qualified play references like "prebuilt/example" or "self/example".',
161
+ 'Play name cannot contain "/". Slash is reserved.',
167
162
  );
168
163
  }
169
164
  return validateIdentifierPart(value, 'Play name', PLAY_NAME_MAX_LENGTH);
@@ -207,9 +202,7 @@ export function validatePlaySheetTableName(
207
202
  const resolved = `${playSegment}_${keySegment}`;
208
203
  if (resolved.length > POSTGRES_IDENTIFIER_MAX_LENGTH) {
209
204
  throw new Error(
210
- `Play sheet table name is too long after normalization (${resolved.length}/63). ` +
211
- `Shorten the play name or ctx.dataset() key. ` +
212
- `Resolved table name: "${resolved}".`,
205
+ `Play sheet table name is too long after normalization (${resolved.length}/63): "${resolved}".`,
213
206
  );
214
207
  }
215
208
  return resolved;
package/dist/cli/index.js CHANGED
@@ -623,10 +623,10 @@ var SDK_RELEASE = {
623
623
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
624
624
  // fields shipped in 0.1.153.
625
625
  // 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
626
- version: "0.1.199",
626
+ version: "0.1.201",
627
627
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
628
628
  supportPolicy: {
629
- latest: "0.1.199",
629
+ latest: "0.1.201",
630
630
  minimumSupported: "0.1.53",
631
631
  deprecatedBelow: "0.1.53",
632
632
  commandMinimumSupported: [
@@ -1067,7 +1067,10 @@ var HttpClient = class {
1067
1067
  * @param path - API path (e.g. `"/api/v2/tools"`)
1068
1068
  */
1069
1069
  async get(path) {
1070
- return this.request(path, { method: "GET" });
1070
+ return this.request(path, {
1071
+ method: "GET",
1072
+ retryApiErrors: true
1073
+ });
1071
1074
  }
1072
1075
  async *streamSse(path, options) {
1073
1076
  const url = `${this.config.baseUrl}${path}`;
@@ -1341,7 +1344,6 @@ function resolveTimingWindow(input2) {
1341
1344
  // ../shared_libs/play-runtime/run-terminal-source.ts
1342
1345
  var PLAY_RUN_LEDGER_EVENT_SOURCES = [
1343
1346
  "worker",
1344
- "temporal",
1345
1347
  "convex",
1346
1348
  "coordinator",
1347
1349
  "system"
@@ -7028,7 +7030,7 @@ function isRecord4(value) {
7028
7030
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
7029
7031
  }
7030
7032
  function isSerializedDataset(value) {
7031
- return isRecord4(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
7033
+ return isRecord4(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
7032
7034
  }
7033
7035
  function isPackagedDatasetOutput(value) {
7034
7036
  return isRecord4(value) && value.kind === "dataset" && isRecord4(value.preview) && Array.isArray(value.preview.rows);
@@ -7089,7 +7091,7 @@ function columnsFromDatasetSummary(summary) {
7089
7091
  function canonicalRowsInfoFromCandidate(input2) {
7090
7092
  const candidate = input2;
7091
7093
  if (isSerializedDataset(candidate.value)) {
7092
- const rawRows = rowArray(candidate.value.preview) ?? [];
7094
+ const rawRows = Array.isArray(candidate.value.preview) ? rowArray(candidate.value.preview) ?? [] : [];
7093
7095
  const totalRows2 = readNumber(candidate.value.count) ?? rawRows.length;
7094
7096
  const hasExplicitColumns = Array.isArray(candidate.value.columns) && candidate.value.columns.every((column) => typeof column === "string");
7095
7097
  const rawColumns = hasExplicitColumns ? candidate.value.columns : inferColumns(rawRows);
@@ -7317,6 +7319,13 @@ function collectSerializedDatasetRowsInfos(statusOrResult) {
7317
7319
  path: "result",
7318
7320
  output: candidates
7319
7321
  });
7322
+ if (isRecord4(result.output)) {
7323
+ collectDatasetCandidates({
7324
+ value: result.output,
7325
+ path: "result",
7326
+ output: candidates
7327
+ });
7328
+ }
7320
7329
  }
7321
7330
  candidates.push(...collectPackagedStepDatasetCandidates(statusOrResult));
7322
7331
  const seen = /* @__PURE__ */ new Set();
@@ -10411,22 +10420,22 @@ var PLAY_DEDUP_BACKENDS = {
10411
10420
 
10412
10421
  // ../shared_libs/play-runtime/scheduler-backend.ts
10413
10422
  var PLAY_SCHEDULER_BACKENDS = {
10414
- temporal: "temporal",
10415
10423
  cfWorkflows: "cf-workflows",
10424
+ /** Private legacy id retained only so old persisted rows can be interpreted. */
10425
+ postgres: "postgres",
10416
10426
  /**
10417
- * Private legacy id retained only so old persisted rows can be interpreted.
10418
- * It is not a selectable scheduler backend after the Hatchet hard cutover.
10427
+ * Postgres-native durable-execution scheduler (vendored Absurd engine). Runs
10428
+ * on the battle-tested run-state store without an external workflow engine.
10429
+ * Selected explicitly by the `absurd` profile.
10419
10430
  */
10420
- postgres: "postgres",
10421
- hatchet: "hatchet",
10431
+ absurd: "absurd",
10422
10432
  inProcess: "in-process"
10423
10433
  };
10424
10434
 
10425
10435
  // ../shared_libs/play-runtime/providers.ts
10426
10436
  var PLAY_RUNTIME_PROVIDER_IDS = {
10427
10437
  workersEdge: "workers_edge",
10428
- hatchet: "hatchet",
10429
- local: "local"
10438
+ absurd: "absurd"
10430
10439
  };
10431
10440
  var PLAY_RUNTIME_PROVIDERS = {
10432
10441
  workers_edge: {
@@ -10437,21 +10446,16 @@ var PLAY_RUNTIME_PROVIDERS = {
10437
10446
  artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
10438
10447
  label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
10439
10448
  },
10440
- hatchet: {
10441
- id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
10442
- scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
10449
+ absurd: {
10450
+ id: PLAY_RUNTIME_PROVIDER_IDS.absurd,
10451
+ scheduler: PLAY_SCHEDULER_BACKENDS.absurd,
10452
+ // Server runs execute on Daytona; the local-dev/test shape swaps the runner
10453
+ // axis to local_process (same as the local profile) via an explicit
10454
+ // runtimeBackend override at submit while tests drive local_process.
10443
10455
  runner: PLAY_RUNTIME_BACKENDS.daytona,
10444
10456
  dedup: PLAY_DEDUP_BACKENDS.inMemory,
10445
10457
  artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
10446
- label: "Hatchet scheduler + one-shot Daytona runner + receipt-backed in-process dedup"
10447
- },
10448
- local: {
10449
- id: PLAY_RUNTIME_PROVIDER_IDS.local,
10450
- scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
10451
- runner: PLAY_RUNTIME_BACKENDS.localProcess,
10452
- dedup: PLAY_DEDUP_BACKENDS.inMemory,
10453
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
10454
- label: "Local Temporal scheduler + local subprocess runner (tests)"
10458
+ label: "Absurd (Postgres-native durable) scheduler + one-shot Daytona runner + receipt-backed in-process dedup"
10455
10459
  }
10456
10460
  };
10457
10461
  function defaultPlayRuntimeProvider() {
@@ -10464,7 +10468,7 @@ function resolvePlayRuntimeProvider(override) {
10464
10468
  return PLAY_RUNTIME_PROVIDERS[id];
10465
10469
  }
10466
10470
  throw new Error(
10467
- `Unknown play runtime provider "${id}". Expected one of: ${Object.keys(
10471
+ `Unsupported play runtime provider "${id}". Expected one of: ${Object.keys(
10468
10472
  PLAY_RUNTIME_PROVIDERS
10469
10473
  ).join(", ")}.`
10470
10474
  );
@@ -13988,7 +13992,7 @@ function writeStartedPlayRun(input2) {
13988
13992
  );
13989
13993
  }
13990
13994
  function parsePlayRunOptions(args) {
13991
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n --profile defaults to workers_edge; pass hatchet explicitly for Hatchet runtime comparison.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
13995
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n --profile defaults to workers_edge, unless your local dev server exports a dev default such as absurd.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
13992
13996
  let filePath = null;
13993
13997
  let playName = null;
13994
13998
  let input2 = null;
@@ -18934,7 +18938,8 @@ async function writeOutputCsv(outputPath, status, options) {
18934
18938
  }
18935
18939
  const selectedSourceRows = selectedSourceCsvRowCount(options);
18936
18940
  const shouldFetchBackingRows = options?.client && shouldFetchBackingRowsForEnrichExport(rowsInfo, status, {
18937
- selectedSourceRows
18941
+ selectedSourceRows,
18942
+ expectedAliases: options?.config ? collectConfigScalarAliasOrder(options.config) : []
18938
18943
  });
18939
18944
  if (options?.client && shouldFetchBackingRows) {
18940
18945
  let fetchedRowsInfo = null;
@@ -18971,6 +18976,7 @@ async function writeOutputCsv(outputPath, status, options) {
18971
18976
  const columns = orderEnrichCsvColumns(
18972
18977
  dataExportColumns(merged.rows, [
18973
18978
  ...merged.preferredColumns,
18979
+ ...options?.config ? collectConfigScalarAliasOrder(options.config) : [],
18974
18980
  ...rowsInfo.columns
18975
18981
  ]),
18976
18982
  options?.config
@@ -19628,26 +19634,39 @@ function shouldFetchBackingRowsForEnrichExport(rowsInfo, status, options = {}) {
19628
19634
  rowsInfo,
19629
19635
  status
19630
19636
  );
19637
+ const isGeneratedEnrichRows = tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
19631
19638
  if (terminalStatus === "failed" || terminalStatus === "cancelled") {
19632
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && rowsInfo.source !== null && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19639
+ if (isGeneratedEnrichRows && rowsInfo.source !== null && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19633
19640
  return true;
19634
19641
  }
19635
- return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && (rowsInfo.recovered === true || hasPartialRunOutputWarning(status));
19642
+ return isGeneratedEnrichRows && (rowsInfo.recovered === true || hasPartialRunOutputWarning(status));
19636
19643
  }
19637
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19644
+ if (isGeneratedEnrichRows && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19638
19645
  return true;
19639
19646
  }
19640
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && typeof options.selectedSourceRows === "number" && options.selectedSourceRows > 0) {
19647
+ if (isGeneratedEnrichRows && (typeof options.selectedSourceRows === "number" && options.selectedSourceRows > 0 || rowsMissingExpectedAlias(rowsInfo.rows, options.expectedAliases))) {
19641
19648
  return true;
19642
19649
  }
19643
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && hasFailedRowSignal(status)) {
19650
+ if (isGeneratedEnrichRows && hasFailedRowSignal(status)) {
19644
19651
  return true;
19645
19652
  }
19646
19653
  if (!rowsInfo.complete) {
19647
- return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
19654
+ return isGeneratedEnrichRows;
19648
19655
  }
19649
19656
  return rowsInfo.rows.some((row) => hasLossyPreviewPlaceholder(row));
19650
19657
  }
19658
+ function rowsMissingExpectedAlias(rows, expectedAliases) {
19659
+ if (rows.length === 0 || !expectedAliases?.length) {
19660
+ return false;
19661
+ }
19662
+ const rowAliases = /* @__PURE__ */ new Set();
19663
+ for (const row of rows) {
19664
+ for (const key of Object.keys(row)) {
19665
+ rowAliases.add(normalizeAlias2(key));
19666
+ }
19667
+ }
19668
+ return expectedAliases.map((alias) => normalizeAlias2(alias)).filter(Boolean).some((alias) => !rowAliases.has(alias));
19669
+ }
19651
19670
  function hasPartialRunOutputWarning(status) {
19652
19671
  const warningLists = [
19653
19672
  recordField(status, "warnings"),
@@ -20213,6 +20232,18 @@ function collectEmptyWaterfallIssues(input2) {
20213
20232
  if (executionSignal === "all_condition_skipped" || executionSignal === "unknown" && waterfallChildrenAreStaticallySkipped(spec)) {
20214
20233
  return;
20215
20234
  }
20235
+ const statsEvidence = emptyWaterfallStatsEvidence(input2.status, spec);
20236
+ if (statsEvidence && input2.rowSetComplete && input2.outputPath) {
20237
+ issues.push(
20238
+ emptyWaterfallIssue({
20239
+ spec,
20240
+ selectedRows: statsEvidence.selectedRows,
20241
+ runId,
20242
+ followUpCommands
20243
+ })
20244
+ );
20245
+ return;
20246
+ }
20216
20247
  const logicalRows = /* @__PURE__ */ new Map();
20217
20248
  input2.rows.forEach((row, rowIndex) => {
20218
20249
  const sourceRowId = sourceRowIndexFromEnrichRow(
@@ -20234,24 +20265,34 @@ function collectEmptyWaterfallIssues(input2) {
20234
20265
  return;
20235
20266
  }
20236
20267
  const selectedRows = logicalRows.size;
20237
- const message = `Waterfall ${spec.alias} produced 0 values for ${selectedRows} selected row(s).`;
20238
- issues.push({
20239
- issue_id: `${spec.alias}-empty-waterfall`,
20240
- kind: "empty_waterfall",
20241
- severity: "needs_attention",
20242
- column: spec.alias,
20243
- selected_rows: selectedRows,
20244
- rows_with_value: 0,
20245
- rows_without_value: selectedRows,
20246
- message,
20247
- next_steps: enrichIssueNextSteps({ runId }),
20248
- follow_up_commands: followUpCommands,
20249
- ...spec.operation ? { operation: spec.operation } : {},
20250
- ...runId ? { run_id: runId } : {}
20251
- });
20268
+ issues.push(
20269
+ emptyWaterfallIssue({
20270
+ spec,
20271
+ selectedRows,
20272
+ runId,
20273
+ followUpCommands
20274
+ })
20275
+ );
20252
20276
  });
20253
20277
  return issues;
20254
20278
  }
20279
+ function emptyWaterfallIssue(input2) {
20280
+ const message = `Waterfall ${input2.spec.alias} produced 0 values for ${input2.selectedRows} selected row(s).`;
20281
+ return {
20282
+ issue_id: `${input2.spec.alias}-empty-waterfall`,
20283
+ kind: "empty_waterfall",
20284
+ severity: "needs_attention",
20285
+ column: input2.spec.alias,
20286
+ selected_rows: input2.selectedRows,
20287
+ rows_with_value: 0,
20288
+ rows_without_value: input2.selectedRows,
20289
+ message,
20290
+ next_steps: enrichIssueNextSteps({ runId: input2.runId }),
20291
+ follow_up_commands: input2.followUpCommands,
20292
+ ...input2.spec.operation ? { operation: input2.spec.operation } : {},
20293
+ ...input2.runId ? { run_id: input2.runId } : {}
20294
+ };
20295
+ }
20255
20296
  function waterfallChildrenAreStaticallySkipped(spec) {
20256
20297
  const childAliases = spec.childAliases ?? [];
20257
20298
  if (childAliases.length === 0 || !spec.childRunIfJsByAlias) {
@@ -20285,14 +20326,18 @@ function waterfallExecutionSignal(status, spec) {
20285
20326
  const executedSummary = parseExecutionSummary(
20286
20327
  execution?.["completed:executed"]
20287
20328
  );
20329
+ const reusedSummary = parseExecutionSummary(
20330
+ execution?.["completed:reused"]
20331
+ );
20288
20332
  const skippedConditionSummary = parseExecutionSummary(
20289
20333
  execution?.["skipped:condition"]
20290
20334
  );
20291
20335
  const executedCount = executedSummary?.count ?? 0;
20336
+ const reusedCount = reusedSummary?.count ?? 0;
20292
20337
  const skippedConditionCount = skippedConditionSummary?.count ?? 0;
20293
- const totalCount = executedSummary?.total ?? skippedConditionSummary?.total;
20294
- const onlyConditionSkips = totalCount !== void 0 && skippedConditionCount >= totalCount && executedCount <= skippedConditionCount;
20295
- if (executedCount > 0 && !onlyConditionSkips || numericFailedRowSignal(execution?.failed) > 0 || numericFailedRowSignal(stat2.failed) > 0 || numericFailedRowSignal(stat2.failedRows) > 0) {
20338
+ const totalCount = executedSummary?.total ?? reusedSummary?.total ?? skippedConditionSummary?.total;
20339
+ const onlyConditionSkips = totalCount !== void 0 && skippedConditionCount >= totalCount && executedCount + reusedCount <= skippedConditionCount;
20340
+ if (executedCount + reusedCount > 0 && !onlyConditionSkips || numericFailedRowSignal(execution?.failed) > 0 || numericFailedRowSignal(stat2.failed) > 0 || numericFailedRowSignal(stat2.failedRows) > 0) {
20296
20341
  return "executed";
20297
20342
  }
20298
20343
  if (!onlyConditionSkips) {
@@ -20305,6 +20350,48 @@ function waterfallExecutionSignal(status, spec) {
20305
20350
  }
20306
20351
  return "unknown";
20307
20352
  }
20353
+ function emptyWaterfallStatsEvidence(status, spec) {
20354
+ const summaries = collectColumnStats(status);
20355
+ const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord7);
20356
+ for (const stat2 of parentStats) {
20357
+ const nonEmpty = parseExecutionSummary(stat2.non_empty);
20358
+ if (nonEmpty?.total && nonEmpty.count === 0) {
20359
+ return { selectedRows: nonEmpty.total };
20360
+ }
20361
+ }
20362
+ const childAliases = spec.childAliases ?? [];
20363
+ if (childAliases.length === 0) {
20364
+ return null;
20365
+ }
20366
+ let selectedRows = 0;
20367
+ let sawStatsForEveryChild = true;
20368
+ for (const childAlias of childAliases) {
20369
+ const stat2 = summaries.map((summary) => summary[childAlias]).find(isRecord7);
20370
+ if (!stat2) {
20371
+ sawStatsForEveryChild = false;
20372
+ break;
20373
+ }
20374
+ const nonEmpty = parseExecutionSummary(stat2.non_empty);
20375
+ if ((nonEmpty?.count ?? 0) > 0) {
20376
+ return null;
20377
+ }
20378
+ const execution = isRecord7(stat2.execution) ? stat2.execution : null;
20379
+ const executed = parseExecutionSummary(execution?.["completed:executed"]);
20380
+ const reused = parseExecutionSummary(execution?.["completed:reused"]);
20381
+ const skipped = parseExecutionSummary(execution?.["skipped:condition"]);
20382
+ selectedRows = Math.max(
20383
+ selectedRows,
20384
+ nonEmpty?.total ?? 0,
20385
+ executed?.total ?? 0,
20386
+ reused?.total ?? 0,
20387
+ skipped?.total ?? 0
20388
+ );
20389
+ }
20390
+ if (!sawStatsForEveryChild || selectedRows <= 0 || waterfallExecutionSignal(status, spec) === "all_condition_skipped") {
20391
+ return null;
20392
+ }
20393
+ return { selectedRows };
20394
+ }
20308
20395
  function mergeEnrichFailureJobs(...jobGroups) {
20309
20396
  const merged = [];
20310
20397
  const seen = /* @__PURE__ */ new Set();
@@ -21124,12 +21211,34 @@ var ENRICH_FLATTENED_CONTROL_FIELDS = /* @__PURE__ */ new Set([
21124
21211
  "provider",
21125
21212
  "status"
21126
21213
  ]);
21214
+ var ENRICH_ALIAS_METADATA_FIELDS = /* @__PURE__ */ new Set([
21215
+ "_metadata",
21216
+ "metadata",
21217
+ "metadata.columns",
21218
+ "metadata__columns"
21219
+ ]);
21220
+ function isEnrichAliasPayloadField(field) {
21221
+ return !field.startsWith("_") && !ENRICH_FLATTENED_CONTROL_FIELDS.has(field) && !ENRICH_ALIAS_METADATA_FIELDS.has(field);
21222
+ }
21127
21223
  function materializeCsvCellValue(value) {
21128
21224
  if (value && typeof value === "object") {
21129
21225
  return csvSafeJsonString(value);
21130
21226
  }
21131
21227
  return value;
21132
21228
  }
21229
+ function compactArrayEnvelopeCompleteValue(value) {
21230
+ if (!isRecord7(value) || value.kind !== "array") {
21231
+ return null;
21232
+ }
21233
+ if (!Array.isArray(value.preview)) {
21234
+ return null;
21235
+ }
21236
+ const length = typeof value.length === "number" && Number.isFinite(value.length) ? Math.max(0, Math.trunc(value.length)) : null;
21237
+ if (length === null || length > value.preview.length) {
21238
+ return null;
21239
+ }
21240
+ return value.preview.slice(0, length);
21241
+ }
21133
21242
  function disambiguateCompactAiInferencePayload(value) {
21134
21243
  const parsed = parseMaybeJsonObject(value);
21135
21244
  if (!isRecord7(parsed) || !cellFailureError(parsed)) {
@@ -21166,6 +21275,10 @@ function compactAiInferenceCellForCsv(value) {
21166
21275
  function materializeEnrichAliasCellForCsv(row, alias, options) {
21167
21276
  const direct = row[alias];
21168
21277
  if (isRecord7(direct)) {
21278
+ const completeArray = compactArrayEnvelopeCompleteValue(direct);
21279
+ if (completeArray) {
21280
+ return materializeCsvCellValue(completeArray);
21281
+ }
21169
21282
  if (options?.compactAiCell && direct.status === "completed" && (isRecord7(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
21170
21283
  return materializeCsvCellValue(compactAiInferenceCellForCsv(direct));
21171
21284
  }
@@ -21174,7 +21287,7 @@ function materializeEnrichAliasCellForCsv(row, alias, options) {
21174
21287
  }
21175
21288
  const directCells = [];
21176
21289
  for (const [field, value] of Object.entries(direct)) {
21177
- if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
21290
+ if (!isEnrichAliasPayloadField(field)) {
21178
21291
  continue;
21179
21292
  }
21180
21293
  if (isNonEmptyCsvCell(value)) {
@@ -21204,7 +21317,7 @@ function materializeEnrichAliasCellForCsv(row, alias, options) {
21204
21317
  }
21205
21318
  }
21206
21319
  const cells = aliasFlattenedCells(row, alias).filter(({ field, value }) => {
21207
- if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
21320
+ if (!isEnrichAliasPayloadField(field)) {
21208
21321
  return false;
21209
21322
  }
21210
21323
  return isNonEmptyCsvCell(value);