@smithers-orchestrator/driver 0.24.2 → 0.25.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smithers-orchestrator/driver",
3
- "version": "0.24.2",
3
+ "version": "0.25.1",
4
4
  "description": "Workflow execution driver — runs tasks, acts on EngineDecisions, reports results",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -63,11 +63,11 @@
63
63
  "dependencies": {
64
64
  "effect": "^3.21.1",
65
65
  "zod": "^4.3.6",
66
- "@smithers-orchestrator/observability": "0.24.2",
67
- "@smithers-orchestrator/graph": "0.24.2",
68
- "@smithers-orchestrator/db": "0.24.2",
69
- "@smithers-orchestrator/errors": "0.24.2",
70
- "@smithers-orchestrator/scheduler": "0.24.2"
66
+ "@smithers-orchestrator/errors": "0.25.1",
67
+ "@smithers-orchestrator/db": "0.25.1",
68
+ "@smithers-orchestrator/graph": "0.25.1",
69
+ "@smithers-orchestrator/observability": "0.25.1",
70
+ "@smithers-orchestrator/scheduler": "0.25.1"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@types/bun": "latest",
@@ -0,0 +1,26 @@
1
+ import type { z } from "zod";
2
+
3
+ /**
4
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
5
+ * from the `table` argument it was given:
6
+ *
7
+ * - a string table name (a key of the workflow Schema) → the inferred row for
8
+ * that registered schema (`outputs.X` keyed by name);
9
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
10
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
11
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
12
+ *
13
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
14
+ * fields instead of an untyped `Record<string, unknown>`.
15
+ */
16
+ export type ResolveOutputRow<Schema, T> = T extends keyof Schema
17
+ ? Schema[T] extends z.ZodTypeAny
18
+ ? z.infer<Schema[T]>
19
+ : Schema[T] extends { $inferSelect: infer R }
20
+ ? R
21
+ : Record<string, unknown>
22
+ : T extends z.ZodTypeAny
23
+ ? z.infer<T>
24
+ : T extends { $inferSelect: infer R }
25
+ ? R
26
+ : Record<string, unknown>;
package/src/RunOptions.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { RunAuthContext } from "./RunAuthContext.ts";
2
+ import type { OutputSnapshot } from "./OutputSnapshot.ts";
2
3
  import type { SmithersEvent } from "@smithers-orchestrator/observability/SmithersEvent";
3
4
 
4
5
  export type HotReloadOptions = {
@@ -19,6 +20,7 @@ export type RunOptions = {
19
20
  parentRunId?: string | null;
20
21
  input: Record<string, unknown>;
21
22
  maxConcurrency?: number;
23
+ requireRerenderOnOutputChange?: boolean;
22
24
  onProgress?: (e: SmithersEvent) => void;
23
25
  signal?: AbortSignal;
24
26
  resume?: boolean;
@@ -34,6 +36,9 @@ export type RunOptions = {
34
36
  auth?: RunAuthContext | null;
35
37
  config?: Record<string, unknown>;
36
38
  cliAgentToolsDefault?: "all" | "explicit-only";
39
+ initialOutputs?: OutputSnapshot;
40
+ initialIteration?: number;
41
+ initialIterations?: Record<string, number> | ReadonlyMap<string, number>;
37
42
  resumeClaim?: {
38
43
  claimOwnerId: string;
39
44
  claimHeartbeatAtMs: number;
package/src/RunResult.ts CHANGED
@@ -6,4 +6,17 @@ export type RunResult = {
6
6
  readonly output?: unknown;
7
7
  readonly error?: unknown;
8
8
  readonly nextRunId?: string;
9
+ /**
10
+ * Number of tasks that ended `failed` yet did not fail the run — "masked"
11
+ * child failures (a `continueOnFail` task, or an agent task that failed
12
+ * transiently: rate limit, timeout, abort) the binary `finished` status cannot
13
+ * express. Present (and `> 0`) only on a `finished` result. See
14
+ * `docs/runtime/run-state.mdx`.
15
+ */
16
+ readonly failedChildren?: number;
17
+ /**
18
+ * Task state keys (`nodeId::iteration`) of the tasks counted by
19
+ * {@link failedChildren}.
20
+ */
21
+ readonly failedChildKeys?: readonly string[];
9
22
  };
package/src/RunStatus.ts CHANGED
@@ -3,6 +3,7 @@ export type RunStatus =
3
3
  | "waiting-approval"
4
4
  | "waiting-event"
5
5
  | "waiting-timer"
6
+ | "waiting-quota"
6
7
  | "finished"
7
8
  | "continued"
8
9
  | "failed"
@@ -12,6 +12,11 @@ import { resolveWorktreePath } from "@smithers-orchestrator/graph";
12
12
  /** @typedef {import("./SmithersRuntimeConfig.ts").SmithersRuntimeConfig} SmithersRuntimeConfig */
13
13
  /** @typedef {unknown} TableRef */
14
14
  /** @typedef {Record<string, unknown>} OutputRow User-visible output row — harness metadata fields (runId, nodeId, iteration) are stripped. */
15
+ /**
16
+ * @template Schema
17
+ * @template T
18
+ * @typedef {import("./ResolveOutputRow.ts").ResolveOutputRow<Schema, T>} ResolveOutputRow
19
+ */
15
20
  /**
16
21
  * @template Schema
17
22
  * @typedef {import("./OutputAccessor.ts").OutputAccessor<Schema>} OutputAccessor
@@ -119,36 +124,93 @@ export class SmithersCtx {
119
124
  });
120
125
  }
121
126
  /**
122
- * @param {TableRef} table
127
+ * @template {keyof Schema & string} K
128
+ * @overload
129
+ * @param {K} table
130
+ * @param {OutputKey} key
131
+ * @returns {ResolveOutputRow<Schema, K>}
132
+ */
133
+ /**
134
+ * @template {TableRef} T
135
+ * @overload
136
+ * @param {T} table
123
137
  * @param {OutputKey} key
124
- * @returns {OutputRow}
138
+ * @returns {ResolveOutputRow<Schema, T>}
139
+ */
140
+ /**
141
+ * @template {TableRef} T
142
+ * @param {T} table
143
+ * @param {OutputKey} key
144
+ * @returns {ResolveOutputRow<Schema, T>}
125
145
  */
126
146
  output(table, key) {
127
147
  const row = this.resolveRow(table, key);
128
148
  if (!row) {
129
149
  throw new SmithersError("MISSING_OUTPUT", `Missing output for nodeId=${key.nodeId} iteration=${key.iteration ?? 0}`, { nodeId: key.nodeId, iteration: key.iteration ?? 0 });
130
150
  }
131
- return /** @type {OutputRow} */ (stripAutoColumns(row));
151
+ return /** @type {ResolveOutputRow<Schema, T>} */ (/** @type {unknown} */ (stripAutoColumns(row)));
132
152
  }
133
153
  /**
134
- * @param {TableRef} table
154
+ * Resolve a single output row. Without an explicit `key.iteration` this
155
+ * resolves the CURRENT render iteration — which equals the loop iteration
156
+ * only for a single, non-nested loop, and is 0 when several loops coexist.
157
+ * For a `<Loop>` exit condition use {@link latest} (the most recent
158
+ * iteration), not `outputMaybe`, or an `until` built on it never advances.
159
+ *
160
+ * @template {keyof Schema & string} K
161
+ * @overload
162
+ * @param {K} table
135
163
  * @param {OutputKey} key
136
- * @returns {OutputRow | undefined}
164
+ * @returns {ResolveOutputRow<Schema, K> | undefined}
165
+ */
166
+ /**
167
+ * @template {TableRef} T
168
+ * @overload
169
+ * @param {T} table
170
+ * @param {OutputKey} key
171
+ * @returns {ResolveOutputRow<Schema, T> | undefined}
172
+ */
173
+ /**
174
+ * @template {TableRef} T
175
+ * @param {T} table
176
+ * @param {OutputKey} key
177
+ * @returns {ResolveOutputRow<Schema, T> | undefined}
137
178
  */
138
179
  outputMaybe(table, key) {
139
180
  const row = this.resolveRow(table, key);
140
- return row !== undefined ? /** @type {OutputRow} */ (stripAutoColumns(row)) : undefined;
181
+ return row !== undefined ? /** @type {ResolveOutputRow<Schema, T>} */ (/** @type {unknown} */ (stripAutoColumns(row))) : undefined;
141
182
  }
142
183
  /**
143
- * @param {TableRef} table
184
+ * Resolve the most recent iteration's output row for `nodeId` (highest
185
+ * iteration across all matching rows). This is the correct reader for a
186
+ * `<Loop>`/`<Ralph>` `until` exit condition; {@link outputMaybe} resolves
187
+ * the current render iteration and can read stale/iteration-0 data inside a
188
+ * loop.
189
+ *
190
+ * @template {keyof Schema & string} K
191
+ * @overload
192
+ * @param {K} table
144
193
  * @param {string} nodeId
145
- * @returns {OutputRow | undefined}
194
+ * @returns {ResolveOutputRow<Schema, K> | undefined}
195
+ */
196
+ /**
197
+ * @template {TableRef} T
198
+ * @overload
199
+ * @param {T} table
200
+ * @param {string} nodeId
201
+ * @returns {ResolveOutputRow<Schema, T> | undefined}
202
+ */
203
+ /**
204
+ * @template {TableRef} T
205
+ * @param {T} table
206
+ * @param {string} nodeId
207
+ * @returns {ResolveOutputRow<Schema, T> | undefined}
146
208
  */
147
209
  latest(table, nodeId) {
148
210
  const tableName = this.resolveTableName(table);
149
211
  const rows = this._outputs[tableName] ?? [];
150
212
  const matching = filterRowsByNodeId(rows, nodeId, this._currentScopes);
151
- /** @type {OutputRow | undefined} */
213
+ /** @type {ResolveOutputRow<Schema, T> | undefined} */
152
214
  let best = undefined;
153
215
  let bestIteration = -Infinity;
154
216
  for (const row of matching) {
@@ -156,7 +218,7 @@ export class SmithersCtx {
156
218
  ? Number(row.iteration)
157
219
  : 0;
158
220
  if (!best || iter >= bestIteration) {
159
- best = row;
221
+ best = /** @type {ResolveOutputRow<Schema, T>} */ (/** @type {unknown} */ (row));
160
222
  bestIteration = iter;
161
223
  }
162
224
  }
@@ -20,7 +20,6 @@ import { withAbort } from "./withAbort.js";
20
20
  /** @typedef {import("@smithers-orchestrator/graph/types").TaskDescriptor} TaskDescriptor */
21
21
 
22
22
  const SCHEDULER_SPECIFIER = "@smithers-orchestrator/scheduler";
23
- const LOCAL_SCHEDULER_SPECIFIER = "../../scheduler/src/index.js";
24
23
  function createRunId() {
25
24
  return `run_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
26
25
  }
@@ -155,19 +154,17 @@ function mergeOutputSnapshots(base, live) {
155
154
  * @returns {Promise<CreateWorkflowSession | null>}
156
155
  */
157
156
  async function loadCreateSession() {
158
- for (const specifier of [SCHEDULER_SPECIFIER, LOCAL_SCHEDULER_SPECIFIER]) {
159
- let mod;
160
- try {
161
- mod = (await import(specifier));
162
- }
163
- catch {
164
- continue;
165
- }
166
- if (typeof mod.createSession === "function")
167
- return mod.createSession;
168
- if (typeof mod.makeWorkflowSession === "function") {
169
- return mod.makeWorkflowSession;
170
- }
157
+ let mod;
158
+ try {
159
+ // The scheduler is a workspace dependency, so the package specifier always
160
+ // resolves (no relative-path fallback needed).
161
+ mod = (await import(SCHEDULER_SPECIFIER));
162
+ }
163
+ catch {
164
+ return null;
165
+ }
166
+ if (typeof mod.makeWorkflowSession === "function") {
167
+ return mod.makeWorkflowSession;
171
168
  }
172
169
  return null;
173
170
  }
@@ -276,6 +273,8 @@ export class WorkflowDriver {
276
273
  baseOutputs = {};
277
274
  /** @type {Map<string, Promise<{ key: string; task: TaskDescriptor; kind: "completed" | "failed" | "cancelled"; output?: unknown; error?: unknown }>>} */
278
275
  inflightTasks = new Map();
276
+ /** @type {Map<string, TaskDescriptor>} */
277
+ inflightTaskDescriptors = new Map();
279
278
  /** @type {Array<{ key: string; task: TaskDescriptor; kind: "completed" | "failed" | "cancelled"; output?: unknown; error?: unknown }>} */
280
279
  settledTasks = [];
281
280
  /**
@@ -428,6 +427,7 @@ export class WorkflowDriver {
428
427
  defaultIteration: iteration,
429
428
  baseRootDir,
430
429
  workflowPath,
430
+ trigger: context.trigger,
431
431
  });
432
432
  // Capture tasks that deferred on unresolved deps this render so the run
433
433
  // loop can fail loudly if any survive to a Finished decision instead of
@@ -490,10 +490,12 @@ export class WorkflowDriver {
490
490
  }
491
491
  })().then((settled) => {
492
492
  this.inflightTasks.delete(key);
493
+ this.inflightTaskDescriptors.delete(key);
493
494
  this.settledTasks.push(settled);
494
495
  return settled;
495
496
  });
496
497
  this.inflightTasks.set(key, promise);
498
+ this.inflightTaskDescriptors.set(key, task);
497
499
  }
498
500
  /**
499
501
  * Wait for the next settled task (or an optional deadline) and report it to
@@ -506,9 +508,12 @@ export class WorkflowDriver {
506
508
  if (!this.session) {
507
509
  throw new Error("WorkflowSession is not initialized.");
508
510
  }
509
- const waitStart = performance.now();
511
+ let waitedTasks = [];
512
+ let waitStart = 0;
510
513
  try {
511
514
  if (this.settledTasks.length === 0 && this.inflightTasks.size > 0) {
515
+ waitedTasks = [...this.inflightTaskDescriptors.values()];
516
+ waitStart = performance.now();
512
517
  const racers = [...this.inflightTasks.values()];
513
518
  if (deadlineMs != null) {
514
519
  racers.push(sleepWithAbort(deadlineMs, this.activeOptions?.signal).then(() => null));
@@ -517,10 +522,12 @@ export class WorkflowDriver {
517
522
  }
518
523
  }
519
524
  finally {
520
- await this.onSchedulerWait?.(performance.now() - waitStart, {
521
- runId: this.activeRunId,
522
- tasks: [],
523
- });
525
+ if (waitedTasks.length > 0) {
526
+ await this.onSchedulerWait?.(performance.now() - waitStart, {
527
+ runId: this.activeRunId,
528
+ tasks: waitedTasks,
529
+ });
530
+ }
524
531
  }
525
532
  if (this.activeOptions?.signal?.aborted) {
526
533
  return this.cancelRun();
@@ -603,6 +610,8 @@ export class WorkflowDriver {
603
610
  return { runId: this.activeRunId, status: "waiting-event" };
604
611
  case "Timer":
605
612
  return { runId: this.activeRunId, status: "waiting-timer" };
613
+ case "Quota":
614
+ return { runId: this.activeRunId, status: "waiting-quota" };
606
615
  case "RetryBackoff": {
607
616
  await sleepWithAbort(reason.waitMs, this.activeOptions?.signal);
608
617
  if (this.activeOptions?.signal?.aborted) {
package/src/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import * as _smithers_graph_types from '@smithers-orchestrator/graph/types';
1
+ import * as _smithers_orchestrator_graph_types from '@smithers-orchestrator/graph/types';
2
2
  import { WorkflowGraph as WorkflowGraph$1, TaskDescriptor as TaskDescriptor$1 } from '@smithers-orchestrator/graph/types';
3
3
  import { SmithersEvent } from '@smithers-orchestrator/observability/SmithersEvent';
4
- import * as _smithers_scheduler from '@smithers-orchestrator/scheduler';
4
+ import * as _smithers_orchestrator_scheduler from '@smithers-orchestrator/scheduler';
5
5
  import { WaitReason as WaitReason$1, EngineDecision as EngineDecision$1 } from '@smithers-orchestrator/scheduler';
6
6
  import { z } from 'zod';
7
7
  import { SmithersWorkflowOptions } from '@smithers-orchestrator/scheduler/SmithersWorkflowOptions';
8
8
  import { SchemaRegistryEntry } from '@smithers-orchestrator/db/SchemaRegistryEntry';
9
- import * as _smithers_graph from '@smithers-orchestrator/graph';
9
+ import * as _smithers_orchestrator_graph from '@smithers-orchestrator/graph';
10
10
  import { ExtractOptions, WorkflowGraph } from '@smithers-orchestrator/graph';
11
11
 
12
12
  type TaskCompletedEvent = {
@@ -40,6 +40,10 @@ type RunAuthContext$2 = {
40
40
  createdAt: string;
41
41
  };
42
42
 
43
+ type OutputSnapshot$2<TFallback = unknown> = {
44
+ [tableName: string]: Array<TFallback>;
45
+ };
46
+
43
47
  type HotReloadOptions$1 = {
44
48
  /** Root directory to watch for changes (default: auto-detect from workflow entry) */
45
49
  rootDir?: string;
@@ -57,6 +61,7 @@ type RunOptions$2 = {
57
61
  parentRunId?: string | null;
58
62
  input: Record<string, unknown>;
59
63
  maxConcurrency?: number;
64
+ requireRerenderOnOutputChange?: boolean;
60
65
  onProgress?: (e: SmithersEvent) => void;
61
66
  signal?: AbortSignal;
62
67
  resume?: boolean;
@@ -72,6 +77,9 @@ type RunOptions$2 = {
72
77
  auth?: RunAuthContext$2 | null;
73
78
  config?: Record<string, unknown>;
74
79
  cliAgentToolsDefault?: "all" | "explicit-only";
80
+ initialOutputs?: OutputSnapshot$2;
81
+ initialIteration?: number;
82
+ initialIterations?: Record<string, number> | ReadonlyMap<string, number>;
75
83
  resumeClaim?: {
76
84
  claimOwnerId: string;
77
85
  claimHeartbeatAtMs: number;
@@ -80,7 +88,7 @@ type RunOptions$2 = {
80
88
  };
81
89
  };
82
90
 
83
- type RunStatus$1 = "running" | "waiting-approval" | "waiting-event" | "waiting-timer" | "finished" | "continued" | "failed" | "cancelled";
91
+ type RunStatus$1 = "running" | "waiting-approval" | "waiting-event" | "waiting-timer" | "waiting-quota" | "finished" | "continued" | "failed" | "cancelled";
84
92
 
85
93
  type RunResult$2 = {
86
94
  readonly runId: string;
@@ -88,6 +96,19 @@ type RunResult$2 = {
88
96
  readonly output?: unknown;
89
97
  readonly error?: unknown;
90
98
  readonly nextRunId?: string;
99
+ /**
100
+ * Number of tasks that ended `failed` yet did not fail the run — "masked"
101
+ * child failures (a `continueOnFail` task, or an agent task that failed
102
+ * transiently: rate limit, timeout, abort) the binary `finished` status cannot
103
+ * express. Present (and `> 0`) only on a `finished` result. See
104
+ * `docs/runtime/run-state.mdx`.
105
+ */
106
+ readonly failedChildren?: number;
107
+ /**
108
+ * Task state keys (`nodeId::iteration`) of the tasks counted by
109
+ * {@link failedChildren}.
110
+ */
111
+ readonly failedChildKeys?: readonly string[];
91
112
  };
92
113
 
93
114
  type ContinueAsNewHandler$1 = (transition: unknown, context: {
@@ -136,10 +157,595 @@ type OutputAccessor$2<Schema, TRow = unknown> = {
136
157
  } & {
137
158
  [K in keyof Schema & string]: Array<InferOutputEntry$1<Schema[K]>>;
138
159
  };
139
- type OutputSchemaKey<Schema> = Exclude<keyof Schema & string, "input">;
140
- type OutputSchemaValue<Schema> = Schema[OutputSchemaKey<Schema>];
141
- type StrictTableRef<Schema> = [OutputSchemaKey<Schema>] extends [never] ? TableRef : OutputSchemaKey<Schema> | OutputSchemaValue<Schema>;
142
- type OutputForTable<Schema, Table> = Table extends OutputSchemaKey<Schema> ? InferOutputEntry$1<Schema[Table]> : Table extends OutputSchemaValue<Schema> ? InferOutputEntry$1<Table> : OutputRow;
160
+
161
+ /**
162
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
163
+ * from the `table` argument it was given:
164
+ *
165
+ * - a string table name (a key of the workflow Schema) → the inferred row for
166
+ * that registered schema (`outputs.X` keyed by name);
167
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
168
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
169
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
170
+ *
171
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
172
+ * fields instead of an untyped `Record<string, unknown>`.
173
+ */
174
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
175
+ $inferSelect: infer R;
176
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
177
+ $inferSelect: infer R;
178
+ } ? R : Record<string, unknown>;
179
+
180
+ /**
181
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
182
+ * from the `table` argument it was given:
183
+ *
184
+ * - a string table name (a key of the workflow Schema) → the inferred row for
185
+ * that registered schema (`outputs.X` keyed by name);
186
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
187
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
188
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
189
+ *
190
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
191
+ * fields instead of an untyped `Record<string, unknown>`.
192
+ */
193
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
194
+ $inferSelect: infer R;
195
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
196
+ $inferSelect: infer R;
197
+ } ? R : Record<string, unknown>;
198
+
199
+ /**
200
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
201
+ * from the `table` argument it was given:
202
+ *
203
+ * - a string table name (a key of the workflow Schema) → the inferred row for
204
+ * that registered schema (`outputs.X` keyed by name);
205
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
206
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
207
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
208
+ *
209
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
210
+ * fields instead of an untyped `Record<string, unknown>`.
211
+ */
212
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
213
+ $inferSelect: infer R;
214
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
215
+ $inferSelect: infer R;
216
+ } ? R : Record<string, unknown>;
217
+
218
+ /**
219
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
220
+ * from the `table` argument it was given:
221
+ *
222
+ * - a string table name (a key of the workflow Schema) → the inferred row for
223
+ * that registered schema (`outputs.X` keyed by name);
224
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
225
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
226
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
227
+ *
228
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
229
+ * fields instead of an untyped `Record<string, unknown>`.
230
+ */
231
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
232
+ $inferSelect: infer R;
233
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
234
+ $inferSelect: infer R;
235
+ } ? R : Record<string, unknown>;
236
+
237
+ /**
238
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
239
+ * from the `table` argument it was given:
240
+ *
241
+ * - a string table name (a key of the workflow Schema) → the inferred row for
242
+ * that registered schema (`outputs.X` keyed by name);
243
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
244
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
245
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
246
+ *
247
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
248
+ * fields instead of an untyped `Record<string, unknown>`.
249
+ */
250
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
251
+ $inferSelect: infer R;
252
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
253
+ $inferSelect: infer R;
254
+ } ? R : Record<string, unknown>;
255
+
256
+ /**
257
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
258
+ * from the `table` argument it was given:
259
+ *
260
+ * - a string table name (a key of the workflow Schema) → the inferred row for
261
+ * that registered schema (`outputs.X` keyed by name);
262
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
263
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
264
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
265
+ *
266
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
267
+ * fields instead of an untyped `Record<string, unknown>`.
268
+ */
269
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
270
+ $inferSelect: infer R;
271
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
272
+ $inferSelect: infer R;
273
+ } ? R : Record<string, unknown>;
274
+
275
+ /**
276
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
277
+ * from the `table` argument it was given:
278
+ *
279
+ * - a string table name (a key of the workflow Schema) → the inferred row for
280
+ * that registered schema (`outputs.X` keyed by name);
281
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
282
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
283
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
284
+ *
285
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
286
+ * fields instead of an untyped `Record<string, unknown>`.
287
+ */
288
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
289
+ $inferSelect: infer R;
290
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
291
+ $inferSelect: infer R;
292
+ } ? R : Record<string, unknown>;
293
+
294
+ /**
295
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
296
+ * from the `table` argument it was given:
297
+ *
298
+ * - a string table name (a key of the workflow Schema) → the inferred row for
299
+ * that registered schema (`outputs.X` keyed by name);
300
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
301
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
302
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
303
+ *
304
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
305
+ * fields instead of an untyped `Record<string, unknown>`.
306
+ */
307
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
308
+ $inferSelect: infer R;
309
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
310
+ $inferSelect: infer R;
311
+ } ? R : Record<string, unknown>;
312
+
313
+ /**
314
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
315
+ * from the `table` argument it was given:
316
+ *
317
+ * - a string table name (a key of the workflow Schema) → the inferred row for
318
+ * that registered schema (`outputs.X` keyed by name);
319
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
320
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
321
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
322
+ *
323
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
324
+ * fields instead of an untyped `Record<string, unknown>`.
325
+ */
326
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
327
+ $inferSelect: infer R;
328
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
329
+ $inferSelect: infer R;
330
+ } ? R : Record<string, unknown>;
331
+
332
+ /**
333
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
334
+ * from the `table` argument it was given:
335
+ *
336
+ * - a string table name (a key of the workflow Schema) → the inferred row for
337
+ * that registered schema (`outputs.X` keyed by name);
338
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
339
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
340
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
341
+ *
342
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
343
+ * fields instead of an untyped `Record<string, unknown>`.
344
+ */
345
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
346
+ $inferSelect: infer R;
347
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
348
+ $inferSelect: infer R;
349
+ } ? R : Record<string, unknown>;
350
+
351
+ /**
352
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
353
+ * from the `table` argument it was given:
354
+ *
355
+ * - a string table name (a key of the workflow Schema) → the inferred row for
356
+ * that registered schema (`outputs.X` keyed by name);
357
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
358
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
359
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
360
+ *
361
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
362
+ * fields instead of an untyped `Record<string, unknown>`.
363
+ */
364
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
365
+ $inferSelect: infer R;
366
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
367
+ $inferSelect: infer R;
368
+ } ? R : Record<string, unknown>;
369
+
370
+ /**
371
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
372
+ * from the `table` argument it was given:
373
+ *
374
+ * - a string table name (a key of the workflow Schema) → the inferred row for
375
+ * that registered schema (`outputs.X` keyed by name);
376
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
377
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
378
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
379
+ *
380
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
381
+ * fields instead of an untyped `Record<string, unknown>`.
382
+ */
383
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
384
+ $inferSelect: infer R;
385
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
386
+ $inferSelect: infer R;
387
+ } ? R : Record<string, unknown>;
388
+
389
+ /**
390
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
391
+ * from the `table` argument it was given:
392
+ *
393
+ * - a string table name (a key of the workflow Schema) → the inferred row for
394
+ * that registered schema (`outputs.X` keyed by name);
395
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
396
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
397
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
398
+ *
399
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
400
+ * fields instead of an untyped `Record<string, unknown>`.
401
+ */
402
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
403
+ $inferSelect: infer R;
404
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
405
+ $inferSelect: infer R;
406
+ } ? R : Record<string, unknown>;
407
+
408
+ /**
409
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
410
+ * from the `table` argument it was given:
411
+ *
412
+ * - a string table name (a key of the workflow Schema) → the inferred row for
413
+ * that registered schema (`outputs.X` keyed by name);
414
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
415
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
416
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
417
+ *
418
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
419
+ * fields instead of an untyped `Record<string, unknown>`.
420
+ */
421
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
422
+ $inferSelect: infer R;
423
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
424
+ $inferSelect: infer R;
425
+ } ? R : Record<string, unknown>;
426
+
427
+ /**
428
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
429
+ * from the `table` argument it was given:
430
+ *
431
+ * - a string table name (a key of the workflow Schema) → the inferred row for
432
+ * that registered schema (`outputs.X` keyed by name);
433
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
434
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
435
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
436
+ *
437
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
438
+ * fields instead of an untyped `Record<string, unknown>`.
439
+ */
440
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
441
+ $inferSelect: infer R;
442
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
443
+ $inferSelect: infer R;
444
+ } ? R : Record<string, unknown>;
445
+
446
+ /**
447
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
448
+ * from the `table` argument it was given:
449
+ *
450
+ * - a string table name (a key of the workflow Schema) → the inferred row for
451
+ * that registered schema (`outputs.X` keyed by name);
452
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
453
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
454
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
455
+ *
456
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
457
+ * fields instead of an untyped `Record<string, unknown>`.
458
+ */
459
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
460
+ $inferSelect: infer R;
461
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
462
+ $inferSelect: infer R;
463
+ } ? R : Record<string, unknown>;
464
+
465
+ /**
466
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
467
+ * from the `table` argument it was given:
468
+ *
469
+ * - a string table name (a key of the workflow Schema) → the inferred row for
470
+ * that registered schema (`outputs.X` keyed by name);
471
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
472
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
473
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
474
+ *
475
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
476
+ * fields instead of an untyped `Record<string, unknown>`.
477
+ */
478
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
479
+ $inferSelect: infer R;
480
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
481
+ $inferSelect: infer R;
482
+ } ? R : Record<string, unknown>;
483
+
484
+ /**
485
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
486
+ * from the `table` argument it was given:
487
+ *
488
+ * - a string table name (a key of the workflow Schema) → the inferred row for
489
+ * that registered schema (`outputs.X` keyed by name);
490
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
491
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
492
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
493
+ *
494
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
495
+ * fields instead of an untyped `Record<string, unknown>`.
496
+ */
497
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
498
+ $inferSelect: infer R;
499
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
500
+ $inferSelect: infer R;
501
+ } ? R : Record<string, unknown>;
502
+
503
+ /**
504
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
505
+ * from the `table` argument it was given:
506
+ *
507
+ * - a string table name (a key of the workflow Schema) → the inferred row for
508
+ * that registered schema (`outputs.X` keyed by name);
509
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
510
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
511
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
512
+ *
513
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
514
+ * fields instead of an untyped `Record<string, unknown>`.
515
+ */
516
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
517
+ $inferSelect: infer R;
518
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
519
+ $inferSelect: infer R;
520
+ } ? R : Record<string, unknown>;
521
+
522
+ /**
523
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
524
+ * from the `table` argument it was given:
525
+ *
526
+ * - a string table name (a key of the workflow Schema) → the inferred row for
527
+ * that registered schema (`outputs.X` keyed by name);
528
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
529
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
530
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
531
+ *
532
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
533
+ * fields instead of an untyped `Record<string, unknown>`.
534
+ */
535
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
536
+ $inferSelect: infer R;
537
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
538
+ $inferSelect: infer R;
539
+ } ? R : Record<string, unknown>;
540
+
541
+ /**
542
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
543
+ * from the `table` argument it was given:
544
+ *
545
+ * - a string table name (a key of the workflow Schema) → the inferred row for
546
+ * that registered schema (`outputs.X` keyed by name);
547
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
548
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
549
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
550
+ *
551
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
552
+ * fields instead of an untyped `Record<string, unknown>`.
553
+ */
554
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
555
+ $inferSelect: infer R;
556
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
557
+ $inferSelect: infer R;
558
+ } ? R : Record<string, unknown>;
559
+
560
+ /**
561
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
562
+ * from the `table` argument it was given:
563
+ *
564
+ * - a string table name (a key of the workflow Schema) → the inferred row for
565
+ * that registered schema (`outputs.X` keyed by name);
566
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
567
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
568
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
569
+ *
570
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
571
+ * fields instead of an untyped `Record<string, unknown>`.
572
+ */
573
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
574
+ $inferSelect: infer R;
575
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
576
+ $inferSelect: infer R;
577
+ } ? R : Record<string, unknown>;
578
+
579
+ /**
580
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
581
+ * from the `table` argument it was given:
582
+ *
583
+ * - a string table name (a key of the workflow Schema) → the inferred row for
584
+ * that registered schema (`outputs.X` keyed by name);
585
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
586
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
587
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
588
+ *
589
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
590
+ * fields instead of an untyped `Record<string, unknown>`.
591
+ */
592
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
593
+ $inferSelect: infer R;
594
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
595
+ $inferSelect: infer R;
596
+ } ? R : Record<string, unknown>;
597
+
598
+ /**
599
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
600
+ * from the `table` argument it was given:
601
+ *
602
+ * - a string table name (a key of the workflow Schema) → the inferred row for
603
+ * that registered schema (`outputs.X` keyed by name);
604
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
605
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
606
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
607
+ *
608
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
609
+ * fields instead of an untyped `Record<string, unknown>`.
610
+ */
611
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
612
+ $inferSelect: infer R;
613
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
614
+ $inferSelect: infer R;
615
+ } ? R : Record<string, unknown>;
616
+
617
+ /**
618
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
619
+ * from the `table` argument it was given:
620
+ *
621
+ * - a string table name (a key of the workflow Schema) → the inferred row for
622
+ * that registered schema (`outputs.X` keyed by name);
623
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
624
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
625
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
626
+ *
627
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
628
+ * fields instead of an untyped `Record<string, unknown>`.
629
+ */
630
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
631
+ $inferSelect: infer R;
632
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
633
+ $inferSelect: infer R;
634
+ } ? R : Record<string, unknown>;
635
+
636
+ /**
637
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
638
+ * from the `table` argument it was given:
639
+ *
640
+ * - a string table name (a key of the workflow Schema) → the inferred row for
641
+ * that registered schema (`outputs.X` keyed by name);
642
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
643
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
644
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
645
+ *
646
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
647
+ * fields instead of an untyped `Record<string, unknown>`.
648
+ */
649
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
650
+ $inferSelect: infer R;
651
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
652
+ $inferSelect: infer R;
653
+ } ? R : Record<string, unknown>;
654
+
655
+ /**
656
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
657
+ * from the `table` argument it was given:
658
+ *
659
+ * - a string table name (a key of the workflow Schema) → the inferred row for
660
+ * that registered schema (`outputs.X` keyed by name);
661
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
662
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
663
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
664
+ *
665
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
666
+ * fields instead of an untyped `Record<string, unknown>`.
667
+ */
668
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
669
+ $inferSelect: infer R;
670
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
671
+ $inferSelect: infer R;
672
+ } ? R : Record<string, unknown>;
673
+
674
+ /**
675
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
676
+ * from the `table` argument it was given:
677
+ *
678
+ * - a string table name (a key of the workflow Schema) → the inferred row for
679
+ * that registered schema (`outputs.X` keyed by name);
680
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
681
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
682
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
683
+ *
684
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
685
+ * fields instead of an untyped `Record<string, unknown>`.
686
+ */
687
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
688
+ $inferSelect: infer R;
689
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
690
+ $inferSelect: infer R;
691
+ } ? R : Record<string, unknown>;
692
+
693
+ /**
694
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
695
+ * from the `table` argument it was given:
696
+ *
697
+ * - a string table name (a key of the workflow Schema) → the inferred row for
698
+ * that registered schema (`outputs.X` keyed by name);
699
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
700
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
701
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
702
+ *
703
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
704
+ * fields instead of an untyped `Record<string, unknown>`.
705
+ */
706
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
707
+ $inferSelect: infer R;
708
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
709
+ $inferSelect: infer R;
710
+ } ? R : Record<string, unknown>;
711
+
712
+ /**
713
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
714
+ * from the `table` argument it was given:
715
+ *
716
+ * - a string table name (a key of the workflow Schema) → the inferred row for
717
+ * that registered schema (`outputs.X` keyed by name);
718
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
719
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
720
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
721
+ *
722
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
723
+ * fields instead of an untyped `Record<string, unknown>`.
724
+ */
725
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
726
+ $inferSelect: infer R;
727
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
728
+ $inferSelect: infer R;
729
+ } ? R : Record<string, unknown>;
730
+
731
+ /**
732
+ * Resolve the row type a `ctx.output`/`ctx.outputMaybe`/`ctx.latest` call returns
733
+ * from the `table` argument it was given:
734
+ *
735
+ * - a string table name (a key of the workflow Schema) → the inferred row for
736
+ * that registered schema (`outputs.X` keyed by name);
737
+ * - a Zod schema object (e.g. `outputs.research`) → `z.infer` of that schema;
738
+ * - a Drizzle table (carries `$inferSelect`) → its select row;
739
+ * - anything else (a widened `string`, `unknown`) → an untyped output row.
740
+ *
741
+ * This is what makes `ctx.outputMaybe(outputs.research, ...)` carry the research
742
+ * fields instead of an untyped `Record<string, unknown>`.
743
+ */
744
+ type ResolveOutputRow$1<Schema, T> = T extends keyof Schema ? Schema[T] extends z.ZodTypeAny ? z.infer<Schema[T]> : Schema[T] extends {
745
+ $inferSelect: infer R;
746
+ } ? R : Record<string, unknown> : T extends z.ZodTypeAny ? z.infer<T> : T extends {
747
+ $inferSelect: infer R;
748
+ } ? R : Record<string, unknown>;
143
749
 
144
750
  type SmithersRuntimeConfig$1 = {
145
751
  cliAgentToolsDefault?: "all" | "explicit-only";
@@ -148,10 +754,6 @@ type SmithersRuntimeConfig$1 = {
148
754
  worktreePaths?: Record<string, string>;
149
755
  };
150
756
 
151
- type OutputSnapshot$2<TFallback = unknown> = {
152
- [tableName: string]: Array<TFallback>;
153
- };
154
-
155
757
  type SmithersCtxOptions$2 = {
156
758
  runId: string;
157
759
  iteration: number;
@@ -210,6 +812,19 @@ declare class SmithersCtx<Schema extends unknown = unknown> {
210
812
  _zodToKeyName: Map<unknown, string> | undefined;
211
813
  /** @type {Set<string>} */
212
814
  _currentScopes: Set<string>;
815
+ /**
816
+ * Tasks that declared `deps` but could not resolve them this render, so
817
+ * they deferred (returned null) instead of mounting. The engine reads this
818
+ * after each render: a deferral is normal while an upstream is still
819
+ * producing, but one that survives to quiescence means the dependency can
820
+ * never resolve (e.g. a deps/needs key that maps to a node id no task
821
+ * produces) and the run would otherwise finish silently without it.
822
+ * @type {{ nodeId: string; waitingOn: string[] }[]}
823
+ */
824
+ _deferredDeps: {
825
+ nodeId: string;
826
+ waitingOn: string[];
827
+ }[];
213
828
  /**
214
829
  * Return the resolved absolute path for a rendered worktree or task id.
215
830
  * The lookup is populated from task descriptors, so task node ids and
@@ -228,23 +843,65 @@ declare class SmithersCtx<Schema extends unknown = unknown> {
228
843
  */
229
844
  resolveWorktreePath(path: string): string;
230
845
  /**
231
- * @param {TableRef} table
846
+ * @template {keyof Schema & string} K
847
+ * @overload
848
+ * @param {K} table
232
849
  * @param {OutputKey} key
233
- * @returns {OutputRow}
850
+ * @returns {ResolveOutputRow<Schema, K>}
234
851
  */
235
- output<Table extends StrictTableRef<Schema>>(table: Table, key: OutputKey$1): OutputForTable<Schema, Table>;
852
+ output<K extends keyof Schema & string>(table: K, key: OutputKey$1): ResolveOutputRow<Schema, K>;
236
853
  /**
237
- * @param {TableRef} table
854
+ * @template {TableRef} T
855
+ * @overload
856
+ * @param {T} table
238
857
  * @param {OutputKey} key
239
- * @returns {OutputRow | undefined}
858
+ * @returns {ResolveOutputRow<Schema, T>}
240
859
  */
241
- outputMaybe<Table extends StrictTableRef<Schema>>(table: Table, key: OutputKey$1): OutputForTable<Schema, Table> | undefined;
860
+ output<T extends TableRef>(table: T, key: OutputKey$1): ResolveOutputRow<Schema, T>;
242
861
  /**
243
- * @param {TableRef} table
862
+ * Resolve a single output row. Without an explicit `key.iteration` this
863
+ * resolves the CURRENT render iteration — which equals the loop iteration
864
+ * only for a single, non-nested loop, and is 0 when several loops coexist.
865
+ * For a `<Loop>` exit condition use {@link latest} (the most recent
866
+ * iteration), not `outputMaybe`, or an `until` built on it never advances.
867
+ *
868
+ * @template {keyof Schema & string} K
869
+ * @overload
870
+ * @param {K} table
871
+ * @param {OutputKey} key
872
+ * @returns {ResolveOutputRow<Schema, K> | undefined}
873
+ */
874
+ outputMaybe<K extends keyof Schema & string>(table: K, key: OutputKey$1): ResolveOutputRow<Schema, K> | undefined;
875
+ /**
876
+ * @template {TableRef} T
877
+ * @overload
878
+ * @param {T} table
879
+ * @param {OutputKey} key
880
+ * @returns {ResolveOutputRow<Schema, T> | undefined}
881
+ */
882
+ outputMaybe<T extends TableRef>(table: T, key: OutputKey$1): ResolveOutputRow<Schema, T> | undefined;
883
+ /**
884
+ * Resolve the most recent iteration's output row for `nodeId` (highest
885
+ * iteration across all matching rows). This is the correct reader for a
886
+ * `<Loop>`/`<Ralph>` `until` exit condition; {@link outputMaybe} resolves
887
+ * the current render iteration and can read stale/iteration-0 data inside a
888
+ * loop.
889
+ *
890
+ * @template {keyof Schema & string} K
891
+ * @overload
892
+ * @param {K} table
244
893
  * @param {string} nodeId
245
- * @returns {OutputRow | undefined}
894
+ * @returns {ResolveOutputRow<Schema, K> | undefined}
246
895
  */
247
- latest<Table extends StrictTableRef<Schema>>(table: Table, nodeId: string): OutputForTable<Schema, Table> | undefined;
896
+ latest<K extends keyof Schema & string>(table: K, nodeId: string): ResolveOutputRow<Schema, K> | undefined;
897
+ /**
898
+ * @template {TableRef} T
899
+ * @overload
900
+ * @param {T} table
901
+ * @param {string} nodeId
902
+ * @returns {ResolveOutputRow<Schema, T> | undefined}
903
+ */
904
+ latest<T extends TableRef>(table: T, nodeId: string): ResolveOutputRow<Schema, T> | undefined;
248
905
  /**
249
906
  * @param {unknown} value
250
907
  * @param {SafeParser} schema
@@ -262,6 +919,17 @@ declare class SmithersCtx<Schema extends unknown = unknown> {
262
919
  * @returns {string}
263
920
  */
264
921
  resolveTableName(table: TableRef): string;
922
+ /**
923
+ * Record that a task with `deps` deferred this render because its
924
+ * dependencies were not resolvable. Called by the Task component before it
925
+ * returns null. The engine inspects these at quiescence to turn a permanent
926
+ * deferral (a never-satisfiable dependency) into a loud error instead of a
927
+ * silent skip.
928
+ * @param {string} nodeId
929
+ * @param {string[]} waitingOn
930
+ * @returns {void}
931
+ */
932
+ recordDeferredDep(nodeId: string, waitingOn: string[]): void;
265
933
  /**
266
934
  * @param {TableRef} table
267
935
  * @param {OutputKey} key
@@ -275,8 +943,11 @@ type SmithersCtxOptions$1 = SmithersCtxOptions$2;
275
943
  type RunAuthContext$1 = RunAuthContext$2;
276
944
  type SmithersRuntimeConfig = SmithersRuntimeConfig$1;
277
945
  type TableRef = unknown;
278
- /** User-visible output row — harness metadata fields (runId, nodeId, iteration) are stripped. */
946
+ /**
947
+ * User-visible output row — harness metadata fields (runId, nodeId, iteration) are stripped.
948
+ */
279
949
  type OutputRow = Record<string, unknown>;
950
+ type ResolveOutputRow<Schema, T> = ResolveOutputRow$1<Schema, T>;
280
951
  type OutputAccessor$1<Schema> = OutputAccessor$2<Schema>;
281
952
 
282
953
  type WorkflowElement = {
@@ -355,11 +1026,36 @@ declare class WorkflowDriver<Schema extends unknown = unknown> {
355
1026
  /** @type {RunOptions | undefined} */
356
1027
  activeOptions: RunOptions$1 | undefined;
357
1028
  /** @type {import("@smithers-orchestrator/graph").WorkflowGraph | undefined} */
358
- lastGraph: _smithers_graph.WorkflowGraph | undefined;
1029
+ lastGraph: _smithers_orchestrator_graph.WorkflowGraph | undefined;
1030
+ /** @type {{ nodeId: string; waitingOn: string[] }[]} Tasks that deferred on unresolved deps in the latest render. */
1031
+ lastDeferredDeps: {
1032
+ nodeId: string;
1033
+ waitingOn: string[];
1034
+ }[];
1035
+ /** @type {Record<string, string>} */
1036
+ worktreePathsById: Record<string, string>;
359
1037
  /** @type {Map<string, string>} */
360
1038
  outputTablesByNodeId: Map<string, string>;
361
1039
  /** @type {OutputSnapshot} */
362
1040
  baseOutputs: OutputSnapshot$1;
1041
+ /** @type {Map<string, Promise<{ key: string; task: TaskDescriptor; kind: "completed" | "failed" | "cancelled"; output?: unknown; error?: unknown }>>} */
1042
+ inflightTasks: Map<string, Promise<{
1043
+ key: string;
1044
+ task: TaskDescriptor;
1045
+ kind: "completed" | "failed" | "cancelled";
1046
+ output?: unknown;
1047
+ error?: unknown;
1048
+ }>>;
1049
+ /** @type {Map<string, TaskDescriptor>} */
1050
+ inflightTaskDescriptors: Map<string, TaskDescriptor>;
1051
+ /** @type {Array<{ key: string; task: TaskDescriptor; kind: "completed" | "failed" | "cancelled"; output?: unknown; error?: unknown }>} */
1052
+ settledTasks: Array<{
1053
+ key: string;
1054
+ task: TaskDescriptor;
1055
+ kind: "completed" | "failed" | "cancelled";
1056
+ output?: unknown;
1057
+ error?: unknown;
1058
+ }>;
363
1059
  /**
364
1060
  * @param {RunOptions} options
365
1061
  * @returns {Promise<RunResult>}
@@ -382,6 +1078,38 @@ declare class WorkflowDriver<Schema extends unknown = unknown> {
382
1078
  */
383
1079
  executeTasks(tasks: readonly TaskDescriptor[]): Promise<EngineDecision | RunResult$1>;
384
1080
  /**
1081
+ * Start a task without blocking the driver loop on its completion. Settled
1082
+ * tasks queue in `settledTasks` and are reported to the session one at a
1083
+ * time from `nextCompletionDecision`, so each decision is computed against
1084
+ * fresh session state and a slow task never blocks scheduling work that
1085
+ * became ready elsewhere in the graph (#267).
1086
+ * @param {TaskDescriptor} task
1087
+ * @param {{ runId: string; options: RunOptions; signal?: AbortSignal }} context
1088
+ */
1089
+ startInflightTask(task: TaskDescriptor, context: {
1090
+ runId: string;
1091
+ options: RunOptions$1;
1092
+ signal?: AbortSignal;
1093
+ }): void;
1094
+ /**
1095
+ * Wait for the next settled task (or an optional deadline) and report it to
1096
+ * the session for a fresh decision. Completions that landed while a previous
1097
+ * one was being processed drain from `settledTasks` first.
1098
+ * @param {number | null} [deadlineMs]
1099
+ * @returns {Promise<EngineDecision | RunResult>}
1100
+ */
1101
+ nextCompletionDecision(deadlineMs?: number | null): Promise<EngineDecision | RunResult$1>;
1102
+ /**
1103
+ * Await every in-flight task without reporting further decisions. Used
1104
+ * before run-level exits (failure, continue-as-new) so task executors are
1105
+ * not abandoned mid-write. This matches the pre-#267 barrier semantics:
1106
+ * failure reporting waits for in-flight siblings (bounded by their
1107
+ * timeouts), trading latency for the invariant that no executor writes
1108
+ * after the run is terminal. Fail-fast would need a per-run abort threaded
1109
+ * through executors.
1110
+ */
1111
+ drainInflight(): Promise<void>;
1112
+ /**
385
1113
  * @param {WaitReason} reason
386
1114
  * @returns {Promise<EngineDecision | RunResult>}
387
1115
  */
@@ -412,11 +1140,11 @@ type SchedulerWaitHandler = SchedulerWaitHandler$1;
412
1140
  type WaitHandler = WaitHandler$1;
413
1141
  type ContinueAsNewHandler = ContinueAsNewHandler$1;
414
1142
  type RunOptions$1 = RunOptions$2;
415
- type RunResult$1 = _smithers_scheduler.RunResult;
416
- type EngineDecision = _smithers_scheduler.EngineDecision;
417
- type RenderContext = _smithers_scheduler.RenderContext;
418
- type WaitReason = _smithers_scheduler.WaitReason;
419
- type TaskDescriptor = _smithers_graph_types.TaskDescriptor;
1143
+ type RunResult$1 = _smithers_orchestrator_scheduler.RunResult;
1144
+ type EngineDecision = _smithers_orchestrator_scheduler.EngineDecision;
1145
+ type RenderContext = _smithers_orchestrator_scheduler.RenderContext;
1146
+ type WaitReason = _smithers_orchestrator_scheduler.WaitReason;
1147
+ type TaskDescriptor = _smithers_orchestrator_graph_types.TaskDescriptor;
420
1148
 
421
1149
  type HotReloadOptions = HotReloadOptions$1;
422
1150
  type OutputAccessor<Schema = any> = OutputAccessor$2<Schema>;