@relayflows/surface 2.0.30 → 2.0.31

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.
@@ -7,4 +7,19 @@ export type RunCompletionReason = (typeof RUN_COMPLETION_REASONS)[number];
7
7
  /** Authored verdicts include handoff and declination without widening kernel facts. */
8
8
  export declare const FLOW_COMPLETION_REASONS: readonly ["success", "step_failed", "canceled", "budget_exceeded", "needs_human", "declined"];
9
9
  export type FlowCompletionReason = (typeof FLOW_COMPLETION_REASONS)[number];
10
+ /**
11
+ * The bound on the optional `done()` detail, in Unicode code points of the
12
+ * FINAL normalized string — truncation suffix included.
13
+ *
14
+ * Stated in code points rather than `String.length` on purpose: `.length`
15
+ * counts UTF-16 code units, so an emoji-heavy detail measured that way is
16
+ * half the length a reader would call it. The number is the same order the
17
+ * kernel uses for a gate's free-text detail
18
+ * (`kernel/relayflowd/src/engine/remote.rs`), but it is not the same bound:
19
+ * that one takes 2,000 characters and then appends its suffix.
20
+ *
21
+ * The runtime enforces this; it is exported so an author can measure a detail
22
+ * before passing one.
23
+ */
24
+ export declare const COMPLETION_DETAIL_MAX_CODE_POINTS = 2000;
10
25
  //# sourceMappingURL=completion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../src/completion.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,wJAUrB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,oEAKzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,+FAI1B,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../src/completion.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,wJAUrB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,oEAKzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,+FAI1B,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iCAAiC,OAAO,CAAC"}
@@ -23,4 +23,19 @@ export const FLOW_COMPLETION_REASONS = [
23
23
  'needs_human',
24
24
  'declined',
25
25
  ];
26
+ /**
27
+ * The bound on the optional `done()` detail, in Unicode code points of the
28
+ * FINAL normalized string — truncation suffix included.
29
+ *
30
+ * Stated in code points rather than `String.length` on purpose: `.length`
31
+ * counts UTF-16 code units, so an emoji-heavy detail measured that way is
32
+ * half the length a reader would call it. The number is the same order the
33
+ * kernel uses for a gate's free-text detail
34
+ * (`kernel/relayflowd/src/engine/remote.rs`), but it is not the same bound:
35
+ * that one takes 2,000 characters and then appends its suffix.
36
+ *
37
+ * The runtime enforces this; it is exported so an author can measure a detail
38
+ * before passing one.
39
+ */
40
+ export const COMPLETION_DETAIL_MAX_CODE_POINTS = 2000;
26
41
  //# sourceMappingURL=completion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"completion.js","sourceRoot":"","sources":["../src/completion.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,SAAS;IACT,qBAAqB;IACrB,mBAAmB;IACnB,eAAe;IACf,SAAS;IACT,SAAS;IACT,cAAc;IACd,iBAAiB;IACjB,UAAU;CACF,CAAC;AAIX,sEAAsE;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,SAAS;IACT,aAAa;IACb,UAAU;IACV,iBAAiB;CACT,CAAC;AAIX,uFAAuF;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,sBAAsB;IACzB,aAAa;IACb,UAAU;CACF,CAAC"}
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../src/completion.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,SAAS;IACT,qBAAqB;IACrB,mBAAmB;IACnB,eAAe;IACf,SAAS;IACT,SAAS;IACT,cAAc;IACd,iBAAiB;IACjB,UAAU;CACF,CAAC;AAIX,sEAAsE;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,SAAS;IACT,aAAa;IACb,UAAU;IACV,iBAAiB;CACT,CAAC;AAIX,uFAAuF;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,sBAAsB;IACzB,aAAa;IACb,UAAU;CACF,CAAC;AAIX;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,IAAI,CAAC"}
package/dist/context.d.ts CHANGED
@@ -29,7 +29,19 @@ export interface AgentOptions {
29
29
  permissions?: PermissionsSpec;
30
30
  cli?: string;
31
31
  model?: string;
32
- /** Working directory for the CLI subprocess; defaults to the flow-runner's cwd. */
32
+ /**
33
+ * Directory this agent's CLI is spawned in, relative to the run root — the
34
+ * flow-runner's working directory, and where the CLI runs when this is
35
+ * absent. One flow can therefore drive agents in sibling checkouts. The
36
+ * path must be relative and free of `.`, `..` and empty components, and
37
+ * must name an existing directory inside the run root at dispatch;
38
+ * anything else refuses the step instead of running it somewhere else.
39
+ * An absolute path is accepted when it names a directory inside the run
40
+ * root — it lowers to the same relative declaration — and refused when it
41
+ * escapes. `artifacts` are reported relative to this directory. It is a
42
+ * declaration of where to start, not a sandbox. Not supported with
43
+ * `transport: 'relay'`. See docs/SURFACE.md.
44
+ */
33
45
  cwd?: string;
34
46
  /**
35
47
  * Dispatch transport (flows#385). `'direct'` (default) spawns the CLI as a
@@ -38,12 +50,55 @@ export interface AgentOptions {
38
50
  */
39
51
  transport?: 'direct' | 'relay';
40
52
  }
53
+ /**
54
+ * What `f.run` resolves to under `onNonZero: 'record'`.
55
+ *
56
+ * Every field is read back from the step's journaled output envelope, never
57
+ * re-measured: `ok` is the recorded exit code, not a second execution. This is
58
+ * the point of the policy — `<command> || true` discards the code, so the
59
+ * branch below it can only ever be taken on faith.
60
+ */
61
+ export interface RunResult {
62
+ /** Exactly `exitCode === 0`. */
63
+ ok: boolean;
64
+ /** The exit code the kernel journaled for this command. */
65
+ exitCode: number;
66
+ /**
67
+ * `stdout` then `stderr`, joined by a newline when both are nonempty — the
68
+ * string to hand an agent asked to repair what the command reported. It is a
69
+ * diagnostic convenience, not a reconstruction of the real interleaving: the
70
+ * two streams were captured separately and their true ordering is not
71
+ * journaled. Read `stdout` when you need to parse the command's own output.
72
+ */
73
+ output: string;
74
+ /** stdout tail — the same string the default `f.run` resolves to. */
75
+ stdout: string;
76
+ /** stderr tail, where a failing check usually explains itself. */
77
+ stderr: string;
78
+ }
79
+ export interface RunOptions {
80
+ /** Command lease: milliseconds or a duration such as "5m"; default 30s, maximum 15m. */
81
+ timeout?: string | number;
82
+ /**
83
+ * What a nonzero exit means. `'fail'` (the default) throws, ending the flow
84
+ * at this line. `'record'` journals the exit code and output and resolves to
85
+ * a `RunResult`, so the body can hand a red check's own output to whatever is
86
+ * built to repair it. A timeout, a signal, or a step that never ran still
87
+ * throws under either policy: those produced no verdict to record.
88
+ */
89
+ onNonZero?: 'fail' | 'record';
90
+ }
41
91
  export interface LlmOptions {
42
92
  /** JSON Schema checked before the result is accepted by the journal. */
43
93
  output: Record<string, unknown>;
44
94
  cli?: string;
45
95
  model?: string;
46
96
  }
97
+ /** The optional second argument to {@link Ctx.done}. */
98
+ export interface DoneOptions {
99
+ /** Why the flow reached this verdict; redacted, bounded, and journaled. */
100
+ detail?: string;
101
+ }
47
102
  /**
48
103
  * The context a journal-backed runtime injects into a flow body.
49
104
  *
@@ -56,10 +111,24 @@ export interface Ctx extends Helpers {
56
111
  readonly cloud?: CloudCapabilities;
57
112
  };
58
113
  readonly mcp: Readonly<Record<string, Readonly<Record<string, (args: unknown) => Step<unknown>>>>>;
59
- /** Command lease: milliseconds or a duration such as "5m"; default 30s, maximum 15m. */
60
- run(command: string, options?: {
61
- timeout?: string | number;
114
+ /**
115
+ * Run a command. Resolves to its stdout tail, and a nonzero exit ends the
116
+ * flow — unless `onNonZero: 'record'` is declared, which resolves to a
117
+ * `RunResult` carrying the journaled exit code instead.
118
+ *
119
+ * The literal overloads come first so the default stays the common case: an
120
+ * omitted or `'fail'` policy keeps the `Step<string>` every existing body is
121
+ * written against, and only the literal `'record'` widens the result. The
122
+ * third is for a policy held in a variable, where neither literal applies and
123
+ * the author has to narrow the union themselves.
124
+ */
125
+ run(command: string, options?: RunOptions & {
126
+ onNonZero?: 'fail';
62
127
  }): Step<string>;
128
+ run(command: string, options: RunOptions & {
129
+ onNonZero: 'record';
130
+ }): Step<RunResult>;
131
+ run(command: string, options: RunOptions): Step<string | RunResult>;
63
132
  llm(strings: TemplateStringsArray, ...values: unknown[]): Step<string>;
64
133
  /** JSON Schema validates the value at runtime; narrow unknown in author code. */
65
134
  llm(prompt: string, options: LlmOptions): Step<unknown>;
@@ -81,7 +150,21 @@ export interface Ctx extends Helpers {
81
150
  * no-op that returns true. A name must appear in the flow header's `hooks`.
82
151
  */
83
152
  hook(name: string, input: unknown): Step<boolean>;
84
- done(reason: FlowCompletionReason): void;
153
+ /**
154
+ * End the flow with an authored verdict, and optionally say why.
155
+ *
156
+ * `options.detail` is free prose the flow already knows — "review found 1
157
+ * P2: `review.clean` was not created" — and it is what a reader gets instead
158
+ * of a generic sentence. It is journaled with the verdict, so it survives
159
+ * into the run report and `flows status`; the runtime redacts it and bounds
160
+ * it to `COMPLETION_DETAIL_MAX_CODE_POINTS` code points, truncating
161
+ * with a visible marker rather than refusing an over-long one.
162
+ *
163
+ * Whitespace-only is the same as saying nothing: it normalizes to absence,
164
+ * and the verdict reports exactly as the one-argument call does. A `detail`
165
+ * that is present and not a string is refused.
166
+ */
167
+ done(reason: FlowCompletionReason, options?: DoneOptions): void;
85
168
  cloud: CloudHelper;
86
169
  memory: MemoryHelper;
87
170
  }
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export type { EnrollmentReceipt, Heartbeat, JournalStep, RunJournal, ScheduleState, WorkerSummary, CloudHelper, CloudCapabilities, CloudBabysitterTurnCapability, CloudBabysitterTurnDelivery, CloudBabysitterTurnReceipt, } from "./cloud.js";
2
- export type { AgentOptions, AgentResult, PermissionsSpec, LlmOptions, Ctx } from "./context.js";
3
- export { COMPLETION_REASONS, RUN_COMPLETION_REASONS, FLOW_COMPLETION_REASONS, type CompletionReason, type RunCompletionReason, type FlowCompletionReason, } from "./completion.js";
2
+ export type { AgentOptions, AgentResult, DoneOptions, PermissionsSpec, LlmOptions, RunOptions, RunResult, Ctx } from "./context.js";
3
+ export { COMPLETION_DETAIL_MAX_CODE_POINTS, COMPLETION_REASONS, RUN_COMPLETION_REASONS, FLOW_COMPLETION_REASONS, type CompletionReason, type RunCompletionReason, type FlowCompletionReason, } from "./completion.js";
4
4
  export type { Step, NamedGate, ReferencesInputNamedGate, SubprocessNamedGate, WordCountBoundsNamedGate, RegexMatchNamedGate, } from "./step.js";
5
5
  export { flow, type FlowHandle, type TriggeredFlowHandle, type FlowHeader, } from "./flow.js";
6
6
  export { flowRunWritebackIdempotency, type SlackHelper, type SlackReceipt, type SlackBlock, type SlackAttachment, type SlackPostMessage, type SlackPostOptions, } from "./slack.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,UAAU,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,6BAA6B,EAC7B,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,IAAI,EACJ,SAAS,EACT,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,IAAI,EACJ,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,UAAU,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,2BAA2B,EAC3B,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnH,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9H,OAAO,EACL,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,SAAS,EAC1F,KAAK,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,GACrF,MAAM,eAAe,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,UAAU,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,6BAA6B,EAC7B,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACpI,OAAO,EACL,iCAAiC,EACjC,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,IAAI,EACJ,SAAS,EACT,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,IAAI,EACJ,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,UAAU,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,2BAA2B,EAC3B,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnH,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9H,OAAO,EACL,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,SAAS,EAC1F,KAAK,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,GACrF,MAAM,eAAe,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { COMPLETION_REASONS, RUN_COMPLETION_REASONS, FLOW_COMPLETION_REASONS, } from "./completion.js";
1
+ export { COMPLETION_DETAIL_MAX_CODE_POINTS, COMPLETION_REASONS, RUN_COMPLETION_REASONS, FLOW_COMPLETION_REASONS, } from "./completion.js";
2
2
  export { flow, } from "./flow.js";
3
3
  export { flowRunWritebackIdempotency, } from "./slack.js";
4
4
  export { webhook } from "./triggers.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,GAIxB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EACL,IAAI,GAIL,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,2BAA2B,GAO5B,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,OAAO,EAAwF,MAAM,eAAe,CAAC;AAC9H,OAAO,EACL,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,SAAS,GAE3F,MAAM,eAAe,CAAC;AACvB,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,iCAAiC,EACjC,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,GAIxB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EACL,IAAI,GAIL,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,2BAA2B,GAO5B,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,OAAO,EAAwF,MAAM,eAAe,CAAC;AAC9H,OAAO,EACL,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,SAAS,GAE3F,MAAM,eAAe,CAAC;AACvB,cAAc,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayflows/surface",
3
- "version": "2.0.30",
3
+ "version": "2.0.31",
4
4
  "description": "TypeScript authoring surface for Relayflows.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/completion.ts CHANGED
@@ -31,3 +31,19 @@ export const FLOW_COMPLETION_REASONS = [
31
31
  ] as const;
32
32
 
33
33
  export type FlowCompletionReason = (typeof FLOW_COMPLETION_REASONS)[number];
34
+
35
+ /**
36
+ * The bound on the optional `done()` detail, in Unicode code points of the
37
+ * FINAL normalized string — truncation suffix included.
38
+ *
39
+ * Stated in code points rather than `String.length` on purpose: `.length`
40
+ * counts UTF-16 code units, so an emoji-heavy detail measured that way is
41
+ * half the length a reader would call it. The number is the same order the
42
+ * kernel uses for a gate's free-text detail
43
+ * (`kernel/relayflowd/src/engine/remote.rs`), but it is not the same bound:
44
+ * that one takes 2,000 characters and then appends its suffix.
45
+ *
46
+ * The runtime enforces this; it is exported so an author can measure a detail
47
+ * before passing one.
48
+ */
49
+ export const COMPLETION_DETAIL_MAX_CODE_POINTS = 2000;
package/src/context.ts CHANGED
@@ -32,7 +32,19 @@ export interface AgentOptions {
32
32
  permissions?: PermissionsSpec;
33
33
  cli?: string;
34
34
  model?: string;
35
- /** Working directory for the CLI subprocess; defaults to the flow-runner's cwd. */
35
+ /**
36
+ * Directory this agent's CLI is spawned in, relative to the run root — the
37
+ * flow-runner's working directory, and where the CLI runs when this is
38
+ * absent. One flow can therefore drive agents in sibling checkouts. The
39
+ * path must be relative and free of `.`, `..` and empty components, and
40
+ * must name an existing directory inside the run root at dispatch;
41
+ * anything else refuses the step instead of running it somewhere else.
42
+ * An absolute path is accepted when it names a directory inside the run
43
+ * root — it lowers to the same relative declaration — and refused when it
44
+ * escapes. `artifacts` are reported relative to this directory. It is a
45
+ * declaration of where to start, not a sandbox. Not supported with
46
+ * `transport: 'relay'`. See docs/SURFACE.md.
47
+ */
36
48
  cwd?: string;
37
49
  /**
38
50
  * Dispatch transport (flows#385). `'direct'` (default) spawns the CLI as a
@@ -42,6 +54,46 @@ export interface AgentOptions {
42
54
  transport?: 'direct' | 'relay';
43
55
  }
44
56
 
57
+ /**
58
+ * What `f.run` resolves to under `onNonZero: 'record'`.
59
+ *
60
+ * Every field is read back from the step's journaled output envelope, never
61
+ * re-measured: `ok` is the recorded exit code, not a second execution. This is
62
+ * the point of the policy — `<command> || true` discards the code, so the
63
+ * branch below it can only ever be taken on faith.
64
+ */
65
+ export interface RunResult {
66
+ /** Exactly `exitCode === 0`. */
67
+ ok: boolean;
68
+ /** The exit code the kernel journaled for this command. */
69
+ exitCode: number;
70
+ /**
71
+ * `stdout` then `stderr`, joined by a newline when both are nonempty — the
72
+ * string to hand an agent asked to repair what the command reported. It is a
73
+ * diagnostic convenience, not a reconstruction of the real interleaving: the
74
+ * two streams were captured separately and their true ordering is not
75
+ * journaled. Read `stdout` when you need to parse the command's own output.
76
+ */
77
+ output: string;
78
+ /** stdout tail — the same string the default `f.run` resolves to. */
79
+ stdout: string;
80
+ /** stderr tail, where a failing check usually explains itself. */
81
+ stderr: string;
82
+ }
83
+
84
+ export interface RunOptions {
85
+ /** Command lease: milliseconds or a duration such as "5m"; default 30s, maximum 15m. */
86
+ timeout?: string | number;
87
+ /**
88
+ * What a nonzero exit means. `'fail'` (the default) throws, ending the flow
89
+ * at this line. `'record'` journals the exit code and output and resolves to
90
+ * a `RunResult`, so the body can hand a red check's own output to whatever is
91
+ * built to repair it. A timeout, a signal, or a step that never ran still
92
+ * throws under either policy: those produced no verdict to record.
93
+ */
94
+ onNonZero?: 'fail' | 'record';
95
+ }
96
+
45
97
  export interface LlmOptions {
46
98
  /** JSON Schema checked before the result is accepted by the journal. */
47
99
  output: Record<string, unknown>;
@@ -49,6 +101,12 @@ export interface LlmOptions {
49
101
  model?: string;
50
102
  }
51
103
 
104
+ /** The optional second argument to {@link Ctx.done}. */
105
+ export interface DoneOptions {
106
+ /** Why the flow reached this verdict; redacted, bounded, and journaled. */
107
+ detail?: string;
108
+ }
109
+
52
110
  /**
53
111
  * The context a journal-backed runtime injects into a flow body.
54
112
  *
@@ -59,8 +117,20 @@ export interface Ctx extends Helpers {
59
117
  /** Host-verified ports. Absent from direct/local runs and ordinary authored execution. */
60
118
  readonly capabilities?: { readonly cloud?: CloudCapabilities };
61
119
  readonly mcp: Readonly<Record<string, Readonly<Record<string, (args: unknown) => Step<unknown>>>>>;
62
- /** Command lease: milliseconds or a duration such as "5m"; default 30s, maximum 15m. */
63
- run(command: string, options?: { timeout?: string | number }): Step<string>;
120
+ /**
121
+ * Run a command. Resolves to its stdout tail, and a nonzero exit ends the
122
+ * flow — unless `onNonZero: 'record'` is declared, which resolves to a
123
+ * `RunResult` carrying the journaled exit code instead.
124
+ *
125
+ * The literal overloads come first so the default stays the common case: an
126
+ * omitted or `'fail'` policy keeps the `Step<string>` every existing body is
127
+ * written against, and only the literal `'record'` widens the result. The
128
+ * third is for a policy held in a variable, where neither literal applies and
129
+ * the author has to narrow the union themselves.
130
+ */
131
+ run(command: string, options?: RunOptions & { onNonZero?: 'fail' }): Step<string>;
132
+ run(command: string, options: RunOptions & { onNonZero: 'record' }): Step<RunResult>;
133
+ run(command: string, options: RunOptions): Step<string | RunResult>;
64
134
  llm(strings: TemplateStringsArray, ...values: unknown[]): Step<string>;
65
135
  /** JSON Schema validates the value at runtime; narrow unknown in author code. */
66
136
  llm(prompt: string, options: LlmOptions): Step<unknown>;
@@ -80,7 +150,21 @@ export interface Ctx extends Helpers {
80
150
  * no-op that returns true. A name must appear in the flow header's `hooks`.
81
151
  */
82
152
  hook(name: string, input: unknown): Step<boolean>;
83
- done(reason: FlowCompletionReason): void;
153
+ /**
154
+ * End the flow with an authored verdict, and optionally say why.
155
+ *
156
+ * `options.detail` is free prose the flow already knows — "review found 1
157
+ * P2: `review.clean` was not created" — and it is what a reader gets instead
158
+ * of a generic sentence. It is journaled with the verdict, so it survives
159
+ * into the run report and `flows status`; the runtime redacts it and bounds
160
+ * it to `COMPLETION_DETAIL_MAX_CODE_POINTS` code points, truncating
161
+ * with a visible marker rather than refusing an over-long one.
162
+ *
163
+ * Whitespace-only is the same as saying nothing: it normalizes to absence,
164
+ * and the verdict reports exactly as the one-argument call does. A `detail`
165
+ * that is present and not a string is refused.
166
+ */
167
+ done(reason: FlowCompletionReason, options?: DoneOptions): void;
84
168
  cloud: CloudHelper;
85
169
  memory: MemoryHelper;
86
170
  }
package/src/index.ts CHANGED
@@ -11,8 +11,9 @@ export type {
11
11
  CloudBabysitterTurnDelivery,
12
12
  CloudBabysitterTurnReceipt,
13
13
  } from "./cloud.js";
14
- export type { AgentOptions, AgentResult, PermissionsSpec, LlmOptions, Ctx } from "./context.js";
14
+ export type { AgentOptions, AgentResult, DoneOptions, PermissionsSpec, LlmOptions, RunOptions, RunResult, Ctx } from "./context.js";
15
15
  export {
16
+ COMPLETION_DETAIL_MAX_CODE_POINTS,
16
17
  COMPLETION_REASONS,
17
18
  RUN_COMPLETION_REASONS,
18
19
  FLOW_COMPLETION_REASONS,