lua-cli 3.31.0 → 3.32.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/api-exports.d.ts +416 -103
  2. package/dist/api-exports.js +1992 -299
  3. package/dist/api-exports.js.map +1 -1
  4. package/dist/index.js +5262 -1914
  5. package/dist/index.js.map +1 -1
  6. package/dist/voice/test/index.d.ts +54 -54
  7. package/dist/workflow-builder.d.ts +257 -44
  8. package/dist/workflow-builder.js +1382 -265
  9. package/dist/workflow-builder.js.map +1 -1
  10. package/docs/README.md +2 -2
  11. package/docs/api/LuaWorkflow.md +44 -28
  12. package/docs/api/Workflows.md +12 -1
  13. package/docs/workflows/approvals.md +14 -1
  14. package/docs/workflows/connections-in-coding-turns.md +1 -0
  15. package/docs/workflows/correlation-keys.md +1 -0
  16. package/docs/workflows/git-credentials.md +22 -1
  17. package/docs/workflows/goals.md +46 -0
  18. package/docs/workflows/limits.md +6 -0
  19. package/docs/workflows/recovery.md +6 -2
  20. package/docs/workflows/replay-local.md +10 -10
  21. package/docs/workflows/schedules.md +15 -0
  22. package/docs/workflows/script-form.md +20 -10
  23. package/docs/workflows/testing-offline.md +25 -20
  24. package/docs/workflows/workspaces-and-long-steps.md +38 -2
  25. package/package.json +2 -2
  26. package/template/examples/workflows/CLAUDE.md +16 -13
  27. package/template/examples/workflows/pr-review-round.ts +61 -20
  28. package/template/examples/workflows/provision-tenant.ts +25 -8
  29. package/template/examples/workflows/refund-approval.ts +30 -17
  30. package/template/examples/workflows/support-triage.ts +59 -22
  31. package/template/examples/workflows/ticket-to-pr.ts +125 -46
  32. package/template/examples/workflows/vendor-invoices.ts +69 -16
  33. package/template/package.json +1 -1
@@ -12,7 +12,9 @@ import { PathOrLiteral } from '@lua/workflow-graph';
12
12
  import { SerializedWorkflowGraph } from '@lua/workflow-graph';
13
13
  import { TemplateBinding } from '@lua/workflow-graph';
14
14
  import { TypedRef } from '@lua/workflow-graph';
15
+ import type { WorkflowExecFn } from '@lua/shared-types/workflow-exec';
15
16
  import { WorkflowGraphEntry } from '@lua/workflow-graph';
17
+ import type { WorkflowShellFn } from '@lua/shared-types/workflow-exec';
16
18
  import type { z } from 'zod';
17
19
  import { ZodType } from 'zod';
18
20
 
@@ -26,16 +28,26 @@ export declare interface AgentStepOptions {
26
28
  };
27
29
  timeoutSeconds?: number;
28
30
  retry?: RetryPolicy;
29
- onError?: 'fail' | 'continue' | 'park';
31
+ onError?: WorkflowOnError;
30
32
  requiredConnections?: string[];
31
33
  /** static-only persona override (§11 S3) */
32
34
  systemPrompt?: string;
33
- tier?: 'job';
35
+ tier?: WorkflowTier;
34
36
  workspace?: WorkflowStepWorkspace;
35
- jobResources?: 'small' | 'medium' | 'large';
37
+ jobResources?: WorkflowJobResources;
36
38
  harness?: WorkflowJobHarness;
37
39
  /** Coding-turn cap for a tier:'job' step (1..500); absent ⇒ the platform default. A monorepo change needs more than the default. */
38
40
  maxTurns?: number;
41
+ /**
42
+ * Per-ATTEMPT ceilings for a tier:'job' step (LUA-636): `maxTurns` bounds one harness query; these bound the whole
43
+ * attempt (every pass and resumed segment). Crossing one checkpoints the workspace and ends the attempt
44
+ * `attempt_budget_exhausted` — retryable, so the step's `retry` policy continues from that tree with a fresh
45
+ * session. `maxMessages` counts harness messages (one per content block; 1..5000, default 400),
46
+ * `maxInputTokens` the attempt's input-side tokens (prompt + cache; 1M..500M, default 4M — LUA-708: the per-attempt
47
+ * cost bound, since `budget.maxCredits` counts attempts, not tokens).
48
+ */
49
+ maxMessages?: number;
50
+ maxInputTokens?: number;
39
51
  }
40
52
 
41
53
  export declare interface AgentToolScope {
@@ -58,7 +70,7 @@ export declare interface ApprovalOptions {
58
70
  /** 'deny' (default) | 'cancel-run' | 'fail' | a chain of ≤ 3 hops ending in one terminal member */
59
71
  onTimeout?: WorkflowSuspendTimeoutChain;
60
72
  /** default 'continue' (denial is data unless 'fail') */
61
- onDeny?: 'fail' | 'continue';
73
+ onDeny?: WorkflowApprovalOnDeny;
62
74
  businessHours?: WorkflowBusinessHours;
63
75
  editable?: boolean;
64
76
  /** grammar: `drafts`, `drafts[*]`, `drafts[*].body`, `drafts[3].body`, `summary.title` */
@@ -80,13 +92,21 @@ declare interface BuiltWorkflow {
80
92
  steps: Record<string, LuaWorkflowStep<any, any, any>>;
81
93
  warnings: LuaWorkflowBuildWarning[];
82
94
  envTemplateKeys: string[];
95
+ /** `.workflow(id, ref, …, { workspace })` targets; `workspace:'inherit'` marks an inherit child — the compiler defers `workspace-not-declared` for it (03 §3.1). */
83
96
  nestedRefs: Array<{
84
97
  id: string;
85
98
  name: string;
99
+ workspace?: 'inherit';
86
100
  }>;
87
101
  }
88
102
 
89
- /** A container arm: a `StepRef`, or (B14 — lands with WF-509) the two-element chain `[mapConfig, stepRef]`. */
103
+ /**
104
+ * A container arm: a `StepRef` — a `createStep` object, or a string naming an entry declared elsewhere in the chain
105
+ * (`agentStep` / `specialistStep` / `toolStep` / `workflow`, and since LUA-684 `approval` / `waitForSignal`, so an
106
+ * approval can run concurrently with another row) — or (B14 — lands with WF-509) the two-element chain
107
+ * `[mapConfig, stepRef]`. A HITL arm takes the previous output as its payload, so it never heads a `[map, step]`
108
+ * chain, and a `loop` body cannot be one until the engine proves it (`node-type-unsupported-in-container`).
109
+ */
90
110
  export declare type ContainerArm = StepRef | [LuaMapConfig, StepRef];
91
111
 
92
112
  export declare function createStep<TIn extends ZodType, TOut extends ZodType, TResume extends ZodType = ZodType>(s: LuaWorkflowStep<TIn, TOut, TResume>): LuaWorkflowStep<TIn, TOut, TResume>;
@@ -249,29 +269,44 @@ export declare class LuaWorkflow {
249
269
  getBuildWarnings(): LuaWorkflowBuildWarning[];
250
270
  /** Every `env.template(KEY)` placeholder key the graph carries (sorted, deduped) — `ManifestWorkflow.envTemplateKeys`. */
251
271
  getEnvTemplateKeys(): string[];
252
- /** `.workflow(id, ref)` targets by name — `ManifestWorkflow.workflowRefs`. */
272
+ /** `.workflow(id, ref)` targets by name — `ManifestWorkflow.workflowRefs`; `workspace:'inherit'` marks the inherit children the compiler defers `workspace-not-declared` for. */
253
273
  getNestedWorkflowRefs(): Array<{
254
274
  id: string;
255
275
  name: string;
276
+ workspace?: 'inherit';
256
277
  }>;
257
278
  /** Pure: no I/O, no env, no time. Called by the compiler in the VM tier and by `lua test`. */
258
279
  __serializeGraph(): SerializedWorkflowGraph;
259
280
  }
260
281
 
261
- export declare type LuaWorkflowBuildCode = 'duplicate-step-id' | 'unknown-step-ref' | 'map-id-required' | 'closure-predicate' | 'closure-binding' | 'timeout-out-of-range' | 'timeout-exceeds-tier' | 'job-timeout-exceeds-cap' | 'long-job-requires-workspace' | 'workspace-requires-job-tier' | 'workspace-not-declared' | 'workspace-inherit-without-parent-workspace' | 'workspace-inherit-conflict' | 'harness-requires-job-tier' | 'max-turns-requires-job-tier' | 'max-turns-invalid' | 'cap-exceeded' | 'chunk-size-invalid' | 'rate-limit-invalid' | 'backoff-invalid' | 'loop-interval-out-of-range' | 'mapping-placement' | 'container-arm-empty' | 'approval-inside-container' | 'empty-graph' | 'ephemeral-role-too-long' | 'role-ref-and-inline' | 'approver-excludes-only-candidate' | 'four-eyes-requires-editable' | 'escalation-chain-not-terminal' | 'escalation-chain-too-long' | 'editable-path-invalid' | 'env-template-secret-key' | 'invalid-envelope' | 'invalid-step' | 'invalid-step-id' | 'invalid-workflow-name' | 'schedule-input-required' | 'schedule-input-invalid' | 'hitl-duration-defaulted' | 'WORKFLOW_UNPLACED_STEP';
282
+ export declare type LuaWorkflowBuildCode = 'duplicate-step-id' | 'unknown-step-ref' | 'map-id-required' | 'closure-predicate' | 'closure-binding' | 'timeout-out-of-range' | 'timeout-exceeds-tier' | 'job-timeout-exceeds-cap' | 'long-job-requires-workspace' | 'workspace-requires-job-tier'
283
+ /**
284
+ * @deprecated LUA-635 — the builder no longer throws it: a mount with no envelope `workspace` is the SHARED validator's
285
+ * verdict (deferred for an inherit child, 03 §3.1 table). Kept for one minor so a consumer switching on the union still
286
+ * compiles; removed in the next.
287
+ */
288
+ | 'workspace-not-declared' | 'workspace-inherit-without-parent-workspace' | 'workspace-inherit-conflict' | 'harness-requires-job-tier' | 'max-turns-requires-job-tier' | 'max-turns-invalid' | 'cap-exceeded' | 'chunk-size-invalid' | 'rate-limit-invalid' | 'backoff-invalid' | 'loop-interval-out-of-range' | 'mapping-placement' | 'container-arm-empty'
289
+ /**
290
+ * @deprecated LUA-684 — the builder no longer throws it: an `approval` / `waitForSignal` IS a container arm
291
+ * (`parallel(['approve', …])`). Where the engine cannot run one — a `loop` body, the step of a `[map, step]`
292
+ * chain — the code is `node-type-unsupported-in-container`. Kept for one minor so a consumer switching on the
293
+ * union still compiles; removed in the next.
294
+ */
295
+ | 'approval-inside-container' | 'node-type-unsupported-in-container' | 'empty-graph' | 'ephemeral-role-too-long' | 'role-ref-and-inline' | 'approver-excludes-only-candidate' | 'four-eyes-requires-editable' | 'escalation-chain-not-terminal' | 'escalation-chain-too-long' | 'editable-path-invalid' | 'env-template-secret-key' | 'invalid-envelope' | 'invalid-step' | 'invalid-step-id' | 'invalid-workflow-name' | 'schedule-input-required' | 'schedule-input-invalid' | 'hitl-duration-defaulted' | 'WORKFLOW_UNPLACED_STEP';
262
296
 
263
297
  export declare interface LuaWorkflowBuilder {
264
298
  then(step: StepRef): this;
265
- /** 2..16 arms; output = { [stepId]: output } */
299
+ /** 2..16 arms; output = { [stepId]: output }. An `approval` / `waitForSignal` arm (by id) parks beside its siblings. */
266
300
  parallel(steps: ContainerArm[], opts?: {
267
301
  merge?: WorkflowMergePolicy;
268
302
  }): this;
269
- /** all-true arms run (Mastra); exclusive:true ≡ switch() */
303
+ /** all-true arms run (Mastra); exclusive:true ≡ switch(). An arm may name a declared `approval` / `waitForSignal`. */
270
304
  branch(arms: Array<[LuaPredicate, StepRef]>, opts?: {
271
305
  exclusive?: boolean;
272
306
  }): this;
273
307
  /** first true arm only ⇒ conditional{ exclusive:true, otherwise } */
274
308
  switch(arms: Array<[LuaPredicate, StepRef]>, otherwise?: StepRef): this;
309
+ /** one body run per item; an `approval` / `waitForSignal` body (by id) is one approval / wait per item */
275
310
  foreach(step: ContainerArm, opts?: ForeachOptions): this;
276
311
  dowhile(step: ContainerArm, predicate: LuaPredicate, opts?: LoopOptions): this;
277
312
  dountil(step: ContainerArm, predicate: LuaPredicate, opts?: LoopOptions): this;
@@ -294,12 +329,11 @@ export declare interface LuaWorkflowBuilder {
294
329
  /** D25 ephemeral specialist: runs AS THE OWNING AGENT (`agentId:'$self'`) with an additive role block. */
295
330
  specialistStep(id: string, opts: SpecialistStepOptions): this;
296
331
  toolStep(id: string, tool: LuaTool<any>, opts?: ToolStepOptions): this;
332
+ /** a declaration like `agentStep` (LUA-684): placed where called unless a container claims the id — `parallel(['approve', …])` */
297
333
  approval(id: string, opts: ApprovalOptions): this;
298
334
  waitForSignal(id: string, opts: WaitForSignalOptions): this;
299
- /** nested run; depth ≤ 3 */
300
- workflow(id: string, ref: LuaWorkflow | string, input?: LuaMapConfig, opts?: {
301
- workspace?: 'inherit';
302
- }): this;
335
+ /** nested run; depth ≤ 3 — declares `id`, so a container may place it by string ref (03 §3.2.0) */
336
+ workflow(id: string, ref: LuaWorkflow | string, input?: LuaMapConfig, opts?: NestedWorkflowOptions): this;
303
337
  commit(): LuaWorkflow;
304
338
  }
305
339
 
@@ -327,12 +361,19 @@ export declare interface LuaWorkflowConfig {
327
361
  concurrencyPolicy?: 'allow' | 'forbid';
328
362
  /** Who may READ this workflow's run outputs beyond `workflows:read-outputs` holders (B44). Envelope member outside `graphHash`. */
329
363
  outputVisibility?: WorkflowOutputVisibility;
330
- /** `maxDurationSeconds` default 604 800; 2 592 000 when the graph contains an approval / waitForSignal / suspend-capable step (P1-4). */
331
- budget?: {
332
- maxCredits?: number;
333
- maxSteps?: number;
334
- maxDurationSeconds?: number;
335
- };
364
+ /**
365
+ * `maxDurationSeconds` default 604 800; 2 592 000 when the graph contains an approval / waitForSignal / suspend-capable
366
+ * step (P1-4). The three members the SDK forwards, spelled by the ONE definition budget (`WorkflowDefinitionBudget`).
367
+ *
368
+ * `maxCredits` counts agent steps, never tokens (LUA-708): an inline agent step settles a flat 1 credit when it
369
+ * completes, a `tier:'job'` attempt a flat 4 at its first claim (a retry is a new attempt). The run parks on a
370
+ * budget gate (`nextAction:'raise_budget'`, `lua workflows raise-budget`) when what remains is under the next agent
371
+ * step's reserve — so `maxCredits: 40` buys ten Job-tier attempts, and a value under 4 never dispatches one. Each
372
+ * attempt then runs to its own wall (`timeoutSeconds`), `maxInputTokens` (default 4M ≈ $1–13 on a Sonnet-class
373
+ * model), `maxMessages` and `maxTurns`; nothing meters its tokens against the credits mid-attempt. Size
374
+ * `maxInputTokens` for what one attempt may cost and `maxCredits` for how many attempts the run may make.
375
+ */
376
+ budget?: Pick<WorkflowDefinitionBudget, 'maxCredits' | 'maxSteps' | 'maxDurationSeconds'>;
336
377
  /** verbatim LuaJob union (D12) → Job{kind:'workflow'} on publish */
337
378
  schedule?: JobSchedule;
338
379
  backfillOnEnable?: {
@@ -344,6 +385,13 @@ export declare interface LuaWorkflowConfig {
344
385
  /** NEVER set by hand — the compiler derives it from the source file. */
345
386
  form?: 'graph' | 'script';
346
387
  workspace?: WorkspaceSpec;
388
+ /**
389
+ * Declared connection keys. `workspace.credentialsRef` and a step's `requiredConnections` may name a
390
+ * `key` instead of a connection id; the engine resolves it against the owner agent's own connections
391
+ * at run time (agent-scoped first, then org-scoped — never a user's), so the same definition runs on
392
+ * a template install, a hand-built agent and a duplicate without a frozen id.
393
+ */
394
+ connections?: WorkflowConnectionDeclaration[];
347
395
  }
348
396
 
349
397
  export declare interface LuaWorkflowStep<TIn extends ZodType = ZodType, TOut extends ZodType = ZodType, TResume extends ZodType = ZodType> {
@@ -358,16 +406,16 @@ export declare interface LuaWorkflowStep<TIn extends ZodType = ZodType, TOut ext
358
406
  /** 1..600 (D19); default 300 — on `tier:'job'` 1..86 400, default 3600. */
359
407
  timeoutSeconds?: number;
360
408
  /** Run this step as a k8s Job (hours tier). Implied by `workspace`. */
361
- tier?: 'job';
409
+ tier?: WorkflowTier;
362
410
  workspace?: WorkflowStepWorkspace;
363
- jobResources?: 'small' | 'medium' | 'large';
411
+ jobResources?: WorkflowJobResources;
364
412
  jobTools?: WorkflowJobToolId[];
365
413
  /** default { maxAttempts: 1 } */
366
414
  retry?: RetryPolicy;
367
415
  /** default 'none'; 'external' ⇒ park on platform-fault reclaim. */
368
- sideEffects?: 'none' | 'external';
416
+ sideEffects?: WorkflowSideEffects;
369
417
  /** What the FINAL failure of this step does to the run (default 'fail'). */
370
- onError?: 'fail' | 'continue' | 'park';
418
+ onError?: WorkflowOnError;
371
419
  requiredConnections?: string[];
372
420
  /** Deadline for a `ctx.suspend()` suspension; default 168, max 720. */
373
421
  resumeTimeoutHours?: number;
@@ -379,6 +427,18 @@ export { MapDescriptor }
379
427
 
380
428
  export declare const ne: <T>(l: TypedRef<T>, r: TypedRef<T> | Literal<T>) => LuaPredicate;
381
429
 
430
+ /** `.workflow(id, ref, input?, opts?)` — a nested run (a `subrun` row). */
431
+ export declare interface NestedWorkflowOptions {
432
+ /** Mount the PARENT's run workspace in the child (05 §5.17.5; LUA-650) — the parent must declare one. */
433
+ workspace?: 'inherit';
434
+ /**
435
+ * LUA-669 (#2446): the same policy a code / agent / tool step carries — the row re-arms when the child run ends
436
+ * `failed` or `timed_out` on its own (a child the parent side ended — cancelled, abandoned — is never retried),
437
+ * behind the WF-222 backoff, and every attempt starts a FRESH child run. Default `{ maxAttempts: 1 }`.
438
+ */
439
+ retry?: RetryPolicy;
440
+ }
441
+
382
442
  export declare const not: (arg: LuaPredicate) => LuaPredicate;
383
443
 
384
444
  export declare const notExists: (ref: TypedRef<unknown>) => LuaPredicate;
@@ -394,15 +454,10 @@ export declare type PathValue<T, P extends string> = P extends `${infer H}.${inf
394
454
 
395
455
  export declare type ReplyChannel = 'whatsapp' | 'sms' | 'email' | 'webchat' | 'slack';
396
456
 
397
- export declare interface RetryPolicy {
398
- maxAttempts: number;
399
- /** delay before attempt 2 (default 0 = immediate) */
400
- backoffSeconds?: number;
401
- /** 'fixed' (default) | 'exponential' — an engine timer, never a sleep inside the step VM (P1-10). */
402
- backoff?: 'fixed' | 'exponential';
403
- /** default 3600; only meaningful with 'exponential' (`backoff-invalid` otherwise). */
404
- maxBackoffSeconds?: number;
405
- }
457
+ /** The ONE retry shape (`@lua/shared-types` `WorkflowRetryPolicy`): `maxAttempts` ≥ 1; `backoffSeconds` (default 0 =
458
+ * immediate) — an engine timer, never a sleep inside the step VM (P1-10); `backoff` 'fixed' (default) | 'exponential';
459
+ * `maxBackoffSeconds` (default 3600) only meaningful with 'exponential' (`backoff-invalid` otherwise). */
460
+ export declare type RetryPolicy = WorkflowRetryPolicy;
406
461
 
407
462
  export declare const rows: (s: LuaWorkflowStep<any, any, any> | string, path: string, page: {
408
463
  offset: number;
@@ -421,7 +476,7 @@ export declare interface SpecialistStepOptions {
421
476
  toolScope?: AgentToolScope;
422
477
  timeoutSeconds?: number;
423
478
  retry?: RetryPolicy;
424
- onError?: 'fail' | 'continue' | 'park';
479
+ onError?: WorkflowOnError;
425
480
  requiredConnections?: string[];
426
481
  }
427
482
 
@@ -513,8 +568,8 @@ export declare interface ToolStepOptions {
513
568
  input?: LuaMapConfig;
514
569
  timeoutSeconds?: number;
515
570
  retry?: RetryPolicy;
516
- sideEffects?: 'none' | 'external';
517
- onError?: 'fail' | 'continue' | 'park';
571
+ sideEffects?: WorkflowSideEffects;
572
+ onError?: WorkflowOnError;
518
573
  requiredConnections?: string[];
519
574
  }
520
575
 
@@ -529,16 +584,42 @@ export declare interface WaitForSignalOptions {
529
584
  schema?: ZodType;
530
585
  timeoutHours?: number | TemplateBinding;
531
586
  /** default 'fail'; 'continue' ⇒ output {received:false,timedOut:true} */
532
- onTimeout?: 'fail' | 'continue';
587
+ onTimeout?: WorkflowSignalOnTimeout;
533
588
  businessHours?: WorkflowBusinessHours;
534
589
  /** default ['webhook','api','user'] */
535
590
  acceptedSources?: Array<'webhook' | 'api' | 'user' | 'agent'>;
536
591
  }
537
592
 
593
+ /** `approval.onDeny` (§6.4.11 deny-as-data): `'fail'` fails the step on a denial; default `'continue'`. */
594
+ declare const WORKFLOW_APPROVAL_ON_DENY: readonly ["fail", "continue"];
595
+
538
596
  export declare const WORKFLOW_DEFAULT_MAX_DURATION_SECONDS = 604800;
539
597
 
540
598
  export declare const WORKFLOW_HITL_MAX_DURATION_SECONDS = 2592000;
541
599
 
600
+ /** D19-r2 (B22; 05 §5.17.6 Harness row) — both behind one `CodingHarness { run(turn) }`. */
601
+ declare const WORKFLOW_JOB_HARNESSES: readonly ["claude-code", "generic"];
602
+
603
+ /** `jobResources` (05 §5.17): the Job-tier pod size class. Default `'small'` at spawn. */
604
+ declare const WORKFLOW_JOB_RESOURCES: readonly ["small", "medium", "large"];
605
+
606
+ /** What the FINAL failure of a step does to the run: `'park'` → the §06 §6.3.5 exception gate. Default `'fail'`. */
607
+ declare const WORKFLOW_ON_ERROR: readonly ["fail", "continue", "park"];
608
+
609
+ /** `backoff` absent ⇒ `'fixed'`; `'exponential'` = backoffSeconds·2^(attempt−1) capped at `maxBackoffSeconds`. */
610
+ declare const WORKFLOW_RETRY_BACKOFFS: readonly ["fixed", "exponential"];
611
+
612
+ /** `sideEffects` (03 §3.1): `'external'` ⇒ park on platform-fault reclaim instead of retrying. Default `'none'`. */
613
+ declare const WORKFLOW_SIDE_EFFECTS: readonly ["none", "external"];
614
+
615
+ /** `waitForSignal.onTimeout`: default `'fail'`; `'continue'` ⇒ output `{received:false, timedOut:true}`. */
616
+ declare const WORKFLOW_SIGNAL_ON_TIMEOUT: readonly ["fail", "continue"];
617
+
618
+ /** The only tier a node may DECLARE (`tier:'job'`, implied by `workspace`); the worker tier is the absence. */
619
+ declare const WORKFLOW_TIERS: readonly ["job"];
620
+
621
+ declare type WorkflowApprovalOnDeny = (typeof WORKFLOW_APPROVAL_ON_DENY)[number];
622
+
542
623
  export declare type WorkflowApproverSpec = 'creator' | 'org-admins' | {
543
624
  users: string[] | TemplateBinding;
544
625
  } | {
@@ -582,6 +663,37 @@ export declare interface WorkflowBusinessHours {
582
663
  };
583
664
  }
584
665
 
666
+ /** The ONE `connections[]` declaration shape (`@lua/shared-types`): `key` /^[a-z][a-z0-9_-]{0,63}$/ unique per workflow,
667
+ * `integrationType` the catalog type (`'github'`, `'linear'`, …), optional `required` / `description`. */
668
+ declare type WorkflowConnectionDeclaration = WorkflowConnectionDeclaration_2;
669
+
670
+ declare interface WorkflowConnectionDeclaration_2 {
671
+ /** /^[a-z][a-z0-9_-]{0,63}$/ — unique per workflow. */
672
+ key: string;
673
+ /** Catalog integration type (`github`, `linear`, …) the key resolves within. */
674
+ integrationType: string;
675
+ required?: boolean;
676
+ description?: string;
677
+ }
678
+
679
+ /** The declared budget (10 §10.7.1) — every member optional on the DEFINITION; the server resolves
680
+ * `maxDurationSeconds` onto the version (`WorkflowVersion.budget`) and the run. */
681
+ declare interface WorkflowDefinitionBudget {
682
+ /**
683
+ * The run's credit ceiling — it counts agent steps, never tokens (LUA-708). An inline agent step settles a flat
684
+ * 1 credit when it completes; a `tier:'job'` attempt settles a flat 4 at its first claim (a retry is a new
685
+ * attempt). The engine parks the run on a budget gate (`nextAction:'raise_budget'`) when what remains is under
686
+ * the next agent step's reserve, so `maxCredits: 40` is ten Job-tier attempts and a value under 4 never
687
+ * dispatches one. A Job-tier attempt's own spend is bounded by its wall / `maxInputTokens` / `maxMessages`.
688
+ */
689
+ maxCredits?: number;
690
+ maxSteps?: number;
691
+ /** Job-tier seconds across the run (05 §5.17). */
692
+ maxJobSeconds?: number;
693
+ /** default 604 800; 2 592 000 when the graph contains an approval / waitForSignal / suspend-capable step (P1-4). */
694
+ maxDurationSeconds?: number;
695
+ }
696
+
585
697
  export declare interface WorkflowFourEyes {
586
698
  edit: WorkflowApproverSpec;
587
699
  approve: WorkflowApproverSpec;
@@ -601,7 +713,11 @@ export declare interface WorkflowGoalEnvelope {
601
713
  initialState?: Record<string, unknown>;
602
714
  }
603
715
 
604
- export declare type WorkflowJobHarness = 'claude-code' | 'generic';
716
+ export declare type WorkflowJobHarness = WorkflowJobHarness_2;
717
+
718
+ declare type WorkflowJobHarness_2 = (typeof WORKFLOW_JOB_HARNESSES)[number];
719
+
720
+ declare type WorkflowJobResources = (typeof WORKFLOW_JOB_RESOURCES)[number];
605
721
 
606
722
  export declare type WorkflowJobToolId = 'shell' | 'read' | 'write' | 'edit' | 'glob' | 'grep' | 'git' | 'gh' | 'fetch';
607
723
 
@@ -610,14 +726,32 @@ export declare interface WorkflowMergePolicy {
610
726
  onConflict: 'fail' | 'agent';
611
727
  }
612
728
 
729
+ declare type WorkflowOnError = (typeof WORKFLOW_ON_ERROR)[number];
730
+
613
731
  export declare interface WorkflowOutputVisibility {
614
732
  roles: string[];
615
733
  users?: string[];
616
734
  ownerBypass?: boolean;
617
735
  }
618
736
 
737
+ declare type WorkflowRetryBackoff = (typeof WORKFLOW_RETRY_BACKOFFS)[number];
738
+
739
+ declare interface WorkflowRetryPolicy {
740
+ maxAttempts: number;
741
+ /** delay before attempt 2 (default 0 = immediate) — an engine timer, never a sleep inside the step VM (P1-10). */
742
+ backoffSeconds?: number;
743
+ /** `'fixed'` (default) | `'exponential'` */
744
+ backoff?: WorkflowRetryBackoff;
745
+ /** default 3600; only meaningful with `'exponential'` (`backoff-invalid` otherwise). */
746
+ maxBackoffSeconds?: number;
747
+ }
748
+
619
749
  export declare type WorkflowRunTrigger = 'chat' | 'sdk' | 'api' | 'schedule' | 'webhook' | 'template' | 'workflow' | 'device';
620
750
 
751
+ declare type WorkflowSideEffects = (typeof WORKFLOW_SIDE_EFFECTS)[number];
752
+
753
+ declare type WorkflowSignalOnTimeout = (typeof WORKFLOW_SIGNAL_ON_TIMEOUT)[number];
754
+
621
755
  export declare interface WorkflowSpecialistRole {
622
756
  name: string;
623
757
  instructions: string;
@@ -641,7 +775,11 @@ export declare interface WorkflowStepContext<TIn = unknown, TResume = unknown, T
641
775
  /** What the prior invocation passed to `suspend()`. */
642
776
  suspendData?: unknown;
643
777
  getInitData<T = unknown>(): T;
644
- /** Output of an UPSTREAM step. Throws `WorkflowStepResultError{ code:'STEP_RESULT_NOT_ANCESTOR' }` for a non-ancestor. */
778
+ /**
779
+ * Output of an UPSTREAM step. Throws `WorkflowStepResultError` — `code:'STEP_RESULT_NOT_ANCESTOR'` for a
780
+ * non-ancestor (or unknown) id, `'STEP_RESULT_TOO_LARGE'` / `'STEP_RESULT_OFFLOADED'` for an output the claim
781
+ * could not carry (see the error's doc for `bytes` / `reason`) — never `undefined`, never a raw ref object.
782
+ */
645
783
  getStepResult<T = unknown>(stepId: string): T;
646
784
  /** Run-scoped KV, ledger-backed, ≤ 64KB total. `set` is durable when the step terminalizes. */
647
785
  state: {
@@ -660,17 +798,65 @@ export declare interface WorkflowStepContext<TIn = unknown, TResume = unknown, T
660
798
  signal: AbortSignal;
661
799
  /** Sub-agent env, exactly as jobs receive it. */
662
800
  env: Record<string, string>;
663
- /** EXACTLY-ONCE effect keyed on `{occurrenceId, key}` (P1-18). Claim → run `fn` → settle. */
801
+ /**
802
+ * EXACTLY-ONCE effect keyed on `{occurrenceId, key}` (P1-18). Claim → run `fn` → settle. Served on every tier:
803
+ * worker-tier steps and the offline driver, and (LUA-722) Job-tier code steps — the pod relays the claim / settle
804
+ * under its own attempt token, so the key is scoped to the step's run / row / attempt server-side. A replayed key
805
+ * (a retried attempt, a repair run) returns the settled result without running `fn`; a key a previous attempt
806
+ * claimed and never settled throws `EFFECT_IN_DOUBT` (fail closed — `fn` never runs on an unknown claim state).
807
+ * The result is JSON-serialised on settle, exactly like a step output: a `Date` replays as its ISO string, a
808
+ * `BigInt` (or a cycle) fails the settle — `EFFECT_SETTLE_FAILED`, the key stays claimed — and a result over the
809
+ * platform's cap (32 KB) is `EFFECT_SETTLE_FAILED` naming `EFFECT_RESULT_TOO_LARGE`. Calling `once` again for the
810
+ * same key while its `fn` is still running (re-entrantly) throws `EFFECT_KEY_INVALID` at once.
811
+ */
664
812
  once<T>(key: string, fn: () => Promise<T>): Promise<T>;
665
- /** Job-tier steps only: the mounted run workspace. */
813
+ /**
814
+ * Job-tier steps only: the mounted run workspace, exactly as the Job pod hands it to `execute` (`ctx.workspace` in
815
+ * `packages/lua-workflow-job/src/code-step.ts`): `root` is the absolute directory of the checkout (`/workspace`),
816
+ * `branch` the run branch it is on, `headSha` the commit it was restored at, `mount` this step's declared mount,
817
+ * `isolation` whether the step got its own worktree. LUA-679: the name is `root` — the 3.32.1 type and both
818
+ * `lua init` examples said `path`, the pod never served it, and a copied definition died `ENOENT /workspace/undefined`.
819
+ */
666
820
  workspace?: {
667
- path: string;
821
+ root: string;
668
822
  mount: 'rw' | 'ro';
669
823
  branch?: string;
824
+ headSha?: string;
825
+ isolation?: 'shared' | 'worktree';
826
+ /**
827
+ * @deprecated LUA-679 — read `root`. The Job pod serves `path` as an alias (a getter that returns `root` and warns
828
+ * once per step) for one minor after 3.32 and then removes it; it never appears on `Object.keys(ctx.workspace)`.
829
+ */
830
+ readonly path?: string;
831
+ /**
832
+ * The run workspace's stamps, served when the pod hands them to the step (LUA-706): `baseSha` is the commit the
833
+ * run's base ref resolved to at provision (a git workspace — `headSha` is where THIS step's checkout is), `arm`
834
+ * the worktree arm id when the step runs in its own worktree (`isolation:'worktree'`), `backend` the volume
835
+ * backend. Absent on an `empty` workspace, a shared-mount step, or a pod that predates them.
836
+ */
670
837
  baseSha?: string;
671
838
  arm?: string;
672
839
  backend?: WorkflowWorkspaceBackend;
673
840
  };
841
+ /**
842
+ * Job-tier steps only (LUA-682): run one of `WORKFLOW_EXEC_BINARIES` (`git`, `gh`, `pnpm`, `npm`, `npx`, `node`,
843
+ * `yarn`, `python3`, `pytest`, `make`) in the workspace — `exec(['git', 'status'], { cwd?, timeoutMs?, env? })`.
844
+ * Argv only, never a shell: no `&&`, pipes, globs or `$VAR`; `cwd` must stay inside the workspace; the timeout
845
+ * (default 10 min) is capped by the step's remaining wall; stdout / stderr are kept to 1 MiB each (`truncated`);
846
+ * one command at a time. A non-zero exit is RETURNED (`result.code`) — `exec.strict` throws `WorkflowExecError`.
847
+ * The Job pod spawns the command itself with a scrubbed env (no token, no `LUA_WF_*`; git goes through the
848
+ * credential proxy exactly as the coding turn's does); `child_process` is not available to a code step and fails
849
+ * `lua compile` with `node-capability-unavailable`. Worker-tier steps have neither `exec` nor `$`. Offline,
850
+ * `lua workflows run --workspace <dir>` provides both with the same allowlist against your own PATH.
851
+ */
852
+ exec?: WorkflowExecFn;
853
+ /**
854
+ * Job-tier steps only (LUA-682): `exec` as a tagged template — `$\`gh pr create --title ${title} --body ${body}\``.
855
+ * Literal text splits on whitespace (with `'…'` / `"…"` quoting); every `${value}` is exactly ONE argument, never
856
+ * re-parsed (a title with spaces, a body with newlines); an array spreads into one argument per item; `undefined`
857
+ * is refused rather than stringified. `$.strict` throws on a non-zero exit.
858
+ */
859
+ $?: WorkflowShellFn;
674
860
  /** The run artefact store (P1-8). */
675
861
  artefacts: {
676
862
  put(name: string, data: Uint8Array | string | ReadableStream, opts: {
@@ -705,7 +891,12 @@ export declare interface WorkflowStepContext<TIn = unknown, TResume = unknown, T
705
891
  }>;
706
892
  list(): Promise<WorkflowArtefactMeta[]>;
707
893
  };
708
- /** Stamped by the executor for observability; read-only. */
894
+ /**
895
+ * Stamped by the executor for observability; read-only (frozen). Served on both tiers from the run's stamps
896
+ * (LUA-706): `trigger` / `principalKind`, plus `parentRunId` / `traceparent` / `correlationKey` / `tags` /
897
+ * `replyTo` when the run carries them; `agentVersion` is not stamped today. A run created before the stamps
898
+ * existed reads `{}`. Offline, `lua workflows run` serves `{ trigger:'sdk', principalKind:'user' }`.
899
+ */
709
900
  runtime: {
710
901
  trigger: WorkflowRunTrigger;
711
902
  parentRunId?: string;
@@ -721,10 +912,26 @@ export declare interface WorkflowStepContext<TIn = unknown, TResume = unknown, T
721
912
  };
722
913
  }
723
914
 
724
- /** Thrown by `ctx.getStepResult` for a non-ancestor / unknown id — never `undefined` (03 §3.1). */
915
+ /**
916
+ * Thrown by `ctx.getStepResult` — never `undefined`, never a raw ref object (03 §3.1). Check `err.code`, never
917
+ * `instanceof` (a step runs in its own realm on every tier):
918
+ * - `STEP_RESULT_NOT_ANCESTOR` — `stepId` is not an upstream step of this one (or is unknown);
919
+ * - `STEP_RESULT_TOO_LARGE` — the ancestor's output could not ride the claim beside its siblings (the 4 MiB
920
+ * `stepResults` wire budget, dropped largest-first); `bytes` is its serialized size;
921
+ * - `STEP_RESULT_OFFLOADED` — the ledger holds the output offloaded (> 256 KB) and the claim could not carry it
922
+ * hydrated; `bytes` is its size, `reason` why: `over_wire_cap` (it would break the budget), `hydrate_timeout`
923
+ * (the per-claim hydration deadline passed), or the control plane's code (`CDN_REF_MISSING`, `CDN_REF_CORRUPT`,
924
+ * `CDN_REF_FOREIGN`, …).
925
+ * For the last two, bind the value through the step's input instead, or read it via `ctx.artefacts` /
926
+ * `ctx.datasets`. The offline driver (`lua workflows execute`) only ever throws the first.
927
+ */
725
928
  export declare interface WorkflowStepResultError extends Error {
726
- code: 'STEP_RESULT_NOT_ANCESTOR';
929
+ code: 'STEP_RESULT_NOT_ANCESTOR' | 'STEP_RESULT_TOO_LARGE' | 'STEP_RESULT_OFFLOADED';
727
930
  stepId: string;
931
+ /** `STEP_RESULT_TOO_LARGE` / `STEP_RESULT_OFFLOADED`: the output's serialized size. */
932
+ bytes?: number;
933
+ /** `STEP_RESULT_OFFLOADED`: why the claim could not carry it. */
934
+ reason?: string;
728
935
  }
729
936
 
730
937
  export declare interface WorkflowStepWorkspace {
@@ -743,6 +950,8 @@ export declare type WorkflowSuspendTimeoutChainMember = 'deny' | 'cancel-run' |
743
950
  timeoutHours: number;
744
951
  };
745
952
 
953
+ declare type WorkflowTier = (typeof WORKFLOW_TIERS)[number];
954
+
746
955
  export declare type WorkflowWorkspaceBackend = 'ebs' | 'efs' | 's3';
747
956
 
748
957
  export declare type WorkspaceSpec = {
@@ -759,6 +968,10 @@ export declare type WorkspaceSpec = {
759
968
  kind: 'empty';
760
969
  sizeGb?: number;
761
970
  ttlHours?: number;
971
+ /**
972
+ * Keep the volume after the run completes: held until `ttlHours` (24 h when undeclared), then expired. A kept
973
+ * volume holds one of the organisation's workspace slots (`maxWorkspacesPerOrg`, 10 by default) until then.
974
+ */
762
975
  keepArtefacts?: boolean;
763
976
  backend?: WorkflowWorkspaceBackend;
764
977
  };