deepline 0.3.131 → 0.3.133

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.
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
200
200
  // getters keep their established compatibility behavior.
201
201
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
202
202
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
203
- version: '0.3.131',
203
+ version: '0.3.133',
204
204
  updateSummary:
205
205
  '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.',
206
206
  packageCapabilities: {
@@ -783,6 +783,16 @@ export interface PlayStatus {
783
783
  progress?: PlayProgressStatus;
784
784
  /** Partial or final result. Available once the play returns. */
785
785
  result?: unknown;
786
+ /**
787
+ * Terminal row outcome truth. A completed run may still contain failed rows
788
+ * when row-level failure isolation persisted those rows for retry.
789
+ */
790
+ rowOutcomes?: {
791
+ completedRows: number;
792
+ failedRows: number;
793
+ totalRows: number;
794
+ hasRowFailures: boolean;
795
+ };
786
796
  /** Compact typed run package returned by current run status endpoints. */
787
797
  package?: PlayRunPackage;
788
798
  /** Compact typed output summaries, mirrored from the run package when present. */
@@ -9461,6 +9461,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
9461
9461
  totalRows: totalInputCount,
9462
9462
  completedRowKeys,
9463
9463
  pendingRowKeys,
9464
+ failedRowsCount: 0,
9464
9465
  startedAt: Date.now(),
9465
9466
  updatedAt: Date.now(),
9466
9467
  });
@@ -10159,6 +10160,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
10159
10160
  let liveFrameSets: {
10160
10161
  completedRowKeys: Set<string>;
10161
10162
  pendingRowKeys: Set<string>;
10163
+ failedRowsCount: number;
10162
10164
  } | null = null;
10163
10165
  let lastFrameFlushAt = 0;
10164
10166
  let rowsSinceFrameFlush = 0;
@@ -10181,6 +10183,10 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
10181
10183
  liveFrameSets ??= {
10182
10184
  completedRowKeys: new Set(existing.completedRowKeys),
10183
10185
  pendingRowKeys: new Set(existing.pendingRowKeys),
10186
+ // Failure counts are explicit row outcomes, not the complement of the
10187
+ // live key sets. The sets may be intentionally sparse for a fed map
10188
+ // and may lag the durable row writer while a batch is in flight.
10189
+ failedRowsCount: 0,
10184
10190
  };
10185
10191
  const { completedRowKeys, pendingRowKeys } = liveFrameSets;
10186
10192
  const completedBefore = completedRowKeys.size;
@@ -10211,6 +10217,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
10211
10217
  if (input.failedRowKey?.trim()) {
10212
10218
  pendingRowKeys.delete(input.failedRowKey.trim());
10213
10219
  }
10220
+ liveFrameSets.failedRowsCount += Math.max(0, input.failedDelta ?? 0);
10214
10221
  rowsSinceFrameFlush += completedRowKeys.size - completedBefore;
10215
10222
 
10216
10223
  const isTransition =
@@ -10246,14 +10253,14 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
10246
10253
  pendingRowsCount: pendingRowKeys.size,
10247
10254
  failedRowsCount:
10248
10255
  liveNumber(runtimeOptions?.progressFailedOffset, 0) +
10249
- Math.max(
10250
- 0,
10251
- items.length - completedRowKeys.size - pendingRowKeys.size,
10252
- ),
10256
+ liveFrameSets.failedRowsCount,
10253
10257
  }
10254
10258
  : {
10255
10259
  completedRowKeys: [...completedRowKeys],
10256
10260
  pendingRowKeys: [...pendingRowKeys],
10261
+ failedRowsCount:
10262
+ liveNumber(runtimeOptions?.progressFailedOffset, 0) +
10263
+ liveFrameSets.failedRowsCount,
10257
10264
  }),
10258
10265
  ...(input.activeBoundaryId !== undefined
10259
10266
  ? { activeBoundaryId: input.activeBoundaryId }
@@ -10271,7 +10278,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
10271
10278
  const failedRows = Math.max(
10272
10279
  0,
10273
10280
  liveNumber(runtimeOptions?.progressFailedOffset, 0) +
10274
- (items.length - completedRowKeys.size - pendingRowKeys.size),
10281
+ liveFrameSets.failedRowsCount,
10275
10282
  );
10276
10283
  this.emitExecutionEvent({
10277
10284
  type: progressEventType,
@@ -10616,7 +10623,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
10616
10623
  rowKey,
10617
10624
  normalizedTableNamespace,
10618
10625
  );
10619
- updateMapFrameProgress({ failedRowKey: rowKey });
10626
+ updateMapFrameProgress({ failedDelta: 1, failedRowKey: rowKey });
10620
10627
  });
10621
10628
  return FAILED_ROW;
10622
10629
  } finally {
@@ -10799,6 +10806,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
10799
10806
  }
10800
10807
  const fieldName = rowContext.getStore()?.fieldName;
10801
10808
  updateMapFrameProgress({
10809
+ failedDelta: 1,
10802
10810
  status: 'failed',
10803
10811
  emitEventType: 'map.failed',
10804
10812
  });
@@ -39,6 +39,7 @@ export class MapExecutionFrameStore {
39
39
  totalRows: number;
40
40
  completedRowKeys: readonly string[];
41
41
  pendingRowKeys: readonly string[];
42
+ failedRows?: number;
42
43
  }): void {
43
44
  const now = Date.now();
44
45
  this.set({
@@ -50,6 +51,7 @@ export class MapExecutionFrameStore {
50
51
  totalRows: input.totalRows,
51
52
  completedRowKeys: [...input.completedRowKeys],
52
53
  pendingRowKeys: [...input.pendingRowKeys],
54
+ failedRowsCount: Math.max(0, input.failedRows ?? 0),
53
55
  startedAt: now,
54
56
  updatedAt: now,
55
57
  });
@@ -72,6 +74,7 @@ export class MapExecutionFrameStore {
72
74
  status?: MapExecutionFrame['status'];
73
75
  completedRowKey?: string | null;
74
76
  pendingRowKey?: string | null;
77
+ failedDelta?: number;
75
78
  activeBoundaryId?: string | null;
76
79
  emitEventType?: PlayExecutionEvent['type'];
77
80
  }): void {
@@ -91,11 +94,16 @@ export class MapExecutionFrameStore {
91
94
  if (input.pendingRowKey?.trim()) {
92
95
  pendingRowKeys.add(input.pendingRowKey.trim());
93
96
  }
97
+ const failedRowsCount = Math.max(
98
+ 0,
99
+ (existing.failedRowsCount ?? 0) + Math.max(0, input.failedDelta ?? 0),
100
+ );
94
101
  const nextFrame: MapExecutionFrame = {
95
102
  ...existing,
96
103
  status: input.status ?? existing.status,
97
104
  completedRowKeys: [...completedRowKeys],
98
105
  pendingRowKeys: [...pendingRowKeys],
106
+ failedRowsCount,
99
107
  ...(input.activeBoundaryId !== undefined
100
108
  ? { activeBoundaryId: input.activeBoundaryId }
101
109
  : {}),
@@ -113,12 +121,7 @@ export class MapExecutionFrameStore {
113
121
  logicalNamespace: input.scope.logicalNamespace,
114
122
  artifactTableNamespace: input.scope.artifactTableNamespace,
115
123
  completedRows: nextFrame.completedRowKeys.length,
116
- failedRows: Math.max(
117
- 0,
118
- input.totalRows -
119
- nextFrame.completedRowKeys.length -
120
- nextFrame.pendingRowKeys.length,
121
- ),
124
+ failedRows: failedRowsCount,
122
125
  totalRows: input.totalRows,
123
126
  at: Date.now(),
124
127
  } as PlayExecutionEvent);
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.131",
3071
+ version: "0.3.133",
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
@@ -14866,6 +14866,15 @@ function customerDbColumnNames(result) {
14866
14866
  function errorMessage(value) {
14867
14867
  return value instanceof Error ? value.message : String(value ?? "");
14868
14868
  }
14869
+ function resolveDbQuerySql(rawSql, readFile7 = (path) => (0, import_node_fs8.readFileSync)(path, "utf8")) {
14870
+ const value = rawSql.trim();
14871
+ if (!value.startsWith("@")) return value;
14872
+ const filePath = value.slice(1).trim();
14873
+ if (!filePath) {
14874
+ throw new Error("--sql @file requires a file path after `@`.");
14875
+ }
14876
+ return readFile7((0, import_node_path9.resolve)(filePath)).trim();
14877
+ }
14869
14878
  function collectErrorText(value) {
14870
14879
  if (!value || typeof value !== "object" || Array.isArray(value)) {
14871
14880
  return errorMessage(value);
@@ -14964,13 +14973,24 @@ function dbQueryExportEnvelope(input2) {
14964
14973
  }
14965
14974
  async function handleDbQuery(args) {
14966
14975
  const sqlIndex = args.indexOf("--sql");
14967
- const sql = sqlIndex >= 0 ? args[sqlIndex + 1]?.trim() : "";
14968
- if (!sql) {
14976
+ const rawSql = sqlIndex >= 0 ? args[sqlIndex + 1]?.trim() : "";
14977
+ if (!rawSql) {
14969
14978
  console.error(
14970
- 'Usage: deepline db query --sql "select * from table limit 20" [--max-rows N] [--json]'
14979
+ 'Usage: deepline db query --sql "select * from table limit 20"|@query.sql [--max-rows N] [--json]'
14971
14980
  );
14972
14981
  return 1;
14973
14982
  }
14983
+ let sql;
14984
+ try {
14985
+ sql = resolveDbQuerySql(rawSql);
14986
+ } catch (error) {
14987
+ console.error(errorMessage(error));
14988
+ return 1;
14989
+ }
14990
+ if (!sql) {
14991
+ console.error("SQL file is empty.");
14992
+ return 1;
14993
+ }
14974
14994
  const maxRowsIndex = args.indexOf("--max-rows");
14975
14995
  const maxRows = maxRowsIndex >= 0 && args[maxRowsIndex + 1] ? parseMaxRows(args[maxRowsIndex + 1]) : void 0;
14976
14996
  const formatIndex = args.indexOf("--format");
@@ -15136,8 +15156,9 @@ function registerDbCommands(program) {
15136
15156
  const db = program.command("db").description("Query the tenant customer database.").addHelpText(
15137
15157
  "after",
15138
15158
  `
15139
- Notes:
15159
+ Notes:
15140
15160
  Agent-safe SQL for the active workspace customer database.
15161
+ Use --sql @query.sql for multiline or shell-sensitive SQL (portable across macOS and Windows).
15141
15162
  Reads: SELECT, EXPLAIN, and read-only WITH can inspect permitted schemas.
15142
15163
  Writes: CREATE TABLE, INSERT, UPDATE, DELETE, ALTER, DROP, TRUNCATE, and
15143
15164
  CREATE INDEX must target schema-qualified storage tables, such as storage.agent_notes.
@@ -15150,6 +15171,7 @@ Examples:
15150
15171
  deepline db query --sql "select domain, name from companies limit 20" --json
15151
15172
  deepline db query --sql "create table if not exists storage.agent_notes (id text primary key, note text not null)"
15152
15173
  deepline db query --sql "select * from contacts" --max-rows 100 --json
15174
+ deepline db query --sql @query.sql --json
15153
15175
  deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
15154
15176
  deepline db query --sql "select domain, name from companies limit 20" --format markdown
15155
15177
  `
@@ -15157,8 +15179,8 @@ Examples:
15157
15179
  db.command("query").description("Run SQL against the tenant customer database.").addHelpText(
15158
15180
  "after",
15159
15181
  `
15160
- Notes:
15161
- Requires --sql. Output is a compact table in a terminal and raw JSON with
15182
+ Notes:
15183
+ Requires --sql (inline SQL or @file.sql). Output is a compact table in a terminal and raw JSON with
15162
15184
  --json or when stdout is piped. The active auth workspace determines scope.
15163
15185
  Read permitted schemas with SELECT, EXPLAIN, or read-only WITH.
15164
15186
  Write only to schema-qualified storage tables. For example, use
@@ -15171,6 +15193,7 @@ Examples:
15171
15193
  deepline db query --sql "select domain, name from companies limit 20" --json
15172
15194
  deepline db query --sql "create table if not exists storage.agent_notes (id text primary key, note text not null)"
15173
15195
  deepline db query --sql "select count(*) from contacts" --json
15196
+ deepline db query --sql @query.sql --json
15174
15197
  deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
15175
15198
  deepline db query --sql "select domain, name from companies limit 20" --format markdown
15176
15199
  `
@@ -23563,6 +23586,19 @@ function getProgressLinesFromLiveEvent(event) {
23563
23586
  `progress ${formatProgressLabel(record3.nodeId ?? progress.artifactTableNamespace)}: ${counts}${messageSuffix}`
23564
23587
  );
23565
23588
  }
23589
+ const rowOutcomes = readRowOutcomeSummary({
23590
+ rowOutcomes: payload.rowOutcomes
23591
+ });
23592
+ if (rowOutcomes?.hasRowFailures) {
23593
+ const counts = formatProgressCounts({
23594
+ completed: rowOutcomes.completedRows,
23595
+ total: rowOutcomes.totalRows,
23596
+ failed: rowOutcomes.failedRows
23597
+ });
23598
+ if (counts) {
23599
+ lines.push(`progress run outcomes: ${counts}`);
23600
+ }
23601
+ }
23566
23602
  return lines;
23567
23603
  }
23568
23604
  function shouldPrintPlayProgressLine(input2) {
@@ -24427,6 +24463,7 @@ function collectDatasetHandleLines(value, path = "result") {
24427
24463
  return lines;
24428
24464
  }
24429
24465
  function buildRunWarnings(status, rowsInfo) {
24466
+ const rowOutcomes = readRowOutcomeSummary(status);
24430
24467
  const result = readRecord(status.result);
24431
24468
  const metadata = readRecord(result?._metadata);
24432
24469
  const outputWarnings = Array.isArray(metadata?.outputWarnings) ? metadata.outputWarnings.map((warning) => readRecord(warning)).filter((warning) => {
@@ -24435,16 +24472,24 @@ function buildRunWarnings(status, rowsInfo) {
24435
24472
  }).map((warning) => warning?.message).filter(
24436
24473
  (message) => typeof message === "string" && message.trim().length > 0
24437
24474
  ).slice(0, 16) : [];
24475
+ const rowOutcomeWarnings = rowOutcomes?.hasRowFailures ? [
24476
+ `${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.`
24477
+ ] : [];
24438
24478
  if (status.status === "completed" && rowsInfo?.totalRows === 0) {
24439
- return ["Run completed with 0 output rows.", ...outputWarnings];
24479
+ return [
24480
+ ...rowOutcomeWarnings,
24481
+ "Run completed with 0 output rows.",
24482
+ ...outputWarnings
24483
+ ];
24440
24484
  }
24441
24485
  if (rowsInfo && !rowsInfo.complete) {
24442
24486
  return [
24487
+ ...rowOutcomeWarnings,
24443
24488
  `Run output is partial: showing ${rowsInfo.rows.length} preview row(s) of ${rowsInfo.totalRows}.`,
24444
24489
  ...outputWarnings
24445
24490
  ];
24446
24491
  }
24447
- return outputWarnings;
24492
+ return [...rowOutcomeWarnings, ...outputWarnings];
24448
24493
  }
24449
24494
  function buildRunNextCommands(status) {
24450
24495
  const runId = status.runId?.trim();
@@ -24480,6 +24525,23 @@ function getNumericField(value, key) {
24480
24525
  const field = getRecordField(value, key);
24481
24526
  return typeof field === "number" && Number.isFinite(field) ? field : null;
24482
24527
  }
24528
+ function readRowOutcomeSummary(value) {
24529
+ const record3 = getRecordField(value, "rowOutcomes");
24530
+ if (!record3) return null;
24531
+ const completedRows = getNumericField(record3, "completedRows");
24532
+ const failedRows = getNumericField(record3, "failedRows");
24533
+ const totalRows = getNumericField(record3, "totalRows");
24534
+ if (completedRows === null || failedRows === null || totalRows === null) {
24535
+ return null;
24536
+ }
24537
+ const explicitHasFailures = getRecordField(record3, "hasRowFailures");
24538
+ return {
24539
+ completedRows,
24540
+ failedRows,
24541
+ totalRows,
24542
+ hasRowFailures: typeof explicitHasFailures === "boolean" ? explicitHasFailures : failedRows > 0
24543
+ };
24544
+ }
24483
24545
  function getStringField(value, key) {
24484
24546
  const field = getRecordField(value, key);
24485
24547
  return typeof field === "string" && field.trim() ? field : null;
@@ -24693,9 +24755,10 @@ function normalizeRunStatusForEnvelope(status) {
24693
24755
  }
24694
24756
  function normalizeProgressForEnvelope(status, rowsInfo) {
24695
24757
  const progress = status.progress;
24696
- const total = getNumericField(progress, "totalRows") ?? getNumericField(progress, "total") ?? rowsInfo?.totalRows ?? null;
24697
- const failed = getNumericField(progress, "failed") ?? getNumericField(progress, "failedRows") ?? null;
24698
- const completed = getNumericField(progress, "completed") ?? getNumericField(progress, "completedRows") ?? (status.status === "completed" ? total : null);
24758
+ const rowOutcomes = readRowOutcomeSummary(status);
24759
+ const total = rowOutcomes?.totalRows ?? getNumericField(progress, "totalRows") ?? getNumericField(progress, "total") ?? rowsInfo?.totalRows ?? null;
24760
+ const failed = rowOutcomes?.failedRows ?? getNumericField(progress, "failed") ?? getNumericField(progress, "failedRows") ?? null;
24761
+ const completed = rowOutcomes?.completedRows ?? getNumericField(progress, "completed") ?? getNumericField(progress, "completedRows") ?? (status.status === "completed" ? total : null);
24699
24762
  const pending = getNumericField(progress, "pending") ?? (typeof total === "number" && typeof completed === "number" && typeof failed === "number" ? Math.max(0, total - completed - failed) : null);
24700
24763
  return {
24701
24764
  total,
@@ -24824,9 +24887,22 @@ function compactPlayStatus(status) {
24824
24887
  const packagedError = typeof packagedRun?.error === "string" ? packagedRun.error : null;
24825
24888
  const error2 = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : packagedError);
24826
24889
  const compactError = error2 ? compactRunErrorForEnvelope(error2, status.runId) : null;
24890
+ const rowOutcomes2 = readRowOutcomeSummary(status);
24891
+ const packagedWithRowOutcomes = rowOutcomes2 ? {
24892
+ ...packaged,
24893
+ rowOutcomes: rowOutcomes2,
24894
+ warnings: [
24895
+ ...Array.isArray(packaged.warnings) ? packaged.warnings.filter(
24896
+ (warning) => typeof warning === "string"
24897
+ ) : [],
24898
+ ...rowOutcomes2.hasRowFailures ? [
24899
+ `${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.`
24900
+ ] : []
24901
+ ]
24902
+ } : packaged;
24827
24903
  if (!error2) {
24828
24904
  return status.failedLogs || status.rerunCommand ? {
24829
- ...packaged,
24905
+ ...packagedWithRowOutcomes,
24830
24906
  ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
24831
24907
  next: {
24832
24908
  ...readRecord(packaged.next) ?? {},
@@ -24835,11 +24911,11 @@ function compactPlayStatus(status) {
24835
24911
  } : {},
24836
24912
  ...status.rerunCommand ? { run: status.rerunCommand } : {}
24837
24913
  }
24838
- } : packaged;
24914
+ } : packagedWithRowOutcomes;
24839
24915
  }
24840
24916
  const run = packagedRun;
24841
24917
  return {
24842
- ...packaged,
24918
+ ...packagedWithRowOutcomes,
24843
24919
  ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
24844
24920
  ...status.failedLogs ? {
24845
24921
  next: {
@@ -24868,6 +24944,7 @@ function compactPlayStatus(status) {
24868
24944
  ) : null;
24869
24945
  const error = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : null);
24870
24946
  const displayError = formatPlayErrorForDisplay(status, error);
24947
+ const rowOutcomes = readRowOutcomeSummary(status);
24871
24948
  return {
24872
24949
  runId: status.runId,
24873
24950
  apiVersion: status.apiVersion ?? 1,
@@ -24877,6 +24954,7 @@ function compactPlayStatus(status) {
24877
24954
  status: status.status,
24878
24955
  run: normalizeRunStatusForEnvelope(status),
24879
24956
  progress: normalizeProgressForEnvelope(status, rowsInfo),
24957
+ ...rowOutcomes ? { rowOutcomes } : {},
24880
24958
  steps: normalizeStepsForEnvelope(status),
24881
24959
  errors: normalizeErrorsForEnvelope(status, error),
24882
24960
  logs: normalizeLogsForEnvelope(status),
@@ -3063,7 +3063,7 @@ var SDK_RELEASE = {
3063
3063
  // getters keep their established compatibility behavior.
3064
3064
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3065
3065
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3066
- version: "0.3.131",
3066
+ version: "0.3.133",
3067
3067
  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.",
3068
3068
  packageCapabilities: {
3069
3069
  updatePreferences: 1
@@ -14800,7 +14800,7 @@ Examples:
14800
14800
  }
14801
14801
 
14802
14802
  // src/cli/commands/db.ts
14803
- import { writeFileSync as writeFileSync8 } from "fs";
14803
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "fs";
14804
14804
  import { resolve as resolve6 } from "path";
14805
14805
  var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set(["table", "json", "csv", "markdown"]);
14806
14806
  var CUSTOMER_DB_QUERY_MAX_ROWS = 1e3;
@@ -14881,6 +14881,15 @@ function customerDbColumnNames(result) {
14881
14881
  function errorMessage(value) {
14882
14882
  return value instanceof Error ? value.message : String(value ?? "");
14883
14883
  }
14884
+ function resolveDbQuerySql(rawSql, readFile7 = (path) => readFileSync7(path, "utf8")) {
14885
+ const value = rawSql.trim();
14886
+ if (!value.startsWith("@")) return value;
14887
+ const filePath = value.slice(1).trim();
14888
+ if (!filePath) {
14889
+ throw new Error("--sql @file requires a file path after `@`.");
14890
+ }
14891
+ return readFile7(resolve6(filePath)).trim();
14892
+ }
14884
14893
  function collectErrorText(value) {
14885
14894
  if (!value || typeof value !== "object" || Array.isArray(value)) {
14886
14895
  return errorMessage(value);
@@ -14979,13 +14988,24 @@ function dbQueryExportEnvelope(input2) {
14979
14988
  }
14980
14989
  async function handleDbQuery(args) {
14981
14990
  const sqlIndex = args.indexOf("--sql");
14982
- const sql = sqlIndex >= 0 ? args[sqlIndex + 1]?.trim() : "";
14983
- if (!sql) {
14991
+ const rawSql = sqlIndex >= 0 ? args[sqlIndex + 1]?.trim() : "";
14992
+ if (!rawSql) {
14984
14993
  console.error(
14985
- 'Usage: deepline db query --sql "select * from table limit 20" [--max-rows N] [--json]'
14994
+ 'Usage: deepline db query --sql "select * from table limit 20"|@query.sql [--max-rows N] [--json]'
14986
14995
  );
14987
14996
  return 1;
14988
14997
  }
14998
+ let sql;
14999
+ try {
15000
+ sql = resolveDbQuerySql(rawSql);
15001
+ } catch (error) {
15002
+ console.error(errorMessage(error));
15003
+ return 1;
15004
+ }
15005
+ if (!sql) {
15006
+ console.error("SQL file is empty.");
15007
+ return 1;
15008
+ }
14989
15009
  const maxRowsIndex = args.indexOf("--max-rows");
14990
15010
  const maxRows = maxRowsIndex >= 0 && args[maxRowsIndex + 1] ? parseMaxRows(args[maxRowsIndex + 1]) : void 0;
14991
15011
  const formatIndex = args.indexOf("--format");
@@ -15151,8 +15171,9 @@ function registerDbCommands(program) {
15151
15171
  const db = program.command("db").description("Query the tenant customer database.").addHelpText(
15152
15172
  "after",
15153
15173
  `
15154
- Notes:
15174
+ Notes:
15155
15175
  Agent-safe SQL for the active workspace customer database.
15176
+ Use --sql @query.sql for multiline or shell-sensitive SQL (portable across macOS and Windows).
15156
15177
  Reads: SELECT, EXPLAIN, and read-only WITH can inspect permitted schemas.
15157
15178
  Writes: CREATE TABLE, INSERT, UPDATE, DELETE, ALTER, DROP, TRUNCATE, and
15158
15179
  CREATE INDEX must target schema-qualified storage tables, such as storage.agent_notes.
@@ -15165,6 +15186,7 @@ Examples:
15165
15186
  deepline db query --sql "select domain, name from companies limit 20" --json
15166
15187
  deepline db query --sql "create table if not exists storage.agent_notes (id text primary key, note text not null)"
15167
15188
  deepline db query --sql "select * from contacts" --max-rows 100 --json
15189
+ deepline db query --sql @query.sql --json
15168
15190
  deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
15169
15191
  deepline db query --sql "select domain, name from companies limit 20" --format markdown
15170
15192
  `
@@ -15172,8 +15194,8 @@ Examples:
15172
15194
  db.command("query").description("Run SQL against the tenant customer database.").addHelpText(
15173
15195
  "after",
15174
15196
  `
15175
- Notes:
15176
- Requires --sql. Output is a compact table in a terminal and raw JSON with
15197
+ Notes:
15198
+ Requires --sql (inline SQL or @file.sql). Output is a compact table in a terminal and raw JSON with
15177
15199
  --json or when stdout is piped. The active auth workspace determines scope.
15178
15200
  Read permitted schemas with SELECT, EXPLAIN, or read-only WITH.
15179
15201
  Write only to schema-qualified storage tables. For example, use
@@ -15186,6 +15208,7 @@ Examples:
15186
15208
  deepline db query --sql "select domain, name from companies limit 20" --json
15187
15209
  deepline db query --sql "create table if not exists storage.agent_notes (id text primary key, note text not null)"
15188
15210
  deepline db query --sql "select count(*) from contacts" --json
15211
+ deepline db query --sql @query.sql --json
15189
15212
  deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
15190
15213
  deepline db query --sql "select domain, name from companies limit 20" --format markdown
15191
15214
  `
@@ -15252,7 +15275,7 @@ import { createHash as createHash4, randomUUID as randomUUID4 } from "crypto";
15252
15275
  import {
15253
15276
  existsSync as existsSync9,
15254
15277
  mkdirSync as mkdirSync7,
15255
- readFileSync as readFileSync8,
15278
+ readFileSync as readFileSync9,
15256
15279
  readdirSync as readdirSync2,
15257
15280
  realpathSync as realpathSync2,
15258
15281
  statSync as statSync3,
@@ -16988,7 +17011,7 @@ import { realpath as realpath2 } from "fs/promises";
16988
17011
 
16989
17012
  // ../plays/bundling/index.ts
16990
17013
  import { createHash as createHash2 } from "crypto";
16991
- import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
17014
+ import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
16992
17015
  import { mkdir as mkdir3, readFile, realpath, stat, writeFile as writeFile3 } from "fs/promises";
16993
17016
  import { tmpdir as tmpdir2 } from "os";
16994
17017
  import {
@@ -22566,7 +22589,7 @@ function materializeRemotePlaySource(input2) {
22566
22589
  if (!existsSync9(outputPath2)) {
22567
22590
  writeFileSync10(outputPath2, sourceCode, "utf-8");
22568
22591
  created += 1;
22569
- } else if (readFileSync8(outputPath2, "utf-8") !== sourceCode) {
22592
+ } else if (readFileSync9(outputPath2, "utf-8") !== sourceCode) {
22570
22593
  writeFileSync10(outputPath2, sourceCode, "utf-8");
22571
22594
  updated += 1;
22572
22595
  }
@@ -22580,7 +22603,7 @@ function materializeRemotePlaySource(input2) {
22580
22603
  }
22581
22604
  const outputPath = input2.outPath ?? defaultMaterializedPlayPath(input2.playName);
22582
22605
  if (existsSync9(outputPath)) {
22583
- const existingSource = readFileSync8(outputPath, "utf-8");
22606
+ const existingSource = readFileSync9(outputPath, "utf-8");
22584
22607
  if (existingSource === entrySource) {
22585
22608
  return { path: outputPath, status: "unchanged", created: false };
22586
22609
  }
@@ -22661,7 +22684,7 @@ function parsePositiveInteger3(value, flagName) {
22661
22684
  return parsed;
22662
22685
  }
22663
22686
  function parseJsonInput(raw) {
22664
- const source = raw.startsWith("@") ? readFileSync8(resolve12(raw.slice(1)), "utf-8") : raw;
22687
+ const source = raw.startsWith("@") ? readFileSync9(resolve12(raw.slice(1)), "utf-8") : raw;
22665
22688
  const parsed = JSON.parse(source);
22666
22689
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
22667
22690
  throw new Error("--input must be a JSON object.");
@@ -22891,7 +22914,7 @@ function preflightLocalFileInputs(runtimeInput) {
22891
22914
  function preflightCsvDataInput(ref, absolutePath) {
22892
22915
  let content;
22893
22916
  try {
22894
- content = readFileSync8(absolutePath, "utf-8");
22917
+ content = readFileSync9(absolutePath, "utf-8");
22895
22918
  } catch (error) {
22896
22919
  throw new DeeplineError(
22897
22920
  `Input ${ref.inputPath} CSV ${ref.value} is not readable: ${error instanceof Error ? error.message : String(error)}. No run was created.`,
@@ -23006,7 +23029,7 @@ async function stageFileInputArgs(input2) {
23006
23029
  };
23007
23030
  }
23008
23031
  function stageFile(logicalPath, absolutePath) {
23009
- const buffer = readFileSync8(absolutePath);
23032
+ const buffer = readFileSync9(absolutePath);
23010
23033
  return {
23011
23034
  logicalPath,
23012
23035
  contentBase64: buffer.toString("base64"),
@@ -23635,6 +23658,19 @@ function getProgressLinesFromLiveEvent(event) {
23635
23658
  `progress ${formatProgressLabel(record3.nodeId ?? progress.artifactTableNamespace)}: ${counts}${messageSuffix}`
23636
23659
  );
23637
23660
  }
23661
+ const rowOutcomes = readRowOutcomeSummary({
23662
+ rowOutcomes: payload.rowOutcomes
23663
+ });
23664
+ if (rowOutcomes?.hasRowFailures) {
23665
+ const counts = formatProgressCounts({
23666
+ completed: rowOutcomes.completedRows,
23667
+ total: rowOutcomes.totalRows,
23668
+ failed: rowOutcomes.failedRows
23669
+ });
23670
+ if (counts) {
23671
+ lines.push(`progress run outcomes: ${counts}`);
23672
+ }
23673
+ }
23638
23674
  return lines;
23639
23675
  }
23640
23676
  function shouldPrintPlayProgressLine(input2) {
@@ -24499,6 +24535,7 @@ function collectDatasetHandleLines(value, path = "result") {
24499
24535
  return lines;
24500
24536
  }
24501
24537
  function buildRunWarnings(status, rowsInfo) {
24538
+ const rowOutcomes = readRowOutcomeSummary(status);
24502
24539
  const result = readRecord(status.result);
24503
24540
  const metadata = readRecord(result?._metadata);
24504
24541
  const outputWarnings = Array.isArray(metadata?.outputWarnings) ? metadata.outputWarnings.map((warning) => readRecord(warning)).filter((warning) => {
@@ -24507,16 +24544,24 @@ function buildRunWarnings(status, rowsInfo) {
24507
24544
  }).map((warning) => warning?.message).filter(
24508
24545
  (message) => typeof message === "string" && message.trim().length > 0
24509
24546
  ).slice(0, 16) : [];
24547
+ const rowOutcomeWarnings = rowOutcomes?.hasRowFailures ? [
24548
+ `${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.`
24549
+ ] : [];
24510
24550
  if (status.status === "completed" && rowsInfo?.totalRows === 0) {
24511
- return ["Run completed with 0 output rows.", ...outputWarnings];
24551
+ return [
24552
+ ...rowOutcomeWarnings,
24553
+ "Run completed with 0 output rows.",
24554
+ ...outputWarnings
24555
+ ];
24512
24556
  }
24513
24557
  if (rowsInfo && !rowsInfo.complete) {
24514
24558
  return [
24559
+ ...rowOutcomeWarnings,
24515
24560
  `Run output is partial: showing ${rowsInfo.rows.length} preview row(s) of ${rowsInfo.totalRows}.`,
24516
24561
  ...outputWarnings
24517
24562
  ];
24518
24563
  }
24519
- return outputWarnings;
24564
+ return [...rowOutcomeWarnings, ...outputWarnings];
24520
24565
  }
24521
24566
  function buildRunNextCommands(status) {
24522
24567
  const runId = status.runId?.trim();
@@ -24552,6 +24597,23 @@ function getNumericField(value, key) {
24552
24597
  const field = getRecordField(value, key);
24553
24598
  return typeof field === "number" && Number.isFinite(field) ? field : null;
24554
24599
  }
24600
+ function readRowOutcomeSummary(value) {
24601
+ const record3 = getRecordField(value, "rowOutcomes");
24602
+ if (!record3) return null;
24603
+ const completedRows = getNumericField(record3, "completedRows");
24604
+ const failedRows = getNumericField(record3, "failedRows");
24605
+ const totalRows = getNumericField(record3, "totalRows");
24606
+ if (completedRows === null || failedRows === null || totalRows === null) {
24607
+ return null;
24608
+ }
24609
+ const explicitHasFailures = getRecordField(record3, "hasRowFailures");
24610
+ return {
24611
+ completedRows,
24612
+ failedRows,
24613
+ totalRows,
24614
+ hasRowFailures: typeof explicitHasFailures === "boolean" ? explicitHasFailures : failedRows > 0
24615
+ };
24616
+ }
24555
24617
  function getStringField(value, key) {
24556
24618
  const field = getRecordField(value, key);
24557
24619
  return typeof field === "string" && field.trim() ? field : null;
@@ -24765,9 +24827,10 @@ function normalizeRunStatusForEnvelope(status) {
24765
24827
  }
24766
24828
  function normalizeProgressForEnvelope(status, rowsInfo) {
24767
24829
  const progress = status.progress;
24768
- const total = getNumericField(progress, "totalRows") ?? getNumericField(progress, "total") ?? rowsInfo?.totalRows ?? null;
24769
- const failed = getNumericField(progress, "failed") ?? getNumericField(progress, "failedRows") ?? null;
24770
- const completed = getNumericField(progress, "completed") ?? getNumericField(progress, "completedRows") ?? (status.status === "completed" ? total : null);
24830
+ const rowOutcomes = readRowOutcomeSummary(status);
24831
+ const total = rowOutcomes?.totalRows ?? getNumericField(progress, "totalRows") ?? getNumericField(progress, "total") ?? rowsInfo?.totalRows ?? null;
24832
+ const failed = rowOutcomes?.failedRows ?? getNumericField(progress, "failed") ?? getNumericField(progress, "failedRows") ?? null;
24833
+ const completed = rowOutcomes?.completedRows ?? getNumericField(progress, "completed") ?? getNumericField(progress, "completedRows") ?? (status.status === "completed" ? total : null);
24771
24834
  const pending = getNumericField(progress, "pending") ?? (typeof total === "number" && typeof completed === "number" && typeof failed === "number" ? Math.max(0, total - completed - failed) : null);
24772
24835
  return {
24773
24836
  total,
@@ -24896,9 +24959,22 @@ function compactPlayStatus(status) {
24896
24959
  const packagedError = typeof packagedRun?.error === "string" ? packagedRun.error : null;
24897
24960
  const error2 = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : packagedError);
24898
24961
  const compactError = error2 ? compactRunErrorForEnvelope(error2, status.runId) : null;
24962
+ const rowOutcomes2 = readRowOutcomeSummary(status);
24963
+ const packagedWithRowOutcomes = rowOutcomes2 ? {
24964
+ ...packaged,
24965
+ rowOutcomes: rowOutcomes2,
24966
+ warnings: [
24967
+ ...Array.isArray(packaged.warnings) ? packaged.warnings.filter(
24968
+ (warning) => typeof warning === "string"
24969
+ ) : [],
24970
+ ...rowOutcomes2.hasRowFailures ? [
24971
+ `${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.`
24972
+ ] : []
24973
+ ]
24974
+ } : packaged;
24899
24975
  if (!error2) {
24900
24976
  return status.failedLogs || status.rerunCommand ? {
24901
- ...packaged,
24977
+ ...packagedWithRowOutcomes,
24902
24978
  ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
24903
24979
  next: {
24904
24980
  ...readRecord(packaged.next) ?? {},
@@ -24907,11 +24983,11 @@ function compactPlayStatus(status) {
24907
24983
  } : {},
24908
24984
  ...status.rerunCommand ? { run: status.rerunCommand } : {}
24909
24985
  }
24910
- } : packaged;
24986
+ } : packagedWithRowOutcomes;
24911
24987
  }
24912
24988
  const run = packagedRun;
24913
24989
  return {
24914
- ...packaged,
24990
+ ...packagedWithRowOutcomes,
24915
24991
  ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
24916
24992
  ...status.failedLogs ? {
24917
24993
  next: {
@@ -24940,6 +25016,7 @@ function compactPlayStatus(status) {
24940
25016
  ) : null;
24941
25017
  const error = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : null);
24942
25018
  const displayError = formatPlayErrorForDisplay(status, error);
25019
+ const rowOutcomes = readRowOutcomeSummary(status);
24943
25020
  return {
24944
25021
  runId: status.runId,
24945
25022
  apiVersion: status.apiVersion ?? 1,
@@ -24949,6 +25026,7 @@ function compactPlayStatus(status) {
24949
25026
  status: status.status,
24950
25027
  run: normalizeRunStatusForEnvelope(status),
24951
25028
  progress: normalizeProgressForEnvelope(status, rowsInfo),
25029
+ ...rowOutcomes ? { rowOutcomes } : {},
24952
25030
  steps: normalizeStepsForEnvelope(status),
24953
25031
  errors: normalizeErrorsForEnvelope(status, error),
24954
25032
  logs: normalizeLogsForEnvelope(status),
@@ -26997,7 +27075,7 @@ async function handlePlayCheck(args) {
26997
27075
  }
26998
27076
  }
26999
27077
  const absolutePlayPath = resolve12(options.target);
27000
- const sourceCode = readFileSync8(absolutePlayPath, "utf-8");
27078
+ const sourceCode = readFileSync9(absolutePlayPath, "utf-8");
27001
27079
  const exportNames = resolvePlayCheckExportNames(sourceCode);
27002
27080
  const outcomes = [];
27003
27081
  for (const exportName of exportNames) {
@@ -27243,7 +27321,7 @@ async function handleFileBackedRun(options, hooks) {
27243
27321
  const sourceCode = traceCliSync(
27244
27322
  "cli.play_file_read_source",
27245
27323
  { targetKind: "file" },
27246
- () => readFileSync8(absolutePlayPath, "utf-8")
27324
+ () => readFileSync9(absolutePlayPath, "utf-8")
27247
27325
  );
27248
27326
  const runtimeInput = options.input ? { ...options.input } : {};
27249
27327
  try {
@@ -28435,7 +28513,7 @@ async function handlePlayGet(args) {
28435
28513
  );
28436
28514
  return 2;
28437
28515
  }
28438
- const playName = isFileTarget(target) ? extractPlayName(readFileSync8(resolve12(target), "utf-8"), resolve12(target)) : parseReferencedPlayTarget2(target).playName;
28516
+ const playName = isFileTarget(target) ? extractPlayName(readFileSync9(resolve12(target), "utf-8"), resolve12(target)) : parseReferencedPlayTarget2(target).playName;
28439
28517
  const includeSource = sourceOutput || outPath !== null;
28440
28518
  const detail = isFileTarget(target) ? await client2.getPlay(
28441
28519
  playName,
@@ -28940,7 +29018,7 @@ async function handlePlayDescribe(args) {
28940
29018
  const definedName = isFileTarget(playName) ? (() => {
28941
29019
  try {
28942
29020
  return extractPlayName(
28943
- readFileSync8(resolve12(playName), "utf-8"),
29021
+ readFileSync9(resolve12(playName), "utf-8"),
28944
29022
  playName
28945
29023
  );
28946
29024
  } catch {
@@ -35861,7 +35939,7 @@ function registerEnrichCommand(program) {
35861
35939
 
35862
35940
  // src/cli/commands/feedback.ts
35863
35941
  import { Option as Option3 } from "commander";
35864
- import { readFileSync as readFileSync9 } from "fs";
35942
+ import { readFileSync as readFileSync10 } from "fs";
35865
35943
  async function handleFeedback(text, options) {
35866
35944
  const message = resolveFeedbackText(text, options.file);
35867
35945
  const { http } = getAuthedHttpClient();
@@ -35885,7 +35963,7 @@ async function handleFeedback(text, options) {
35885
35963
  { json: options.json }
35886
35964
  );
35887
35965
  }
35888
- function resolveFeedbackText(text, file, readFile7 = (path) => readFileSync9(path, "utf8")) {
35966
+ function resolveFeedbackText(text, file, readFile7 = (path) => readFileSync10(path, "utf8")) {
35889
35967
  if (text !== void 0 && file !== void 0) {
35890
35968
  throw new Error(
35891
35969
  "Pass feedback text positionally or with --file, not both."
@@ -35956,7 +36034,7 @@ import {
35956
36034
  existsSync as existsSync10,
35957
36035
  mkdirSync as mkdirSync8,
35958
36036
  readdirSync as readdirSync3,
35959
- readFileSync as readFileSync10,
36037
+ readFileSync as readFileSync11,
35960
36038
  statSync as statSync4,
35961
36039
  writeFileSync as writeFileSync11
35962
36040
  } from "fs";
@@ -36094,7 +36172,7 @@ function sessionIdFromCodexFilePath(filePath) {
36094
36172
  }
36095
36173
  function readCodexSessionId(filePath) {
36096
36174
  try {
36097
- for (const line of normalizedJsonLines(readFileSync10(filePath)).slice(
36175
+ for (const line of normalizedJsonLines(readFileSync11(filePath)).slice(
36098
36176
  0,
36099
36177
  20
36100
36178
  )) {
@@ -36413,7 +36491,7 @@ async function handleSessionsSend(options) {
36413
36491
  throw new Error(`File not found: ${options.file}`);
36414
36492
  }
36415
36493
  const response2 = await uploadPayload("/api/v2/cli/send-session", {
36416
- file: readFileSync10(filePath).toString("base64"),
36494
+ file: readFileSync11(filePath).toString("base64"),
36417
36495
  filename: basename5(filePath)
36418
36496
  });
36419
36497
  printCommandEnvelope(
@@ -36443,7 +36521,7 @@ async function handleSessionsSend(options) {
36443
36521
  agent: options.agent
36444
36522
  });
36445
36523
  const built = targets.map((target) => {
36446
- const upload = buildSessionUploadContent(readFileSync10(target.filePath));
36524
+ const upload = buildSessionUploadContent(readFileSync11(target.filePath));
36447
36525
  return { ...target, ...upload };
36448
36526
  });
36449
36527
  if (built.some((session) => session.needsChunking)) {
@@ -36527,8 +36605,8 @@ function loadViewerAssets() {
36527
36605
  const jsPath = join15(root, "viewer.js");
36528
36606
  if (!existsSync10(cssPath) || !existsSync10(jsPath)) continue;
36529
36607
  return {
36530
- css: readFileSync10(cssPath, "utf8"),
36531
- js: readFileSync10(jsPath, "utf8")
36608
+ css: readFileSync11(cssPath, "utf8"),
36609
+ js: readFileSync11(jsPath, "utf8")
36532
36610
  };
36533
36611
  } catch {
36534
36612
  continue;
@@ -36566,7 +36644,7 @@ async function handleSessionsRender(options) {
36566
36644
  const sessions = targets.map((target) => ({
36567
36645
  label: target.label,
36568
36646
  events: parsePreparedEvents(
36569
- prepareSessionBuffer(readFileSync10(target.filePath))
36647
+ prepareSessionBuffer(readFileSync11(target.filePath))
36570
36648
  )
36571
36649
  }));
36572
36650
  const { css, js } = loadViewerAssets();
@@ -36800,7 +36878,7 @@ Examples:
36800
36878
 
36801
36879
  // src/cli/commands/monitors.ts
36802
36880
  import { randomUUID as randomUUID6 } from "crypto";
36803
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync12 } from "fs";
36881
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
36804
36882
  import { resolve as resolve15 } from "path";
36805
36883
  import { createInterface } from "readline/promises";
36806
36884
 
@@ -37664,8 +37742,8 @@ function parseJsonObjectArg(raw, argLabel) {
37664
37742
  return parsed;
37665
37743
  }
37666
37744
  function resolveMonitorJsonBody(input2) {
37667
- const readFile7 = input2.readFile ?? ((path) => readFileSync11(path, "utf-8"));
37668
- const readStdin = input2.readStdin ?? (() => readFileSync11(0, "utf-8"));
37745
+ const readFile7 = input2.readFile ?? ((path) => readFileSync12(path, "utf-8"));
37746
+ const readStdin = input2.readStdin ?? (() => readFileSync12(0, "utf-8"));
37669
37747
  if (input2.positional !== void 0 && input2.file !== void 0) {
37670
37748
  throw new MonitorsUsageError(
37671
37749
  `Pass exactly one source for ${input2.argLabel}: the positional JSON or --file, not both.`
@@ -38328,7 +38406,7 @@ function monitorJobIdempotencyKey(operation, supplied) {
38328
38406
  function readMonitorDefinitionsJsonFile(file) {
38329
38407
  let raw;
38330
38408
  try {
38331
- raw = file === "-" ? readFileSync11(0, "utf8") : readFileSync11(file, "utf8");
38409
+ raw = file === "-" ? readFileSync12(0, "utf8") : readFileSync12(file, "utf8");
38332
38410
  } catch (error) {
38333
38411
  throw new MonitorsUsageError(
38334
38412
  `Could not read --file ${file}: ${error instanceof Error ? error.message : String(error)}`
@@ -39843,7 +39921,7 @@ async function handleMonitorBatchDeploy(options) {
39843
39921
  }
39844
39922
  let manifestNdjson;
39845
39923
  try {
39846
- manifestNdjson = readFileSync11(resolve15(options.file), "utf8");
39924
+ manifestNdjson = readFileSync12(resolve15(options.file), "utf8");
39847
39925
  } catch (error) {
39848
39926
  throw new MonitorsUsageError(
39849
39927
  `Could not read monitor batch manifest '${options.file}': ${error instanceof Error ? error.message : String(error)}`
@@ -40746,7 +40824,7 @@ import { createHash as createHash5, randomUUID as randomUUID7 } from "crypto";
40746
40824
  import {
40747
40825
  existsSync as existsSync11,
40748
40826
  mkdirSync as mkdirSync9,
40749
- readFileSync as readFileSync12,
40827
+ readFileSync as readFileSync13,
40750
40828
  unlinkSync,
40751
40829
  writeFileSync as writeFileSync13
40752
40830
  } from "fs";
@@ -40758,7 +40836,7 @@ function pendingOrgCreatePath(baseUrl, accountId, sourceOrgId, name) {
40758
40836
  function readPendingOrgCreate(path, accountId, sourceOrgId, name) {
40759
40837
  let value;
40760
40838
  try {
40761
- value = JSON.parse(readFileSync12(path, "utf8"));
40839
+ value = JSON.parse(readFileSync13(path, "utf8"));
40762
40840
  } catch (error) {
40763
40841
  throw new Error(
40764
40842
  `Cannot resume the pending workspace creation recorded at ${path}: ${error instanceof Error ? error.message : String(error)}`
@@ -42015,7 +42093,7 @@ import {
42015
42093
  existsSync as existsSync15,
42016
42094
  lstatSync as lstatSync2,
42017
42095
  mkdirSync as mkdirSync12,
42018
- readFileSync as readFileSync16,
42096
+ readFileSync as readFileSync17,
42019
42097
  realpathSync as realpathSync4,
42020
42098
  writeFileSync as writeFileSync16
42021
42099
  } from "fs";
@@ -42026,7 +42104,7 @@ import { dirname as dirname16, join as join20, resolve as resolve17 } from "path
42026
42104
  import {
42027
42105
  existsSync as existsSync12,
42028
42106
  lstatSync,
42029
- readFileSync as readFileSync13,
42107
+ readFileSync as readFileSync14,
42030
42108
  realpathSync as realpathSync3,
42031
42109
  rmSync as rmSync4
42032
42110
  } from "fs";
@@ -42042,7 +42120,7 @@ var nodeFileSystem = {
42042
42120
  },
42043
42121
  read(path) {
42044
42122
  try {
42045
- return readFileSync13(path, "utf8");
42123
+ return readFileSync14(path, "utf8");
42046
42124
  } catch {
42047
42125
  return "";
42048
42126
  }
@@ -42152,7 +42230,7 @@ function isOwnedInstallerCommandPath(input2) {
42152
42230
 
42153
42231
  // src/cli/commands/skills.ts
42154
42232
  import { spawn as spawn3 } from "child_process";
42155
- import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync15 } from "fs";
42233
+ import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync15 } from "fs";
42156
42234
  import { homedir as homedir8 } from "os";
42157
42235
  import { dirname as dirname15, join as join19 } from "path";
42158
42236
 
@@ -42273,7 +42351,7 @@ import {
42273
42351
  appendFileSync,
42274
42352
  existsSync as existsSync13,
42275
42353
  mkdirSync as mkdirSync10,
42276
- readFileSync as readFileSync14,
42354
+ readFileSync as readFileSync15,
42277
42355
  renameSync,
42278
42356
  rmSync as rmSync5,
42279
42357
  unlinkSync as unlinkSync2,
@@ -42892,7 +42970,7 @@ function flushDeferredSkillsNotices(baseUrl, agents) {
42892
42970
  if (!tombstone) return;
42893
42971
  let text = "";
42894
42972
  try {
42895
- text = readFileSync14(tombstone, "utf-8");
42973
+ text = readFileSync15(tombstone, "utf-8");
42896
42974
  } catch {
42897
42975
  return;
42898
42976
  } finally {
@@ -42930,7 +43008,7 @@ function hasMarkedSkillsSyncVersion(path, version) {
42930
43008
  }
42931
43009
  function readMarkedSkillsSyncVersion(path) {
42932
43010
  try {
42933
- return existsSync13(path) ? readFileSync14(path, "utf-8").trim() : "";
43011
+ return existsSync13(path) ? readFileSync15(path, "utf-8").trim() : "";
42934
43012
  } catch {
42935
43013
  return "";
42936
43014
  }
@@ -43491,7 +43569,7 @@ function isSkillsPlanCurrent(plan, state) {
43491
43569
  }
43492
43570
  function readSkillsInstallState(path) {
43493
43571
  try {
43494
- const parsed = JSON.parse(readFileSync15(path, "utf8"));
43572
+ const parsed = JSON.parse(readFileSync16(path, "utf8"));
43495
43573
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
43496
43574
  } catch {
43497
43575
  return null;
@@ -43859,7 +43937,7 @@ function phasesFromLegacyStatus(status) {
43859
43937
  function readSetupState(input2) {
43860
43938
  try {
43861
43939
  const parsed = JSON.parse(
43862
- readFileSync16(
43940
+ readFileSync17(
43863
43941
  setupStatePath(input2.baseUrl, input2.scope, input2.root),
43864
43942
  "utf8"
43865
43943
  )
@@ -43964,7 +44042,7 @@ function asRecord3(value) {
43964
44042
  }
43965
44043
  function safeRead(path) {
43966
44044
  try {
43967
- return readFileSync16(path, "utf8");
44045
+ return readFileSync17(path, "utf8");
43968
44046
  } catch {
43969
44047
  return "";
43970
44048
  }
@@ -44723,13 +44801,13 @@ Examples:
44723
44801
  }
44724
44802
 
44725
44803
  // src/cli/commands/settings.ts
44726
- import { readFileSync as readFileSync20 } from "fs";
44804
+ import { readFileSync as readFileSync21 } from "fs";
44727
44805
 
44728
44806
  // src/cli/update-preferences.ts
44729
44807
  import {
44730
44808
  existsSync as existsSync16,
44731
44809
  mkdirSync as mkdirSync13,
44732
- readFileSync as readFileSync17,
44810
+ readFileSync as readFileSync18,
44733
44811
  renameSync as renameSync2,
44734
44812
  rmSync as rmSync6,
44735
44813
  writeFileSync as writeFileSync17
@@ -44776,7 +44854,7 @@ function readCliUpdatePreferences(homeDir2 = homedir10()) {
44776
44854
  const path = cliUpdatePreferencesPath(homeDir2);
44777
44855
  if (!existsSync16(path)) return defaultPreferences();
44778
44856
  try {
44779
- const parsed = JSON.parse(readFileSync17(path, "utf8"));
44857
+ const parsed = JSON.parse(readFileSync18(path, "utf8"));
44780
44858
  return {
44781
44859
  schemaVersion: UPDATE_PREFERENCES_SCHEMA_VERSION,
44782
44860
  autoUpdateEnabled: typeof parsed.autoUpdateEnabled === "boolean" ? parsed.autoUpdateEnabled : true,
@@ -44855,7 +44933,7 @@ import {
44855
44933
  existsSync as existsSync18,
44856
44934
  mkdirSync as mkdirSync14,
44857
44935
  realpathSync as realpathSync5,
44858
- readFileSync as readFileSync19,
44936
+ readFileSync as readFileSync20,
44859
44937
  renameSync as renameSync3,
44860
44938
  rmSync as rmSync7,
44861
44939
  unlinkSync as unlinkSync3,
@@ -44873,7 +44951,7 @@ import {
44873
44951
 
44874
44952
  // src/cli/install-integrity.ts
44875
44953
  import { createRequire } from "module";
44876
- import { existsSync as existsSync17, readFileSync as readFileSync18, statSync as statSync5 } from "fs";
44954
+ import { existsSync as existsSync17, readFileSync as readFileSync19, statSync as statSync5 } from "fs";
44877
44955
  import { isAbsolute as isAbsolute6, join as join22, relative as relative7, resolve as resolve18 } from "path";
44878
44956
  var SDK_SIDECAR_CRITICAL_PACKAGE_FILES = [
44879
44957
  "dist/cli/index.mjs",
@@ -44909,7 +44987,7 @@ function resolveContainedPath(root, value) {
44909
44987
  return target;
44910
44988
  }
44911
44989
  function parseJson(path) {
44912
- return JSON.parse(readFileSync18(path, "utf8"));
44990
+ return JSON.parse(readFileSync19(path, "utf8"));
44913
44991
  }
44914
44992
  function isFile(path) {
44915
44993
  try {
@@ -45113,7 +45191,7 @@ function publicNpmFallbackRegistryUrl(hostUrl) {
45113
45191
  }
45114
45192
  function readOptionalText(path) {
45115
45193
  try {
45116
- return readFileSync19(path, "utf8").trim();
45194
+ return readFileSync20(path, "utf8").trim();
45117
45195
  } catch {
45118
45196
  return "";
45119
45197
  }
@@ -45316,7 +45394,7 @@ function readAutoUpdateFailure(plan) {
45316
45394
  if (!path) return null;
45317
45395
  try {
45318
45396
  const parsed = JSON.parse(
45319
- readFileSync19(path, "utf8")
45397
+ readFileSync20(path, "utf8")
45320
45398
  );
45321
45399
  if ((parsed.kind === "npm-global" || parsed.kind === "python-sidecar") && typeof parsed.packageSpec === "string" && typeof parsed.failedAt === "string" && typeof parsed.exitCode === "number" && typeof parsed.manualCommand === "string") {
45322
45400
  return parsed;
@@ -45402,7 +45480,7 @@ function installedPackageVersion(versionDir) {
45402
45480
  "package.json"
45403
45481
  );
45404
45482
  try {
45405
- const parsed = JSON.parse(readFileSync19(packageJsonPath, "utf8"));
45483
+ const parsed = JSON.parse(readFileSync20(packageJsonPath, "utf8"));
45406
45484
  return typeof parsed.version === "string" ? safeVersionSegment(parsed.version) : "";
45407
45485
  } catch {
45408
45486
  return "";
@@ -46442,7 +46520,7 @@ function collectEvent(value, previous = []) {
46442
46520
  function collectNotificationTarget(value, previous = []) {
46443
46521
  return [...previous, value];
46444
46522
  }
46445
- async function readNotificationConfigurationChange(source, read = (path, encoding) => readFileSync20(path, encoding)) {
46523
+ async function readNotificationConfigurationChange(source, read = (path, encoding) => readFileSync21(path, encoding)) {
46446
46524
  const label = source === "-" ? "stdin" : source;
46447
46525
  let text;
46448
46526
  try {
@@ -46785,7 +46863,7 @@ import {
46785
46863
  chmodSync,
46786
46864
  existsSync as existsSync19,
46787
46865
  mkdtempSync,
46788
- readFileSync as readFileSync21,
46866
+ readFileSync as readFileSync22,
46789
46867
  writeFileSync as writeFileSync20
46790
46868
  } from "fs";
46791
46869
  import { tmpdir as tmpdir6 } from "os";
@@ -48927,7 +49005,7 @@ function readJsonArgument(raw, flagName) {
48927
49005
  throw new Error(`Invalid ${flagName} value: empty @file path.`);
48928
49006
  }
48929
49007
  try {
48930
- return readFileSync21(resolveAtFilePath(filePath), "utf8").replace(
49008
+ return readFileSync22(resolveAtFilePath(filePath), "utf8").replace(
48931
49009
  /^\uFEFF/,
48932
49010
  ""
48933
49011
  );
package/dist/index.d.mts CHANGED
@@ -1734,6 +1734,16 @@ interface PlayStatus {
1734
1734
  progress?: PlayProgressStatus;
1735
1735
  /** Partial or final result. Available once the play returns. */
1736
1736
  result?: unknown;
1737
+ /**
1738
+ * Terminal row outcome truth. A completed run may still contain failed rows
1739
+ * when row-level failure isolation persisted those rows for retry.
1740
+ */
1741
+ rowOutcomes?: {
1742
+ completedRows: number;
1743
+ failedRows: number;
1744
+ totalRows: number;
1745
+ hasRowFailures: boolean;
1746
+ };
1737
1747
  /** Compact typed run package returned by current run status endpoints. */
1738
1748
  package?: PlayRunPackage;
1739
1749
  /** Compact typed output summaries, mirrored from the run package when present. */
package/dist/index.d.ts CHANGED
@@ -1734,6 +1734,16 @@ interface PlayStatus {
1734
1734
  progress?: PlayProgressStatus;
1735
1735
  /** Partial or final result. Available once the play returns. */
1736
1736
  result?: unknown;
1737
+ /**
1738
+ * Terminal row outcome truth. A completed run may still contain failed rows
1739
+ * when row-level failure isolation persisted those rows for retry.
1740
+ */
1741
+ rowOutcomes?: {
1742
+ completedRows: number;
1743
+ failedRows: number;
1744
+ totalRows: number;
1745
+ hasRowFailures: boolean;
1746
+ };
1737
1747
  /** Compact typed run package returned by current run status endpoints. */
1738
1748
  package?: PlayRunPackage;
1739
1749
  /** Compact typed output summaries, mirrored from the run package when present. */
package/dist/index.js CHANGED
@@ -864,7 +864,7 @@ var SDK_RELEASE = {
864
864
  // getters keep their established compatibility behavior.
865
865
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
866
866
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
867
- version: "0.3.131",
867
+ version: "0.3.133",
868
868
  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.",
869
869
  packageCapabilities: {
870
870
  updatePreferences: 1
package/dist/index.mjs CHANGED
@@ -768,7 +768,7 @@ var SDK_RELEASE = {
768
768
  // getters keep their established compatibility behavior.
769
769
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
770
770
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
771
- version: "0.3.131",
771
+ version: "0.3.133",
772
772
  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.",
773
773
  packageCapabilities: {
774
774
  updatePreferences: 1
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.131";
152
+ readonly version: "0.3.133";
153
153
  readonly 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.";
154
154
  readonly packageCapabilities: {
155
155
  readonly updatePreferences: 1;
package/dist/release.d.ts CHANGED
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.131";
152
+ readonly version: "0.3.133";
153
153
  readonly 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.";
154
154
  readonly packageCapabilities: {
155
155
  readonly updatePreferences: 1;
package/dist/release.js CHANGED
@@ -74,7 +74,7 @@ var SDK_RELEASE = {
74
74
  // getters keep their established compatibility behavior.
75
75
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
76
76
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
77
- version: "0.3.131",
77
+ version: "0.3.133",
78
78
  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.",
79
79
  packageCapabilities: {
80
80
  updatePreferences: 1
package/dist/release.mjs CHANGED
@@ -48,7 +48,7 @@ var SDK_RELEASE = {
48
48
  // getters keep their established compatibility behavior.
49
49
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
50
50
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
51
- version: "0.3.131",
51
+ version: "0.3.133",
52
52
  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.",
53
53
  packageCapabilities: {
54
54
  updatePreferences: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.3.131",
3
+ "version": "0.3.133",
4
4
  "description": "GTM data CLI and TypeScript SDK for coding agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://code.deepline.com",